zidane 9.1.1 → 9.1.4

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-Cl4gCZN6.js} +7 -7
  2. package/dist/{acp-Di9WvMDF.js.map → acp-Cl4gCZN6.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-DBl2JUC6.js} +2 -2
  11. package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-DBl2JUC6.js.map} +1 -1
  12. package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CF_kjcJd.js} +277 -41
  13. package/dist/auto-update-restart-CF_kjcJd.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-DIV9c5Nr.js} +4 -4
  27. package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DIV9c5Nr.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-D71duF64.js} +2 -2
  50. package/dist/{credentials-wwETW8rI.js.map → credentials-D71duF64.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-DD4wPWKS.js} +4 -4
  58. package/dist/{discovery-DycXFxdA.js.map → discovery-DD4wPWKS.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-BDmtgr2O.js} +6 -6
  62. package/dist/{engine-VQ86XGdG.js.map → engine-BDmtgr2O.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-EWOhLyd9.js} +4 -4
  68. package/dist/{executor-C7RQrkEq.js.map → executor-EWOhLyd9.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-DklXPjiq.js} +8 -8
  74. package/dist/{extensions-BCx4QuGB.js.map → extensions-DklXPjiq.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-BtMW9KzL.js} +2 -2
  82. package/dist/{google-Crva32sk.js.map → google-BtMW9KzL.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-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
  89. package/dist/host-DEoEzQal.js.map +1 -0
  90. package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
  91. package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
  92. package/dist/{host-signals-Jsjd_-4g.js → host-signals-91zyko_i.js} +5 -5
  93. package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-91zyko_i.js.map} +1 -1
  94. package/dist/{host-wO_6GW0y.js → host-uP3t08w8.js} +276 -103
  95. package/dist/host-uP3t08w8.js.map +1 -0
  96. package/dist/{host-version-CNAr9pov.js → host-version-_RHlAB29.js} +2 -2
  97. package/dist/{host-version-CNAr9pov.js.map → host-version-_RHlAB29.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-CatnsVEd.js} +4 -4
  115. package/dist/{ipc-BzWhIybr.js.map → ipc-CatnsVEd.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-a8C9eby4.js} +9 -9
  121. package/dist/{links-CJG_rFvf.js.map → links-a8C9eby4.js.map} +1 -1
  122. package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-D6jzt5HQ.js} +2 -2
  123. package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-D6jzt5HQ.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-CJy52DNi.js} +132 -31
  128. package/dist/memory-CJy52DNi.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-CAWz-sMq.js} +3 -3
  137. package/dist/{path-display-COVV71Yu.js.map → path-display-CAWz-sMq.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-zVRxiJDv.js} +5 -5
  162. package/dist/providers-zVRxiJDv.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-CBoYDIND.js} +2 -2
  168. package/dist/{registry-BKjeBnoy.js.map → registry-CBoYDIND.js.map} +1 -1
  169. package/dist/{registry-B6Ww76iW.js → registry-CQOU5jvF.js} +2 -2
  170. package/dist/{registry-B6Ww76iW.js.map → registry-CQOU5jvF.js.map} +1 -1
  171. package/dist/{registry-B9INJwJR.js → registry-YUUqbYGr.js} +324 -39
  172. package/dist/registry-YUUqbYGr.js.map +1 -0
  173. package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-CT8Q95dR.js} +4 -4
  174. package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-CT8Q95dR.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-_jh2OtiL.js} +6 -6
  185. package/dist/{setting-BQBSyUq0.js.map → setting-_jh2OtiL.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-BT0_oKjO.js} +3 -3
  189. package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-BT0_oKjO.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-DxJ-lRhu.js} +3 -3
  203. package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-DxJ-lRhu.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-DwQI12WA.js} +2 -2
  231. package/dist/{version-DqqqvHDP.js.map → version-DwQI12WA.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-Dxwxb7QQ.js} +2 -2
  235. package/dist/{wire-CLm2rMK0.js.map → wire-Dxwxb7QQ.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-CA3o2nie.js} +4 -4
  239. package/dist/{ws-DfGGYQ4W.js.map → ws-CA3o2nie.js.map} +1 -1
  240. package/dist/{ws-client-CFMbhsNq.js → ws-client-C0iPAAzc.js} +2 -2
  241. package/dist/{ws-client-CFMbhsNq.js.map → ws-client-C0iPAAzc.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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-CJy52DNi.js","names":["inputsCurrent","fsWatch","stringList","extensionEntries","optionalString","MAX_KEY_LENGTH","DEFAULT_TIMEOUT_MS","NAME_RE","optionalString","optionalString","optionalString","optionalString","process","isRecord","isRecord","isRecord","optionalString","process"],"sources":["../src/extensions/bundle/compile-ui.ts","../src/ipc/transports/paced-writer.ts","../src/ipc/client.ts","../src/ipc/daemon/extension-watch.ts","../src/ipc/daemon/watch-file.ts","../src/ipc/daemon/extensions/clients.ts","../src/ipc/daemon/extensions/flows.ts","../src/ipc/daemon/extensions/host-ports.ts","../src/ipc/daemon/extensions/image-port.ts","../src/ipc/daemon/extensions/session-settings.ts","../src/ipc/daemon/extensions/settings-port.ts","../src/ipc/daemon/extensions/storage-sync.ts","../src/ipc/daemon/extensions/ui-bundles.ts","../src/ipc/daemon/extensions/host.ts","../src/ipc/daemon/environment.ts","../src/ipc/daemon/handlers/machine-links.ts","../src/ipc/daemon/handlers/machines.ts","../src/ipc/transports/peer-rpc.ts","../src/ipc/transports/send-budget.ts","../src/ipc/history/rpc-client.ts","../src/ipc/history/transcript.ts","../src/ipc/daemon/redact.ts","../src/ipc/daemon/catalog-entries.ts","../src/ipc/daemon/handlers/catalogs.ts","../src/ipc/daemon/handlers/artifacts.ts","../src/ipc/daemon/handlers/auth.ts","../src/ipc/daemon/handlers/block-runs.ts","../src/ipc/daemon/handlers/browser.ts","../src/ipc/daemon/handlers/catalog-install.ts","../src/text-origin.ts","../src/ipc/daemon/send-requests.ts","../src/ipc/daemon/handlers/chat.ts","../src/ipc/daemon/handlers/client-state.ts","../src/ipc/daemon/handlers/context.ts","../src/ipc/daemon/handlers/daemon.ts","../src/ipc/daemon/handlers/drafts.ts","../src/ipc/daemon/handlers/environments.ts","../src/ipc/daemon/handlers/session-policy.ts","../src/ipc/daemon/handlers/extensions.ts","../src/ipc/daemon/handlers/extension-ui.ts","../src/ipc/daemon/handlers/files.ts","../src/ipc/daemon/handlers/fs.ts","../src/ipc/daemon/handlers/sessions.ts","../src/ipc/daemon/handlers/git.ts","../src/ipc/daemon/handlers/history.ts","../src/ipc/daemon/handlers/hitl.ts","../src/ipc/daemon/handlers/launch-overrides.ts","../src/ipc/daemon/handlers/machine-serve.ts","../src/ipc/daemon/handlers/oauth-flows.ts","../src/ipc/daemon/handlers/onboarding.ts","../src/ipc/daemon/handlers/orchestration.ts","../src/ipc/daemon/handlers/panels.ts","../src/ipc/daemon/handlers/perf.ts","../src/ipc/daemon/integrations.ts","../src/ipc/daemon/handlers/integrations.ts","../src/ipc/daemon/handlers/presence.ts","../src/ipc/daemon/handlers/queue.ts","../src/ipc/daemon/handlers/resume.ts","../src/ipc/daemon/handlers/logs.ts","../src/ipc/daemon/handlers/server.ts","../src/ipc/daemon/handlers/session-reads.ts","../src/ipc/daemon/handlers/settings.ts","../src/ipc/daemon/handlers/suggest.ts","../src/ipc/daemon/sync-apply.ts","../src/ipc/daemon/sync-store.ts","../src/ipc/daemon/handlers/sync.ts","../src/ipc/daemon/handlers/terminal.ts","../src/ipc/daemon/handlers/titles.ts","../src/ipc/daemon/handlers/todos.ts","../src/ipc/daemon/handlers/transcript.ts","../src/ipc/daemon/handlers/usage.ts","../src/ipc/daemon/handlers/workspace.ts","../src/ipc/daemon/handlers/workspace-exec-stream.ts","../src/ipc/daemon/handshake.ts","../src/ipc/daemon/identity.ts","../src/ipc/daemon/peers.ts","../src/ipc/daemon/principal-work.ts","../src/ipc/daemon/signal-log.ts","../src/ipc/daemon/workspace-roots.ts","../src/ipc/daemon/dispatcher.ts","../src/ipc/daemon/update-retire.ts","../src/ipc/daemon/server.ts","../src/ipc/daemon/shell-path.ts","../src/ipc/memory.ts"],"sourcesContent":["/**\n * Bundles an extension's `ui` entry into one ESM module for the desktop and\n * web renderer. Every dependency is inlined (dynamic imports included);\n * the renderer's shared modules stay external (`./policy`). The result is\n * kept in `cacheDir` and served again while none of the bundled files\n * changed.\n *\n * Runs on Bun (`Bun.build`): the daemon, the TUI and the server. Node hosts\n * (the Electron main process) have no bundler at runtime and get a clear\n * error; they compile through a Bun host or ship their own backend reusing\n * {@link classifyUiImport}.\n *\n * Cache layout: one JSON file per entry, `<cacheDir>/ui-<key>.json`, holding\n * the code and the content hash of every bundled file. A hit re-hashes those\n * files; one changed file rebuilds. Old files go with\n * `pruneExtensionCompileCache(cacheDir)` (`../compile-cache`), by mtime.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport { createHash } from 'node:crypto'\nimport { readFileSync, realpathSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { writeFileAtomic } from '../../atomic-write'\nimport { classifyUiImport } from './policy'\n\n/** Bumped when the cache file's shape or the build options change. */\nconst CACHE_FORMAT = 1\n\n/** Options of {@link compileUiEntry}. */\nexport interface CompileUiEntryOptions {\n /** Absolute path of the `ui.tsx` entry. */\n entry: string\n /** The extension's id; names the cache file and the errors. */\n extensionId: string\n /** Folder the bundle is cached in. Created when missing. */\n cacheDir: string\n /** The extension folder. Imports must stay inside it. Default: the entry's folder. */\n dir?: string\n /** More bare specifiers to keep external (the renderer must provide them). */\n external?: readonly string[]\n}\n\n/** A bundled `ui` entry. */\nexport interface CompiledUiEntry {\n /** One ESM module. Host modules stay as bare imports. */\n code: string\n /** sha256 of `code`, hex. Changes exactly when the code does. */\n hash: string\n /** Bundler warnings, and the host modules the code imports at runtime. */\n warnings: string[]\n /** `true` when served from the cache. */\n cached: boolean\n /** Every bundled file (absolute path) → sha256 of the content bundled. The bundle is current while they all match. */\n inputs: Readonly<Record<string, string>>\n}\n\n/** A `ui` entry that did not bundle. `errors` holds one line per problem. */\nexport class UiBundleError extends Error {\n /**\n * @param extensionId - The extension whose entry failed.\n * @param errors - What went wrong, one line each.\n */\n constructor(readonly extensionId: string, readonly errors: readonly string[]) {\n super(`${extensionId}: the ui entry did not bundle:\\n ${errors.join('\\n ')}`)\n this.name = 'UiBundleError'\n }\n}\n\ninterface CacheFile {\n format: number\n bun: string\n /** Absolute path → sha256 of the content bundled. */\n inputs: Record<string, string>\n code: string\n hash: string\n warnings: string[]\n}\n\n/** The subset of `Bun.build` used here (the module typechecks without Bun's types in scope). */\ninterface BunBuildLike {\n version: string\n build: (config: Record<string, unknown>) => Promise<{\n success: boolean\n outputs: readonly { kind: string, text: () => Promise<string> }[]\n logs: readonly { level: string, message: string }[]\n metafile?: { inputs: Record<string, { imports: readonly { path: string, external?: boolean }[] }> }\n }>\n}\n\nfunction sha256(data: string | Buffer): string {\n return createHash('sha256').update(data).digest('hex')\n}\n\nfunction real(path: string): string {\n try {\n return realpathSync(path)\n }\n catch {\n return path\n }\n}\n\nfunction readCache(path: string): CacheFile | undefined {\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(path, 'utf8'))\n }\n catch {\n return undefined\n }\n const file = parsed as Partial<CacheFile> | null\n if (!file || file.format !== CACHE_FORMAT || typeof file.code !== 'string' || typeof file.hash !== 'string' || !file.inputs || typeof file.inputs !== 'object')\n return undefined\n return file as CacheFile\n}\n\n/** Every bundled file still has the content it was bundled with. */\nfunction inputsCurrent(inputs: Record<string, string>): boolean {\n for (const [path, hash] of Object.entries(inputs)) {\n try {\n if (sha256(readFileSync(path)) !== hash)\n return false\n }\n catch {\n return false\n }\n }\n return Object.keys(inputs).length > 0\n}\n\nfunction messageOf(error: unknown): string {\n if (error instanceof Error)\n return error.message\n return String(error)\n}\n\n/**\n * Bundles the `ui` entry of an extension into one ESM module, or returns the\n * cached bundle when none of its files changed.\n *\n * @param options - The entry, the extension id, the cache folder.\n * @returns The code, its hash and the warnings.\n * @throws {UiBundleError} When an import is not allowed, a file does not compile, or the host has no bundler.\n * @example\n * ```ts\n * const { code, hash } = await compileUiEntry({ entry: '/ext/notes/ui.tsx', extensionId: 'notes', cacheDir })\n * ```\n */\nexport async function compileUiEntry(options: CompileUiEntryOptions): Promise<CompiledUiEntry> {\n const bun = (globalThis as unknown as { Bun?: Partial<BunBuildLike> }).Bun\n if (typeof bun?.build !== 'function')\n throw new UiBundleError(options.extensionId, ['bundling a ui entry needs Bun (Bun.build); this host runs without it. Compile it in a Bun host (the daemon or the server).'])\n const entry = real(resolve(options.entry))\n const root = real(resolve(options.dir ?? dirname(options.entry)))\n const extra = options.external ?? []\n const version = bun.version ?? 'unknown'\n const key = sha256(JSON.stringify([CACHE_FORMAT, version, options.extensionId, entry, root, [...extra].sort()])).slice(0, 24)\n const cachePath = resolve(options.cacheDir, `ui-${key}.json`)\n\n const hit = readCache(cachePath)\n if (hit && hit.bun === version && inputsCurrent(hit.inputs))\n return { code: hit.code, hash: hit.hash, warnings: [...hit.warnings], cached: true, inputs: hit.inputs }\n\n const refused: string[] = []\n const guard = {\n name: 'zidane-ui-entry-imports',\n setup(build: { onResolve: (opts: { filter: RegExp }, cb: (args: { path: string, importer: string }) => { path: string, external: true } | undefined) => void }) {\n build.onResolve({ filter: /.*/ }, (args) => {\n const verdict = classifyUiImport(args.path, args.importer, root, extra)\n if (verdict.kind === 'external')\n return { path: args.path, external: true }\n if (verdict.kind === 'error') {\n refused.push(verdict.message)\n // Kept external so the build goes on and reports every refused import at once.\n return { path: args.path, external: true }\n }\n return undefined\n })\n },\n }\n\n let result: Awaited<ReturnType<BunBuildLike['build']>>\n try {\n result = await bun.build({\n entrypoints: [entry],\n root,\n target: 'browser',\n format: 'esm',\n splitting: false,\n metafile: true,\n throw: false,\n plugins: [guard],\n jsx: { runtime: 'automatic', importSource: 'react', development: false },\n define: { 'process.env.NODE_ENV': '\"production\"' },\n })\n }\n catch (error) {\n const errors = error instanceof AggregateError ? error.errors.map(messageOf) : [messageOf(error)]\n throw new UiBundleError(options.extensionId, [...refused, ...errors])\n }\n const buildErrors = result.logs.filter(log => log.level === 'error').map(log => log.message)\n if (refused.length > 0 || !result.success || buildErrors.length > 0)\n throw new UiBundleError(options.extensionId, [...refused, ...buildErrors].length > 0 ? [...refused, ...buildErrors] : ['the bundler failed without a message'])\n const output = result.outputs.find(o => o.kind === 'entry-point') ?? result.outputs[0]\n if (!output || result.outputs.length !== 1)\n throw new UiBundleError(options.extensionId, [`expected one module, the bundler produced ${result.outputs.length}`])\n const code = await output.text()\n const hash = sha256(code)\n\n const warnings = result.logs.filter(log => log.level === 'warning').map(log => log.message)\n const inputs: Record<string, string> = {}\n const runtimeHostModules = new Set<string>()\n for (const [path, meta] of Object.entries(result.metafile?.inputs ?? {})) {\n // Metafile paths are relative to the working directory.\n const absolute = resolve(process.cwd(), path)\n try {\n inputs[absolute] = sha256(readFileSync(absolute))\n }\n catch {\n // A virtual input: nothing on disk to watch.\n }\n for (const imported of meta.imports) {\n if (imported.external && (imported.path === 'zidane' || imported.path.startsWith('zidane/')))\n runtimeHostModules.add(imported.path)\n }\n }\n for (const specifier of runtimeHostModules)\n warnings.push(`imports \"${specifier}\" at runtime: the renderer must provide it (type-only imports are erased)`)\n\n const file: CacheFile = { format: CACHE_FORMAT, bun: version, inputs, code, hash, warnings }\n try {\n writeFileAtomic(cachePath, JSON.stringify(file), { ensureDir: true })\n }\n catch {\n // A cache that can't be written only costs the next build.\n }\n return { code, hash, warnings, cached: false, inputs }\n}\n","/**\n * Writes to a socket with backpressure: slices go out while the socket takes\n * them (`write` returns true), the rest waits for `drain`. Messages keep\n * their order, and `buffered` counts what is queued here plus what the\n * socket still holds, so a send budget measuring it sees the whole backlog.\n *\n * Handing a socket one large buffer at once is what this avoids: Bun's\n * `node:net` re-copies the unsent remainder after each partial write, so a\n * 100 MB reply took ~12 s to cross a unix socket, against ~70 ms when paced\n * (Node is fast either way).\n *\n * Small messages written in one go (a fan-out, a reply behind its signals)\n * are joined and handed over as one buffer, from a microtask (so before any\n * I/O), as soon as the socket asks for more, or once they add up to a slice:\n * one encode and one socket write instead of one per message. A large message is not joined: it goes\n * out in slices, after what was written before it.\n */\nimport type { Writable } from 'node:stream'\nimport { Buffer } from 'node:buffer'\n\n/** Largest slice handed to the socket at once. */\nconst SLICE_BYTES = 64 * 1024\n\nexport interface PacedWriter {\n write: (text: string) => void\n /** Bytes not yet handed to the OS: queued here, plus the socket's own buffer. */\n buffered: () => number\n}\n\nexport function createPacedWriter(stream: Writable): PacedWriter {\n const queue: Buffer[] = []\n let queuedBytes = 0\n let waiting = false\n /** Small messages not yet encoded, joined on their way into `queue`. */\n let pending: string[] = []\n let pendingBytes = 0\n let armed = false\n\n const takePending = (): void => {\n if (pending.length === 0)\n return\n const bytes = Buffer.from(pending.length === 1 ? pending[0]! : pending.join(''))\n pending = []\n pendingBytes = 0\n queue.push(bytes)\n queuedBytes += bytes.length\n }\n\n const pump = (): void => {\n waiting = false\n takePending()\n while (queue.length > 0) {\n if (stream.destroyed || stream.writableEnded) {\n queue.length = 0\n queuedBytes = 0\n return\n }\n const head = queue[0]!\n const slice = head.length > SLICE_BYTES ? head.subarray(0, SLICE_BYTES) : head\n if (slice === head)\n queue.shift()\n else\n queue[0] = head.subarray(SLICE_BYTES)\n queuedBytes -= slice.length\n if (!stream.write(slice)) {\n waiting = true\n stream.once('drain', pump)\n return\n }\n }\n }\n\n return {\n write(text) {\n if (text.length >= SLICE_BYTES) {\n takePending()\n const bytes = Buffer.from(text)\n queue.push(bytes)\n queuedBytes += bytes.length\n if (!waiting)\n pump()\n return\n }\n pending.push(text)\n pendingBytes += Buffer.byteLength(text)\n // While the socket is full, `drain` takes them.\n if (waiting)\n return\n if (pendingBytes >= SLICE_BYTES) {\n pump()\n return\n }\n if (armed)\n return\n armed = true\n queueMicrotask(() => {\n armed = false\n if (!waiting)\n pump()\n })\n },\n buffered: () => pendingBytes + queuedBytes + stream.writableLength,\n }\n}\n","/**\n * Typed daemon client — the only thing a zidane window (TUI, attach CLI,\n * GUI main process) needs to talk to a shared chat host.\n *\n * `request` is checked against the `IpcMethods` contract, `onSignal`\n * delivers every `HostSignal` fan-out, and `connectIpcClient` handles the\n * handshake including the protocol-version dance: a mismatched daemon is\n * asked to drain (`daemon.shutdown`) so the caller can respawn a fresh one.\n * The transport-independent half (handshake, deadlines, signals) is shared\n * with the WebSocket client in `./transports/client-core`.\n */\nimport type { Socket } from 'node:net'\nimport type { EnsureDaemonOptions } from './daemon/lifecycle'\nimport type { IpcClient } from './transports/client-core'\nimport { connect } from 'node:net'\nimport { createJsonRpcConnection, errorResponse } from '../acp/json-rpc'\nimport { METHOD_NOT_FOUND } from '../chat/hosts/connection'\nimport { ensureDaemonRunning, probeSocket } from './daemon/lifecycle'\nimport { createSignalListeners, IpcVersionMismatchError, openIpcClient } from './transports/client-core'\nimport { createPacedWriter } from './transports/paced-writer'\n\nexport { type IpcClient, IpcVersionMismatchError } from './transports/client-core'\n\n/** Options for {@link connectIpcClient}. */\nexport interface IpcClientOptions {\n /** Path of the daemon's unix socket. */\n socketPath: string\n /** Client zidane version, surfaced in daemon diagnostics. */\n appVersion?: string\n /** Called when the daemon connection drops (socket close/error). */\n onClose?: () => void\n /**\n * On a version/build mismatch, ask the stale daemon to drain before\n * throwing (default). PASSIVE clients (the presence watcher) must set\n * this false: they retry on a timer, and an old-build window left open\n * across a protocol bump would otherwise drain the NEW daemon in a\n * loop, aborting every other window's runs.\n */\n drainOnMismatch?: boolean\n}\n\n/**\n * Connects to a daemon over its unix socket and completes the `ipc.hello` handshake.\n * On a protocol, build or code version mismatch it throws {@link IpcVersionMismatchError}. Unless `drainOnMismatch` is `false`, it first asks the stale daemon to drain. Rejects when nothing listens on the socket.\n * @param options - Socket path and client settings.\n * @returns A typed client. Requests are checked against {@link IpcMethods}.\n * @example\n * ```ts\n * import { connectIpcClient, defaultSocketPath } from 'zidane/ipc'\n *\n * const client = await connectIpcClient({ socketPath: defaultSocketPath() })\n * const sessions = await client.request('sessions.list', {})\n * const stop = client.onSignal(signal => console.log(signal.kind))\n * console.log(sessions.length)\n * stop()\n * client.close()\n * ```\n */\nexport async function connectIpcClient(options: IpcClientOptions): Promise<IpcClient> {\n const socket: Socket = await new Promise((resolvePromise, reject) => {\n const s = connect(options.socketPath)\n s.once('connect', () => {\n s.off('error', reject)\n resolvePromise(s)\n })\n s.once('error', reject)\n })\n\n const signals = createSignalListeners()\n let closed = false\n\n // A large request (turns with images) goes out paced, as the daemon's replies do.\n const writer = createPacedWriter(socket)\n const connection = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: json => writer.write(`${json}\\n`),\n // The daemon never sends requests to clients — only notifications.\n onRequest: message => errorResponse(message.id, METHOD_NOT_FOUND, 'Clients do not accept requests.'),\n onNotification: signals.onNotification,\n })\n connection.start()\n\n const close = (): void => {\n if (closed)\n return\n closed = true\n connection.close()\n socket.destroy()\n }\n\n socket.on('close', () => {\n if (closed)\n return\n closed = true\n connection.close()\n options.onClose?.()\n })\n socket.on('error', () => {\n // 'close' follows; swallow so an unhandled 'error' doesn't crash us.\n })\n\n const passive = options.drainOnMismatch === false\n return openIpcClient(\n // `abort` destroys the socket (not `close()`), so its 'close' handler fires `onClose`.\n { rpc: connection, close, abort: () => socket.destroy(), where: options.socketPath },\n signals.listeners,\n {\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n drain: passive ? 'stale-only' : 'always',\n buildFence: !passive,\n },\n )\n}\n\n/**\n * One-call convenience for windows: make sure a daemon is up (spawning if\n * needed), connect, and — when the running daemon speaks an older protocol\n * — drain it and spawn a fresh one before retrying once.\n * @param options - Client options without `socketPath`, plus the daemon spawn options.\n * @returns A connected client.\n */\nexport async function connectOrSpawnDaemon(\n options: Omit<IpcClientOptions, 'socketPath'> & EnsureDaemonOptions = {},\n): Promise<IpcClient> {\n const socketPath = await ensureDaemonRunning(options)\n try {\n return await connectIpcClient({ ...options, socketPath })\n }\n catch (err) {\n if (!(err instanceof IpcVersionMismatchError))\n throw err\n /*\n * The stale daemon was told to drain by `connectIpcClient`, but\n * `daemon.shutdown` replies BEFORE the socket actually closes (the\n * drain runs on `setImmediate`). Poll until the socket stops\n * accepting connections (bounded) before respawning, so\n * `ensureDaemonRunning` doesn't re-probe the still-listening stale\n * daemon and hit a second mismatch.\n */\n const drainDeadline = Date.now() + 2000\n while (await probeSocket(socketPath)) {\n if (Date.now() > drainDeadline)\n break\n await new Promise(r => setTimeout(r, 100))\n }\n const retryPath = await ensureDaemonRunning(options)\n return connectIpcClient({ ...options, socketPath: retryPath })\n }\n}\n","/**\n * Live reload of a daemon's extensions : one recursive\n * watch per extension folder a registry holds, plus a watch on each scan\n * root (`<scope>/.zidane/extensions`) for folders that appear or go. A\n * burst of edits (an agent writing several files) settles into one call with\n * every folder that changed, which the environment hands to\n * `reloadChangedExtensions`: only those extensions reload.\n *\n * Only source changes count. Extensions write their own state into their\n * folder (git-flow's `reviews/`), and reloading on those writes would loop,\n * so the filter keeps code files and the root `package.json`, never\n * anything under `node_modules` or a dot-folder. Same rule as the desktop\n * app's watcher.\n *\n * A reload swaps the code sessions run on, so it waits while `canReload`\n * says a run is in flight (asked again every `retryMs`): the agent writing\n * the extension finishes its turn first, and its half-written files are\n * never loaded. Same rule as the desktop app's watcher.\n *\n * A scan root that does not exist yet (`.zidane/extensions` before the\n * first extension) is watched through its nearest existing parent: when the\n * next folder towards it appears the watch moves down, and once the root\n * exists it is watched itself and every folder already in it counts as\n * changed.\n *\n * On macOS `fs.watch` returns before its FSEvents stream listens, so a\n * change made at once can go unheard; a test writes a probe until it is\n * heard (`onProbe`).\n */\nimport type { FSWatcher } from 'node:fs'\nimport { existsSync, watch as fsWatch, readdirSync } from 'node:fs'\nimport { dirname, join, relative, sep } from 'node:path'\n\nconst SETTLE_MS = 300\nconst RETRY_MS = 1000\nconst SOURCE_FILE = /\\.[cm]?[jt]sx?$/\n/** A file a test writes in a watched folder to learn its watch listens (`onProbe`). Never a source change. */\nexport const EXTENSION_WATCH_PROBE = '.zidane-watch-probe'\n\n/** Whether a change to `name` (relative to the extension folder) should reload it. */\nexport function isExtensionSourceChange(name: string | null): boolean {\n // No name: the platform didn't say what changed; reloading is the safe side.\n if (!name)\n return true\n const parts = name.split(/[\\\\/]/)\n if (parts.some(part => part === 'node_modules' || part.startsWith('.')))\n return false\n if (parts.length === 1 && parts[0] === 'package.json')\n return true\n return SOURCE_FILE.test(name)\n}\n\n/** Starts a watch; `recursive` for an extension folder, not for a scan root. */\nexport type ExtensionWatchFn = (dir: string, recursive: boolean, onFile: (name: string | null) => void) => Pick<FSWatcher, 'close' | 'on'>\n\n/** What to watch: extension folders (recursively) and scan roots (their children). */\nexport interface ExtensionWatchTargets {\n dirs: readonly string[]\n roots: readonly string[]\n}\n\n/** A set of watches kept in line with a registry's folders. */\nexport interface ExtensionFolderWatch {\n /** Watch exactly `targets`: start the missing watches, close the rest. */\n sync: (targets: ExtensionWatchTargets) => void\n /** Close every watch and drop a pending call. */\n close: () => void\n}\n\n/** Options of {@link watchExtensionFolders}. */\nexport interface ExtensionFolderWatchOptions {\n /** How long writes must stop before `onChange`. Default 300 ms. */\n settleMs?: number\n /** The watch. Default `node:fs`'s, not keeping the process alive. */\n watch?: ExtensionWatchFn\n /**\n * Told each time a watched folder sees {@link EXTENSION_WATCH_PROBE}: its\n * watch listens. For a scan root not created yet, the folder watched in\n * its place. A test seam.\n */\n onProbe?: (dir: string) => void\n /** Whether a reload may run now. While `false`, changes wait and it is asked again every `retryMs`. Default: always. */\n canReload?: () => boolean\n /** How often a waiting reload asks `canReload` again. Default 1000 ms. */\n retryMs?: number\n}\n\n/** A watch on a scan root, or on the nearest existing parent while the root is missing. */\ninterface RootWatch {\n close: () => void\n}\n\nconst nodeWatch: ExtensionWatchFn = (dir, recursive, onFile) =>\n fsWatch(dir, { recursive, persistent: false }, (_event, name) => onFile(name ? String(name) : null))\n\n/**\n * Watches extension folders and scan roots; `onChange` gets the folders\n * that changed (a root's child that appeared or went counts as changed)\n * once writes settle.\n *\n * @param onChange - Called with the changed folders, absolute.\n * @param options - Settle time, the watch and the probe seam.\n * @returns The watch set; `sync` it after each build or reload.\n */\nexport function watchExtensionFolders(onChange: (dirs: string[]) => void, options: ExtensionFolderWatchOptions = {}): ExtensionFolderWatch {\n const settleMs = options.settleMs ?? SETTLE_MS\n const retryMs = options.retryMs ?? RETRY_MS\n const canReload = options.canReload ?? (() => true)\n const watch = options.watch ?? nodeWatch\n const watchers = new Map<string, Pick<FSWatcher, 'close'>>()\n const pending = new Set<string>()\n let timer: ReturnType<typeof setTimeout> | undefined\n let closed = false\n\n const schedule = (delay: number): void => {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n if (closed)\n return\n if (!canReload())\n return schedule(retryMs)\n const dirs = [...pending]\n pending.clear()\n if (dirs.length > 0)\n onChange(dirs)\n }, delay)\n timer.unref?.()\n }\n\n const changed = (dir: string): void => {\n pending.add(dir)\n schedule(settleMs)\n }\n\n const isProbe = (name: string | null): boolean => name === EXTENSION_WATCH_PROBE || name?.endsWith(`${sep}${EXTENSION_WATCH_PROBE}`) === true\n\n const stop = (key: string): void => {\n const watcher = watchers.get(key)\n watchers.delete(key)\n try {\n watcher?.close()\n }\n catch {}\n }\n\n /** Starts one `fs.watch`; `undefined` when the folder is gone (or never was). `onGone`: it errored. */\n const open = (dir: string, recursive: boolean, onFile: (name: string | null) => void, onGone: () => void): Pick<FSWatcher, 'close'> | undefined => {\n let watcher: Pick<FSWatcher, 'close' | 'on'>\n try {\n watcher = watch(dir, recursive, (name) => {\n if (isProbe(name)) {\n options.onProbe?.(dir)\n return\n }\n onFile(name)\n })\n }\n catch {\n return undefined\n }\n watcher.on('error', onGone)\n return watcher\n }\n\n /** A scan root's children that appeared, went or changed. */\n const rootChange = (root: string) => (name: string | null): void => {\n // The first segment names the extension folder.\n const child = name?.split(/[\\\\/]/)[0]\n if (child && !child.startsWith('.'))\n changed(join(root, child))\n }\n\n /**\n * Watches `root`, or while it is missing its nearest existing parent,\n * moving down as the folders towards it appear. `undefined` when not even\n * a parent can be watched (the next sync tries again).\n */\n const watchRoot = (key: string, root: string): RootWatch | undefined => {\n let current: Pick<FSWatcher, 'close'> | undefined\n /** The folder `current` watches. */\n let watched: string | undefined\n /** The root was missing at some point: once it appears, what is already in it is new. */\n let missing = false\n let done = false\n const swap = (dir: string | undefined, next: Pick<FSWatcher, 'close'> | undefined): void => {\n try {\n current?.close()\n }\n catch {}\n current = next\n watched = next ? dir : undefined\n }\n const handle: RootWatch = {\n close: () => {\n done = true\n swap(undefined, undefined)\n },\n }\n /** The watched folder went (the root deleted): watch the nearest existing parent again. */\n function gone(): void {\n swap(undefined, undefined)\n if (!place() && watchers.get(key) === handle)\n stop(key)\n }\n /** Watches the root, or the nearest existing parent. Returns whether anything is watched. */\n function place(): boolean {\n if (done)\n return false\n if (existsSync(root)) {\n if (watched === root && current)\n return true\n swap(root, open(root, false, rootChange(root), gone))\n if (!current)\n return false\n if (!missing)\n return true\n missing = false\n // Folders made before the watch listened.\n try {\n for (const child of readdirSync(root, { withFileTypes: true })) {\n if (child.isDirectory() && !child.name.startsWith('.'))\n changed(join(root, child.name))\n }\n }\n catch {}\n return true\n }\n missing = true\n let parent = dirname(root)\n while (!existsSync(parent) && dirname(parent) !== parent)\n parent = dirname(parent)\n const next = relative(parent, root).split(sep)[0]\n if (watched === parent && current)\n return true\n swap(parent, open(parent, false, (name) => {\n // The folder towards the root appeared (or the platform didn't say): move down.\n if (!name || name.split(/[\\\\/]/)[0] === next)\n place()\n }, gone))\n // Made between the check and the watch: move down now.\n if (current && next && existsSync(join(parent, next)))\n return place()\n return current !== undefined\n }\n return place() ? handle : undefined\n }\n\n const start = (key: string, dir: string, recursive: boolean): void => {\n if (!recursive) {\n const root = watchRoot(key, dir)\n if (root)\n watchers.set(key, root)\n return\n }\n const watcher = open(dir, true, (name) => {\n if (isExtensionSourceChange(name))\n changed(dir)\n }, () => {\n if (watchers.get(key) === watcher)\n stop(key)\n })\n if (watcher)\n watchers.set(key, watcher)\n }\n\n return {\n sync: ({ dirs, roots }) => {\n if (closed)\n return\n const wanted = new Map<string, { dir: string, recursive: boolean }>()\n for (const dir of dirs)\n wanted.set(`d:${dir}`, { dir, recursive: true })\n for (const root of roots)\n wanted.set(`r:${root}`, { dir: root, recursive: false })\n for (const key of [...watchers.keys()]) {\n if (!wanted.has(key))\n stop(key)\n }\n for (const [key, { dir, recursive }] of wanted) {\n if (!watchers.has(key))\n start(key, dir, recursive)\n }\n },\n close: () => {\n closed = true\n clearTimeout(timer)\n pending.clear()\n for (const key of [...watchers.keys()])\n stop(key)\n },\n }\n}\n","/**\n * Notice when another process rewrites a file (the settings in `state.json`):\n * a watch on the file, followed to each new file a writer swaps in (writers\n * replace it atomically), plus a slow poll for file systems that send no\n * events. Both compare its modification time and size, so a burst of events\n * from one write calls back once.\n */\n\nimport { statSync, watch } from 'node:fs'\n\n/** Coalesces the events one write produces. */\nconst DEBOUNCE_MS = 100\n/** The fallback poll, when file events are missed. */\nconst POLL_MS = 2_000\n\nfunction stampOf(file: string): string {\n try {\n const stats = statSync(file)\n return `${stats.mtimeMs}:${stats.size}`\n }\n catch {\n return 'missing'\n }\n}\n\n/**\n * Call `onChange` after `file` changes. Returns the function that stops watching.\n *\n * @param file - The file to watch.\n * @param onChange - Called once per change, after its events settle.\n * @param options - Options.\n * @param options.pollMs - The fallback poll interval. Default 2 s.\n * @param options.watch - The file watch: `node:fs`'s by default; tests pass their own.\n */\nexport function watchFileChanges(file: string, onChange: () => void, options: { pollMs?: number, watch?: typeof watch } = {}): () => void {\n let stamp = stampOf(file)\n let pending: ReturnType<typeof setTimeout> | undefined\n let watcher: ReturnType<typeof watch> | undefined\n let stopped = false\n\n const check = (): void => {\n pending = undefined\n const now = stampOf(file)\n if (now === stamp)\n return\n stamp = now\n onChange()\n }\n // One check after a burst of events settles.\n const onEvent = (): void => {\n clearTimeout(pending)\n pending = setTimeout(check, DEBOUNCE_MS)\n pending.unref?.()\n }\n const arm = (): void => {\n watcher?.close()\n watcher = undefined\n if (stopped)\n return\n try {\n watcher = (options.watch ?? watch)(file, (event) => {\n onEvent()\n // The file was replaced: the watch still follows the old one.\n if (event === 'rename')\n arm()\n })\n watcher.on('error', () => undefined)\n watcher.unref()\n }\n catch {\n // No file yet: the poll watches it once it exists.\n }\n }\n\n arm()\n // Leaves a burst to its debounced check.\n const poll = setInterval(() => {\n if (watcher === undefined)\n arm()\n if (pending === undefined)\n check()\n }, options.pollMs ?? POLL_MS)\n poll.unref?.()\n return () => {\n stopped = true\n clearTimeout(pending)\n clearInterval(poll)\n watcher?.close()\n watcher = undefined\n }\n}\n","/**\n * The connected clients as extension UI sees them :\n * which session each one shows and when its user last acted, for the\n * dialog router (`ctx.ui` dialogs and toasts) and the UI client port\n * (`ctx.ui.panel`, `navigate`, `ctx.composer`, `notify`, `ctx.keymap.dispatch`).\n *\n * A client takes part once it announces itself (`ui.client.announce`); a\n * headless connection that never does (a channel, `/mcp`) is never asked.\n * A dialog goes to its client as `ui:dialog` and comes back through\n * `ui.dialog.answer`; a UI request goes as `ui:client` and comes back through\n * `ui.client.reply`. A client that drops cancels what it was showing.\n */\nimport type { UiClientAnnounce, UiClientRequest, WireComposerEdit } from '../../../chat/host/extensions-wire'\nimport type { DialogPort, UiClientInfo, UiClientPort } from '../../../extensions/ui'\nimport type { ComposerOp } from '../../../extensions/ui/domain'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport { Buffer } from 'node:buffer'\nimport { NoUiError } from '../../../extensions/api/ui'\n\n/** How long a client has to answer a UI request before the host stops waiting and takes \"did nothing\". */\nconst CLIENT_REPLY_LIMIT_MS = 30_000\n\n/** One announced client. */\ninterface ClientRecord {\n id: string\n peer: HostPeer\n viewing?: string[]\n lastActiveAt: number\n dialogs: boolean\n ui: boolean\n}\n\ninterface PendingDialog {\n peer: HostPeer\n resolve: (answer: unknown) => void\n reject: (error: unknown) => void\n validate?: (key: string, value: unknown) => string | undefined\n}\n\ninterface PendingRequest {\n peer: HostPeer\n resolve: (result: unknown) => void\n}\n\n/** The client directory and the two ports the extension runtime takes from it. */\nexport interface UiClientDirectory {\n /** Records what a connection shows; the first announce makes it a client. */\n announce: (peer: HostPeer, info: UiClientAnnounce) => void\n /** The connection dropped: it is no client anymore, its dialogs reject and its requests answer \"did nothing\". */\n remove: (peer: HostPeer) => void\n /** The announced clients. */\n clients: () => UiClientInfo[]\n /** The connection of a client id. */\n peerOf: (clientId: string) => HostPeer | undefined\n /** The client id of an announced connection. */\n idOf: (peer: HostPeer) => string | undefined\n /** `ctx.ui` dialogs, routed to the clients here. */\n readonly dialogPort: DialogPort\n /** `ctx.ui.panel` / `navigate` / `notify` and `ctx.composer`, sent to the clients here. */\n readonly uiClientPort: UiClientPort\n /** A dialog's answer from the connection that shows it. `false` when it is not pending there. */\n answerDialog: (peer: HostPeer, dialogId: string, answer: unknown) => boolean\n /** Checks one form value of a dialog the connection shows. `undefined`: accepted, or no such dialog. */\n validateDialog: (peer: HostPeer, dialogId: string, key: string, value: unknown) => string | undefined\n /** A UI request's reply from the connection it went to. `false` when it is not pending there. */\n reply: (peer: HostPeer, requestId: string, result: unknown) => boolean\n}\n\n/** Options of {@link createUiClientDirectory}. */\nexport interface UiClientDirectoryOptions {\n /** Epoch ms. Default `Date.now`. */\n now?: () => number\n /** How long a UI request waits for its reply. Default 30 s. */\n replyLimitMs?: number\n}\n\nfunction stringList(value: unknown): string[] | undefined {\n return Array.isArray(value) ? value.filter((v): v is string => typeof v === 'string' && v.length > 0 && v.length <= 256).slice(0, 64) : undefined\n}\n\n/** A composer edit on the wire: inline bytes as base64. */\nfunction wireEdit(op: ComposerOp): WireComposerEdit {\n if (op.op !== 'attach')\n return op\n const files = op.files as readonly ({ path: string } | { name: string, mimeType: string, data: Uint8Array })[]\n if (files.every(f => 'path' in f))\n return { op: 'attach', files: (files as { path: string }[]).map(f => ({ path: f.path })) }\n return {\n op: 'attach',\n files: (files as { name: string, mimeType: string, data: Uint8Array }[]).map(f => ({ name: f.name, mimeType: f.mimeType, data: Buffer.from(f.data).toString('base64') })),\n }\n}\n\n/**\n * Creates an empty directory.\n *\n * @param options - Clock and reply limit.\n */\nexport function createUiClientDirectory(options: UiClientDirectoryOptions = {}): UiClientDirectory {\n const now = options.now ?? Date.now\n const replyLimitMs = options.replyLimitMs ?? CLIENT_REPLY_LIMIT_MS\n const records = new Map<HostPeer, ClientRecord>()\n const byId = new Map<string, ClientRecord>()\n const dialogs = new Map<string, PendingDialog>()\n const requests = new Map<string, PendingRequest>()\n let seq = 0\n /** The latest activity stamp handed out: a later announce always ranks later, even within one millisecond. */\n let latest = 0\n const stamp = (): number => (latest = Math.max(now(), latest + 1))\n\n const send = (peer: HostPeer, signal: HostSignal): void => peer.send(signal)\n\n /** Sends a request to the client and waits for its reply; `fallback` when it drops, refuses or never answers. */\n const ask = <T>(clientId: string, request: UiClientRequest, coerce: (raw: unknown) => T | undefined, fallback: T): Promise<T> => {\n const record = byId.get(clientId)\n if (!record || !record.ui)\n return Promise.resolve(fallback)\n const requestId = `r${++seq}`\n return new Promise<T>((resolve) => {\n const timer = setTimeout(() => {\n requests.delete(requestId)\n resolve(fallback)\n }, replyLimitMs)\n timer.unref?.()\n requests.set(requestId, {\n peer: record.peer,\n resolve: (raw) => {\n clearTimeout(timer)\n requests.delete(requestId)\n resolve(coerce(raw) ?? fallback)\n },\n })\n send(record.peer, { kind: 'ui:client', requestId, request })\n })\n }\n const asBoolean = (raw: unknown): boolean | undefined => (typeof raw === 'boolean' ? raw : undefined)\n\n const clientList = (): UiClientInfo[] => [...records.values()].map(r => ({\n id: r.id,\n viewing: r.viewing ?? (r.peer.watching ? [r.peer.watching] : []),\n lastActiveAt: r.lastActiveAt,\n dialogs: r.dialogs,\n }))\n\n const dialogPort: DialogPort = {\n clients: clientList,\n show: (clientId, request, ctx) => {\n const record = byId.get(clientId)\n if (!record)\n return Promise.reject(new NoUiError(request.kind))\n const dialogId = `d${++seq}`\n return new Promise<unknown>((resolve, reject) => {\n const onAbort = (): void => {\n if (!dialogs.delete(dialogId))\n return\n send(record.peer, { kind: 'ui:dialog:close', dialogId })\n }\n const done = (): void => ctx.signal.removeEventListener('abort', onAbort)\n dialogs.set(dialogId, {\n peer: record.peer,\n resolve: (answer) => {\n done()\n resolve(answer)\n },\n reject: (error) => {\n done()\n reject(error)\n },\n ...(ctx.validate ? { validate: ctx.validate } : {}),\n })\n ctx.signal.addEventListener('abort', onAbort, { once: true })\n send(record.peer, { kind: 'ui:dialog', dialogId, extensionId: ctx.extensionId, ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}), request })\n })\n },\n }\n\n const uiClientPort: UiClientPort = {\n panel: (clientId, request) => ask(clientId, { op: 'panel', ...request }, asBoolean, false),\n panelState: (clientId, opts) => ask(clientId, { op: 'panelState', ...(opts.sessionId ? { sessionId: opts.sessionId } : {}) }, raw => stringList(raw), [] as readonly string[]),\n navigate: (clientId, to) => ask(clientId, { op: 'navigate', to }, asBoolean, false),\n composer: (clientId, op, opts) => ask(clientId, { op: 'composer', edit: wireEdit(op), ...(opts.sessionId ? { sessionId: opts.sessionId } : {}) }, asBoolean, false),\n notify: (clientId, notification) => {\n const record = byId.get(clientId)\n if (record?.ui)\n send(record.peer, { kind: 'ui:client', request: { op: 'notify', ...notification } })\n },\n keymapDispatch: (clientId, request) => ask(clientId, { op: 'keymap.dispatch', ...request }, asBoolean, false),\n }\n\n return {\n announce(peer, info) {\n let record = records.get(peer)\n if (!record) {\n record = { id: `c${++seq}`, peer, lastActiveAt: stamp(), dialogs: true, ui: true }\n records.set(peer, record)\n byId.set(record.id, record)\n }\n const viewing = stringList(info.viewing)\n if (viewing)\n record.viewing = viewing\n if (info.active === true)\n record.lastActiveAt = stamp()\n if (typeof info.dialogs === 'boolean')\n record.dialogs = info.dialogs\n if (typeof info.ui === 'boolean')\n record.ui = info.ui\n },\n remove(peer) {\n const record = records.get(peer)\n if (!record)\n return\n records.delete(peer)\n byId.delete(record.id)\n for (const [id, pending] of [...dialogs]) {\n if (pending.peer !== peer)\n continue\n dialogs.delete(id)\n pending.reject(new NoUiError('dialog (its client disconnected)'))\n }\n for (const pending of [...requests.values()]) {\n if (pending.peer === peer)\n pending.resolve(undefined)\n }\n },\n clients: clientList,\n peerOf: clientId => byId.get(clientId)?.peer,\n idOf: peer => records.get(peer)?.id,\n dialogPort,\n uiClientPort,\n answerDialog(peer, dialogId, answer) {\n const pending = dialogs.get(dialogId)\n if (!pending || pending.peer !== peer)\n return false\n dialogs.delete(dialogId)\n pending.resolve(answer)\n return true\n },\n validateDialog(peer, dialogId, key, value) {\n const pending = dialogs.get(dialogId)\n return pending && pending.peer === peer ? pending.validate?.(key, value) : undefined\n },\n reply(peer, requestId, result) {\n const pending = requests.get(requestId)\n if (!pending || pending.peer !== peer)\n return false\n pending.resolve(result)\n return true\n },\n }\n}\n","/**\n * Integration sign-in flows on a daemon or server : the\n * {@link IntegrationFlowPort} that shows an OAuth or command method's steps\n * on one client, as `extensions:integration-flow` signals, and reads what\n * the user enters back through `extensions.integrations.flowInput`.\n *\n * A local daemon listens for the OAuth redirect itself (the loopback\n * callback server of the OAuth kit, the browser is on the same computer).\n * A zidane-server asks the client to paste the redirect instead: the user's\n * browser is not on the server's machine. A `command` method runs its argv\n * on the host, without a shell.\n */\nimport type { IntegrationFlowStep } from '../../../chat/host/extensions-wire'\nimport type { IntegrationCommandResult, IntegrationFlowPort } from '../../../extensions/integrations'\nimport type { HostPeer } from '../peers'\nimport { execFile } from 'node:child_process'\n\n/** The flows in progress, by id: what each waits for. */\nexport interface FlowRegistry {\n /**\n * A flow port whose steps go to `peer` (re-read on each step: a routed\n * client may change). Absent peer: the flow fails at its first step.\n */\n portFor: (peer: () => HostPeer | undefined, opts?: { flowId?: string, integrationId?: string }) => { port: IntegrationFlowPort, readonly flowId: string, finish: (outcome: { ok: boolean, error?: string }) => void }\n /** Input the user entered for a step. `undefined` cancels the flow. `false` when nothing waits for it from `peer`. */\n input: (peer: HostPeer, flowId: string, inputId: string, value: string | undefined) => boolean\n /** The client dropped: what its flows wait for is cancelled. */\n release: (peer: HostPeer) => void\n}\n\n/** Options of {@link createFlowRegistry}. */\nexport interface FlowRegistryOptions {\n /** `false`: no loopback callback server, the client pastes the redirect (a zidane-server). */\n callbackServer: boolean\n /** Runs a command method's argv. Default: a local process, no shell. */\n runCommand?: IntegrationFlowPort['runCommand']\n}\n\ninterface Waiting {\n peer: HostPeer\n flowId: string\n resolve: (value: string | undefined) => void\n}\n\nclass FlowCancelledError extends Error {\n constructor() {\n super('The sign-in was cancelled.')\n this.name = 'AbortError'\n }\n}\n\n/**\n * Runs `command` (argv, no shell) and collects its output.\n *\n * @param command - The argv.\n * @param opts - Abort signal.\n * @param opts.signal - Kills the process when it aborts.\n */\nexport function runLocalCommand(command: readonly string[], opts: { signal: AbortSignal }): Promise<IntegrationCommandResult> {\n const [file, ...args] = command\n if (!file)\n return Promise.reject(new Error('the command is empty'))\n return new Promise((resolve, reject) => {\n execFile(file, args, { signal: opts.signal, maxBuffer: 1024 * 1024, encoding: 'utf8' }, (error, stdout, stderr) => {\n if (error && (error as NodeJS.ErrnoException).code === 'ABORT_ERR')\n return reject(new FlowCancelledError())\n if (error && typeof (error as { code?: unknown }).code === 'string')\n return reject(error)\n const code = error ? (typeof (error as { code?: unknown }).code === 'number' ? (error as { code: number }).code : 1) : 0\n resolve({ stdout, stderr, exitCode: code })\n })\n })\n}\n\n/**\n * Creates the registry.\n *\n * @param options - Callback server mode and command runner.\n */\nexport function createFlowRegistry(options: FlowRegistryOptions): FlowRegistry {\n const waiting = new Map<string, Waiting>()\n let seq = 0\n\n const portFor: FlowRegistry['portFor'] = (peerOf, opts = {}) => {\n // A fixed id (a client's `extensions.integrations.start`), else a new one per flow the port runs.\n const fixed = opts.flowId && opts.flowId.length <= 128 ? opts.flowId : undefined\n let flowId = fixed ?? `f${++seq}`\n let integrationId = opts.integrationId ?? ''\n let used = false\n const step = (s: IntegrationFlowStep): HostPeer => {\n const peer = peerOf()\n if (!peer)\n throw new Error('No client can show the sign-in.')\n peer.send({ kind: 'extensions:integration-flow', flowId, integrationId, step: s })\n return peer\n }\n const ask = (s: (inputId: string) => IntegrationFlowStep, signal: AbortSignal | undefined): Promise<string | undefined> => {\n const inputId = `i${++seq}`\n const peer = step(s(inputId))\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n waiting.delete(inputId)\n reject(new FlowCancelledError())\n }\n if (signal?.aborted)\n return onAbort()\n signal?.addEventListener('abort', onAbort, { once: true })\n waiting.set(inputId, {\n peer,\n flowId,\n resolve: (value) => {\n signal?.removeEventListener('abort', onAbort)\n waiting.delete(inputId)\n resolve(value)\n },\n })\n })\n }\n const required = async (value: Promise<string | undefined>): Promise<string> => {\n const got = await value\n if (got === undefined)\n throw new FlowCancelledError()\n return got\n }\n const port: IntegrationFlowPort = {\n oauthCallbacks: (request) => {\n if (!fixed && used)\n flowId = `f${++seq}`\n used = true\n integrationId = request.integrationId\n return {\n onAuth: info => void step({ type: 'auth', url: info.url, ...(info.instructions ? { instructions: info.instructions } : {}) }),\n onDeviceCode: info => void step({ type: 'device', userCode: info.userCode, verificationUri: info.verificationUri, ...(info.expiresInSeconds !== undefined ? { expiresInSeconds: info.expiresInSeconds } : {}) }),\n onProgress: message => void step({ type: 'progress', message }),\n onPrompt: prompt => required(ask(inputId => ({ type: 'prompt', inputId, message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }), request.signal)),\n onSelect: prompt => ask(inputId => ({ type: 'select', inputId, message: prompt.message, options: prompt.options.map(o => ({ id: o.id, label: o.label })) }), request.signal),\n ...(options.callbackServer\n ? {}\n : {\n callbackServer: false as const,\n onManualCodeInput: () => required(ask(inputId => ({ type: 'manual-code', inputId }), request.signal)),\n }),\n signal: request.signal,\n }\n },\n runCommand: options.runCommand ?? runLocalCommand,\n }\n return {\n port,\n get flowId() { return flowId },\n finish: (outcome) => {\n const peer = peerOf()\n peer?.send({ kind: 'extensions:integration-flow', flowId, integrationId, step: { type: 'done', ok: outcome.ok, ...(outcome.error ? { error: outcome.error } : {}) } })\n },\n }\n }\n\n return {\n portFor,\n input: (peer, flowId, inputId, value) => {\n const w = waiting.get(inputId)\n if (!w || w.peer !== peer || w.flowId !== flowId)\n return false\n w.resolve(value)\n return true\n },\n release: (peer) => {\n for (const w of [...waiting.values()]) {\n if (w.peer === peer)\n w.resolve(undefined)\n }\n },\n }\n}\n","import type { Hookable } from 'hookable'\n/**\n * Ports of the daemon's extension host that read the chat host or the settings at\n * call time : `ctx.mcp` status and calls, the decisions\n * model behind `ctx.generate.decide`, and the session-bound members of a\n * command run that does not come from `/`.\n */\nimport type { AgentHooks } from '../../../agent'\nimport type { ProviderKey } from '../../../chat/auth'\nimport type { CommandStepContext } from '../../../chat/commands'\nimport type { SessionMcpServer } from '../../../chat/host/mcp'\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { AgentDecide } from '../../../decisions'\nimport type { McpCatalogPort, McpPortStatus } from '../../../extensions/catalog'\nimport type { ExtensionRuntime } from '../../../extensions/index'\nimport type { ExtensionMcpHost } from '../../../extensions/mcp-host'\nimport type { McpConnection, McpServerConfig } from '../../../mcp'\nimport type { Provider } from '../../../providers'\nimport type { ToolContext } from '../../../tools/types'\nimport type { HostSettings } from '../../protocol'\nimport type { DaemonChatHostPort } from './host'\nimport { randomUUID } from 'node:crypto'\nimport { createHooks } from 'hookable'\nimport { resolveDecisionsOption } from '../../../chat/decision-models'\nimport { discoverSessionMcpServers } from '../../../chat/host/mcp'\nimport { loadMcpToolsCache } from '../../../chat/mcp-tools-cache'\nimport { createDecider } from '../../../decisions'\nimport { toolResultToText } from '../../../types'\n\n/**\n * `ctx.mcp.list()` of a folder: its catalog servers with a live pooled\n * process or a session agent connected to them (`connected`), the servers\n * sessions in the folder connected to that the catalog does not list (a\n * remote `sse` / `streamable-http` server, a `--mcp` launch one), and the\n * configured ones the user has not enabled (`disabled`). Tools come from\n * the session's connection, else the tools cache (any host on this data dir).\n *\n * @param deps - The folder, its runtime, the storage prefix, settings, data dir and chat host.\n * @param deps.cwd - The folder.\n * @param deps.runtime - Its extension runtime (the replayed MCP catalog).\n * @param deps.prefix - Storage prefix such as `.zidane`.\n * @param deps.settings - The host's settings (the MCP allowlist).\n * @param deps.dataDir - Where the MCP tools cache is.\n * @param deps.host - The chat host, for its pooled server processes.\n */\nexport function mcpStatusOf(deps: { cwd: string, runtime: ExtensionRuntime | undefined, prefix: string, settings: HostSettings, dataDir: string, host: DaemonChatHostPort | undefined }): McpPortStatus[] {\n const servers = deps.runtime?.outputs.catalogs.mcp.read().sections.servers\n if (!servers)\n return []\n const enabled = new Set(discoverSessionMcpServers(deps.cwd, deps.prefix, deps.settings).map(s => s.name))\n const live = new Set((deps.host?.mcpServers.instances() ?? []).filter(i => !i.retired && (i.cwd === deps.cwd || i.cwd === '')).map(i => i.name))\n const inSessions = new Map<string, SessionMcpServer>()\n for (const s of deps.host?.mcpServers.connected(deps.cwd) ?? []) {\n if (!inSessions.has(s.name))\n inSessions.set(s.name, s)\n }\n const cache = loadMcpToolsCache({ dataDir: deps.dataDir })\n const out: McpPortStatus[] = []\n for (const server of servers.items) {\n const session = inSessions.get(server.name)\n inSessions.delete(server.name)\n const tools = session?.tools ?? cache[server.name]?.tools.map(t => t.name) ?? []\n if (live.has(server.name) || session)\n out.push({ name: server.name, status: 'connected', tools })\n else if (servers.origin(server.name)?.kind === 'config' && !enabled.has(server.name))\n out.push({ name: server.name, status: 'disabled', tools })\n }\n for (const s of inSessions.values())\n out.push({ name: s.name, status: 'connected', tools: s.tools, ...(s.url ? { url: s.url } : {}), ...(s.command ? { command: s.command } : {}) })\n return out\n}\n\n/**\n * `ctx.mcp.call`: a server the user configured goes through the host's\n * extension MCP connections (the enabled servers of the folder,\n * `createExtensionMcpHost`); a server only an extension registered\n * (`ctx.mcp.register`, an Agent Plugin's) is connected on demand from its\n * catalog config (`extensionServers`).\n *\n * @param mcp - The host's MCP connections; absent: a configured server's call rejects.\n * @param extensionServers - On-demand connections to extension servers, with the folder's catalog config of the server.\n * @param cwd - The folder.\n * @param rest - Server, tool, arguments and options, as the catalog port takes them.\n */\nexport async function mcpCallVia(\n mcp: ExtensionMcpHost | undefined,\n extensionServers: { calls: ExtensionMcpServerCalls, config: (server: string) => McpServerConfig | undefined } | undefined,\n cwd: string,\n ...rest: Parameters<McpCatalogPort['call']>\n): ReturnType<McpCatalogPort['call']> {\n const [server, tool, args, opts] = rest\n const config = extensionServers?.config(server)\n if (config)\n return extensionServers!.calls.call(cwd, config, tool, args ?? {}, opts)\n if (!mcp)\n throw new Error(`mcp.call: this host has no MCP connections (server \"${server}\", tool \"${tool}\")`)\n const result = await mcp.callTool(cwd, server, tool, args ?? {}, { ...(opts.timeoutMs !== undefined ? { timeout: opts.timeoutMs } : {}), ...(opts.signal ? { signal: opts.signal } : {}) })\n return { content: result.text, isError: result.isError }\n}\n\n/** Calls into extension-registered MCP servers, on connections opened on demand. */\nexport interface ExtensionMcpServerCalls {\n /** Calls `tool` (the server's own name) of `config`'s server in `cwd`. Rejects when it cannot connect or has no such tool. */\n call: (cwd: string, config: McpServerConfig, tool: string, args: Record<string, unknown>, opts: { timeoutMs?: number, signal?: AbortSignal }) => Promise<{ content: unknown, isError: boolean }>\n /** Closes every connection. */\n dispose: () => Promise<void>\n}\n\n/**\n * On-demand connections to extension-registered MCP servers: opened on the\n * first call per `(cwd, config)` through `connect` (the host's pool, so a\n * stdio process a session runs is shared), closed after `idleMs` without\n * a call.\n *\n * @param connect - Connects configs (`ChatHost.mcpServers.connect`); `undefined` until the chat host is bound.\n * @param idleMs - Idle time before a connection closes. Default 60 s.\n */\nexport function createExtensionMcpServerCalls(connect: () => ((configs: McpServerConfig[], cwd: string) => Promise<McpConnection>) | undefined, idleMs = 60_000): ExtensionMcpServerCalls {\n const pool = new Map<string, { connection: Promise<McpConnection>, busy: number, timer?: ReturnType<typeof setTimeout> }>()\n const release = (key: string): void => {\n const entry = pool.get(key)\n if (!entry || --entry.busy > 0)\n return\n entry.timer = setTimeout(() => {\n if (pool.get(key) !== entry)\n return\n pool.delete(key)\n void entry.connection.then(c => c.close()).catch(() => undefined)\n }, idleMs)\n entry.timer.unref?.()\n }\n return {\n call: async (cwd, config, tool, args, opts) => {\n const open = connect()\n if (!open)\n throw new Error(`mcp.call: this host cannot connect MCP servers yet (server \"${config.name}\")`)\n const key = `${cwd}\\u0000${JSON.stringify(config)}`\n let entry = pool.get(key)\n if (!entry) {\n const connection = open([config], cwd)\n const created = { connection, busy: 0 }\n entry = created\n pool.set(key, created)\n connection.catch(() => {\n if (pool.get(key) === created)\n pool.delete(key)\n })\n }\n clearTimeout(entry.timer)\n entry.busy++\n try {\n const connection = await entry.connection\n const def = connection.tools[`mcp_${config.name}_${tool}`]\n if (!def)\n throw new Error(`MCP server \"${config.name}\" offers no tool \"${tool}\" (not connected, a login is needed, or no such tool)`)\n const deadline = opts.timeoutMs !== undefined ? AbortSignal.timeout(opts.timeoutMs) : undefined\n const signal = deadline && opts.signal ? AbortSignal.any([deadline, opts.signal]) : deadline ?? opts.signal\n const ctx = { turnId: 'extension', callId: randomUUID(), ...(signal ? { signal } : {}) } as unknown as ToolContext\n try {\n return { content: toolResultToText(await def.execute(args, ctx)), isError: false }\n }\n catch (err) {\n return { content: err instanceof Error ? err.message : String(err), isError: true }\n }\n }\n finally {\n release(key)\n }\n },\n dispose: async () => {\n const entries = [...pool.values()]\n pool.clear()\n await Promise.all(entries.map(async (e) => {\n clearTimeout(e.timer)\n await e.connection.then(c => c.close()).catch(() => undefined)\n }))\n },\n }\n}\n\n/**\n * `ctx.generate.decide`: the decisions model the settings pick\n * (`resolveDecisionsOption`), resolved at each call since settings and\n * credentials change.\n *\n * Each decision fires `decision:start` / `decision:end` on `hooks`: the\n * daemon hands its registry's agent-hook fan-out there, so the extensions'\n * `hooks.on('decision:end')` observers see the decisions extensions make\n * outside any run as they see an agent's. (Inside a hook observer of a run\n * `ctx.generate.decide` uses that run's decider instead, journaled like the\n * agent's own.)\n *\n * @param providers - The folder's providers.\n * @param readSettings - The host's live settings.\n * @param buildProvider - Builds a provider of the registry.\n * @param hooks - Where the `decision:*` events go. Default: nowhere.\n */\nexport function decisionsPort(\n providers: () => Readonly<Record<string, ProviderDescriptor>>,\n readSettings: () => HostSettings,\n buildProvider: (providers: Readonly<Record<string, ProviderDescriptor>>, key: ProviderKey) => Provider,\n hooks: Hookable<AgentHooks> = createHooks<AgentHooks>(),\n): AgentDecide {\n const current = (): AgentDecide => {\n const all = providers()\n const config = resolveDecisionsOption(readSettings(), all, key => buildProvider(all, key as ProviderKey))\n return createDecider({ providers: [], config, hooks }).forRun(undefined)\n }\n const decide = ((request: never, opts?: never) => (opts === undefined ? current()(request) : current()(request, opts))) as unknown as AgentDecide\n Object.defineProperty(decide, 'available', { get: () => current().available })\n return decide\n}\n\n/**\n * The session-bound members of a command run that does not come from `/`\n * (a key, the palette, `commands.run`): `emit` persists a note,\n * `appendContext` a model-visible user turn. `runAgent` is not offered.\n *\n * @param host - The chat host, once bound.\n * @param cwd - The folder.\n * @param sessionId - The session the run is for.\n */\nexport function commandInvocationOf(host: DaemonChatHostPort | undefined, cwd: string, sessionId: string | undefined): Partial<CommandStepContext> {\n if (!sessionId || !host)\n return { cwd }\n return {\n cwd,\n emit: (block) => {\n void host.appendNote(sessionId, [block]).catch(() => undefined)\n },\n appendContext: async (text, opts) => {\n const trimmed = text.trim()\n if (!trimmed)\n return\n // As the `/` path: `display: false` persists as `''`, a model-only note.\n const display = opts?.display === false ? '' : opts?.display\n await host.appendTurns(sessionId, [{ id: randomUUID(), role: 'user', content: [{ type: 'text', text: trimmed }], createdAt: Date.now(), ...(display !== undefined ? { display } : {}) }])\n },\n }\n}\n","/**\n * The host side of `ctx.generate.image`: the generate_image tool's models\n * (the connected providers' image endpoints, `Settings.imageModel` as the\n * default) and, with `save`, the files the tool writes\n * (`generated-images/<prompt words>-<time>.<ext>` plus a `.json` record) in\n * the session's folder, else the project's, recorded as `file` artifacts of\n * the session. One factory for the daemon, the TUI and Electron main.\n */\nimport type { ProviderKey } from '../../../chat/auth'\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { ExtensionHostRuntimeBridge } from '../../../extensions/host-runtime'\nimport type { GenerateImageReference, GenerateImageRequest, GenerateImageResult, GeneratePort } from '../../../extensions/runtime/domains/ports'\nimport type { Provider } from '../../../providers'\nimport type { ImageAspectRatio, ImageData, ImageModelInfo, ProviderImages } from '../../../providers/images'\nimport type { SessionArtifact } from '../../../session/artifacts'\nimport { Buffer } from 'node:buffer'\nimport { randomBytes, randomUUID } from 'node:crypto'\nimport { mkdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, join, resolve } from 'node:path'\nimport { imageModelSources } from '../../../chat/image-models'\nimport { parseModelSetting } from '../../../chat/model-setting'\nimport { imageSizeFromBase64 } from '../../../media/image-size'\nimport { imageMediaTypeFor } from '../../../tools/binary-read'\nimport { DEFAULT_IMAGE_DIR } from '../../../tools/generate-image'\n\n/** Largest reference image read from disk, in bytes (as the generate_image tool). */\nconst MAX_REFERENCE_BYTES = 20 * 1024 * 1024\n\nconst EXTENSION_BY_TYPE: Readonly<Record<string, string>> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n}\n\n/** What {@link createHostImagePort} reads at call time. */\nexport interface HostImagePortDeps {\n /** The folder's providers. */\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n /** Builds a provider of the registry. May throw (no credentials). */\n buildProvider: (providers: Readonly<Record<string, ProviderDescriptor>>, key: ProviderKey) => Provider\n /** `Settings.imageModel` (`<provider>/<model>`): the default model, as the tool's. */\n imageModel: () => string | undefined\n /** Where `save` writes without a session: the project root, else the folder. */\n folder: string\n /** The session behind a save: its folder (`sessionControl`) and, without a `sessionId`, the active one. */\n bridge?: ExtensionHostRuntimeBridge\n /**\n * Stores an artifact on its session. Default: the active session's artifact\n * scope on `bridge` (`record`, else `store.upsertArtifact`).\n */\n recordArtifact?: (artifact: SessionArtifact) => Promise<unknown>\n}\n\ninterface ImageSource {\n provider: string\n images: ProviderImages\n model: ImageModelInfo\n}\n\n/** The model a request names, else `Settings.imageModel`, else the first provider's default: the generate_image tool's order. */\nfunction pickModel(request: GenerateImageRequest, deps: HostImagePortDeps): ImageSource {\n const all = deps.providers()\n const sources = imageModelSources(all, key => deps.buildProvider(all, key as ProviderKey))\n const entries = sources.flatMap(s => s.images.models.map(model => ({ provider: s.provider, images: s.images, model })))\n if (entries.length === 0)\n throw new Error('generate.image: no connected provider can generate images (OpenRouter, OpenAI with a platform key, Google Gemini or xAI)')\n const find = (providerId: string, modelId: string): ImageSource | undefined => entries.find(e => e.provider === providerId && e.model.id === modelId)\n if (request.model) {\n const named = find(request.model.providerId, request.model.modelId)\n if (!named)\n throw new Error(`generate.image: no image model \"${request.model.providerId}/${request.model.modelId}\"; available: ${entries.map(e => `${e.provider}/${e.model.id}`).join(', ')}`)\n return named\n }\n const configured = parseModelSetting(deps.imageModel())\n const first = sources[0]!\n return (configured && find(configured.providerKey, configured.modelId)) ?? find(first.provider, first.images.defaultModel) ?? entries[0]!\n}\n\n/** A reference as the image APIs take it: base64. A relative path resolves against `base`. */\nasync function referenceData(ref: GenerateImageReference, base: string): Promise<ImageData> {\n if (!('path' in ref))\n return { mediaType: ref.mimeType, data: Buffer.from(ref.data).toString('base64') }\n const file = isAbsolute(ref.path) ? ref.path : resolve(base, ref.path)\n const mediaType = imageMediaTypeFor(file)\n if (!mediaType)\n throw new Error(`generate.image: reference \"${ref.path}\" is not a PNG, JPEG, WebP or GIF file`)\n if ((await stat(file)).size > MAX_REFERENCE_BYTES)\n throw new Error(`generate.image: reference \"${ref.path}\" is over ${MAX_REFERENCE_BYTES} bytes`)\n return { mediaType, data: (await readFile(file)).toString('base64') }\n}\n\n/** A file-name stem from the first words of the prompt, then the time and a random tail (as the tool names its files). */\nfunction stemOf(prompt: string, now: Date): string {\n const slug = prompt.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim().split(' ').slice(0, 6).join('-') || 'image'\n const pad = (n: number): string => String(n).padStart(2, '0')\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${[now.getHours(), now.getMinutes(), now.getSeconds()].map(pad).join('')}-${randomBytes(2).toString('hex')}`\n return `${DEFAULT_IMAGE_DIR}/${slug}-${stamp}`\n}\n\n/**\n * The image port of a host's `ctx.generate` (`GeneratePort.image`).\n *\n * @param deps - Providers, the default model, the fallback folder and the session bridge.\n * @returns The port member.\n */\nexport function createHostImagePort(deps: HostImagePortDeps): NonNullable<GeneratePort['image']> {\n /** The session a save belongs to and the folder it writes under. */\n const saveTarget = async (request: GenerateImageRequest): Promise<{ cwd: string, sessionId?: string }> => {\n const sessionId = request.save?.sessionId ?? deps.bridge?.current()?.artifacts?.()?.sessionId\n if (!sessionId)\n return { cwd: deps.folder }\n const control = deps.bridge?.sessionControl()\n const cwd = await control?.verbs(request.extensionId).read(sessionId).then(s => s.cwd, () => undefined)\n return { cwd: cwd || deps.folder, sessionId }\n }\n\n const record = async (artifact: SessionArtifact): Promise<void> => {\n if (deps.recordArtifact) {\n await deps.recordArtifact(artifact)\n return\n }\n const scope = deps.bridge?.current()?.artifacts?.()\n const write = scope?.record ?? scope?.store.upsertArtifact?.bind(scope.store)\n await write?.(artifact)\n }\n\n return async (request): Promise<GenerateImageResult> => {\n const source = pickModel(request, deps)\n if (request.references.length > 0 && !source.model.input.includes('image'))\n throw new Error(`generate.image: ${source.provider}/${source.model.id} does not take reference images`)\n const target = request.save ? await saveTarget(request) : undefined\n const references = await Promise.all(request.references.map(ref => referenceData(ref, target?.cwd ?? deps.folder)))\n const response = await source.images.generate({\n model: source.model.id,\n prompt: request.prompt,\n ...(references.length > 0 ? { references } : {}),\n ...(request.aspectRatio ? { aspectRatio: request.aspectRatio as ImageAspectRatio } : {}),\n count: request.n,\n }, request.signal)\n const images = response.images.slice(0, request.n)\n const result: GenerateImageResult = {\n images: images.map(image => ({ mimeType: image.mediaType, data: new Uint8Array(Buffer.from(image.data, 'base64')) })),\n providerId: source.provider,\n modelId: response.model || source.model.id,\n ...(response.costUsd !== undefined ? { costUsd: response.costUsd } : {}),\n }\n if (!target)\n return result\n const now = new Date()\n const stem = stemOf(request.prompt, now)\n for (const [i, image] of images.entries()) {\n const rel = `${stem}${images.length > 1 ? `-${i + 1}` : ''}.${EXTENSION_BY_TYPE[image.mediaType] ?? 'png'}`\n const file = join(target.cwd, rel)\n await mkdir(dirname(file), { recursive: true })\n await writeFile(file, result.images[i]!.data)\n const info = {\n prompt: request.prompt,\n provider: source.provider,\n model: result.modelId,\n extension: request.extensionId,\n ...(request.aspectRatio ? { aspectRatio: request.aspectRatio } : {}),\n ...(response.costUsd !== undefined ? { costUsd: response.costUsd / images.length } : {}),\n createdAt: now.toISOString(),\n }\n await writeFile(`${file}.json`, `${JSON.stringify(info, null, 2)}\\n`)\n result.images[i]!.path = file\n if (target.sessionId) {\n const size = imageSizeFromBase64(image.data)\n const at = Date.now()\n await record({\n id: randomUUID(),\n sessionId: target.sessionId,\n kind: 'file',\n uri: `file:${rel}`,\n label: rel,\n meta: { size: size ? `${size.width}x${size.height}` : image.mediaType },\n createdAt: at,\n updatedAt: at,\n }).catch(() => undefined)\n }\n }\n return result\n }\n}\n","/**\n * Session-scope extension settings on a daemon or server: kept with the\n * session, in its metadata under\n * {@link SESSION_SETTINGS_METADATA_KEY} (`{ [extensionId]: { [key]: value } }`),\n * so they survive a restart.\n *\n * The settings port reads synchronously, so values are served from a cache.\n * A session read for the first time is loaded from the store in the\n * background; when it lands, listeners are told which extensions changed and\n * `ctx.settings.onChange` fires. A write updates the cache at once and\n * persists through the host (`ChatHost.patchSessionMeta`, which a live\n * session's next save does not revert).\n */\n\n/** Session metadata key of the session-scope extension settings. */\nexport const SESSION_SETTINGS_METADATA_KEY = 'zidane.extensionSettings'\n\ntype ExtensionValues = Record<string, unknown>\ntype SessionValues = Record<string, ExtensionValues>\n\n/** The session-scope values every settings port of a host shares. */\nexport interface SessionSettingsStore {\n /** The extension's values in the session; loads the session in the background on first read. */\n get: (sessionId: string, extensionId: string) => Readonly<ExtensionValues> | undefined\n /** Sets or clears (`undefined`) one value, and persists the session's values. */\n set: (sessionId: string, extensionId: string, key: string, value: unknown) => void\n /** Calls `listener` with each extension whose values a background load changed. Returns the unsubscribe. */\n subscribe: (listener: (extensionId: string) => void) => () => void\n /** Forgets a deleted session. */\n remove: (sessionId: string) => void\n /** Resolves once every background load and write started so far settled (tests, shutdown). */\n idle: () => Promise<void>\n}\n\n/** Options of {@link createSessionSettingsStore}. */\nexport interface SessionSettingsStoreOptions {\n /** The session's stored metadata, `undefined` for an unknown session. */\n load?: (sessionId: string) => Promise<Readonly<Record<string, unknown>> | undefined>\n /** Persists the session's values (the whole bag under the metadata key; `undefined` deletes it). */\n save?: (sessionId: string, values: SessionValues | undefined) => Promise<void>\n /** Where a failed load or save is reported. */\n onError?: (what: string, error: unknown) => void\n}\n\nfunction asBag(raw: unknown): SessionValues {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw))\n return {}\n const out: SessionValues = {}\n for (const [ext, values] of Object.entries(raw as Record<string, unknown>)) {\n if (values && typeof values === 'object' && !Array.isArray(values))\n out[ext] = { ...(values as ExtensionValues) }\n }\n return out\n}\n\n/**\n * Creates the store.\n *\n * @param options - How a session's metadata is loaded and saved.\n */\nexport function createSessionSettingsStore(options: SessionSettingsStoreOptions = {}): SessionSettingsStore {\n const cache = new Map<string, SessionValues>()\n const loading = new Map<string, Promise<void>>()\n const pending = new Set<Promise<unknown>>()\n const listeners = new Set<(extensionId: string) => void>()\n const report = (what: string, error: unknown): void => options.onError?.(what, error)\n const track = <T>(work: Promise<T>): void => {\n pending.add(work)\n void work.finally(() => pending.delete(work)).catch(() => undefined)\n }\n\n const hydrate = (sessionId: string): void => {\n if (!options.load || loading.has(sessionId))\n return\n const work = options.load(sessionId).then((metadata) => {\n const stored = asBag(metadata?.[SESSION_SETTINGS_METADATA_KEY])\n // A write made while loading wins over what was stored.\n const current = cache.get(sessionId) ?? {}\n const merged: SessionValues = { ...stored }\n for (const [ext, values] of Object.entries(current))\n merged[ext] = { ...stored[ext], ...values }\n cache.set(sessionId, merged)\n for (const ext of Object.keys(stored)) {\n for (const listener of [...listeners]) {\n try {\n listener(ext)\n }\n catch {}\n }\n }\n }, error => report(`load session ${sessionId}`, error))\n loading.set(sessionId, work)\n track(work)\n }\n\n return {\n get: (sessionId, ext) => {\n const values = cache.get(sessionId)\n if (!values)\n hydrate(sessionId)\n return values?.[ext]\n },\n set: (sessionId, ext, key, value) => {\n const values = { ...cache.get(sessionId) }\n const bag = { ...values[ext] }\n if (value === undefined)\n delete bag[key]\n else\n bag[key] = value\n if (Object.keys(bag).length === 0)\n delete values[ext]\n else\n values[ext] = bag\n cache.set(sessionId, values)\n if (options.save) {\n // Saved after the stored values arrived, so a first write never drops another extension's.\n const before = loading.get(sessionId) ?? Promise.resolve()\n if (!loading.has(sessionId))\n hydrate(sessionId)\n const work = (loading.get(sessionId) ?? before).then(() => {\n const all = cache.get(sessionId) ?? {}\n return options.save!(sessionId, Object.keys(all).length > 0 ? all : undefined)\n }).catch(error => report(`save session ${sessionId}`, error))\n track(work)\n }\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n remove: (sessionId) => {\n cache.delete(sessionId)\n loading.delete(sessionId)\n },\n idle: async () => {\n while (pending.size > 0)\n await Promise.allSettled([...pending])\n },\n }\n}\n","/**\n * Where a daemon or server keeps extension settings:\n *\n * user the settings file's `extensionConfig` (`state.json`), the bag the\n * registry's config items and today's Settings UIs read and write\n * project `<projectRoot>/<prefix>/extension-settings.json`, by extension\n * session with the session, in its metadata (`./session-settings`)\n * config the declarative `extensions` entries of the user and project\n * `config.json` (read-only: Settings shows those keys locked)\n * secrets the credentials file, as `extension-secret:<id>:<key>` API key\n * entries; never a settings file. A secret an older version left in the bag is\n * still read, and moved out on the next write.\n *\n * Every write notifies the extension's listeners, so `ctx.settings.onChange`\n * fires in each runtime that built over the port.\n */\nimport type { ExtensionConfigValue } from '../../../extensions/config'\nimport type { ConfigSettingsLayer } from '../../../extensions/declarative/settings-layer'\nimport type { SettingsLayer, SettingsPort } from '../../../extensions/settings'\nimport type { StoredSettingValue } from '../../../extensions/settings/validate'\nimport type { HostSettings } from '../../protocol'\nimport type { SessionSettingsStore } from './session-settings'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../../atomic-write'\nimport { readCredentialEntry, writeCredentialEntry } from '../../../chat/credentials'\nimport { toWireValue } from '../../../extensions/settings/wire'\nimport { isSafeRecordKey } from '../../../extensions/shared'\nimport { createSessionSettingsStore } from './session-settings'\n\n/** Prefix of an extension setting secret's key in the credentials file. */\nexport const EXTENSION_SECRET_PREFIX = 'extension-secret:'\n\n/** The project file's name under `<projectRoot>/<prefix>`. */\nexport const PROJECT_SETTINGS_FILE = 'extension-settings.json'\n\n/** A settings port with a way to tell listeners the files changed outside it. */\nexport interface DaemonSettingsPort extends SettingsPort {\n /** Re-reads the project file and the config layer, and notifies every listener (a file changed on disk). */\n refresh: () => void\n /** Stops listening to the session store. */\n dispose: () => void\n}\n\n/** Options of {@link createDaemonSettingsPort}. */\nexport interface DaemonSettingsPortOptions {\n /** The host's live settings. */\n readSettings: () => Pick<HostSettings, 'extensionConfig'>\n /** Persists a settings patch (the daemon environment's `writeSettings`). */\n writeSettings: (patch: Pick<HostSettings, 'extensionConfig'>) => void\n /** The credentials file's folder (the host's user data dir). */\n dataDir: string\n /** `<projectRoot>/<prefix>`, when the folder is in a project. */\n projectDir?: string\n /** Session-scope values, shared by every port of the host. Default: in memory only. */\n sessions?: SessionSettingsStore\n /** The `config` layer (`createConfigSettingsLayer`), read once and again after {@link DaemonSettingsPort.refresh}. Absent: no config layer. */\n configLayer?: () => ConfigSettingsLayer\n}\n\ntype Bag = Record<string, Record<string, unknown>>\n\nfunction readJson(path: string): Bag {\n if (!existsSync(path))\n return {}\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8')) as unknown\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed as Bag : {}\n }\n catch {\n return {}\n }\n}\n\n/**\n * The credentials-file key of a setting secret.\n *\n * @param extensionId - The extension.\n * @param key - The setting key.\n */\nexport function extensionSecretKey(extensionId: string, key: string): string {\n return `${EXTENSION_SECRET_PREFIX}${extensionId}:${key}`\n}\n\n/**\n * Creates the port for one folder (its project file) over the host's settings.\n *\n * @param options - Settings access, credentials folder, project folder.\n */\nexport function createDaemonSettingsPort(options: DaemonSettingsPortOptions): DaemonSettingsPort {\n const listeners = new Map<string, Set<() => void>>()\n const sessions = options.sessions ?? createSessionSettingsStore()\n const projectFile = options.projectDir ? join(options.projectDir, PROJECT_SETTINGS_FILE) : undefined\n let project: Bag | undefined\n let configLayer: ConfigSettingsLayer | undefined\n const configValues = (ext: string): Readonly<Record<string, unknown>> | undefined => {\n if (!options.configLayer)\n return undefined\n configLayer ??= options.configLayer()\n const values = configLayer.values(ext)\n return Object.keys(values).length > 0 ? values : undefined\n }\n\n const projectBag = (): Bag => (project ??= projectFile ? readJson(projectFile) : {})\n const userBag = (ext: string): Readonly<Record<string, unknown>> | undefined => {\n const all = options.readSettings().extensionConfig\n return all && Object.hasOwn(all, ext) ? all[ext] : undefined\n }\n const notify = (ext: string): void => {\n for (const listener of [...listeners.get(ext) ?? []]) {\n try {\n listener()\n }\n catch {}\n }\n }\n // A session's stored values arrived: the extensions they belong to re-read.\n const stopSessions = sessions.subscribe(notify)\n const writeUser = (ext: string, key: string, value: ExtensionConfigValue | undefined): void => {\n const all = { ...options.readSettings().extensionConfig }\n const bag = { ...all[ext] }\n if (value === undefined && !Object.hasOwn(bag, key))\n return\n if (value === undefined)\n delete bag[key]\n else\n bag[key] = value\n if (Object.keys(bag).length === 0)\n delete all[ext]\n else\n all[ext] = bag\n options.writeSettings({ extensionConfig: all })\n }\n\n return {\n read: (ext: string, layer: SettingsLayer, sessionId?: string) => {\n switch (layer) {\n case 'user': return userBag(ext)\n case 'project': return projectFile ? projectBag()[ext] : undefined\n case 'session': return sessionId ? sessions.get(sessionId, ext) : undefined\n case 'config': return configValues(ext)\n default: return undefined\n }\n },\n write: (ext, scope, key, value: StoredSettingValue | undefined, sessionId) => {\n if (!isSafeRecordKey(key))\n throw new TypeError(`invalid setting key ${JSON.stringify(key)}`)\n if (scope === 'user') {\n writeUser(ext, key, value === undefined ? undefined : toWireValue(value))\n }\n else if (scope === 'project') {\n if (!projectFile)\n throw new Error('this folder is in no project: project settings have nowhere to go')\n const all = { ...readJson(projectFile) }\n const bag = { ...all[ext] }\n if (value === undefined)\n delete bag[key]\n else\n bag[key] = value\n all[ext] = bag\n writeJsonFileAtomic(projectFile, all, OWNER_ONLY)\n project = all\n }\n else {\n if (!sessionId)\n throw new Error('a session setting needs a session')\n sessions.set(sessionId, ext, key, value)\n }\n notify(ext)\n },\n subscribe: (ext, listener) => {\n let set = listeners.get(ext)\n if (!set) {\n set = new Set()\n listeners.set(ext, set)\n }\n set.add(listener)\n const own = set\n return () => {\n own.delete(listener)\n }\n },\n secrets: {\n get: (ext, key) => {\n const entry = readCredentialEntry(options.dataDir, extensionSecretKey(ext, key))\n if (entry?.kind === 'apikey' && entry.value)\n return entry.value\n // Older versions kept secrets in the settings bag.\n const legacy = userBag(ext)?.[key]\n return typeof legacy === 'string' && legacy ? legacy : undefined\n },\n set: (ext, key, value) => {\n writeCredentialEntry(options.dataDir, extensionSecretKey(ext, key), value === undefined ? undefined : { kind: 'apikey', value })\n writeUser(ext, key, undefined)\n notify(ext)\n },\n },\n refresh: () => {\n project = undefined\n configLayer = undefined\n for (const ext of listeners.keys())\n notify(ext)\n },\n dispose: stopSessions,\n }\n}\n","/**\n * Extension storage on a daemon or server, synced to its clients\n * . Files as `createFileStoragePort` lays them out\n * (`<dataDir>/extension-storage`, and `<projectRoot>/<prefix>/extension-storage`\n * for project and session scope), one port per project root, shared by\n * every runtime built for a folder of that project.\n *\n * A write from an extension reaches the other runtimes holding the same file\n * (several folders of one project, the user scope everywhere) and every\n * client as `extensions:storage`. A write from a client\n * (`extensions.storage.set`) reaches every runtime holding the file, and\n * every other client.\n */\nimport type { ExtensionsSignal } from '../../../chat/host/extensions-wire'\nimport type { Disposable } from '../../../extensions/api/core'\nimport type { Json } from '../../../extensions/api/storage'\nimport type { FileStoragePort, StorageArea, StorageChange, StorageLocation, StoragePort, StorageSnapshot } from '../../../extensions/storage'\nimport { join } from 'node:path'\nimport { createFileStoragePort } from '../../../extensions/storage'\n\n/** A storage change as clients get it. */\nexport type StorageSignal = Extract<ExtensionsSignal, { kind: 'extensions:storage' }>\n\n/** One project's storage, as the runtimes and the protocol handlers use it. */\nexport interface SyncedStorage {\n /** The port the runtimes of this project take. */\n readonly port: StoragePort\n /** The project root of `project` / `session` files, when there is one. */\n readonly projectRoot?: string\n /** Reads a location for a client. */\n load: (loc: StorageLocation) => Promise<StorageSnapshot>\n /** Writes for a client: every runtime holding the file hears it. Returns the signal for the other clients (with the entry's new `version`). */\n write: (loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined) => Promise<StorageSignal & { version: number }>\n /** One entry as stored now, and how many writes it has had on this host. */\n current: (loc: StorageLocation, area: StorageArea, key: string) => Promise<{ version: number, value?: Json }>\n}\n\n/** Every project's synced storage of one host. */\nexport interface StorageSyncHub {\n /** The storage of `projectRoot` (`undefined`: no project, everything under the data dir). */\n forProject: (projectRoot: string | undefined) => SyncedStorage\n /** Closes every port. */\n close: () => void\n}\n\n/** Options of {@link createStorageSyncHub}. */\nexport interface StorageSyncHubOptions {\n /** The host's data dir (`<dataDir>/extension-storage`). */\n dataDir: string\n /** Storage prefix (`.zidane`). */\n prefix: string\n /** Sends a change made by an extension to every client. */\n publish: (signal: StorageSignal) => void\n}\n\n/**\n * Creates the hub.\n *\n * @param options - Where files live and how changes reach clients.\n */\nexport function createStorageSyncHub(options: StorageSyncHubOptions): StorageSyncHub {\n /** Listeners by file path: every runtime's subscription to that file. */\n const listeners = new Map<string, Set<(change: StorageChange) => void>>()\n const projects = new Map<string, SyncedStorage & { file: FileStoragePort }>()\n /** Writes per entry (file, area, key) since the host started: clients order signals and set results by it. */\n const versions = new Map<string, number>()\n const entryKey = (path: string, area: StorageArea, key: string): string => `${path}\\u0000${area}\\u0000${key}`\n const bump = (path: string, area: StorageArea, key: string): number => {\n const k = entryKey(path, area, key)\n const next = (versions.get(k) ?? 0) + 1\n versions.set(k, next)\n return next\n }\n\n const notify = (path: string, change: StorageChange): void => {\n for (const listener of [...listeners.get(path) ?? []]) {\n try {\n listener(change)\n }\n catch {\n // A domain listener is guarded; a broken one never stops the others.\n }\n }\n }\n\n const signalOf = (projectRoot: string | undefined, loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined, version: number): StorageSignal & { version: number } => ({\n kind: 'extensions:storage',\n extensionId: loc.extensionId,\n scope: loc.scope,\n ...(loc.sessionId !== undefined ? { sessionId: loc.sessionId } : {}),\n ...(projectRoot !== undefined && loc.scope !== 'user' ? { projectRoot } : {}),\n area,\n key,\n ...(value !== undefined ? { value } : {}),\n version,\n })\n\n const forProject = (projectRoot: string | undefined): SyncedStorage => {\n const memo = projects.get(projectRoot ?? '')\n if (memo)\n return memo\n const file = createFileStoragePort({\n root: join(options.dataDir, 'extension-storage'),\n ...(projectRoot ? { projectRoot: join(projectRoot, options.prefix, 'extension-storage') } : {}),\n watch: false,\n })\n const apply = async (loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined): Promise<number> => {\n if (value === undefined)\n await file.delete(loc, area, key)\n else\n await file.save(loc, area, key, value)\n const version = bump(file.fileOf(loc), area, key)\n notify(file.fileOf(loc), { area, key, value })\n return version\n }\n const port: StoragePort = {\n folderOf: file.folderOf,\n load: loc => file.load(loc),\n save: async (loc, area, key, value) => {\n const version = await apply(loc, area, key, value)\n options.publish(signalOf(projectRoot, loc, area, key, value, version))\n },\n delete: async (loc, area, key) => {\n const version = await apply(loc, area, key, undefined)\n options.publish(signalOf(projectRoot, loc, area, key, undefined, version))\n },\n subscribe: (loc, listener): Disposable => {\n const path = file.fileOf(loc)\n let set = listeners.get(path)\n if (!set) {\n set = new Set()\n listeners.set(path, set)\n }\n set.add(listener)\n const own = set\n return {\n dispose: () => {\n own.delete(listener)\n if (own.size === 0 && listeners.get(path) === own)\n listeners.delete(path)\n },\n }\n },\n }\n const synced = {\n file,\n port,\n ...(projectRoot ? { projectRoot } : {}),\n load: (loc: StorageLocation) => file.load(loc),\n write: async (loc: StorageLocation, area: StorageArea, key: string, value: Json | undefined) => {\n const version = await apply(loc, area, key, value)\n return signalOf(projectRoot, loc, area, key, value, version)\n },\n current: async (loc: StorageLocation, area: StorageArea, key: string) => {\n const snapshot = await file.load(loc)\n const entries = snapshot[area]\n const value = Object.hasOwn(entries, key) ? entries[key] : undefined\n return { version: versions.get(entryKey(file.fileOf(loc), area, key)) ?? 0, ...(value !== undefined ? { value } : {}) }\n },\n }\n projects.set(projectRoot ?? '', synced)\n return synced\n }\n\n return {\n forProject,\n close: () => {\n for (const p of projects.values())\n p.file.close()\n projects.clear()\n listeners.clear()\n },\n }\n}\n","/**\n * The `ui` bundles of a host's extensions: each\n * active extension's `ui.tsx` compiled once per content (`compileUiEntry`,\n * cached on disk by the bundler), kept in memory by hash, and named by a URL\n * a window loads.\n *\n * Compiles are remembered in memory by entry and content: while every file\n * the last compile of an entry bundled still has the content it had (its\n * `inputs` hashes), the entry is not compiled again. Listing the entries and\n * listing the UI each ask for the same bundles; only the first compiles.\n *\n * A zidane-server names bundles by its HTTP route\n * (`/zidane/extensions/ui/<hash>.js`, served from this store by\n * `server/extension-assets`); a daemon, which has no HTTP port, writes each\n * bundle to `<cacheDir>/bundles/<hash>.js` and names it by its `file:` URL\n * (windows on the same machine read it).\n */\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { compileUiEntry, resolveUiEntries, UiBundleError } from '../../../extensions/bundle'\nimport { SERVER_EXTENSIONS_UI_PATH } from '../../extension-paths'\n\n/** One active extension, as its bundle needs it. */\nexport interface UiBundleSource {\n id: string\n /** Its folder; absent for an inline extension (nothing to bundle). */\n dir?: string\n /** `definition.ui`, when set. */\n ui?: unknown\n}\n\n/**\n * A compiled bundle. `inputs` (absolute path → sha256 of the content\n * bundled) lets the store reuse it while those files are unchanged; without\n * it every ask compiles again.\n */\nexport interface CompiledBundle { code: string, hash: string, inputs?: Readonly<Record<string, string>> }\n\n/** Where a window loads a bundle, and its content hash. */\nexport interface UiBundleRef { url: string, hash: string }\n\n/** The bundles of one host. */\nexport interface UiBundleStore {\n /** The extension's bundle, why it did not bundle (`errors`), or `undefined` when it has no `ui` entry. */\n bundle: (source: UiBundleSource) => Promise<UiBundleRef | { errors: string[] } | undefined>\n /** A bundle's code by hash, while kept. */\n code: (hash: string) => string | undefined\n}\n\n/** Options of {@link createUiBundleStore}. */\nexport interface UiBundleStoreOptions {\n /** Where the bundler caches compiled entries (and, for `file` URLs, the bundles). */\n cacheDir: () => string\n /** How bundles are named: by the server route, or by a `file:` URL of the written bundle. */\n urls: 'route' | 'file'\n /** Bundles one entry. Default `compileUiEntry`. */\n compile?: (options: { entry: string, extensionId: string, cacheDir: string, dir: string }) => Promise<CompiledBundle>\n}\n\nconst MAX_BUNDLES = 256\n\n/** Every input still has the content it was bundled with. */\nfunction inputsCurrent(inputs: Readonly<Record<string, string>> | undefined): boolean {\n if (!inputs || Object.keys(inputs).length === 0)\n return false\n for (const [path, hash] of Object.entries(inputs)) {\n try {\n if (createHash('sha256').update(readFileSync(path)).digest('hex') !== hash)\n return false\n }\n catch {\n return false\n }\n }\n return true\n}\n\n/**\n * Creates a host's bundle store.\n *\n * @param options - Cache folder, URL kind and the compiler.\n * @returns The store.\n */\nexport function createUiBundleStore(options: UiBundleStoreOptions): UiBundleStore {\n const compile = options.compile ?? compileUiEntry\n const bundles = new Map<string, string>()\n const building = new Map<string, Promise<CompiledBundle>>()\n /** Entry → its last compile, reused while its inputs are unchanged. */\n const compiled = new Map<string, CompiledBundle>()\n\n const keep = (bundle: CompiledBundle): void => {\n bundles.delete(bundle.hash)\n bundles.set(bundle.hash, bundle.code)\n for (const old of bundles.keys()) {\n if (bundles.size <= MAX_BUNDLES)\n break\n bundles.delete(old)\n }\n }\n\n const urlOf = (bundle: CompiledBundle): string => {\n if (options.urls === 'route')\n return `${SERVER_EXTENSIONS_UI_PATH}/${bundle.hash}.js`\n const dir = join(options.cacheDir(), 'bundles')\n const file = join(dir, `${bundle.hash}.js`)\n // Named by its content: an existing file already holds these bytes. A new one is\n // renamed into place whole, so a window importing it never reads a partial write.\n if (!existsSync(file)) {\n mkdirSync(dir, { recursive: true })\n const temp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n writeFileSync(temp, bundle.code)\n renameSync(temp, file)\n }\n return pathToFileURL(file).href\n }\n\n return {\n bundle: async (source) => {\n if (!source.dir)\n return undefined\n const entries = resolveUiEntries(source.dir, { ui: source.ui })\n if (!entries.ui) {\n const errors = entries.errors.filter(e => e.startsWith('ui:'))\n return errors.length > 0 ? { errors } : undefined\n }\n const entry = entries.ui\n const known = compiled.get(entry)\n if (known && inputsCurrent(known.inputs)) {\n keep(known)\n return { hash: known.hash, url: urlOf(known) }\n }\n compiled.delete(entry)\n let pending = building.get(entry)\n if (!pending) {\n pending = compile({ entry, extensionId: source.id, cacheDir: options.cacheDir(), dir: source.dir })\n building.set(entry, pending)\n void pending.finally(() => building.delete(entry)).catch(() => undefined)\n }\n try {\n const bundle = await pending\n if (bundle.inputs) {\n compiled.delete(entry)\n compiled.set(entry, bundle)\n for (const old of compiled.keys()) {\n if (compiled.size <= MAX_BUNDLES)\n break\n compiled.delete(old)\n }\n }\n keep(bundle)\n return { hash: bundle.hash, url: urlOf(bundle) }\n }\n catch (err) {\n return { errors: err instanceof UiBundleError ? [...err.errors] : [err instanceof Error ? err.message : String(err)] }\n }\n },\n code: hash => bundles.get(hash),\n }\n}\n","import type { Hookable } from 'hookable'\nimport type { AgentHooks } from '../../../agent'\nimport type { ProviderKey } from '../../../chat/auth'\n/**\n * The extension API host of a daemon or a zidane-server: the real ports\n * every per-folder extension runtime is built over, and the\n * runtimes themselves, so the protocol handlers (`../handlers/extensions`)\n * reach their UI, RPC, storage, settings, commands and integrations.\n *\n * One per host process, shared by every folder's registry:\n *\n * storage files, synced to the other runtimes and to clients (`./storage-sync`)\n * settings the settings file, the project's `extension-settings.json`,\n * secrets in the credentials file (`./settings-port`)\n * authStore the credentials file (`createCredentialsAuthStore`)\n * flows sign-in steps shown on a client (`./flows`)\n * dialogs, ui routed to the client viewing the session (`./clients`)\n * rpc events published to every client as `rpc.event`\n * commands the host's `/` commands as built-ins; slash runs go through the session queue\n * keymap user overrides from `keybindings.json`, keyed by command id\n * catalogs built-ins, registry contributions and the folder's MCP and skills config\n * host sessions and workspace over the host-runtime bridge, a\n * `generate` port over this host's providers, artifact kinds\n * into the registry the build adopts (`chat/host/extension-artifact-kinds`)\n *\n * A session's `'session'` storage is preloaded into every runtime when a\n * client starts viewing it (`sessionOpened`); the chat host preloads it\n * again before each run.\n *\n * Host events: the runtimes are told the host emits `run:settled` and\n * `session:event` itself (`emitsHostEvents`); the chat host does, where it\n * runs the registry's session handlers (`chat/host/extension-sessions`). Agent hooks go\n * through one fan-out per registry (`chat/host/extension-hooks-fanout`):\n * the agent build attaches every session agent to it.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { AgentHooksFanout } from '../../../chat/host/extension-hooks-fanout'\nimport type { ExtensionsSignal, WireExtensionEntry, WireUiBundle } from '../../../chat/host/extensions-wire'\nimport type { ResolvedConfig } from '../../../chat/index'\nimport type { AccessScope } from '../../../extensions/api/core'\nimport type { CommandHostPort, CommandListing, KeymapPort } from '../../../extensions/commands'\nimport type { BuildRuntimeOptions, ExtensionHostRuntimeBridge, ExtensionRegistry, ExtensionRuntime } from '../../../extensions/index'\nimport type { ExtensionMcpHost } from '../../../extensions/mcp-host'\nimport type { RpcRemoteCaller } from '../../../extensions/rpc/bridge'\nimport type { RpcResponseEnvelope } from '../../../extensions/rpc/wire'\nimport type { HostRuntimePorts } from '../../../extensions/runtime/domains'\nimport type { McpServerConfig } from '../../../mcp'\nimport type { SessionArtifact } from '../../../session/artifacts'\nimport type { HostSettings, HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { UiClientDirectory } from './clients'\nimport type { FlowRegistry } from './flows'\nimport type { DaemonSettingsPort } from './settings-port'\nimport type { StorageSyncHub } from './storage-sync'\nimport type { UiBundleSource, UiBundleStore, UiBundleStoreOptions } from './ui-bundles'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { createHooks } from 'hookable'\nimport { activeAccountOf } from '../../../chat/auth'\nimport { createCatalogPorts, linkCatalogs } from '../../../chat/host/agent-build'\nimport { createArtifactKindsHost } from '../../../chat/host/extension-artifact-kinds'\nimport { createAgentHooksFanout, recordAgentHooksFanout } from '../../../chat/host/extension-hooks-fanout'\nimport { createProviderBuilder, resolveSessionModel } from '../../../chat/host/models/index'\nimport { keybindingsPath, readKeybindingsRaw } from '../../../chat/keybindings'\nimport { BUILTIN_PROVIDERS } from '../../../chat/providers'\nimport { resolveUiEntries } from '../../../extensions/bundle'\nimport { builtinKeymapEntries } from '../../../extensions/commands'\nimport { loadExtensionsConfig } from '../../../extensions/declarative/node'\nimport { createConfigSettingsLayer } from '../../../extensions/declarative/settings-layer'\nimport { extensionRuntimeOf } from '../../../extensions/index'\nimport { createCredentialsAuthStore } from '../../../extensions/integrations'\nimport { RpcErrorType } from '../../../extensions/rpc/wire'\nimport { onPanelChanged } from '../../../extensions/ui/registry'\nimport { watchFileChanges } from '../watch-file'\nimport { createUiClientDirectory } from './clients'\nimport { createFlowRegistry } from './flows'\nimport { commandInvocationOf, createExtensionMcpServerCalls, decisionsPort, mcpCallVia, mcpStatusOf } from './host-ports'\nimport { createHostImagePort } from './image-port'\nimport { createSessionSettingsStore, SESSION_SETTINGS_METADATA_KEY } from './session-settings'\nimport { createDaemonSettingsPort } from './settings-port'\nimport { createStorageSyncHub } from './storage-sync'\nimport { createUiBundleStore } from './ui-bundles'\n\n/** What the extension host uses of the chat host, once it exists. */\nexport type DaemonChatHostPort = Pick<ChatHost, 'listCommands' | 'queueAdd' | 'appendNote' | 'appendTurns' | 'patchSessionMeta'> & { mcpServers: Pick<ChatHost['mcpServers'], 'instances' | 'connected' | 'connect'> }\n\n/** One folder's runtime, as the protocol handlers find it. */\nexport interface AdoptedRuntime {\n /** The folder the registry was built for. */\n cwd: string\n /** Its project root, when it has one. */\n projectRoot?: string\n runtime: ExtensionRuntime\n /** The registry over it (its refused entries too). */\n registry: ExtensionRegistry\n /** The folder's settings port. */\n settings: DaemonSettingsPort\n}\n\n/** What {@link DaemonExtensionsHost.prepare} returns for one registry build. */\nexport interface PreparedBuild {\n /** Pass as `runtime` to `discoverAndBuildExtensionRegistry`. */\n runtime: BuildRuntimeOptions\n /** Call with the built registry and config: links the catalogs and publishes the runtime until {@link DaemonExtensionsHost.release}. */\n adopt: (registry: ExtensionRegistry, config?: ResolvedConfig) => void\n}\n\n/** The extension host of one daemon or server process. */\nexport interface DaemonExtensionsHost {\n /** `daemon`, or `server` for a zidane-server. */\n readonly kind: 'daemon' | 'server'\n /** The windows connected to this host, and the routing of dialogs and UI requests to them. */\n readonly clients: UiClientDirectory\n /** The synced storage of each project, shared by every client. */\n readonly storage: StorageSyncHub\n /** The integration sign-in flows in progress, and the input each waits for. */\n readonly flows: FlowRegistry\n /** The extensions' compiled `ui` bundles (a server's routes serve them, a daemon writes them to its cache). */\n readonly uiBundles: UiBundleStore\n /** The extensions of an adopted folder, as windows list them (`extensions.entries`). Never rejects. */\n entries: (adopted: AdoptedRuntime) => Promise<WireExtensionEntry[]>\n /** The compiled `ui` bundle of each active extension of an adopted folder, by id. Never rejects. */\n bundles: (adopted: AdoptedRuntime) => Promise<Record<string, WireUiBundle>>\n /** Late-bound: extension signals go out unnumbered through the peer fan-out once it exists. */\n bindPeers: (peers: { broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void }) => void\n /** Late-bound: the chat host, for built-in commands, slash runs, command invocations, session settings and MCP status. */\n bindHost: (host: DaemonChatHostPort) => void\n /** Late-bound: the MCP connections behind `ctx.mcp.call` (the environment's `createExtensionMcpHost`). */\n bindMcp: (mcp: ExtensionMcpHost) => void\n /** The runtime build options and the adopt step of one registry build for `cwd`. */\n prepare: (target: { cwd: string, projectRoot?: string }) => PreparedBuild\n /** The registry is being disposed: its runtime stops publishing and is no longer found. */\n release: (registry: ExtensionRegistry) => void\n /** The newest runtime adopted for `cwd`. */\n runtimeFor: (cwd: string) => AdoptedRuntime | undefined\n /** Every adopted runtime, newest first. */\n runtimes: () => AdoptedRuntime[]\n /** Sends an extension signal to every client (except `origin`). */\n publish: (signal: ExtensionsSignal, origin?: HostPeer | null) => void\n /** A session was deleted: its UI items go. */\n removeSession: (sessionId: string) => void\n /** A client opened a session: its `'session'` storage is loaded into every runtime. Never rejects. */\n sessionOpened: (sessionId: string) => Promise<void>\n /**\n * Runs a remote RPC call: the runtime of `params.cwd` when given, else the\n * newest runtime holding the contract. `authorize`: whether the caller's\n * token reaches a method's `scope` (absent: a local connection, not\n * limited). Never rejects.\n */\n rpcCall: (params: unknown, caller: RpcRemoteCaller, signal?: AbortSignal, authorize?: (scope: AccessScope) => boolean) => Promise<RpcResponseEnvelope>\n /** Closes the storage ports and watchers. */\n close: () => void\n}\n\n/** Options of {@link createDaemonExtensionsHost}. */\nexport interface DaemonExtensionsHostOptions {\n kind: 'daemon' | 'server'\n /** The host's user data dir: credentials, extension storage, `keybindings.json`. */\n dataDir: () => string\n /** Storage prefix (`.zidane`). */\n prefix: string\n readSettings: () => HostSettings\n writeSettings: (patch: Partial<HostSettings>) => void\n /** Sends a signal to every client until {@link DaemonExtensionsHost.bindPeers}. */\n broadcast: (signal: HostSignal) => void\n /** The host-runtime bridge the chat host attaches its session control to. */\n hostRuntime?: ExtensionHostRuntimeBridge\n /** Applies the credentials to the environment before a provider is built. */\n applyAuthEnv?: () => void\n /** The user config dir, whose `config.json` declares extensions (the `config` settings layer). Default {@link dataDir}. */\n configDir?: () => string\n /** A session's stored metadata, where session-scope settings are kept. Absent: they live in memory only. */\n sessionMetadata?: (sessionId: string) => Promise<Readonly<Record<string, unknown>> | undefined>\n /** Where background failures (a session settings save) are logged. */\n log?: (message: string) => void\n /** Stores an artifact (`ctx.generate.image` with `save` records each file). Default: the active session's artifact scope on {@link hostRuntime}. */\n recordArtifact?: (artifact: SessionArtifact) => Promise<unknown>\n /** Bundles one `ui` entry. Default `compileUiEntry`. A test seam. */\n compileUi?: UiBundleStoreOptions['compile']\n}\n\n/** What `extensions:entries` follows: each extension's id and status. */\nfunction entriesStamp(rt: ExtensionRuntime): string {\n return rt.extensions().map(info => `${info.id}:${info.status}:${info.error ?? ''}`).join('\\n')\n}\n\n/**\n * One `extensions:entries` (and `catalog:changed`) per change of a\n * runtime's extensions (their statuses), not per catalog or command change.\n */\nfunction entriesChanged(cwd: string, rt: ExtensionRuntime, publish: (signal: HostSignal) => void): () => void {\n let last = entriesStamp(rt)\n return () => {\n const now = entriesStamp(rt)\n if (now === last)\n return\n last = now\n publish({ kind: 'extensions:entries', cwd })\n publish({ kind: 'catalog:changed', catalog: 'extensions' })\n }\n}\n\n/** What `models.list` follows of a runtime's providers catalog: every provider and account list, by model id, name and state. */\nfunction modelListsStamp(rt: ExtensionRuntime): string {\n const { models, accountModels } = rt.outputs.catalogs.providers.read().sections\n return JSON.stringify([\n models.items.map(m => [m.providerId, m.id, m.name, m.enabled]),\n accountModels.items.map(m => [m.providerId, m.account, m.id, m.name, m.enabled]),\n ])\n}\n\n/**\n * One `catalog:changed` (`models`) when a provider transform changes what\n * `models.list` answers: a provider's list or an account's (a sign-in, a\n * new default account). Changes in one turn of the event loop send once.\n * Returns the unsubscribe.\n */\nfunction modelListsChanged(rt: ExtensionRuntime, publish: (signal: HostSignal) => void): () => void {\n let last = modelListsStamp(rt)\n let queued = false\n let stopped = false\n const off = rt.outputs.catalogs.providers.subscribe(() => {\n if (queued || stopped)\n return\n queued = true\n queueMicrotask(() => {\n queued = false\n if (stopped)\n return\n const now = modelListsStamp(rt)\n if (now === last)\n return\n last = now\n publish({ kind: 'catalog:changed', catalog: 'models' })\n })\n })\n return () => {\n stopped = true\n off()\n }\n}\n\n/** The compiled `ui` bundle of each active extension of an adopted folder, by id. */\nasync function bundlesOf(adopted: AdoptedRuntime, uiBundles: UiBundleStore): Promise<Record<string, WireUiBundle>> {\n const out: Record<string, WireUiBundle> = {}\n await Promise.all(adopted.runtime.extensions().filter(info => info.status === 'active').map(async (info) => {\n const ref = await uiBundles.bundle(uiSourceOf(adopted.runtime, info.id)).catch(() => undefined)\n if (ref && 'url' in ref)\n out[info.id] = ref\n }))\n return out\n}\n\n/** An extension's `ui` bundle source: its folder and `definition.ui`. */\nfunction uiSourceOf(rt: ExtensionRuntime, id: string): UiBundleSource {\n const record = rt.get(id)\n const ui = (record?.definition as { ui?: unknown } | undefined)?.ui\n return { id, ...(record?.entry.dir ? { dir: record.entry.dir } : {}), ...(ui !== undefined ? { ui } : {}) }\n}\n\n/** A catalog MCP server only an extension registered (`ctx.mcp.call` connects it on demand). */\nfunction extensionServerConfig(rt: ExtensionRuntime | undefined, name: string): McpServerConfig | undefined {\n const servers = rt?.outputs.catalogs.mcp.read().sections.servers\n return servers?.origin(name)?.kind === 'extension' ? servers.get(name) : undefined\n}\n\n/**\n * The extensions of an adopted folder, as windows list them: the runtime's\n * (with the `tui` entry and compiled `ui` bundle of the active ones), then\n * the folders the build refused (import errors, untrusted project folders).\n */\nasync function extensionEntries(adopted: AdoptedRuntime, bundles: UiBundleStore): Promise<WireExtensionEntry[]> {\n const { runtime, registry } = adopted\n const held = new Set<string>()\n const fromRuntime = await Promise.all(runtime.extensions().map(async (info): Promise<WireExtensionEntry> => {\n const record = runtime.get(info.id)\n const dir = record?.entry.dir\n if (dir)\n held.add(dir)\n const entry: WireExtensionEntry = {\n id: info.id,\n displayName: info.displayName,\n ...(info.version !== undefined ? { version: info.version } : {}),\n source: info.source,\n status: info.status,\n ...(info.error !== undefined ? { error: info.error } : {}),\n ...(dir ? { dir } : {}),\n }\n if (info.status !== 'active' || !dir)\n return entry\n const def = record?.definition as { ui?: unknown, tui?: unknown } | undefined\n const tui = resolveUiEntries(dir, { ...(def?.tui !== undefined ? { tui: def.tui } : {}) }).tui\n const ui = await bundles.bundle(uiSourceOf(runtime, info.id)).catch((err: unknown) => ({ errors: [err instanceof Error ? err.message : String(err)] }))\n return {\n ...entry,\n ...(tui ? { tuiEntry: tui } : {}),\n ...(ui && 'url' in ui ? { uiBundle: ui } : {}),\n ...(ui && 'errors' in ui ? { uiErrors: ui.errors } : {}),\n }\n }))\n const refused = registry.inactive.filter(e => e.error !== undefined && (e.dir === undefined || !held.has(e.dir)) && !runtime.get(e.name)).map((e): WireExtensionEntry => ({\n id: e.name,\n displayName: e.manifest?.displayName ?? e.name,\n source: e.source,\n status: 'failed',\n ...(e.error !== undefined ? { error: e.error } : {}),\n ...(e.dir !== undefined ? { dir: e.dir } : {}),\n }))\n return [...fromRuntime, ...refused]\n}\n\n/** `ctx.generate.decide` outside a run: a bus whose `decision:*` events reach the extensions' observers like an agent's. */\nfunction decisionHooksInto(fanout: AgentHooksFanout): Hookable<AgentHooks> {\n const hooks = createHooks<AgentHooks>()\n hooks.hook('decision:start', event => fanout.emit('decision:start', event))\n hooks.hook('decision:end', event => fanout.emit('decision:end', event))\n return hooks\n}\n\n/** Runs a remote RPC call: the runtime of `params.cwd` when given, else the newest runtime holding the contract. Never rejects. */\nasync function rpcCallOn(adopted: readonly AdoptedRuntime[], params: unknown, caller: RpcRemoteCaller, signal: AbortSignal | undefined, authorize: ((scope: AccessScope) => boolean) | undefined): Promise<RpcResponseEnvelope> {\n const p = (params && typeof params === 'object' ? params : {}) as { cwd?: unknown, contract?: unknown, method?: unknown }\n const contract = typeof p.contract === 'string' ? p.contract : ''\n const method = typeof p.method === 'string' ? p.method : ''\n const byCwd = typeof p.cwd === 'string' ? adopted.find(a => a.cwd === p.cwd) : undefined\n const target = byCwd ?? adopted.find(a => a.runtime.outputs.rpc.has(contract)) ?? adopted[0]\n const bridge = target?.runtime.rpcBridge\n if (!bridge)\n return { ok: false, error: { type: RpcErrorType.Unavailable, message: `no extension provides \"${contract}\"` }, meta: { contract, method, scope: 'chat' } }\n const { cwd: _cwd, ...rest } = p as Record<string, unknown>\n return bridge.call(rest, caller, signal, authorize)\n}\n\n/** User overrides of extension bindings from `keybindings.json` in the data dir, re-read when it changes. */\nfunction keymapPortOf(dataDir: () => string): KeymapPort {\n return {\n overrides: (commandId) => {\n const raw = readKeybindingsRaw(dataDir())[commandId]\n if (typeof raw === 'string')\n return raw\n return Array.isArray(raw) ? raw.filter((r): r is string => typeof r === 'string') : undefined\n },\n subscribe: listener => watchFileChanges(keybindingsPath(dataDir()), listener),\n }\n}\n\n/** Loads the `'session'` storage of each session into each runtime. Never rejects. */\nasync function preloadSessions(runtimes: readonly ExtensionRuntime[], sessionIds: Iterable<string>): Promise<void> {\n await Promise.all([...sessionIds].flatMap(id => runtimes.map(rt => rt.preloadSession(id))))\n}\n\nfunction refresh(runtime: ExtensionRuntime): void {\n const c = runtime.outputs.catalogs\n for (const catalog of [c.providers, c.models, c.agents, c.mcp, c.skills, c.tools])\n void catalog.reload()\n}\n\n/**\n * Creates the host's extension side.\n *\n * @param options - Kind, folders, settings and the broadcast sink.\n */\nexport function createDaemonExtensionsHost(options: DaemonExtensionsHostOptions): DaemonExtensionsHost {\n let fanOut: ((origin: HostPeer | null, signal: HostSignal) => void) | undefined\n let chatHost: DaemonChatHostPort | undefined\n let mcpHost: ExtensionMcpHost | undefined\n const publish = (signal: HostSignal, origin: HostPeer | null = null): void => {\n if (fanOut)\n fanOut(origin, signal)\n else\n options.broadcast(signal)\n }\n const clients = createUiClientDirectory()\n const storage = createStorageSyncHub({ dataDir: options.dataDir(), prefix: options.prefix, publish })\n const flows = createFlowRegistry({ callbackServer: options.kind === 'daemon' })\n const uiBundles = createUiBundleStore({\n cacheDir: () => join(options.dataDir(), 'cache', 'extension-ui'),\n urls: options.kind === 'server' ? 'route' : 'file',\n ...(options.compileUi ? { compile: options.compileUi } : {}),\n })\n const extensionMcp = createExtensionMcpServerCalls(() => chatHost?.mcpServers.connect)\n const authStore = createCredentialsAuthStore(options.dataDir())\n const sessionSettings = createSessionSettingsStore({\n ...(options.sessionMetadata ? { load: options.sessionMetadata } : {}),\n save: async (sessionId, values) => {\n await chatHost?.patchSessionMeta(sessionId, { [SESSION_SETTINGS_METADATA_KEY]: values })\n },\n onError: (what, error) => options.log?.(`[extensions] session settings: ${what}: ${String(error)}`),\n })\n const adopted: AdoptedRuntime[] = []\n const releases = new WeakMap<ExtensionRegistry, () => void>()\n const buildProvider = createProviderBuilder({ ...(options.applyAuthEnv ? { applyAuthEnv: options.applyAuthEnv } : {}), userDataDir: options.dataDir })\n\n /** The client a flow started by an extension shows on: the last active one that shows dialogs. */\n const routedPeer = (): HostPeer | undefined => {\n const best = clients.clients().filter(c => c.dialogs !== false).reduce<{ id: string, lastActiveAt: number } | undefined>((a, c) => (!a || c.lastActiveAt > a.lastActiveAt ? c : a), undefined)\n return best ? clients.peerOf(best.id) : undefined\n }\n\n const keymapPort = (): KeymapPort => keymapPortOf(options.dataDir)\n\n const commandsPort = (cwd: string, builtins: { list: readonly CommandListing[] }): CommandHostPort => ({\n builtins: () => builtins.list,\n keybindings: () => builtinKeymapEntries(readKeybindingsRaw(options.dataDir())),\n invocation: (_source, sessionId) => commandInvocationOf(chatHost, cwd, sessionId),\n runBuiltin: async (id, { args, sessionId }) => {\n if (!sessionId || !chatHost || !builtins.list.some(b => b.id === id))\n return false\n await chatHost.queueAdd(sessionId, `/${id}${args ? ` ${args}` : ''}`, undefined, undefined, id)\n return true\n },\n submitSlash: async (text, sessionId) => {\n if (sessionId && chatHost)\n await chatHost.queueAdd(sessionId, text)\n },\n })\n\n const hostPorts = (config: () => ResolvedConfig | undefined, registerKind: NonNullable<NonNullable<HostRuntimePorts['artifacts']>['registerKind']>, decisionHooks: Hookable<AgentHooks>, folder: string): HostRuntimePorts => {\n const bridge = options.hostRuntime\n return {\n ...(bridge\n ? {\n sessions: { sessionControl: bridge.sessionControl },\n workspace: { current: bridge.current },\n artifacts: { current: bridge.current, registerKind },\n }\n : {}),\n generate: {\n decide: decisionsPort(() => config()?.providers ?? BUILTIN_PROVIDERS, options.readSettings, buildProvider, decisionHooks),\n image: createHostImagePort({ providers: () => config()?.providers ?? BUILTIN_PROVIDERS, buildProvider, imageModel: () => options.readSettings().imageModel, folder, ...(bridge ? { bridge } : {}), ...(options.recordArtifact ? { recordArtifact: options.recordArtifact } : {}) }),\n resolve: (model) => {\n const providers = config()?.providers ?? BUILTIN_PROVIDERS\n const pick = model ?? (() => {\n const session = resolveSessionModel(undefined, providers)\n return { providerId: session.providerKey, modelId: session.model }\n })()\n if (!Object.hasOwn(providers, pick.providerId))\n throw new Error(`generate: no provider \"${pick.providerId}\" on this host`)\n return { ...pick, provider: buildProvider(providers, pick.providerId as ProviderKey) }\n },\n },\n }\n }\n\n const prepare = ({ cwd, projectRoot }: { cwd: string, projectRoot?: string }): PreparedBuild => {\n let config: ResolvedConfig | undefined\n let runtime: ExtensionRuntime | undefined\n const builtins: { list: readonly CommandListing[] } = { list: [] }\n const settings = createDaemonSettingsPort({\n readSettings: options.readSettings,\n writeSettings: options.writeSettings,\n dataDir: options.dataDir(),\n ...(projectRoot ? { projectDir: join(projectRoot, options.prefix) } : {}),\n sessions: sessionSettings,\n configLayer: () => {\n const loaded = loadExtensionsConfig({ configDir: (options.configDir ?? options.dataDir)(), cwd, prefix: options.prefix })\n return createConfigSettingsLayer([loaded.user, loaded.project])\n },\n })\n const fanout = createAgentHooksFanout()\n const decisionHooks = decisionHooksInto(fanout)\n const artifactKinds = createArtifactKindsHost()\n const catalogs = createCatalogPorts({\n providersCatalog: () => runtime?.outputs.catalogs.providers,\n activeAccount: (providerId) => {\n const descriptor = runtime?.outputs.catalogs.providers.read().sections.providers.get(providerId)\n return descriptor ? activeAccountOf(options.dataDir(), descriptor) : undefined\n },\n discovery: () => ({ cwd, prefix: options.prefix, home: homedir() }),\n mcp: {\n status: () => mcpStatusOf({ cwd, runtime, prefix: options.prefix, settings: options.readSettings(), dataDir: options.dataDir(), host: chatHost }),\n call: (server, tool, args, opts) => mcpCallVia(mcpHost, { calls: extensionMcp, config: name => extensionServerConfig(runtime, name) }, cwd, server, tool, args, opts),\n },\n })\n const runtimeOptions: BuildRuntimeOptions = {\n host: options.kind,\n ports: {\n storage: storage.forProject(projectRoot).port,\n settings,\n authStore,\n integrationFlows: flows.portFor(routedPeer).port,\n hooks: { ...fanout.port, emitsHostEvents: true },\n catalogs,\n commands: commandsPort(cwd, builtins),\n keymap: keymapPort(),\n dialogs: clients.dialogPort,\n uiClient: clients.uiClientPort,\n rpcTransport: { publish: envelope => publish({ kind: 'rpc.event', envelope }) },\n host: hostPorts(() => config, artifactKinds.registerKind, decisionHooks, projectRoot ?? cwd),\n },\n }\n const adopt = (built: ExtensionRegistry, resolved?: ResolvedConfig): void => {\n config = resolved\n runtime = extensionRuntimeOf(built)\n recordAgentHooksFanout(built, fanout)\n if (!runtime)\n return\n const releaseKinds = artifactKinds.adopt(built)\n const rt = runtime\n const entry: AdoptedRuntime = { cwd, ...(projectRoot ? { projectRoot } : {}), runtime: rt, registry: built, settings }\n adopted.unshift(entry)\n const { ui, commands, integrations } = rt.outputs\n const stops = [\n linkCatalogs(rt.outputs.catalogs),\n modelListsChanged(rt, publish),\n ui.subscribe(change => publish({ kind: 'extensions:ui', cwd, change })),\n onPanelChanged(ui, event => publish({ kind: 'extensions:panel', cwd, ...event })),\n commands.subscribe(() => publish({ kind: 'extensions:commands', cwd })),\n commands.keymap.subscribe(() => publish({ kind: 'extensions:keymap', cwd, ...(commands.keymap.currentMode() ? { mode: commands.keymap.currentMode()! } : {}) })),\n integrations.subscribe(() => publish({ kind: 'extensions:integrations', cwd })),\n // Loaded, reloaded, failed or unloaded (and a refused folder that loads now): windows list the entries again.\n built.subscribe(entriesChanged(cwd, rt, publish)),\n ]\n refresh(rt)\n // Sessions clients already show were opened before this runtime existed.\n void preloadSessions([rt], new Set(clients.clients().flatMap(c => c.viewing)))\n void chatHost?.listCommands(cwd).then((list) => {\n builtins.list = list.map(c => ({ id: c.name, title: c.description || c.name, slash: c.name }))\n publish({ kind: 'extensions:commands', cwd })\n }, () => undefined)\n publish({ kind: 'extensions:ui', cwd, change: { type: 'reset' } })\n releases.set(built, () => {\n releases.delete(built)\n settings.dispose()\n releaseKinds()\n for (const stop of stops) stop()\n const at = adopted.indexOf(entry)\n if (at >= 0)\n adopted.splice(at, 1)\n })\n }\n return { runtime: runtimeOptions, adopt }\n }\n\n return {\n kind: options.kind,\n clients,\n storage,\n flows,\n uiBundles,\n bundles: adopted => bundlesOf(adopted, uiBundles),\n entries: adopted => extensionEntries(adopted, uiBundles),\n bindPeers: (peers) => {\n fanOut = peers.broadcastExcept\n },\n bindHost: (host) => {\n chatHost = host\n },\n bindMcp: (mcp) => {\n mcpHost = mcp\n },\n prepare,\n release: registry => releases.get(registry)?.(),\n runtimeFor: cwd => adopted.find(a => a.cwd === cwd),\n runtimes: () => [...adopted],\n publish,\n removeSession: (sessionId) => {\n sessionSettings.remove(sessionId)\n for (const a of adopted)\n a.runtime.outputs.ui.removeSession(sessionId)\n },\n sessionOpened: sessionId => preloadSessions(adopted.map(a => a.runtime), [sessionId]),\n rpcCall: (params, caller, signal, authorize) => rpcCallOn(adopted, params, caller, signal, authorize),\n close: () => {\n storage.close()\n void extensionMcp.dispose()\n },\n }\n}\n","import type { ChatHostEnvironment, PendingApprovalsStore } from '../../chat/host/environment'\n/**\n * Disk-backed `ChatHostEnvironment` for the zidane daemon.\n *\n * Mirrors the TUI's storage layout so the daemon is a drop-in peer of the\n * terminal process: sessions in `sessions.db` (canonical sqlite store),\n * settings in `state.json`'s `settings` slot, credentials/safelist under the\n * shared user dir, extensions discovered per-cwd with the same allowlist +\n * trust contract every other surface uses.\n */\nimport type { ResolvedConfig } from '../../chat/index'\nimport type { ExtensionHostRuntimeBridge, ExtensionsConfigSync, ExtensionsConfigSyncOptions } from '../../extensions/index'\nimport type { ExtensionRegistry } from '../../extensions/types'\nimport type { LogSink } from '../../logger'\nimport type { SessionStore } from '../../session/index'\nimport type { HostSettings, HostSignal, WireApprovalRequest } from '../protocol'\nimport type { ExtensionFolderWatchOptions } from './extension-watch'\nimport type { DaemonExtensionsHost } from './extensions/host'\nimport { existsSync, readFileSync, unlinkSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { resolveConfig } from '../../chat/config'\nimport { applyApiKeyEnv, credentialsPath } from '../../chat/credentials'\nimport { createExtensionMcpHost } from '../../chat/extension-mcp-host'\nimport { createMemoryApprovalsStore } from '../../chat/host/approvals'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { projectRootOf } from '../../chat/project-root'\nimport { BUILTIN_PROVIDERS } from '../../chat/providers'\nimport { enforceSettingsInvariants, SETTINGS_TOGGLES } from '../../chat/settings-catalog'\nimport { DEFAULT_SETTINGS, settingsFromStored, sparseSettingsUpdate } from '../../chat/settings-defaults'\nimport { readSessionHeader } from '../../chat/store'\nimport { applyExtensionsConfigReport, configuredExtensions, createExtensionHostRuntimeBridge, createExtensionsConfigSync, defaultExtensionScanPaths, discoverAndBuildExtensionRegistry, extensionRuntimeOf, loadableExtensionDirs, registerExtensionApiHostModules, reloadChangedExtensions } from '../../extensions/index'\nimport { consoleSink, createLogger, fanoutSink } from '../../logger'\nimport { watchExtensionFolders } from './extension-watch'\nimport { createDaemonExtensionsHost } from './extensions/host'\nimport { watchFileChanges } from './watch-file'\n\n/** The host environment of a daemon or an embedded host: a {@link ChatHostEnvironment} backed by disk, with settings writes and runtime-config control. */\nexport interface DaemonEnvironment extends ChatHostEnvironment {\n /** Merges a patch into the stored settings, drops the `reset` keys it doesn't set, and returns the settings in effect afterwards. */\n writeSettings: (patch: Partial<HostSettings>, reset?: readonly (keyof HostSettings)[]) => HostSettings\n /** Drop the per-cwd runtime-config memo (settings changed) and dispose the registries it held. */\n invalidateRuntime: () => void\n /**\n * Gives the live reload of extensions (`watchExtensions`) and the runtime\n * cache's eviction the check they wait on: a folder's registry reloads, or\n * leaves the cache, only while `runActiveIn(cwd)` is `false` (no run in a\n * session reading that folder's extensions). The dispatcher sets it from\n * its chat host. Absent: an environment that does not watch extensions.\n */\n gateExtensionReloads?: (runActiveIn: (cwd: string) => boolean) => void\n /**\n * Drop the memo WITHOUT disposing: the next `runtimeConfig` builds fresh\n * registries while agents still running on the old ones keep working.\n * Returns the disposer for what was dropped; call it once no agent\n * holds those registries (`runtime.reload` after every session rebuilt).\n */\n forgetRuntime: () => () => void\n /** Base config resolved at daemon boot (paths, store, state). */\n config: ResolvedConfig\n /**\n * Calls `onChange` after the settings file changes, whoever wrote it (another\n * daemon or window on the same `state.json`). Returns the function that stops\n * watching. Absent when the settings live in no file.\n */\n watchSettings?: (onChange: () => void) => () => void\n /**\n * The extension API side: the real ports every folder's extension runtime is\n * built over, and the runtimes, for the protocol (`./extensions/host`).\n * Absent: a host whose registries another process builds (a window's\n * shared setup), or a test environment.\n */\n extensionRuntimes?: DaemonExtensionsHost\n /**\n * Declarative install: reconciles the `extensions` entries of the user and\n * project `config.json` for every folder's registry, in the background and\n * again when a config or lock file changes. Absent: a host whose registries\n * another process builds, or one built with `extensionsConfigSync: false`.\n */\n extensionsConfigSync?: ExtensionsConfigSync\n}\n\n/**\n * File-backed pending-approvals persistence (`pending-approvals.json` next\n * to `state.json`). Small, rewritten atomically enough for its purpose —\n * the queue holds at most a handful of rows.\n * @param path - Path of the JSON file. A missing or unreadable file reads as empty.\n * @returns A store that persists approvals to that file.\n */\nexport function createFileApprovalsStore(path: string): PendingApprovalsStore {\n function read(): WireApprovalRequest[] {\n if (!existsSync(path))\n return []\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8'))\n return Array.isArray(parsed) ? (parsed as WireApprovalRequest[]) : []\n }\n catch {\n return []\n }\n }\n\n function write(rows: WireApprovalRequest[]): void {\n if (rows.length === 0) {\n try {\n unlinkSync(path)\n }\n catch {\n // absent already — fine\n }\n return\n }\n // Atomic: this file exists to survive a crash — a torn write would\n // corrupt the very queue we're persisting to recover. Owner-only: rows\n // carry tool inputs (commands, file contents).\n writeJsonFileAtomic(path, rows, OWNER_ONLY)\n }\n\n return {\n insert(request) {\n const rows = read().filter(r => r.id !== request.id)\n rows.push(request)\n write(rows)\n },\n delete(id) {\n write(read().filter(r => r.id !== id))\n },\n clear() {\n write([])\n },\n list() {\n return read()\n },\n }\n}\n\n/** Options for {@link createHostEnvironment}. */\nexport interface HostEnvironmentOptions {\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Turns on verbose stream logging to the host console. */\n debugStream?: boolean\n /** Also receives its extensions' setup and runtime log records (stderr gets the warnings either way). */\n logSink?: LogSink\n /** Daemon only: base cwd for its own boot-time config resolution. Default: `process.cwd()`. */\n cwd?: string\n /** What the extensions see as `ctx.app.host`: a zidane-server passes `'server'`. Default `'daemon'`. */\n extensionsHost?: 'daemon' | 'server'\n /**\n * Reload an extension when its folder changes, load a folder that appears\n * under a scan root, unload one that goes (`./extension-watch`). Only\n * that extension reloads; the others keep running. Default `true`;\n * `false` leaves changes to `/reload`. Ignored with `shared`.\n */\n watchExtensions?: boolean | ExtensionFolderWatchOptions\n /**\n * Install the extensions config files declare (`extensions` in\n * `config.json`), in the background, and follow their changes. Default on;\n * `false` turns it off; an object replaces the install port or the file\n * watch (tests). Ignored with `shared`.\n */\n extensionsConfigSync?: false | Pick<ExtensionsConfigSyncOptions, 'port' | 'watch'>\n /**\n * Share the embedding window's setup instead of resolving the daemon's\n * own: a host in the window's process. Absent: the daemon (own config,\n * per-cwd extension discovery, multi-process).\n */\n shared?: SharedHostSetup\n}\n\n/** What a host in the window's own process takes from the window. */\nexport interface SharedHostSetup {\n /**\n * The window's boot config (paths, store, state file): one store and one\n * writer to `state.json` in the process.\n */\n config: ResolvedConfig\n /**\n * The window's per-cwd session config. Discovering extensions here instead\n * would run every extension's `setup` a second time in the same process.\n * `invalidate` / `forget` back `DaemonEnvironment.invalidateRuntime` /\n * `forgetRuntime` (settings changes, `runtime.reload`).\n */\n runtimeConfig: {\n resolve: (cwd: string) => Promise<ResolvedConfig>\n invalidate?: () => void\n forget?: () => () => void\n }\n /** Host-runtime bridge the window's registries were built with (`ChatHostEnvironment.hostRuntime`). */\n hostRuntime?: ExtensionHostRuntimeBridge\n /** Whether another process also drives these sessions. Default `false` (single writer). */\n multiProcess?: boolean\n /** The window's instrumentation for every agent the host builds (`ChatHostEnvironment.instrumentAgent`). */\n instrumentAgent?: ChatHostEnvironment['instrumentAgent']\n /** Whether the window can show terminals (`ChatHostEnvironment.terminals`). */\n terminals?: boolean\n}\n\n/**\n * The daemon's environment: its own config, per-cwd extension discovery, multi-process.\n * @param options - Broadcast sink and boot settings. `shared` is not accepted.\n * @returns The environment.\n */\nexport function createDaemonEnvironment(options: Omit<HostEnvironmentOptions, 'shared'>): Promise<DaemonEnvironment> {\n // Installed extensions import the authoring entries' runtime values (`Panel`, `createTestHost`) from this process.\n registerExtensionApiHostModules()\n return createHostEnvironment(options)\n}\n\n/**\n * Disk-backed host environment: the daemon's, or (with `shared`) a host\n * sharing the window's process and setup.\n * @param options - Broadcast sink, boot settings and the optional shared window setup.\n * @returns The environment.\n */\nexport async function createHostEnvironment(options: HostEnvironmentOptions): Promise<DaemonEnvironment> {\n const { shared } = options\n const config = shared?.config ?? await resolveOwnConfig(options.cwd)\n const store: SessionStore = config.store\n\n /*\n * Project-DB mode resolves storage to a PER-REPO `.zidane/sessions.db`\n * from the boot cwd. A single daemon serving windows opened in different\n * projects would then read/write every session against ONE project's DB.\n * The daemon is a single-store process, so warn loudly rather than\n * silently mixing projects; a project-scoped daemon (own socket) is the\n * supported way to use project-DB mode with the daemon.\n */\n if (!shared && config.paths.projectDir) {\n process.stderr.write(\n `[zidane-daemon] warning: project-DB mode is on, so this daemon uses ${config.paths.db}. `\n + `Windows opened in other projects will share this project's sessions. `\n + `Run a per-project daemon (ZIDANE_DAEMON_SOCKET) to isolate them.\\n`,\n )\n }\n\n /*\n * `config.initialSettings` is `resolveConfig`'s migrated snapshot of the\n * on-disk settings (it went through `settingsFromStored`, which maps the\n * legacy keys). Layering it under the live raw read means a user with\n * legacy-shaped settings gets the SAME effective settings in the daemon\n * as in the TUI, while mid-session writes (live `stateStore`) still win.\n * The live read goes through the same defaults migration, so a value\n * frozen at an old default by an older full-object writer doesn't override it.\n */\n const readSettings = (): HostSettings => ({\n ...DEFAULT_SETTINGS,\n ...config.initialSettings,\n ...settingsFromStored(config.stateStore.load().settings ?? {}),\n })\n\n /**\n * Fields the invariant forced (only ever `false`), so the stored file records\n * them too — otherwise a later read of `state.settings` would resurrect the\n * value the invariant just rejected. A field already `false` before the\n * invariant ran is left out: writing it would freeze a default on disk.\n */\n const pickInvariantFields = (unenforced: HostSettings, merged: HostSettings, patch: Partial<HostSettings>): Partial<HostSettings> => {\n const out: Partial<HostSettings> = {}\n for (const row of SETTINGS_TOGGLES) {\n if (row.requires && merged[row.key] === false && unenforced[row.key] !== false && patch[row.key] !== false)\n out[row.key] = false\n }\n return out\n }\n\n const writeSettings = (patch: Partial<HostSettings>, reset: readonly (keyof HostSettings)[] = []): HostSettings => {\n /*\n * Read-modify-write of the whole `state.json`, synchronous, through the\n * state store. A host in the window's process shares the window's store\n * (`config`), so the two writers interleave whole writes and each keeps\n * the other's fields. Across processes (the daemon and a local-mode\n * window on the same file) nothing locks; in daemon mode the window\n * leaves settings to the daemon and persists only its window-local\n * keys (`WINDOW_LOCAL_SETTINGS`: `useDaemon`, `remoteHosts`).\n */\n const state = config.stateStore.load()\n // Same invariants every writer applies (`orchestration` needs `useDaemon`,\n // …) — enforced on the MERGED view, since a patch can flip a requirement\n // off while the dependent stays true in the stored fields.\n const written = sparseSettingsUpdate(state.settings, patch, reset)\n const unenforced: HostSettings = { ...DEFAULT_SETTINGS, ...config.initialSettings, ...settingsFromStored(written) }\n const merged = enforceSettingsInvariants(unenforced)\n const next = sparseSettingsUpdate(written, pickInvariantFields(unenforced, merged, patch)) as Partial<HostSettings>\n config.stateStore.save({ ...state, settings: next })\n return merged\n }\n\n const userDataDir = (): string => config.paths.userDir\n\n const applyAuthEnv = (): void => {\n const dir = userDataDir()\n process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir)\n // The window's own registry when sharing its config (custom providers);\n // the daemon uses the built-ins.\n applyApiKeyEnv(dir, shared ? config.providers : BUILTIN_PROVIDERS)\n }\n\n // One bridge for every registry this daemon builds (the engine scopes the invoking session onto it per command), and the extension host's ports.\n const hostRuntime = shared ? undefined : createExtensionHostRuntimeBridge()\n const extensionRuntimes = hostRuntime && ownExtensionsHost(options, config, { readSettings, writeSettings, applyAuthEnv, hostRuntime, store })\n\n const base = {\n // The daemon serves explicitly-invoked clients (`zidane attach`)\n // even when `useDaemon` is off: a multi-writer surface by\n // construction, so the run guard + heartbeat are not setting-gated.\n // A shared host is single-writer unless told otherwise.\n multiProcess: shared ? shared.multiProcess === true : true,\n broadcast: (signal: HostSignal) => {\n // A deleted session's extension slot items go with it.\n if (signal.kind === 'sessions:changed' && signal.op === 'delete')\n extensionRuntimes?.removeSession(signal.sessionId)\n options.broadcast(signal)\n },\n store,\n readSettings,\n writeSettings,\n ...(config.stateStore.path ? { watchSettings: (onChange: () => void) => watchFileChanges(config.stateStore.path!, onChange) } : {}),\n userDataDir,\n stateDir: () => config.paths.stateDir,\n /*\n * The host's own log (a shared MCP server's output no session owns): the\n * daemon's stderr, its log file, plus the log sink. A host in the window's\n * process writes only to the sink: stderr there is the window's terminal.\n */\n ...(shared\n ? (options.logSink ? { logger: createLogger(options.logSink) } : {})\n : { logger: createLogger(options.logSink ? fanoutSink([options.logSink, consoleSink()]) : consoleSink()) }),\n applyAuthEnv,\n mcpCredentialStore: () => createFileMcpCredentialStore(userDataDir()),\n /*\n * The daemon persists parked approvals so a restart can re-offer them. A\n * host in the window's process dies with its runs, so it keeps them in\n * memory: the file is the daemon's (same state dir), not its to load or\n * clear.\n */\n approvalsPersistence: shared\n ? createMemoryApprovalsStore()\n : createFileApprovalsStore(join(dirname(config.paths.state), 'pending-approvals.json')),\n ...(options.debugStream !== undefined ? { debugStream: options.debugStream } : {}),\n config,\n }\n\n // The window's per-cwd config: no discovery of our own;\n // the window's registries own those.\n if (shared) {\n const { resolve, invalidate, forget } = shared.runtimeConfig\n return {\n ...base,\n // Session artifacts where the window's local agent kept them.\n cacheDir: () => config.paths.cacheDir,\n runtimeConfig: resolve,\n ...(shared.hostRuntime ? { hostRuntime: shared.hostRuntime } : {}),\n ...(shared.instrumentAgent ? { instrumentAgent: shared.instrumentAgent } : {}),\n ...(shared.terminals !== undefined ? { terminals: shared.terminals } : {}),\n invalidateRuntime: () => invalidate?.(),\n // Same contract as the daemon's: drop now, dispose when the returned\n // disposer runs (once no agent holds the old registries).\n forgetRuntime: () => forget?.() ?? (() => undefined),\n }\n }\n\n /*\n * Per-(cwd + allowlist + trust) runtime-config memo — same invalidation\n * axes the GUI's extension registry cache uses. Dropped wholesale on\n * settings writes that touch extension keys (see the server's\n * `settings.set` handler calling `invalidate`).\n */\n /*\n * LRU-bounded: a service-style daemon (`--idle-exit 0`) serving many\n * project folders would otherwise accumulate a full ResolvedConfig +\n * extension registry per (cwd × allowlist) key forever. Map iteration\n * order is insertion order; a cache hit re-inserts to mark recency.\n * A folder with a run in flight is never evicted (`runActiveIn`): the run\n * calls into its registry for as long as it lasts (a `/review` waits on\n * its workers for minutes without touching the cache), and a window\n * listing more folders than the cache holds would otherwise dispose it\n * under the run. The cache holds more than the cap until one is idle.\n */\n const RUNTIME_CACHE_MAX = 16\n const runtimeCache = new Map<string, Promise<ResolvedConfig>>()\n\n // `ctx.mcp.call`: one connection pool for every per-cwd runtime.\n const mcpHost = createExtensionMcpHost({\n prefix: config.prefix,\n readSettings,\n credentialStore: () => createFileMcpCredentialStore(userDataDir()),\n })\n extensionRuntimes?.bindMcp(mcpHost)\n\n const sink = options.logSink ? fanoutSink([options.logSink, consoleSink({ minLevel: 'warn' })]) : undefined\n /** Each cached registry's folder watch and config-sync attachment, closed with it. */\n const watches = new Map<Promise<ResolvedConfig>, { close: () => void } | undefined>()\n const configLog = createLogger(sink ?? consoleSink({ minLevel: 'warn' }))\n const configSync = options.extensionsConfigSync === false\n ? undefined\n : createExtensionsConfigSync({\n configDir: config.paths.configDir,\n prefix: config.prefix,\n log: (level, message) => configLog[level](message),\n watch: watchFileChanges,\n ...(options.extensionsConfigSync ?? {}),\n })\n\n /**\n * Best-effort release of an evicted entry's extension registry\n * (teardown hooks — `registry.dispose()` is idempotent).\n * Fire-and-forget: eviction must never block or throw on a broken\n * extension teardown, and a rejected resolve has nothing to release.\n */\n const disposeRuntime = (promise: Promise<ResolvedConfig>): void => {\n watches.get(promise)?.close()\n watches.delete(promise)\n void promise\n .then((config) => {\n extensionRuntimes?.release(config.extensions)\n return config.extensions.dispose()\n })\n .catch(() => undefined)\n }\n\n // Set by the dispatcher once its chat host exists; until then no run can be active.\n let runActiveIn: (cwd: string) => boolean = () => false\n const watchRegistry = registryWatcher({ prefix: config.prefix, cache: runtimeCache, dispose: disposeRuntime, broadcast: base.broadcast, runActiveIn: cwd => runActiveIn(cwd), ...(sink ? { sink } : {}), ...(options.watchExtensions !== undefined ? { watch: options.watchExtensions } : {}), ...(configSync ? { configSync } : {}) })\n\n const runtimeKey = (cwd: string, settings: HostSettings): string => [\n cwd,\n JSON.stringify(settings.enabledExtensions ?? null),\n String(settings.loadProjectExtensions === true),\n ].join('\\u0000')\n const cwdOfKey = (key: string): string => key.slice(0, key.indexOf('\\u0000'))\n\n const runtimeConfig = (cwd: string): Promise<ResolvedConfig> => {\n const settings = readSettings()\n const key = runtimeKey(cwd, settings)\n\n const existing = runtimeCache.get(key)\n if (existing) {\n // Refresh recency.\n runtimeCache.delete(key)\n runtimeCache.set(key, existing)\n return existing\n }\n\n const prepared = extensionRuntimes?.prepare({ cwd, ...(cwd ? { projectRoot: projectRootOf(cwd) } : {}) })\n // This build's promise, read by the build itself once it awaited (the `const` below is assigned by then).\n const self: { promise?: Promise<ResolvedConfig> } = {}\n const promise = self.promise = (async () => {\n // Folders config entries link in place and the ids they keep off, as the last reconcile left them.\n const declared = configSync\n ? configuredExtensions({ configDir: config.paths.configDir, ...(cwd ? { cwd } : {}), prefix: config.prefix }, { trustProject: settings.loadProjectExtensions === true })\n : undefined\n const extensionRegistry = await discoverAndBuildExtensionRegistry({\n cwd,\n hostRuntime,\n prefix: config.prefix,\n ...(declared ? { linkedExtensionDirs: declared.links, configDisabled: declared.disabled } : {}),\n ...(settings.enabledExtensions !== undefined ? { enabledAllowlist: [...settings.enabledExtensions] } : {}),\n trustProjectExtensions: settings.loadProjectExtensions === true,\n readSettings,\n ...(sink ? { sink } : {}),\n ...(prepared ? { runtime: prepared.runtime } : {}),\n })\n const resolved = resolveConfig({\n cwd,\n extensionRegistry,\n store: () => store,\n })\n // Evicted while building (more folders than the cache holds): disposed, not adopted. Adopting lists its\n // commands through `runtimeConfig(cwd)`, which would build it again and evict another, endlessly.\n if (runtimeCache.get(key) === self.promise)\n prepared?.adopt(extensionRegistry, resolved)\n return resolved\n })()\n // The folder watch starts once built, while this build is still the cached one.\n void promise.then(resolved => void (runtimeCache.get(key) === promise && watches.set(promise, watchRegistry(resolved.extensions, { key, promise, cwd, settings }))), () => undefined)\n\n runtimeCache.set(key, promise)\n while (runtimeCache.size > RUNTIME_CACHE_MAX) {\n const oldest = [...runtimeCache.keys()].find(other => other !== key && !runActiveIn(cwdOfKey(other)))\n if (oldest === undefined)\n break\n const evicted = runtimeCache.get(oldest)\n runtimeCache.delete(oldest)\n if (evicted)\n disposeRuntime(evicted)\n }\n promise.catch(() => {\n if (runtimeCache.get(key) === promise)\n runtimeCache.delete(key)\n })\n return promise\n }\n\n return {\n ...base,\n runtimeConfig,\n peekRuntimeConfig: cwd => runtimeCache.get(runtimeKey(cwd, readSettings())),\n gateExtensionReloads: (check) => {\n runActiveIn = check\n },\n ...(hostRuntime ? { hostRuntime } : {}),\n ...(extensionRuntimes ? { extensionRuntimes } : {}),\n ...(configSync ? { extensionsConfigSync: configSync } : {}),\n invalidateRuntime: () => {\n for (const entry of runtimeCache.values())\n disposeRuntime(entry)\n runtimeCache.clear()\n },\n forgetRuntime: () => {\n const dropped = [...runtimeCache.values()]\n runtimeCache.clear()\n return () => {\n for (const entry of dropped)\n disposeRuntime(entry)\n }\n },\n }\n}\n\n/** The daemon's own boot config: paths + store + state, from `cwd`. */\nasync function resolveOwnConfig(cwd: string | undefined): Promise<ResolvedConfig> {\n /*\n * `bun:sqlite` is loaded LAZILY so `zidane/ipc` stays importable under\n * plain Node (the Electron GUI main process imports this barrel for\n * `createChatHost`; the sqlite chunk must never be evaluated there).\n * Same invariant the tsdown config maintains for `zidane/session/sqlite`.\n */\n const { createTuiStore } = await import('../../session/sqlite')\n /*\n * Session-facing runtime config is re-resolved per cwd (project\n * extensions differ per folder); this one only carries paths, store, state.\n */\n return resolveConfig({\n ...(cwd !== undefined ? { cwd } : {}),\n store: resolved => createTuiStore(resolved.db),\n })\n}\n\n/** The extension host ports of a host that builds its own registries (`./extensions/host`). */\nfunction ownExtensionsHost(\n options: HostEnvironmentOptions,\n config: ResolvedConfig,\n deps: { readSettings: () => HostSettings, writeSettings: (patch: Partial<HostSettings>) => HostSettings, applyAuthEnv: () => void, hostRuntime: ExtensionHostRuntimeBridge, store: SessionStore },\n): DaemonExtensionsHost {\n return createDaemonExtensionsHost({\n kind: options.extensionsHost ?? 'daemon',\n dataDir: () => config.paths.userDir,\n configDir: () => config.paths.configDir,\n sessionMetadata: async sessionId => (await readSessionHeader(deps.store, sessionId))?.metadata,\n log: message => console.warn(message),\n prefix: config.prefix,\n readSettings: deps.readSettings,\n writeSettings: patch => void deps.writeSettings(patch),\n broadcast: options.broadcast,\n hostRuntime: deps.hostRuntime,\n applyAuthEnv: deps.applyAuthEnv,\n // `ctx.generate.image` saves: stored like a host-side write, with the same signal as `artifacts.upsert`.\n recordArtifact: async (artifact) => {\n if (deps.readSettings().artifacts === false || !deps.store.upsertArtifact)\n return\n const stored = await deps.store.upsertArtifact(artifact)\n if (stored)\n options.broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n },\n })\n}\n\n/** One cached registry {@link registryWatcher} watches. */\ninterface RegistryWatchTarget {\n /** Its cache key and build: an evicted build reloads nothing. */\n key: string\n promise: Promise<ResolvedConfig>\n cwd: string\n /** The settings it was built with (trust, allowlist). */\n settings: HostSettings\n}\n\n/**\n * Live reload of the daemon's cached registries, once no session reading\n * the folder's extensions has a run in flight (`runActiveIn`; a watch\n * option's `canReload` replaces it): a changed folder reloads\n * its extension only (`reloadChangedExtensions`); a folder that appears\n * loads when discovery would load it (trusted, not shadowed), with the\n * allowlist the registry was built for. With `configSync`, the registry\n * also follows the config files' `extensions` entries: each reconcile's\n * result is applied in place (`applyExtensionsConfigReport`), in the same\n * queue and under the same run check. Returns the starter; it answers\n * `undefined` when neither is on.\n */\nfunction registryWatcher(opts: {\n prefix: string\n /** The runtime-config cache, and how an entry is released. */\n cache: Map<string, Promise<ResolvedConfig>>\n dispose: (promise: Promise<ResolvedConfig>) => void\n broadcast: (signal: HostSignal) => void\n /** Whether a session reading `cwd`'s extensions has a run in flight: reloads wait for it. */\n runActiveIn: (cwd: string) => boolean\n sink?: LogSink\n watch?: boolean | ExtensionFolderWatchOptions\n configSync?: ExtensionsConfigSync\n}): (registry: ExtensionRegistry, target: RegistryWatchTarget) => { close: () => void } | undefined {\n return (registry, { key, promise, cwd, settings }) => {\n if (opts.watch === false && !opts.configSync)\n return undefined\n const current = (): boolean => opts.cache.get(key) === promise\n // No runtime to load a new folder into: drop the build, so the next session builds the folder again.\n const drop = (): void => {\n opts.cache.delete(key)\n opts.dispose(promise)\n opts.broadcast({ kind: 'catalog:changed', catalog: 'extensions' })\n }\n const scan = { cwd, prefix: opts.prefix, trustProjectExtensions: settings.loadProjectExtensions === true }\n const roots = (): { path: string, source: 'project' | 'user' }[] => defaultExtensionScanPaths({ cwd, prefix: opts.prefix })\n const targets = (): { dirs: string[], roots: string[] } => {\n const runtime = extensionRuntimeOf(registry)\n const dirs = new Set<string>()\n for (const info of runtime?.extensions() ?? []) {\n const dir = runtime!.get(info.id)?.entry.dir\n if (dir)\n dirs.add(dir)\n }\n for (const entry of registry.inactive) {\n if (entry.dir)\n dirs.add(entry.dir)\n }\n return { dirs: [...dirs], roots: roots().map(root => root.path) }\n }\n const allowed = (id: string): boolean => settings.enabledExtensions === undefined || settings.enabledExtensions.includes(id)\n const classify = (dir: string): { source: 'project' | 'user', enabled: boolean } | undefined => {\n const root = roots().find(r => r.path === dirname(dir))\n if (!root || !loadableExtensionDirs(scan).includes(dir))\n return undefined\n return { source: root.source, enabled: allowed(basename(dir)) }\n }\n const watchOptions = typeof opts.watch === 'object' ? opts.watch : {}\n let queue: Promise<void> = Promise.resolve()\n // A reload swaps the code sessions run on: inside the queue, wait for the folder's runs (one may have started while this waited).\n const settled = async (): Promise<boolean> => {\n while (opts.runActiveIn(cwd) && current())\n await new Promise(resolve => setTimeout(resolve, watchOptions.retryMs ?? 1000))\n return current()\n }\n const enqueue = (work: () => Promise<void>): Promise<void> => {\n queue = queue.then(async () => {\n if (current())\n await work()\n }).catch(() => undefined)\n return queue\n }\n const watch = opts.watch === false\n ? undefined\n : watchExtensionFolders((dirs) => {\n void enqueue(async () => {\n if (!await settled())\n return\n const result = await reloadChangedExtensions(registry, dirs, { classify, ...(opts.sink ? { sink: opts.sink } : {}) })\n if (result.needsRebuild)\n return drop()\n watch?.sync(targets())\n })\n }, { canReload: () => !opts.runActiveIn(cwd), ...watchOptions })\n watch?.sync(targets())\n const detach = opts.configSync?.attach({\n cwd,\n trustProject: () => settings.loadProjectExtensions === true,\n apply: report => enqueue(async () => {\n if (!await settled())\n return\n const result = await applyExtensionsConfigReport(registry, report, { classify, allowed, ...(opts.sink ? { sink: opts.sink } : {}) })\n if (result.needsRebuild)\n return drop()\n watch?.sync(targets())\n // Failure rows changed the listed entries even when no status did.\n opts.broadcast({ kind: 'extensions:entries', cwd })\n // A replay to a registry just built changed nothing installed: announcing it to every\n // folder makes clients list them all again, building more folders than the cache holds.\n if (!report.replay || result.loaded.length + result.reloaded.length + result.unloaded.length > 0)\n opts.broadcast({ kind: 'catalog:changed', catalog: 'extensions' })\n }),\n })\n return {\n close: () => {\n watch?.close()\n detach?.()\n },\n }\n }\n}\n","/**\n * A local host's machine links for its clients (`machines.share.*`,\n * `machines.useServer`, `machines.links.status`; `docs/MACHINES.md` § Client\n * UI). Opt-in down to the module graph: the controller (`../../machine/links`,\n * which dials servers) is imported only while remote hosts are on, so with\n * the setting off nothing is loaded, no token read, nothing dialed. Turning\n * remote hosts off stops every link (the wanted links stay saved).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineLinksStatus } from '../../../chat/machine-protocol'\nimport type { MachineLinks } from '../../machine/links'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { remoteHostsGate } from '../../../chat/feature-gate'\nimport { InvalidParamsError } from './params'\n\nconst GATE_POLL_MS = 2000\nconst EMPTY: MachineLinksStatus = { shares: [], uses: [] }\n\n/** Options for {@link createMachineLinkHandlers}: the host, settings access and the signal sink. */\nexport interface MachineLinksHandlerOptions {\n /** The chat host whose machine registry the links feed. */\n host: ChatHost\n /** Environment accessors for reading settings and locating the user data directory. */\n env: Pick<DaemonEnvironment, 'readSettings' | 'userDataDir'>\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Id of this host, when it has one. */\n hostId: string | undefined\n /** A zidane-server: it has no links (a server is shared from, never shares from here); every method is refused. */\n server?: boolean\n /** zidane version reported when dialing a server. */\n appVersion: string\n /** Connection pacing for the links (tests shrink it). */\n pacing?: { minDelayMs?: number, maxDelayMs?: number, heartbeatMs?: number, pollMs?: number }\n}\n\ntype Methods = 'machines.share.start' | 'machines.share.stop' | 'machines.useServer' | 'machines.links.status'\n\n/** A server's: no links, nothing loaded or resumed. */\nfunction serverLinkHandlers(): Handlers<Methods> {\n const refuse = (): never => {\n throw new Error('A zidane-server has no machine links: share a computer with it from that computer (zidane machine share, or its Hosts page).')\n }\n return { 'machines.share.start': refuse, 'machines.share.stop': refuse, 'machines.useServer': refuse, 'machines.links.status': refuse }\n}\n\n/**\n * Builds the `machines.share.*`, `machines.useServer` and `machines.links.status` handlers.\n * The links load lazily and only while remote hosts are enabled. On a zidane-server every method throws. Turning remote hosts off stops every link.\n * @param options - Host, environment, broadcast sink and pacing.\n * @returns The four method handlers.\n */\nexport function createMachineLinkHandlers(options: MachineLinksHandlerOptions): Handlers<Methods> {\n if (options.server)\n return serverLinkHandlers()\n const { host, env, broadcast } = options\n let links: Promise<MachineLinks> | undefined\n let gateTimer: ReturnType<typeof setInterval> | undefined\n\n const gateOn = (): boolean => remoteHostsGate.isEnabled(env.readSettings())\n\n const stop = (): void => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n gateTimer = undefined\n void current?.then(l => l.close()).catch(() => undefined)\n broadcast({ kind: 'machine:links', links: EMPTY })\n }\n\n const load = (): Promise<MachineLinks> => {\n links ??= import('../../machine/links').then(({ startMachineLinks }) => startMachineLinks({\n dataDir: env.userDataDir(),\n machines: host.machines,\n hostId: options.hostId,\n appVersion: options.appVersion,\n settings: () => env.readSettings(),\n onChange: status => broadcast({ kind: 'machine:links', links: status }),\n ...options.pacing,\n }))\n // Remote hosts turned off (here or in another window): every link stops.\n gateTimer ??= setInterval(() => {\n if (!gateOn())\n stop()\n }, options.pacing?.pollMs ?? GATE_POLL_MS)\n gateTimer.unref?.()\n return links\n }\n\n const required = (): Promise<MachineLinks> => {\n if (!gateOn())\n throw new Error(`Remote hosts are off${remoteHostsGate.isKilled() ? ` (${remoteHostsGate.killSwitchEnv}=1)` : ''}: machines are part of them.`)\n return load()\n }\n\n const str = (value: unknown, name: string): string => {\n if (typeof value !== 'string' || value === '')\n throw new InvalidParamsError(`\"${name}\" must be a non-empty string.`)\n return value\n }\n\n // Links saved by an earlier run resume with the host, only while remote hosts are on.\n if (gateOn() && existsSync(join(env.userDataDir(), 'machine-links.json')))\n void load().catch(() => undefined)\n host.machines.onClose(() => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n void current?.then(l => l.close()).catch(() => undefined)\n })\n\n return {\n 'machines.share.start': async (p) => {\n if (!Array.isArray(p.roots))\n throw new InvalidParamsError('\"roots\" must be a list of folders.')\n // A confined host lends only its own workspace (local hosts are not confined).\n if (host.workspace.confined) {\n for (const root of p.roots)\n host.workspace.resolveFolder(String(root))\n }\n return (await required()).startShare({ hostId: str(p.hostId, 'hostId'), name: str(p.name, 'name'), roots: p.roots, ...(typeof p.token === 'string' ? { token: p.token } : {}) })\n },\n 'machines.share.stop': async p => (await required()).stopShare(str(p.hostId, 'hostId')),\n 'machines.useServer': async (p) => {\n if (typeof p.enabled !== 'boolean')\n throw new InvalidParamsError('\"enabled\" must be a boolean.')\n return (await required()).setUse(str(p.hostId, 'hostId'), p.enabled)\n },\n 'machines.links.status': async () => (gateOn() ? (await load()).status() : EMPTY),\n }\n}\n","/** Machines this host knows, for clients (`docs/MACHINES.md`): list them, forget one, browse one's folders. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { posix } from 'node:path'\nimport { insideDeclaredRoots } from '../../../chat/host/machines'\nimport { InvalidParamsError } from './params'\n\n/** Folders listed per call at most. */\nconst MAX_DIRS = 2000\n\n/**\n * Builds the `machines.list`, `machines.forget` and `machines.listDirs` handlers.\n * `machines.forget` broadcasts a `machine:status` signal with the machine offline when it removed one. `machines.listDirs` is confined to the machine's declared roots and throws for a path outside them.\n * @param options - The chat host and the signal broadcast sink.\n * @returns The three method handlers.\n */\nexport function createMachineHandlers({ host, broadcast }: { host: ChatHost, broadcast: (signal: HostSignal) => void }): Handlers<'machines.list' | 'machines.forget' | 'machines.listDirs'> {\n return {\n 'machines.list': () => host.machines.list(),\n 'machines.forget': (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.forget: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const forgotten = host.machines.forget(p.machineId)\n if (forgotten && machine)\n broadcast({ kind: 'machine:status', machineId: machine.id, name: machine.name, status: 'offline' })\n return { forgotten }\n },\n 'machines.listDirs': async (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.listDirs: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const link = host.machines.link(p.machineId)\n if (!machine || !link)\n throw new Error(`Unknown machine \"${p.machineId}\".`)\n const roots = machine.roots.map(root => root.path)\n // No path: the first root.\n const asked = p.path === undefined || p.path === '' ? roots[0]! : p.path\n if (typeof asked !== 'string' || !insideDeclaredRoots(machine.roots, asked))\n throw new Error(`${String(asked)} is outside ${machine.name}'s roots.`)\n const path = posix.normalize(asked)\n const root = roots.find(r => insideDeclaredRoots([{ path: r }], path))!\n // The machine confines the listing again on its filesystem (real paths); never waits for an offline one.\n const { entries } = await link.call('fs.list', { handle: { id: 'host-list-dirs', cwd: root }, path }, { wait: false })\n const dirs = entries\n .map(entry => (typeof entry === 'string' ? entry : entry.path))\n .filter(name => name.endsWith('/'))\n .map(name => posix.join(path, name.slice(0, -1)))\n .sort()\n .slice(0, MAX_DIRS)\n return { path, dirs, roots }\n },\n }\n}\n","/**\n * The host side of one JSON-RPC connection, for every wire transport (the\n * unix socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`):\n * a dispatcher {@link HostPeer} whose signals go out as `ipc.signal`\n * notifications, and the request / notification handlers that hand incoming\n * messages to the dispatcher. Framing and the write-backpressure bound\n * (`./send-budget`) stay with the transport.\n *\n * A signal is serialized once per fan-out, not once per peer: the first peer\n * builds the notification text from the signal's JSON and every other peer\n * of the fan-out sends the same string ({@link signalFrame}).\n */\nimport type { JsonRpcConnectionOptions } from '../../acp/json-rpc'\nimport type { AcpPeer, JsonRpcMessage, JsonRpcRequest, JsonRpcResponse } from '../../acp/types'\nimport type { HostDispatcher, HostPeer } from '../daemon/dispatcher'\nimport type { HostSignal } from '../protocol'\nimport { errorResponse, successResponse } from '../../acp/json-rpc'\nimport { SIGNAL_SEQ_FIELD } from '../protocol'\n\n/**\n * Per-peer write backpressure bound. A wedged peer (e.g. a SIGSTOP'd\n * terminal) stops reading, so fan-out writes pile up in the transport's\n * send buffer without bound and can OOM the host. A peer buffering more\n * than this is dropped: the protocol supports re-attach + backfill, so\n * killing a wedged peer is safe and self-healing.\n */\nexport const PEER_WRITE_HIGH_WATERMARK = 8 * 1024 * 1024\n\nexport interface RpcPeerOptions {\n /** The connection's JSON-RPC side; signals are dropped until it exists. */\n rpc: () => (Pick<AcpPeer, 'sendNotification'> & { sendSerialized?: (json: string, message: JsonRpcMessage) => void }) | undefined\n}\n\n/** What the send budget sees of a pre-serialized signal: a notification, never a reply. */\nconst SIGNAL_MESSAGE: JsonRpcMessage = { jsonrpc: '2.0', method: 'ipc.signal' }\n\n/**\n * The `ipc.signal` notification text for a signal whose JSON is `json`,\n * byte for byte what serializing `{ jsonrpc, method, params: { ...signal,\n * [SIGNAL_SEQ_FIELD]: seq } }` gives; `undefined` when splicing could not\n * promise that (an empty or non-object JSON, a signal that has the field).\n */\nexport function signalFrame(signal: HostSignal, json: string, seq: number | undefined): string | undefined {\n if (seq === undefined)\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json}}`\n if (json.length <= 2 || json[0] !== '{' || !json.endsWith('}') || Object.hasOwn(signal, SIGNAL_SEQ_FIELD))\n return undefined\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json.slice(0, -1)},\"${SIGNAL_SEQ_FIELD}\":${seq}}}`\n}\n\nexport function createRpcPeer(options: RpcPeerOptions): HostPeer {\n return {\n ready: false,\n watching: null,\n send(signal, seq, encoded) {\n try {\n const rpc = options.rpc()\n if (!rpc)\n return\n if (encoded && rpc.sendSerialized) {\n const json = encoded.json()\n if (json === undefined)\n return // Not JSON-able: no peer can receive it.\n encoded.frame ??= signalFrame(signal, json, seq)\n if (encoded.frame !== undefined) {\n rpc.sendSerialized(encoded.frame, SIGNAL_MESSAGE)\n return\n }\n }\n rpc.sendNotification('ipc.signal', seq === undefined ? signal : { ...signal, [SIGNAL_SEQ_FIELD]: seq })\n }\n catch {\n // A dying connection (or a signal JSON can't encode) must never take the host down with it.\n }\n },\n }\n}\n\n/** The JSON-RPC handlers that route one peer's requests and notifications to the dispatcher. */\nexport function dispatcherHandlers(dispatcher: HostDispatcher, peer: HostPeer): Pick<JsonRpcConnectionOptions, 'onRequest' | 'onNotification'> {\n return {\n onRequest: async (message: JsonRpcRequest): Promise<JsonRpcResponse> => {\n const outcome = await dispatcher.handleRequest(message.method, message.params, peer)\n return outcome.ok\n ? successResponse(message.id, outcome.result)\n : errorResponse(message.id, outcome.code, outcome.message, outcome.data)\n },\n onNotification: message => dispatcher.handleNotification(message.method, message.params, peer),\n }\n}\n","/**\n * One connection's outgoing budget, for every wire transport (the unix\n * socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`).\n *\n * The slow-consumer bound is about pushed signals piling up for a peer that\n * stopped reading, not about one big reply it asked for: reply bytes still\n * queued are set aside (`replyReserve`) when the backlog is measured. The\n * buffer drains in order, so the reserve can only shrink to what is still\n * buffered; a peer that never reads keeps it whole and is dropped once the\n * signals behind it pass the bound. A reply itself is bounded by the message\n * size (over it, an `IpcErrorCode.ResponseTooLarge` error goes instead and\n * the connection stays), and the whole buffer by a hard cap for memory.\n *\n * The reserve is an approximation: it assumes the buffer drains oldest\n * first and only clamps it to what is still buffered, so after a partial\n * drain it may still count reply bytes that already left, and the signals\n * backlog reads low by at most that much. The memory bound, precisely: a\n * reply leaves the whole buffer at most `H = maxBuffered + 2 × maxMessage`\n * (checked after its write), and every signal re-clamps the reserve to what\n * is buffered, so the reserve never exceeds what the buffer held at the\n * first signal after the last reply (at most `H` plus that signal). A\n * signal leaves the measured backlog at most `maxBuffered`, so between\n * sends a peer holds at most `maxBuffered + H = 2 × maxBuffered + 2 ×\n * maxMessage` bytes (plus one signal). The write that crosses a bound is\n * the last: the peer is marked stuck and nothing more goes out. That is the\n * only backlog check: the buffer grows through `send`, so a backlog\n * over the bound is always seen by the write that made it.\n */\nimport type { JsonRpcMessage } from '../../acp/types'\nimport { Buffer } from 'node:buffer'\nimport { errorResponse } from '../../acp/json-rpc'\nimport { IpcErrorCode } from '../protocol'\n\n/** What the budget writes to: the transport's buffer and its framing. */\nexport interface SendTarget {\n /** Bytes written but not yet handed to the OS. */\n buffered: () => number\n /** Write one serialized message (the target frames it); `false`: the transport dropped it. */\n write: (json: string) => boolean\n}\n\nexport interface SendLimits {\n /** Signals backlog past which the peer is stuck (replies set aside). */\n maxBuffered: number\n /** Largest reply; a bigger one is answered with `ResponseTooLarge`. */\n maxMessage: number\n /** The peer cannot keep up: tear it down (called once). */\n stuck: (why: string) => void\n log: (line: string) => void\n /** Log prefix, e.g. `[ipc-ws]`. */\n label: string\n}\n\nexport interface PeerSend {\n /** Bytes buffered that are not reply bytes: what the slow-consumer bound measures. */\n backlog: () => number\n /** Send one message (the JSON-RPC endpoint's `send`): replies and the rest apart. */\n send: (json: string, message: JsonRpcMessage) => void\n /** Give up on the peer (once): {@link SendLimits.stuck} runs and nothing more goes out. */\n markStuck: (why: string) => void\n}\n\nfunction isReply(message: JsonRpcMessage): boolean {\n return 'id' in message && message.id !== undefined && message.id !== null && ('result' in message || 'error' in message)\n}\n\nexport function createPeerSend(target: SendTarget, limits: SendLimits): PeerSend {\n const { maxBuffered, maxMessage, log, label } = limits\n let replyReserve = 0\n let stuck = false\n const markStuck = (why: string): void => {\n if (stuck)\n return\n stuck = true\n limits.stuck(why)\n }\n const backlog = (): number => {\n const buffered = target.buffered()\n replyReserve = Math.min(replyReserve, buffered)\n return buffered - replyReserve\n }\n const send = (json: string, message: JsonRpcMessage): void => {\n if (stuck)\n return\n if (!isReply(message)) {\n if (!target.write(json) || backlog() > maxBuffered)\n markStuck(`more than ${maxBuffered} bytes of signals unsent`)\n return\n }\n let text = json\n let bytes = Buffer.byteLength(text)\n if (bytes > maxMessage) {\n const id = (message as { id: string | number }).id\n log(`${label} reply to ${String(id)} is ${bytes} bytes (> ${maxMessage}): answering with an error instead`)\n text = JSON.stringify(errorResponse(id, IpcErrorCode.ResponseTooLarge, `The reply is over ${maxMessage} bytes: ask for less (a transcript: a smaller page).`, { bytes, maxBytes: maxMessage }))\n bytes = Buffer.byteLength(text)\n }\n if (!target.write(text)) {\n markStuck('reply dropped by the transport')\n return\n }\n replyReserve += bytes\n if (target.buffered() > maxBuffered + 2 * maxMessage)\n markStuck(`more than ${maxBuffered + 2 * maxMessage} bytes unsent`)\n }\n return { backlog, send, markStuck }\n}\n","/**\n * The calling side of a worker RPC: request ids, a pending map, a timeout\n * per request, and crash recovery. A worker that crashes rejects what is\n * pending and is spawned again on the next use, after a backoff that doubles\n * up to a cap. A worker that cannot start (the factory throws, or it dies\n * before it said ready) or that crashes `maxCrashes` times in a row puts the\n * client in degraded mode: every request then rejects at once with a\n * {@link WorkerUnavailableError}, the caller's signal to do the work on its\n * own thread.\n *\n * Runtime-neutral: the factory returns a Bun / Web `Worker` or a Node\n * `worker_threads.Worker` ({@link WorkerLike}). The worker side is\n * `serveWorkerRpc` (`./rpc-serve.ts`); the wire is {@link WorkerCall} out,\n * {@link WorkerMessage} back.\n */\n\n/** A worker from either runtime: Bun / Web `Worker` (`addEventListener`) or Node `worker_threads.Worker` (`on`). */\nexport interface WorkerLike {\n /** Sends a {@link WorkerCall} to the worker. */\n postMessage: (message: unknown) => void\n /** Ends the worker. */\n terminate: () => unknown\n /** Lets the worker keep the process alive (while a reply is due). */\n ref?: () => void\n /** Stops the worker from keeping the process alive. */\n unref?: () => void\n /** Node's events: `message`, `error`, `exit`. */\n on?: (event: string, listener: (value: unknown) => void) => unknown\n /** Bun / Web events: `message`, `error`, `close`. */\n addEventListener?: (type: string, listener: (event: unknown) => void) => void\n}\n\n/** What the client posts: `init` once per spawn, then requests (`id` absent: a notification, no reply). */\nexport type WorkerCall = { init: unknown } | { id?: number, request: unknown }\n\n/** What the worker posts back: a request's answer, or an `event` it sends unasked. */\nexport type WorkerMessage\n = | { ready: true }\n | { fatal: string }\n | { event: unknown }\n | { id: number, ok: true, result: unknown }\n | { id: number, ok: false, error: { name: string, message: string } }\n\n/** No worker served the request: do the work on this thread. `degraded`: none will until the client is recreated. */\nexport class WorkerUnavailableError extends Error {\n /**\n * @param message - Why no worker served.\n * @param degraded - No worker will serve until the client is recreated.\n */\n constructor(message: string, readonly degraded: boolean) {\n super(message)\n this.name = 'WorkerUnavailableError'\n }\n}\n\n/** The worker's handler threw: `remoteName` and `message` are the thrown error's. */\nexport class WorkerRequestError extends Error {\n /**\n * @param remoteName - The thrown error's `name`.\n * @param message - The thrown error's `message`.\n */\n constructor(readonly remoteName: string, message: string) {\n super(message)\n this.name = 'WorkerRequestError'\n }\n}\n\n/** How {@link createWorkerRpcClient} spawns and supervises its worker. */\nexport interface WorkerRpcClientOptions {\n /** Spawns the worker. A throw puts the client in degraded mode. */\n create: () => WorkerLike\n /** Posted to every worker this client spawns, before any request (`serveWorkerRpc`'s `init`). */\n init?: unknown\n /** A request unanswered this long rejects, and the worker counts as crashed. Default 30 s. */\n timeoutMs?: number\n /** Crashes in a row before degraded mode. Default 3. */\n maxCrashes?: number\n /** Wait before spawning again after a crash: `base` doubled per crash in a row, at most `max`. Default 250 ms / 10 s. */\n backoffMs?: { base: number, max: number }\n /** What the worker is called in the errors it causes (`<name> unavailable: …`). Default `worker`. */\n name?: string\n /** Called once, with the reason, when the client goes degraded: from then on the caller does the work on its own thread. */\n onDegraded?: (reason: string) => void\n /** Each event the worker sends unasked (`emit` in `serveWorkerRpc`). */\n onEvent?: (event: unknown) => void\n}\n\n/** The calling side of a worker RPC, from {@link createWorkerRpcClient}. */\nexport interface WorkerRpcClient<Req, Res> {\n /** Spawns the worker when none runs. Rejects {@link WorkerUnavailableError} when no worker can serve, {@link WorkerRequestError} when the handler threw. */\n request: (request: Req, options?: { timeoutMs?: number }) => Promise<Res>\n /** Fire-and-forget, only to a running worker (none: nothing to tell). */\n notify: (request: Req) => void\n /** True once no worker will serve (it could not start, or crashed `maxCrashes` times in a row). */\n isDegraded: () => boolean\n /** Terminates the worker and rejects what is pending; later requests reject. Idempotent. */\n close: () => void\n}\n\ninterface Pending {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/** Subscribes to a worker's messages, errors and exit, whichever event API it has. */\nfunction listen(worker: WorkerLike, on: { message: (data: unknown) => void, failed: (reason: string) => void }): void {\n if (typeof worker.on === 'function') {\n worker.on('message', data => on.message(data))\n worker.on('error', err => on.failed(err instanceof Error ? err.message : String(err)))\n worker.on('exit', code => on.failed(`exited with code ${String(code)}`))\n return\n }\n worker.addEventListener?.('message', event => on.message((event as MessageEvent).data))\n worker.addEventListener?.('error', event => on.failed((event as ErrorEvent).message || 'worker error'))\n // Bun's `close`: the worker exited.\n worker.addEventListener?.('close', event => on.failed(`exited with code ${(event as { code?: number }).code ?? '?'}`))\n}\n\n/**\n * A worker RPC client. The worker spawns on the first request.\n * @param options - How to spawn the worker, its `init`, the timeout and the crash policy.\n */\nexport function createWorkerRpcClient<Req, Res>(options: WorkerRpcClientOptions): WorkerRpcClient<Req, Res> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const maxCrashes = options.maxCrashes ?? 3\n const backoff = options.backoffMs ?? { base: 250, max: 10_000 }\n const name = options.name ?? 'worker'\n const pending = new Map<number, Pending>()\n let nextId = 1\n let worker: WorkerLike | null = null\n let ready = false\n let crashes = 0\n let retryAt = 0\n let degraded: string | null = null\n let closed = false\n\n function degrade(reason: string): string {\n degraded = reason\n options.onDegraded?.(reason)\n return reason\n }\n\n function settleAll(reason: string): void {\n const error = new WorkerUnavailableError(reason, degraded !== null || closed)\n for (const [id, entry] of pending) {\n clearTimeout(entry.timer)\n pending.delete(id)\n entry.reject(error)\n }\n }\n\n /** The current worker is gone: a spawn failure degrades, a crash backs off. */\n function fail(failed: WorkerLike, reason: string): void {\n if (failed !== worker)\n return\n const wasReady = ready\n worker = null\n ready = false\n try {\n void failed.terminate()\n }\n catch {\n // Already gone.\n }\n crashes++\n if (!wasReady || crashes >= maxCrashes)\n degrade(`${name} unavailable: ${wasReady ? `${crashes} crashes in a row` : 'it did not start'} (${reason})`)\n retryAt = Date.now() + Math.min(backoff.base * 2 ** (crashes - 1), backoff.max)\n settleAll(degraded ?? `worker crashed: ${reason}`)\n }\n\n function onMessage(from: WorkerLike, data: unknown): void {\n if (from !== worker || typeof data !== 'object' || data === null)\n return\n const message = data as WorkerMessage\n if ('ready' in message) {\n ready = true\n return\n }\n if ('fatal' in message) {\n ready = false\n fail(from, message.fatal)\n return\n }\n if ('event' in message) {\n options.onEvent?.(message.event)\n return\n }\n const entry = pending.get(message.id)\n if (!entry)\n return\n pending.delete(message.id)\n clearTimeout(entry.timer)\n crashes = 0\n if (pending.size === 0)\n from.unref?.()\n if (message.ok)\n entry.resolve(message.result)\n else\n entry.reject(new WorkerRequestError(message.error.name, message.error.message))\n }\n\n function ensureWorker(): WorkerLike {\n if (closed)\n throw new WorkerUnavailableError('worker client closed', true)\n if (degraded !== null)\n throw new WorkerUnavailableError(degraded, true)\n if (worker)\n return worker\n if (Date.now() < retryAt)\n throw new WorkerUnavailableError('worker restarting after a crash', false)\n let spawned: WorkerLike\n try {\n spawned = options.create()\n }\n catch (err) {\n throw new WorkerUnavailableError(degrade(`${name} unavailable: ${err instanceof Error ? err.message : String(err)}`), true)\n }\n worker = spawned\n listen(spawned, { message: data => onMessage(spawned, data), failed: reason => fail(spawned, reason) })\n // Idle, it must not keep the process alive; `request` refs it while a reply is due.\n spawned.unref?.()\n spawned.postMessage({ init: options.init } satisfies WorkerCall)\n return spawned\n }\n\n return {\n request(request, requestOptions = {}) {\n return new Promise<Res>((resolve, reject) => {\n let target: WorkerLike\n try {\n target = ensureWorker()\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n const id = nextId++\n const wait = requestOptions.timeoutMs ?? timeoutMs\n const timer = setTimeout(fail, wait, target, `no reply in ${wait} ms`)\n pending.set(id, { resolve: resolve as (value: unknown) => void, reject, timer })\n target.ref?.()\n try {\n target.postMessage({ id, request } satisfies WorkerCall)\n }\n catch (err) {\n // Not cloneable: this request only, the worker is fine.\n pending.delete(id)\n clearTimeout(timer)\n if (pending.size === 0)\n target.unref?.()\n reject(new WorkerUnavailableError(`could not post the request: ${err instanceof Error ? err.message : String(err)}`, false))\n }\n })\n },\n notify(request) {\n try {\n worker?.postMessage({ request } satisfies WorkerCall)\n }\n catch {\n // A worker going away takes its state with it.\n }\n },\n isDegraded: () => degraded !== null,\n close() {\n if (closed)\n return\n closed = true\n const current = worker\n worker = null\n settleAll('worker client closed')\n try {\n void current?.terminate()\n }\n catch {\n // Already gone.\n }\n },\n }\n}\n","/**\n * `sessions.loadEvents` pages served off the host's thread. A whole-session\n * replay (load every turn, replay them all) takes tens to hundreds of\n * milliseconds on a long session; on the host's event loop that stalls the\n * TUI in local mode, and every session's streaming on a daemon or a\n * zidane-server. The history worker (`./worker.ts`) runs the same replay\n * cache against its own read-only connection to the sessions database, so\n * pages are identical to the in-thread ones (same versioning by `getMeta`,\n * same bounds); only the thread differs.\n *\n * The pager falls back to the in-thread cache whenever the worker cannot\n * serve: a store that is not a SQLite file, `ZIDANE_NO_HISTORY_WORKER=1`,\n * a worker that cannot start or keeps crashing (degraded), or one request it\n * lost (a crash, a timeout).\n *\n * The worker also scans the usage summary's day buckets (`usage.summary`),\n * a read of every turn; without it, the scan runs here on a read-only\n * connection of its own.\n */\nimport type { SessionStore } from '../../session/index'\nimport type { SqliteStoreFile } from '../../session/sqlite-store'\nimport type { UsageBuckets } from '../../session/sqlite-usage'\nimport type { TranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport type { HostSignal, LoadEventsPaging, SessionEventsPage } from '../protocol'\nimport type { WorkerLike, WorkerRpcClientOptions } from './rpc-client'\nimport { sqliteStoreFile } from '../../session/sqlite-store'\nimport { runUsageAggregates } from '../../session/sqlite-usage'\nimport { InvalidParamsError } from '../daemon/handlers/params'\nimport { changedSessionOf, createTranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport { openReadonlySqlite } from './readonly-db'\nimport { createWorkerRpcClient, WorkerRequestError, WorkerUnavailableError } from './rpc-client'\n\n/** Kill switch: `1` pages on the host's thread, with no worker. */\nexport const HISTORY_WORKER_KILL_SWITCH = 'ZIDANE_NO_HISTORY_WORKER'\n\n/** What `./worker.ts` takes as `init`. */\nexport interface HistoryWorkerInit {\n /** The sessions database, opened read-only by the worker. */\n dbPath: string\n}\n\n/** The history worker's requests. */\nexport type HistoryWorkerRequest\n = | { op: 'page', sessionId: string, paging: LoadEventsPaging }\n /** `live`: a run of the session appended to it here, so the next read may build on the last one. */\n | { op: 'drop', sessionId: string, live?: boolean }\n | { op: 'usage' }\n\n/**\n * The history worker's module: the sibling source file in development, the\n * sibling `history-worker.js` entry in the published dist, and the entry\n * embedded under the binary's root in a compiled executable\n * (`scripts/build-executables.ts`, `scripts/build-server.ts`).\n */\nexport function historyWorkerUrl(): URL {\n if (typeof Bun !== 'undefined' && (Bun as unknown as { isStandaloneExecutable?: boolean }).isStandaloneExecutable)\n return new URL('./src/ipc/history/worker.ts', import.meta.url)\n return new URL(import.meta.url.endsWith('.ts') ? './worker.ts' : './history-worker.js', import.meta.url)\n}\n\n/** A Bun / Web `Worker` on the history worker module. */\nfunction spawnHistoryWorker(): WorkerLike {\n return new Worker(historyWorkerUrl().href, { type: 'module' })\n}\n\n/** A client of the history worker, from {@link createTranscriptHistoryWorker}. */\nexport interface TranscriptHistoryWorker {\n /**\n * One `sessions.loadEvents` page, from the worker. Rejects\n * {@link WorkerUnavailableError} when the worker could not serve it (page\n * in-thread then), {@link InvalidParamsError} for bad paging, and the\n * worker's error otherwise (an unknown session).\n */\n page: (sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** The session changed or went away: the worker forgets its replay. `live`: a run here appended to it. */\n drop: (sessionId: string, live?: boolean) => void\n /** The usage summary's day buckets (`runUsageAggregates`). Rejects {@link WorkerUnavailableError} when the worker could not serve them. */\n usage: () => Promise<UsageBuckets>\n /** True once the worker will not serve again (it could not start, or keeps crashing). */\n isDegraded: () => boolean\n /** Terminates the worker; later pages reject {@link WorkerUnavailableError}. */\n close: () => void\n}\n\n/**\n * A client of the history worker over `dbPath`. The worker spawns on the\n * first page.\n * @param options - The database, and (tests, a Node host) how to spawn the worker.\n */\nexport function createTranscriptHistoryWorker(options: {\n dbPath: string\n /** Default: a Bun / Web `Worker` on {@link historyWorkerUrl}. */\n create?: () => WorkerLike\n} & Pick<WorkerRpcClientOptions, 'timeoutMs' | 'maxCrashes' | 'backoffMs' | 'onDegraded'>): TranscriptHistoryWorker {\n const { dbPath, create = spawnHistoryWorker, ...rest } = options\n const client = createWorkerRpcClient<HistoryWorkerRequest, unknown>({ name: 'history worker', create, init: { dbPath } satisfies HistoryWorkerInit, ...rest })\n return {\n async page(sessionId, paging) {\n try {\n return await client.request({ op: 'page', sessionId, paging }) as SessionEventsPage\n }\n catch (err) {\n if (err instanceof WorkerRequestError)\n throw err.remoteName === 'InvalidParamsError' ? new InvalidParamsError(err.message) : new Error(err.message)\n throw err\n }\n },\n drop: (sessionId, live) => client.notify({ op: 'drop', sessionId, ...(live ? { live } : {}) }),\n usage: async () => await client.request({ op: 'usage' }) as UsageBuckets,\n isDegraded: client.isDegraded,\n close: client.close,\n }\n}\n\n/** Where a host's paged `sessions.loadEvents` are served: the history worker when it can, else the in-thread cache. */\nexport interface HostTranscriptPager {\n /** The in-thread cache: the fallback pages, and the host's other whole-session reads (`document`). */\n replays: TranscriptReplayCache\n /** One page of a session of `store` (the worker serves it when `store` is a SQLite file). */\n page: (store: SessionStore, sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** A host signal: one that follows a change to a session drops its replay, here and in the worker. */\n observe: (signal: HostSignal) => void\n /** The session is gone: forget it here and in the worker. */\n forget: (sessionId: string) => void\n /** The usage summary's day buckets of `store`; `null` for a store that is not a SQLite file (it keeps no usage to scan). */\n usage: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Terminates the worker (the host is shutting down); later pages are served in-thread. */\n close: () => void\n}\n\n/**\n * Signals of a run's turns being saved: the worker's next read of the\n * session builds on its last one (`./transcript-reader.ts`). Every other\n * change (the run's end, a compaction, a history edit) reads it whole again.\n */\nconst RUN_APPENDS = new Set<HostSignal['kind']>(['run:start', 'turn:end', 'prompt-turns'])\n\nconst debugFallback: (error: unknown) => void = process.env.ZIDANE_DEBUG\n ? error => console.error('[zidane/ipc] the history worker could not serve; the host thread does:', error)\n : () => {}\n\n/**\n * A host's pager. The worker is used only for a store that is a SQLite file\n * (`sqliteStoreFile`), with the kill switch off; it spawns lazily, on the\n * first page, for the first such file (one host, one store).\n * @param options - Options.\n * @param options.replays - The in-thread cache; default a new one.\n * @param options.worker - Makes the worker client (tests); default {@link createTranscriptHistoryWorker}.\n */\nexport function createHostTranscriptPager(options: {\n replays?: TranscriptReplayCache\n worker?: (dbPath: string) => TranscriptHistoryWorker\n} = {}): HostTranscriptPager {\n const replays = options.replays ?? createTranscriptReplayCache()\n const makeWorker = options.worker ?? (dbPath => createTranscriptHistoryWorker({ dbPath }))\n let worker: { client: TranscriptHistoryWorker, path: string } | null = null\n let closed = false\n\n const usable = (store: SessionStore): { client: TranscriptHistoryWorker, file: SqliteStoreFile } | null => {\n const file = sqliteStoreFile(store)\n if (closed || !file || process.env[HISTORY_WORKER_KILL_SWITCH] === '1')\n return null\n worker ??= { client: makeWorker(file.path), path: file.path }\n return worker.path === file.path && !worker.client.isDegraded() ? { client: worker.client, file } : null\n }\n const drop = (sessionId: string, live?: boolean): void => worker?.client.drop(sessionId, live)\n\n return {\n replays,\n async page(store, sessionId, paging) {\n const target = usable(store)\n if (target) {\n // The worker reads on its own connection: let this one's queued writes land first, as an in-thread read would wait for them.\n await target.file.settled()\n try {\n return await target.client.page(sessionId, paging)\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n return replays.page(store, sessionId, paging)\n },\n observe(signal) {\n replays.observe(signal)\n const sessionId = changedSessionOf(signal)\n if (sessionId !== undefined)\n drop(sessionId, RUN_APPENDS.has(signal.kind))\n },\n forget(sessionId) {\n replays.forget(sessionId)\n drop(sessionId)\n },\n async usage(store) {\n const file = sqliteStoreFile(store)\n if (!file)\n return null\n await file.settled()\n const target = usable(store)\n if (target) {\n try {\n return await target.client.usage()\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n const db = await openReadonlySqlite(file.path)\n try {\n return runUsageAggregates(db)\n }\n finally {\n db.close()\n }\n },\n close() {\n closed = true\n worker?.client.close()\n worker = null\n },\n }\n}\n","/**\n * Secret redaction for what a host shows about its MCP servers\n * (`catalog.mcps`): command-line arguments and URLs, which config files\n * routinely fill with tokens. Over-redacting an ordinary argument is a\n * cosmetic loss; under-redacting leaks a credential to every client, so the\n * rules lean wide, but stay off file paths, package names and plain words.\n *\n * - URLs (`scheme://…`, as an argument or inside one): userinfo, query values,\n * fragment values, and secret-looking path segments.\n * - Values of secret-looking flags (`--token x`, `--api-key=x`), of header\n * flags (`-H \"Name: value\"`, `--header=Name: value`), of secret-looking\n * headers anywhere (`Authorization: Bearer …`), and of secret-looking\n * `KEY=VALUE` pairs (`-e GITHUB_TOKEN=…`, `env API_KEY=…`, `--pass x`).\n * - JSON arguments (`--config '{\"apiKey\":\"…\"}'`): the value of every\n * secret-named key at any depth; the other strings as values.\n * - Connection strings and form bodies (`Server=x;Password=…`,\n * `a=1&token=…`): each secret-named pair's value.\n * - Known token shapes anywhere in an argument (`sk-…`, `ghp_…`, `xoxb-…`,\n * `AKIA…`, `glpat-…`, `zds_…`), and whole high-entropy arguments.\n *\n * What counts as secret-looking is shared (`src/chat/secret-shapes`): the\n * remote host URL check refuses the same shapes in a URL's path.\n */\nimport { isSecretName, isSecretPathSegment, KNOWN_TOKEN, looksLikeSecret } from '../../chat/secret-shapes'\nimport { REDACTED } from '../protocol'\n\nconst HEADER_FLAGS = new Set(['-H', '--header', '--headers'])\nconst URL_SHAPED = /^[a-z][a-z0-9+.-]*:\\/\\//i\nconst HEADER = /^([\\w-]+):(\\s*)\\S.*$/s\nconst KEY_VALUE = /^([A-Z_][\\w.-]*)=(.*)$/is\n/** `k=v` pairs joined by `;` or `&` (a connection string, a form body): `Server=x;Password=y`, `a=1&token=x`. */\nconst DELIMITED_PAIRS = /^[a-z_][\\w .-]*=[^;&]*(?:[;&][a-z_][\\w .-]*=[^;&]*)+[;&]?$/i\n/** A JSON object or array argument (`--config '{\"apiKey\":\"…\"}'`). */\nconst JSON_SHAPED = /^\\s*[{[][\\s\\S]*[}\\]]\\s*$/\n\nconst scrubKnownTokens = (value: string): string => value.replace(KNOWN_TOKEN, REDACTED)\n\nfunction redactPairs(text: string): string {\n return text.split('&').map((pair) => {\n const eq = pair.indexOf('=')\n return eq < 0 ? pair : `${pair.slice(0, eq)}=${REDACTED}`\n }).join('&')\n}\n\n/**\n * `https://user:pw@host/p/<key>/sse?k=v#t=x` → `https://<redacted>@host/p/<redacted>/sse?k=<redacted>#t=<redacted>`;\n * an unparsable URL is redacted whole.\n */\nexport function redactUrl(raw: string): string {\n let url: URL\n try {\n url = new URL(raw)\n }\n catch {\n return REDACTED\n }\n const credentials = url.username !== '' || url.password !== '' ? `${REDACTED}@` : ''\n const path = url.pathname.split('/').map(segment => isSecretPathSegment(segment) ? REDACTED : segment).join('/')\n const keys = [...url.searchParams.keys()]\n const query = keys.length > 0 ? `?${keys.map(key => `${encodeURIComponent(key)}=${REDACTED}`).join('&')}` : ''\n const fragment = url.hash.slice(1)\n const hash = fragment === '' ? '' : fragment.includes('=') ? `#${redactPairs(fragment)}` : looksLikeSecret(fragment) ? `#${REDACTED}` : `#${fragment}`\n const authority = url.host !== '' || raw.includes('//') ? `//${credentials}${url.host}` : ''\n return scrubKnownTokens(`${url.protocol}${authority}${path}${query}${hash}`)\n}\n\nfunction redactHeader(value: string): string {\n const match = HEADER.exec(value)\n return match ? `${match[1]}:${match[2]}${REDACTED}` : REDACTED\n}\n\n/** One value standing on its own (a positional argument, or what follows `--flag=`). */\nfunction redactValue(value: string): string {\n if (URL_SHAPED.test(value))\n return redactUrl(value)\n const header = HEADER.exec(value)\n if (header && isSecretName(header[1]!))\n return redactHeader(value)\n const json = JSON_SHAPED.test(value) ? redactJson(value) : null\n if (json !== null)\n return json\n if (DELIMITED_PAIRS.test(value))\n return redactDelimitedPairs(value)\n const pair = KEY_VALUE.exec(value)\n if (pair)\n return `${pair[1]}=${isSecretName(pair[1]!) ? REDACTED : redactValue(pair[2]!)}`\n if (looksLikeSecret(value))\n return REDACTED\n return scrubKnownTokens(value)\n}\n\n/** `Server=x;Password=y` → `Server=x;Password=<redacted>`: each secret-named pair's value, the others' as values. */\nfunction redactDelimitedPairs(value: string): string {\n return value.split(/([;&])/).map((part) => {\n const eq = part.indexOf('=')\n if (eq < 0)\n return part\n const name = part.slice(0, eq)\n return `${name}=${isSecretName(name.trim()) ? REDACTED : redactValue(part.slice(eq + 1))}`\n }).join('')\n}\n\n/** A JSON argument with every secret-named key's value redacted (any depth), the other strings as values; `null` when not JSON. */\nfunction redactJson(value: string): string | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n }\n catch {\n return null\n }\n if (parsed === null || typeof parsed !== 'object')\n return null\n const walk = (node: unknown): unknown => {\n if (typeof node === 'string')\n return redactValue(node)\n if (Array.isArray(node))\n return node.map(walk)\n if (node !== null && typeof node === 'object')\n return Object.fromEntries(Object.entries(node).map(([key, child]) => [key, isSecretName(key) ? REDACTED : walk(child)]))\n return node\n }\n return JSON.stringify(walk(parsed))\n}\n\n/** An MCP server's arguments with every secret-looking value replaced by {@link REDACTED}. */\nexport function redactArgs(args: readonly string[]): string[] {\n const out: string[] = []\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!\n if (!arg.startsWith('-')) {\n out.push(redactValue(arg))\n continue\n }\n const eq = arg.indexOf('=')\n const flag = eq > 0 ? arg.slice(0, eq) : arg\n if (eq > 0) {\n const value = arg.slice(eq + 1)\n out.push(`${flag}=${HEADER_FLAGS.has(flag) ? redactHeader(value) : isSecretName(flag) ? REDACTED : redactValue(value)}`)\n continue\n }\n out.push(scrubKnownTokens(arg))\n const next = args[i + 1]\n if (next === undefined || next.startsWith('-'))\n continue\n if (HEADER_FLAGS.has(flag)) {\n out.push(redactHeader(next))\n i++\n }\n else if (isSecretName(flag)) {\n out.push(REDACTED)\n i++\n }\n }\n return out\n}\n","/**\n * What a host discovered, as the settings tabs list it (`catalog.*`): the\n * same scans and gates the host's agents use (`composeSessionSkills`,\n * `discoverSessionMcpServers`, the plugin gates), each entry with whether\n * the host's settings enable it. Wire-safe and secret-free: an MCP server's\n * `env` / `headers` values never leave the host, and its URL and arguments\n * go through `./redact` (credentials, query / fragment values, header and\n * secret-flag values, secret `KEY=VALUE` pairs, token-shaped values).\n */\nimport type { McpServerStatus } from '../../chat/mcp-status'\nimport type { DiscoveredMcp, DiscoveryError } from '../../chat/mcps-discovery'\nimport type { DiscoveredPlugin } from '../../chat/plugins-discovery'\nimport type { LoadedExtension, LoadedPluginRecord } from '../../extensions/index'\nimport type { SkillConfig } from '../../skills/index'\nimport type { HostCatalogError, HostCatalogExtension, HostCatalogMcp, HostCatalogPlugin, HostCatalogSkill, HostSettings } from '../protocol'\nimport { readExtensionInstallOrigin } from '../../extensions/install'\nimport { REDACTED } from '../protocol'\nimport { redactArgs, redactUrl } from './redact'\n\nconst allows = (list: readonly string[] | undefined, name: string): boolean => list === undefined || list.includes(name)\n\n/**\n * Disk skills (gated by `enabledSkills`), then plugin and extension skills\n * (gated by their plugin / extension, so always on here), later ones winning\n * a name like the agent's own merge (`mergeSkillCatalog`).\n */\nexport function skillEntries(input: { disk: readonly SkillConfig[], plugin: readonly SkillConfig[], extension: readonly SkillConfig[], settings: HostSettings }): HostCatalogSkill[] {\n const byName = new Map<string, HostCatalogSkill>()\n const add = (skill: SkillConfig, origin: HostCatalogSkill['origin']): void => {\n const contributedBy = origin === 'plugin' ? skill.metadata?.['zidane.plugin'] : origin === 'extension' ? skill.metadata?.['zidane.extension'] : undefined\n byName.set(skill.name, {\n name: skill.name,\n description: skill.description,\n ...(skill.source ? { source: skill.source } : {}),\n ...(skill.location ? { location: skill.location } : {}),\n origin,\n ...(contributedBy ? { contributedBy } : {}),\n enabled: origin === 'disk' ? allows(input.settings.enabledSkills, skill.name) : true,\n toggleable: origin === 'disk',\n })\n }\n for (const skill of input.disk)\n add(skill, 'disk')\n for (const skill of input.plugin)\n add(skill, 'plugin')\n for (const skill of input.extension)\n add(skill, 'extension')\n return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\nfunction redactValues(record: Readonly<Record<string, string>> | undefined): Record<string, string> | undefined {\n if (!record)\n return undefined\n return Object.fromEntries(Object.keys(record).map(key => [key, REDACTED]))\n}\n\nexport function mcpEntries(servers: readonly DiscoveredMcp[], errors: readonly DiscoveryError[], settings: HostSettings, statuses: ReadonlyMap<string, McpServerStatus>): { servers: HostCatalogMcp[], errors: HostCatalogError[] } {\n return {\n servers: servers.map(({ config, source, path }) => {\n const env = redactValues(config.env)\n const headers = redactValues(config.headers)\n const status = statuses.get(config.name)\n return {\n name: config.name,\n transport: config.transport,\n source,\n path,\n enabled: allows(settings.enabledMcps, config.name),\n toggleable: true,\n ...(config.command !== undefined ? { command: config.command } : {}),\n ...(config.args ? { args: redactArgs(config.args) } : {}),\n ...(config.url !== undefined ? { url: redactUrl(config.url) } : {}),\n ...(config.cwd !== undefined ? { cwd: config.cwd } : {}),\n // Always said for a stdio server, so a client knows where it runs (and whether it can share it).\n ...(config.transport === 'stdio' ? { scope: config.scope === 'context' ? 'context' as const : 'host' as const } : {}),\n ...(config.shared !== undefined ? { shared: config.shared } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(env ? { env } : {}),\n ...(headers ? { headers } : {}),\n ...(status ? { status } : {}),\n }\n }),\n errors: errors.map(e => ({ path: e.path, source: e.source, message: e.message, ...(e.informational ? { informational: true } : {}) })),\n }\n}\n\nfunction capabilities(contributions: NonNullable<LoadedExtension['contributions']>): string[] {\n const labels: string[] = []\n const add = (label: string, present: boolean): void => {\n if (present)\n labels.push(label)\n }\n add('agents', Object.keys(contributions.agents).length > 0)\n add('providers', Object.keys(contributions.providers).length > 0)\n add('tools', Object.keys(contributions.tools).length > 0)\n add('hooks', Object.values(contributions.hooks).some(handlers => handlers !== undefined && handlers.length > 0))\n add('mcps', contributions.mcpServers.length > 0)\n add('skills', contributions.skills.length > 0)\n add('commands', contributions.commands.length > 0)\n add('completions', contributions.completionProviders.length > 0)\n add('themes', Object.keys(contributions.themes).length > 0)\n return labels\n}\n\n/**\n * What a row shows of an extension beside its name: its display name and\n * icon (the definition's, else the manifest's) and the source it was\n * installed from (`.install.json`). Shared by every host's extension list.\n *\n * @param ext - The extension.\n */\nexport function extensionPresentation(ext: LoadedExtension): Pick<HostCatalogExtension, 'displayName' | 'icon' | 'origin'> {\n const displayName = ext.definition?.displayName?.trim() || ext.manifest?.displayName?.trim()\n const icon = ext.definition?.icon ?? ext.manifest?.icon\n const gui = icon?.gui?.trim() ? icon.gui : undefined\n const tui = icon?.tui?.trim() ? icon.tui : undefined\n const origin = ext.dir ? readExtensionInstallOrigin(ext.dir) : null\n return {\n ...(displayName ? { displayName } : {}),\n ...(gui !== undefined || tui !== undefined ? { icon: { ...(gui !== undefined ? { gui } : {}), ...(tui !== undefined ? { tui } : {}) } } : {}),\n ...(origin ? { origin } : {}),\n }\n}\n\n/** Loaded, then inactive (disabled or broken), first one of a name wins. */\nexport function extensionEntries(loaded: readonly LoadedExtension[], inactive: readonly LoadedExtension[], settings: HostSettings): HostCatalogExtension[] {\n const rows = new Map<string, HostCatalogExtension>()\n for (const ext of [...loaded, ...inactive]) {\n if (rows.has(ext.name))\n continue\n rows.set(ext.name, {\n ...extensionPresentation(ext),\n name: ext.name,\n source: ext.source,\n enabled: !ext.error && allows(settings.enabledExtensions, ext.name),\n toggleable: !ext.error,\n ...(ext.definition?.version ? { version: ext.definition.version } : {}),\n ...(ext.definition?.description ? { description: ext.definition.description } : {}),\n ...(ext.dir ? { dir: ext.dir } : {}),\n ...(ext.error ? { error: ext.error } : {}),\n ...(ext.contributions ? { capabilities: capabilities(ext.contributions) } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\ninterface PluginSource { plugin: DiscoveredPlugin['plugin'], name: string, origin: HostCatalogPlugin['origin'] }\n\n/** Disk plugins, then the ones extensions loaded (a name on disk wins, as the agent's gate decides). */\nexport function pluginEntries(disk: readonly DiscoveredPlugin[], fromExtensions: readonly LoadedPluginRecord[], settings: HostSettings): HostCatalogPlugin[] {\n const sources: PluginSource[] = [\n ...disk.map(p => ({ plugin: p.plugin, name: p.name, origin: { kind: 'disk' as const, scope: p.source, dir: p.path } })),\n ...fromExtensions.map(r => ({ plugin: r.plugin, name: r.name, origin: { kind: 'extension' as const, extensionName: r.extensionName, dir: r.dir } })),\n ]\n const rows = new Map<string, HostCatalogPlugin>()\n for (const { plugin, name, origin } of sources) {\n if (rows.has(name))\n continue\n const error = plugin.ok ? undefined : plugin.diagnostics.find(d => d.severity === 'error')?.message\n rows.set(name, {\n name,\n origin,\n ok: plugin.ok,\n enabled: plugin.ok && allows(settings.enabledPlugins, name),\n toggleable: plugin.ok,\n ...(plugin.manifest?.version !== undefined ? { version: plugin.manifest.version } : {}),\n ...(plugin.manifest?.description !== undefined ? { description: plugin.manifest.description } : {}),\n skills: plugin.skills.map(s => s.name),\n mcpServers: plugin.mcpServers.map(s => s.name),\n ...(error ? { error } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n","/**\n * What the host discovered for its settings tabs (`catalog.*`), the agent\n * profiles a folder offers (`agents.list`) and the models its credentials\n * can run (`models.list`), so a window on a server lists the server's\n * skills, MCP servers, extensions, plugins, agents and providers, not its own.\n * An MCP server's row carries its state on the host (sign-in, tools, last\n * Test: `mcp.test`, `mcp.signOut`), and the server processes its sessions\n * share can be listed and restarted (`mcp.instances`, `mcp.restart`).\n */\nimport type { ProviderKey } from '../../../chat/auth'\nimport type { ResolvedConfig } from '../../../chat/config'\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineProject } from '../../../chat/host/machines'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { DiscoveredPlugin } from '../../../chat/plugins-discovery'\nimport type { HostModelProvider } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { availableAgents } from '../../../chat/agents'\nimport { liveAgentProfiles } from '../../../chat/agents-catalog'\nimport { detectAuth } from '../../../chat/auth'\nimport { listDecisionModels, testDecisionModel } from '../../../chat/decision-models'\nimport { machineDiscoveryCwd } from '../../../chat/host/machines'\nimport { createProviderBuilder } from '../../../chat/host/models/index'\nimport { listImageModels } from '../../../chat/image-models'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { testModel } from '../../../chat/model-test'\nimport { buildPluginContributions, discoverProjectPlugins } from '../../../chat/plugins-discovery'\nimport { scopeCwd } from '../../../chat/session-cwd'\nimport { discoverProjectSkills } from '../../../chat/skills-discovery'\nimport { filterRegistryPlugins } from '../../../extensions/index'\nimport { extensionEntries, mcpEntries, pluginEntries, skillEntries } from '../catalog-entries'\nimport { optionalString, requiredString } from './params'\n\ntype CatalogMethod = 'catalog.skills' | 'catalog.mcps' | 'catalog.extensions' | 'catalog.plugins' | 'agents.list' | 'models.list' | 'models.test' | 'decisions.test' | 'mcp.test' | 'mcp.signOut' | 'mcp.instances' | 'mcp.restart'\n\nconst kindOf = (kind: unknown): string | undefined => (typeof kind === 'string' ? kind : undefined)\n\n/**\n * The folder a catalog scans: `cwd` (inside the roots on a server), else the\n * host user's home. A machine's folder (`docs/MACHINES.md` § Folders) is\n * never read here: a folder of this host's stands in for the user scope.\n */\nexport function catalogFolder({ env, host }: { env: Pick<DaemonEnvironment, 'userDataDir'>, host: Pick<ChatHost, 'resolveFolder'> }, cwd: unknown, kind?: unknown): string {\n if (cwd !== undefined && typeof cwd !== 'string')\n throw new Error('cwd must be a string.')\n if (!cwd)\n return scopeCwd('')\n const folder = host.resolveFolder(cwd, kindOf(kind))\n return folder.machine ? machineDiscoveryCwd(env.userDataDir()) : scopeCwd(folder.cwd)\n}\n\n/** One account of a `models.list` provider: its own list only when it differs from the provider's (both as JSON). */\nfunction accountEntry(id: string, label: string, active: boolean, own: string, provider: string): NonNullable<HostModelProvider['accounts']>[number] {\n return { id, label, active, ...(own !== provider ? { models: JSON.parse(own) as HostModelProvider['models'] } : {}) }\n}\n\nexport function createCatalogHandlers({ env, host, mcpStatus }: {\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder' | 'folderCatalog' | 'mcpServers'>\n mcpStatus: McpStatusTracker\n}): Handlers<CatalogMethod> {\n const folderOf = (cwd: unknown, kind?: unknown): string => catalogFolder({ env, host }, cwd, kind)\n /** User scope here, project scope read on the machine for a machine's folder. */\n const catalogOf = async (cwd: unknown, kind: unknown, prefix: string): Promise<{ dir: string, project?: MachineProject }> => {\n if (typeof cwd !== 'string' || !cwd || !host.resolveFolder(cwd, kindOf(kind)).machine)\n return { dir: folderOf(cwd, kind) }\n const { discoveryCwd, project } = await host.folderCatalog(cwd, kindOf(kind), prefix)\n return { dir: discoveryCwd, ...(project ? { project } : {}) }\n }\n const scanFlags = () => {\n const settings = env.readSettings()\n return { settings, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false }\n }\n /** A folder's MCP servers: a machine's project ones first, as in its sessions. */\n const mcpsOf = async (cwd: unknown, kind: unknown) => {\n const { dir, project } = await catalogOf(cwd, kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { foreignAgents, ruler } = scanFlags()\n const { servers: found, errors } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents, ruler })\n const machineNames = new Set((project?.mcps ?? []).map(server => server.config.name))\n return { servers: [...(project?.mcps ?? []), ...found.filter(server => !machineNames.has(server.config.name))], errors }\n }\n const plugins = async (dir: string, config: ResolvedConfig): Promise<DiscoveredPlugin[]> => {\n const { plugins: found } = await discoverProjectPlugins({\n cwd: dir,\n prefix: config.prefix,\n ...(config.pluginScanPaths.length > 0 ? { extraRoots: config.pluginScanPaths } : {}),\n })\n return found\n }\n\n return {\n 'catalog.skills': async (p) => {\n const { dir, project } = await catalogOf(p?.cwd, p?.kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { settings, foreignAgents, ruler } = scanFlags()\n const [found, discovered] = await Promise.all([\n discoverProjectSkills({ cwd: dir, prefix: config.prefix, foreignAgents, ruler }),\n plugins(dir, config),\n ])\n // A machine's project skills first: project beats user, as in its sessions.\n const machineNames = new Set((project?.skills ?? []).map(skill => skill.name))\n const disk = [...(project?.skills ?? []), ...found.filter(skill => !machineNames.has(skill.name))]\n const pluginSkills = buildPluginContributions({ discovered, ...(settings.enabledPlugins !== undefined ? { enabled: settings.enabledPlugins } : {}) }).skills\n const live = filterRegistryPlugins(config.extensions, settings.enabledPlugins, new Set(discovered.map(d => d.name)))\n return { skills: skillEntries({ disk, plugin: pluginSkills, extension: live.skills, settings }) }\n },\n 'catalog.mcps': async (p) => {\n const { servers, errors } = await mcpsOf(p?.cwd, p?.kind)\n return mcpEntries(servers, errors, env.readSettings(), mcpStatus.statuses(servers.map(server => server.config)))\n },\n 'mcp.test': async (p) => {\n const name = requiredString(p.name, 'name')\n const found = (await mcpsOf(p.cwd, p.kind)).servers.find(server => server.config.name === name)\n if (!found)\n throw new Error(`No MCP server \"${name}\" in that folder's catalog.`)\n await mcpStatus.test(found.config)\n return mcpStatus.statuses([found.config]).get(name)!\n },\n 'mcp.signOut': (p) => {\n mcpStatus.signOut(requiredString(p.name, 'name'))\n },\n 'mcp.instances': p => host.mcpServers.instances(optionalString(p?.cwd, 'cwd')),\n 'mcp.restart': async p => ({\n restarted: await host.mcpServers.restart(requiredString(p?.name, 'name'), optionalString(p?.cwd, 'cwd')),\n }),\n 'catalog.extensions': async (p) => {\n const config = await env.runtimeConfig(folderOf(p?.cwd, p?.kind))\n return { extensions: extensionEntries(config.extensions.loaded, config.extensions.inactive, env.readSettings()) }\n },\n 'catalog.plugins': async (p) => {\n const dir = folderOf(p?.cwd, p?.kind)\n const config = await env.runtimeConfig(dir)\n return { plugins: pluginEntries(await plugins(dir, config), config.extensions.plugins, env.readSettings()) }\n },\n // A profile a setting turns off (Codemode) is not offered; one an extension registered since the config was resolved is.\n 'agents.list': async (p) => {\n const config = await env.runtimeConfig(folderOf(p.cwd))\n return Object.values(availableAgents(liveAgentProfiles(config), env.readSettings())).map(a => ({ id: a.id, label: a.label, description: a.description, accent: a.accent ?? 'accent' }))\n },\n 'models.list': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const authed = detectAuth(env.userDataDir(), config.providers).filter(auth => auth.available)\n // Decision and image availability read stored API keys from the environment.\n env.applyAuthEnv?.()\n const decisionModels = listDecisionModels({ providers: config.providers, authed })\n const imageModels = listImageModels({ providers: config.providers, authed })\n const providers: HostModelProvider[] = authed.map((auth) => {\n const decisions = decisionModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({ id: entry.modelId, available: entry.available, ...(entry.reason ? { reason: entry.reason } : {}) }))\n const images = imageModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({\n id: entry.modelId,\n name: entry.modelName,\n references: entry.references,\n transparency: entry.transparency,\n available: entry.available,\n ...(entry.reason ? { reason: entry.reason } : {}),\n ...(entry.isDefault ? { isDefault: true } : {}),\n }))\n // JSON copies: `ModelInfo` is data, but a provider may hand out frozen or shared arrays.\n const models = JSON.stringify(config.modelsFor(auth.key))\n return {\n key: auth.key,\n label: config.providers[auth.key]?.label ?? auth.label,\n models: JSON.parse(models) as HostModelProvider['models'],\n ...(auth.accounts ? { accounts: auth.accounts.map(({ id, label, active }) => accountEntry(id, label, active, JSON.stringify(config.modelsFor(auth.key, id)), models)) } : {}),\n ...(decisions.length > 0 ? { decisionModels: decisions } : {}),\n ...(images.length > 0 ? { imageModels: images } : {}),\n }\n })\n return { providers }\n },\n 'models.test': async (p) => {\n if (typeof p?.model !== 'string' || !p.model)\n throw new Error('model must be a \"provider/model\" string.')\n const config = p.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const build = createProviderBuilder(env)\n return testModel({\n providers: config.providers,\n buildProvider: (key, account) => build(config.providers, key as ProviderKey, account),\n model: p.model,\n })\n },\n 'decisions.test': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n env.applyAuthEnv?.()\n const model = typeof p?.model === 'string' ? p.model : env.readSettings().decisionModel\n return testDecisionModel({\n providers: config.providers,\n buildProvider: (key) => {\n const descriptor = config.providers[key]\n if (!descriptor)\n throw new Error(`Provider \"${key}\" is not configured`)\n return descriptor.factory()\n },\n ...(model ? { decisionModel: model } : {}),\n })\n },\n }\n}\n","/**\n * Session artifacts: list, delete, upsert, re-resolve (a kind's `resolve()`,\n * run here with the extensions of the folder the artifact landed in), with\n * change fan-out, and the sidebar rows' badges.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ExtensionRegistry } from '../../../extensions/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { ARTIFACT_BADGES_MAX, refreshArtifact, sessionsBadges } from '../../../extensions/index'\nimport { normalizeArtifactInput } from '../../../session/artifacts'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, sessionIdOf } from './params'\n\n/** Wire-supplied limit → sane positive integer capped at 1000, else `undefined` (no limit). */\nfunction boundedLimit(raw: unknown): number | undefined {\n return Number.isInteger(raw) && (raw as number) > 0 ? Math.min(raw as number, 1000) : undefined\n}\n\nexport function createArtifactHandlers({ store, broadcast, env, host }: {\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder'>\n}): Handlers<'sessions.artifacts' | 'artifacts.list' | 'artifacts.delete' | 'artifacts.upsert' | 'artifacts.refresh' | 'artifacts.badges'> {\n /** The registry of the folder an artifact landed in; `undefined` (the built-in kinds) when it can't be built (a folder gone, or outside the roots). */\n const registryOf = async (projectRoot: string | undefined): Promise<ExtensionRegistry | undefined> => {\n try {\n return (await env.runtimeConfig(catalogFolder({ env, host }, projectRoot ?? ''))).extensions\n }\n catch {\n return undefined\n }\n }\n return {\n 'sessions.artifacts': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n sessionId: p.sessionId,\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.list': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n // Tri-state: `null` selects untagged sessions, omitted ignores the axis.\n ...(p.projectRoot === null || typeof p.projectRoot === 'string' ? { projectRoot: p.projectRoot } : {}),\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(typeof p.uri === 'string' ? { uri: p.uri } : {}),\n ...(typeof p.since === 'number' && Number.isFinite(p.since) ? { since: p.since } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.delete': async (p) => {\n if (!store.deleteArtifact)\n return false\n await store.deleteArtifact(p.sessionId, p.artifactId)\n broadcast({ kind: 'artifact:changed', sessionId: p.sessionId, op: 'delete', artifactId: p.artifactId })\n return true\n },\n 'artifacts.upsert': async (p) => {\n if (!store.upsertArtifact)\n return null\n // Wire input: re-normalize the presentation fields (bounds, kind\n // shape) before trusting them; identity fields pass through since\n // the store merges onto the existing row anyway.\n const normalized = normalizeArtifactInput(p.artifact)\n if (!normalized || typeof p.artifact?.sessionId !== 'string' || typeof p.artifact?.id !== 'string')\n return null\n const now = Date.now()\n const stored = await store.upsertArtifact({\n ...normalized,\n id: p.artifact.id,\n sessionId: p.artifact.sessionId,\n ...(typeof p.artifact.runId === 'string' ? { runId: p.artifact.runId } : {}),\n ...(typeof p.artifact.turnId === 'string' ? { turnId: p.artifact.turnId } : {}),\n createdAt: typeof p.artifact.createdAt === 'number' ? p.artifact.createdAt : now,\n updatedAt: now,\n })\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.refresh': async (p) => {\n const sessionId = sessionIdOf(p)\n if (!store.listArtifacts || !store.upsertArtifact)\n return null\n const artifact = (await store.listArtifacts({ sessionId })).find(a => a.id === p.artifactId)\n if (!artifact)\n return null\n const updated = await refreshArtifact(artifact, await registryOf(artifact.projectRoot), p.force === true ? { force: true } : undefined)\n if (!updated)\n return null\n const stored = await store.upsertArtifact(updated)\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.badges': async (p) => {\n const ids: unknown = p.sessionIds\n if (!Array.isArray(ids) || ids.length > ARTIFACT_BADGES_MAX || ids.some(id => typeof id !== 'string'))\n throw new InvalidParamsError(`sessionIds must be an array of at most ${ARTIFACT_BADGES_MAX} session ids.`)\n if (!store.listArtifacts)\n return {}\n const list = store.listArtifacts.bind(store)\n const lists = Object.fromEntries(await Promise.all([...new Set(ids as string[])].map(async sessionId => [sessionId, await list({ sessionId })] as const)))\n const roots = [...new Set(Object.values(lists).flat().map(a => a.projectRoot ?? ''))]\n const registries = new Map(await Promise.all(roots.map(async root => [root, await registryOf(root)] as const)))\n return sessionsBadges(lists, root => registries.get(root))\n },\n }\n}\n","/**\n * The host's provider credentials, managed by a client (Settings on a\n * window attached to a zidane-server): status, set an API key (with a\n * provider's custom fields: `auth.configure`), remove, pick the active\n * stored credential, rename an OAuth account.\n * Secrets go in, never out: statuses carry sources, labels and env var\n * names only, and nothing here logs a key.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { HostProviderAuth } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { detectAuth } from '../../../chat/auth'\nimport { applyApiKeyEnv, configuredProviderFields, configureProviderCredential, providerFieldViews, readProviderCredentials, removeProviderCredential, removeStoredCredential, setCredentialLabel, setPreferredCredential, setProviderCredential } from '../../../chat/credentials'\nimport { supportsOAuth } from '../../../chat/oauth'\nimport { InvalidParamsError } from './params'\n\n/** Longest API key accepted (keys are well under 1 KiB; this bounds a mistaken paste). */\nconst MAX_KEY_LENGTH = 8192\n/** Longest account name accepted. */\nconst MAX_LABEL_LENGTH = 200\n\nexport type ProviderAuth = ReturnType<typeof createProviderAuth>\n\n/** The host's providers and their credentials: lookups, statuses, and applying a change. */\nexport function createProviderAuth({ host, env }: { host: Pick<ChatHost, 'rebuildAllAgents'>, env: DaemonEnvironment }) {\n const registry = (): Readonly<Record<string, ProviderDescriptor>> => env.config.providers\n const dataDir = (): string => env.userDataDir()\n\n const descriptorOf = (provider: unknown): ProviderDescriptor => {\n const descriptor = typeof provider === 'string' ? registry()[provider] : undefined\n if (!descriptor)\n throw new Error(`Unknown provider \"${String(provider)}\".`)\n return descriptor\n }\n\n const statusOf = (key: string): HostProviderAuth => {\n const descriptor = registry()[key]!\n const auth = detectAuth(dataDir(), { [key]: descriptor })[0]!\n const customFields = providerFieldViews(descriptor)\n const configuredFields = configuredProviderFields(dataDir(), descriptor)\n return {\n key: auth.key,\n label: auth.label,\n configured: auth.available,\n oauth: supportsOAuth(descriptor),\n ...(auth.envKey ? { envKey: auth.envKey } : {}),\n methods: auth.methods.map(m => ({\n source: m.source,\n active: m.active === true,\n ...(m.key !== undefined ? { key: m.key } : {}),\n ...(m.label !== undefined ? { label: m.label } : {}),\n detail: m.detail,\n })),\n ...(customFields ? { customFields } : {}),\n ...(configuredFields ? { configuredFields } : {}),\n }\n }\n\n /** The stored API key values of a provider (to clear them from the environment once removed). */\n const storedKeys = (descriptor: ProviderDescriptor): string[] =>\n readProviderCredentials(dataDir(), descriptor).flatMap(s => s.credential.kind === 'apikey' && s.credential.value ? [s.credential.value] : [])\n\n /** Make the change take effect: env re-applied, a removed key out of it, agents rebuilt. */\n const applied = (descriptor: ProviderDescriptor, removedKeys: readonly string[] = []): void => {\n if (env.applyAuthEnv)\n env.applyAuthEnv()\n else\n applyApiKeyEnv(dataDir(), registry(), { log: () => undefined })\n // `applyApiKeyEnv` leaves the env alone when nothing is stored; a key it\n // put there earlier must not outlive its removal.\n const envKey = descriptor.envKey\n if (envKey && removedKeys.includes(process.env[envKey] ?? '') && !storedKeys(descriptor).includes(process.env[envKey]!))\n delete process.env[envKey]\n void host.rebuildAllAgents().catch(() => undefined)\n }\n\n return { registry, dataDir, descriptorOf, statusOf, storedKeys, applied }\n}\n\nexport function createAuthHandlers({ auth }: { auth: ProviderAuth }): Handlers<'auth.status' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred' | 'auth.rename'> {\n const { registry, dataDir, descriptorOf, statusOf, storedKeys, applied } = auth\n return {\n 'auth.status': () => ({ providers: Object.keys(registry()).map(statusOf) }),\n 'auth.setApiKey': (p) => {\n const descriptor = descriptorOf(p.provider)\n const key = typeof p.key === 'string' ? p.key.trim() : ''\n if (!key)\n throw new Error('The API key is empty.')\n if (key.length > MAX_KEY_LENGTH)\n throw new Error(`The API key is longer than ${MAX_KEY_LENGTH} characters.`)\n setProviderCredential(dataDir(), descriptor, { kind: 'apikey', value: key })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.configure': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (p.value !== undefined && (typeof p.value !== 'string' || p.value.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError(`value must be a string of at most ${MAX_KEY_LENGTH} characters.`)\n const fields = p.customFields ?? {}\n if (typeof fields !== 'object' || Array.isArray(fields) || Object.values(fields).some(v => typeof v !== 'string' || v.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError('customFields must map field keys to strings.')\n configureProviderCredential(dataDir(), descriptor, { ...(p.value !== undefined ? { value: p.value } : {}), customFields: fields })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.remove': (p) => {\n const descriptor = descriptorOf(p.provider)\n const before = storedKeys(descriptor)\n let removed: boolean\n if (typeof p.account === 'string') {\n removed = removeStoredCredential(dataDir(), descriptor, p.account)\n }\n else {\n removed = readProviderCredentials(dataDir(), descriptor).length > 0\n removeProviderCredential(dataDir(), descriptor)\n }\n if (removed)\n applied(descriptor, before.filter(k => !storedKeys(descriptor).includes(k)))\n return { removed, provider: statusOf(descriptor.key) }\n },\n 'auth.setPreferred': (p) => {\n const descriptor = descriptorOf(p.provider)\n const target = p.target\n const key = typeof target === 'object' && target !== null ? (target as { key?: unknown }).key : undefined\n if (target !== 'apikey' && target !== 'oauth' && typeof key !== 'string')\n throw new InvalidParamsError('target must be \"apikey\", \"oauth\" or { key }.')\n const outcome = setPreferredCredential(dataDir(), descriptor, typeof key === 'string' ? { key } : target as 'apikey' | 'oauth')\n if (outcome === 'not-stored')\n throw new Error(`No stored ${typeof key === 'string' ? `credential ${key}` : `${String(target)} credential`} for ${descriptor.label}.`)\n if (outcome !== 'already-active')\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.rename': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (typeof p.account !== 'string' || typeof p.label !== 'string' || p.label.length > MAX_LABEL_LENGTH)\n throw new InvalidParamsError(`account must be a string and label a string of at most ${MAX_LABEL_LENGTH} characters.`)\n if (!setCredentialLabel(dataDir(), descriptor, p.account, p.label))\n throw new Error(`No stored OAuth account ${p.account} for ${descriptor.label}.`)\n return statusOf(descriptor.key)\n },\n }\n}\n","/**\n * Run here on a reply's shell blocks, over the wire: `sessions.runBlock`\n * starts the host's `runBlock` and answers with a run id; the output goes to\n * the connection that started it only, as `block-run:data` signals, then one\n * `block-run:end` with the saved run. `sessions.runBlockCancel` and a dropped\n * connection stop it. Bounded per connection (runs at once, block size); the\n * host bounds the time and the output it keeps. `sessions.blockRuns` and\n * `sessions.removeBlockRun` read and forget the saved runs.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { randomUUID } from 'node:crypto'\nimport { SHELL_BLOCK_MAX_CHARS } from '../../../chat/shell-blocks'\nimport { InvalidParamsError } from './params'\n\nexport const BLOCK_RUN_LIMITS = {\n /** Runs one connection may have going at once. */\n maxConcurrent: 4,\n}\n\ninterface Running {\n peer: HostPeer\n controller: AbortController\n}\n\nfunction nonEmpty(value: unknown, name: string): string {\n if (typeof value !== 'string' || value === '')\n throw new InvalidParamsError(`${name} must be a non-empty string.`)\n return value\n}\n\nexport function createBlockRunHandlers({ host, isConnected, limits = BLOCK_RUN_LIMITS }: {\n host: Pick<ChatHost, 'runBlock' | 'listBlockRuns' | 'removeBlockRun'>\n isConnected: (peer: HostPeer) => boolean\n limits?: typeof BLOCK_RUN_LIMITS\n}): {\n methods: Handlers<'sessions.runBlock' | 'sessions.runBlockCancel' | 'sessions.blockRuns' | 'sessions.removeBlockRun'>\n /** The peer dropped: stop what it started. */\n releasePeer: (peer: HostPeer) => void\n} {\n const running = new Map<string, Running>()\n const perPeer = new WeakMap<HostPeer, Set<string>>()\n const send = (peer: HostPeer, signal: HostSignal): void => {\n if (isConnected(peer))\n peer.send(signal)\n }\n\n return {\n methods: {\n 'sessions.runBlock': (p, peer) => {\n const sessionId = nonEmpty(p.sessionId, 'sessionId')\n const turnId = nonEmpty(p.turnId, 'turnId')\n const code = nonEmpty(p.code, 'code')\n const language = nonEmpty(p.language, 'language')\n if (code.length > SHELL_BLOCK_MAX_CHARS)\n throw new InvalidParamsError(`code is longer than ${SHELL_BLOCK_MAX_CHARS} characters.`)\n const own = perPeer.get(peer) ?? new Set<string>()\n perPeer.set(peer, own)\n if (own.size >= limits.maxConcurrent)\n throw new Error(`This connection already runs ${own.size} blocks (at most ${limits.maxConcurrent}): stop one first.`)\n const runId = randomUUID()\n const controller = new AbortController()\n own.add(runId)\n running.set(runId, { peer, controller })\n void host.runBlock(sessionId, { turnId, code, language }, {\n signal: controller.signal,\n onOutput: (stream, chunk) => send(peer, { kind: 'block-run:data', runId, stream, chunk }),\n }).then(\n run => send(peer, { kind: 'block-run:end', runId, run }),\n (err: unknown) => send(peer, { kind: 'block-run:end', runId, error: err instanceof Error ? err.message : String(err) }),\n ).finally(() => {\n own.delete(runId)\n running.delete(runId)\n })\n return { runId }\n },\n 'sessions.runBlockCancel': (p, peer) => {\n const entry = typeof p.runId === 'string' ? running.get(p.runId) : undefined\n if (!entry || entry.peer !== peer)\n return { cancelled: false }\n entry.controller.abort()\n return { cancelled: true }\n },\n 'sessions.blockRuns': async p => ({ runs: await host.listBlockRuns(nonEmpty(p.sessionId, 'sessionId')) }),\n 'sessions.removeBlockRun': async (p) => {\n await host.removeBlockRun(nonEmpty(p.sessionId, 'sessionId'), nonEmpty(p.key, 'key'))\n },\n },\n releasePeer(peer) {\n for (const runId of perPeer.get(peer) ?? [])\n running.get(runId)?.controller.abort()\n },\n }\n}\n\n/**\n * Other streamed-command handlers (a workspace exec's) with Run here's added:\n * the methods of both, and one release that stops what a dropped connection\n * started in either.\n *\n * @param streams - The other handlers.\n * @param deps - What {@link createBlockRunHandlers} needs.\n */\nexport function withBlockRunHandlers<M>(\n streams: { methods: M, releasePeer: (peer: HostPeer) => void },\n deps: Parameters<typeof createBlockRunHandlers>[0],\n): { methods: M & ReturnType<typeof createBlockRunHandlers>['methods'], releasePeer: (peer: HostPeer) => void } {\n const blocks = createBlockRunHandlers(deps)\n return {\n methods: { ...streams.methods, ...blocks.methods },\n releasePeer(peer) {\n streams.releasePeer(peer)\n blocks.releasePeer(peer)\n },\n }\n}\n","/** Browser hosts a client registers to serve the agent's browser tool. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\nexport function createBrowserHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'browser.registerHost' | 'browser.unregisterHost' | 'browser.respond'>\n /** The peer dropped: release the browser hosts it registered. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'browser.registerHost': (p, peer) => {\n ;(peer.browserHosts ??= new Set()).add(p.hostId)\n host.browser.registerHost(p.hostId)\n return { ok: true }\n },\n 'browser.unregisterHost': (p, peer) => {\n peer.browserHosts?.delete(p.hostId)\n host.browser.unregisterHost(p.hostId)\n return { ok: true }\n },\n 'browser.respond': (p, peer) => host.browser.respond(p.requestId, p.response, peer.browserHosts ?? new Set()),\n },\n releasePeer(peer) {\n for (const hostId of peer.browserHosts ?? [])\n host.browser.unregisterHost(hostId)\n },\n }\n}\n","/**\n * Installs and removals from a client (`catalog.install` / `remove` /\n * `update`, `extensions.changeOrigin`, `mcp.upsert` / `remove`, a new\n * extension's scaffold `extensions.create`): the local Settings actions, run on the host for a\n * window attached to a zidane-server. The Claude Code import goes through\n * the same gate (`guardedInstall`, `./onboarding`).\n *\n * Scope: the host user's only (`~/.agents/*`, `~/.<prefix>/*`). A\n * project's skills, extensions and MCP servers are files in its folder,\n * which the agent and the files panel already edit; installing into one\n * from a client would run a package manager inside a workspace for no gain.\n *\n * Installs fetch code and may run package managers ON THE HOST, so a\n * zidane-server gates them (`allowRemoteInstalls`, on by default: a client\n * token already runs commands there) and audits every attempt, refused or\n * failed ones too, with the token. Specs are GitHub or npm only (a path is\n * refused), work is bounded in time, progress lines come back with the\n * result. MCP `env` / `headers` values go into the host's `mcps.json` and\n * never come back. After a change the host rebuilds what reads it and\n * every window gets `catalog:changed`.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/host/signals'\nimport type { InstallIo } from '../../../install/source'\nimport type { McpServerConfig } from '../../../types'\nimport type { ExtensionInstallErrorData, HostCatalogName, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { existsSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { enabledMcpsWith, enabledMcpsWithout } from '../../../chat/mcp-allowlist'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { isMcpServerName, mcpsWritePath, removeMcpServer, upsertMcpServer } from '../../../chat/mcps-write'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { projectUserPaths } from '../../../chat/project-user-paths'\nimport { createExtension } from '../../../extension-authoring'\nimport { changeExtensionOrigin, ExtensionInstallError, installExtensionFromSpec, removeInstalledExtension, updateInstalledExtension } from '../../../extensions/install'\nimport { abortableInstallIo } from '../../../install/source'\nimport { saveMcpClientSecret } from '../../../mcp/oauth-provider'\nimport { installSkillFromSpec } from '../../../skills/install'\nimport { IpcErrorCode } from '../../protocol'\nimport { InvalidParamsError } from './params'\n\nexport interface RemoteInstallsOptions {\n /** `allowRemoteInstalls`, read at each call. */\n allowed: () => boolean\n /** One audit line per attempt (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n /** Test seam: the installers' fetch / exec / which. */\n io?: InstallIo\n /** Bound on one install or update. Default 5 minutes. */\n timeoutMs?: number\n}\n\ntype InstallMethod = 'catalog.install' | 'catalog.remove' | 'catalog.update' | 'extensions.changeOrigin' | 'mcp.upsert' | 'mcp.remove' | 'extensions.create'\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60_000\nconst MAX_SPEC_LENGTH = 500\nconst MAX_MCP_CONFIG_BYTES = 64 * 1024\nconst NAME_RE = /^[\\w@.-]{1,100}$/\nconst MCP_TRANSPORTS = new Set(['stdio', 'sse', 'streamable-http'])\n\nconst OFF_MESSAGE = 'Installs from clients are off on this server (allowRemoteInstalls is off).'\n\n/** An extension install that found other extensions in the source: `HandlerFailed`, the names found as its `data`. */\nexport class ExtensionInstallFailedError extends Error {\n readonly code = IpcErrorCode.HandlerFailed\n readonly data: ExtensionInstallErrorData\n constructor(message: string, data: ExtensionInstallErrorData) {\n super(message)\n this.name = 'ExtensionInstallFailedError'\n this.data = data\n }\n}\n\n/** The installer's error with the names it found carried as the call's error `data`; any other error as it is. */\nfunction withFoundNames(err: unknown): unknown {\n if (err instanceof ExtensionInstallError && err.candidates)\n return new ExtensionInstallFailedError(err.message, { installError: err.code, candidates: [...err.candidates] })\n return err\n}\n\n/** A spec a server may fetch: GitHub or npm. Anything path-like is refused before the parsers see it. */\nfunction checkSpec(spec: unknown): string {\n if (typeof spec !== 'string' || spec.trim() === '')\n throw new InvalidParamsError('spec must be a non-empty string.')\n const value = spec.trim()\n if (value.length > MAX_SPEC_LENGTH)\n throw new InvalidParamsError(`spec is longer than ${MAX_SPEC_LENGTH} characters.`)\n const segments = value.split(/[/:#@]/)\n if (/^(?:[./~\\\\]|file:)/i.test(value) || value.includes('\\\\') || segments.includes('.') || segments.includes('..'))\n throw new InvalidParamsError(`\"${value}\" is a path: a server installs from GitHub (owner/repo, a GitHub URL) or npm only.`)\n return value\n}\n\nfunction checkName(name: unknown, what: string): string {\n if (typeof name !== 'string' || !NAME_RE.test(name) || name === '.' || name === '..')\n throw new InvalidParamsError(`${what} must be a plain name (letters, digits, ., _, -, @).`)\n return name\n}\n\nfunction checkMcpName(name: unknown): string {\n if (!isMcpServerName(name))\n throw new InvalidParamsError('name must be a plain name (letters, digits, ., _, -, @, single spaces inside).')\n return name\n}\n\nfunction checkKind(kind: unknown): 'skill' | 'extension' {\n if (kind !== 'skill' && kind !== 'extension')\n throw new InvalidParamsError('kind must be \"skill\" or \"extension\".')\n return kind\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && Object.values(value).every(v => typeof v === 'string')\n}\n\nfunction checkMcpConfig(config: unknown): McpServerConfig {\n if (typeof config !== 'object' || config === null || Array.isArray(config))\n throw new InvalidParamsError('config must be an MCP server object.')\n if (JSON.stringify(config).length > MAX_MCP_CONFIG_BYTES)\n throw new InvalidParamsError(`config is larger than ${MAX_MCP_CONFIG_BYTES} bytes.`)\n const c = config as Record<string, unknown>\n checkMcpName(c.name)\n if (c.transport !== undefined && !MCP_TRANSPORTS.has(c.transport as string))\n throw new InvalidParamsError('transport must be stdio, sse or streamable-http.')\n const hasCommand = typeof c.command === 'string' && c.command.trim() !== ''\n let hasUrl = false\n if (typeof c.url === 'string') {\n try {\n hasUrl = ['http:', 'https:'].includes(new URL(c.url).protocol)\n }\n catch {}\n if (!hasUrl)\n throw new InvalidParamsError('url must be an http(s) URL.')\n }\n if (!hasCommand && !hasUrl)\n throw new InvalidParamsError('An MCP server needs a command (stdio) or a url.')\n if (c.args !== undefined && (!Array.isArray(c.args) || !c.args.every(a => typeof a === 'string')))\n throw new InvalidParamsError('args must be strings.')\n for (const key of ['env', 'headers'] as const) {\n if (c[key] !== undefined && !isStringRecord(c[key]))\n throw new InvalidParamsError(`${key} must map names to strings.`)\n }\n return c as unknown as McpServerConfig\n}\n\n/** The installer's progress lines, kept for the reply (at most 200). */\nfunction progressLines(): { progress: string[], onProgress: (line: string) => void } {\n const progress: string[] = []\n return {\n progress,\n onProgress: (line) => {\n if (progress.length < 200)\n progress.push(line)\n },\n }\n}\n\n/** How long a stopped install may take to roll back before the refusal is answered anyway. */\nconst ROLLBACK_GRACE_MS = 10_000\n\n/**\n * `run` bounded by `ms`: past it, its signal fires (children killed, no next\n * step: `abortableInstallIo`) and the refusal waits for the installer's own\n * rollback (staging dir, transactional target), up to {@link ROLLBACK_GRACE_MS}.\n */\nasync function bounded<T>(run: (signal: AbortSignal) => Promise<T>, ms: number, what: string): Promise<T> {\n const controller = new AbortController()\n const work = run(controller.signal)\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([work, new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.abort()\n reject(new Error(`${what} took longer than ${Math.round(ms / 1000)}s and was stopped.`))\n }, ms)\n })])\n }\n catch (err) {\n if (controller.signal.aborted) {\n let grace: ReturnType<typeof setTimeout> | undefined\n await Promise.race([work.catch(() => undefined), new Promise((resolve) => {\n grace = setTimeout(resolve, ROLLBACK_GRACE_MS)\n })])\n clearTimeout(grace)\n }\n throw err\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Gate, run, audit a client's install: refused unless the host takes them\n * (`allowRemoteInstalls`); every attempt leaves one line, refusals and\n * failures included.\n */\nexport async function guardedInstall<T>(options: RemoteInstallsOptions | undefined, peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> {\n if (!options)\n throw new Error('This host takes no installs from clients (a zidane-server does, with allowRemoteInstalls on).')\n if (!options.allowed()) {\n options.audit?.(peer, { event, ...fields, ok: false, refused: 'allowRemoteInstalls is off' })\n throw new Error(OFF_MESSAGE)\n }\n try {\n const result = await run()\n options.audit?.(peer, { event, ...fields, ok: true })\n return result\n }\n catch (err) {\n options.audit?.(peer, { event, ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n}\n\nexport function createCatalogInstallHandlers({ host, env, broadcast, setSettings, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'workspace' | 'mcpServers'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** `settings.set`: writes, rebuilds what the change needs, tells every window. */\n setSettings: (patch: Partial<HostSettings>) => unknown\n options?: RemoteInstallsOptions\n}): Handlers<InstallMethod> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const io = options?.io\n const prefix = (): string => env.config.prefix\n /** The host user's roots for `subPath` (`~/.agents/<sub>`, `~/.<prefix>/<sub>`), read at call time. */\n const userRoots = (subPath: string): string[] =>\n projectUserPaths({ subPath, cwd: homedir(), home: homedir(), prefix: prefix() }).filter(p => p.source === 'user').map(p => p.path)\n\n const guarded = <T>(peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> =>\n guardedInstall(options, peer, event, fields, run)\n\n const changed = (catalog: HostCatalogName): void => broadcast({ kind: 'catalog:changed', catalog })\n\n /** Skills and MCP servers are read when an agent is built. */\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n /** Extensions live in the runtime registry: forget it, rebuild, dispose the old one once idle (as `runtime.reload`). */\n const reloadExtensions = (): void => {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n\n /** `name` dropped from (or added to) an explicit allowlist; an absent list means \"all\", left alone. */\n const allowlist = (key: 'enabledExtensions' | 'enabledSkills', name: string, present: boolean): boolean => {\n const list = env.readSettings()[key]\n if (list === undefined || list.includes(name) === present)\n return false\n setSettings({ [key]: present ? [...list, name] : list.filter(n => n !== name) })\n return true\n }\n\n /** The user-scope install directory named `name` under `subPath`, if any. */\n const userDir = (subPath: string, name: string, marker?: string): string | undefined =>\n userRoots(subPath).map(root => join(root, name)).find(dir => existsSync(marker ? join(dir, marker) : dir))\n\n return {\n 'catalog.install': (p, peer) => guarded(peer, 'catalog.install', { kind: p.kind, spec: typeof p.spec === 'string' ? p.spec.slice(0, MAX_SPEC_LENGTH) : undefined }, async () => {\n const kind = checkKind(p.kind)\n const spec = checkSpec(p.spec)\n if (p.scope !== undefined && p.scope !== 'user')\n throw new InvalidParamsError('A server installs in its user scope only (scope: \"user\").')\n const { progress, onProgress } = progressLines()\n const home = homedir()\n if (kind === 'skill') {\n const result = await bounded(signal => installSkillFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(Array.isArray(p.skills) ? { skills: p.skills.filter(s => typeof s === 'string') } : {}),\n ...(p.all === true ? { all: true } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n rebuild()\n changed('skills')\n const skipped = result.skipped?.length ? `. Skipped existing: ${result.skipped.join(', ')}` : ''\n return { installed: [...result.installed], message: `installed ${result.installed.join(', ')} (${result.provenance ?? result.engine})${skipped}`, progress }\n }\n let result\n try {\n result = await bounded(signal => installExtensionFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(typeof p.extension === 'string' ? { extension: p.extension } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n }\n catch (err) {\n if (err instanceof ExtensionInstallError && err.code === 'exists')\n throw new Error('already installed on the server: update or remove it first.')\n throw withFoundNames(err)\n }\n // Enabled in an explicit allowlist (that write reloads the registry); else reload here.\n if (!allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n const warn = result.warnings.length > 0 ? `. ${result.warnings.join('. ')}` : ''\n return { installed: [result.name], message: `installed \"${result.name}\" (${result.provenance})${warn}`, progress }\n }),\n\n 'catalog.remove': (p, peer) => guarded(peer, 'catalog.remove', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill') {\n const dir = userDir('skills', name, 'SKILL.md')\n if (!dir)\n throw new Error(`No user-scope skill \"${name}\" on this server (project skills are files in their folder).`)\n rmSync(dir, { recursive: true, force: true })\n allowlist('enabledSkills', name, false)\n rebuild()\n changed('skills')\n return { removed: name, message: `deleted \"${name}\"` }\n }\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n removeInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix() })\n if (!allowlist('enabledExtensions', name, false))\n reloadExtensions()\n changed('extensions')\n return { removed: name, message: `removed \"${name}\"` }\n }),\n\n 'catalog.update': (p, peer) => guarded(peer, 'catalog.update', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill')\n throw new Error('Skills are not updated in place: install again with overwrite.')\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n const result = await bounded(signal => updateInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix(), io: abortableInstallIo(io, signal) }), timeoutMs, `Updating ${name}`)\n if (result.upToDate)\n return { updated: result.name, upToDate: true, message: `\"${result.name}\" is already up to date${result.commit ? ` (${result.commit.slice(0, 7)})` : ''}` }\n reloadExtensions()\n changed('extensions')\n return { updated: result.name, upToDate: false, message: `updated \"${result.name}\" → ${result.provenance}` }\n }),\n\n 'extensions.changeOrigin': (p, peer) => guarded(peer, 'extensions.changeOrigin', { name: p.name, spec: typeof p.source === 'string' ? p.source.slice(0, MAX_SPEC_LENGTH) : undefined }, async () => {\n const name = checkName(p.name, 'name')\n const spec = checkSpec(p.source)\n if (p.scope !== 'user')\n throw new InvalidParamsError('A server changes its user-scope extensions only (scope: \"user\").')\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n const { progress, onProgress } = progressLines()\n const result = await bounded(signal => changeExtensionOrigin({ dir, source: spec, cwd: homedir(), home: homedir(), prefix: prefix(), onProgress, io: abortableInstallIo(io, signal) }), timeoutMs, `Installing ${name} from ${spec}`)\n .catch((err: unknown) => {\n throw withFoundNames(err)\n })\n reloadExtensions()\n changed('extensions')\n const warn = result.warnings.length > 0 ? `. ${result.warnings.join('. ')}` : ''\n return { name: result.name, origin: result.origin, message: `\"${result.name}\" now comes from ${result.origin.label} (${result.provenance})${warn}`, progress }\n }),\n\n 'mcp.upsert': (p, peer) => guarded(peer, 'mcp.upsert', { name: (p.config as { name?: unknown } | undefined)?.name, scope: p.scope ?? 'user' }, () => {\n const config = checkMcpConfig(p.config)\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n if (p.clientSecret !== undefined && (typeof p.clientSecret !== 'string' || p.clientSecret.length > MAX_MCP_CONFIG_BYTES))\n throw new InvalidParamsError('clientSecret must be a string.')\n if (p.scope === 'project' && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project MCP server needs the project\\'s cwd.')\n // The project's checkout, which must lie in the roots too.\n const folder = p.scope === 'project' ? host.workspace.resolveFolder(p.cwd!) : homedir()\n const cwd = p.scope === 'project' ? host.workspace.resolveFolder(findGitRoot(folder) ?? folder) : folder\n const result = upsertMcpServer(mcpsWritePath(p.scope ?? 'user', { home: homedir(), cwd, prefix: prefix() }), config)\n const store = env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir())\n // The secret stays out of mcps.json; an entry without an oauth client must not keep sending one.\n if (!config.oauth)\n saveMcpClientSecret(store, config.name, undefined)\n else if (p.clientSecret)\n saveMcpClientSecret(store, config.name, p.clientSecret)\n // Added from a client: on, like a server added in local Settings. An edit keeps its toggle.\n const enabled = result.action === 'added' ? enabledMcpsWith(env.readSettings().enabledMcps, config.name) : undefined\n if (enabled)\n setSettings({ enabledMcps: enabled })\n // An edited server must not keep running on its old config.\n host.mcpServers.retire(config.name)\n rebuild()\n changed('mcps')\n return { name: config.name, created: result.action === 'added' }\n }),\n\n 'mcp.remove': (p, peer) => guarded(peer, 'mcp.remove', { name: p.name }, () => {\n const name = checkMcpName(p.name)\n const path = mcpsWritePath('user', { home: homedir(), cwd: homedir(), prefix: prefix() })\n try {\n removeMcpServer(path, name)\n }\n catch (err) {\n // No file, or no entry of that name: nothing to remove. A malformed file is an error.\n if (!existsSync(path) || /no entry named/.test(err instanceof Error ? err.message : ''))\n return { removed: false }\n throw err\n }\n const enabled = enabledMcpsWithout(env.readSettings().enabledMcps, name)\n if (enabled)\n setSettings({ enabledMcps: enabled })\n host.mcpServers.retire(name)\n rebuild()\n changed('mcps')\n return { removed: true }\n }),\n\n 'extensions.create': (p, peer) => guarded(peer, 'extensions.create', { name: p.name, scope: p.scope ?? 'user' }, () => {\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n const project = p.scope === 'project'\n if (project && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project extension needs the project\\'s cwd.')\n const result = createExtension({ name: typeof p.name === 'string' ? p.name : '', ...(project ? { scope: 'project', cwd: p.cwd } : {}) }, {\n userDir: join(homedir(), prefix()),\n // The checkout holding `cwd`, which must lie in the roots too: the session that writes the extension works there.\n resolveCheckoutRoot: (cwd) => {\n const folder = host.workspace.resolveFolder(cwd)\n return host.workspace.resolveFolder(findGitRoot(folder) ?? folder)\n },\n })\n // A project extension loads once its project is trusted; a user one is enabled now.\n if (project || !allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n return result\n }),\n\n }\n}\n\n/** For `ipc.hello`: installs are offered when the server allows them. */\nexport function remoteInstallsAllowed(options: RemoteInstallsOptions | undefined): boolean {\n return options?.allowed() === true\n}\n","/**\n * Who or what a text block of a user turn comes from, when it is not the\n * session's own user typing in a window. Dependency-free, like\n * `thinking-levels.ts`, so any surface can read and check it.\n */\n\n/** Where a text block came from: the {@link SessionContentBlock} text member's `origin`. Absent: the session's own user. */\nexport interface TextOrigin {\n /** 'user': the session's user, through another surface; 'signal': someone else (a channel participant); 'event': something that happened (orchestration, a webhook). */\n kind: 'user' | 'signal' | 'event'\n /** Where it came from: 'slack', 'github', 'orchestration'… */\n source: string\n /** Who, when known: a provider id and a display name. */\n sender?: { id: string, name?: string }\n /** The client's id for this message (see clientMessageId), so a client can find it in the transcript after a restart. */\n messageId?: string\n}\n\n/** Longest string a {@link TextOrigin} field may hold. */\nconst MAX_FIELD_CHARS = 1024\n\nconst TEXT_ORIGIN_KINDS: readonly string[] = ['user', 'signal', 'event'] satisfies readonly TextOrigin['kind'][]\n\nfunction isField(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= MAX_FIELD_CHARS\n}\n\n/**\n * Type guard for a {@link TextOrigin} read off the wire: a known `kind`, a\n * non-empty `source`, and well-formed optional fields, each string at most\n * 1024 characters.\n *\n * @param value - Any value, usually a peer's request param.\n */\nexport function isTextOrigin(value: unknown): value is TextOrigin {\n if (!value || typeof value !== 'object')\n return false\n const { kind, source, sender, messageId } = value as Record<string, unknown>\n if (typeof kind !== 'string' || !TEXT_ORIGIN_KINDS.includes(kind) || !isField(source))\n return false\n if (messageId !== undefined && !isField(messageId))\n return false\n if (sender === undefined)\n return true\n if (!sender || typeof sender !== 'object')\n return false\n const { id, name } = sender as Record<string, unknown>\n return isField(id) && (name === undefined || isField(name))\n}\n","/**\n * Idempotent sends: the optional `requestId` of `chat.send`,\n * `chat.pushQueued` and `queue.add`.\n *\n * A client that lost a send's reply retries with the same `requestId`. Per\n * session, the first send with an id runs; a later one with the same id and\n * the same content gets the first one's result without running again, and\n * one with other content is refused. The claim and the result live in the\n * session store (`claimSendRequest`), so this holds across a host restart.\n *\n * - A duplicate of a send still running in this process waits for it and\n * gets its result (or its error).\n * - A send that failed drops its claim: nothing ran, so the retry runs.\n * - A claim with no result and no send running here (still running in another\n * process, or its process died before it settled) answers\n * {@link SendRequestPendingError}: the prompt may have been accepted, so it\n * is not submitted again.\n * - If dropping a failed send's claim fails too, this process remembers it, so\n * a retry here still runs.\n * - A store without `claimSendRequest` deduplicates in this process only.\n */\nimport type { SessionStore } from '../../session'\nimport type { SendRequestClaim } from '../../session/send-requests'\nimport type { JsonValue } from '../../types'\nimport { createHash } from 'node:crypto'\nimport { createSendRequestBook } from '../../session/send-requests'\nimport { InvalidParamsError } from './handlers/params'\n\n/** Longest `requestId` accepted (a UUID is 36 characters). */\nconst MAX_REQUEST_ID_LENGTH = 128\n\n/** Params that never change what a send submits: left out of its fingerprint. */\nconst NOT_CONTENT = new Set(['sessionId', 'requestId', 'keepDraft', 'wake'])\n\n/** A retried `requestId` whose first send was accepted but has not settled (still running elsewhere, or its host stopped first). */\nexport class SendRequestPendingError extends Error {\n constructor(requestId: string) {\n super(`Send request \"${requestId}\" was already accepted; its outcome is unknown (it may still be running in another host process, or its host stopped before it settled), so it was not submitted again.`)\n this.name = 'SendRequestPendingError'\n }\n}\n\nexport interface SendDedup {\n /** Run `call` for the send `params` of `method`, or answer the first outcome of its `requestId`. Without one, just runs `call`. */\n run: <T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>) => Promise<T>\n /** The content hash a send's `requestId` is bound to. */\n fingerprint: (method: string, params: object) => string\n}\n\nexport function createSendDedup({ store }: { store: SessionStore }): SendDedup {\n const local = createSendRequestBook()\n const claim = async (sessionId: string, requestId: string, fp: string): Promise<SendRequestClaim> =>\n store.claimSendRequest ? store.claimSendRequest(sessionId, requestId, fp) : local.claim(sessionId, requestId, fp)\n const settle = async (sessionId: string, requestId: string, result: JsonValue | null): Promise<void> => {\n if (store.settleSendRequest)\n await store.settleSendRequest(sessionId, requestId, result)\n else\n local.settle(sessionId, requestId, result)\n }\n /** Sends running here, by `sessionId \\0 requestId`: a duplicate waits for the first. */\n const running = new Map<string, { fingerprint: string, outcome: Promise<unknown> }>()\n /** Failed sends whose claim could not be dropped from the store, by key: a retry here runs anyway. */\n const failedHere = new Set<string>()\n\n const fingerprint = (method: string, params: object): string => {\n const content = Object.fromEntries(Object.entries(params).filter(([key]) => !NOT_CONTENT.has(key)))\n return createHash('sha256').update(stableJson({ method, ...content })).digest('hex')\n }\n\n const refuse = (requestId: string): never => {\n throw new InvalidParamsError(`requestId \"${requestId}\" was already used for a different send in this session; use a new requestId for new content.`)\n }\n\n return {\n fingerprint,\n async run<T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n const { sessionId, requestId } = params\n if (requestId === undefined)\n return call()\n if (typeof requestId !== 'string' || requestId.length === 0 || requestId.length > MAX_REQUEST_ID_LENGTH)\n throw new InvalidParamsError(`requestId must be a non-empty string of at most ${MAX_REQUEST_ID_LENGTH} characters.`)\n const fp = fingerprint(method, params)\n const key = `${sessionId}\\0${requestId}`\n\n const live = running.get(key)\n if (live) {\n if (live.fingerprint !== fp)\n refuse(requestId)\n return live.outcome as Promise<T>\n }\n\n // Registered before the first await, so a concurrent duplicate waits\n // here instead of racing the store claim.\n const outcome = (async () => {\n const claimed = await claim(sessionId, requestId, fp)\n if (!claimed.claimed) {\n if (claimed.record.fingerprint !== fp)\n refuse(requestId)\n if (claimed.record.result !== undefined)\n return claimed.record.result as T\n if (!failedHere.has(key))\n throw new SendRequestPendingError(requestId)\n }\n failedHere.delete(key)\n let result: T\n try {\n result = await call()\n }\n catch (err) {\n // Nothing ran: drop the claim so a retry runs. Retried once; if it still fails, a retry here re-runs anyway.\n const dropped = await settle(sessionId, requestId, null).then(() => true, () => false)\n || await settle(sessionId, requestId, null).then(() => true, () => false)\n if (!dropped)\n failedHere.add(key)\n throw err\n }\n // The send ran: a store failure here must not turn it into an error the client would retry.\n await settle(sessionId, requestId, result as JsonValue).catch(() => undefined)\n return result\n })()\n running.set(key, { fingerprint: fp, outcome })\n try {\n return await outcome\n }\n finally {\n running.delete(key)\n }\n },\n }\n}\n\nconst dedupByStore = new WeakMap<SessionStore, SendDedup>()\n\n/** The one dedup of `store`: every send method of a host shares it (and its in-process waits). */\nexport function sendDedupFor(store: SessionStore): SendDedup {\n let dedup = dedupByStore.get(store)\n if (!dedup) {\n dedup = createSendDedup({ store })\n dedupByStore.set(store, dedup)\n }\n return dedup\n}\n\n/** `dedup.run`, or just `call` without a dedup. */\nexport async function deduped<T>(dedup: SendDedup | undefined, method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n return dedup ? dedup.run(method, params, call) : call()\n}\n\n/** JSON with object keys sorted, so a fingerprint does not depend on key order. */\nfunction stableJson(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) => {\n if (!v || typeof v !== 'object' || Array.isArray(v))\n return v\n return Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)))\n })\n}\n","/** Runs: send, interrupt, steer, follow-up, running work, and slash-command discovery. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SendTransform } from '../../../chat/host/prompt-transforms'\nimport type { QueuedPromptFields } from '../../../chat/host/signals'\nimport type { TextOrigin } from '../../../text-origin'\nimport type { SendOptions } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { createPromptSubmissions } from '../../../chat/host/prompt-transforms'\nimport { isTextOrigin } from '../../../text-origin'\nimport { deduped } from '../send-requests'\nimport { InvalidParamsError } from './params'\n\ntype ChatMethod\n = | 'chat.send' | 'chat.interrupt' | 'chat.steer' | 'chat.followUp' | 'chat.pushQueued'\n | 'chat.isRunning' | 'chat.rebuildAgent' | 'chat.listWork' | 'chat.cancelWork'\n | 'commands.list' | 'commands.completeArgs'\n\nexport function createChatHandlers({ host, clearDraft, dedup, transforms }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n /** The extensions' prompt transforms of the session's folder (`ChatHost.transformPrompt`). Absent: prompts go as sent. */\n transforms?: SendTransform\n}): Handlers<ChatMethod> {\n // Each submission is transformed once, here: or handed to the live run, or dropped when an extension consumed it.\n const submit = createPromptSubmissions(host, transforms)\n const send = (opts: SendOptions) => submit.send(opts)\n return {\n 'chat.send': async (p, peer) => {\n // `wake` is host-internal: a wire peer must not run a session with\n // the `user-prompt` broadcast suppressed (params are unchecked JSON\n // — the Omit<> in the method type is not a runtime guarantee).\n const { wake: _stripped, keepDraft, requestId: _id, origin: _origin, literal: _literal, clientMessageId: _clientMessageId, metadata: _metadata, ...params } = p as SendOptions & { requestId?: string }\n const result = await deduped(dedup, 'chat.send', p, () => send({ ...params, ...promptFields(p) }))\n // A composer submit consumed the shared draft — clear it everywhere\n // else (the sender's input is already empty; excluding it means a user\n // already typing their NEXT message is never clobbered). A prompt sent\n // from elsewhere (Continue, Retry, the palette) did not.\n if (!keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.interrupt': p => host.interrupt(p.sessionId),\n 'chat.steer': p => submit.steer(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.followUp': p => submit.followUp(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.pushQueued': async (p, peer) => {\n const result = await deduped(dedup, 'chat.pushQueued', p, () => submit.pushQueued(p.sessionId, p.message, p.activatedSkills, promptFields(p)))\n if (!p.keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.isRunning': p => host.isSessionRunning(p.sessionId),\n 'chat.rebuildAgent': p => host.disposeAgentForRebuild(p.sessionId),\n 'chat.listWork': p => host.listRunningWork(p.sessionId, p.children === true ? { children: true } : undefined),\n 'chat.cancelWork': p => host.cancelRunningWork(p.sessionId, p.id, p.reason),\n\n 'commands.list': p => host.listCommands(p.cwd, typeof p.kind === 'string' ? p.kind : undefined),\n 'commands.completeArgs': p => host.completeCommandArgs(p.cwd, p.name, p.argsPrefix, typeof p.kind === 'string' ? p.kind : undefined),\n }\n}\n\n/** A peer's `origin` / `literal` / `clientMessageId` / `metadata` params, checked (params are unchecked JSON): a malformed origin, id or metadata is refused. */\nexport function promptFields(p: { origin?: unknown, literal?: unknown, clientMessageId?: unknown, metadata?: unknown }): QueuedPromptFields {\n if (p.origin !== undefined && !isTextOrigin(p.origin))\n throw new InvalidParamsError('origin: must be { kind: \\'user\\' | \\'signal\\' | \\'event\\', source, sender?: { id, name? }, messageId? } with non-empty strings of at most 1024 characters.')\n const id = clientMessageId(p.clientMessageId)\n const metadata = promptMetadata(p.metadata)\n return {\n ...(p.origin !== undefined ? { origin: knownOriginFields(p.origin) } : {}),\n ...(p.literal === true ? { literal: true } : {}),\n ...(id !== undefined ? { clientMessageId: id } : {}),\n ...(metadata ? { metadata } : {}),\n }\n}\n\n/** Largest `metadata` a peer may send with a prompt, as JSON. */\nconst MAX_PROMPT_METADATA_BYTES = 64 * 1024\n\n/** A peer's prompt `metadata`, checked: absent, or a JSON object of at most 64 KiB. */\nfunction promptMetadata(value: unknown): QueuedPromptFields['metadata'] {\n if (value === undefined)\n return undefined\n if (!value || typeof value !== 'object' || Array.isArray(value))\n throw new InvalidParamsError('metadata: must be a JSON object.')\n const json = JSON.stringify(value)\n if (json.length > MAX_PROMPT_METADATA_BYTES)\n throw new InvalidParamsError(`metadata: must be at most ${MAX_PROMPT_METADATA_BYTES} bytes as JSON.`)\n const parsed = JSON.parse(json) as Record<string, never>\n return Object.keys(parsed).length > 0 ? parsed : undefined\n}\n\n/** A checked origin with only its known fields: it is stored with the turn, so a peer's extra keys are not. */\nfunction knownOriginFields({ kind, source, sender, messageId }: TextOrigin): TextOrigin {\n return {\n kind,\n source,\n ...(sender ? { sender: { id: sender.id, ...(sender.name !== undefined ? { name: sender.name } : {}) } } : {}),\n ...(messageId !== undefined ? { messageId } : {}),\n }\n}\n\n/** A peer's `clientMessageId`, checked: absent, or a non-empty string of at most 256 characters. */\nfunction clientMessageId(value: unknown): string | undefined {\n if (value === undefined)\n return undefined\n if (typeof value !== 'string' || value.length === 0 || value.length > 256)\n throw new InvalidParamsError('clientMessageId: must be a non-empty string of at most 256 characters.')\n return value\n}\n","/**\n * What a host keeps for its clients' apps in its `state.json`, so a web app\n * finds it again in any browser: the picks remembered across apps\n * (`prefs.*`: effort and options per model, the next chat's model chain)\n * and the sidebar's view (`sidebar.*`: each space's filters, checked by the\n * client when read, and the space on show).\n */\nimport type { HostComposerPrefs } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { isThinkingLevel } from '../../../types'\nimport { InvalidParamsError } from './params'\n\ntype ClientStateMethod = 'prefs.get' | 'prefs.set' | 'sidebar.getViews' | 'sidebar.setView' | 'sidebar.getSpace' | 'sidebar.setSpace'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Each pref's shape: `state.json` is read by every app on the host, a client's junk must not reach it. */\nconst PREF_CHECKS: { [K in keyof Required<HostComposerPrefs>]: (value: unknown) => boolean } = {\n lastEffortByModel: v => isRecord(v) && Object.values(v).every(isThinkingLevel),\n lastModelOptionsByModel: v => isRecord(v) && Object.values(v).every(options => isRecord(options) && Object.values(options).every(on => typeof on === 'boolean')),\n lastModelChain: v => Array.isArray(v) && v.every(entry => isRecord(entry) && typeof entry.provider === 'string' && typeof entry.model === 'string' && (entry.account === undefined || typeof entry.account === 'string')),\n}\nconst PREF_KEYS = Object.keys(PREF_CHECKS) as (keyof HostComposerPrefs)[]\n\n/** Space ids are short slugs (`default`, `space-1`). */\nconst MAX_SPACE_ID = 200\n/** A view is five short fields. */\nconst MAX_VIEW_JSON = 4096\n/** Spaces with a saved view; a client can't grow `state.json` without bound. */\nconst MAX_VIEWS = 100\n\nfunction spaceIdOf(value: unknown): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_SPACE_ID)\n throw new InvalidParamsError(`spaceId must be a non-empty string of at most ${MAX_SPACE_ID} characters.`)\n return value\n}\n\nexport function createClientStateHandlers({ env }: { env: Pick<DaemonEnvironment, 'config'> }): Handlers<ClientStateMethod> {\n const { stateStore } = env.config\n return {\n 'prefs.get': () => {\n const state = stateStore.load()\n const prefs: HostComposerPrefs = Object.fromEntries(PREF_KEYS.flatMap(key => (state[key] === undefined ? [] : [[key, state[key]]])))\n return Object.keys(prefs).length > 0 ? prefs : null\n },\n 'prefs.set': (p) => {\n const patch: unknown = p.patch\n if (!isRecord(patch))\n throw new InvalidParamsError('patch must be an object.')\n const bad = PREF_KEYS.find(key => key in patch && !PREF_CHECKS[key](patch[key]))\n if (bad)\n throw new InvalidParamsError(`patch.${bad} has the wrong shape.`)\n stateStore.save({ ...stateStore.load(), ...Object.fromEntries(PREF_KEYS.flatMap(key => (key in patch ? [[key, patch[key]]] : []))) })\n },\n 'sidebar.getViews': () => stateStore.load().sidebarViews ?? {},\n 'sidebar.setView': (p) => {\n const spaceId = spaceIdOf(p.spaceId)\n if (!isRecord(p.view))\n throw new InvalidParamsError('view must be an object.')\n if (JSON.stringify(p.view).length > MAX_VIEW_JSON)\n throw new InvalidParamsError(`view must be at most ${MAX_VIEW_JSON} characters of JSON.`)\n const state = stateStore.load()\n const views = state.sidebarViews ?? {}\n if (!(spaceId in views) && Object.keys(views).length >= MAX_VIEWS)\n throw new Error(`This host keeps the views of ${MAX_VIEWS} spaces at most.`)\n stateStore.save({ ...state, sidebarViews: { ...views, [spaceId]: p.view } })\n },\n 'sidebar.getSpace': () => stateStore.load().sidebarSpaceId ?? null,\n 'sidebar.setSpace': (p) => {\n const sidebarSpaceId = spaceIdOf(p.spaceId)\n stateStore.save({ ...stateStore.load(), sidebarSpaceId })\n },\n }\n}\n","/** What a session's model sees: context breakdown and segments, the session's system prompt override, and its prompt cache. */\nimport type { CacheImpactChange, ChatHost } from '../../../chat/host/engine'\nimport type { ThinkingLevel } from '../../../types'\nimport type { Handlers } from './types'\nimport { THINKING_LEVELS } from '../../../types'\nimport { InvalidParamsError, nonNegativeInt, optionalString } from './params'\n\nexport function createContextHandlers({ host }: { host: ChatHost }): Handlers<'sessions.contextBreakdown' | 'sessions.contextSegments' | 'sessions.createSystemOverride' | 'sessions.systemMd' | 'sessions.cacheImpact' | 'sessions.cacheReport'> {\n return {\n 'sessions.systemMd': p => host.sessionSystemMd(p.sessionId),\n 'sessions.contextSegments': p => host.getContextSegments(p.sessionId),\n 'sessions.createSystemOverride': p => host.createSystemOverride(p.sessionId),\n 'sessions.contextBreakdown': p => host.getContextBreakdown(p.sessionId),\n 'sessions.cacheImpact': p => host.cacheImpact(p.sessionId, cacheImpactChange(p.change)),\n 'sessions.cacheReport': p => host.cacheReport(p.sessionId, nonNegativeInt(p.limit, 'limit')),\n }\n}\n\nfunction cacheImpactChange(value: unknown): CacheImpactChange {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n throw new InvalidParamsError('change must be an object.')\n const raw = value as Record<string, unknown>\n const change: CacheImpactChange = {}\n const modelId = optionalString(raw.modelId, 'change.modelId')\n const providerKey = optionalString(raw.providerKey, 'change.providerKey')\n const agentId = optionalString(raw.agentId, 'change.agentId')\n const effort = optionalString(raw.effort, 'change.effort')\n if (effort !== undefined && !(THINKING_LEVELS as readonly string[]).includes(effort))\n throw new InvalidParamsError('change.effort must be a thinking level.')\n if (modelId !== undefined)\n change.modelId = modelId\n if (providerKey !== undefined)\n change.providerKey = providerKey\n if (agentId !== undefined)\n change.agentId = agentId\n if (effort !== undefined)\n change.effort = effort as ThinkingLevel\n return change\n}\n","/** The daemon process itself: identity, the processes it started for its own work and for each session, and shutdown. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HelloResult } from '../../protocol'\nimport type { Handlers } from './types'\nimport { listOwnedProcesses } from '../../../contexts/owned-processes'\nimport { listSessionProcesses } from '../../../contexts/session-processes'\nimport { IPC_PROTOCOL_VERSION } from '../../protocol'\n\nexport function createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity }: {\n host: ChatHost\n appVersion: string\n startedAt: number\n lifecycle: { shutdown: () => void, retireWhenIdle: () => void, isRetiring?: () => boolean }\n /** The host identity fields `ipc.hello` reports. */\n identity: Pick<HelloResult, 'hostId' | 'hostKind' | 'hostName'>\n}): Handlers<'daemon.info' | 'daemon.ownedProcesses' | 'daemon.sessionProcesses' | 'daemon.shutdown'> {\n return {\n 'daemon.info': (): HelloResult => ({\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion,\n pid: process.pid,\n startedAt,\n ...identity,\n activeWork: host.hasActiveRuns(),\n // Live, unlike the hello: a daemon starts retiring after windows attached (a newer install landed).\n ...(lifecycle.isRetiring?.() ? { retiring: true } : {}),\n }),\n 'daemon.ownedProcesses': () => listOwnedProcesses(),\n 'daemon.sessionProcesses': () => listSessionProcesses(),\n 'daemon.shutdown': async (p) => {\n // Version-skew retirement never aborts live work: exit once idle.\n if (p?.whenIdle === true && host.hasActiveWork()) {\n lifecycle.retireWhenIdle()\n return { deferred: true }\n }\n // Reply first (return), then drain on the next tick.\n setImmediate(lifecycle.shutdown)\n },\n }\n}\n","/**\n * Shared per-session composer state: prompt drafts, draft attachments, and\n * transcript-search state, synced across windows. Ephemeral by design —\n * in-memory only, cleared when any window submits, gone on daemon restart.\n */\nimport type { HostSignal, PromptAttachment } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\ninterface DraftEntry { text?: string, shell?: boolean, attachments?: PromptAttachment[], search?: { active: boolean, query: string } }\n\n/**\n * Bound a peer-supplied attachment list: shape-guarded entries only,\n * 24 MiB of base64 per list. Shared by `queue.add` and\n * `drafts.setAttachments`.\n */\nexport function boundAttachments(list: unknown[]): PromptAttachment[] {\n let budget = 24 * 1024 * 1024\n const out: PromptAttachment[] = []\n for (const entry of list) {\n const a = entry as Partial<PromptAttachment>\n if (typeof a?.mediaType !== 'string' || typeof a?.data !== 'string')\n continue\n budget -= a.data.length\n if (budget < 0)\n break\n // Names render in every window's UI — cap them so a hostile peer\n // can't pin megabytes of \"name\" per attachment.\n out.push({ mediaType: a.mediaType, data: a.data, ...(typeof a.name === 'string' ? { name: a.name.slice(0, 256) } : {}) })\n }\n return out\n}\n\nexport function createDraftHandlers({ broadcastExcept }: {\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'>\n /** Consume the draft after a submit — every window except the sender clears. */\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** The session was deleted: drop its draft silently. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared per-session prompt drafts. Ephemeral by design — in-memory\n * only, cleared when any window submits, gone on daemon restart.\n */\n const drafts = new Map<string, DraftEntry>()\n\n /** Total base64 bytes currently pinned by ALL draft attachments. */\n function draftAttachmentBytes(): number {\n let total = 0\n for (const entry of drafts.values()) {\n for (const attachment of entry.attachments ?? [])\n total += attachment.data.length\n }\n return total\n }\n\n function clearDraft(sessionId: string, origin: HostPeer | null): void {\n const entry = drafts.get(sessionId)\n if (!entry)\n return\n drafts.delete(sessionId)\n if (entry.text)\n broadcastExcept(origin, { kind: 'draft:changed', sessionId, text: '' })\n if (entry.attachments?.length)\n broadcastExcept(origin, { kind: 'draft:attachments', sessionId, attachments: [] })\n }\n\n /** Drop empty draft entries so the map only holds live composing state. */\n function compactDraft(sessionId: string, entry: DraftEntry): void {\n if (!entry.text && !entry.shell && !entry.attachments?.length && !entry.search?.active)\n drafts.delete(sessionId)\n else\n drafts.set(sessionId, entry)\n }\n\n const methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'> = {\n 'drafts.get': (p) => {\n const entry = drafts.get(p.sessionId)\n return {\n text: entry?.text ?? '',\n ...(entry?.shell ? { shell: true } : {}),\n ...(entry?.attachments?.length ? { attachments: entry.attachments } : {}),\n ...(entry?.search?.active ? { search: entry.search } : {}),\n }\n },\n 'drafts.set': (p, peer) => {\n // Bound the ephemeral draft store: a buggy/looping client must not\n // grow daemon memory without limit (drafts only evict on submit or\n // session delete). 64 KiB is far above any real prompt.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n // When the cap actually truncated, INCLUDE the origin in the fan-out\n // so its local buffer converges to the stored truth — otherwise the\n // origin silently diverges from what every other window (and a\n // remote submit) sees.\n const truncated = typeof p.text === 'string' && p.text.length > text.length\n // Also bound the KEY count: drafts only evict on submit / session\n // delete, so a client writing under many bogus session ids could\n // otherwise grow the map unbounded. 256 concurrent drafts is far\n // beyond any real multi-window session set.\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.text = text.length > 0 ? text : undefined\n // Shell mode rides out of band — never sniffed from the text.\n entry.shell = p.shell === true ? true : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(truncated ? null : peer, { kind: 'draft:changed', sessionId: p.sessionId, text, ...(p.shell === true ? { shell: true } : {}) })\n },\n 'search.set': (p, peer) => {\n // Shared transcript-search state — same lifecycle + caps as drafts.\n const active = p.active === true\n const query = typeof p.query === 'string' ? p.query.slice(0, 4 * 1024) : ''\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.search = active || query.length > 0 ? { active, query } : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'search:changed', sessionId: p.sessionId, active, query })\n },\n 'drafts.setAttachments': (p, peer) => {\n /*\n * Composing attachments (payloads included, so a remote window can\n * submit the shared draft attachments-and-all). Bounded three ways:\n * shape-guarded entries, 24 MiB of base64 per session, and a 96 MiB\n * GLOBAL budget across every draft — the per-session cap times the\n * 256-key cap would otherwise let a looping client pin gigabytes.\n */\n const bounded = Array.isArray(p.attachments) ? boundAttachments(p.attachments) : []\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const current = drafts.get(p.sessionId)?.attachments ?? []\n const currentBytes = current.reduce((sum, a) => sum + a.data.length, 0)\n const incomingBytes = bounded.reduce((sum, a) => sum + a.data.length, 0)\n if (draftAttachmentBytes() - currentBytes + incomingBytes > 96 * 1024 * 1024)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.attachments = bounded.length > 0 ? bounded : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'draft:attachments', sessionId: p.sessionId, attachments: bounded })\n },\n }\n\n return {\n methods,\n clearDraft,\n forget: (sessionId) => {\n drafts.delete(sessionId)\n },\n }\n}\n","/** Execution environments: the catalog, verification, settings, and a session's provisioning and actions. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handler, Handlers } from './types'\nimport { applyEnvironmentSettingsChange } from '../../../chat/environment-settings'\nimport { loadOrThrow } from './session-load'\n\ntype EnvironmentMethod\n = | 'environments.list' | 'environments.verify' | 'environments.update'\n | 'sessions.retryEnvironment' | 'sessions.moveEnvironment' | 'sessions.environmentActions' | 'sessions.runEnvironmentAction'\n\nexport function createEnvironmentHandlers({ host, env, setSettings }: {\n host: ChatHost\n env: DaemonEnvironment\n /** The `settings.set` handler, so an environment edit fans out like any settings edit. */\n setSettings: Handler<'settings.set'>\n}): Handlers<EnvironmentMethod> {\n return {\n 'sessions.retryEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n // Provisioning can take minutes (a sandbox, a clone): respond once the\n // row shows `provisioning` (a poller must not read the old failure) and\n // let `prepare` run in the background, announced as `sessions:changed`.\n await host.retryEnvironment(p.sessionId, { background: true })\n },\n 'sessions.moveEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n return host.moveSessionEnvironment(p.sessionId, p.environment, typeof p.cwd === 'string' ? p.cwd : undefined, p.removeOldWorktree === true ? { removeOldWorktree: true } : undefined)\n },\n 'sessions.environmentActions': p => host.listEnvironmentActions(p.sessionId),\n 'sessions.runEnvironmentAction': p => host.runEnvironmentAction(p.sessionId, p.actionId),\n 'environments.list': p => host.listEnvironments(p.cwd ?? '', typeof p.kind === 'string' ? p.kind : undefined),\n 'environments.verify': p => host.verifyEnvironment(p.kind),\n 'environments.update': async (p, peer) => {\n const write = applyEnvironmentSettingsChange(host.environments, env.readSettings(), p)\n for (const secret of write.secrets)\n host.environmentSecrets.set(p.kind, secret.key, secret.value)\n // Through `settings.set` so the change fans out (and tears down what a\n // bound key like `sandbox` requires) exactly like any settings edit.\n await setSettings({ patch: write.settingsPatch as Partial<HostSettings> }, peer)\n },\n }\n}\n","/**\n * The wire checks of a session's rules (`sessions.create`'s `policy`,\n * `sessions.setPolicy`): the shape (`chat/session-policy`), and the scope\n * loosening needs. A client whose token can't approve calls may only tighten\n * the session's current rules: a looser `approvalMode` ('ask' > 'decide' > 'off'), or\n * removing or weakening a rule, lets the agent do more, so it needs a token\n * that may approve calls itself. A local connection (no grant) reaches\n * everything.\n */\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport { parseSessionPolicy, policyLoosening, SessionPolicyError } from '../../../chat/session-policy'\nimport { IpcErrorCode } from '../../protocol'\nimport { scopeAllows } from '../../scopes'\nimport { InvalidParamsError } from './params'\n\n/** A call the connection's token may not make (a policy it may not set, an action above its scope), worded like the dispatcher's scope refusal: it names the scope needed. */\nexport class PolicyScopeError extends Error {\n readonly code = IpcErrorCode.Forbidden\n readonly data: { required: ClientScope, granted: ClientScope }\n /**\n * @param method - The refused method.\n * @param what - The loosening, as {@link policyLoosening} words it.\n * @param granted - The connection's scope.\n * @param required - The scope it needs.\n */\n constructor(method: string, what: string, granted: ClientScope, required: ClientScope = 'approve') {\n super(`\"${method}\" ${what} needs ${required === 'chat' ? 'a' : 'an'} ${required} token; this connection's token is ${granted}.`)\n this.name = 'PolicyScopeError'\n this.data = { required, granted }\n }\n}\n\n/**\n * `value` as a clean policy that `peer` may set in place of `previous`.\n *\n * @param value - The `policy` param, untrusted.\n * @param peer - The calling connection (`null` for a host-internal call).\n * @param method - The method, named in the refusal.\n * @param previous - The session's current policy, read only when the token can't approve (default: none, a new session).\n * @throws {InvalidParamsError} When the policy does not validate.\n * @throws {PolicyScopeError} When it loosens `previous` and the token can't approve.\n */\nexport async function checkPolicyParam(\n value: unknown,\n peer: HostPeer | null | undefined,\n method: string,\n previous: () => SessionPolicy | Promise<SessionPolicy> = () => ({}),\n): Promise<SessionPolicy> {\n let policy: SessionPolicy\n try {\n policy = parseSessionPolicy(value, 'policy')\n }\n catch (err) {\n throw err instanceof SessionPolicyError ? new InvalidParamsError(err.message) : err\n }\n const grant = peer?.grant\n if (grant && !scopeAllows(grant, 'approve')) {\n const loosened = policyLoosening(await previous(), policy)\n if (loosened !== undefined)\n throw new PolicyScopeError(method, loosened, grant)\n }\n return policy\n}\n","/**\n * Extension API over the protocol : RPC (`rpc.*`), UI\n * items and their callbacks (`extensions.ui.*`), routed dialogs and UI\n * requests (`ui.*`), storage sync (`extensions.storage.*`), settings with\n * provenance (`extensions.settings*`), commands and keymap modes\n * (`extensions.command*`, `extensions.keymap.*`), integrations\n * (`extensions.integrations.*`) and catalog provenance. Each method naming a\n * `cwd` acts on the extension runtime of that folder's registry (built on\n * demand, as the catalog methods do); a folder without extensions answers\n * empty.\n *\n * The runtimes and ports live in the environment (`../extensions/host`);\n * this module checks the untrusted params and keeps per-connection state\n * (calls to cancel, pushed keymap modes), released when the connection drops.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { UiInvokeRequest, WireExtensionCommand, WireExtensionSettings, WireIntegration, WireIntegrationMethod } from '../../../chat/host/extensions-wire'\nimport type { Disposable } from '../../../extensions/api/core'\nimport type { StorageScope } from '../../../extensions/api/storage'\nimport type { LinkSource } from '../../../extensions/api/ui'\nimport type { IntegrationEntry } from '../../../extensions/integrations'\nimport type { SettingSource } from '../../../extensions/settings'\nimport type { StorageArea, StorageLocation } from '../../../extensions/storage'\nimport type { UiSnapshot } from '../../../extensions/ui'\nimport type { JsonValue } from '../../../types'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { AdoptedRuntime, DaemonChatHostPort, DaemonExtensionsHost } from '../extensions/host'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { changedCatalogItems } from '../../../chat/agents-catalog'\nimport { projectRootOf } from '../../../chat/project-root'\nimport { normalizeBadgeTarget } from '../../../extensions/badge-actions'\nimport { runtimeSettingsWire } from '../../../extensions/runtime/settings-wire'\nimport { isValueSetting, mergeWireSettings, SettingsWriteError } from '../../../extensions/settings'\nimport { isSafeRecordKey } from '../../../extensions/shared'\nimport { isJson } from '../../../extensions/storage'\nimport { UI_TOKEN_NAMES } from '../../../extensions/ui'\nimport { scopeAllows } from '../../scopes'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, requiredString } from './params'\nimport { PolicyScopeError } from './session-policy'\n\n/** The extension API methods (`createExtensionsHandlers`). */\nexport type ExtensionsMethod\n = | 'rpc.call' | 'rpc.cancel'\n | 'extensions.ui.list' | 'extensions.ui.invoke' | 'extensions.links.open' | 'extensions.entries'\n | 'ui.client.announce' | 'ui.client.reply' | 'ui.dialog.answer' | 'ui.dialog.validate'\n | 'extensions.storage.load' | 'extensions.storage.set'\n | 'extensions.settings' | 'extensions.settings.set'\n | 'extensions.commands' | 'extensions.command.run' | 'extensions.keymap.push' | 'extensions.keymap.pop' | 'extensions.keymap.list'\n | 'extensions.integrations.list' | 'extensions.integrations.connectKey' | 'extensions.integrations.start'\n | 'extensions.integrations.flowInput' | 'extensions.integrations.disconnect' | 'extensions.integrations.setDefault'\n | 'extensions.catalogs.provenance'\n\nconst SCOPES: ReadonlySet<string> = new Set<StorageScope>(['user', 'project', 'session'])\nconst AREAS: ReadonlySet<string> = new Set<StorageArea>(['kv', 'stores'])\nconst CATALOG_KINDS: ReadonlySet<string> = new Set(['tools', 'agents', 'subagents', 'models', 'providers', 'mcp', 'skills'])\n\nfunction emptySnapshot(): UiSnapshot {\n return Object.fromEntries(UI_TOKEN_NAMES.map(n => [n, []])) as unknown as UiSnapshot\n}\n\nfunction optionalString(value: unknown, name: string): string | undefined {\n if (value === undefined)\n return undefined\n if (typeof value !== 'string' || value.length === 0 || value.length > 1024)\n throw new InvalidParamsError(`${name} must be a non-empty string.`)\n return value\n}\n\n/** An integration as Settings lists it: methods without a client secret. */\nexport function wireIntegration(entry: IntegrationEntry): WireIntegration {\n const { spec } = entry\n return {\n id: spec.id,\n name: spec.name,\n ...(spec.description !== undefined ? { description: spec.description } : {}),\n extensionId: entry.extensionId,\n methods: spec.methods.map((m): WireIntegrationMethod => {\n if (m.type === 'custom') {\n const { connect: _connect, refresh: _refresh, ...rest } = m\n return rest\n }\n if (m.type !== 'oauth')\n return { ...m }\n const { clientSecret: _secret, ...rest } = m\n return rest\n }),\n ...(entry.connection ? { connection: entry.connection } : {}),\n connections: entry.connections,\n }\n}\n\n/** The settings wire of every extension of a runtime, with the layer each value comes from. */\nfunction settingsOf(adopted: AdoptedRuntime | undefined, sessionId: string | undefined): WireExtensionSettings {\n if (!adopted)\n return { ...mergeWireSettings([]), sources: {} }\n const { runtime } = adopted\n const sources: Record<string, SettingSource> = {}\n for (const info of runtime.extensions()) {\n const live = runtime.get(info.id)?.settings\n for (const [key, item] of Object.entries(live?.schema.items ?? {})) {\n if (!isValueSetting(item))\n continue\n const source = live!.source(key, sessionId ? { sessionId } : {})\n if (source)\n sources[`${info.id}:${key}`] = source\n }\n }\n return { ...runtimeSettingsWire(runtime, sessionId ? { sessionId } : {}), sources }\n}\n\n/** Every command of a runtime with its effective binding. */\nfunction commandsOf(adopted: AdoptedRuntime, sessionId: string | undefined): { commands: WireExtensionCommand[], mode?: string } {\n const registry = adopted.runtime.outputs.commands\n const keys = new Map(registry.keymap.list().map(b => [b.commandId, b]))\n const commands = registry.list().map((listing): WireExtensionCommand => {\n const entry = registry.get(listing.id)\n const key = keys.get(listing.id)\n const bind = [...(key?.chords ?? listing.bind ?? [])]\n if (!entry)\n return { id: listing.id, title: listing.title, when: 'always', enabled: true, palette: true, bind, scope: key?.scope ?? 'global', editable: key?.editable ?? false, hint: false, ...(listing.slash ? { slash: { name: listing.slash, aliases: [] } } : {}) }\n const spec = entry.spec\n const description = entry.description()\n return {\n id: entry.id,\n extensionId: entry.extensionId,\n title: entry.title(),\n ...(description !== undefined ? { description } : {}),\n group: spec.group ?? entry.group,\n ...(spec.keywords !== undefined ? { keywords: spec.keywords } : {}),\n ...(spec.icon ? { icon: { ...spec.icon } } : {}),\n when: spec.when ?? 'always',\n enabled: entry.enabled(),\n palette: spec.palette === undefined ? true : typeof spec.palette === 'boolean' ? spec.palette : { ...spec.palette },\n bind,\n ...(key?.overridden ? { overridden: true } : {}),\n scope: key?.scope ?? spec.scope ?? 'global',\n editable: key?.editable ?? spec.editable === true,\n ...(spec.mode !== undefined ? { mode: spec.mode } : {}),\n hint: spec.hint === true,\n ...(entry.slash ? { slash: { name: entry.slash.name, aliases: [...entry.slash.aliases], ...(entry.slash.argumentHint !== undefined ? { argumentHint: entry.slash.argumentHint } : {}) } } : {}),\n }\n })\n const mode = registry.keymap.currentMode(sessionId)\n return { commands, ...(mode !== undefined ? { mode } : {}) }\n}\n\n/** A storage location from untrusted params. */\nfunction locationOf(p: { extensionId?: unknown, scope?: unknown, sessionId?: unknown }): StorageLocation {\n const extensionId = requiredString(p.extensionId, 'extensionId')\n if (typeof p.scope !== 'string' || !SCOPES.has(p.scope))\n throw new InvalidParamsError('scope must be user, project or session.')\n const scope = p.scope as StorageScope\n if (scope === 'session')\n return { extensionId, scope, sessionId: requiredString(p.sessionId, 'sessionId') }\n return { extensionId, scope }\n}\n\n/** Runs one UI item callback of a runtime; `setting.action` goes through the handler (scope, dedupe, cancel). */\nasync function invokeUi(adopted: AdoptedRuntime, folder: string, p: Exclude<UiInvokeRequest, { op: 'setting.action' }>): Promise<unknown> {\n const ui = adopted.runtime.outputs.ui\n switch (p.op) {\n case 'panel.load':\n return ui.loadPanel(requiredString(p.panelId, 'panelId'), p.ctx, folder)\n case 'panel.action':\n return ui.panelAction(requiredString(p.panelId, 'panelId'), requiredString(p.actionId, 'actionId'), isJson(p.payload) ? p.payload as JsonValue : undefined, p.ctx, folder)\n case 'reference.resolve':\n return ui.resolveReference(requiredString(p.providerId, 'providerId'), requiredString(p.key, 'key'))\n case 'badge.menu': {\n const target = normalizeBadgeTarget(p.target)\n return target ? ui.badgeMenu(target) : []\n }\n case 'badge.run': {\n const target = normalizeBadgeTarget(p.target)\n if (!target)\n return { notice: 'Unknown badge.' }\n const sessionId = optionalString(p.sessionId, 'sessionId') ?? target.sessionId\n return ui.runBadgeAction(requiredString(p.source, 'source'), requiredString(p.actionId, 'actionId'), target, { cwd: folder, ...(sessionId ? { sessionId } : {}) })\n }\n case 'setting.status':\n return (await ui.settingStatus(requiredString(p.pageId, 'pageId'), requiredString(p.key, 'key'))) ?? null\n case 'setting.validate':\n return ui.validateSetting(requiredString(p.pageId, 'pageId'), requiredString(p.key, 'key'), p.value) ?? null\n default:\n throw new InvalidParamsError(`unknown op ${JSON.stringify((p as { op?: unknown }).op)}.`)\n }\n}\n\n/** What every group of handlers shares. */\ninterface ExtensionContext {\n env: DaemonEnvironment\n /** A client's folder, checked as the catalog methods check it (`catalogFolder`). */\n folderOf: (cwd: unknown) => string\n /** The extension host, or a refusal for a host without one. */\n runtime: () => DaemonExtensionsHost\n /** The folder's runtime, building its registry when needed. */\n runtimeOf: (cwd: unknown) => Promise<AdoptedRuntime | undefined>\n /** {@link ExtensionContext.runtimeOf}, refused when the folder has no extension. */\n requireRuntime: (cwd: unknown) => Promise<AdoptedRuntime>\n}\n\nfunction extensionContext(host: Pick<ChatHost, 'resolveFolder'>, env: DaemonEnvironment): ExtensionContext {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, requiredString(cwd, 'cwd'))\n const runtimeOf = async (cwd: unknown): Promise<AdoptedRuntime | undefined> => {\n const folder = folderOf(cwd)\n await env.runtimeConfig(folder)\n return env.extensionRuntimes?.runtimeFor(folder)\n }\n return {\n env,\n folderOf,\n runtime: () => {\n if (!env.extensionRuntimes)\n throw new Error('This host does not run extensions.')\n return env.extensionRuntimes\n },\n runtimeOf,\n requireRuntime: async (cwd) => {\n const adopted = await runtimeOf(cwd)\n if (!adopted)\n throw new InvalidParamsError('This folder has no extensions.')\n return adopted\n },\n }\n}\n\n/** Per-connection state: RPC calls and setting actions to cancel, keymap modes pushed. Released when the connection drops. */\ninterface PeerState {\n calls: Map<HostPeer, Map<string, AbortController>>\n actions: Map<HostPeer, Set<AbortController>>\n modes: Map<HostPeer, Map<string, Disposable>>\n}\n\nfunction rpcAndUiHandlers({ env, folderOf, runtime, runtimeOf, requireRuntime }: ExtensionContext, { calls, actions }: PeerState): Handlers<'rpc.call' | 'rpc.cancel' | 'extensions.ui.list' | 'extensions.ui.invoke' | 'extensions.links.open' | 'extensions.entries' | 'ui.client.announce' | 'ui.client.reply' | 'ui.dialog.answer' | 'ui.dialog.validate'> {\n /** Setting actions running now, by folder, page and key: a second click is refused, as `extensions.runAction` does. */\n const runningActions = new Set<string>()\n return {\n 'rpc.call': async (p, peer) => {\n const callId = optionalString(p.callId, 'callId')\n const controller = new AbortController()\n let mine = calls.get(peer)\n if (callId) {\n if (!mine) {\n mine = new Map()\n calls.set(peer, mine)\n }\n mine.set(callId, controller)\n }\n try {\n const clientId = env.extensionRuntimes?.clients.idOf(peer) ?? peer.principal ?? 'local'\n const { callId: _id, ...params } = p\n if (!env.extensionRuntimes)\n return { ok: false, error: { type: 'rpc.unavailable', message: 'This host does not run extensions.' }, meta: { contract: String(p.contract ?? ''), method: String(p.method ?? ''), scope: 'chat' } }\n // Build the folder's registry first, so a call into a folder not opened yet still finds its extensions.\n if (typeof params.cwd === 'string')\n await runtimeOf(params.cwd)\n // A method's `scope` against this connection's token; a local connection (no grant) is not limited.\n const grant = peer.grant\n return await env.extensionRuntimes.rpcCall(\n typeof params.cwd === 'string' ? { ...params, cwd: folderOf(params.cwd) } : params,\n { kind: 'client', clientId },\n controller.signal,\n grant ? scope => scopeAllows(grant, scope) : undefined,\n )\n }\n finally {\n if (callId && mine?.get(callId) === controller)\n mine.delete(callId)\n }\n },\n 'rpc.cancel': (p, peer) => {\n const controller = calls.get(peer)?.get(requiredString(p.callId, 'callId'))\n controller?.abort()\n return controller !== undefined\n },\n\n 'extensions.ui.list': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n if (!adopted)\n return { ...emptySnapshot(), bundles: {} }\n const bundles = await runtime().bundles(adopted)\n return { ...adopted.runtime.outputs.ui.snapshot(), bundles }\n },\n 'extensions.entries': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n return adopted ? runtime().entries(adopted) : []\n },\n 'extensions.ui.invoke': async (p, peer) => {\n const { cwd, ...rest } = p\n const request = rest as UiInvokeRequest\n const adopted = await requireRuntime(cwd)\n const folder = folderOf(cwd)\n if (request.op !== 'setting.action')\n return invokeUi(adopted, folder, request)\n const pageId = requiredString(request.pageId, 'pageId')\n const key = requiredString(request.key, 'key')\n // The action's own `scope` (default admin): it may write settings and do what `extensions.runAction` does.\n const required = adopted.runtime.outputs.ui.settingActionScope(pageId, key) ?? 'admin'\n if (peer.grant && !scopeAllows(peer.grant, required))\n throw new PolicyScopeError('extensions.ui.invoke', `with op \"setting.action\" (${key})`, peer.grant, required)\n const guard = `${folder}\\u001E${pageId}\\u001E${key}`\n if (runningActions.has(guard))\n throw new Error('action is already running.')\n const controller = new AbortController()\n let mine = actions.get(peer)\n if (!mine) {\n mine = new Set()\n actions.set(peer, mine)\n }\n mine.add(controller)\n runningActions.add(guard)\n try {\n return (await adopted.runtime.outputs.ui.runSettingAction(pageId, key, controller.signal)) ?? null\n }\n finally {\n runningActions.delete(guard)\n mine.delete(controller)\n }\n },\n\n 'extensions.links.open': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n if (!adopted)\n return { handled: false }\n const sessionId = optionalString(p.sessionId, 'sessionId')\n const source = optionalString(p.source, 'source')\n return adopted.runtime.outputs.ui.openLink({\n url: requiredString(p.url, 'url'),\n ...(sessionId ? { sessionId } : {}),\n ...(source ? { source: source as LinkSource } : {}),\n })\n },\n\n 'ui.client.announce': (p, peer) => {\n const host = runtime()\n const id = host.clients.idOf(peer)\n const before = new Set(id ? host.clients.clients().find(c => c.id === id)?.viewing : [])\n host.clients.announce(peer, p ?? {})\n // A session the client starts showing: its extensions' session storage is loaded for their sync reads.\n for (const sessionId of Array.isArray(p?.viewing) ? p.viewing : []) {\n if (typeof sessionId === 'string' && !before.has(sessionId))\n void host.sessionOpened(sessionId)\n }\n },\n 'ui.client.reply': (p, peer) => runtime().clients.reply(peer, requiredString(p.requestId, 'requestId'), p.result),\n 'ui.dialog.answer': (p, peer) => runtime().clients.answerDialog(peer, requiredString(p.dialogId, 'dialogId'), p.answer),\n 'ui.dialog.validate': (p, peer) => runtime().clients.validateDialog(peer, requiredString(p.dialogId, 'dialogId'), requiredString(p.key, 'key'), p.value) ?? null,\n }\n}\n\nfunction storageAndSettingsHandlers({ folderOf, runtime, runtimeOf, requireRuntime }: ExtensionContext): Handlers<'extensions.storage.load' | 'extensions.storage.set' | 'extensions.settings' | 'extensions.settings.set'> {\n return {\n 'extensions.storage.load': async (p) => {\n const folder = folderOf(p.cwd)\n const storage = runtime().storage.forProject(folder ? projectRootOf(folder) : undefined)\n const snapshot = await storage.load(locationOf(p))\n return { ...snapshot, ...(storage.projectRoot ? { projectRoot: storage.projectRoot } : {}) }\n },\n 'extensions.storage.set': async (p, peer) => {\n const folder = folderOf(p.cwd)\n const loc = locationOf(p)\n if (typeof p.area !== 'string' || !AREAS.has(p.area))\n throw new InvalidParamsError('area must be kv or stores.')\n const key = requiredString(p.key, 'key')\n if (!isSafeRecordKey(key))\n throw new InvalidParamsError('key is not a safe record key.')\n if (p.value !== undefined && !isJson(p.value))\n throw new InvalidParamsError('value must be JSON.')\n const host = runtime()\n const area = p.area as StorageArea\n const storage = host.storage.forProject(folder ? projectRootOf(folder) : undefined)\n // Every runtime of the folder holding the entry may refuse it (a store's version and schema).\n const adopted = await runtimeOf(p.cwd)\n const reason = adopted ? await adopted.runtime.checkStorageWrite(loc, area, key, p.value) : undefined\n if (reason !== undefined)\n return { accepted: false, reason, ...await storage.current(loc, area, key) }\n const signal = await storage.write(loc, area, key, p.value)\n host.publish(signal, peer)\n return { accepted: true, version: signal.version, ...(p.value !== undefined ? { value: p.value } : {}) }\n },\n\n 'extensions.settings': async p => settingsOf(await runtimeOf(p.cwd), optionalString(p.sessionId, 'sessionId')),\n 'extensions.settings.set': async (p) => {\n const adopted = await requireRuntime(p.cwd)\n const settings = adopted.runtime.get(requiredString(p.extension, 'extension'))?.settings\n if (!settings)\n throw new InvalidParamsError(`No active extension \"${p.extension}\" in this folder.`)\n const sessionId = optionalString(p.sessionId, 'sessionId')\n try {\n await settings.set(requiredString(p.key, 'key'), p.value, { scope: p.scope, ...(sessionId ? { sessionId } : {}) })\n }\n catch (err) {\n if (err instanceof SettingsWriteError)\n throw new InvalidParamsError(err.message)\n throw err\n }\n },\n }\n}\n\nfunction commandHandlers({ runtimeOf, requireRuntime }: ExtensionContext, { modes }: PeerState): Handlers<'extensions.commands' | 'extensions.command.run' | 'extensions.keymap.push' | 'extensions.keymap.pop' | 'extensions.keymap.list'> {\n let modeSeq = 0\n return {\n 'extensions.commands': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n return adopted ? commandsOf(adopted, optionalString(p.sessionId, 'sessionId')) : { commands: [] }\n },\n 'extensions.command.run': async (p) => {\n const adopted = await requireRuntime(p.cwd)\n const args = typeof p.args === 'string' ? p.args : ''\n const sessionId = optionalString(p.sessionId, 'sessionId')\n return adopted.runtime.outputs.commands.run(requiredString(p.id, 'id'), { args, ...(sessionId ? { sessionId } : {}) })\n },\n 'extensions.keymap.push': async (p, peer) => {\n const adopted = await requireRuntime(p.cwd)\n const sessionId = optionalString(p.sessionId, 'sessionId')\n const mode = adopted.runtime.outputs.commands.keymap.pushMode(requiredString(p.mode, 'mode'), {\n ...(typeof p.priority === 'number' && Number.isFinite(p.priority) ? { priority: p.priority } : {}),\n ...(sessionId ? { sessionId } : {}),\n })\n const handle = `m${++modeSeq}`\n let mine = modes.get(peer)\n if (!mine) {\n mine = new Map()\n modes.set(peer, mine)\n }\n mine.set(handle, mode)\n return handle\n },\n 'extensions.keymap.list': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n if (!adopted)\n return { entries: [], active: [] }\n const commands = adopted.runtime.outputs.commands\n return { entries: commands.keymapEntries().map(e => ({ ...e, bindings: [...e.bindings] })), active: [...commands.keymap.activeModes(optionalString(p.sessionId, 'sessionId'))] }\n },\n 'extensions.keymap.pop': (p, peer) => {\n const handle = requiredString(p.handle, 'handle')\n const mode = modes.get(peer)?.get(handle)\n if (!mode)\n return false\n modes.get(peer)!.delete(handle)\n mode.dispose()\n return true\n },\n }\n}\n\nfunction integrationHandlers({ env, folderOf, runtime, runtimeOf, requireRuntime }: ExtensionContext): Handlers<'extensions.integrations.list' | 'extensions.integrations.connectKey' | 'extensions.integrations.start' | 'extensions.integrations.flowInput' | 'extensions.integrations.disconnect' | 'extensions.integrations.setDefault' | 'extensions.catalogs.provenance'> {\n return {\n 'extensions.integrations.list': async (p) => {\n const adopted = await runtimeOf(p.cwd)\n return adopted ? adopted.runtime.outputs.integrations.list().map(wireIntegration) : []\n },\n 'extensions.integrations.connectKey': async (p) => {\n const integrations = (await requireRuntime(p.cwd)).runtime.outputs.integrations\n const id = requiredString(p.integrationId, 'integrationId')\n await integrations.connectKey(id, requiredString(p.key, 'key'), optionalString(p.methodId, 'methodId'))\n const entry = integrations.get(id)\n if (!entry)\n throw new Error(`Integration \"${id}\" is gone.`)\n return wireIntegration(entry)\n },\n 'extensions.integrations.start': async (p, peer) => {\n const integrations = (await requireRuntime(p.cwd)).runtime.outputs.integrations\n const id = requiredString(p.integrationId, 'integrationId')\n const flowId = optionalString(p.flowId, 'flowId')\n const flow = runtime().flows.portFor(() => peer, { integrationId: id, ...(flowId ? { flowId } : {}) })\n try {\n await integrations.start(id, requiredString(p.methodId, 'methodId'), flow.port)\n flow.finish({ ok: true })\n }\n catch (err) {\n flow.finish({ ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n const entry = integrations.get(id)\n if (!entry)\n throw new Error(`Integration \"${id}\" is gone.`)\n return wireIntegration(entry)\n },\n 'extensions.integrations.flowInput': (p, peer) => runtime().flows.input(peer, requiredString(p.flowId, 'flowId'), requiredString(p.inputId, 'inputId'), typeof p.value === 'string' ? p.value : undefined),\n 'extensions.integrations.disconnect': async (p) => {\n await (await requireRuntime(p.cwd)).runtime.outputs.integrations.disconnect(requiredString(p.integrationId, 'integrationId'), optionalString(p.account, 'account'))\n },\n 'extensions.integrations.setDefault': async (p) => {\n await (await requireRuntime(p.cwd)).runtime.outputs.integrations.setDefault(requiredString(p.integrationId, 'integrationId'), requiredString(p.account, 'account'))\n },\n\n 'extensions.catalogs.provenance': async (p) => {\n if (typeof p.kind !== 'string' || !CATALOG_KINDS.has(p.kind))\n throw new InvalidParamsError('kind must be a catalog kind.')\n const config = await env.runtimeConfig(folderOf(p.cwd))\n return [...changedCatalogItems(config.extensions.runtime, p.kind as Parameters<typeof changedCatalogItems>[1])]\n },\n }\n}\n\n/**\n * The extension API methods. Binds the environment's extension host to the\n * peer fan-out (its\n * signals go out unnumbered: none belongs to a transcript) and to the chat\n * host (built-in commands, slash runs, command invocations, session\n * settings, MCP status).\n */\nexport function createExtensionsHandlers({ host, env, onClose, broadcastExcept }: {\n host: Pick<ChatHost, 'resolveFolder'> & DaemonChatHostPort\n env: DaemonEnvironment\n onClose: (release: (peer: HostPeer) => void) => void\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): Handlers<ExtensionsMethod> {\n env.extensionRuntimes?.bindPeers({ broadcastExcept })\n env.extensionRuntimes?.bindHost(host)\n const ctx = extensionContext(host, env)\n const state: PeerState = { calls: new Map(), actions: new Map(), modes: new Map() }\n onClose((peer) => {\n for (const controller of state.calls.get(peer)?.values() ?? [])\n controller.abort()\n state.calls.delete(peer)\n for (const controller of state.actions.get(peer) ?? [])\n controller.abort()\n state.actions.delete(peer)\n for (const mode of state.modes.get(peer)?.values() ?? [])\n mode.dispose()\n state.modes.delete(peer)\n env.extensionRuntimes?.clients.remove(peer)\n env.extensionRuntimes?.flows.release(peer)\n })\n return {\n ...rpcAndUiHandlers(ctx, state),\n ...storageAndSettingsHandlers(ctx),\n ...commandHandlers(ctx, state),\n ...integrationHandlers(ctx),\n }\n}\n","/**\n * What an extension adds to a client's app, run here and answered as data:\n * composer completions (`completions.*`: the providers, a provider's items,\n * the submit hooks), text references in prose (`references.*`: the\n * providers' patterns, then the views of the keys a client found), badge\n * menu items (`badges.*`), and Settings › Extensions (`extensions.*`: the\n * options a folder's extensions declare, their action rows, the actions'\n * status probes, a run). A badge item runs outside any session's scope: its\n * `ctx.artifacts` reads nothing.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { CompletionRunner, ExtensionRegistry, ReferenceResolver } from '../../../extensions/index'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { DaemonChatHostPort } from '../extensions/host'\nimport type { HostPeer } from '../peers'\nimport type { ExtensionsMethod } from './extensions'\nimport type { Handlers } from './types'\nimport {\n completionProviderSummaries,\n createCompletionRunner,\n createReferenceResolver,\n extensionBadgeActions,\n listActionSummaries,\n normalizeBadgeTarget,\n probeActionStatuses,\n referenceProviderWires,\n runBadgeAction,\n runExtensionAction,\n toWireConfigSchema,\n} from '../../../extensions/index'\nimport { actionScope } from '../../../extensions/settings'\nimport { scopeAllows } from '../../scopes'\nimport { catalogFolder } from './catalogs'\nimport { createExtensionsHandlers } from './extensions'\nimport { InvalidParamsError } from './params'\nimport { PolicyScopeError } from './session-policy'\n\ntype ExtensionUiMethod\n = | 'completions.providers' | 'completions.suggest' | 'completions.submit'\n | 'references.providers' | 'references.resolve' | 'badges.actions' | 'badges.run'\n | 'extensions.configSchema' | 'extensions.actions' | 'extensions.actionStatuses' | 'extensions.runAction'\n\n/** Keys per `references.resolve` call. */\nconst RESOLVE_MAX = 50\n/** Longest reference key resolved. */\nconst MAX_KEY_LENGTH = 512\n\n/** The text and cursor of a completion call. */\nfunction composerText(p: { text?: unknown, cursor?: unknown }): { text: string, cursor: number } {\n if (typeof p.text !== 'string' || typeof p.cursor !== 'number' || !Number.isSafeInteger(p.cursor) || p.cursor < 0 || p.cursor > p.text.length)\n throw new InvalidParamsError('text must be a string and cursor a position in it.')\n return { text: p.text, cursor: p.cursor }\n}\n\n/** One value per owner (a connection, a registry), dropped with it. */\nfunction weakMemo<K extends object, V>(make: (owner: K) => V): (owner: K) => V {\n const memo = new WeakMap<K, V>()\n return (owner) => {\n let value = memo.get(owner)\n if (value === undefined) {\n value = make(owner)\n memo.set(owner, value)\n }\n return value\n }\n}\n\nexport function createExtensionUiHandlers({ host, env, onClose, broadcastExcept }: {\n host: Pick<ChatHost, 'resolveFolder'> & DaemonChatHostPort\n env: DaemonEnvironment\n /** For the extension API methods (`./extensions`): per-connection state and the unnumbered fan-out. */\n onClose: (release: (peer: HostPeer) => void) => void\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): Handlers<ExtensionUiMethod | ExtensionsMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n const configOf = (cwd: unknown) => env.runtimeConfig(folderOf(cwd))\n const registryOf = async (cwd: unknown): Promise<ExtensionRegistry> => (await configOf(cwd)).extensions\n /** One completion runner per connection: a newer suggest aborts only that window's older one. */\n const runnerOf = weakMemo<HostPeer, CompletionRunner>(() => createCompletionRunner())\n /** One reference resolver (and so one view cache) per registry: a rebuilt registry starts fresh. */\n const resolverOf = weakMemo<ExtensionRegistry, ReferenceResolver>(registry => createReferenceResolver(registry))\n /** Actions running now, by folder, extension and key: a second click waits for the first. */\n const running = new Set<string>()\n\n return {\n ...createExtensionsHandlers({ host, env, onClose, broadcastExcept }),\n 'completions.providers': async p => completionProviderSummaries((await registryOf(p.cwd)).completionProviders),\n 'completions.suggest': async (p, peer) => {\n const context = composerText(p)\n if (typeof p.providerId !== 'string' || typeof p.query !== 'string')\n throw new InvalidParamsError('providerId and query must be strings.')\n const cwd = folderOf(p.cwd)\n const provider = (await env.runtimeConfig(cwd)).extensions.completionProviders.find(c => c.id === p.providerId)\n if (!provider || typeof provider.suggest !== 'function')\n return []\n return runnerOf(peer).suggest(`${cwd}\\u001E${provider.id}`, provider, p.query, context)\n },\n 'completions.submit': async (p, peer) => {\n const { text, cursor } = composerText(p)\n await runnerOf(peer).submit((await registryOf(p.cwd)).completionProviders, text, cursor)\n },\n\n 'references.providers': async (p) => {\n if (p.peek !== true)\n return referenceProviderWires(await registryOf(p.cwd))\n const cached = env.peekRuntimeConfig?.(folderOf(p.cwd))\n return cached ? referenceProviderWires((await cached).extensions) : null\n },\n 'references.resolve': async (p) => {\n const asked = Array.isArray(p.items) ? p.items.slice(0, RESOLVE_MAX) : []\n const resolver = resolverOf(await registryOf(p.cwd))\n return Promise.all(asked.map((item) => {\n const { providerId, key } = (item ?? {}) as { providerId?: unknown, key?: unknown }\n if (typeof providerId !== 'string' || typeof key !== 'string' || key.length > MAX_KEY_LENGTH)\n return null\n return resolver.resolve(providerId, key)\n }))\n },\n 'badges.actions': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n return target ? extensionBadgeActions(target, await registryOf(p.cwd)) : []\n },\n 'badges.run': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n if (!target || typeof p.source !== 'string' || typeof p.id !== 'string')\n return { notice: 'Unknown badge.' }\n const ctx = {\n ...(target.sessionId ? { sessionId: target.sessionId } : {}),\n ...(typeof p.cwd === 'string' && p.cwd ? { cwd: p.cwd } : {}),\n }\n return runBadgeAction(p.source, p.id, target, await registryOf(p.cwd), ctx)\n },\n\n 'extensions.configSchema': async (p) => {\n const config = await configOf(p.cwd)\n return toWireConfigSchema({ configCategories: config.extensionConfigCategories, configItems: config.extensionConfigItems })\n },\n 'extensions.actions': async (p) => {\n const config = await configOf(p.cwd)\n return listActionSummaries(config.extensionConfigCategories, config.extensionConfigItems)\n },\n 'extensions.actionStatuses': async p => probeActionStatuses((await configOf(p.cwd)).extensionConfigItems),\n 'extensions.runAction': async (p, peer) => {\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n const cwd = folderOf(p.cwd)\n const config = await env.runtimeConfig(cwd)\n // The action's own `scope` (`ActionSetting.scope`, default admin); a config-declared action needs admin.\n if (peer.grant) {\n const declared = env.extensionRuntimes?.runtimeFor(cwd)?.runtime.get(p.extension)?.settings?.schema.items[p.key]\n const required = declared?.type === 'action' ? actionScope(declared) : 'admin'\n if (!scopeAllows(peer.grant, required))\n throw new PolicyScopeError('extensions.runAction', `of \"${p.extension}\" \"${p.key}\"`, peer.grant, required)\n }\n const guard = `${cwd}\\u001E${p.extension}\\u001E${p.key}`\n if (running.has(guard))\n throw new Error('action is already running.')\n running.add(guard)\n try {\n // An extension's action writes its own patch through its settings port.\n const extensionSettings = env.extensionRuntimes?.runtimeFor(cwd)?.runtime.get(p.extension)?.settings\n if (extensionSettings)\n return await extensionSettings.runAction(p.key)\n return await runExtensionAction(config.extensionConfigItems, p.extension, p.key)\n }\n finally {\n running.delete(guard)\n }\n },\n }\n}\n","/**\n * A folder's files beyond a session's workspace (`files.*`): the files `@`\n * completes and where the folder sits, search in files, what prose names on disk, the project's own diagnostics, and the ticket a\n * connection's media play under (a zidane-server serves them over HTTP,\n * `src/server/media.ts`). The work is the desktop app's own\n * (`src/chat/workspace`); this slice confines every folder to the host's\n * workspace roots.\n */\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { randomUUID } from 'node:crypto'\nimport { listProjectFiles } from '../../../chat/files-discovery'\nimport { folderLocation } from '../../../chat/project-root'\nimport { invalidateDiagnostics, listDiagnosticsTools, runDiagnostics } from '../../../chat/workspace/diagnostics/runner'\nimport { resolvePaths } from '../../../chat/workspace/path-resolve'\nimport { searchWorkspace } from '../../../chat/workspace/search'\nimport { InvalidParamsError, optionalString } from './params'\n\ntype FilesMethod = 'files.list' | 'files.location' | 'files.search' | 'files.resolvePaths' | 'files.diagnostics' | 'files.diagnosticsInvalidate' | 'files.diagnosticsTools' | 'files.mediaTicket'\n\n/** The connections' media tickets: a zidane-server's (`src/server/media.ts`). */\nexport interface MediaTicketRegistry {\n /** Lets `peer`'s media play under `ticket`, replacing its previous one. Throws when another connection holds it. */\n register: (ticket: string, peer: HostPeer) => void\n /** Drops `peer`'s ticket (its connection closed). */\n release: (peer: HostPeer) => void\n}\n\n/** A media ticket: random, URL-safe, long enough not to be guessed. */\nconst MEDIA_TICKET = /^[\\w-]{32,128}$/\n\n/** Longest query searched; the rest is cut. */\nconst MAX_QUERY_LENGTH = 500\n/** Most texts one `files.resolvePaths` resolves. */\nconst MAX_TEXTS = 500\n\nfunction stringList(value: unknown, name: string, max = Infinity): string[] {\n if (!Array.isArray(value) || value.length > max || value.some(v => typeof v !== 'string'))\n throw new InvalidParamsError(`${name} must be an array of at most ${max} strings.`)\n return value\n}\n\nexport function createFilesHandlers({ workspace, media, onClose }: {\n workspace: WorkspaceRoots\n /** Absent: this host serves no media (`files.mediaTicket` refuses). */\n media?: MediaTicketRegistry\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<FilesMethod> {\n if (media)\n onClose(peer => media.release(peer))\n const folder = (cwd: unknown): string => {\n if (typeof cwd !== 'string' || cwd.length === 0)\n throw new InvalidParamsError('cwd must be a non-empty string.')\n return workspace.resolveFolder(cwd)\n }\n // Search ids are per connection: one client's search never cancels another's.\n const connectionIds = new WeakMap<HostPeer, string>()\n const connectionId = (peer: HostPeer): string => {\n let id = connectionIds.get(peer)\n if (!id)\n connectionIds.set(peer, id = randomUUID())\n return id\n }\n return {\n 'files.list': p => listProjectFiles({ cwd: folder(p.cwd) }),\n 'files.location': p => folderLocation(folder(p.cwd)),\n 'files.search': (p, peer) => {\n if (typeof p.query !== 'string')\n throw new InvalidParamsError('query must be a string.')\n return searchWorkspace(folder(p.cwd), p.query.slice(0, MAX_QUERY_LENGTH), {\n caseSensitive: p.caseSensitive === true,\n searchId: `${connectionId(peer)}:${optionalString(p.searchId, 'searchId') ?? ''}`,\n })\n },\n 'files.resolvePaths': p => resolvePaths(folder(p.cwd), stringList(p.texts, 'texts', MAX_TEXTS)),\n 'files.diagnostics': p => runDiagnostics(folder(p.cwd), stringList(p.paths, 'paths'), {\n disabled: p.disabled === undefined ? [] : stringList(p.disabled, 'disabled'),\n ...(typeof p.timeoutMs === 'number' ? { timeoutMs: p.timeoutMs } : {}),\n }),\n 'files.diagnosticsInvalidate': (p) => {\n invalidateDiagnostics(folder(p.cwd))\n },\n 'files.diagnosticsTools': p => listDiagnosticsTools(folder(p.cwd)),\n 'files.mediaTicket': (p, peer) => {\n if (!media)\n throw new Error('This host serves no media (only a zidane-server does).')\n if (typeof p.ticket !== 'string' || !MEDIA_TICKET.test(p.ticket))\n throw new InvalidParamsError('ticket must be 32 to 128 URL-safe characters.')\n media.register(p.ticket, peer)\n },\n }\n}\n","/**\n * The host's machine: folders within its workspace roots (`fs.roots`,\n * `fs.listDirs`, `fs.searchDirs`, and `fs.mkdir` while `createFolders`\n * allows it) and what it can do (`host.capabilities`).\n */\nimport type { HostCapabilities } from '../../../chat/capabilities'\nimport type { EnvironmentDescriptor } from '../../../chat/environment-settings'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { createCapabilityProbe } from '../../../chat/capabilities-probe'\nimport { optionalString, requiredString } from './params'\n\n/** What `fs.mkdir` answers while a zidane-server's `allowCreateFolders` is off. */\nexport const CREATE_FOLDERS_OFF_MESSAGE = 'Creating folders is off on this server (allowCreateFolders).'\n\nexport function createFsHandlers({ workspace, environments, allows, createFolders = () => true }: {\n workspace: WorkspaceRoots\n /** The host's environment kinds (`environments.list`). */\n environments?: () => Promise<EnvironmentDescriptor[]>\n /** What it lets clients do (the hello flags). */\n allows?: () => HostCapabilities['allows']\n /** Clients may create folders (`fs.mkdir`): a zidane-server's `allowCreateFolders`. Default: yes. */\n createFolders?: () => boolean\n}): Handlers<'fs.roots' | 'fs.listDirs' | 'fs.mkdir' | 'fs.searchDirs' | 'host.capabilities'> {\n const probe = createCapabilityProbe({\n environments: async () => (await (environments?.() ?? Promise.resolve([])))\n .filter(d => d.enabled)\n .map(d => ({ kind: d.kind, label: d.label, available: d.available, ...(d.reason ? { reason: d.reason } : {}) })),\n roots: () => workspace.describe().roots,\n allows: allows ?? (() => ({ remoteInstalls: false, asMachine: false, sync: false, clone: true, createFolders: createFolders() })),\n })\n return {\n 'fs.roots': () => workspace.describe(),\n 'fs.listDirs': p => workspace.list(optionalString(p?.path, 'path')),\n 'fs.mkdir': (p) => {\n if (!createFolders())\n throw new Error(CREATE_FOLDERS_OFF_MESSAGE)\n return workspace.mkdir(requiredString(p.parent, 'parent'), requiredString(p.name, 'name'))\n },\n 'fs.searchDirs': p => workspace.search(requiredString(p.query, 'query'), optionalString(p.path, 'path')),\n 'host.capabilities': p => probe(p?.refresh === true),\n }\n}\n","/** Session rows: list, create, delete, and metadata edits (title, archive, agent, model, folder, policy). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { SessionData, SessionStore } from '../../../session/index'\nimport type { CreateSessionParams, HostSignal, IpcParams, SessionRow } from '../../protocol'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { TITLE_SOURCE_KEY } from '../../../chat/auto-title'\nimport { isStaleRunMarker } from '../../../chat/host/engine'\nimport { readSessionAccount, sessionModelFallbacks } from '../../../chat/model-chain-metadata'\nimport { isMainSession, isSideSession, sideSessionParent } from '../../../chat/orchestration'\nimport { PINNED_SKILLS_META_KEY, pinnedSkillsValue, readPinnedSkills } from '../../../chat/pinned-skills'\nimport { cachedRepoKeyOf } from '../../../chat/project-root'\nimport { runningEstimateViews } from '../../../chat/run-estimate'\nimport { SESSION_POLICY_KEY, sessionPolicyOf } from '../../../chat/session-policy'\nimport { DEFAULT_SPACE_ID, readSessionSpaceId, SPACE_METADATA_KEY } from '../../../chat/spaces'\nimport { deriveSessionTitle, runInProgress, sessionEnvironmentSummary } from '../../../chat/store'\nimport { readSessionFacets } from '../../../session/facets'\nimport { loadOrThrow } from './session-load'\nimport { checkPolicyParam } from './session-policy'\n\ntype SessionMethod\n = | 'sessions.list' | 'sessions.create' | 'sessions.delete' | 'sessions.sideSession' | 'sessions.setTitle' | 'sessions.setArchived' | 'sessions.setFavorite' | 'sessions.setSpace'\n | 'sessions.setAgentId' | 'sessions.setEffort' | 'sessions.setModel' | 'sessions.setModelOptions' | 'sessions.setFolder'\n | 'sessions.setPolicy'\n\nexport function createSessionHandlers({ host, store, broadcast, forgetSession, hostId, workspace }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Drop the per-session wire state other handlers keep, before the host deletes the session. */\n forgetSession: (sessionId: string) => void\n /** Stamped on every returned row (`SessionRow.hostId`). */\n hostId: string | undefined\n /** Where session folders may be (a server confines them to its workspace roots). */\n workspace?: WorkspaceRoots\n}): Handlers<SessionMethod> {\n const stamp = (row: SessionRow): SessionRow => hostId ? { ...row, hostId } : row\n /** Each session's last `sessions.setPolicy`: the next one checks against what it wrote, not against what was there before it. */\n const policyWrites = new Map<string, Promise<unknown>>()\n /**\n * Apply a metadata-only patch. Prefers the host's live-session path (safe\n * mid-run — routes through the in-memory `Session` whose turns are the\n * source of truth); only falls back to a store-level full-document\n * `save()` when the session is idle, where no run is appending turns so\n * `load → mutate → save` can't drop concurrently-persisted turns.\n *\n * `bumpUpdatedAt: false` skips the recency bump so a rename doesn't yank\n * the row to the top of recency-sorted lists (mirrors the GUI).\n */\n async function patchSessionMeta(\n sessionId: string,\n patch: Record<string, unknown>,\n opts: { bumpUpdatedAt?: boolean } = {},\n ): Promise<void> {\n /*\n * Live path: route through the in-memory `Session` so the full-document\n * save() re-persists the CURRENT turns; `bumpUpdatedAt` holds there too.\n */\n await host.patchSessionMeta(sessionId, patch, opts)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function patchSession(\n sessionId: string,\n mutate: (data: SessionData) => void,\n ): Promise<void> {\n const data = await loadOrThrow(store, sessionId)\n mutate(data)\n data.updatedAt = Date.now()\n await store.save(data)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function createSessionRow(params: CreateSessionParams, policy?: SessionPolicy): Promise<SessionRow> {\n // Creation lives in the host (shared with the embedded GUI host and\n // orchestration); this adds only the wire row + the change broadcast.\n // Forward the wire fields by name: the host factory also accepts an\n // explicit `id` and raw `metadata`, which a wire client must not set\n // (only the validated keys below).\n const metadata = policy && Object.keys(policy).length > 0 ? { ...creationMetadata(params), [SESSION_POLICY_KEY]: policy } : creationMetadata(params)\n // A machine's folder (`local@<machine>`) is not on this host: the host checks it against the machine's roots instead.\n const onMachine = params.environment?.kind ? host.environments.get(params.environment.kind)?.checkFolder !== undefined : false\n const cwd = workspace?.describe().confined && !onMachine ? workspace.sessionFolder(params.cwd ?? '') : params.cwd\n const id = await host.createSession({\n cwd,\n ...(metadata ? { metadata } : {}),\n ...(params.title ? { title: params.title } : {}),\n ...(params.agentId ? { agentId: params.agentId } : {}),\n ...(params.providerKey && params.modelId ? { providerKey: params.providerKey, modelId: params.modelId } : {}),\n ...(params.providerKey && params.modelId && typeof params.account === 'string' && params.account ? { account: params.account } : {}),\n ...(params.fallbacks ? { fallbacks: params.fallbacks } : {}),\n ...(params.extensionEdit ? { extensionEdit: true } : {}),\n ...(params.skillEdit?.name ? { skillEdit: { name: params.skillEdit.name } } : {}),\n ...(typeof params.spaceId === 'string' && params.spaceId ? { spaceId: params.spaceId } : {}),\n ...(typeof params.sideOf === 'string' && params.sideOf ? { sideOf: params.sideOf } : {}),\n ...(params.environment?.kind\n ? {\n environment: {\n kind: params.environment.kind,\n ...(params.environment.branch ? { branch: params.environment.branch } : {}),\n ...(params.environment.base ? { base: params.environment.base } : {}),\n },\n }\n : {}),\n })\n const data = await loadOrThrow(store, id)\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: id })\n return stamp(toRow(host, data))\n }\n\n return {\n 'sessions.list': async p => (await listSessionRows(host, store, p)).map(stamp),\n // Awaited, not returned: a rejection handed back unawaited reaches Bun's unhandled-rejection check first.\n 'sessions.create': async (p, peer) => await createSessionRow(p, p.policy === undefined ? undefined : await checkPolicyParam(p.policy, peer, 'sessions.create')),\n 'sessions.delete': async (p) => {\n forgetSession(p.sessionId)\n // Agent retirement + environment + row + on-disk artifacts: the shared host delete.\n const { environment } = await host.deleteSession(p.sessionId)\n broadcast({ kind: 'sessions:changed', op: 'delete', sessionId: p.sessionId })\n return environment.removed && !environment.reason ? {} : { environment }\n },\n 'sessions.sideSession': async (p) => {\n const rowOf = async (id: string | undefined): Promise<SessionRow | null> => {\n const data = id ? await store.load(id) : null\n return data ? stamp(toRow(host, data)) : null\n }\n const [side, parent] = await Promise.all([rowOf(await newestSideSession(store, p.sessionId)), rowOf(p.sessionId)])\n return { side, parent }\n },\n // Rename skips the recency bump so it doesn't yank the row to the top\n // of recency-sorted lists (mirrors the GUI).\n // A typed title: auto-titling never replaces it (`metadata.titleSource`).\n 'sessions.setTitle': p => patchSessionMeta(p.sessionId, { title: p.title, [TITLE_SOURCE_KEY]: 'user' }, { bumpUpdatedAt: false }),\n 'sessions.setArchived': async (p) => {\n await patchSessionMeta(p.sessionId, { archived: p.archived })\n // An archived session's shells on this machine end (in the background:\n // archiving never waits on a slow one); its environment's are left to idle suspension.\n if (p.archived)\n void host.terminals.archiveSession(p.sessionId)\n },\n // Like a rename: not activity, so the row keeps its place by recency.\n 'sessions.setFavorite': p => patchSessionMeta(p.sessionId, { favorite: p.favorite }, { bumpUpdatedAt: false }),\n // Replaces the whole policy; `{}` clears it. Not activity: no recency bump.\n 'sessions.setPolicy': (p, peer) => {\n const write = async (): Promise<void> => {\n // Live metadata first: it is what the host enforces.\n const current = async () => sessionPolicyOf((host.getLiveSession(p.sessionId) ?? await loadOrThrow(store, p.sessionId)).metadata)\n const policy = await checkPolicyParam(p.policy, peer, 'sessions.setPolicy', current)\n return patchSessionMeta(p.sessionId, { [SESSION_POLICY_KEY]: Object.keys(policy).length > 0 ? policy : undefined }, { bumpUpdatedAt: false })\n }\n const next = (policyWrites.get(p.sessionId) ?? Promise.resolve()).then(write, write)\n const settled = next.catch(() => undefined)\n policyWrites.set(p.sessionId, settled)\n void settled.then(() => {\n if (policyWrites.get(p.sessionId) === settled)\n policyWrites.delete(p.sessionId)\n })\n return next\n },\n // Default is stored as its id rather than deleted: the patch is a shallow\n // spread, and every reader maps the Default id to \"no space\".\n // A move is not activity: no recency bump.\n 'sessions.setSpace': p => patchSessionMeta(\n p.sessionId,\n { [SPACE_METADATA_KEY]: typeof p.spaceId === 'string' && p.spaceId ? p.spaceId : DEFAULT_SPACE_ID },\n { bumpUpdatedAt: false },\n ),\n 'sessions.setAgentId': async (p) => {\n /*\n * `agentId` is a top-level field (not metadata) and rebuilds the\n * agent. Patch the LIVE document when the host holds one — a bare\n * store patch loads a stale copy whose full save would clobber\n * mid-run turn appends, and the untouched live doc would revert the\n * label on its next save. Idle sessions take the store patch (no\n * concurrent writer). Then retire the agent (deferred to run end\n * while running) so a swap doesn't abort a shared run mid-stream —\n * unless the live agent's composition fits the new profile\n * (`ChatHost.agentSwitchRebuilds`).\n */\n const rebuild = host.agentSwitchRebuilds(p.sessionId, p.agentId)\n if (await host.setLiveSessionAgentId(p.sessionId, p.agentId)) {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n }\n else {\n await patchSession(p.sessionId, (d) => {\n d.agentId = p.agentId\n })\n }\n if (rebuild)\n host.disposeAgentForRebuild(p.sessionId)\n },\n 'sessions.setEffort': p => patchSessionMeta(p.sessionId, { effort: p.effort }),\n 'sessions.setModel': async (p) => {\n // The one model-swap contract (`ChatHost.setSessionModel`): patch\n // race-free, replace the chain, reset effort/options, retire the agent\n // (run-end deferred mid-run). Documented in protocol.ts.\n await host.setSessionModel(p.sessionId, {\n providerKey: p.providerKey,\n modelId: p.modelId,\n ...(typeof p.account === 'string' && p.account ? { account: p.account } : {}),\n ...(p.fallbacks ? { fallbacks: p.fallbacks } : {}),\n ...(p.effort ? { effort: p.effort } : {}),\n ...(p.modelOptions ? { modelOptions: p.modelOptions } : {}),\n })\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.setModelOptions': p => patchSessionMeta(p.sessionId, { modelOptions: p.options }),\n 'sessions.setFolder': (p) => {\n const cwd = typeof p.cwd === 'string' ? p.cwd : ''\n // The host checks it: against this host's roots, or a machine session's machine's (`docs/MACHINES.md` § Folders).\n return host.setSessionFolder(p.sessionId, cwd)\n },\n }\n}\n\n/** The creation-time metadata a client may stamp: the pick's effort and options, pinned skills. */\nfunction creationMetadata(params: CreateSessionParams): Record<string, unknown> | undefined {\n const metadata: Record<string, unknown> = {}\n if (typeof params.effort === 'string')\n metadata.effort = params.effort\n if (params.modelOptions && typeof params.modelOptions === 'object') {\n const options = Object.fromEntries(Object.entries(params.modelOptions).filter(([, on]) => typeof on === 'boolean'))\n if (Object.keys(options).length > 0)\n metadata.modelOptions = options\n }\n if (Array.isArray(params.pinnedSkills)) {\n const pins = readPinnedSkills(params.pinnedSkills.slice(0, 64))\n if (pins.size > 0)\n metadata[PINNED_SKILLS_META_KEY] = pinnedSkillsValue(pins)\n }\n return Object.keys(metadata).length > 0 ? metadata : undefined\n}\n\nexport async function listSessionRows(host: ChatHost, store: SessionStore, p: IpcParams<'sessions.list'>): Promise<SessionRow[]> {\n const filter\n = p?.projectRoot !== undefined ? { projectRoot: p.projectRoot as string | null } : undefined\n\n const applyArchive = (rows: SessionRow[]): SessionRow[] => {\n const filtered = rows.filter((row) => {\n if (p?.archive === 'active')\n return !row.archived\n if (p?.archive === 'archived')\n return row.archived\n return true\n })\n filtered.sort((a, b) => b.updatedAt - a.updatedAt)\n return filtered\n }\n\n /*\n * Fast path: `listMeta` returns header rows without materializing\n * turn arrays — O(sessions), not O(total turns). Falls back to the\n * load-per-id path for stores that don't implement it.\n */\n if (store.listMeta) {\n const metas = await store.listMeta(filter)\n return applyArchive(metas.filter(meta => !isSideSession(meta.metadata)).map((meta) => {\n const md = meta.metadata\n // Canonical derivation — the same helper the TUI list uses, so\n // daemon-fed rows can't render a different title for the same\n // session (the hand-rolled fallback had its own truncation).\n const title = deriveSessionTitle(meta.firstUserTurn ? [meta.firstUserTurn] : [], md)\n const running = host.isSessionRunning(meta.id)\n const cwd = typeof md.cwd === 'string' ? md.cwd : (meta.projectRoot ?? '')\n return {\n id: meta.id,\n title,\n // As `toRow`: clients place rows in spaces (and pin Main) from these two.\n ...(isMainSession(md) ? { isMain: true } : {}),\n ...(readSessionSpaceId(md) ? { spaceId: readSessionSpaceId(md) } : {}),\n projectRoot: meta.projectRoot ?? null,\n cwd,\n ...repoKeyField(meta.projectRoot || cwd),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n // A crashed process's leftover 'running' marker must not render\n // forever — apply the same freshness bound the run guard uses.\n status: running\n ? 'running' as const\n : isStaleRunMarker(meta.status, meta.updatedAt, Date.now(), meta.runOwner)\n ? 'idle' as const\n : (meta.status ?? 'idle'),\n ...(running ? runStartOf(host, meta.id) : {}),\n createdAt: meta.createdAt ?? 0,\n updatedAt: meta.updatedAt,\n archived: md.archived === true,\n ...(md.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(md)\n return environment ? { environment } : {}\n })(),\n ...(typeof md.providerKey === 'string' ? { providerKey: md.providerKey } : {}),\n ...(typeof md.modelId === 'string' ? { modelId: md.modelId } : {}),\n ...(readSessionAccount(md) ? { account: readSessionAccount(md) } : {}),\n ...(typeof md.effort === 'string' ? { effort: md.effort as SessionRow['effort'] } : {}),\n ...(md.modelOptions && typeof md.modelOptions === 'object'\n ? { modelOptions: md.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(md)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n ...facetsField(md),\n }\n }))\n }\n\n const ids = await store.list(filter)\n const rows: SessionRow[] = []\n for (const id of ids) {\n const data = await store.load(id)\n if (!data || isSideSession(data.metadata))\n continue\n rows.push(toRow(host, data))\n }\n return applyArchive(rows)\n}\n\n/** The newest `/side` session of `parentId` (`metadata.sideOf`). */\nasync function newestSideSession(store: SessionStore, parentId: string): Promise<string | undefined> {\n const rows = store.listMeta\n ? (await store.listMeta()).map(row => ({ id: row.id, metadata: row.metadata, updatedAt: row.updatedAt }))\n : (await Promise.all((await store.list()).map(async (id) => {\n const data = await store.load(id)\n return { id, metadata: data?.metadata, updatedAt: data?.updatedAt ?? 0 }\n })))\n return rows\n .filter(row => row.id !== parentId && sideSessionParent(row.metadata) === parentId)\n .sort((a, b) => b.updatedAt - a.updatedAt)[0]\n ?.id\n}\n\n/** The row's `repoKey`: the repository its folder is a checkout of, when it has a shared remote. */\nfunction repoKeyField(folder: string | undefined): { repoKey?: string } {\n const repoKey = folder ? cachedRepoKeyOf(folder) : null\n return repoKey ? { repoKey } : {}\n}\n\n/**\n * A running session's `runStartedAt` (its top-level run in progress, as the\n * agent recorded it) and `runEstimates` (its runs in progress that have one).\n */\nfunction runStartOf(host: ChatHost, sessionId: string): Pick<SessionRow, 'runStartedAt' | 'runEstimates'> {\n const runs = host.getLiveSession(sessionId)?.runs ?? []\n const run = runInProgress(runs)\n const estimates = runningEstimateViews(runs)\n return {\n ...(run ? { runStartedAt: run.startedAt } : {}),\n ...(estimates.length > 0 ? { runEstimates: estimates } : {}),\n }\n}\n\nfunction toRow(host: ChatHost, data: SessionData): SessionRow {\n const meta = data.metadata ?? {}\n // Canonical derivation — same helper as the TUI list (see the\n // listMeta fast path above).\n const title = deriveSessionTitle(data.turns, meta)\n const running = host.isSessionRunning(data.id)\n\n return {\n id: data.id,\n title,\n ...(isMainSession(meta) ? { isMain: true } : {}),\n ...(readSessionSpaceId(meta) ? { spaceId: readSessionSpaceId(meta) } : {}),\n projectRoot: data.projectRoot ?? null,\n cwd: typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? ''),\n ...repoKeyField(data.projectRoot || (typeof meta.cwd === 'string' ? meta.cwd : '')),\n ...(typeof data.agentId === 'string' ? { agentId: data.agentId } : {}),\n status: running\n ? 'running'\n : isStaleRunMarker(data.status, data.updatedAt, Date.now(), data.runOwner)\n ? 'idle'\n : data.status,\n ...(running ? runStartOf(host, data.id) : {}),\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n archived: meta.archived === true,\n ...(meta.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(meta)\n return environment ? { environment } : {}\n })(),\n ...(typeof meta.providerKey === 'string' ? { providerKey: meta.providerKey } : {}),\n ...(typeof meta.modelId === 'string' ? { modelId: meta.modelId } : {}),\n ...(readSessionAccount(meta) ? { account: readSessionAccount(meta) } : {}),\n ...(typeof meta.effort === 'string' ? { effort: meta.effort as SessionRow['effort'] } : {}),\n ...(meta.modelOptions && typeof meta.modelOptions === 'object'\n ? { modelOptions: meta.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(meta)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n ...facetsField(meta),\n }\n}\n\n/** The row's `facets`: the values stored with the session, when it has any. */\nfunction facetsField(metadata: Record<string, unknown>): { facets?: SessionRow['facets'] } {\n const facets = readSessionFacets(metadata)\n return Object.keys(facets).length > 0 ? { facets } : {}\n}\n","import type { CloneRun } from '../../../chat/git/clone'\n/**\n * A folder's git checkout (`git.*`): the composer's git bar, the branch menu,\n * the Files tab's changed marks and working-tree diffs, a commit chip's facts,\n * sync, the repository import (while `clone` allows it), and a checkout's refs moving (`git.watch`:\n * `git:refs` to the connections that follow it). The git and `gh` work is\n * the desktop app's own (`src/chat/git`, `src/chat/workspace/files`); this\n * slice confines every folder to the host's workspace roots and finds the\n * sessions in a checkout.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { realpathSync } from 'node:fs'\nimport { cloneRepository } from '../../../chat/git/clone'\nimport { forgetGitCaches, gitBranches, gitCommit, gitCreateBranch, gitInfo, gitPr, gitPrList, gitSwitch } from '../../../chat/git/info'\nimport { parseRepoInput } from '../../../chat/git/repo-url'\nimport { gitSync } from '../../../chat/git/sync'\nimport { createGitWatches } from '../../../chat/git/watch'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { isInside } from '../../../chat/workspace-confinement'\nimport { gitDiff, gitStatus } from '../../../chat/workspace/files'\nimport { InvalidParamsError, optionalString, requiredString } from './params'\nimport { listSessionRows } from './sessions'\n\n/** What `git.clone` answers while a zidane-server's `allowClone` is off. */\nexport const CLONE_OFF_MESSAGE = 'Cloning is off on this server (allowClone).'\n\ntype GitMethod\n = | 'git.status' | 'git.branches' | 'git.pullRequests' | 'git.branchPullRequest' | 'git.commit' | 'git.fileStatus'\n | 'git.diff' | 'git.checkout' | 'git.createBranch' | 'git.sync' | 'git.clone' | 'git.cloneCancel' | 'git.watch' | 'git.unwatch'\n\n/** The checkout holding `folder` (a nested worktree or repository is its own), or the folder outside git. */\nfunction checkoutOf(folder: string): string | null {\n try {\n const real = realpathSync.native(folder)\n return findGitRoot(real) ?? real\n }\n catch {\n return null\n }\n}\n\nexport function createGitHandlers({ host, store, workspace, isConnected, onClose, clone = () => true }: {\n host: ChatHost\n store: SessionStore\n workspace: WorkspaceRoots\n isConnected: (peer: HostPeer) => boolean\n /** Registers a peer-close hook: a dropped connection's clone is cancelled, its watches released. */\n onClose: (release: (peer: HostPeer) => void) => void\n /** Clients may clone (`git.clone`): a zidane-server's `allowClone`. Default: yes. */\n clone?: () => boolean\n}): Handlers<GitMethod> {\n const clones = new Map<HostPeer, CloneRun>()\n onClose(peer => clones.get(peer)?.cancel())\n // Keyed by the folder as each client names it: `git:refs` carries that name back.\n const refs = createGitWatches<HostPeer>((cwd, change) => {\n forgetGitCaches(cwd, change === 'refs' ? 'git:refs' : 'git:config')\n if (change === 'refs') {\n for (const peer of refs.owners(cwd))\n peer.send({ kind: 'git:refs', cwd })\n }\n })\n onClose(peer => refs.release(peer))\n const folder = (cwd: unknown): string => workspace.resolveFolder(requiredString(cwd, 'cwd'))\n /** `folder`, when the checkout holding it is inside the roots too: git reports on the whole repository, not the folder it runs in. */\n const repoFolder = (cwd: unknown): string => {\n const at = folder(cwd)\n workspace.resolveFolder(findGitRoot(at) ?? at)\n return at\n }\n\n /** The unarchived sessions working in `cwd`'s checkout, `except` left out. */\n async function sessionsInCheckout(cwd: string, except?: string): Promise<string[]> {\n const checkout = checkoutOf(cwd)\n if (!checkout)\n return []\n const rows = await listSessionRows(host, store, { archive: 'active' })\n return rows.filter(row => row.id !== except && row.cwd && checkoutOf(row.cwd) === checkout).map(row => row.id)\n }\n\n /** An agent runs in `cwd`'s checkout (the asking session included). */\n async function agentRunsIn(cwd: string, sessionId: string | undefined): Promise<boolean> {\n if (sessionId && host.isSessionRunning(sessionId))\n return true\n return (await sessionsInCheckout(cwd, sessionId)).some(id => host.isSessionRunning(id))\n }\n\n return {\n 'git.status': p => gitInfo(folder(p.cwd)),\n 'git.branches': p => gitBranches(folder(p.cwd)),\n 'git.pullRequests': p => gitPrList(folder(p.cwd), optionalString(p.search, 'search'), p.fresh === true),\n 'git.branchPullRequest': p => gitPr(folder(p.cwd), requiredString(p.branch, 'branch'), p.fresh === true),\n 'git.commit': p => gitCommit(repoFolder(p.cwd), requiredString(p.sha, 'sha')),\n 'git.fileStatus': p => gitStatus(repoFolder(p.cwd)),\n 'git.diff': (p) => {\n if (p.context !== undefined && p.context !== null && (typeof p.context !== 'number' || p.context < 0))\n throw new InvalidParamsError('context must be a non-negative number or null.')\n return gitDiff(repoFolder(p.cwd), optionalString(p.path, 'path'), p.context === null ? Infinity : p.context)\n },\n 'git.checkout': async (p) => {\n const cwd = folder(p.cwd)\n const target = p.target as unknown\n const pr = typeof target === 'object' && target !== null ? (target as { pr?: unknown }).pr : undefined\n if (typeof target !== 'string' && typeof pr !== 'number')\n throw new InvalidParamsError('target must be a branch name or { pr: number }.')\n const sessionId = optionalString(p.sessionId, 'sessionId')\n const result = await gitSwitch(cwd, typeof target === 'string' ? target : { pr: pr as number }, await agentRunsIn(cwd, sessionId))\n if (result.ok || !result.worktree)\n return result\n // git names the worktree resolved: only one inside the roots is told apart by its sessions.\n const inRoots = workspace.describe().roots.some(root => isInside(root, result.worktree!))\n return { ...result, chats: inRoots ? await sessionsInCheckout(result.worktree, sessionId) : [] }\n },\n 'git.createBranch': async (p) => {\n const cwd = folder(p.cwd)\n return gitCreateBranch(cwd, requiredString(p.name, 'name'), await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.sync': async (p) => {\n const cwd = folder(p.cwd)\n return gitSync(cwd, await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.clone': async (p, peer) => {\n if (!clone())\n throw new Error(CLONE_OFF_MESSAGE)\n const input = requiredString(p.input, 'input')\n const parent = workspace.resolveFolder(requiredString(p.parent, 'parent'))\n // A `file://` source is a folder on this machine: confined like `parent`, or a client copies out what the roots keep from it.\n const spec = parseRepoInput(input)\n if (spec && /^file:/i.test(spec.cloneUrl)) {\n const source = new URL(spec.cloneUrl)\n if (source.host && source.host !== 'localhost')\n throw new InvalidParamsError('A file:// source must be on this machine.')\n workspace.resolveFolder(decodeURIComponent(source.pathname))\n }\n if (clones.has(peer))\n return { ok: false, error: 'A clone is already running.' }\n const run = cloneRepository(input, parent, ({ phase, percent }) => {\n if (isConnected(peer))\n peer.send({ kind: 'git:clone:progress', phase, percent })\n })\n clones.set(peer, run)\n try {\n return await run.result\n }\n finally {\n clones.delete(peer)\n }\n },\n 'git.cloneCancel': (_p, peer) => {\n clones.get(peer)?.cancel()\n },\n 'git.watch': (p, peer) => {\n folder(p.cwd)\n return refs.watch(p.cwd, peer)\n },\n 'git.unwatch': (p, peer) => {\n refs.unwatch(peer, requiredString(p.cwd, 'cwd'))\n },\n }\n}\n","/** Transcript history search, per session and across sessions, over one shared index cache. */\nimport type { SessionHistoryMatch, SessionTextIndex } from '../../../chat/history-search'\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { buildSessionSearchIndexAsync, buildSessionTextIndexAsync, searchSessionHistoryIndexAsync, searchSessionHistoryTextIndexAsync, searchSessionIndexAsync, searchSessionTextIndexAsync } from '../../../chat/history-search'\nimport { changedSessionOf } from './transcript-cache'\n\n/*\n * Daemon-side history search — one index cache shared by EVERY window,\n * so repeat queries (and other windows' queries) pay match cost only.\n * Off the UI thread by construction (this process has no renderer), so\n * no Worker indirection is needed. Live sessions index the host's\n * in-memory turns (fresh mid-run); idle sessions index store turns.\n *\n * The cache keeps each turn's lowercased text only; a match reads its turn\n * back from the turns loaded for the query. Bounded by bytes (least\n * recently used first out), a session is dropped when it changes or goes,\n * and the whole cache when no search came for a while.\n */\nconst SEARCH_INDEX_CACHE_MAX_BYTES = 32 * 1024 * 1024\nconst SEARCH_INDEX_IDLE_MS = 10 * 60_000\n\ntype HistoryMethods = Handlers<'history.searchSession' | 'history.searchAll'>\n\n/** The history search methods, and the hold on their index cache. */\nexport interface HistoryHandlers {\n methods: HistoryMethods\n /** A host signal: one that follows a change to a session drops its index. */\n observe: (signal: HostSignal) => void\n /** The session is gone: drop its index. */\n forget: (sessionId: string) => void\n /** Sessions with an index kept, and the bytes they hold. */\n sizes: () => { sessions: number, bytes: number }\n /** Drops every index (the host is shutting down). */\n close: () => void\n}\n\ninterface SessionSearch {\n index: SessionTextIndex\n /** What the index was built from (or matches): its matches are read back from them. */\n turns: readonly SessionTurn[]\n}\n\nexport function createHistoryHandlers({ host, store, onClose, maxBytes = SEARCH_INDEX_CACHE_MAX_BYTES, idleMs = SEARCH_INDEX_IDLE_MS }: {\n host: ChatHost\n store: SessionStore\n /** Registers the drop of every index at the host's shutdown. */\n onClose?: (stop: () => void) => void\n maxBytes?: number\n idleMs?: number\n}): HistoryHandlers {\n /** Latest `history.searchAll` generation per peer — see the handler. */\n const searchGenerations = new WeakMap<HostPeer, number>()\n /** Insertion order = least recently used first. */\n const searchIndexCache = new Map<string, { key: string, index: SessionTextIndex }>()\n let cachedBytes = 0\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n /** Index builds in flight: one whose session is dropped meanwhile is served, not kept. */\n const building = new Map<string, Set<{ dropped: boolean }>>()\n\n function forget(sessionId: string): void {\n for (const build of building.get(sessionId) ?? [])\n build.dropped = true\n const cached = searchIndexCache.get(sessionId)\n if (!cached)\n return\n cachedBytes -= cached.index.bytes\n searchIndexCache.delete(sessionId)\n }\n\n function clear(): void {\n clearTimeout(idleTimer)\n idleTimer = undefined\n for (const builds of building.values()) {\n for (const build of builds)\n build.dropped = true\n }\n searchIndexCache.clear()\n cachedBytes = 0\n }\n\n /** Every search pushes the idle drop back. */\n function touch(): void {\n clearTimeout(idleTimer)\n idleTimer = setTimeout(clear, idleMs)\n idleTimer.unref?.()\n }\n\n onClose?.(clear)\n\n function keep(sessionId: string, key: string, index: SessionTextIndex): void {\n forget(sessionId)\n // Over the budget alone: served, not kept.\n if (index.bytes > maxBytes)\n return\n searchIndexCache.set(sessionId, { key, index })\n cachedBytes += index.bytes\n for (const [id, oldest] of searchIndexCache) {\n if (cachedBytes <= maxBytes || id === sessionId)\n break\n searchIndexCache.delete(id)\n cachedBytes -= oldest.index.bytes\n }\n }\n\n async function sessionSearch(sessionId: string): Promise<SessionSearch | null> {\n touch()\n const liveTurns = host.getLiveTurns(sessionId)\n let turns: readonly SessionTurn[]\n let key: string\n if (liveTurns) {\n /*\n * SNAPSHOT before the async index build — the agent may append\n * mid-build and the builder yields between turns. The cache key\n * folds in the last turn id so a same-count content change (e.g.\n * compaction replacing turns) can't serve a stale index.\n */\n turns = [...liveTurns]\n key = `live:${turns.length}:${turns.at(-1)?.id ?? ''}`\n }\n else {\n const data = await store.load(sessionId)\n if (!data)\n return null\n turns = data.turns\n key = `store:${data.updatedAt}:${data.turns.length}`\n }\n\n const cached = searchIndexCache.get(sessionId)\n if (cached?.key === key) {\n // Refresh LRU recency (Map preserves insertion order).\n searchIndexCache.delete(sessionId)\n searchIndexCache.set(sessionId, cached)\n return { index: cached.index, turns }\n }\n\n const build = { dropped: false }\n const builds = building.get(sessionId) ?? new Set()\n building.set(sessionId, builds.add(build))\n try {\n const index = await buildSessionTextIndexAsync(turns)\n if (!build.dropped)\n keep(sessionId, key, index)\n return { index, turns }\n }\n finally {\n builds.delete(build)\n if (builds.size === 0 && building.get(sessionId) === builds)\n building.delete(sessionId)\n }\n }\n\n const methods: HistoryMethods = {\n 'history.searchSession': async (p) => {\n const search = await sessionSearch(p.sessionId)\n if (!search)\n return []\n const { index, turns } = search\n // Wire-supplied limit: unchecked JSON — coerce to a sane positive\n // integer bounded by the corpus (same policy as queue/draft bounds).\n const limit = Number.isInteger(p.limit) && (p.limit as number) > 0\n ? Math.min(p.limit as number, index.turns.length)\n : index.turns.length\n let matches = await searchSessionTextIndexAsync(index, turns, p.query, limit)\n if (!matches) {\n // The kept index no longer matches the turns: search them whole.\n forget(p.sessionId)\n matches = await searchSessionIndexAsync(await buildSessionSearchIndexAsync(turns), p.query, { limit })\n }\n // Turn order, not relevance — search is a transcript filter, and\n // sorting here spares clients from re-fetching the turn list.\n const order = new Map(turns.map((turn, i) => [turn.id, i]))\n matches.sort((a, b) => (order.get(a.turn.id) ?? 0) - (order.get(b.turn.id) ?? 0))\n return matches\n },\n 'history.searchAll': async (p, peer) => {\n /*\n * Per-peer supersession: search fires per debounced keystroke and\n * the client discards stale responses, but without this the daemon\n * would still run every superseded full-corpus pass to completion —\n * stacked CPU that delays signal fan-out for every window. A newer\n * query from the same peer makes older loops bail at the next\n * session boundary (partial result; the client ignores it anyway).\n */\n const generation = (searchGenerations.get(peer) ?? 0) + 1\n searchGenerations.set(peer, generation)\n\n const results: Record<string, SessionHistoryMatch> = {}\n // Bound the per-request corpus: `store.load` materializes full turn\n // arrays, and supersession only cancels SAME-peer re-queries — one\n // oversized request must not run the shared daemon to completion.\n const ids = Array.isArray(p.sessionIds) ? p.sessionIds.slice(0, 500) : []\n const excerptLimit = p.excerptLimit ?? 3\n for (const sessionId of ids) {\n if (searchGenerations.get(peer) !== generation)\n break\n try {\n const search = await sessionSearch(sessionId)\n if (!search)\n continue\n let match = await searchSessionHistoryTextIndexAsync(search.index, search.turns, p.query, excerptLimit)\n if (match === undefined) {\n forget(sessionId)\n match = await searchSessionHistoryIndexAsync(await buildSessionSearchIndexAsync(search.turns), p.query, excerptLimit)\n }\n if (match)\n results[sessionId] = match\n }\n catch {\n // One bad session must not sink the whole cross-session search.\n }\n }\n return results\n },\n }\n\n return {\n methods,\n observe(signal) {\n const sessionId = changedSessionOf(signal)\n if (sessionId !== undefined)\n forget(sessionId)\n },\n forget,\n sizes: () => ({ sessions: searchIndexCache.size + building.size, bytes: cachedBytes }),\n close: clear,\n }\n}\n","/**\n * Human-in-the-loop: tool approvals and interactions (questions, plans)\n * awaiting an answer, and the \"Always allow\" entries approvals saved (the\n * host user's `projects.json`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { PendingInteraction } from '../../../chat/host/signals'\nimport type { SessionStore } from '../../../session/index'\nimport type { Handlers } from './types'\nimport { pendingInteractionsFromTurns } from '../../../chat/interactions-protocol'\nimport { listSafelists, removeFromSafelist } from '../../../chat/safe-mode'\nimport { requiredString } from './params'\n\ntype HitlMethod\n = | 'interactions.list' | 'interactions.respond' | 'interactions.cancel' | 'interactions.rehydrate' | 'interactions.rehydrateSessions'\n | 'approvals.resolve' | 'approvals.denyAll' | 'approvals.listPending'\n | 'safelist.list' | 'safelist.remove'\n\n/** Turns read back from a session's end to find a question its run stopped on (notes may follow it). */\nconst OPEN_PROMPT_TAIL = 20\n\n/**\n * Whether the session's last turns hold a question or plan with no answer,\n * read without loading the session. A store with no header index answers\n * `true`: it is loaded, as a window opening it would.\n */\nasync function endsOnOpenPrompt(store: SessionStore, sessionId: string): Promise<boolean> {\n if (!store.getMeta)\n return true\n const meta = await store.getMeta(sessionId)\n if (!meta)\n return false\n // `turnCount` leaves out system turns: from there, the tail still reaches the last turn.\n const tail = await store.getTurns(sessionId, Math.max(0, (meta.turnCount ?? 0) - OPEN_PROMPT_TAIL))\n return pendingInteractionsFromTurns(tail).length > 0\n}\n\nexport function createHitlHandlers({ host, store, userDataDir }: { host: ChatHost, store: SessionStore, userDataDir: () => string }): Handlers<HitlMethod> {\n return {\n 'interactions.list': p => host.interactions.list(p?.sessionId),\n 'interactions.respond': p => host.interactions.respond(p.requestId, p.response),\n 'interactions.cancel': p => host.interactions.cancel(p.requestId, p.reason),\n // A window opening a session: a durable run a dead process left resumes, or its question goes up first, so the list below has it.\n 'interactions.rehydrate': async (p) => {\n await host.resumePending({ sessionId: p.sessionId }).catch(() => undefined)\n return host.interactions.rehydrate(p.sessionId)\n },\n // A channel start, over every conversation it ever had: a session is loaded only when its run waits to resume or its last turns ask.\n 'interactions.rehydrateSessions': async (p) => {\n const out: PendingInteraction[] = []\n for (const sessionId of Array.isArray(p.sessionIds) ? p.sessionIds : []) {\n if (typeof sessionId !== 'string' || host.isSessionRunning(sessionId))\n continue\n await host.resumePending({ sessionId }).catch(() => undefined)\n if (await endsOnOpenPrompt(store, sessionId).catch(() => false))\n out.push(...await host.interactions.rehydrate(sessionId))\n }\n return out\n },\n\n 'approvals.resolve': (p) => {\n host.approvals.resolve(p.requestId, p.decision)\n },\n 'approvals.denyAll': p => host.approvals.denyAll(p?.sessionId),\n 'approvals.listPending': () => host.approvals.listPending(),\n\n 'safelist.list': () => ({ projects: listSafelists(userDataDir()) }),\n 'safelist.remove': p => ({ removed: removeFromSafelist(userDataDir(), requiredString(p.project, 'project'), requiredString(p.entry, 'entry')) }),\n }\n}\n","/** Per-client launch overrides: each window's own, the latest connected setter's applied. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionLaunchOverrides } from '../../../chat/host/launch-overrides'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { normalizeLaunchOverrides } from '../../../chat/host/launch-overrides'\n\n/**\n * A confined host (a server) drops a `cwd` outside its workspace roots\n * itself (`ChatHost.setLaunchOverrides`): a window's own folder is a path on\n * ITS machine, which the session must not move to.\n */\nexport function createLaunchOverrideHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'sessions.setLaunchOverrides'>\n /** The peer dropped: forget its overrides, so the previous setter's apply again. */\n releasePeer: (peer: HostPeer) => void\n /** The session was deleted: forget every setter's overrides. */\n forget: (sessionId: string) => void\n} {\n /**\n * Each client's launch overrides per session, oldest setter first. The\n * session runs the most recent connected setter's; a client clearing, or\n * disconnecting, drops only its own, and the previous setter's apply again.\n */\n const launchOverridesByPeer = new Map<string, Map<HostPeer, SessionLaunchOverrides>>()\n\n /** Run the latest connected setter's overrides (see `launchOverridesByPeer`). */\n const applyLaunchOverrides = (sessionId: string): void => {\n const setters = launchOverridesByPeer.get(sessionId)\n const latest = setters ? [...setters.values()].at(-1) : undefined\n if (!latest)\n launchOverridesByPeer.delete(sessionId)\n host.setLaunchOverrides(sessionId, latest ?? null)\n }\n\n return {\n methods: {\n 'sessions.setLaunchOverrides': (p, peer) => {\n const { sessionId, ...rest } = p\n const next = normalizeLaunchOverrides(rest)\n const setters = launchOverridesByPeer.get(sessionId) ?? new Map<HostPeer, SessionLaunchOverrides>()\n // Re-inserted, so a client setting again becomes the latest setter.\n setters.delete(peer)\n if (next)\n setters.set(peer, next)\n launchOverridesByPeer.set(sessionId, setters)\n applyLaunchOverrides(sessionId)\n },\n },\n releasePeer(peer) {\n for (const [sessionId, setters] of launchOverridesByPeer) {\n if (setters.delete(peer))\n applyLaunchOverrides(sessionId)\n }\n },\n forget(sessionId) {\n launchOverridesByPeer.delete(sessionId)\n },\n }\n}\n","/**\n * Reverse direction (`docs/MACHINES.md` § Reverse direction): this server\n * lends itself as a machine to a client's host over that client's own\n * connection, because a local host (a laptop) has no listener to be dialed.\n * The client sends `machine.attach`, then one `machine.call` per\n * host→machine request; the server's confined executor\n * (`../../machine/executor`, loaded on first attach) answers them inside the\n * server's workspace roots. Machine notifications go back to that connection\n * only, as `machine:notification` signals.\n *\n * Off unless the server allows it (`allowAsMachine`). It does not widen what a\n * client token can do: `sessions.workspaceExec` and terminals already run\n * commands in the same roots with the same token.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineRegisterParams } from '../../../chat/machine-protocol'\nimport type { LooseSandboxSettings } from '../../../chat/sandbox-settings'\nimport type { JsonValue } from '../../../types'\nimport type { MachineExecutor } from '../../machine/executor'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { join } from 'node:path'\nimport { MACHINE_PROTOCOL_VERSION, MachineErrorCode, toMachineName } from '../../../chat/machine-protocol'\nimport { ZIDANE_VERSION } from '../../../version'\n\n/**\n * Executors kept between their connections (tasks, terminals), keyed by the\n * token that attached them and the host id it named: a host id is the\n * client's word, so another token naming it gets an executor of its own,\n * never the first one's tasks, terminals or exits. Each token holds at most\n * {@link MAX_PER_PRINCIPAL} and evicts only its own idle ones.\n */\nconst MAX_PER_PRINCIPAL = 4\nconst MAX_ATTACHED_HOSTS = 32\n\nexport interface MachineServeOptions {\n /** `allowAsMachine`: read per attach, so a restart is not needed to turn it off for new links. */\n allowed: () => boolean\n}\n\nclass MachineServeError extends Error {\n readonly code: number = MachineErrorCode.MethodNotAllowed\n}\n\n/** A capacity limit: the client retries later (`../../machine/reverse.ts`). */\nclass MachineServeBusyError extends MachineServeError {\n override readonly code: number = MachineErrorCode.Busy\n}\n\ninterface Served {\n executor: MachineExecutor\n peer: HostPeer | null\n principal: string\n}\n\n/** Who attached: the token's id (`''` on a host without auth, a loopback test server). */\nconst principalOf = (peer: HostPeer): string => peer.principal ?? ''\n\nexport function createMachineServeHandlers(input: {\n host: ChatHost\n dataDir: () => string\n hostName: string\n settings: () => LooseSandboxSettings\n options?: MachineServeOptions\n isConnected: (peer: HostPeer) => boolean\n}): { methods: Handlers<'machine.attach' | 'machine.call' | 'machine.detach'>, releasePeer: (peer: HostPeer) => void, allowed: () => boolean } {\n const { host } = input\n const allowed = (): boolean => input.options?.allowed() === true\n const served = new Map<string, Served>()\n const byPeer = new Map<HostPeer, string>()\n\n const roots = (): string[] => {\n const { roots: list, confined } = host.workspace\n if (!confined || list.length === 0)\n throw new MachineServeError('This host has no workspace roots to lend.')\n return [...list]\n }\n\n /** Make room for one more of `principal`'s: its own idle executor goes, never another token's. */\n const makeRoom = (principal: string): void => {\n const own = [...served].filter(([, entry]) => entry.principal === principal)\n if (own.length < MAX_PER_PRINCIPAL && served.size < MAX_ATTACHED_HOSTS)\n return\n const idle = own.find(([, entry]) => entry.peer === null)\n if (!idle)\n throw new MachineServeBusyError(own.length >= MAX_PER_PRINCIPAL ? `This token already has ${MAX_PER_PRINCIPAL} hosts attached here.` : `This server already lends itself to ${MAX_ATTACHED_HOSTS} hosts.`)\n served.delete(idle[0])\n void idle[1].executor.close()\n }\n\n async function executorFor(hostId: string, peer: HostPeer): Promise<MachineExecutor> {\n const principal = principalOf(peer)\n const key = `${principal}:${hostId}`\n const existing = served.get(key)\n if (existing) {\n const previous = existing.peer\n if (previous && previous !== peer)\n byPeer.delete(previous)\n existing.peer = peer\n return existing.executor\n }\n makeRoom(principal)\n const { createMachineExecutor } = await import('../../machine/executor')\n const entry: Served = { peer, principal, executor: undefined as unknown as MachineExecutor }\n entry.executor = createMachineExecutor({\n roots: roots().map(path => ({ path })),\n dataDir: join(input.dataDir(), 'machine-self'),\n // The server's own sandbox settings apply to what it runs as a machine, as to its own sessions.\n sandbox: input.settings(),\n credentialsDataDir: input.dataDir(),\n notify: (method, params) => {\n const target = entry.peer\n if (!target || !input.isConnected(target))\n return false\n target.send({ kind: 'machine:notification', method, params: params as JsonValue })\n return true\n },\n })\n served.set(key, entry)\n return entry.executor\n }\n\n const attachedOf = (peer: HostPeer): Served => {\n const key = byPeer.get(peer)\n const entry = key ? served.get(key) : undefined\n if (!entry || entry.peer !== peer)\n throw new MachineServeError('Send machine.attach first on this connection.')\n return entry\n }\n\n return {\n allowed,\n methods: {\n 'machine.attach': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.hostId !== 'string' || !/^[\\w-]{1,64}$/.test(p.hostId))\n throw new MachineServeError('machine.attach: \"hostId\" must be 1 to 64 letters, digits, \"-\" or \"_\".')\n const executor = await executorFor(p.hostId, peer)\n byPeer.set(peer, `${principalOf(peer)}:${p.hostId}`)\n executor.linkUp()\n const { machineIdentity } = await import('../../machine/identity')\n const result: MachineRegisterParams = {\n machineId: machineIdentity(join(input.dataDir(), 'machine-self')),\n name: toMachineName(input.hostName),\n roots: roots().map(path => ({ path })),\n capabilities: { shell: true, terminals: typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined', background: true, worktrees: true, stream: true, sandboxed: executor.sandbox.on },\n version: ZIDANE_VERSION,\n protocolVersion: MACHINE_PROTOCOL_VERSION,\n }\n return result\n },\n 'machine.call': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.method !== 'string')\n throw new MachineServeError('machine.call: \"method\" must be a string.')\n return (await attachedOf(peer).executor.handle(p.method, p.params ?? {})) as JsonValue\n },\n 'machine.detach': (_p, peer) => {\n const key = byPeer.get(peer)\n if (!key)\n return { detached: false }\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n return { detached: true }\n },\n },\n releasePeer(peer) {\n const key = byPeer.get(peer)\n if (!key)\n return\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n },\n }\n}\n","/**\n * OAuth sign-in over the wire (`auth.oauth.*`): the browser on the client,\n * the tokens on the host.\n *\n * `begin` runs the login HERE (a provider's `runOAuthLogin`, an MCP server's\n * `loginMcpServer`), so the PKCE verifier, `state` and the token exchange\n * never leave the host, and answers with the authorization URL as soon as\n * the login produces it. The redirect lands on the client's loopback (a\n * provider's fixed `redirect_uri`, or the loopback URI the client chose for\n * an MCP server; a browser client's MCP sign-in comes back to this server's\n * own callback instead: `deliverCallback`); the client sends the code back with `complete`, which\n * checks `state` here and hands the code to the waiting login: zidane's\n * providers read it through their manual-input path (`callbackServer:\n * false`: nothing listens on this machine), an MCP login through an\n * injected callback. Paste-back and device-code flows ride the same calls.\n *\n * A provider's questions (a choice between flows, a free-text prompt) are\n * the client's to answer, never picked here: `begin` answers with a `step`\n * when one comes before the URL, `complete` when one comes after, and\n * `respond` delivers the answer. A provider that would listen on this\n * machine for the redirect (one that ignores `callbackServer: false`) is\n * refused: the client's browser could never reach that port.\n *\n * A flow is bound to the connection that began it, takes one code, and\n * expires; a dropped connection abandons its flows. Codes and tokens are\n * never logged nor returned.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { McpServerConfig } from '../../../types'\nimport type { HostOAuthBegin, HostOAuthComplete, HostOAuthStep } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { randomBytes } from 'node:crypto'\nimport { setProviderCredential } from '../../../chat/credentials'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { runIntegrationSignIn, runOAuthLogin, signsInWithIntegration } from '../../../chat/oauth'\nimport { canSignInRemotely } from '../../../chat/oauth-page/server'\nimport { loginMcpServer } from '../../../mcp/login'\nimport { pinnedMcpRedirectUri } from '../../../mcp/server-config'\nimport { SERVER_OAUTH_CALLBACK_PATH } from '../../browser'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\n/** How long a flow waits for its code. */\nexport const OAUTH_FLOW_TTL_MS = 10 * 60_000\n/** Open flows per connection. */\nconst MAX_FLOWS_PER_PEER = 4\n/** How long a login may take to produce its URL. */\nconst BEGIN_TIMEOUT_MS = 30_000\n\ntype Delivery = { code: string, state?: string } | { input: string }\n\ninterface Flow {\n id: string\n peer: HostPeer\n expiresAt: number\n /** The `state` the authorization URL carries; a code must come back with it. */\n expectedState?: string\n /** Where the browser is sent back (rebuilds a callback URL from a code + state). */\n redirectUri?: string\n /** The code comes back to this server's own callback (`deliverCallback`): the MCP server signed in to. */\n held?: string\n delivered: boolean\n deliver: (delivery: Delivery) => void\n result: Promise<HostOAuthComplete>\n abort: AbortController\n timer: ReturnType<typeof setTimeout>\n /** The provider's questions (absent: an MCP sign-in, which asks none). */\n steps?: StepChannel\n /** Where the flow stands for `respond`: its URL once known. */\n started?: Promise<Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>>\n /** Set once the URL was handed out: later questions come through `complete`. */\n begun?: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>\n}\n\ntype StepInput = { kind: 'select', message: string, options: Array<{ id: string, label: string }> } | { kind: 'prompt', message: string, placeholder?: string, allowEmpty?: boolean }\n\n/** A provider's questions, one at a time: asked by its login, answered by the client. */\ninterface StepChannel {\n ask: (step: StepInput) => Promise<string | undefined>\n /** The question waiting for its answer. */\n pending: () => HostOAuthStep | undefined\n /** The next question (the pending one, if any). */\n next: () => Promise<HostOAuthStep>\n answer: (stepId: string, value: string | undefined) => void\n}\n\nfunction stepChannel(signal: AbortSignal): StepChannel {\n let current: { step: HostOAuthStep, resolve: (value: string | undefined) => void } | undefined\n const waiters: Array<(step: HostOAuthStep) => void> = []\n return {\n ask: step => new Promise((resolve, reject) => {\n if (signal.aborted)\n return reject(new Error('The sign-in was cancelled.'))\n const full = { ...step, id: randomBytes(9).toString('base64url') } as HostOAuthStep\n current = { step: full, resolve }\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n for (const waiter of waiters.splice(0))\n waiter(full)\n }),\n pending: () => current?.step,\n next: () => (current ? Promise.resolve(current.step) : new Promise(resolve => waiters.push(resolve))),\n answer(stepId, value) {\n const step = current?.step\n if (!step || step.id !== stepId)\n throw new Error('That sign-in is not waiting on this question (answered already, or another one).')\n if (step.kind === 'select' && value !== undefined && !step.options.some(option => option.id === value))\n throw new InvalidParamsError(`\"${value}\" is not one of the choices.`)\n if (step.kind === 'prompt' && (value === undefined || (value.trim() === '' && !step.allowEmpty)))\n throw new InvalidParamsError('That question needs an answer.')\n const { resolve } = current!\n current = undefined\n resolve(value)\n },\n }\n}\n\ninterface Deferred<T> {\n promise: Promise<T>\n resolve: (value: T) => void\n}\n\nfunction deferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void\n const promise = new Promise<T>((r) => {\n resolve = r\n })\n return { promise, resolve }\n}\n\nconst LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '[::1]', '::1'])\n\n/**\n * Where an MCP sign-in may send the browser: `http://<loopback>:<port>/<path>`\n * on the client, or (`held`) this server's own callback at the origin the\n * client reaches it by, when it serves one. Nothing else.\n */\nfunction mcpRedirect(raw: unknown, serverCallback: boolean): { uri: string, held: boolean } {\n let url: URL | undefined\n try {\n url = typeof raw === 'string' ? new URL(raw) : undefined\n }\n catch {}\n const plain = url !== undefined && !url.username && !url.password && !url.search && !url.hash\n if (plain && serverCallback && (url!.protocol === 'https:' || url!.protocol === 'http:') && url!.pathname === SERVER_OAUTH_CALLBACK_PATH)\n return { uri: url!.toString(), held: true }\n if (!plain || url!.protocol !== 'http:' || !LOOPBACK_HOSTS.has(url!.hostname) || !url!.port)\n throw new InvalidParamsError(`redirectUri must be a loopback URL on the client (http://127.0.0.1:<port>/callback)${serverCallback ? ` or this server's ${SERVER_OAUTH_CALLBACK_PATH}` : ''}.`)\n return { uri: url!.toString(), held: false }\n}\n\n/** `state` in what a user pasted: a callback URL, a `code=…&state=…` query, or Anthropic's `code#state`. */\nfunction stateIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('state') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[1]\n if (value.includes('state='))\n return new URLSearchParams(value).get('state') ?? undefined\n return undefined\n}\n\n/** The code in a pasted callback URL / query / `code#state`. */\nfunction codeIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('code') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[0]\n if (value.includes('code='))\n return new URLSearchParams(value).get('code') ?? undefined\n return value || undefined\n}\n\nfunction isLoopbackUrl(raw: string | null): raw is string {\n if (!raw)\n return false\n try {\n const url = new URL(raw)\n return url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname)\n }\n catch {\n return false\n }\n}\n\n/** What a provider's manual-input path reads: the pasted text, or the callback URL rebuilt from a code + state. */\nfunction manualInput(delivery: Delivery, redirectUri: string | undefined): string {\n if ('input' in delivery)\n return delivery.input\n const query = new URLSearchParams({ code: delivery.code, ...(delivery.state !== undefined ? { state: delivery.state } : {}) }).toString()\n return redirectUri ? `${redirectUri}?${query}` : query\n}\n\n/** First of: what the login produced, its early end, a timeout, the abort. */\nasync function firstOf<T>(started: Promise<T>, login: Promise<unknown>, signal: AbortSignal): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n started,\n login.then(() => {\n throw new Error('The sign-in finished without a browser step (already signed in?).')\n }),\n new Promise<never>((_, reject) => {\n timer = setTimeout(reject, BEGIN_TIMEOUT_MS, new Error(`The sign-in did not produce an authorization URL within ${BEGIN_TIMEOUT_MS / 1000}s.`))\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n }),\n ])\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * A provider's login, running here for a client: its URL (once known), its\n * questions, the code the client delivers, its stored result. Refused for a\n * provider that would listen on this machine (see the module header).\n */\nfunction startProviderLogin(auth: ProviderAuth, provider: unknown) {\n const descriptor = auth.descriptorOf(provider)\n const viaIntegration = signsInWithIntegration(descriptor)\n if (!descriptor.oauthProvider && !viaIntegration)\n throw new Error(`OAuth not supported for ${descriptor.label} (${descriptor.key}). Use an API key instead.`)\n // An integration's flow honors `callbackServer: false` (PKCE reads the pasted redirect; device flows need no listener).\n if (!viaIntegration && descriptor.oauthProvider && !canSignInRemotely(descriptor.oauthProvider))\n throw new Error(`${descriptor.label}'s sign-in can't run from another computer: it waits for the browser on a port of the server's own machine. Sign in on the server machine or use an API key.`)\n const abort = new AbortController()\n const code = deferred<string>()\n const steps = stepChannel(abort.signal)\n const url = deferred<{ url: string, instructions?: string, userCode?: string, device?: true }>()\n const login = (viaIntegration ? runIntegrationSignIn : runOAuthLogin)(descriptor, {\n onUrl: (u, instructions) => url.resolve({ url: u, ...(instructions ? { instructions } : {}) }),\n onDeviceCode: info => url.resolve({ url: info.verificationUri, userCode: info.userCode, device: true }),\n // The loopback's callback URL, or what the user pasted.\n onManualCodeInput: () => code.promise,\n // The provider's own questions go to the client (never answered here).\n onPrompt: prompt => steps.ask({ kind: 'prompt', message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }).then(value => value ?? ''),\n onSelect: prompt => steps.ask({ kind: 'select', message: prompt.message, options: prompt.options.map(option => ({ id: option.id, label: option.label })) }),\n signal: abort.signal,\n callbackServer: false,\n openBrowser: false,\n })\n login.catch(() => undefined)\n // Where the flow stands once it has its URL (the loopback redirect the code is rebuilt for).\n let redirectUri: string | undefined\n const started = url.promise.then((first): Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> => {\n if (!first.device) {\n const redirect = new URL(first.url).searchParams.get('redirect_uri')\n if (isLoopbackUrl(redirect))\n redirectUri = redirect\n }\n return {\n url: first.url,\n mode: first.device ? 'device' : redirectUri ? 'loopback' : 'browser',\n ...(redirectUri ? { redirectUri } : {}),\n ...(first.userCode ? { userCode: first.userCode } : {}),\n ...(first.instructions ? { instructions: first.instructions } : {}),\n }\n })\n started.catch(() => undefined)\n const result = login.then((credentials): HostOAuthComplete => {\n // An integration's registry stored the connection itself.\n if (!viaIntegration)\n setProviderCredential(auth.dataDir(), descriptor, { kind: 'oauth', ...(credentials as Awaited<ReturnType<typeof runOAuthLogin>>) })\n auth.applied(descriptor)\n return { provider: auth.statusOf(descriptor.key) }\n })\n return { login, abort, result, steps, started, deliver: (delivery: Delivery) => code.resolve(manualInput(delivery, redirectUri)) }\n}\n\n/** The flow `flowId` names, if it exists and belongs to this connection. */\nfunction flowOf(flows: ReadonlyMap<string, Flow>, flowId: unknown, peer: HostPeer): Flow {\n const flow = typeof flowId === 'string' ? flows.get(flowId) : undefined\n if (!flow)\n throw new Error('No sign-in with that id: it finished, expired or was cancelled. Start it again.')\n if (flow.peer !== peer)\n throw new Error('That sign-in belongs to another connection.')\n return flow\n}\n\n/** Hand the flow its code (from the client's loopback) or pasted input, once, after checking its `state`. */\nfunction deliverCode(flow: Flow, p: { code?: unknown, state?: unknown, input?: unknown }, end: (flow: Flow, reason: string) => void): void {\n const code = typeof p.code === 'string' && p.code !== '' ? p.code : undefined\n const input = typeof p.input === 'string' && p.input.trim() !== '' ? p.input : undefined\n if (code === undefined && input === undefined)\n return\n if (flow.delivered)\n throw new Error('That sign-in already received its code.')\n const state = code !== undefined ? (typeof p.state === 'string' ? p.state : undefined) : stateIn(input!)\n // A code from the loopback must carry the flow's state; a pasted bare code (Anthropic's page) may omit it.\n if (flow.expectedState !== undefined && (state !== undefined || code !== undefined) && state !== flow.expectedState) {\n end(flow, 'OAuth state mismatch.')\n throw new Error('OAuth state mismatch: the sign-in was refused. Start it again.')\n }\n flow.delivered = true\n flow.deliver(code !== undefined ? { code, ...(state !== undefined ? { state } : {}) } : { input: input! })\n}\n\n/** The browser back at the server's callback: the code to the held flow its `state` names (or the refusal ends it). */\nfunction deliverCallback(flows: ReadonlyMap<string, Flow>, query: URLSearchParams, end: (flow: Flow, reason: string) => void): string | undefined {\n const state = query.get('state')\n const flow = state ? [...flows.values()].find(f => f.held && f.expectedState === state) : undefined\n if (!flow?.held || flow.delivered)\n return undefined\n const code = query.get('code')\n if (!code) {\n end(flow, query.get('error_description') ?? query.get('error') ?? 'The sign-in was refused.')\n return flow.held\n }\n flow.delivered = true\n flow.deliver({ code, state: state! })\n return flow.held\n}\n\nexport function createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected, serverCallback = false, ttlMs = OAUTH_FLOW_TTL_MS }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n auth: ProviderAuth\n /** Follows each MCP sign-in, so the MCP servers page shows it. */\n mcpStatus: McpStatusTracker\n isConnected: (peer: HostPeer) => boolean\n /** This host serves {@link SERVER_OAUTH_CALLBACK_PATH} (a zidane-server): a browser client's MCP sign-in may redirect there. */\n serverCallback?: boolean\n ttlMs?: number\n}): {\n methods: Handlers<'auth.oauth.begin' | 'auth.oauth.complete' | 'auth.oauth.respond' | 'auth.oauth.cancel'>\n releasePeer: (peer: HostPeer) => void\n /** The browser came back to the server's callback: hands the code to the flow its `state` names. The MCP server it signs in to; `undefined`: no such flow waits. */\n deliverCallback: (query: URLSearchParams) => string | undefined\n} {\n const flows = new Map<string, Flow>()\n\n const end = (flow: Flow, reason: string): void => {\n clearTimeout(flow.timer)\n flows.delete(flow.id)\n if (!flow.abort.signal.aborted)\n flow.abort.abort(new Error(reason))\n }\n\n /** Register a flow whose login is already running; it ends at expiry, on cancel, or once settled and collected. */\n function register(peer: HostPeer, parts: { abort: AbortController, deliver: Flow['deliver'], result: Promise<HostOAuthComplete>, expectedState?: string, redirectUri?: string, held?: string, steps?: StepChannel, started?: Flow['started'] }): Flow {\n const id = randomBytes(24).toString('base64url')\n const flow: Flow = {\n id,\n peer,\n expiresAt: Date.now() + ttlMs,\n delivered: false,\n ...parts,\n timer: undefined as unknown as ReturnType<typeof setTimeout>,\n }\n flow.timer = setTimeout(end, ttlMs, flow, 'The sign-in expired.')\n flow.timer.unref?.()\n // Nobody may be waiting on it (expired, abandoned): never an unhandled rejection.\n flow.result.catch(() => undefined)\n flows.set(id, flow)\n return flow\n }\n\n const ownFlows = (peer: HostPeer): Flow[] => [...flows.values()].filter(flow => flow.peer === peer)\n /** MCP begins in flight per connection: counted against the cap before their flow registers. */\n const startingMcp = new Map<HostPeer, number>()\n\n async function beginProvider(peer: HostPeer, provider: unknown): Promise<HostOAuthBegin> {\n const { login, ...parts } = startProviderLogin(auth, provider)\n const flow = register(peer, parts)\n try {\n return await stateOf(flow, login)\n }\n catch (err) {\n end(flow, 'The sign-in did not start.')\n throw err\n }\n }\n\n /** The flow's URL, or the question it waits on first; its `state` and redirect recorded once the URL is known. */\n async function stateOf(flow: Flow, login: Promise<unknown>): Promise<HostOAuthBegin> {\n const steps = flow.steps!\n const next = await firstOf<{ step: HostOAuthStep } | { begin: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> }>(\n Promise.race([flow.started!.then(begin => ({ begin })), steps.next().then(step => ({ step }))]),\n login,\n flow.abort.signal,\n )\n if ('step' in next)\n return { flowId: flow.id, url: '', mode: 'step', step: next.step, expiresAt: flow.expiresAt }\n const begin = next.begin\n flow.begun = begin\n if (begin.mode !== 'device') {\n const authorize = new URL(begin.url)\n flow.expectedState = authorize.searchParams.get('state') ?? undefined\n if (begin.redirectUri)\n flow.redirectUri = begin.redirectUri\n }\n return { flowId: flow.id, ...begin, expiresAt: flow.expiresAt }\n }\n\n async function beginMcp(peer: HostPeer, p: { mcpServer: string, cwd?: string, kind?: string, redirectUri?: string }): Promise<HostOAuthBegin> {\n const asked = mcpRedirect(p.redirectUri, serverCallback)\n const dir = catalogFolder({ env, host }, p.cwd, p.kind)\n const config = await env.runtimeConfig(dir)\n const settings = env.readSettings()\n const { servers } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false })\n const entry: McpServerConfig | undefined = servers.find(server => server.config.name === p.mcpServer)?.config\n if (!entry)\n throw new Error(`No MCP server \"${p.mcpServer}\" in that folder's catalog.`)\n // A pre-registered client's redirect is the one registered with the\n // provider; the client rebinds its listener to it (`redirectUri` below),\n // or a browser client has the user paste it.\n const redirectUri = pinnedMcpRedirectUri(entry) ?? asked.uri\n const held = redirectUri === asked.uri && asked.held ? entry.name : undefined\n const abort = new AbortController()\n const state = randomBytes(24).toString('base64url')\n const callbackCode = deferred<{ code: string, state?: string }>()\n const started = deferred<{ url: string }>()\n const login = loginMcpServer(entry, {\n store: env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()),\n signal: abort.signal,\n state,\n timeoutMs: ttlMs,\n // The client's loopback; the code comes back through `complete`.\n callback: { redirectUri, promise: callbackCode.promise, close: async () => undefined },\n onAuthorizationUrl: url => started.resolve({ url: url.toString() }),\n })\n login.catch(() => undefined)\n const first = await firstOf(started.promise, login, abort.signal).catch((err) => {\n abort.abort()\n throw err\n })\n const result = login.then(() => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n return { mcpServer: entry.name }\n })\n void mcpStatus.signingIn(entry.name, login, abort.signal)\n const flow = register(peer, {\n abort,\n result,\n expectedState: state,\n redirectUri,\n ...(held ? { held } : {}),\n deliver: (delivery) => {\n if ('input' in delivery) {\n const code = codeIn(delivery.input)\n const pastedState = stateIn(delivery.input)\n if (code)\n callbackCode.resolve({ code, ...(pastedState !== undefined ? { state: pastedState } : {}) })\n return\n }\n callbackCode.resolve(delivery)\n },\n })\n return { flowId: flow.id, url: first.url, ...(held ? { mode: 'browser' } : { mode: 'loopback', redirectUri }), expiresAt: flow.expiresAt }\n }\n\n return {\n methods: {\n 'auth.oauth.begin': async (p, peer) => {\n const target = [p.provider, p.mcpServer].filter(value => value !== undefined)\n if (target.length !== 1 || typeof target[0] !== 'string' || target[0] === '')\n throw new InvalidParamsError('auth.oauth.begin needs exactly one of \"provider\" or \"mcpServer\".')\n if (ownFlows(peer).length + (startingMcp.get(peer) ?? 0) >= MAX_FLOWS_PER_PEER)\n throw new Error(`This connection already has ${MAX_FLOWS_PER_PEER} sign-ins open: finish or cancel one first.`)\n let begun: HostOAuthBegin\n if (p.provider !== undefined) {\n begun = await beginProvider(peer, p.provider)\n }\n else {\n // An MCP flow registers only once its URL is known; hold its slot meanwhile.\n startingMcp.set(peer, (startingMcp.get(peer) ?? 0) + 1)\n try {\n begun = await beginMcp(peer, { mcpServer: p.mcpServer!, ...(p.cwd !== undefined ? { cwd: p.cwd } : {}), ...(p.kind !== undefined ? { kind: p.kind } : {}), ...(p.redirectUri !== undefined ? { redirectUri: p.redirectUri } : {}) })\n }\n finally {\n const left = (startingMcp.get(peer) ?? 1) - 1\n if (left > 0)\n startingMcp.set(peer, left)\n else\n startingMcp.delete(peer)\n }\n }\n // Dropped while it started: nobody will finish it.\n if (!isConnected(peer)) {\n const flow = flows.get(begun.flowId)\n if (flow)\n end(flow, 'The connection closed.')\n }\n return begun\n },\n\n 'auth.oauth.complete': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n deliverCode(flow, p, end)\n let asking = false\n try {\n // The login may ask something first: the client answers (`respond`), then calls again.\n const outcome = await (flow.steps\n ? Promise.race([flow.result, flow.steps.next().then(step => ({ step }))])\n : flow.result)\n asking = outcome.step !== undefined\n return outcome\n }\n catch (err) {\n throw new Error(flow.abort.signal.aborted && flow.abort.signal.reason instanceof Error ? flow.abort.signal.reason.message : err instanceof Error ? err.message : String(err))\n }\n finally {\n if (!asking)\n end(flow, 'The sign-in finished.')\n }\n },\n\n 'auth.oauth.respond': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n if (!flow.steps || typeof p.stepId !== 'string')\n throw new InvalidParamsError('auth.oauth.respond needs the flow\\'s \"stepId\".')\n if (p.value !== undefined && typeof p.value !== 'string')\n throw new InvalidParamsError('\"value\" must be a string.')\n const cancelled = p.value === undefined && flow.steps.pending()?.kind === 'select'\n flow.steps.answer(p.stepId, p.value)\n if (cancelled) {\n end(flow, 'The sign-in was cancelled.')\n throw new Error('The sign-in was cancelled (no choice made).')\n }\n // After the URL: where it stands (`complete` again waits for the rest).\n return flow.begun ? { flowId: flow.id, ...flow.begun, expiresAt: flow.expiresAt } : stateOf(flow, flow.result)\n },\n\n 'auth.oauth.cancel': (p, peer) => {\n const flow = typeof p.flowId === 'string' ? flows.get(p.flowId) : undefined\n if (!flow || flow.peer !== peer)\n return { cancelled: false }\n end(flow, 'The sign-in was cancelled.')\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const flow of ownFlows(peer))\n end(flow, 'The connection closed.')\n },\n deliverCallback: query => deliverCallback(flows, query, end),\n }\n}\n","/**\n * What the setup wizard reads on the host's machine for a client: what it\n * finds there (`onboarding.detect`: credentials, other agents, local model\n * servers), the providers Connect lists with their custom fields and default\n * model (`onboarding.providers`), a Claude Code setup and its import\n * (`claudeImport.*`; the import copies commands the host will run, so it\n * goes through the install gate, `guardedInstall`), a skill source's\n * skills (`skills.browse`) and an extension source's extensions\n * (`extensions.browse`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { RemoteInstallsOptions } from './catalog-install'\nimport type { Handlers } from './types'\nimport { homedir } from 'node:os'\nimport { detectAuth } from '../../../chat/auth'\nimport { countClaudeSessionFiles, hasClaudeCodeSetup, importFromClaudeCode, previewClaudeImport } from '../../../chat/claude-import'\nimport { listExtensionSource } from '../../../chat/extension-browse'\nimport { connectorGithubToken, detectOnboardingEnvironment, onboardingProviders } from '../../../chat/host/onboarding/index'\nimport { browseSkillSource } from '../../../skills/browse'\nimport { guardedInstall } from './catalog-install'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\ntype OnboardingMethod = 'onboarding.detect' | 'onboarding.providers' | 'claudeImport.detect' | 'claudeImport.preview' | 'claudeImport.run' | 'skills.browse' | 'extensions.browse'\n\n/** Longest source spec browsed. */\nconst MAX_SOURCE_LENGTH = 500\n\nexport function createOnboardingHandlers({ host, env, broadcast, installs }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** A zidane-server's `allowRemoteInstalls` and audit (`./catalog-install`). Absent: the import is refused. */\n installs?: RemoteInstallsOptions\n}): Handlers<OnboardingMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n /** The providers of `folder`, extension ones included. */\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).providers\n const hasSessions = async (): Promise<boolean> => {\n try {\n return (await env.store.list({ limit: 1 })).length > 0\n }\n catch {\n // An unreadable store: the other signals decide.\n return false\n }\n }\n\n return {\n 'onboarding.detect': async (p) => {\n const cwd = folderOf(p.cwd)\n return detectOnboardingEnvironment({\n dataDir: env.userDataDir(),\n registry: await registryOf(cwd),\n state: env.config.stateStore.load(),\n sessions: await hasSessions(),\n // A browser's first visit says nothing about this machine.\n surfaceFirstRun: false,\n cwd,\n })\n },\n 'onboarding.providers': async (p) => {\n const registry = await registryOf(folderOf(p.cwd))\n return onboardingProviders(registry, detectAuth(env.userDataDir(), registry)).map((provider) => {\n const defaultModel = registry[provider.key]?.defaultModel\n return defaultModel ? { ...provider, defaultModel } : provider\n })\n },\n 'claudeImport.detect': (p) => {\n if (!hasClaudeCodeSetup())\n return { available: false, counts: { project: 0, all: 0 } }\n return { available: true, counts: countClaudeSessionFiles({ cwd: folderOf(p.cwd) }) }\n },\n 'claudeImport.preview': p => previewClaudeImport({ cwd: folderOf(p.cwd), prefix: env.config.prefix }),\n 'claudeImport.run': (p, peer) => guardedInstall(installs, peer, 'claudeImport.run', { sessions: p.sessions === true, mcps: p.mcps === true, skills: p.skills === true, commands: p.commands === true }, async () => {\n const commands = p.commands === true\n const summary = await importFromClaudeCode(env.store, {\n cwd: folderOf(p.cwd),\n prefix: env.config.prefix,\n sessions: p.sessions === true,\n mcps: p.mcps === true,\n skills: p.skills === true,\n commands,\n agents: typeof p.agents === 'boolean' ? p.agents : commands,\n allProjects: p.allProjects === true,\n })\n // MCP servers, skills and subagents are read when an agent is built.\n if (summary.mcps || summary.skills || summary.agents)\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n if (summary.mcps)\n broadcast({ kind: 'catalog:changed', catalog: 'mcps' })\n if (summary.skills)\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n return summary\n }),\n // The GitHub login raises GitHub's limit from 60 to 5,000 calls an hour.\n 'skills.browse': async (p) => {\n if (typeof p.source !== 'string' || p.source.trim() === '' || p.source.length > MAX_SOURCE_LENGTH)\n throw new InvalidParamsError(`source must be a non-empty string of at most ${MAX_SOURCE_LENGTH} characters.`)\n const token = (await connectorGithubToken())?.token\n return browseSkillSource(p.source, token ? { token } : {})\n },\n // Manifests only: no extension code runs. A relative folder is the host user's home's.\n 'extensions.browse': async (p) => {\n if (typeof p.source !== 'string' || p.source.trim() === '' || p.source.length > MAX_SOURCE_LENGTH)\n throw new InvalidParamsError(`source must be a non-empty string of at most ${MAX_SOURCE_LENGTH} characters.`)\n const token = (await connectorGithubToken())?.token\n return listExtensionSource(p.source, { cwd: homedir(), ...(token ? { token } : {}) })\n },\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/** The orchestration verbs, called by a connection: its token is the caller. */\nimport type { Caller } from '../../../chat/host/orchestration'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { scopeAllows } from '../../scopes'\nimport { InvalidParamsError, nonNegativeInt, requiredString, sessionIdOf } from './params'\nimport { PolicyScopeError } from './session-policy'\n\ntype OrchestrationMethod\n = | 'orchestration.main' | 'orchestration.createWorker' | 'orchestration.list' | 'orchestration.read'\n | 'orchestration.send' | 'orchestration.steer' | 'orchestration.cancel' | 'orchestration.transcript'\n | 'orchestration.wait' | 'orchestration.events' | 'orchestration.pending' | 'orchestration.answer' | 'orchestration.approve'\n\n/** The caller a connection acts as: its token's principal, or the local window. Never a session: a client cannot speak for one. */\nexport function peerCaller(peer: HostPeer): Caller {\n return { kind: 'client', ...(peer.principal ? { principal: peer.principal } : {}), ...(peer.principalName ? { name: peer.principalName } : {}) }\n}\n\nexport function createOrchestrationHandlers({ host }: { host: ChatHost }): Handlers<OrchestrationMethod> {\n const o = host.orchestration\n return {\n 'orchestration.main': () => o.ensureMain(),\n 'orchestration.createWorker': (params, peer) => {\n if (typeof params?.cwd !== 'string')\n throw new InvalidParamsError('cwd must be a string (empty for none).')\n // A session holding `interactions` answers tool approvals (`approve`), so creating one needs the approve scope too.\n const grant = peer?.grant\n if (grant && !scopeAllows(grant, 'approve') && Array.isArray(params.tools) && params.tools.includes('interactions'))\n throw new PolicyScopeError('orchestration.createWorker', 'with the `interactions` tool', grant)\n return o.create(peerCaller(peer), params)\n },\n 'orchestration.list': (p, peer) => o.list(peerCaller(peer), nonNegativeInt(p?.limit, 'limit')),\n 'orchestration.read': (p, peer) => o.read(peerCaller(peer), sessionIdOf(p)),\n 'orchestration.send': (p, peer) => o.send(peerCaller(peer), sessionIdOf(p), requiredString(p.prompt, 'prompt')),\n 'orchestration.steer': (p, peer) => o.steer(peerCaller(peer), sessionIdOf(p), requiredString(p.message, 'message')),\n 'orchestration.cancel': (p, peer) => o.cancel(peerCaller(peer), sessionIdOf(p)),\n 'orchestration.transcript': (p, peer) => o.transcript(peerCaller(peer), sessionIdOf(p), nonNegativeInt(p.limit, 'limit')),\n 'orchestration.wait': (p, peer) => o.wait(peerCaller(peer), sessionIdOf(p), nonNegativeInt(p.timeoutSec, 'timeoutSec')),\n 'orchestration.events': (p, peer) => o.events(peerCaller(peer), { ...(p ?? {}), ...(p?.limit !== undefined ? { limit: nonNegativeInt(p.limit, 'limit') } : {}), ...(p?.since !== undefined ? { since: nonNegativeInt(p.since, 'since') } : {}) }),\n 'orchestration.pending': (p, peer) => o.pending(peerCaller(peer), p?.sessionId),\n 'orchestration.answer': (p, peer) => {\n const response = p.response as { kind?: unknown } | undefined\n if (!response || typeof response !== 'object' || (response.kind !== 'plan' && response.kind !== 'question'))\n throw new InvalidParamsError('response must be a plan or question response.')\n return o.answer(peerCaller(peer), requiredString(p.requestId, 'requestId'), p.response)\n },\n 'orchestration.approve': (p, peer) => {\n if (p.decision === undefined || p.decision === null)\n throw new InvalidParamsError('decision is required.')\n return o.approve(peerCaller(peer), requiredString(p.requestId, 'requestId'), p.decision)\n },\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Extension side panels and command palette items for a client's app\n * (`panels.*`, `palette.*`): run here (`../../../extensions/panel-host`),\n * answered as data. A panel runs in a read-only scope of its folder's\n * project and the session it shows beside (that session's artifacts, the\n * project's). Live updates go to the connections watching: `panel:changed`,\n * `palette:changed`, one subscription per panel or folder however many\n * watch it; a dropped connection releases its own.\n */\nimport type { PanelHostDeps } from '../../../extensions/panel-host'\nimport type { SessionStore } from '../../../session/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isPaletteContext } from '../../../chat/palette'\nimport { projectRootOf } from '../../../chat/project-root'\nimport { listExtensionPaletteItems, loadExtensionPanel, panelSummaries, runExtensionPaletteItem, runExtensionPanelAction, subscribeExtensionPalette, subscribeExtensionPanel } from '../../../extensions/panel-host'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, requiredString } from './params'\n\ntype PanelMethod\n = | 'panels.list' | 'panels.load' | 'panels.action' | 'panels.watch' | 'panels.unwatch'\n | 'palette.list' | 'palette.run' | 'palette.watch' | 'palette.unwatch'\n\nexport function createPanelHandlers({ host, env, store, onClose }: {\n host: Pick<ChatHost, 'resolveFolder'>\n env: DaemonEnvironment\n store: Pick<SessionStore, 'listArtifacts'>\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<PanelMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, requiredString(cwd, 'cwd'))\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).extensions\n const panelOf = async (folder: string, panelId: unknown) => (await registryOf(folder)).panels.find(p => p.id === panelId)\n const deps: PanelHostDeps = {\n ...(env.hostRuntime ? { hostRuntime: env.hostRuntime } : {}),\n listArtifacts: async query => (await store.listArtifacts?.(query)) ?? [],\n artifactsEnabled: () => env.readSettings().artifacts !== false,\n projectRootOf,\n }\n const paletteContext = (ctx: unknown) => {\n if (!isPaletteContext(ctx))\n throw new InvalidParamsError('ctx must be a palette context.')\n return ctx\n }\n\n // Keyed by the folder as each client names it: the signals carry that name back.\n const panelWatches = createSharedWatches<HostPeer>()\n const paletteWatches = createSharedWatches<HostPeer>()\n onClose((peer) => {\n panelWatches.release(peer)\n paletteWatches.release(peer)\n })\n const panelKey = (cwd: string, panelId: string): string => `${cwd}\\u0000${panelId}`\n\n return {\n 'panels.list': async p => panelSummaries((await registryOf(folderOf(p.cwd))).panels),\n 'panels.load': async (p) => {\n const folder = folderOf(p.cwd)\n return loadExtensionPanel(await panelOf(folder, p.panelId), p.ctx, folder, deps)\n },\n 'panels.action': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPanelAction(await panelOf(folder, p.panelId), requiredString(p.actionId, 'actionId'), p.payload, p.ctx, folder, deps)\n },\n 'panels.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n const panelId = requiredString(p.panelId, 'panelId')\n const key = panelKey(p.cwd, panelId)\n return panelWatches.watch(key, peer, async () => subscribeExtensionPanel(await panelOf(folder, panelId), () => {\n for (const watcher of panelWatches.owners(key))\n watcher.send({ kind: 'panel:changed', cwd: p.cwd, panelId })\n }))\n },\n 'panels.unwatch': (p, peer) => {\n panelWatches.unwatch(panelKey(requiredString(p.cwd, 'cwd'), requiredString(p.panelId, 'panelId')), peer)\n },\n\n 'palette.list': async (p) => {\n const folder = folderOf(p.cwd)\n return listExtensionPaletteItems((await registryOf(folder)).palette, folder, paletteContext(p.ctx))\n },\n 'palette.run': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPaletteItem((await registryOf(folder)).palette, requiredString(p.source, 'source'), requiredString(p.itemId, 'itemId'), folder, paletteContext(p.ctx))\n },\n 'palette.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n return paletteWatches.watch(p.cwd, peer, async () => subscribeExtensionPalette((await registryOf(folder)).palette, () => {\n for (const watcher of paletteWatches.owners(p.cwd))\n watcher.send({ kind: 'palette:changed', cwd: p.cwd })\n }))\n },\n 'palette.unwatch': (p, peer) => {\n paletteWatches.unwatch(requiredString(p.cwd, 'cwd'), peer)\n },\n }\n}\n","/**\n * The host's own performance, for a client's Settings › Performance on it:\n * the samples held (`perf.history`), each new one to the connections\n * watching (`perf.watch`, `perf:sample`), and the OS threads of a process\n * it lists (`perf.threads`). The monitor (`src/perf/host.ts`) is made on\n * the first call and samples only while a connection watches; a dropped\n * connection releases its watches, and the host's shutdown stops them all.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPerf } from '../../../perf/host'\nimport type { SessionStore } from '../../../session'\nimport type { HostKind } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { createHostPerf } from '../../../perf/host'\nimport { InvalidParamsError } from './params'\n\n/** The host process's row in its samples. */\nconst LABEL: Record<HostKind, string> = { 'server': 'Server', 'daemon': 'Daemon', 'in-process': 'Host' }\n\n/**\n * This host's monitor, made on the first call: its process labelled by its\n * kind, its sessions' MCP processes, its sessions' titles from its store.\n *\n * @param host - The host: its kind, engine and store.\n * @param host.kind - What it reports itself as (`ipc.hello`'s `hostKind`).\n * @param host.host - Its engine (the MCP server processes).\n * @param host.store - Its session store (the titles).\n */\nexport function lazyHostPerf({ kind, host, store }: { kind: HostKind, host: Pick<ChatHost, 'mcpServers'>, store: Pick<SessionStore, 'getMeta'> }): () => HostPerf {\n let monitor: HostPerf | null = null\n return () => monitor ??= createHostPerf({\n label: LABEL[kind],\n mcpInstances: () => host.mcpServers.instances(),\n sessionTitle: async (sessionId) => {\n const title = (await store.getMeta?.(sessionId))?.metadata.title\n return typeof title === 'string' && title.trim() ? title : undefined\n },\n })\n}\n\nexport function createPerfHandlers({ perf, onPeerClose, onShutdown }: {\n /** The host's monitor (made once, on first use). */\n perf: () => HostPerf\n /** Registers what to release when a connection drops (its watches). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n /** Registers what to stop when the host shuts down. */\n onShutdown: (stop: () => void) => void\n}): Handlers<'perf.watch' | 'perf.unwatch' | 'perf.history' | 'perf.threads'> {\n const watchers = createSharedWatches<HostPeer>()\n onPeerClose(peer => watchers.release(peer))\n onShutdown(() => watchers.reset())\n return {\n 'perf.watch': (_p, peer) => watchers.watch('perf', peer, async () => perf().watch((sample) => {\n for (const watcher of watchers.owners('perf'))\n watcher.send({ kind: 'perf:sample', sample })\n })),\n 'perf.unwatch': (_p, peer) => {\n watchers.unwatch('perf', peer)\n },\n 'perf.history': () => ({ samples: perf().history() }),\n 'perf.threads': async (p) => {\n if (!Number.isInteger(p?.pid) || p.pid <= 0)\n throw new InvalidParamsError('perf.threads: \"pid\" must be a process id.')\n return { threads: await perf().threads(p.pid) }\n },\n }\n}\n","/**\n * The integrations the host's clients registered (`integrations.*`): each one\n * belongs to the peer that registered it and goes away when that peer\n * disconnects. State only; the methods and the signal live in\n * `./handlers/integrations`, as presence's do next to `./peers`.\n */\nimport type { IntegrationInfo, IntegrationState } from '../../chat/integrations'\nimport type { HostPeer } from './peers'\n\n/** Integrations one connection may hold at once. */\nexport const MAX_INTEGRATIONS_PER_PEER = 32\n\n/** What a client registers: an {@link IntegrationInfo} without its `since`. */\nexport interface IntegrationEntry {\n name: string\n kind: string\n state: IntegrationState\n detail?: string\n}\n\nexport interface IntegrationRegistry {\n /**\n * Add `peer`'s integration, or replace the one it registered under that name.\n * @returns Whether the list changed.\n * @throws {Error} When another peer registered the name, or `peer` already holds {@link MAX_INTEGRATIONS_PER_PEER} others.\n */\n register: (peer: HostPeer, entry: IntegrationEntry) => boolean\n /**\n * Set the state and detail of `peer`'s integration (an absent detail clears it).\n * @returns Whether the list changed.\n * @throws {Error} When `peer` registered no integration under that name.\n */\n update: (peer: HostPeer, entry: Omit<IntegrationEntry, 'kind'>) => boolean\n /** Every integration, in registration order. */\n list: () => IntegrationInfo[]\n /**\n * Drop every integration `peer` registered.\n * @returns Whether the list changed.\n */\n release: (peer: HostPeer) => boolean\n}\n\n/**\n * @param now - The clock `since` reads (epoch ms).\n */\nexport function createIntegrationRegistry(now: () => number = Date.now): IntegrationRegistry {\n const entries = new Map<string, { owner: HostPeer, info: IntegrationInfo }>()\n\n /** Store `entry` for `owner`; `since` moves only when the state does. */\n function put(owner: HostPeer, entry: IntegrationEntry): boolean {\n const previous = entries.get(entry.name)?.info\n const info: IntegrationInfo = {\n name: entry.name,\n kind: entry.kind,\n state: entry.state,\n ...(entry.detail !== undefined ? { detail: entry.detail } : {}),\n since: previous && previous.state === entry.state ? previous.since : now(),\n }\n entries.set(entry.name, { owner, info })\n return !previous || previous.kind !== info.kind || previous.state !== info.state || previous.detail !== info.detail\n }\n\n return {\n register(peer, entry) {\n const existing = entries.get(entry.name)\n if (existing && existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is registered by another connection.`)\n if (!existing && [...entries.values()].filter(e => e.owner === peer).length >= MAX_INTEGRATIONS_PER_PEER)\n throw new Error(`This connection already registered ${MAX_INTEGRATIONS_PER_PEER} integrations, the most one may.`)\n return put(peer, entry)\n },\n update(peer, entry) {\n const existing = entries.get(entry.name)\n if (!existing || existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is not registered by this connection.`)\n return put(peer, { ...entry, kind: existing.info.kind })\n },\n list: () => [...entries.values()].map(entry => ({ ...entry.info })),\n release(peer) {\n let changed = false\n for (const [name, entry] of entries) {\n if (entry.owner === peer) {\n entries.delete(name)\n changed = true\n }\n }\n return changed\n },\n }\n}\n","/** Integrations the host's clients run (a channel), as they report them, and the signal that follows each change. */\nimport type { IntegrationState } from '../../../chat/integrations'\nimport type { HostSignal } from '../../protocol'\nimport type { IntegrationRegistry } from '../integrations'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { CHANNEL_KIND_PREFIX, hasControlCharacters, INTEGRATION_STATES, isIntegrationState } from '../../../chat/integrations'\nimport { scopeAllows } from '../../scopes'\nimport { createIntegrationRegistry } from '../integrations'\nimport { InvalidParamsError } from './params'\nimport { PolicyScopeError } from './session-policy'\n\n/** Longest `name` and `kind`. */\nconst MAX_NAME_LENGTH = 200\n/** Longest `detail`. */\nconst MAX_DETAIL_LENGTH = 2000\n\nfunction boundedString(value: unknown, name: string, max: number): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > max)\n throw new InvalidParamsError(`${name} must be a non-empty string of at most ${max} characters.`)\n return printable(value, name)\n}\n\n/** `value`, refused when it holds a control character (`channels status` and windows print it). */\nfunction printable(value: string, name: string): string {\n if (hasControlCharacters(value))\n throw new InvalidParamsError(`${name} must not contain control characters.`)\n return value\n}\n\n/** `kind`, refused when it claims to be a channel and the connection's token can't approve (a local connection can). */\nfunction kindFor(peer: HostPeer, kind: string): string {\n if (kind.startsWith(CHANNEL_KIND_PREFIX) && peer.grant && !scopeAllows(peer.grant, 'approve'))\n throw new PolicyScopeError('integrations.register', `with kind \"${CHANNEL_KIND_PREFIX}…\"`, peer.grant)\n return kind\n}\n\nfunction stateOf(value: unknown): IntegrationState {\n if (!isIntegrationState(value))\n throw new InvalidParamsError(`state must be one of ${INTEGRATION_STATES.join(', ')}.`)\n return value\n}\n\nfunction detailOf(value: unknown): { detail?: string } {\n if (value === undefined)\n return {}\n if (typeof value !== 'string' || value.length > MAX_DETAIL_LENGTH)\n throw new InvalidParamsError(`detail must be a string of at most ${MAX_DETAIL_LENGTH} characters.`)\n return { detail: printable(value, 'detail') }\n}\n\nexport function createIntegrationHandlers({ broadcast, onClose, registry = createIntegrationRegistry() }: {\n broadcast: (signal: HostSignal) => void\n /** Registers the peer-close cleanup (`PeerRegistry.onClose`). */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n registry?: IntegrationRegistry\n}): Handlers<'integrations.register' | 'integrations.update' | 'integrations.list'> {\n const changed = (didChange: boolean): void => {\n if (didChange)\n broadcast({ kind: 'integrations:changed', integrations: registry.list() })\n }\n onClose(peer => changed(registry.release(peer)))\n\n return {\n 'integrations.register': (p, peer) => {\n changed(registry.register(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n kind: kindFor(peer, boundedString(p?.kind, 'kind', MAX_NAME_LENGTH)),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.update': (p, peer) => {\n changed(registry.update(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.list': () => registry.list(),\n }\n}\n","/**\n * Who is connected: which sessions have windows attached, which one this\n * window watches, and the integrations (channels and other non-window\n * clients) that registered themselves.\n */\nimport type { DaemonEnvironment } from '../environment'\nimport type { PeerRegistry } from '../peers'\nimport type { Handlers } from './types'\nimport { createIntegrationHandlers } from './integrations'\n\nexport function createPresenceHandlers({ env, peers }: {\n env: DaemonEnvironment\n peers: Pick<PeerRegistry, 'computePresence' | 'broadcastPresence' | 'broadcast' | 'onClose'>\n}): Handlers<'presence.list' | 'presence.watch' | 'integrations.register' | 'integrations.update' | 'integrations.list'> {\n return {\n ...createIntegrationHandlers({ broadcast: peers.broadcast, onClose: peers.onClose }),\n 'presence.list': () => peers.computePresence(),\n 'presence.watch': (p, peer) => {\n peer.watching = p.sessionId\n peers.broadcastPresence()\n // Warm the per-cwd runtime config off the keystroke path: the first\n // suggest.resolve on a cold cwd would otherwise pay full extension\n // discovery inside the typist's wait (the 150ms provider deadline\n // starts only AFTER the registry exists). Fire-and-forget; the\n // 16-entry LRU keeps recently watched cwds hot.\n void env.store.load(p.sessionId).then((data) => {\n if (!data)\n return\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n return env.runtimeConfig(cwd)\n }).catch(() => undefined)\n },\n }\n}\n","/** The host-owned type-ahead queue every window shares. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SendTransform } from '../../../chat/host/prompt-transforms'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { createPromptSubmissions } from '../../../chat/host/prompt-transforms'\nimport { deduped } from '../send-requests'\nimport { promptFields } from './chat'\nimport { boundAttachments } from './drafts'\nimport { InvalidParamsError } from './params'\n\nexport function createQueueHandlers({ host, clearDraft, dedup, transforms }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n /** The extensions' prompt transforms (`ChatHost.transformPrompt`), run once on each `queue.add`. Absent: prompts go as sent. */\n transforms?: SendTransform\n}): Handlers<'queue.list' | 'queue.add' | 'queue.remove' | 'queue.update' | 'queue.attachments' | 'queue.pushNow'> {\n const submit = createPromptSubmissions(host, transforms)\n return {\n 'queue.list': p => host.queueList(p.sessionId),\n 'queue.add': async (p, peer) => {\n // Same cheap shape guards as `drafts.set` — a malformed peer payload\n // must not propagate a non-string into every window's queue box.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const activatedSkills = Array.isArray(p.activatedSkills)\n ? p.activatedSkills.filter((name): name is string => typeof name === 'string')\n : undefined\n const attachments = Array.isArray(p.attachments)\n ? boundAttachments(p.attachments)\n : undefined\n const asCommand = typeof p.asCommand === 'string' ? p.asCommand.slice(0, 128) : undefined\n const fields = promptFields(p)\n const delivery = p.delivery === 'steer' || p.delivery === 'followUp' ? p.delivery : undefined\n const result = await deduped(dedup, 'queue.add', p, () => submit.queueAdd(p.sessionId, text, activatedSkills, attachments, asCommand, fields, delivery))\n // Queuing/sending consumed the shared draft, same as a direct send\n // (not for a prompt sent from outside the composer).\n if (p.keepDraft !== true)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'queue.remove': p => host.queueRemove(p.sessionId, p.id),\n 'queue.update': p => host.queueUpdate(\n p.sessionId,\n p.id,\n typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : '',\n updatedAttachments(p.attachments),\n ),\n 'queue.attachments': p => host.queueAttachments(p.sessionId, p.id),\n 'queue.pushNow': p => host.queuePushNow(p.sessionId, p.id),\n }\n}\n\n/**\n * The list `queue.update` stores in place of an entry's attachments. An entry\n * that is malformed or over the budget is refused, not dropped: the list\n * REPLACES what is stored, so a quietly shorter list would delete the rest.\n */\nfunction updatedAttachments(list: unknown): ReturnType<typeof boundAttachments> | undefined {\n if (!Array.isArray(list))\n return undefined\n const bounded = boundAttachments(list)\n if (bounded.length !== list.length)\n throw new InvalidParamsError('attachments: an entry is malformed, or the list is over 24 MiB.')\n return bounded\n}\n","/** Reattach without a reload: replay a session's numbered signals from the host's log (`../signal-log`). */\nimport type { SignalLog } from '../signal-log'\nimport type { Handlers } from './types'\n\nexport function createResumeHandlers({ log }: { log: Pick<SignalLog, 'epoch' | 'replay'> }): Handlers<'sessions.resume'> {\n return {\n 'sessions.resume': (p) => {\n if (p.epoch !== log.epoch)\n return { ok: false, reason: 'epoch' }\n const signals = typeof p.afterSeq === 'number' ? log.replay(p.sessionId, p.afterSeq) : null\n return signals ? { ok: true, signals } : { ok: false, reason: 'gap' }\n },\n }\n}\n","/**\n * A zidane-server's log, for a client's Settings › Logs: the records its\n * bounded buffer holds (`logs.list`) and each new one to the connections\n * following it (`logs.watch`, `logs:record`). Another host has no buffer\n * and refuses both.\n */\nimport type { LogRecord, RingBufferSink } from '../../../logger'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\n\nconst NO_LOGS = 'This host keeps no log for clients (a zidane-server does).'\n\n/** A value as it can cross the wire: an error by its message, anything JSON can't hold by its text. */\nfunction wireValue(value: unknown): unknown {\n if (value instanceof Error)\n return value.message\n try {\n return JSON.parse(JSON.stringify(value) ?? 'null') as unknown\n }\n catch {\n return String(value)\n }\n}\n\n/** A record with its attributes made wire-safe (an extension may log anything). */\nfunction wireRecord(record: LogRecord): LogRecord {\n return { ...record, attrs: Object.fromEntries(Object.entries(record.attrs).map(([key, value]) => [key, wireValue(value)])) }\n}\n\nexport function createLogHandlers({ logs, onClose }: {\n logs?: RingBufferSink\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const buffer = (): RingBufferSink => {\n if (!logs)\n throw new Error(NO_LOGS)\n return logs\n }\n const followers = createSharedWatches<HostPeer>()\n onClose(peer => followers.release(peer))\n return {\n 'logs.list': () => ({ records: buffer().getRecords().map(wireRecord) }),\n 'logs.watch': (_p, peer) => {\n const sink = buffer()\n return followers.watch('log', peer, async () => sink.subscribe(() => {\n const last = sink.getRecords().at(-1)\n if (!last)\n return\n const record = wireRecord(last)\n for (const follower of followers.owners('log'))\n follower.send({ kind: 'logs:record', record })\n }))\n },\n 'logs.unwatch': (_p, peer) => {\n followers.unwatch('log', peer)\n },\n }\n}\n","/**\n * What only a zidane-server does: manage its tokens (`tokens.*`, and\n * `tokens:changed` to every window after a change), update itself\n * (`server.update.*`) and show its log (`logs.*`, `./logs`). Another host\n * answers them with a refusal.\n */\nimport type { RingBufferSink } from '../../../logger'\nimport type { HostSignal, ServerTokenInfo, ServerTokenScope, ServerUpdateStatus } from '../../protocol'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isValidMachineName } from '../../../chat/machine-protocol'\nimport { isClientScope } from '../../scopes'\nimport { createLogHandlers } from './logs'\nimport { InvalidParamsError } from './params'\n\nexport interface ServerUpdateControl {\n status: () => ServerUpdateStatus\n configure: (enabled: boolean) => ServerUpdateStatus\n check: () => Promise<ServerUpdateStatus>\n installNow: () => Promise<ServerUpdateStatus>\n}\n\n/** A zidane-server's token store, as its clients reach it (`src/server/server.ts` audits each call). */\nexport interface ServerTokensControl {\n createMachineToken: (name: string, by: string | undefined) => { id: string, name: string, token: string }\n list: () => ServerTokenInfo[]\n create: (name: string, scope: ServerTokenScope, by: string | undefined) => ServerTokenInfo & { token: string }\n /** `null`: no live token has that id. */\n revoke: (id: string, by: string | undefined) => ServerTokenInfo[] | null\n /** A one-time pairing code (`src/server/pairing.ts`); throws past the live-code cap. */\n pair: (scope: ClientScope, ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** A one-time machine join code (`src/ipc/machine/join.ts`); throws past the live-code cap or the server's longest lifetime. */\n machineInvite: (ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** Calls `listener` after the tokens changed, whoever changed them (a client, a pairing, the CLI). Returns the unsubscribe. */\n onChange: (listener: () => void) => () => void\n}\n\n/** Bounds of `tokens.pair`'s `ttlMs` (`src/server/pairing.ts`). */\nconst PAIR_TTL_MIN_MS = 30_000\nconst PAIR_TTL_MAX_MS = 60 * 60_000\n\nconst NO_UPDATER = 'This host does not update itself (a zidane-server does).'\nconst NO_TOKENS = 'This host has no tokens (only a zidane-server does).'\n\nfunction validName(method: string, name: unknown): string {\n if (typeof name !== 'string' || name.trim() === '')\n throw new InvalidParamsError(`${method}: \"name\" must be a non-empty string.`)\n return name.trim().slice(0, 100)\n}\n\nexport function createServerHandlers({ tokens, update, logs, broadcast, onClose, onPeerClose }: {\n tokens?: ServerTokensControl\n update?: () => ServerUpdateControl | null\n logs?: RingBufferSink\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down. */\n onClose: (stop: () => void) => void\n /** Registers what to release when a connection drops (its log follow). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'tokens.createMachineToken' | 'tokens.list' | 'tokens.create' | 'tokens.revoke' | 'tokens.revokeSelf' | 'tokens.pair' | 'tokens.machineInvite' | 'server.update.status' | 'server.update.configure' | 'server.update.check' | 'server.update.install' | 'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const updater = (): ServerUpdateControl => {\n const control = update?.()\n if (!control)\n throw new Error(NO_UPDATER)\n return control\n }\n const store = (): ServerTokensControl => {\n if (!tokens)\n throw new Error(NO_TOKENS)\n return tokens\n }\n // A token created, revoked or paired, here or by the CLI: every window's token list re-reads.\n if (tokens)\n onClose(tokens.onChange(() => broadcast({ kind: 'tokens:changed' })))\n return {\n // Counted against, and audited with, the token that asks.\n 'tokens.createMachineToken': (p, peer) => store().createMachineToken(validName('tokens.createMachineToken', p.name), peer.principal),\n 'tokens.list': () => store().list(),\n 'tokens.create': (p, peer) => {\n const name = validName('tokens.create', p.name)\n if (p.scope !== 'machine' && !isClientScope(p.scope))\n throw new InvalidParamsError('tokens.create: \"scope\" must be \"chat\", \"approve\", \"admin\" or \"machine\".')\n return store().create(name, p.scope, peer.principal)\n },\n 'tokens.revoke': (p, peer) => {\n if (typeof p.id !== 'string' || p.id === '')\n throw new InvalidParamsError('tokens.revoke: \"id\" must be a token id.')\n const revoked = store().revoke(p.id, peer.principal)\n if (!revoked)\n throw new Error(`No live token has the id \"${p.id}\".`)\n return { revoked }\n },\n 'tokens.revokeSelf': (_p, peer) => {\n if (!peer.principal)\n throw new Error('This connection has no token to revoke.')\n const revoked = store().revoke(peer.principal, peer.principal)\n if (!revoked)\n throw new Error('This connection\\'s token is no longer live.')\n return { revoked }\n },\n 'tokens.pair': (p, peer) => {\n if (!isClientScope(p.scope))\n throw new InvalidParamsError('tokens.pair: \"scope\" must be \"chat\", \"approve\" or \"admin\".')\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.pair: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n if (p.name !== undefined && typeof p.name !== 'string')\n throw new InvalidParamsError('tokens.pair: \"name\" must be a string.')\n return store().pair(p.scope, p.ttlMs, p.name?.trim() || undefined, peer.principal)\n },\n 'tokens.machineInvite': (p, peer) => {\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.machineInvite: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n const name = typeof p.name === 'string' ? p.name.trim() : p.name\n if (name !== undefined && (typeof name !== 'string' || (name !== '' && !isValidMachineName(name))))\n throw new InvalidParamsError('tokens.machineInvite: \"name\" must be a machine name: up to 64 letters, digits, dots, dashes or underscores.')\n return store().machineInvite(p.ttlMs, name || undefined, peer.principal)\n },\n 'server.update.status': () => updater().status(),\n 'server.update.configure': (p) => {\n if (typeof p?.enabled !== 'boolean')\n throw new InvalidParamsError('server.update.configure: \"enabled\" must be true or false.')\n return updater().configure(p.enabled)\n },\n 'server.update.check': () => updater().check(),\n 'server.update.install': () => updater().installNow(),\n ...createLogHandlers({ ...(logs ? { logs } : {}), onClose: onPeerClose }),\n }\n}\n","/**\n * Session data a client reads (and the extension state it writes) instead of\n * its own store: the list rows, one row, the whole document (or it a page of\n * turns at a time), one tool result's text, how its title came about. A window on\n * another machine (zidane-server) has no other way to see the host's\n * sessions.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Session, SessionData, SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { TranscriptReplayCache } from './transcript-cache'\nimport type { Handlers } from './types'\nimport { describeTitleStatus } from '../../../chat/auto-title'\nimport { exportFilename, renderSession } from '../../../chat/session-export'\nimport { getSessionHeader, getSessionMeta, headerFromData, lastContextSizeFromTurns, listSessionMeta, runProgress, sumRunCosts, toolResultText } from '../../../chat/store'\nimport { deleteExtensionSessionState, loadSession, setExtensionSessionState } from '../../../session/index'\nimport { SESSION_TURNS_MAX_PAGE, SESSION_TURNS_PAGE } from '../../protocol'\nimport { InvalidParamsError, nonNegativeInt, sessionIdOf } from './params'\n\ntype SessionReadMethod = 'sessions.listMeta' | 'sessions.getMeta' | 'sessions.get' | 'sessions.getTurns' | 'sessions.getToolResult' | 'sessions.getHeader' | 'sessions.titleStatus' | 'sessions.setExtensionState' | 'sessions.export'\n\nfunction pageBound(value: unknown, name: string, fallback: number, max: number): number {\n return Math.min(nonNegativeInt(value, name) ?? fallback, max)\n}\n\n/**\n * The live session's document without copying it (`toJSON()` deep-clones\n * every turn). Read-only: each transport serializes the reply before the\n * session can change under it.\n */\nfunction liveView(live: Session): SessionData {\n return {\n id: live.id,\n ...(live.agentId !== undefined ? { agentId: live.agentId } : {}),\n ...(live.projectRoot !== undefined ? { projectRoot: live.projectRoot } : {}),\n turns: live.turns,\n runs: live.runs,\n status: live.status,\n metadata: live.metadata,\n createdAt: live.createdAt,\n updatedAt: live.updatedAt,\n }\n}\n\nexport function createSessionReadHandlers({ host, store, snapshots }: { host: ChatHost, store: SessionStore, snapshots: Pick<TranscriptReplayCache, 'document'> }): Handlers<SessionReadMethod> {\n /** The document as the host holds it: the live copy (ahead of the store mid-run, and holding the todos), else the stored one. */\n const documentOf = async (sessionId: string): Promise<SessionData | null> => {\n const live = host.getLiveSession(sessionId)\n if (live)\n return live.toJSON()\n // A reader: a load-time pairing heal stays in memory, the host's own\n // agent persists the document.\n const loaded = await loadSession(store, sessionId, { persistHeal: false })\n return loaded ? loaded.toJSON() : null\n }\n return {\n 'sessions.listMeta': (p) => {\n const projectRoot = p?.projectRoot\n if (projectRoot !== undefined && projectRoot !== null && typeof projectRoot !== 'string')\n throw new InvalidParamsError('projectRoot must be a string or null.')\n return listSessionMeta(store, projectRoot !== undefined ? { projectRoot } : undefined)\n },\n 'sessions.getMeta': p => getSessionMeta(store, sessionIdOf(p)),\n 'sessions.export': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.format !== 'markdown' && p.format !== 'json')\n throw new InvalidParamsError('format must be \"markdown\" or \"json\".')\n const data = await documentOf(sessionId)\n if (!data)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return { filename: exportFilename(sessionId, p.format), content: renderSession(data, p.format) }\n },\n 'sessions.get': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.turns !== false)\n return documentOf(sessionId)\n // `turns: false`: the rest of the document, its turns read a page at a time\n // (`sessions.getTurns`), from the same snapshot, named by its version.\n // Kept here besides the history worker's replay on purpose: that one holds events in another heap, this one the healed document this thread serves.\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n return snapshot && { ...snapshot.data, turns: [], version: snapshot.version }\n },\n 'sessions.getTurns': async (p) => {\n // One snapshot per content version serves every page (not a load, heal and copy per page).\n const sessionId = sessionIdOf(p)\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n if (!snapshot)\n return null\n const from = pageBound(p.from, 'from', 0, Number.MAX_SAFE_INTEGER)\n const limit = Math.max(1, pageBound(p.limit, 'limit', SESSION_TURNS_PAGE, SESSION_TURNS_MAX_PAGE))\n const { turns } = snapshot.data\n return { turns: turns.slice(from, from + limit), total: turns.length, version: snapshot.version }\n },\n 'sessions.getToolResult': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.callId !== 'string' || p.callId.length === 0)\n throw new InvalidParamsError('callId must be a non-empty string.')\n // Read in place: the live turns, else the cached snapshot (no load and copy per expand).\n const live = host.getLiveSession(sessionId)\n const turns = live ? live.turns : (await snapshots.document(store, sessionId, null))?.data.turns\n if (!turns)\n return null\n const resultIn = (turn: SessionTurn): string | undefined => {\n for (const block of turn.content) {\n if (block.type === 'tool_result' && block.callId === p.callId)\n return toolResultText(block.output)\n }\n return undefined\n }\n // The named turn first, then the rest (newest first: results sit near their call).\n if (typeof p.turnId === 'string') {\n for (const turn of turns) {\n const text = turn.id === p.turnId ? resultIn(turn) : undefined\n if (text !== undefined)\n return text\n }\n }\n for (let i = turns.length - 1; i >= 0; i--) {\n const text = resultIn(turns[i]!)\n if (text !== undefined)\n return text\n }\n return null\n },\n 'sessions.titleStatus': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n const header = live ? headerFromData(liveView(live)) : await getSessionHeader(store, sessionId)\n if (!header)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return describeTitleStatus(header.metadata)\n },\n 'sessions.getHeader': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n if (p.usage !== true)\n return live ? headerFromData(liveView(live)) : getSessionHeader(store, sessionId)\n // The footer's numbers need the turns: read here, only the numbers go out.\n const data = live ? liveView(live) : await store.load(sessionId)\n if (!data)\n return null\n const header = live ? headerFromData(data) : (await getSessionHeader(store, sessionId)) ?? headerFromData({ ...data, id: sessionId })\n // Only a run this host is running: a stored `running` run can be a dead process's.\n const run = live && host.isSessionRunning(sessionId) ? runProgress(data) : undefined\n return {\n ...header,\n contextTokens: lastContextSizeFromTurns(data.turns, data.runs),\n costUsd: sumRunCosts(data.runs),\n ...(run ? { runStartedAt: run.startedAt, runOutputTokens: run.outputTokens } : {}),\n }\n },\n 'sessions.setExtensionState': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n // The live copy when an agent holds the session (its save is\n // header-only, safe mid-run), else the stored one.\n const session = host.getLiveSession(sessionId) ?? await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n throw new Error(`Session \"${sessionId}\" not found.`)\n // Key checks and size bounds are the shared helpers' own.\n if (p.value === undefined)\n await deleteExtensionSessionState(session, p.extension, p.key)\n else\n await setExtensionSessionState(session, p.extension, p.key, p.value)\n },\n }\n}\n","/** Host settings and the runtime registry: read, write (rebuilding what a change requires), reload, and the setup wizard's write. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { settingsToWire } from '../../../chat/host-scoped-settings'\nimport { mergeOnboardingState } from '../../../chat/onboarding/result'\nimport { InvalidParamsError } from './params'\n\nconst isObject = (value: unknown): value is object => typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Settings that choose what is discovered on disk (MCP servers, skills,\n * plugins and the configs they come from): a change also re-walks the plugin\n * catalog, so a plugin installed outside the catalog shows up. Which agents\n * rebuild is decided per agent, from what its build read (`applyAgentSettings`).\n */\nconst DISCOVERY_KEYS = ['enabledMcps', 'disabledMcpTools', 'enabledSkills', 'enabledPlugins', 'importForeignConfigs', 'importRulerConfigs'] as const\n\nexport function createSettingsHandlers({ host, env, broadcast, onClose }: {\n host: ChatHost\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down: the watch on the settings file. */\n onClose?: (stop: () => void) => void\n}): Handlers<'settings.get' | 'settings.set' | 'runtime.reload' | 'onboarding.complete'> {\n /*\n * The settings this host last acted on. A write through `settings.set` and a\n * change another process made to the file (two daemons, or a daemon and a\n * window in local mode, share `state.json`) are both applied against them,\n * so neither is missed.\n */\n let applied = env.readSettings()\n\n /**\n * Act on a settings change: swap the extension registry when its keys\n * changed, answer the interactions on screen when they switched to skip,\n * rebuild every agent built from a value that changed (at run end when busy,\n * no run aborted), and converge every window's settings UI.\n */\n function apply(next: HostSettings) {\n const before = applied\n applied = next\n const changed = (key: keyof HostSettings): boolean =>\n JSON.stringify(before[key]) !== JSON.stringify(next[key])\n\n /*\n * Extension toggles swap the registry: forget the runtime config first so\n * every rebuild resolves a fresh one, and dispose the old registries only\n * once no agent runs on them (as `runtime.reload`).\n */\n if (changed('enabledExtensions') || changed('loadProjectExtensions')) {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n else if (DISCOVERY_KEYS.some(changed)) {\n // Best-effort, as the extension branch: a failed rebuild must not reject unobserved.\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n // Flipping to skip answers the modals already on screen — otherwise an\n // interaction raised under `ask` waits forever for an answer the new mode\n // says nobody will give. Resolved host-side so every window converges.\n if (changed('interactionMode') && next.interactionMode === 'skip')\n host.interactions.resolveAutomatically()\n\n // Rebuild what the change makes stale; close terminals turned off.\n host.applyAgentSettings(before, next)\n\n const wire = settingsToWire(next)\n broadcast({ kind: 'settings:changed', settings: wire })\n return wire\n }\n\n // Runs from a file watcher's timer: a throw there would be uncaught and end the host.\n const stopWatching = env.watchSettings?.(() => {\n try {\n const next = env.readSettings()\n if (JSON.stringify(next) !== JSON.stringify(applied))\n apply(next)\n }\n catch (err) {\n console.error('[ipc-daemon] applying a settings change from disk failed:', err)\n }\n })\n if (stopWatching)\n onClose?.(stopWatching)\n\n return {\n 'runtime.reload': () => {\n // Forget first so every rebuild (now for idle sessions, at run end for\n // busy ones) resolves a fresh registry; dispose the old registries only\n // once no agent runs on them. Disposing up front would tear down hooks\n // a busy run is still using.\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents().then(disposeOld, disposeOld)\n },\n\n // Every settings payload carries the legacy `safeMode` for windows older than `approvalMode`.\n 'settings.get': () => settingsToWire(env.readSettings()),\n 'settings.set': (p) => {\n const patch: unknown = p?.patch\n if (typeof patch !== 'object' || patch === null || Array.isArray(patch))\n throw new InvalidParamsError('patch must be an object of settings.')\n return apply(env.writeSettings(p.patch))\n },\n 'onboarding.complete': (p) => {\n const { set, reset } = p?.settings ?? {}\n if (!isObject(set) || !Array.isArray(reset) || reset.some(key => typeof key !== 'string'))\n throw new InvalidParamsError('settings must hold `set` (an object of settings) and `reset` (an array of keys).')\n if (!isObject(p.records))\n throw new InvalidParamsError('records must be an object.')\n const next = apply(env.writeSettings(set, reset))\n const { stateStore } = env.config\n const state = stateStore.load()\n stateStore.save({ ...state, onboarding: mergeOnboardingState(state.onboarding, p.records) })\n return next\n },\n }\n}\n","/** Inline autocomplete, resolved daemon-side and fanned out to every window on the session. */\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createPathAutocompleteProvider, resolveInlineSuggestion } from '../../../chat/inline-autocomplete'\nimport { loadOrThrow } from './session-load'\n\nexport function createSuggestHandlers({ env, broadcastExcept }: {\n env: DaemonEnvironment\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'suggest.resolve'>\n /** The session was deleted: abort its in-flight compute and forget its sequence. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared inline-autocomplete state — per-session latest-wins\n * coalescing for `suggest.resolve`. `seq` is the newest sequence seen\n * (stale requests return without computing); `controller` aborts an\n * in-flight compute when a newer request supersedes it (the GUI's\n * controller-map pattern, daemon-side). Entries outlive their compute\n * (the seq high-water mark), so the map is an LRU of 256 sessions:\n * refusing new keys at the cap instead would switch suggestions off for\n * every session past the 256th until the daemon restarts.\n */\n const suggests = new Map<string, { seq: number, controller: AbortController | null }>()\n\n const methods: Handlers<'suggest.resolve'> = {\n 'suggest.resolve': async (p, peer) => {\n const sessionId = String(p.sessionId)\n const seq = typeof p.seq === 'number' ? p.seq : 0\n // Same cheap shape guards + 64 KiB text cap as `drafts.set`.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const caret = typeof p.caret === 'number'\n ? Math.max(0, Math.min(Math.floor(p.caret), text.length))\n : text.length\n\n const prev = suggests.get(sessionId)\n // Latest-wins: a stale seq answers immediately without computing —\n // the requester's own NEWER request (already in flight or about to\n // land) carries the authoritative result.\n if (prev && seq < prev.seq)\n return { suggestion: null, seq }\n // Supersede: abort the in-flight compute for this session, if any.\n prev?.controller?.abort()\n\n const controller = new AbortController()\n const entry = { seq, controller: controller as AbortController | null }\n suggests.delete(sessionId)\n suggests.set(sessionId, entry)\n if (suggests.size > 256) {\n const [oldest, evicted] = suggests.entries().next().value!\n evicted.controller?.abort()\n suggests.delete(oldest)\n }\n\n try {\n // Session cwd from metadata (same derivation as `toRow`) — the\n // per-cwd runtime config is the SAME registry the GUI main uses\n // locally, resolved through the existing daemon environment.\n const data = await loadOrThrow(env.store, sessionId)\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n const config = await env.runtimeConfig(cwd)\n // Canonical provider assembly (built-in path provider first, then\n // extension providers) and canonical deadlines —\n // `resolveInlineSuggestion` races each provider against its own\n // budget exactly as the GUI main / TUI do.\n const providers = [\n createPathAutocompleteProvider({ cwd: () => cwd }),\n ...config.extensions.inlineAutocompleteProviders,\n ]\n const result = await resolveInlineSuggestion(providers, { text, cursor: caret, cwd, signal: controller.signal })\n // Superseded mid-compute — the newer request owns the fan-out.\n if (controller.signal.aborted || suggests.get(sessionId) !== entry)\n return { suggestion: null, seq }\n // Full ordered candidate list rides along (additive field) so\n // clients keep ↑/↓ rotation; `suggestion` stays candidates[0] for\n // older clients that only read the single field.\n const candidates = result ? [...result.suffixes] : []\n const suggestion = candidates[0] ?? null\n // Fan out to every OTHER window on the session — the requester\n // already has the result from this RPC reply (drafts'\n // broadcastExcept pattern).\n broadcastExcept(peer, { kind: 'suggest:changed', sessionId, seq, basis: text, caret, suggestion, ...(candidates.length > 0 ? { candidates } : {}) })\n return { suggestion, seq, ...(candidates.length > 0 ? { candidates } : {}) }\n }\n finally {\n // Keep the seq high-water mark for stale checks; drop only the\n // controller so a finished compute can't be \"aborted\" later.\n if (suggests.get(sessionId) === entry)\n entry.controller = null\n }\n },\n }\n\n return {\n methods,\n forget: (sessionId) => {\n suggests.get(sessionId)?.controller?.abort()\n suggests.delete(sessionId)\n },\n }\n}\n","import type { EnvironmentRegistry } from '../../chat/environment'\nimport type { EnvironmentSecrets } from '../../chat/environment-settings'\n/**\n * Applying one `sync.push` category on a zidane-server (`./handlers/sync`\n * owns the record, the source check and the audit): each writes through the\n * host's own setters or the user-scope files, skipping overrides (a field\n * whose value here no longer matches what sync wrote becomes one), and\n * reports every field as applied, unchanged or skipped (with why).\n */\nimport type { SyncCategory, SyncFile, SyncPayloads, SyncPushResult } from '../../chat/sync/types'\nimport type { McpServerConfig } from '../../types'\nimport type { DaemonEnvironment } from './environment'\nimport type { ProviderAuth } from './handlers/auth'\nimport type { SyncSetters } from './handlers/sync'\nimport type { HostPeer } from './peers'\nimport type { SyncFieldRecord, SyncRecord } from './sync-store'\nimport { Buffer } from 'node:buffer'\nimport { createHash } from 'node:crypto'\nimport { accessSync, constants, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'\nimport { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport process from 'node:process'\nimport { writeFileAtomic } from '../../atomic-write'\nimport { applyEnvironmentSettingsChange, readEnvironmentSettings } from '../../chat/environment-settings'\nimport { isWindowOnlySetting } from '../../chat/host-scoped-settings'\nimport { parseMcpsFile } from '../../chat/mcps-discovery'\nimport { isMcpServerName, mcpsWritePath } from '../../chat/mcps-write'\nimport { projectUserPaths } from '../../chat/project-user-paths'\nimport { readProjects, safelistProjectKey, writeProjects } from '../../chat/safe-mode'\nimport { DEFAULT_SETTINGS } from '../../chat/settings-defaults'\nimport { hashValue, isRecord } from '../../chat/sync/hash'\nimport { isSyncableSetting, settingsFromWire } from '../../chat/sync/settings-keys'\nimport { settingField, SYNCABLE_ENVIRONMENT_KINDS, SYSTEM_MD_FIELD } from '../../chat/sync/types'\nimport { userSystemMdPath } from '../../chat/system-md'\nimport { InvalidParamsError } from './handlers/params'\n\n/** What applying a push reads and writes through. */\nexport interface SyncApplyContext {\n env: DaemonEnvironment\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n /** The host's environment kinds and their secret store (`environments`). */\n environments: EnvironmentRegistry\n environmentSecrets: EnvironmentSecrets\n home: () => string\n prefix: () => string\n}\n\nconst MAX_SETTINGS_BYTES = 256 * 1024\n\nconst MAX_SYSTEM_MD_BYTES = 256 * 1024\n\nconst MAX_FILE_BYTES = 1024 * 1024\n\nconst MAX_SKILL_BYTES = 4 * 1024 * 1024\n\nconst MAX_FILES_BYTES = 16 * 1024 * 1024\n\nconst MAX_SKILL_FILES = 200\n\nconst MAX_SKILLS = 500\n\nconst MAX_PATH_DEPTH = 8\n\nconst MAX_SAFELIST_ENTRIES = 1000\n\nconst MAX_ENTRY_LENGTH = 1000\n\nconst NAME_RE = /^\\w[\\w@.-]{0,99}$/\n\nconst SEGMENT_RE = /^[^/\\\\\\0]{1,255}$/\n\n/** A skill file's relative path: plain segments, no `..`, bounded depth. */\nfunction checkRelativePath(path: unknown): string | null {\n if (typeof path !== 'string' || path === '' || isAbsolute(path) || path.includes('\\\\'))\n return null\n const segments = path.split('/')\n if (segments.length > MAX_PATH_DEPTH || segments.some(s => s === '.' || s === '..' || !SEGMENT_RE.test(s)))\n return null\n return segments.join('/')\n}\n\n/** Is `command` runnable here (an absolute path, or found on PATH)? Looks, never runs. */\nfunction commandAvailable(command: string): boolean {\n const executable = (path: string): boolean => {\n try {\n accessSync(path, constants.X_OK)\n return statSync(path).isFile()\n }\n catch {\n return false\n }\n }\n if (command.includes('/'))\n return isAbsolute(command) && executable(command)\n return (process.env.PATH ?? '').split(delimiter).filter(Boolean).some(dir => executable(join(dir, command)))\n}\n\n/** A folder's files, sorted, as one hash (symlinks hashed by target, never followed). Null when absent. */\nfunction hashDir(dir: string): string | null {\n let stat\n try {\n stat = lstatSync(dir)\n }\n catch {\n return null\n }\n if (!stat.isDirectory())\n return `not-a-folder:${stat.mode}`\n const hash = createHash('sha256')\n const walk = (at: string, depth: number): void => {\n if (depth > MAX_PATH_DEPTH + 1)\n return\n for (const name of readdirSync(at).sort()) {\n const path = join(at, name)\n const rel = relative(dir, path).split(sep).join('/')\n const s = lstatSync(path)\n if (s.isDirectory()) {\n walk(path, depth + 1)\n }\n else if (s.isFile()) {\n hash.update(`f:${rel}\\0`)\n hash.update(readFileSync(path))\n hash.update('\\0')\n }\n else {\n hash.update(`o:${rel}:${s.mode}\\0`)\n }\n }\n }\n walk(dir, 0)\n return hash.digest('hex')\n}\n\n/** The hash `hashDir` gives the folder these files make. */\nfunction hashFiles(files: readonly { path: string, bytes: Buffer }[]): string {\n const hash = createHash('sha256')\n // `hashDir` walks in sorted order level by level: replay that order.\n const sorted = [...files].sort((a, b) => compareWalkOrder(a.path, b.path))\n for (const file of sorted) {\n hash.update(`f:${file.path}\\0`)\n hash.update(file.bytes)\n hash.update('\\0')\n }\n return hash.digest('hex')\n}\n\n/** The order a sorted depth-first walk visits two relative paths. */\nfunction compareWalkOrder(a: string, b: string): number {\n const as = a.split('/')\n const bs = b.split('/')\n for (let i = 0; i < Math.min(as.length, bs.length); i++) {\n if (as[i] !== bs[i]) {\n // Same level: readdir order (code units), whether file or folder.\n return as[i]! < bs[i]! ? -1 : 1\n }\n }\n return as.length - bs.length\n}\n\nfunction userSkillsRoot(ctx: SyncApplyContext): string {\n const root = projectUserPaths({ subPath: 'skills', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() })\n .find(p => p.source === 'user' && p.path.includes(`.${ctx.prefix().replace(/^\\./, '')}`))\n return root!.path\n}\nfunction userMcpsPath(ctx: SyncApplyContext): string {\n return mcpsWritePath('user', { home: ctx.home(), cwd: ctx.home(), prefix: ctx.prefix() })\n}\nfunction userExtensionDirs(ctx: SyncApplyContext, name: string): string[] {\n return projectUserPaths({ subPath: 'extensions', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() }).filter(p => p.source === 'user').map(p => join(p.path, name))\n}\n\n/** Is `field` free to write? An override (now or found by a changed value) is not. */\nfunction writable(record: SyncRecord, field: string, currentHash: string | null, result: SyncPushResult): boolean {\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n const known = record.fields[field]\n if (known?.hash !== undefined && known.hash !== (currentHash ?? 'absent')) {\n record.overrides[field] = { at: Date.now() }\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n return true\n}\n\nfunction mark(record: SyncRecord, field: string, category: SyncCategory, fields: Omit<SyncFieldRecord, 'category' | 'syncedAt'>): void {\n record.fields[field] = { category, syncedAt: Date.now(), ...fields }\n}\n\n// ---- settings ----------------------------------------------------------\nexport function pushSettings(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['settings'], result: SyncPushResult): void {\n if (!isRecord(payload?.values))\n throw new InvalidParamsError('settings: payload.values must be an object.')\n if (JSON.stringify(payload.values).length > MAX_SETTINGS_BYTES)\n throw new InvalidParamsError(`settings: larger than ${MAX_SETTINGS_BYTES} bytes.`)\n const settings = ctx.env.readSettings()\n const current = settings as unknown as Record<string, unknown>\n const patch: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(settingsFromWire(payload.values, settings.approvalMode))) {\n const field = settingField(key)\n if (!Object.hasOwn(DEFAULT_SETTINGS, key)) {\n result.skipped.push({ field, reason: 'not a setting' })\n continue\n }\n if (!isSyncableSetting(key)) {\n result.skipped.push({ field, reason: isWindowOnlySetting(key) ? 'window-only setting' : 'not synced' })\n continue\n }\n const currentHash = hashValue(current[key])\n if (!writable(record, field, currentHash, result))\n continue\n if (hashValue(value) === currentHash) {\n mark(record, field, 'settings', { hash: currentHash, sent: currentHash })\n result.unchanged.push(field)\n continue\n }\n patch[key] = value\n }\n if (Object.keys(patch).length === 0)\n return\n const next = ctx.setters.setSettings(patch)\n for (const key of Object.keys(patch)) {\n mark(record, settingField(key), 'settings', { hash: hashValue(next[key]), sent: hashValue(patch[key]) })\n result.applied.push(settingField(key))\n }\n}\n\n// ---- safe-mode allowlists ----------------------------------------------\n/** The project here a client's path names: the same folder inside a workspace root, else one folder of that name in a root. */\nfunction projectHere(ctx: SyncApplyContext, clientPath: string): string | null {\n const roots = (ctx.env.workspaceRoots ?? []).map((root) => {\n try {\n return realpathSync(root)\n }\n catch {\n return null\n }\n }).filter((r): r is string => r !== null)\n const inRoot = (path: string): boolean => roots.some(root => path === root || path.startsWith(root + sep))\n const isDir = (path: string): boolean => statSync(path, { throwIfNoEntry: false })?.isDirectory() === true\n if (isAbsolute(clientPath) && isDir(clientPath)) {\n const real = realpathSync(clientPath)\n if (inRoot(real))\n return safelistProjectKey(real)\n }\n const name = basename(clientPath)\n if (!name || name === '.' || name === '..')\n return null\n const found = [...new Set(roots.map(root => join(root, name)).filter(isDir).map(path => realpathSync(path)))]\n return found.length === 1 ? safelistProjectKey(found[0]!) : null\n}\n\nexport function pushSafelists(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['safelists'], result: SyncPushResult): void {\n if (!isRecord(payload?.projects))\n throw new InvalidParamsError('safelists: payload.projects must map paths to entries.')\n const dataDir = ctx.env.userDataDir()\n const file = readProjects(dataDir)\n let dirty = false\n for (const [clientPath, entries] of Object.entries(payload.projects)) {\n const field = `safelist:${clientPath}`\n if (!Array.isArray(entries) || entries.length > MAX_SAFELIST_ENTRIES || !entries.every(e => typeof e === 'string' && e.length <= MAX_ENTRY_LENGTH)) {\n result.skipped.push({ field, reason: 'invalid entries' })\n continue\n }\n const target = projectHere(ctx, clientPath)\n if (!target) {\n result.skipped.push({ field, reason: 'no project of that path or name on this server' })\n continue\n }\n // The server's own entries stay; the ones this device put there and dropped since go.\n const previous = record.fields[field]?.target === target ? (record.fields[field]?.entries ?? []) : []\n const current = file[target]?.safelist ?? []\n const next = current.filter(entry => !previous.includes(entry) || entries.includes(entry))\n for (const entry of entries) {\n if (!next.includes(entry))\n next.push(entry)\n }\n mark(record, field, 'safelists', { target, entries: [...entries] })\n if (JSON.stringify(next) === JSON.stringify(current)) {\n result.unchanged.push(field)\n continue\n }\n file[target] = { ...file[target], safelist: next }\n dirty = true\n result.applied.push(field)\n }\n if (dirty)\n writeProjects(dataDir, file)\n}\n\n// ---- SYSTEM.md and skills ----------------------------------------------\n/** A skill as checked bytes, or why it is refused. */\nfunction checkSkill(skill: unknown): { name: string, files: { path: string, bytes: Buffer }[] } | { field: string, reason: string } {\n const name = isRecord(skill) && typeof skill.name === 'string' ? skill.name : ''\n const field = `skill:${name}`\n if (!NAME_RE.test(name))\n return { field, reason: 'not a plain skill name' }\n const files = isRecord(skill) && Array.isArray(skill.files) ? skill.files as SyncFile[] : null\n if (!files || files.length === 0 || files.length > MAX_SKILL_FILES)\n return { field, reason: `needs 1 to ${MAX_SKILL_FILES} files` }\n const out: { path: string, bytes: Buffer }[] = []\n let total = 0\n for (const file of files) {\n const path = checkRelativePath(isRecord(file) ? file.path : undefined)\n if (!path)\n return { field, reason: 'a file path is not a plain relative path' }\n if (typeof file.data !== 'string')\n return { field, reason: `${path}: no data` }\n const bytes = Buffer.from(file.data, 'base64')\n if (bytes.length > MAX_FILE_BYTES)\n return { field, reason: `${path} is larger than ${MAX_FILE_BYTES} bytes` }\n total += bytes.length\n if (out.some(f => f.path === path || f.path.startsWith(`${path}/`) || path.startsWith(`${f.path}/`)))\n return { field, reason: `${path} appears twice` }\n out.push({ path, bytes })\n }\n if (total > MAX_SKILL_BYTES)\n return { field, reason: `larger than ${MAX_SKILL_BYTES} bytes` }\n return { name, files: out }\n}\n\n/** Replace `dir` with exactly these files: staged next to it, then swapped in. */\nfunction writeSkillDir(root: string, name: string, files: readonly { path: string, bytes: Buffer }[]): void {\n mkdirSync(root, { recursive: true })\n const dir = join(root, name)\n const stage = join(root, `.${name}.sync-${process.pid}-${Date.now()}`)\n mkdirSync(stage)\n try {\n for (const file of files) {\n const target = resolve(stage, file.path)\n if (!target.startsWith(stage + sep))\n throw new Error(`${file.path} is outside the skill folder.`)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, file.bytes)\n }\n const backup = existsSync(dir) ? `${stage}.old` : null\n if (backup)\n renameSync(dir, backup)\n renameSync(stage, dir)\n if (backup)\n rmSync(backup, { recursive: true, force: true })\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\nexport function pushFiles(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['files'], result: SyncPushResult): boolean {\n if (!isRecord(payload) || !Array.isArray(payload.skills) || payload.skills.length > MAX_SKILLS || (payload.systemMd !== null && typeof payload.systemMd !== 'string'))\n throw new InvalidParamsError('files: payload must be { systemMd: string | null, skills: [...] }.')\n let touched = false\n let total = 0\n\n // SYSTEM.md (user scope).\n const mdPath = userSystemMdPath({ home: ctx.home(), prefix: ctx.prefix() })\n const currentMd = existsSync(mdPath) ? readFileSync(mdPath, 'utf8') : null\n const currentMdHash = currentMd === null ? null : hashValue(currentMd)\n if (payload.systemMd !== null && Buffer.byteLength(payload.systemMd) > MAX_SYSTEM_MD_BYTES) {\n result.skipped.push({ field: SYSTEM_MD_FIELD, reason: `larger than ${MAX_SYSTEM_MD_BYTES} bytes` })\n }\n else if (payload.systemMd !== null || record.fields[SYSTEM_MD_FIELD]) {\n if (writable(record, SYSTEM_MD_FIELD, currentMdHash, result)) {\n if (payload.systemMd === null) {\n // This computer has none any more: drop the one sync wrote.\n rmSync(mdPath, { force: true })\n delete record.fields[SYSTEM_MD_FIELD]\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n else if (hashValue(payload.systemMd) === currentMdHash) {\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: currentMdHash })\n result.unchanged.push(SYSTEM_MD_FIELD)\n }\n else {\n total += Buffer.byteLength(payload.systemMd)\n writeFileAtomic(mdPath, payload.systemMd, { ensureDir: true })\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: hashValue(payload.systemMd) })\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n }\n }\n\n // Skills (user scope, `~/.<prefix>/skills/<name>`).\n const root = userSkillsRoot(ctx)\n const sent = new Set<string>()\n for (const raw of payload.skills) {\n const skill = checkSkill(raw)\n if ('reason' in skill) {\n result.skipped.push(skill)\n continue\n }\n const field = `skill:${skill.name}`\n sent.add(field)\n const bytes = skill.files.reduce((n, f) => n + f.bytes.length, 0)\n if (total + bytes > MAX_FILES_BYTES) {\n result.skipped.push({ field, reason: `over the ${MAX_FILES_BYTES}-byte bound of one push` })\n continue\n }\n const dir = join(root, skill.name)\n if (existsSync(dir) && lstatSync(dir).isSymbolicLink()) {\n result.skipped.push({ field, reason: 'a link on this server, left alone' })\n continue\n }\n const currentHash = hashDir(dir)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashFiles(skill.files)\n if (wanted === currentHash) {\n mark(record, field, 'files', { hash: wanted })\n result.unchanged.push(field)\n continue\n }\n total += bytes\n writeSkillDir(root, skill.name, skill.files)\n mark(record, field, 'files', { hash: hashDir(dir) ?? wanted })\n result.applied.push(field)\n touched = true\n }\n // Skills this device synced and no longer has.\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'files' || !field.startsWith('skill:') || sent.has(field))\n continue\n const dir = join(root, field.slice('skill:'.length))\n if (!writable(record, field, hashDir(dir), result))\n continue\n rmSync(dir, { recursive: true, force: true })\n delete record.fields[field]\n result.applied.push(field)\n touched = true\n }\n return touched\n}\n\n// ---- MCP servers ---------------------------------------------------------\nfunction readUserMcps(ctx: SyncApplyContext): McpServerConfig[] {\n const path = userMcpsPath(ctx)\n if (!existsSync(path))\n return []\n try {\n return parseMcpsFile(readFileSync(path, 'utf8'))\n }\n catch {\n return []\n }\n}\n\nexport async function pushMcps(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['mcps'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.servers))\n throw new InvalidParamsError('mcps: payload.servers must be a list.')\n const hashOf = (name: string): string | null => {\n const found = readUserMcps(ctx).find(s => s.name === name)\n return found ? hashValue(found) : null\n }\n const sent = new Set<string>()\n for (const config of payload.servers) {\n const name = isRecord(config) && typeof config.name === 'string' ? config.name : ''\n const field = `mcp:${name}`\n if (!isMcpServerName(name)) {\n result.skipped.push({ field, reason: 'not a plain server name' })\n continue\n }\n sent.add(field)\n const currentHash = hashOf(name)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashValue(config)\n if (record.fields[field]?.sent === wanted && currentHash !== null) {\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.mcpUpsert({ config: config as unknown as McpServerConfig }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'mcps', { hash: hashOf(name) ?? wanted, sent: wanted })\n result.applied.push(field)\n if (typeof config.command === 'string' && config.command.trim() !== '' && !commandAvailable(config.command.trim()))\n result.warnings.push({ field, message: `\"${config.command}\" is not on this server's PATH: the server may not run there.` })\n }\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'mcps' || sent.has(field))\n continue\n const name = field.slice('mcp:'.length)\n if (!writable(record, field, hashOf(name), result))\n continue\n try {\n await ctx.setters.mcpRemove({ name }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n delete record.fields[field]\n result.applied.push(field)\n }\n}\n\n// ---- extensions ----------------------------------------------------------\nexport async function pushExtensions(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['extensions'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.extensions))\n throw new InvalidParamsError('extensions: payload.extensions must be a list.')\n for (const entry of payload.extensions) {\n const name = isRecord(entry) && typeof entry.name === 'string' ? entry.name : ''\n const field = `extension:${name}`\n if (!NAME_RE.test(name) || typeof entry.spec !== 'string') {\n result.skipped.push({ field, reason: 'needs a plain name and a source spec' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n // Installed already (by sync or by hand): left as it is, never updated or removed by sync.\n if (userExtensionDirs(ctx, name).some(dir => existsSync(dir))) {\n if (!record.fields[field])\n mark(record, field, 'extensions', {})\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.install({ kind: 'extension', spec: entry.spec, scope: 'user', ...(typeof entry.extension === 'string' ? { extension: entry.extension } : {}) }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'extensions', {})\n result.applied.push(field)\n }\n}\n\n// ---- provider API keys ---------------------------------------------------\n// ---- environments ------------------------------------------------------\n/**\n * Cloud sandbox kinds (`SYNCABLE_ENVIRONMENT_KINDS`): each as the server's\n * own `environments.update` writes it, so its registry checks every option.\n * A kind the server doesn't have, or the device sent outside the list, is\n * skipped. An edit made on the server since is an override (compared by the\n * hash of its options and on/off state; keys are not read back).\n */\nexport function pushEnvironments(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['environments'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.kinds))\n throw new InvalidParamsError('environments: payload.kinds must be a list.')\n const currentHash = (kind: string): string => {\n const settings = readEnvironmentSettings(ctx.env.readSettings())\n return hashValue({ config: settings.config[kind] ?? {}, enabled: settings.enabled.includes(kind), disabled: settings.disabled.includes(kind) })\n }\n for (const entry of payload.kinds) {\n const kind = isRecord(entry) && typeof entry.kind === 'string' ? entry.kind : ''\n const field = `environment:${kind}`\n if (!SYNCABLE_ENVIRONMENT_KINDS.includes(kind)) {\n result.skipped.push({ field, reason: 'not a cloud sandbox' })\n continue\n }\n if (!writable(record, field, currentHash(kind), result))\n continue\n const wanted = hashValue(entry)\n if (record.fields[field]?.sent === wanted) {\n result.unchanged.push(field)\n continue\n }\n const values = isRecord(entry.values) ? entry.values : {}\n const secrets = isRecord(entry.secrets) ? entry.secrets : {}\n try {\n const write = applyEnvironmentSettingsChange(ctx.environments, ctx.env.readSettings(), {\n kind,\n ...(typeof entry.enabled === 'boolean' ? { enabled: entry.enabled } : {}),\n values: { ...values, ...secrets } as Record<string, string | number | boolean>,\n })\n for (const secret of write.secrets)\n ctx.environmentSecrets.set(kind, secret.key, secret.value)\n ctx.setters.setSettings(write.settingsPatch)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'environments', { hash: currentHash(kind), sent: wanted })\n result.applied.push(field)\n }\n}\n\nexport function pushKeys(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['keys'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.keys))\n throw new InvalidParamsError('keys: payload.keys must be a list.')\n for (const entry of payload.keys) {\n const provider = isRecord(entry) && typeof entry.provider === 'string' ? entry.provider : ''\n const field = `key:${provider}`\n if (!record.keys.includes(provider)) {\n result.skipped.push({ field, reason: 'not opted in for this key' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n try {\n if (typeof entry.key !== 'string' || entry.key.trim() === '')\n throw new Error('empty key')\n if (ctx.auth.storedKeys(ctx.auth.descriptorOf(provider)).includes(entry.key.trim())) {\n if (!record.fields[field])\n mark(record, field, 'keys', {})\n result.unchanged.push(field)\n continue\n }\n ctx.setters.setApiKey({ provider, key: entry.key })\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'keys', {})\n result.applied.push(field)\n }\n}\n","/**\n * A zidane-server's settings-sync record (`<dataDir>/sync.json`, 0600,\n * written atomically): the source device, the categories and API keys it\n * opted in, the fields it set (with a hash of what the server held after\n * each write, to tell a server-side edit) and the fields edited here since\n * (overrides). No secret is stored: an API key field has no hash.\n */\nimport type { SyncCategory, SyncSource, SyncStatus } from '../../chat/sync/types'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isRecord } from '../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../chat/sync/types'\n\nexport interface SyncFieldRecord {\n category: SyncCategory\n syncedAt: number\n /** Hash of the server's value right after the last write: anything else there now is an edit made here. */\n hash?: string\n /** Hash of the value the source sent last: the same again is `unchanged`. */\n sent?: string\n /** A safelist: the project key it maps to here, and the entries the source put there. */\n target?: string\n entries?: string[]\n}\n\nexport interface SyncRecord {\n version: 1\n source: SyncSource | null\n categories: SyncCategory[]\n keys: string[]\n fields: Record<string, SyncFieldRecord>\n overrides: Record<string, { at: number }>\n lastPushAt?: number\n}\n\nexport const SYNC_FILE = 'sync.json'\n\nexport function emptySyncRecord(): SyncRecord {\n return { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n}\n\nconst SAFE_MODE_FIELD = settingField('safeMode')\nconst APPROVAL_MODE_FIELD = settingField('approvalMode')\n\n/**\n * `approvalMode` replaced the synced `safeMode`. An override of it still\n * guards the server's mode, so it moves over; its field hash (of a boolean)\n * matches no mode, so it goes and the next push syncs the field afresh.\n */\nfunction withoutSafeModeField(record: SyncRecord): SyncRecord {\n const { [SAFE_MODE_FIELD]: override, ...overrides } = record.overrides\n const { [SAFE_MODE_FIELD]: _field, ...fields } = record.fields\n if (override && !overrides[APPROVAL_MODE_FIELD])\n overrides[APPROVAL_MODE_FIELD] = override\n return { ...record, fields, overrides }\n}\n\nexport interface SyncStore {\n file: string\n read: () => SyncRecord\n write: (record: SyncRecord) => void\n}\n\nexport function createSyncStore(dataDir: string): SyncStore {\n const file = join(dataDir, SYNC_FILE)\n return {\n file,\n read: () => {\n if (!existsSync(file))\n return emptySyncRecord()\n try {\n const raw: unknown = JSON.parse(readFileSync(file, 'utf8'))\n if (!isRecord(raw))\n return emptySyncRecord()\n const source = isRecord(raw.source) && typeof raw.source.deviceId === 'string' && typeof raw.source.deviceName === 'string'\n ? raw.source as unknown as SyncSource\n : null\n return withoutSafeModeField({\n version: 1,\n source,\n categories: Array.isArray(raw.categories) ? raw.categories.filter((c): c is SyncCategory => SYNC_CATEGORIES.includes(c as SyncCategory)) : [],\n keys: Array.isArray(raw.keys) ? raw.keys.filter((k): k is string => typeof k === 'string') : [],\n fields: isRecord(raw.fields) ? raw.fields as Record<string, SyncFieldRecord> : {},\n overrides: isRecord(raw.overrides) ? raw.overrides as Record<string, { at: number }> : {},\n ...(typeof raw.lastPushAt === 'number' ? { lastPushAt: raw.lastPushAt } : {}),\n })\n }\n catch {\n // Unreadable: start over (the next write replaces it).\n return emptySyncRecord()\n }\n },\n write: record => writeJsonFileAtomic(file, record, OWNER_ONLY),\n }\n}\n\n/** What `sync.status` says: the record without hashes or safelist entries. */\nexport function syncStatusOf(record: SyncRecord): SyncStatus {\n return {\n source: record.source,\n categories: [...record.categories],\n keys: [...record.keys],\n fields: Object.fromEntries(Object.entries(record.fields).map(([field, f]) => [field, { category: f.category, syncedAt: f.syncedAt }])),\n overrides: { ...record.overrides },\n ...(record.lastPushAt !== undefined ? { lastPushAt: record.lastPushAt } : {}),\n }\n}\n","/**\n * Settings sync from a client's computer (`sync.*`, `docs/SERVER.md`\n * § Settings sync): a zidane-server takes one device's settings, files,\n * MCP servers, extensions and opted-in API keys, through the same setters a\n * window uses (`settings.set`, `mcp.upsert` / `remove`, `catalog.install`,\n * `auth.setApiKey`, the user-scope files), and keeps a record of what came\n * from where (`../sync-store`).\n *\n * - One source per server: `sync.claim` by another device is refused unless\n * it takes over (which drops the previous source's marks, not its values).\n * The source is the device AND the token it claimed with: a device id is a\n * client's word, so the same id from another token is another source\n * (coordination between a user's devices, bound to who authenticated).\n * - A field edited on the server since it was synced (through a window, or\n * on disk: its value no longer matches what sync wrote) is an override:\n * pushes skip it until `sync.reset`.\n * - Window-only settings never apply; skills are written by plain names and\n * relative paths inside the skills folder, size-bounded; extensions and\n * MCP servers go through the install gate (`allowRemoteInstalls`) and its\n * audit; API keys only for providers the source opted in.\n * - Every call is audited with the connection's token; no value is logged.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SyncCategory, SyncPayloads, SyncPushResult, SyncStatus } from '../../../chat/sync/types'\nimport type { HostSignal, IpcParams } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { SyncApplyContext } from '../sync-apply'\nimport type { SyncRecord } from '../sync-store'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { homedir } from 'node:os'\nimport { isRecord } from '../../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../../chat/sync/types'\nimport { pushEnvironments, pushExtensions, pushFiles, pushKeys, pushMcps, pushSafelists, pushSettings } from '../sync-apply'\nimport { createSyncStore, syncStatusOf } from '../sync-store'\nimport { InvalidParamsError } from './params'\n\nexport interface SyncOptions {\n /** One audit line per call (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n}\n\ntype SyncMethod = 'sync.status' | 'sync.claim' | 'sync.push' | 'sync.reset' | 'sync.release'\n\n/** The host's own setters, as a window calls them (installs gated and audited there). */\nexport interface SyncSetters {\n setSettings: (patch: Record<string, unknown>) => Record<string, unknown>\n install: (params: IpcParams<'catalog.install'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpUpsert: (params: IpcParams<'mcp.upsert'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpRemove: (params: IpcParams<'mcp.remove'>, peer: HostPeer) => Promise<unknown> | unknown\n setApiKey: (params: IpcParams<'auth.setApiKey'>) => unknown\n}\n\nconst MAX_DEVICE_FIELD = 200\n\nconst NOT_A_SERVER = 'This host takes no settings sync (a zidane-server does).'\n\nfunction checkDevice(p: { deviceId?: unknown, deviceName?: unknown }, withName: boolean): { deviceId: string, deviceName: string } {\n if (typeof p.deviceId !== 'string' || p.deviceId.trim() === '' || p.deviceId.length > MAX_DEVICE_FIELD)\n throw new InvalidParamsError('deviceId must be a non-empty string.')\n if (withName && (typeof p.deviceName !== 'string' || p.deviceName.trim() === '' || p.deviceName.length > MAX_DEVICE_FIELD))\n throw new InvalidParamsError('deviceName must be a non-empty string.')\n return { deviceId: p.deviceId, deviceName: typeof p.deviceName === 'string' ? p.deviceName.trim() : '' }\n}\n\nfunction checkCategories(value: unknown): SyncCategory[] | undefined {\n if (value === undefined)\n return undefined\n if (!Array.isArray(value) || !value.every(c => SYNC_CATEGORIES.includes(c as SyncCategory)))\n throw new InvalidParamsError(`categories must be some of: ${SYNC_CATEGORIES.join(', ')}.`)\n return SYNC_CATEGORIES.filter(c => value.includes(c))\n}\n\nexport function createSyncHandlers({ host, env, broadcast, setters, auth, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'environments' | 'environmentSecrets'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n options?: SyncOptions\n}): Handlers<SyncMethod> & { markOverrides: (fields: readonly string[]) => Promise<void> } {\n const store = createSyncStore(env.userDataDir())\n const ctx: SyncApplyContext = { env, setters, auth, environments: host.environments, environmentSecrets: host.environmentSecrets, home: () => homedir(), prefix: () => env.config.prefix }\n\n /** Sync calls (and override marks) one at a time: each reads the record, works, writes it. */\n let queue: Promise<unknown> = Promise.resolve()\n const exclusive = <T>(work: () => Promise<T> | T): Promise<T> => {\n const next = queue.then(work, work)\n queue = next.catch(() => undefined)\n return next\n }\n\n const changed = (): void => broadcast({ kind: 'sync:changed' })\n const audit = (peer: HostPeer, entry: Record<string, unknown>): void => options?.audit?.(peer, entry)\n\n function requireOptions(): void {\n if (!options)\n throw new Error(NOT_A_SERVER)\n }\n\n /** Mark fields the source set as edited here; nothing for fields nobody synced. */\n const markOverrides = (fields: readonly string[]): Promise<void> => {\n if (!options || fields.length === 0)\n return Promise.resolve()\n return exclusive(() => {\n const record = store.read()\n const marked = fields.filter(field => record.fields[field] && !record.overrides[field])\n if (marked.length === 0)\n return\n const at = Date.now()\n for (const field of marked)\n record.overrides[field] = { at }\n store.write(record)\n changed()\n })\n }\n\n /** Whether `deviceId` over `peer`'s token is the recorded source. */\n const isSource = (record: SyncRecord, deviceId: string, peer: HostPeer): boolean =>\n record.source !== null && record.source.deviceId === deviceId && record.source.tokenId === peer.principal\n\n /** The source's own call, or a refusal naming the device that syncs. */\n function requireSource(record: SyncRecord, deviceId: string, peer: HostPeer): void {\n if (!record.source)\n throw new Error('No device syncs to this server: claim it first (sync.claim).')\n if (!isSource(record, deviceId, peer))\n throw new Error(`This server is synced from ${record.source.deviceName}${record.source.deviceId === deviceId ? ' with another token' : ''}: take over from that device first.`)\n }\n\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n return {\n markOverrides,\n\n 'sync.status': (): SyncStatus => {\n requireOptions()\n return syncStatusOf(store.read())\n },\n\n 'sync.claim': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId, deviceName } = checkDevice(p, true)\n const categories = checkCategories(p.categories)\n if (p.keys !== undefined && (!Array.isArray(p.keys) || !p.keys.every(k => typeof k === 'string')))\n throw new InvalidParamsError('keys must be provider names.')\n const takeover = p.takeover === true\n const record = store.read()\n const other = record.source !== null && !isSource(record, deviceId, peer)\n if (other && !takeover) {\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: false, ok: true })\n return { claimed: false, status: syncStatusOf(record) }\n }\n const next: SyncRecord = other\n ? { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n : record\n next.source = {\n deviceId,\n deviceName,\n claimedAt: other || !record.source ? Date.now() : record.source.claimedAt,\n ...(peer.principal ? { tokenId: peer.principal } : {}),\n }\n if (categories)\n next.categories = categories\n if (p.keys !== undefined)\n next.keys = [...new Set(p.keys)]\n store.write(next)\n changed()\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: true, categories: next.categories, keys: next.keys, ok: true })\n return { claimed: true, status: syncStatusOf(next) }\n }),\n\n 'sync.push': (p, peer) => exclusive(async () => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const category = p.category\n const fields = { event: 'sync.push', category, deviceId }\n try {\n if (!SYNC_CATEGORIES.includes(category))\n throw new InvalidParamsError(`category must be one of: ${SYNC_CATEGORIES.join(', ')}.`)\n const record = store.read()\n requireSource(record, deviceId, peer)\n if (!record.categories.includes(category))\n throw new Error(`\"${category}\" is not synced to this server (claim it with that category).`)\n const result: SyncPushResult = { applied: [], unchanged: [], skipped: [], warnings: [] }\n const payload = p.payload as unknown\n if (category === 'settings') {\n pushSettings(ctx, record, payload as SyncPayloads['settings'], result)\n }\n else if (category === 'safelists') {\n pushSafelists(ctx, record, payload as SyncPayloads['safelists'], result)\n }\n else if (category === 'files') {\n if (pushFiles(ctx, record, payload as SyncPayloads['files'], result)) {\n rebuild()\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n }\n }\n else if (category === 'mcps') {\n await pushMcps(ctx, record, payload as SyncPayloads['mcps'], peer, result)\n }\n else if (category === 'extensions') {\n await pushExtensions(ctx, record, payload as SyncPayloads['extensions'], peer, result)\n }\n else if (category === 'environments') {\n pushEnvironments(ctx, record, payload as SyncPayloads['environments'], result)\n }\n else {\n pushKeys(ctx, record, payload as SyncPayloads['keys'], result)\n }\n record.lastPushAt = Date.now()\n store.write(record)\n changed()\n audit(peer, { ...fields, applied: result.applied.length, unchanged: result.unchanged.length, skipped: result.skipped.length, ok: true })\n return result\n }\n catch (err) {\n audit(peer, { ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }),\n\n 'sync.reset': (p, peer) => exclusive(() => {\n requireOptions()\n if (typeof p.field !== 'string' || p.field === '')\n throw new InvalidParamsError('field must be a sync field name.')\n const record = store.read()\n const reset = Boolean(record.overrides[p.field])\n if (reset) {\n delete record.overrides[p.field]\n // Forget the server value it was compared against: the next push writes over it.\n const known = record.fields[p.field]\n if (known) {\n delete known.hash\n delete known.sent\n }\n store.write(record)\n changed()\n }\n audit(peer, { event: 'sync.reset', field: p.field, reset, ok: true })\n return { reset }\n }),\n\n 'sync.release': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const record = store.read()\n if (!record.source)\n return { released: false }\n requireSource(record, deviceId, peer)\n // What it set stays; the marks go.\n store.write({ version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} })\n changed()\n audit(peer, { event: 'sync.release', deviceId, ok: true })\n return { released: true }\n }),\n }\n}\n\ntype OverrideWrapped = 'settings.set' | 'mcp.upsert' | 'mcp.remove' | 'catalog.remove' | 'catalog.update' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred'\n\n/**\n * The window-facing setters, marking what they change as an override when\n * the field came from sync (the sync handlers call the unwrapped ones).\n */\nexport function withSyncOverrides(\n handlers: Handlers<OverrideWrapped>,\n { readSettings, markOverrides }: { readSettings: () => object, markOverrides: (fields: readonly string[]) => Promise<void> },\n): Handlers<OverrideWrapped> {\n const after = async <T>(work: () => Promise<T> | T, fields: (result: T) => string[]): Promise<T> => {\n const result = await work()\n await markOverrides(fields(result))\n return result\n }\n return {\n 'settings.set': async (p, peer) => {\n const before = readSettings() as Record<string, unknown>\n return after(() => handlers['settings.set'](p, peer), next => Object.keys(isRecord(p?.patch) ? p.patch : {})\n .filter(key => JSON.stringify(before[key]) !== JSON.stringify((next as unknown as Record<string, unknown>)[key]))\n .map(settingField))\n },\n 'mcp.upsert': (p, peer) => after(() => handlers['mcp.upsert'](p, peer), r => (p.scope === 'project' ? [] : [`mcp:${r.name}`])),\n 'mcp.remove': (p, peer) => after(() => handlers['mcp.remove'](p, peer), r => (r.removed ? [`mcp:${p.name}`] : [])),\n 'catalog.remove': (p, peer) => after(() => handlers['catalog.remove'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'catalog.update': (p, peer) => after(() => handlers['catalog.update'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'auth.setApiKey': (p, peer) => after(() => handlers['auth.setApiKey'](p, peer), () => [`key:${p.provider}`]),\n 'auth.configure': (p, peer) => after(() => handlers['auth.configure'](p, peer), () => [`key:${p.provider}`]),\n 'auth.remove': (p, peer) => after(() => handlers['auth.remove'](p, peer), r => (r.removed ? [`key:${p.provider}`] : [])),\n 'auth.setPreferred': (p, peer) => after(() => handlers['auth.setPreferred'](p, peer), () => [`key:${p.provider}`]),\n }\n}\n","/** Shared terminals: lifecycle, I/O, and the views and viewers each client attaches. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { nonNegativeInt } from './params'\n\ntype TerminalMethod\n = | 'terminal.state' | 'terminal.open' | 'terminal.attach' | 'terminal.detach' | 'terminal.write'\n | 'terminal.resize' | 'terminal.ack' | 'terminal.restart' | 'terminal.close' | 'terminal.setHidden'\n | 'terminal.registerViewer' | 'terminal.unregisterViewer'\n | 'terminal.projectState' | 'terminal.openInProject' | 'terminal.adopt' | 'terminal.releaseDraft'\n\nexport function createTerminalHandlers({ host, isConnected }: {\n host: ChatHost\n isConnected: (peer: HostPeer) => boolean\n}): {\n methods: Handlers<TerminalMethod>\n /** The peer dropped: release its drafts and viewers, then detach its views. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'terminal.state': p => host.terminals.state(p.sessionId),\n 'terminal.open': p => host.terminals.open(p),\n 'terminal.attach': async (p, peer) => {\n // Optional: older clients omit it, and 0 means no cap.\n const maxLines = nonNegativeInt(p.maxLines, 'maxLines') || undefined\n const result = await host.terminals.attach(p.terminalId, p.clientId, { maxLines })\n // The peer dropped during the attach (a remote reconnect can take seconds):\n // its cleanup already ran, so a client left behind would never ack and stall every view.\n if (!isConnected(peer)) {\n host.terminals.detach(p.terminalId, p.clientId)\n return result\n }\n const views = (peer.terminalViews ??= new Map())\n views.set(p.terminalId, (views.get(p.terminalId) ?? new Set()).add(p.clientId))\n return result\n },\n 'terminal.detach': (p, peer) => {\n const views = peer.terminalViews?.get(p.terminalId)\n views?.delete(p.clientId)\n if (views?.size === 0)\n peer.terminalViews?.delete(p.terminalId)\n host.terminals.detach(p.terminalId, p.clientId)\n },\n 'terminal.write': p => host.terminals.write(p.terminalId, p.data, p.clientId ? { clientId: p.clientId, ...(p.response ? { response: true } : {}) } : undefined),\n 'terminal.resize': p => host.terminals.resize(p.terminalId, p.clientId, p.cols, p.rows, p.claim),\n 'terminal.ack': p => host.terminals.ack(p.terminalId, p.clientId, p.offset),\n 'terminal.restart': p => host.terminals.restart(p.terminalId),\n 'terminal.close': p => host.terminals.close(p.terminalId),\n 'terminal.setHidden': p => host.terminals.setHidden(p.terminalId, p.hidden),\n 'terminal.projectState': p => host.terminals.projectState(p),\n 'terminal.openInProject': async (p, peer) => {\n if (p.draftId)\n (peer.terminalDrafts ??= new Set()).add(p.draftId)\n const result = await host.terminals.openInProject(p)\n // The peer dropped during the open: its cleanup already ran, so nothing would release this draft.\n if (p.draftId && !isConnected(peer))\n host.terminals.releaseDraft(p.draftId)\n return result\n },\n 'terminal.adopt': async (p, peer) => {\n const result = await host.terminals.adopt(p)\n peer.terminalDrafts?.delete(p.draftId)\n return result\n },\n 'terminal.releaseDraft': (p, peer) => {\n peer.terminalDrafts?.delete(p.draftId)\n host.terminals.releaseDraft(p.draftId)\n },\n 'terminal.registerViewer': (p, peer) => {\n ;(peer.terminalViewers ??= new Set()).add(p.viewerId)\n host.terminals.registerViewer(p.viewerId)\n return { ok: true }\n },\n 'terminal.unregisterViewer': (p, peer) => {\n peer.terminalViewers?.delete(p.viewerId)\n host.terminals.unregisterViewer(p.viewerId)\n return { ok: true }\n },\n },\n releasePeer(peer) {\n // A client that crashed or quit never releases its drafts: give their terminals back to the project.\n for (const draftId of peer.terminalDrafts ?? [])\n host.terminals.releaseDraft(draftId)\n for (const viewerId of peer.terminalViewers ?? [])\n host.terminals.unregisterViewer(viewerId)\n for (const [terminalId, clients] of peer.terminalViews ?? []) {\n for (const clientId of clients)\n host.terminals.detach(terminalId, clientId)\n }\n },\n }\n}\n","/** `sessions.generateTitle`: the host titles a session with its own providers and credentials (`ChatHost.generateSessionTitle`). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { optionalString, sessionIdOf } from './params'\n\nexport function createTitleHandlers({ host, broadcast }: {\n host: ChatHost\n broadcast: (signal: HostSignal) => void\n}): Handlers<'sessions.generateTitle'> {\n return {\n 'sessions.generateTitle': async (p) => {\n const sessionId = sessionIdOf(p)\n const providerKey = optionalString(p.providerKey, 'providerKey')\n const model = optionalString(p.model, 'model')\n const title = await host.generateSessionTitle(sessionId, {\n ...(providerKey !== undefined ? { providerKey } : {}),\n ...(model !== undefined ? { model } : {}),\n })\n // As `sessions.setTitle`: every window told.\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n return { title }\n },\n }\n}\n","/** A session's todo list. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { TodoItem } from '../../../chat/todos'\nimport type { SessionStore } from '../../../session/index'\nimport type { TodosSnapshot } from '../../protocol'\nimport type { Handlers } from './types'\nimport { toTodosSnapshot } from '../../../chat/host/signals'\nimport { selectActiveTodos, setTodosForRun } from '../../../chat/todos'\nimport { loadSession } from '../../../session/index'\n\nexport function createTodoHandlers({ host, store }: { host: ChatHost, store: SessionStore }): Handlers<'todos.get' | 'todos.set'> {\n return {\n 'todos.get': (p): TodosSnapshot | null => {\n const state = host.getTodosSnapshot(p.sessionId)\n return state ? toTodosSnapshot(state) : null\n },\n\n /*\n * The host fans the resulting `todos:snapshot` out to every window,\n * including this caller — the returned snapshot is a confirmation, so the\n * sender can tell \"applied\" from \"no live agent\" (null) rather than\n * assuming success. `persistIdle` turns \"no live agent\" into a write to\n * the stored session (nothing else is writing it), for a client that has\n * no store of its own.\n */\n 'todos.set': async (p): Promise<TodosSnapshot | null> => {\n const state = await host.setTodos(p.sessionId, p.items)\n if (state)\n return toTodosSnapshot(state)\n if (p.persistIdle !== true || host.getLiveSession(p.sessionId))\n return null\n return persistIdleTodos(store, p.sessionId, Array.isArray(p.items) ? p.items : [])\n },\n }\n}\n\n/** The idle-session todo edit, as a window applied it to its own copy: the active run's list, archive cleared. */\nasync function persistIdleTodos(store: SessionStore, sessionId: string, items: readonly TodoItem[]): Promise<TodosSnapshot | null> {\n const session = await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n return null\n // `null` before the first run: the session slot that run will read.\n setTodosForRun(session, selectActiveTodos(session).runId, items, { clearArchive: true })\n await session.save()\n return toTodosSnapshot(selectActiveTodos(session))\n}\n","/** A session's turns: replay, fork, edits, out-of-band appends, and compaction. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { StreamEvent } from '../../../chat/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostTranscriptPager } from '../../history/index'\nimport type { HostSignal, LoadEventsPaging } from '../../protocol'\nimport type { Handlers } from './types'\nimport { describeForkFailure } from '../../../chat/session-factory'\nimport { eventsFromTurns } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\nimport { isPagedLoad } from './transcript-page'\n\ntype TranscriptMethod\n = | 'sessions.loadEvents' | 'sessions.getTurn' | 'sessions.touch' | 'sessions.fork' | 'sessions.deleteTurn'\n | 'sessions.editTurnText' | 'sessions.rewind' | 'sessions.appendTurns' | 'sessions.appendNote' | 'sessions.compact'\n\nexport function createTranscriptHandlers({ host, store, broadcast, pages }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Pages, sliced from the session's whole replay (one replay per scroll-back, not per page), off this thread when it can. */\n pages: Pick<HostTranscriptPager, 'page'>\n}): Handlers<TranscriptMethod> {\n return {\n 'sessions.loadEvents': async (p) => {\n const paging = p as typeof p & LoadEventsPaging\n if (isPagedLoad(paging)) {\n // A slice of the whole replay: pages concatenate to exactly one whole load.\n // The paged shape (`loadEventsPage`); the method is typed by its unpaged call.\n return await pages.page(store, p.sessionId, paging) as unknown as StreamEvent[]\n }\n const data = await loadOrThrow(store, p.sessionId)\n // Pass `runs` so replay reconstructs subagent depth / ancestry /\n // spawn rendering — matching the GUI + TUI local replay paths.\n return eventsFromTurns(data.turns, data.runs)\n },\n 'sessions.getTurn': async (p) => {\n const data = await store.load(p.sessionId)\n return data?.turns.find(t => t.id === p.turnId) ?? null\n },\n // Out-of-band transcript append (local command / bash output) — tell\n // every window to re-converge on the store's canonical replay.\n 'sessions.touch': (p) => {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.fork': async (p) => {\n const result = await host.forkSession({\n source: p.sessionId,\n turnId: p.turnId,\n ...(typeof p.title === 'string' && p.title ? { title: p.title.slice(0, 256) } : {}),\n })\n if (!result.ok)\n throw new Error(describeForkFailure(result.reason, p.sessionId, p.turnId))\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: result.id })\n return { id: result.id }\n },\n 'sessions.deleteTurn': p => host.deleteTurn(p.sessionId, p.turnId),\n // Same 64 KiB text cap as the composer paths.\n 'sessions.editTurnText': p => host.editTurnText(p.sessionId, p.turnId, typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''),\n 'sessions.rewind': p => host.rewindSession(p.sessionId, p.turnId, { inclusive: p.inclusive === true }),\n 'sessions.appendTurns': p => host.appendTurns(p.sessionId, Array.isArray(p.turns) ? p.turns : [], { whenIdle: p.whenIdle === true }),\n 'sessions.appendNote': p => host.appendNote(\n p.sessionId,\n Array.isArray(p.blocks) ? p.blocks.filter(block => typeof block?.text === 'string') : [],\n ),\n 'sessions.compact': p => host.compactSessionNow(p.sessionId),\n }\n}\n","/**\n * `usage.summary`: the welcome screen's usage summary over the host's\n * sessions database, as the desktop app reduces its own\n * (`../../../chat/usage-summary.ts`). The scan reads every turn, so its day\n * buckets are kept a minute and every range is cut from them; concurrent\n * calls share one scan. Days are the host's local days. The greeting's name\n * is left out: the host's user is not the person reading.\n *\n * `usage.providers`: each provider's plan windows, probed with the host's\n * credentials (`../../../chat/provider-usage.ts`, which caches them), and\n * `usage.github`: GitHub's API limits as the host's GitHub client sees them.\n */\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { UsageRange } from '../../../chat/usage-summary'\nimport type { SessionStore } from '../../../session/index'\nimport type { UsageBuckets } from '../../../session/sqlite-usage'\nimport type { Handlers } from './types'\nimport { fetchGithubUsage } from '../../../chat/github-usage'\nimport { fetchAllProviderUsage } from '../../../chat/provider-usage'\nimport { summarizeUsage, USAGE_RANGES } from '../../../chat/usage-summary'\nimport { InvalidParamsError } from './params'\n\n/** How long one scan's buckets serve. */\nconst BUCKETS_TTL_MS = 60_000\n\nexport function createUsageHandlers({ store, scan, dataDir, providers }: {\n store: SessionStore\n /** The store's day buckets (`HostTranscriptPager.usage`); `null`: the store keeps no usage. */\n scan: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Where the credentials are. */\n dataDir: () => string\n /** The host's providers. */\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n}): Handlers<'usage.summary' | 'usage.providers' | 'usage.github'> {\n let cached: { buckets: UsageBuckets, at: number } | null = null\n let pending: Promise<UsageBuckets> | null = null\n const buckets = (now: number): Promise<UsageBuckets> => {\n if (cached && now - cached.at < BUCKETS_TTL_MS)\n return Promise.resolve(cached.buckets)\n pending ??= scan(store).then((scanned) => {\n if (!scanned)\n throw new Error('This host\\'s session store keeps no usage history.')\n cached = { buckets: scanned, at: Date.now() }\n return scanned\n }).finally(() => {\n pending = null\n })\n return pending\n }\n return {\n 'usage.summary': async (p) => {\n if (!USAGE_RANGES.includes(p.range as UsageRange))\n throw new InvalidParamsError(`range must be one of ${USAGE_RANGES.join(', ')}.`)\n const now = new Date()\n return summarizeUsage(await buckets(now.getTime()), p.range, { now })\n },\n 'usage.providers': p => fetchAllProviderUsage(dataDir(), providers(), { refresh: p?.refresh === true }),\n 'usage.github': p => fetchGithubUsage({ probe: p?.probe === true }),\n }\n}\n","/** Commands and file access inside a session's workspace (its execution environment). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\n\ntype WorkspaceMethod\n = | 'sessions.workspaceExec' | 'sessions.workspaceReadFile' | 'sessions.workspaceWriteFile'\n | 'sessions.workspaceListFiles' | 'sessions.workspaceFileSize'\n | 'sessions.workspaceCreate' | 'sessions.workspaceMove' | 'sessions.workspaceCopy' | 'sessions.workspaceRemove'\n | 'sessions.workspaceEmptyDirs'\n\n/** A path param of an entry call: a string, else refused like any invalid name (the rules check the rest). */\nconst pathParam = (value: unknown): string => (typeof value === 'string' ? value : '\\0')\n\nexport function createWorkspaceHandlers({ host }: { host: ChatHost }): Handlers<WorkspaceMethod> {\n return {\n 'sessions.workspaceExec': p => host.workspaceExec(p.sessionId, p.command, {\n ...(p.cwd !== undefined ? { cwd: p.cwd } : {}),\n ...(p.env !== undefined ? { env: p.env } : {}),\n ...(p.timeoutSeconds !== undefined ? { timeoutSeconds: p.timeoutSeconds } : {}),\n }),\n 'sessions.workspaceReadFile': p => host.workspaceReadFile(p.sessionId, p.path),\n 'sessions.workspaceWriteFile': p => host.workspaceWriteFile(p.sessionId, p.path, p.content),\n 'sessions.workspaceListFiles': p => host.workspaceListFiles(p.sessionId, p.path, p.options),\n 'sessions.workspaceFileSize': p => host.workspaceFileSize(p.sessionId, p.path),\n 'sessions.workspaceCreate': (p) => {\n if (p.kind !== 'file' && p.kind !== 'dir')\n throw new Error('kind must be \"file\" or \"dir\".')\n if (p.content !== undefined && typeof p.content !== 'string')\n throw new Error('content must be base64 text.')\n return host.workspaceCreate(p.sessionId, pathParam(p.path), p.kind, {\n ...(p.content !== undefined ? { content: new Uint8Array(Buffer.from(p.content, 'base64')) } : {}),\n ...(p.freeName === true ? { freeName: true } : {}),\n })\n },\n 'sessions.workspaceMove': p => host.workspaceMove(p.sessionId, pathParam(p.from), pathParam(p.to)),\n 'sessions.workspaceCopy': p => host.workspaceCopy(p.sessionId, pathParam(p.from), pathParam(p.toDir)),\n 'sessions.workspaceRemove': p => host.workspaceRemove(p.sessionId, pathParam(p.path)),\n 'sessions.workspaceEmptyDirs': p => host.workspaceEmptyDirs(p.sessionId),\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Streamed workspace commands (`sessions.workspaceExecStream` /\n * `sessions.workspaceExecCancel`): `!` on a remote host, live. The process\n * is the session context's `execStream` (a machine's too); its output goes\n * to the connection that started it only, as `workspace:exec:data` signals,\n * then one `workspace:exec:exit`. Bounded per connection: concurrent\n * commands, chunk size, total output (past it the process group is stopped\n * and the exit says `truncated`). Cancel and a dropped connection kill the\n * process group. A context that can't stream runs the buffered exec and\n * reports it the same way (its cancel stops reporting, not the command).\n */\nimport type { StreamHandle } from '../../../contexts/types'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\nimport { InvalidParamsError } from './params'\n\nexport const WORKSPACE_EXEC_STREAM_LIMITS = {\n /** Streamed commands one connection may run at once. */\n maxConcurrent: 4,\n /** Largest `chunk` of one data signal, in bytes. */\n chunkBytes: 64 * 1024,\n /** Output past this (stdout + stderr, bytes) stops the process: the same ceiling as a local `!`. */\n maxOutputBytes: 1024 * 1024,\n /** Longest command text. */\n maxCommandLength: 64 * 1024,\n /** The buffered fallback's bound (seconds), as the buffered `!` had. */\n fallbackTimeoutSeconds: 600,\n}\n\ntype ExitSignal = Extract<HostSignal, { kind: 'workspace:exec:exit' }>\n\ninterface RunningExec {\n peer: HostPeer\n /** Ends the process group (the fallback: stops reporting). */\n kill: () => void\n cancelled: boolean\n /** A kill was sent before the process's exit was known: the exit is the kill's. */\n killedLive?: boolean\n}\n\n/** Cut `text` into pieces of at most `max` UTF-8 bytes, never inside a code point. */\nfunction utf8Pieces(text: string, max: number): string[] {\n if (Buffer.byteLength(text) <= max)\n return [text]\n const pieces: string[] = []\n let current = ''\n let bytes = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max) {\n pieces.push(current)\n current = ''\n bytes = 0\n }\n current += char\n bytes += size\n }\n if (current)\n pieces.push(current)\n return pieces\n}\n\n/** The longest prefix of `text` within `max` UTF-8 bytes. */\nfunction utf8Prefix(text: string, max: number): string {\n let bytes = 0\n let end = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max)\n break\n bytes += size\n end += char.length\n }\n return text.slice(0, end)\n}\n\nexport function createWorkspaceExecStreamHandlers({ host, isConnected, limits = WORKSPACE_EXEC_STREAM_LIMITS }: {\n host: Pick<ChatHost, 'workspaceExecStream' | 'workspaceExec'>\n isConnected: (peer: HostPeer) => boolean\n limits?: typeof WORKSPACE_EXEC_STREAM_LIMITS\n}): {\n methods: Handlers<'sessions.workspaceExecStream' | 'sessions.workspaceExecCancel'>\n /** The peer dropped: kill what it started. */\n releasePeer: (peer: HostPeer) => void\n} {\n const running = new Map<string, RunningExec>()\n const perPeer = new WeakMap<HostPeer, Set<string>>()\n\n const send = (peer: HostPeer, signal: HostSignal): void => {\n if (isConnected(peer))\n peer.send(signal)\n }\n\n /** Output accounting for one exec: emits what fits, reports when the cap is reached. */\n function outputSink(execId: string, peer: HostPeer, onCap: () => void) {\n let total = 0\n let capped = false\n return {\n capped: () => capped,\n emit(stream: 'stdout' | 'stderr', text: string): void {\n if (capped || text === '')\n return\n let piece = text\n if (total + Buffer.byteLength(piece) > limits.maxOutputBytes) {\n piece = utf8Prefix(piece, limits.maxOutputBytes - total)\n capped = true\n }\n total += Buffer.byteLength(piece)\n for (const chunk of piece ? utf8Pieces(piece, limits.chunkBytes) : [])\n send(peer, { kind: 'workspace:exec:data', execId, stream, chunk })\n if (capped)\n onCap()\n },\n }\n }\n\n async function pump(execId: string, peer: HostPeer, stream: StreamHandle, entry: RunningExec): Promise<void> {\n const sink = outputSink(execId, peer, () => entry.kill())\n const drain = async (source: AsyncIterable<Uint8Array> | undefined, name: 'stdout' | 'stderr'): Promise<void> => {\n if (!source)\n return\n const decoder = new TextDecoder()\n try {\n for await (const bytes of source)\n sink.emit(name, decoder.decode(bytes, { stream: true }))\n sink.emit(name, decoder.decode())\n }\n catch {\n // The stream ended badly (a dropped machine link): the exit says how.\n }\n }\n const [code] = await Promise.all([stream.exited, drain(stream.stdout, 'stdout'), drain(stream.stderr, 'stderr')])\n // A cancel or cap that landed after the process exited on its own leaves its real exit.\n const killed = entry.killedLive === true\n const exit: ExitSignal = {\n kind: 'workspace:exec:exit',\n execId,\n code: killed ? null : code,\n signal: killed ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled && killed ? { cancelled: true as const } : {}),\n }\n send(peer, exit)\n }\n\n /** A context without `execStream`: the buffered exec, reported as one stdout and one stderr chunk. */\n async function buffered(execId: string, peer: HostPeer, entry: RunningExec, run: () => Promise<{ stdout: string, stderr: string, exitCode: number }>): Promise<void> {\n let stopped = false\n entry.kill = () => {\n stopped = true\n }\n const sink = outputSink(execId, peer, () => undefined)\n try {\n const result = await run()\n if (!stopped) {\n sink.emit('stdout', result.stdout)\n sink.emit('stderr', result.stderr)\n }\n send(peer, {\n kind: 'workspace:exec:exit',\n execId,\n code: stopped ? null : result.exitCode,\n signal: stopped ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled ? { cancelled: true as const } : {}),\n })\n }\n catch (err) {\n sink.emit('stderr', err instanceof Error ? err.message : String(err))\n send(peer, { kind: 'workspace:exec:exit', execId, code: null, signal: null, ...(entry.cancelled ? { cancelled: true as const } : {}) })\n }\n }\n\n return {\n methods: {\n 'sessions.workspaceExecStream': async (p, peer) => {\n if (typeof p.sessionId !== 'string' || p.sessionId === '')\n throw new InvalidParamsError('sessionId must be a non-empty string.')\n if (typeof p.command !== 'string' || p.command.trim() === '')\n throw new InvalidParamsError('command must be a non-empty string.')\n if (p.command.length > limits.maxCommandLength)\n throw new InvalidParamsError(`command is longer than ${limits.maxCommandLength} characters.`)\n if (p.cwd !== undefined && typeof p.cwd !== 'string')\n throw new InvalidParamsError('cwd must be a string.')\n const own = perPeer.get(peer) ?? new Set<string>()\n perPeer.set(peer, own)\n if (own.size >= limits.maxConcurrent)\n throw new Error(`This connection already runs ${own.size} shell commands (at most ${limits.maxConcurrent}): stop one first.`)\n const execId = randomUUID()\n // Reserved before the await: concurrent requests count against the bound too.\n own.add(execId)\n const entry: RunningExec = { peer, kill: () => undefined, cancelled: false }\n running.set(execId, entry)\n const done = (): void => {\n own.delete(execId)\n running.delete(execId)\n }\n const options = p.cwd !== undefined ? { cwd: p.cwd } : {}\n let stream: StreamHandle | null\n try {\n stream = await host.workspaceExecStream(p.sessionId, p.command, options)\n }\n catch (err) {\n done()\n throw err\n }\n if (stream) {\n const live = stream\n let exited = false\n void live.exited.then(() => {\n exited = true\n }, () => {\n exited = true\n })\n entry.kill = () => {\n if (!exited)\n entry.killedLive = true\n void live.kill()\n }\n // Dropped while it started: nobody will read it.\n if (!isConnected(peer))\n entry.kill()\n void pump(execId, peer, live, entry).finally(done)\n }\n else {\n void buffered(execId, peer, entry, () => host.workspaceExec(p.sessionId, p.command, { ...options, timeoutSeconds: limits.fallbackTimeoutSeconds })).finally(done)\n }\n return { execId }\n },\n 'sessions.workspaceExecCancel': (p, peer) => {\n const entry = typeof p.execId === 'string' ? running.get(p.execId) : undefined\n if (!entry || entry.peer !== peer)\n return { cancelled: false }\n entry.cancelled = true\n entry.kill()\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const execId of perPeer.get(peer) ?? []) {\n const entry = running.get(execId)\n if (entry) {\n entry.cancelled = true\n entry.kill()\n }\n }\n },\n }\n}\n","/**\n * `ipc.hello` verdict: can this client attach to this host process?\n *\n * Pure (no I/O, no state) so every transport applies the same three fences:\n * protocol version, build fingerprint, release. Kept apart from the\n * dispatcher because the rules are subtle and the direction of each fence\n * (only a strictly NEWER client retires the host) matters more than the code.\n *\n * A network server (`hostKind: 'server'`) keeps only the protocol fence: it\n * outlives any one client's upgrade and no client may retire it, so a newer\n * release or build attaches and degrades like an older one does.\n */\nimport type { HelloParams, HostKind } from '../protocol'\nimport { compareVersions } from '../../version'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION } from '../protocol'\n\nexport type HelloVerdict\n /**\n * `retire`: attach, but the host must exit at its first idle point. `protocolVersion`: what\n * the connection speaks (a server and a client in each other's range speak the lower one).\n */\n = | { accept: true, retire: boolean, protocolVersion: number }\n | { accept: false, message: string }\n\nexport interface HelloContext {\n /** This host's build fingerprint (`IPC_BUILD_ID`; `'unknown'` in compiled binaries). */\n buildId: string\n /** This host's release (`ZIDANE_VERSION`). */\n codeVersion: string\n /** Runs, queues or interactions in flight that a drain would abort. */\n hasActiveWork: boolean\n /** What this host is. Default: a local daemon's fences. */\n hostKind?: HostKind\n}\n\n/**\n * A server accepts a client whose version range overlaps its own\n * ({@link IPC_MIN_PROTOCOL_VERSION}…{@link IPC_PROTOCOL_VERSION}); they speak the lower version.\n */\nfunction evaluateServerHello(params: Partial<HelloParams>): HelloVerdict {\n const client = typeof params.protocolVersion === 'number' ? params.protocolVersion : undefined\n const clientMin = typeof params.minProtocolVersion === 'number' ? Math.min(params.minProtocolVersion, client ?? Infinity) : client\n if (client !== undefined && clientMin !== undefined && clientMin <= IPC_PROTOCOL_VERSION && client >= IPC_MIN_PROTOCOL_VERSION)\n return { accept: true, retire: false, protocolVersion: Math.min(client, IPC_PROTOCOL_VERSION) }\n const upgrade = client !== undefined && client > IPC_PROTOCOL_VERSION ? 'server' : 'client'\n const speaks = IPC_MIN_PROTOCOL_VERSION === IPC_PROTOCOL_VERSION ? `v${IPC_PROTOCOL_VERSION}` : `v${IPC_MIN_PROTOCOL_VERSION} to v${IPC_PROTOCOL_VERSION}`\n return {\n accept: false,\n message: `Protocol version mismatch: the server speaks ${speaks}, the client v${client ?? '?'}. Upgrade the ${upgrade}.`,\n }\n}\n\nexport function evaluateHello(params: Partial<HelloParams>, ctx: HelloContext): HelloVerdict {\n if (ctx.hostKind === 'server')\n return evaluateServerHello(params)\n /*\n * Build-fingerprint drain is DIRECTIONAL: only a strictly NEWER\n * client retires this (older) daemon. An older client accepts a\n * newer daemon — its unknown methods degrade via `optional()`.\n * Without the direction check, two concurrently-running clients\n * from different builds would each reject the other's daemon and\n * drain-respawn in a loop, aborting live runs each cycle.\n */\n const clientBuild = Number(params.buildId)\n const daemonBuild = Number(ctx.buildId)\n const staleBuild\n = params.buildId !== undefined\n && params.buildId !== 'unknown'\n && ctx.buildId !== 'unknown'\n && Number.isFinite(clientBuild)\n && Number.isFinite(daemonBuild)\n && clientBuild > daemonBuild\n /*\n * Release fence: the same protocol version can span several\n * releases, and a daemon outlives the upgrade that replaced its\n * binary — a client running strictly NEWER code must not execute on\n * the old process. Same direction rule as the build fence: only a\n * newer client retires the daemon; older clients attach and degrade.\n */\n const staleRelease\n = typeof params.codeVersion === 'string'\n && compareVersions(params.codeVersion, ctx.codeVersion) > 0\n /*\n * Same protocol, older code, live work: attach instead of asking\n * for a drain that would abort it. The client can speak to this\n * daemon; it only must not stay on it, so the daemon retires at\n * its first idle point and the client's reconnect lands on a\n * fresh one. A protocol mismatch can't attach and stays refused.\n */\n const protocolMatches = params.protocolVersion === IPC_PROTOCOL_VERSION\n if (protocolMatches && (staleBuild || staleRelease) && ctx.hasActiveWork)\n return { accept: true, retire: true, protocolVersion: IPC_PROTOCOL_VERSION }\n if (!protocolMatches || staleBuild || staleRelease) {\n return {\n accept: false,\n message: staleRelease\n ? `Stale daemon: it runs zidane ${ctx.codeVersion} but the client runs ${params.codeVersion}. Draining for respawn.`\n : staleBuild\n ? `Build mismatch: the daemon was started from an older build (daemon ${ctx.buildId}, client ${params.buildId}). Draining for respawn.`\n : `Protocol version mismatch: daemon speaks v${IPC_PROTOCOL_VERSION}, client sent v${params.protocolVersion ?? '?'}.`,\n }\n }\n return { accept: true, retire: false, protocolVersion: IPC_PROTOCOL_VERSION }\n}\n","/**\n * Host identity: which host a client is talking to, stable across restarts.\n *\n * The id is a UUID written once to `<dataDir>/host-id` and read back on every\n * start. The data dir is the host's `userDataDir` (the user's zidane dir), so\n * the local daemon and a window's in-process host share one id: they serve\n * the same store on the same computer. A remote `zidane-server` has its own\n * data dir, hence its own id.\n */\nimport type { HostKind } from '../protocol'\nimport { hostname } from 'node:os'\nimport { join } from 'node:path'\nimport { readOrCreateHostIdFile } from '../../host-id'\n\nexport interface HostIdentityOptions {\n kind: HostKind\n /** Display name. Default: the machine's hostname. */\n name?: string\n}\n\nexport interface HostIdentity {\n /** `undefined` when the data dir can't hold the id: the host still serves, without identity. */\n id: string | undefined\n kind: HostKind\n name: string\n}\n\nconst FILE = 'host-id'\n\nexport function resolveHostIdentity(dataDir: string, options: HostIdentityOptions): HostIdentity {\n return {\n id: readOrCreateHostIdFile(join(dataDir, FILE)),\n kind: options.kind,\n name: options.name ?? hostname(),\n }\n}\n","/**\n * Connected peers: the set, signal fan-out, live presence, and the cleanup a\n * dropped peer triggers. Presence piggybacks on fan-out, so the two live\n * together.\n *\n * Streaming deltas are coalesced here, once per event-loop turn: a run of\n * consecutive deltas with the same owner (`deltaKey`) goes out as one signal\n * with their texts joined, one number, one log entry. Anything else that is\n * fanned out (any other signal, terminal output, an origin-excluded one) and\n * a peer joining or leaving sends the held delta first, and so does\n * {@link PeerRegistry.flush}, which the dispatcher calls around every\n * request, so a reply never overtakes a delta emitted before it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal, SessionPresence } from '../protocol'\nimport type { ClientScope } from '../scopes'\n\n/**\n * A signal serialized once for every peer of one fan-out. `json` is the\n * signal's JSON, computed on first use (`undefined`: it cannot be encoded,\n * so no peer can receive it). `frame` is where the wire transports memoize\n * the notification text they all send (`../transports/peer-rpc`).\n */\nexport interface EncodedSignal {\n json: () => string | undefined\n frame?: string\n}\n\nexport function encodeSignal(signal: HostSignal): EncodedSignal {\n let json: string | undefined\n let done = false\n return {\n json: () => {\n if (!done) {\n done = true\n try {\n json = JSON.stringify(signal)\n }\n catch {\n json = undefined\n }\n }\n return json\n },\n }\n}\n\n/** One connected client, as the dispatcher sees it. The transport creates it and supplies `send`. */\nexport interface HostPeer {\n /**\n * Delivers one host signal to this client, with its number in its session\n * when it has one (`./signal-log`; the wire carries it as\n * `SIGNAL_SEQ_FIELD`). `encoded` is the same signal already serialized\n * for every peer of the fan-out (absent: serialize it yourself). Must\n * never throw.\n */\n send: (signal: HostSignal, seq?: number, encoded?: EncodedSignal) => void\n /** Set once `ipc.hello` succeeded; only ready peers receive signals. */\n ready: boolean\n /** Session this peer's window is attached to (`presence.watch`). */\n watching: string | null\n /** Browser hosts this peer registered (`browser.registerHost`), released when it drops. */\n browserHosts?: Set<string>\n /** Terminal views attached through this peer: terminal id → client ids. Detached when it drops. */\n terminalViews?: Map<string, Set<string>>\n /** Terminal viewers this peer registered (`terminal.registerViewer`), released when it drops. */\n terminalViewers?: Set<string>\n /** Drafts this peer opened terminals in (`terminal.openInProject`), released to their project when it drops. */\n terminalDrafts?: Set<string>\n /** What authenticated the connection (a zidane-server's token id), for its audit lines. */\n principal?: string\n /** The token's name, when the transport knows it (`/mcp`): how an answer it gives is attributed. */\n principalName?: string\n /**\n * The client scope its token grants (`../scopes`): a call above it is refused. Absent: the\n * connection reaches every method (a local window, the daemon's socket).\n */\n grant?: ClientScope\n /**\n * The protocol version this connection speaks, set by `ipc.hello` (the lower of the client's\n * and the host's, `../daemon/handshake`). A handler that changed shape across versions reads it.\n */\n protocolVersion?: number\n}\n\nexport interface PeerRegistry {\n add: (peer: HostPeer) => void\n /** Whether the peer is still connected (a handler may outlive its peer across an await). */\n has: (peer: HostPeer) => boolean\n /** The peer's connection ended: run every `onClose` cleanup in registration order, then refresh presence. */\n remove: (peer: HostPeer) => void\n /** Release what a peer registered when it drops; runs in registration order. */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n /** Forget every peer WITHOUT per-peer cleanup (the host is shutting down). */\n clear: () => void\n /** Run `stop` once on {@link clear}, when the host shuts down. */\n onClear: (stop: () => void) => void\n size: () => number\n /** Fan a host signal out to every ready peer (terminal output only to its viewers), refreshing presence on the signals that change it. A streaming delta may be held for the rest of this event-loop turn (see the module header). */\n broadcast: (signal: HostSignal) => void\n /** Send the held streaming delta now, if any. */\n flush: () => void\n /**\n * Fan out to every handshaken peer except `origin`. Draft signals use\n * this so a window's own keystrokes never bounce back and fight its\n * cursor — echo-safety by construction, no client-side dedupe.\n */\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n computePresence: () => SessionPresence[]\n broadcastPresence: () => void\n /**\n * Late-bound: the broadcast sink exists before the host (the environment\n * the host is built on needs it), and presence reads the host only once a\n * signal arrives.\n */\n bindHost: (host: PresenceSource) => void\n}\n\n/** The host as peers read it: presence, and the facets that hear every signal fanned out (`ChatHost.facets.observe`). */\ntype PresenceSource = Pick<ChatHost, 'approvals' | 'interactions' | 'listLiveSessions'> & { facets?: Pick<ChatHost['facets'], 'observe'> }\n\nexport interface PeerRegistryOptions {\n /** Numbers a signal on its way to every peer (`SignalLog.record`); `json` serializes it (once, shared with the peers). */\n sequence?: (signal: HostSignal, json: () => string | undefined) => number | undefined\n}\n\n/** The fields a delta event may carry and still be coalesced. */\nconst DELTA_FIELDS: ReadonlySet<string> = new Set(['kind', 'text', 'streaming', 'turnId', 'childId', 'depth'])\n\ntype DeltaSignal = Extract<HostSignal, { kind: 'event' }>\n\n/**\n * What a streaming delta coalesces under (session, kind, owner, depth,\n * turn), or `null` when the signal is not a plain delta. Two consecutive\n * deltas with the same key give the client reducers (`appendMarkdownDelta`,\n * `appendThinkingLines` in `src/chat/streaming-pure.ts`) the same rows as\n * one delta with both texts: markdown appends the text, thinking splits it\n * on `\\n` into the owner's last row and new rows after it.\n */\nfunction deltaKey(signal: HostSignal): string | null {\n if (signal.kind !== 'event')\n return null\n const event = signal.event as { kind: string, text?: unknown, streaming?: unknown, turnId?: unknown, childId?: unknown, depth?: unknown }\n if (event.kind === 'markdown' ? event.streaming !== true : event.kind !== 'thinking')\n return null\n if (typeof event.text !== 'string')\n return null\n for (const key in signal) {\n if (key !== 'kind' && key !== 'sessionId' && key !== 'event')\n return null\n }\n for (const key in event) {\n if (!DELTA_FIELDS.has(key))\n return null\n }\n return JSON.stringify([signal.sessionId, event.kind, event.streaming ?? null, event.childId ?? null, event.depth ?? null, event.turnId ?? null])\n}\n\nexport function createPeerRegistry(options: PeerRegistryOptions = {}): PeerRegistry {\n const peers = new Set<HostPeer>()\n let boundHost: PresenceSource | null = null\n const closeCleanups: Array<(peer: HostPeer) => void> = []\n const clearListeners: Array<() => void> = []\n\n /** Sessions with a run in flight, tracked from the run signals themselves. */\n const runningSessions = new Set<string>()\n\n /** The held delta: one slot, so deltas of different owners never change order. */\n let held: { key: string, signal: DeltaSignal, copied: boolean } | null = null\n let flushArmed = false\n\n const flush = (): void => {\n const pending = held\n if (!pending)\n return\n held = null\n emit(pending.signal)\n }\n\n const broadcast = (signal: HostSignal): void => {\n const key = deltaKey(signal)\n if (key !== null && held?.key === key) {\n const delta = signal as DeltaSignal\n if (!held.copied) {\n // The caller's object stays as it was.\n held.signal = { ...held.signal, event: { ...held.signal.event } }\n held.copied = true\n }\n const event = held.signal.event as { text: string }\n event.text += (delta.event as { text: string }).text\n return\n }\n flush()\n if (key === null) {\n emit(signal)\n return\n }\n held = { key, signal: signal as DeltaSignal, copied: false }\n if (!flushArmed) {\n flushArmed = true\n setImmediate(() => {\n flushArmed = false\n flush()\n })\n }\n }\n\n function emit(signal: HostSignal): void {\n // Terminal output only goes where the terminal is shown.\n if (signal.kind === 'terminal:output' || signal.kind === 'terminal:reset') {\n const encoded = encodeSignal(signal)\n for (const peer of peers) {\n if (peer.ready && peer.terminalViews?.has(signal.terminalId))\n peer.send(signal, undefined, encoded)\n }\n return\n }\n // Numbered only here: what every peer gets is what a reattaching one can be replayed.\n fanOut(null, signal, true)\n /*\n * Presence piggybacks on the signals that change it — run state and\n * HITL queues — so the snapshot stays fresh without instrumenting the\n * host. `presence:changed` itself is emitted via `broadcastExcept`\n * directly, so this cannot recurse.\n */\n switch (signal.kind) {\n case 'run:start':\n // Signal-tracked rather than read off `agent.isRunning`: the host\n // broadcasts `run:start` BEFORE invoking `agent.run()`, so the\n // flag lags the signal by a tick.\n runningSessions.add(signal.sessionId)\n broadcastPresence()\n break\n case 'run:end':\n runningSessions.delete(signal.sessionId)\n broadcastPresence()\n break\n case 'approval:request':\n case 'approval:resolved':\n case 'interaction:request':\n case 'interaction:resolved':\n broadcastPresence()\n break\n default:\n break\n }\n }\n\n /** Serialized once here, for the log and every peer. */\n function fanOut(origin: HostPeer | null, signal: HostSignal, numbered: boolean): void {\n // The handlers' `sessions:changed` reach the facets here; the host's own reach them twice in one tick, computed once.\n boundHost?.facets?.observe(signal)\n const encoded = encodeSignal(signal)\n const seq = numbered ? options.sequence?.(signal, encoded.json) : undefined\n for (const peer of peers) {\n if (!peer.ready || peer === origin)\n continue\n peer.send(signal, seq, encoded)\n }\n }\n\n function broadcastExcept(origin: HostPeer | null, signal: HostSignal): void {\n flush()\n fanOut(origin, signal, false)\n }\n\n /**\n * Live presence: which sessions have attached windows, and their\n * run / awaiting-input state. Union of watched, live-agent, and\n * pending-HITL sessions — small by construction.\n */\n function computePresence(): SessionPresence[] {\n const host = boundHost\n if (!host)\n throw new Error('Presence read before the host was bound.')\n const windowCounts = new Map<string, number>()\n for (const peer of peers) {\n if (peer.ready && peer.watching)\n windowCounts.set(peer.watching, (windowCounts.get(peer.watching) ?? 0) + 1)\n }\n\n const attention = new Set<string>()\n for (const request of host.approvals.listPending())\n attention.add(request.sessionId)\n for (const pending of host.interactions.list())\n attention.add(pending.sessionId)\n\n // Union of signal-tracked runs (fresh) and the agent flag (covers a\n // window attaching to a daemon whose run started before it connected).\n const live = new Map(host.listLiveSessions().map(entry => [entry.sessionId, entry.running]))\n\n const ids = new Set<string>([...windowCounts.keys(), ...attention, ...live.keys(), ...runningSessions])\n return [...ids].map(sessionId => ({\n sessionId,\n windows: windowCounts.get(sessionId) ?? 0,\n running: runningSessions.has(sessionId) || live.get(sessionId) === true,\n attention: attention.has(sessionId),\n }))\n }\n\n function broadcastPresence(): void {\n broadcastExcept(null, { kind: 'presence:changed', sessions: computePresence() })\n }\n\n return {\n add(peer) {\n flush()\n peers.add(peer)\n },\n has: peer => peers.has(peer),\n remove(peer) {\n flush()\n if (!peers.delete(peer))\n return\n for (const cleanup of closeCleanups)\n cleanup(peer)\n // The window detached: its session may have left the \"active\" set.\n if (peer.watching)\n broadcastPresence()\n },\n onClose(cleanup) {\n closeCleanups.push(cleanup)\n },\n clear() {\n flush()\n peers.clear()\n for (const stop of clearListeners.splice(0))\n stop()\n },\n onClear(stop) {\n clearListeners.push(stop)\n },\n size: () => peers.size,\n broadcast,\n flush,\n broadcastExcept,\n computePresence,\n broadcastPresence,\n bindHost(host) {\n boundHost = host\n },\n }\n}\n","/**\n * What each authenticated principal (a zidane-server token id) set going on\n * this host: the sessions it drove (prompts, queued and steered messages,\n * orchestration) and the terminals it opened. Revoking the token stops them\n * (`stop`): a leaked token's agent runs and shells must not outlive its\n * revocation. A process they left running in the background (`nohup`, a\n * daemonized server) is out of reach: only a restart of the host ends it.\n *\n * A driven session is claimed before its method runs (`claim`), so a\n * revocation landing mid-call (a `chat.send` still provisioning) finds it;\n * the rest is recorded after a method succeeded, from its params or result.\n * Work a revoked principal's call left behind once it resolves is stopped\n * there and then. Stopping is per session, not per run: a session another\n * token also drives has its run in flight interrupted and its whole queue\n * dropped, whichever token started that run or queued those messages (the\n * host does not say who started a run, and a leaked token's run must not\n * survive because another device steered it). Peers without a principal (the unix socket, an auth-less\n * loopback server) record nothing. A deleted session's id stays until its\n * token is revoked or the host restarts: nothing runs there, so `stop`\n * passes over it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostPeer } from './peers'\n\n/** Methods that drive a session's agent: `params.sessionId` names the session. */\nconst DRIVING: ReadonlySet<string> = new Set([\n 'chat.send',\n 'chat.pushQueued',\n 'chat.steer',\n 'chat.followUp',\n 'queue.add',\n 'queue.pushNow',\n 'orchestration.send',\n 'orchestration.steer',\n])\n\n/** What `stop` ended: sessions whose run or background work it stopped, terminals it closed. */\nexport interface StoppedWork {\n runs: number\n terminals: number\n}\n\nexport interface PrincipalWork {\n /** Run `peer`'s call of `method`, noting the session it drives (before the call) or the terminal it opened (after). Returns the call's result. */\n track: (method: string, params: unknown, peer: HostPeer, call: () => unknown) => Promise<unknown>\n /** Drop the queued messages, interrupt the runs, cancel the background work and close the terminals `principal` started, then forget it. */\n stop: (principal: string) => Promise<StoppedWork>\n}\n\ntype WorkHost = Pick<ChatHost, 'isSessionRunning' | 'interrupt' | 'listRunningWork' | 'cancelRunningWork' | 'queueList' | 'queueRemove' | 'terminals'>\n\nexport function createPrincipalWork(host: WorkHost): PrincipalWork {\n const sessions = new Map<string, Set<string>>()\n const terminals = new Map<string, Set<string>>()\n /** Principals already stopped: a call of theirs still in flight is stopped when it resolves. */\n const revoked = new Set<string>()\n\n const add = (map: Map<string, Set<string>>, principal: string, id: string): void => {\n let ids = map.get(principal)\n if (!ids)\n map.set(principal, ids = new Set())\n ids.add(id)\n }\n\n const forgetTerminal = (terminalId: string): void => {\n for (const ids of terminals.values())\n ids.delete(terminalId)\n }\n\n /**\n * Drop the session's queue first: an interrupted run's end drains it, and\n * the next entry would start a fresh run. The whole queue goes, whoever\n * queued each entry: the wire does not say which entries a principal added.\n * Likewise the run in flight is interrupted whoever started it.\n * Returns whether a run, queued messages or background work were stopped.\n */\n const stopSession = async (sessionId: string): Promise<boolean> => {\n const queued = host.queueList(sessionId)\n for (const item of queued)\n host.queueRemove(sessionId, item.id)\n const running = host.isSessionRunning(sessionId)\n const background = host.listRunningWork(sessionId).length > 0\n if (running)\n host.interrupt(sessionId)\n if (background)\n await host.cancelRunningWork(sessionId, 'all', 'The token that started it was revoked.').catch(() => false)\n return running || background || queued.length > 0\n }\n\n const closeTerminal = async (terminalId: string): Promise<boolean> => {\n try {\n await host.terminals.close(terminalId)\n return true\n }\n catch {\n // Already gone, or its shell would not die: the others still close.\n return false\n }\n }\n\n /** Before the call: a revocation landing while it runs (a `chat.send` still provisioning) finds the session. */\n const claim = (method: string, params: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n const sessionId = (params as { sessionId?: unknown } | null)?.sessionId\n if (principal !== undefined && !revoked.has(principal) && DRIVING.has(method) && typeof sessionId === 'string')\n add(sessions, principal, sessionId)\n }\n\n /** After the call succeeded; a principal revoked meanwhile has what it left behind stopped now. */\n const record = (method: string, params: unknown, result: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n if (principal === undefined)\n return\n const p = (params ?? {}) as { sessionId?: unknown, terminalId?: unknown }\n const opened = (result as { id?: unknown } | null)?.id\n const late = revoked.has(principal)\n if (DRIVING.has(method) && typeof p.sessionId === 'string') {\n if (late)\n void stopSession(p.sessionId).catch(() => false)\n else\n add(sessions, principal, p.sessionId)\n }\n else if (method === 'orchestration.createWorker' && typeof result === 'string') {\n if (late)\n void stopSession(result).catch(() => false)\n else\n add(sessions, principal, result)\n }\n else if (method === 'terminal.open' && typeof opened === 'string') {\n if (late)\n void closeTerminal(opened)\n else\n add(terminals, principal, opened)\n }\n else if (method === 'terminal.close' && typeof p.terminalId === 'string') {\n forgetTerminal(p.terminalId)\n }\n }\n\n return {\n async track(method, params, peer, call) {\n claim(method, params, peer)\n const result = await call()\n record(method, params, result, peer)\n return result\n },\n\n async stop(principal) {\n revoked.add(principal)\n const driven = sessions.get(principal) ?? new Set<string>()\n const opened = terminals.get(principal) ?? new Set<string>()\n sessions.delete(principal)\n terminals.delete(principal)\n let runs = 0\n for (const sessionId of driven) {\n if (await stopSession(sessionId))\n runs++\n }\n let closed = 0\n for (const terminalId of opened) {\n if (await closeTerminal(terminalId))\n closed++\n }\n return { runs, terminals: closed }\n },\n }\n}\n","/**\n * Per-session signal numbering and the bounded replay log behind\n * `sessions.resume`.\n *\n * Every session-scoped signal the host fans out to all peers gets the next\n * number of its session (from 1), and the last ones are kept as JSON, so a\n * client that dropped and reattached can be sent exactly what it missed\n * instead of reloading the whole transcript. Signals with no session, and\n * the origin-excluded or viewer-only ones that never go through the full\n * fan-out (drafts, search, suggestions, terminal output), are not numbered.\n *\n * Bounds: per session the last `maxSignals` signals and at most `maxBytes`\n * of them; across sessions `maxTotalBytes`, past which the least recently\n * written session loses its log. Sizes are UTF-8 bytes of the JSON plus\n * {@link ENTRY_OVERHEAD_BYTES} per entry. The bytes are the real bound: a\n * streamed reply is many small signals, and a count bound low enough to bind\n * first would cover less than the time a client needs to notice a dropped\n * connection and come back (`maxSignals` is only a backstop). A\n * position the log no longer covers (or that is not a non-negative integer)\n * is a gap: the client falls back to `sessions.loadEvents`.\n *\n * Numbering survives eviction and `forget`, so a stale position can never\n * pass for a fresh one. A forgotten or evicted session keeps only its next number, in\n * a map bounded by `maxForgotten` (least recently forgotten go first); an\n * evicted counter raises a floor every new log starts from, so a number is\n * never given out twice in one epoch, at the cost of new sessions'\n * numbering not starting at 1 once that happened.\n *\n * `epoch` names this log: numbers mean nothing to another host process.\n */\nimport type { HostSignal, SequencedSignal } from '../protocol'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n/** What one kept entry costs beyond its JSON (the entry object, its slot), counted against the byte bounds. */\nexport const ENTRY_OVERHEAD_BYTES = 64\n\nexport interface SignalLogOptions {\n /** Default 100 000: past the byte bounds for any realistic signal size. */\n maxSignals?: number\n /** Default 4 MiB. */\n maxBytes?: number\n /** Default 32 MiB. */\n maxTotalBytes?: number\n /** Forgotten sessions whose counters are kept. Default 10 000. */\n maxForgotten?: number\n}\n\nexport interface SignalLog {\n readonly epoch: string\n /**\n * The signal's number in its session, or `undefined` when it is not\n * session-scoped. `serialize` gives its JSON (`undefined`: it cannot be\n * encoded), so a caller that encodes it anyway does it once; default\n * `JSON.stringify`.\n */\n record: (signal: HostSignal, serialize?: () => string | undefined) => number | undefined\n /** Every signal of `sessionId` after `afterSeq`, in order; `null` when the log does not cover them all. */\n replay: (sessionId: string, afterSeq: number) => SequencedSignal[] | null\n /** The session is gone: drop its log (its numbering stays). */\n forget: (sessionId: string) => void\n /** Sessions tracked (live logs and forgotten counters): bounded by `maxForgotten` plus live sessions. */\n sessionCount: () => number\n}\n\ninterface Entry {\n seq: number\n json: string\n bytes: number\n}\n\ninterface SessionLog {\n /** Number the next signal gets. */\n next: number\n entries: Entry[]\n /** Index of the oldest kept entry. */\n head: number\n bytes: number\n}\n\nfunction stringify(signal: HostSignal): string | undefined {\n try {\n return JSON.stringify(signal)\n }\n catch {\n return undefined\n }\n}\n\nfunction sessionOf(signal: HostSignal): string | undefined {\n const id = (signal as { sessionId?: unknown }).sessionId\n return typeof id === 'string' ? id : undefined\n}\n\nexport function createSignalLog(options: SignalLogOptions = {}): SignalLog {\n const maxSignals = options.maxSignals ?? 100_000\n const maxBytes = options.maxBytes ?? 4 * 1024 * 1024\n const maxTotalBytes = options.maxTotalBytes ?? 32 * 1024 * 1024\n const maxForgotten = options.maxForgotten ?? 10_000\n const epoch = randomUUID()\n /** Insertion order = least recently written first. */\n const logs = new Map<string, SessionLog>()\n /**\n * Next number of forgotten sessions; insertion order = least recently\n * forgotten first. `evicted`: the log went to the total budget, not to\n * `forget`, and a client already at its end still has nothing to miss.\n */\n const forgotten = new Map<string, { next: number, evicted: boolean }>()\n /** Every number below this may have been given out by a session whose counter is gone. */\n let floor = 1\n let totalBytes = 0\n\n const dropOldest = (log: SessionLog): void => {\n totalBytes -= log.entries[log.head]!.bytes\n log.bytes -= log.entries[log.head]!.bytes\n log.head++\n if (log.head > 1024 && log.head * 2 > log.entries.length) {\n log.entries = log.entries.slice(log.head)\n log.head = 0\n }\n }\n\n const clear = (log: SessionLog): void => {\n totalBytes -= log.bytes\n log.entries = []\n log.head = 0\n log.bytes = 0\n }\n\n /** Drops the session's log, keeping only its next number. */\n const retire = (sessionId: string, log: SessionLog, evicted: boolean): void => {\n clear(log)\n logs.delete(sessionId)\n forgotten.set(sessionId, { next: log.next, evicted })\n while (forgotten.size > maxForgotten) {\n const [oldest, { next }] = forgotten.entries().next().value!\n forgotten.delete(oldest)\n floor = Math.max(floor, next)\n }\n }\n\n return {\n epoch,\n record(signal, serialize = () => stringify(signal)) {\n const sessionId = sessionOf(signal)\n if (sessionId === undefined)\n return undefined\n let log = logs.get(sessionId)\n if (log) {\n logs.delete(sessionId)\n }\n else {\n log = { next: forgotten.get(sessionId)?.next ?? floor, entries: [], head: 0, bytes: 0 }\n forgotten.delete(sessionId)\n }\n logs.set(sessionId, log)\n\n const seq = log.next++\n const json = serialize()\n if (json === undefined) {\n // Not JSON-able, so no peer can receive it either: a hole the log cannot replay.\n clear(log)\n return seq\n }\n const bytes = Buffer.byteLength(json) + ENTRY_OVERHEAD_BYTES\n log.entries.push({ seq, json, bytes })\n log.bytes += bytes\n totalBytes += bytes\n while (log.entries.length - log.head > maxSignals || (log.bytes > maxBytes && log.entries.length - log.head > 0))\n dropOldest(log)\n for (const [id, other] of logs) {\n if (totalBytes <= maxTotalBytes || id === sessionId)\n break\n retire(id, other, true)\n }\n return seq\n },\n replay(sessionId, afterSeq) {\n const log = logs.get(sessionId)\n if (!log) {\n const gone = forgotten.get(sessionId)\n return gone?.evicted && afterSeq === gone.next - 1 ? [] : null\n }\n if (!Number.isSafeInteger(afterSeq) || afterSeq < 0)\n return null\n const last = log.next - 1\n if (afterSeq > last || afterSeq < 0)\n return null\n if (afterSeq === last)\n return []\n const first = log.entries[log.head]?.seq\n if (first === undefined || first > afterSeq + 1)\n return null\n const out: SequencedSignal[] = []\n for (let i = log.head; i < log.entries.length; i++) {\n const entry = log.entries[i]!\n if (entry.seq > afterSeq)\n out.push({ seq: entry.seq, signal: JSON.parse(entry.json) as HostSignal })\n }\n return out\n },\n forget(sessionId) {\n const log = logs.get(sessionId)\n if (log) {\n retire(sessionId, log, false)\n return\n }\n const evicted = forgotten.get(sessionId)\n if (evicted) {\n forgotten.delete(sessionId)\n forgotten.set(sessionId, { next: evicted.next, evicted: false })\n }\n },\n sessionCount: () => logs.size + forgotten.size,\n }\n}\n","import type { WorkspaceConfinement } from '../../chat/workspace-confinement'\nimport type { FsDirEntry, FsDirListing, FsDirSearch, FsRoots } from '../protocol'\n/**\n * The folders a host lets sessions use, as `fs.*` lists them: the host's own\n * confinement (`ChatHost.workspace`, `src/chat/workspace-confinement.ts`,\n * which the host enforces at its entry points), plus the folder listing,\n * folder creation and folder search, each kept inside the roots. A\n * server is confined to its workspace roots; a local host is not, and its\n * listing root is the user's home, like the window's own folder picker.\n */\nimport { existsSync, mkdirSync, readdirSync, realpathSync, statSync } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { isInside } from '../../chat/workspace-confinement'\n\n/** Most folders one listing returns. */\nconst MAX_DIR_ENTRIES = 2000\n\n/** How deep a folder search goes below where it starts. */\nexport const SEARCH_MAX_DEPTH = 4\n/** Most folders one search returns. */\nexport const SEARCH_MAX_RESULTS = 200\n/** Most folders one search reads, so a huge tree answers in bounded time. */\nconst SEARCH_MAX_READS = 5000\n/** Folders a search never enters: dependency trees, not projects. */\nconst SEARCH_SKIP = new Set(['node_modules'])\n\n/** A folder name a client may create: one path segment, not hidden, no control characters. */\nfunction checkFolderName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed)\n throw new Error('A folder name is required.')\n if (trimmed.length > 255)\n throw new Error('That folder name is too long.')\n // eslint-disable-next-line no-control-regex -- refusing control characters is the point\n if (/[/\\\\\\u0000-\\u001F]/.test(trimmed))\n throw new Error('A folder name cannot hold \"/\", \"\\\\\" or control characters.')\n if (trimmed.startsWith('.'))\n throw new Error('A folder name cannot start with a dot.')\n return trimmed\n}\n\n/** Exact name first, then a name that starts with the query, then the rest; shallow before deep. */\nfunction searchRank(entry: FsDirEntry, query: string, depth: number): number {\n const name = entry.name.toLowerCase()\n const kind = name === query ? 0 : name.startsWith(query) ? 1 : 2\n return kind * 100 + depth\n}\n\nexport interface WorkspaceRoots {\n describe: () => FsRoots\n /** The real path of `path` when it is a folder inside the roots; throws otherwise. */\n resolveFolder: (path: string) => string\n /** A new session's folder: `cwd` checked when confined, the first root when confined and empty. */\n sessionFolder: (cwd: string) => string\n /** A folder a running session moves to (`setFolder`, launch override): checked when confined; `''` passes. */\n checkFolder: (cwd: string) => string\n list: (path?: string) => FsDirListing\n /** Creates folder `name` in `parent` (inside the roots); throws when it exists or the name is not one plain segment. */\n mkdir: (parent: string, name: string) => FsDirEntry\n /** The folders whose name holds `query`, in `path` (default: every root) and below, within the search bounds. */\n search: (query: string, path?: string) => Promise<FsDirSearch>\n}\n\nexport function createWorkspaceRoots(confinement: WorkspaceConfinement): WorkspaceRoots {\n const { confined, roots, resolveFolder } = confinement\n return {\n describe: () => ({ roots: [...roots], confined }),\n resolveFolder,\n checkFolder: confinement.checkFolder,\n sessionFolder: confinement.sessionFolder,\n list(path) {\n const dir = resolveFolder(path ?? roots[0]!)\n const entries: FsDirEntry[] = []\n let truncated = false\n const names = readdirSync(dir, { withFileTypes: true })\n .filter(e => !e.name.startsWith('.') && (e.isDirectory() || e.isSymbolicLink()))\n .map(e => e.name)\n .sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n let real: string\n try {\n // Canonical, as the confinement's roots are (`../../chat/workspace-confinement`).\n real = realpathSync.native(join(dir, name))\n if (!statSync(real).isDirectory())\n continue\n }\n catch {\n continue\n }\n // A symlink out of the roots is not offered (it would be refused anyway).\n if (!roots.some(root => isInside(root, real)))\n continue\n if (entries.length >= MAX_DIR_ENTRIES) {\n truncated = true\n break\n }\n entries.push({ name, path: real, isGitRepo: existsSync(join(real, '.git')) })\n }\n const atRoot = roots.includes(dir)\n return { roots: [...roots], path: dir, parent: atRoot ? null : dirname(dir), entries, ...(truncated ? { truncated } : {}) }\n },\n mkdir(parent, name) {\n const dir = resolveFolder(parent)\n const folder = checkFolderName(name)\n const target = join(dir, folder)\n try {\n mkdirSync(target)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST')\n throw new Error(`${folder} already exists in ${dir}.`)\n throw err\n }\n return { name: folder, path: realpathSync.native(target), isGitRepo: false }\n },\n async search(query, path) {\n const needle = query.trim().toLowerCase()\n if (!needle)\n return { results: [] }\n const starts = path === undefined ? [...roots] : [resolveFolder(path)]\n const found: { entry: FsDirEntry, depth: number }[] = []\n const seen = new Set<string>()\n let reads = 0\n let truncated = false\n // Breadth first: a shallow match is found before the bounds cut a deep one.\n let level = starts.map(dir => ({ dir, depth: 0 }))\n while (level.length > 0) {\n const next: typeof level = []\n for (const { dir, depth } of level) {\n if (reads >= SEARCH_MAX_READS) {\n truncated = true\n break\n }\n reads++\n let dirents\n try {\n dirents = await readdir(dir, { withFileTypes: true })\n }\n catch {\n continue\n }\n // Symlinks are not followed: no loops, no way out of the roots.\n for (const dirent of dirents) {\n if (!dirent.isDirectory() || dirent.name.startsWith('.') || SEARCH_SKIP.has(dirent.name))\n continue\n const child = join(dir, dirent.name)\n if (seen.has(child))\n continue\n seen.add(child)\n if (dirent.name.toLowerCase().includes(needle))\n found.push({ entry: { name: dirent.name, path: child, isGitRepo: existsSync(join(child, '.git')) }, depth })\n if (depth + 1 < SEARCH_MAX_DEPTH)\n next.push({ dir: child, depth: depth + 1 })\n }\n }\n if (reads >= SEARCH_MAX_READS) {\n if (next.length > 0)\n truncated = true\n break\n }\n level = next\n }\n found.sort((a, b) => searchRank(a.entry, needle, a.depth) - searchRank(b.entry, needle, b.depth) || a.entry.path.localeCompare(b.entry.path))\n if (found.length > SEARCH_MAX_RESULTS)\n truncated = true\n const results = found.slice(0, SEARCH_MAX_RESULTS).map(f => f.entry)\n return { results, ...(truncated ? { truncated } : {}) }\n },\n }\n}\n","/**\n * Transport-free JSON-RPC dispatch around a `ChatHost`.\n *\n * Owns everything a host connection needs that is NOT the wire: the typed\n * method table, per-peer state (presence, terminal views, browser hosts,\n * terminal viewers), signal fan-out, the shared draft / search / suggest\n * state, and the `ipc.hello` handshake. A transport (the unix-socket server\n * in `server.ts`, the WebSocket server in `../transports/ws-server.ts`, the\n * in-memory one in `../memory.ts`) only frames messages and hands each\n * connection over as a {@link HostPeer} whose `send` delivers signals.\n *\n * Lifecycle that belongs to the process (draining, retiring once idle) stays\n * with the transport and reaches in through {@link DispatcherLifecycle}.\n *\n * This module is the composition root: peers and fan-out live in\n * `./peers`, each feature's methods (and the per-session or per-peer state\n * only they touch) in `./handlers/<feature>`.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { RingBufferSink } from '../../logger'\nimport type { HelloParams, HelloResult, HostKind, HostSignal, IpcMethodName } from '../protocol'\nimport type { ClientScope } from '../scopes'\nimport type { DaemonEnvironment } from './environment'\nimport type { RemoteInstallsOptions } from './handlers/catalog-install'\nimport type { MediaTicketRegistry } from './handlers/files'\nimport type { HistoryHandlers } from './handlers/history'\nimport type { MachineLinksHandlerOptions } from './handlers/machine-links'\nimport type { MachineServeOptions } from './handlers/machine-serve'\nimport type { ServerTokensControl, ServerUpdateControl } from './handlers/server'\nimport type { SyncOptions } from './handlers/sync'\nimport type { MethodTable } from './handlers/types'\nimport type { HostIdentityOptions } from './identity'\nimport type { HostPeer } from './peers'\nimport type { StoppedWork } from './principal-work'\nimport type { SignalLogOptions } from './signal-log'\nimport { realpathSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { AcpErrorCode } from '../../acp/types'\nimport { createChatHost } from '../../chat/host/engine'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { createMcpStatusTracker } from '../../chat/mcp-status'\nimport { SYNC_CATEGORIES } from '../../chat/sync/types'\nimport { ZIDANE_VERSION } from '../../version'\nimport { createHostTranscriptPager } from '../history/index'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION, IpcErrorCode, MachineErrorCode, PING_METHOD } from '../protocol'\nimport { METHOD_SCOPES, methodScope, scopeAllows } from '../scopes'\nimport { createDaemonEnvironment } from './environment'\nimport { createArtifactHandlers } from './handlers/artifacts'\nimport { createAuthHandlers, createProviderAuth } from './handlers/auth'\nimport { withBlockRunHandlers } from './handlers/block-runs'\nimport { createBrowserHandlers } from './handlers/browser'\nimport { createCatalogInstallHandlers, remoteInstallsAllowed } from './handlers/catalog-install'\nimport { createCatalogHandlers } from './handlers/catalogs'\nimport { createChatHandlers } from './handlers/chat'\nimport { createClientStateHandlers } from './handlers/client-state'\nimport { createContextHandlers } from './handlers/context'\nimport { createDaemonHandlers } from './handlers/daemon'\nimport { createDraftHandlers } from './handlers/drafts'\nimport { createEnvironmentHandlers } from './handlers/environments'\nimport { createExtensionUiHandlers } from './handlers/extension-ui'\nimport { createFilesHandlers } from './handlers/files'\nimport { createFsHandlers } from './handlers/fs'\nimport { createGitHandlers } from './handlers/git'\nimport { createHistoryHandlers } from './handlers/history'\nimport { createHitlHandlers } from './handlers/hitl'\nimport { createLaunchOverrideHandlers } from './handlers/launch-overrides'\nimport { createMachineLinkHandlers } from './handlers/machine-links'\nimport { createMachineServeHandlers } from './handlers/machine-serve'\nimport { createMachineHandlers } from './handlers/machines'\nimport { createOAuthFlowHandlers } from './handlers/oauth-flows'\nimport { createOnboardingHandlers } from './handlers/onboarding'\nimport { createOrchestrationHandlers } from './handlers/orchestration'\nimport { createPanelHandlers } from './handlers/panels'\nimport { checkParams, InvalidParamsError } from './handlers/params'\nimport { createPerfHandlers, lazyHostPerf } from './handlers/perf'\nimport { createPresenceHandlers } from './handlers/presence'\nimport { createQueueHandlers } from './handlers/queue'\nimport { createResumeHandlers } from './handlers/resume'\nimport { createServerHandlers } from './handlers/server'\nimport { createSessionReadHandlers } from './handlers/session-reads'\nimport { createSessionHandlers } from './handlers/sessions'\nimport { createSettingsHandlers } from './handlers/settings'\nimport { createSuggestHandlers } from './handlers/suggest'\nimport { createSyncHandlers, withSyncOverrides } from './handlers/sync'\nimport { createTerminalHandlers } from './handlers/terminal'\nimport { createTitleHandlers } from './handlers/titles'\nimport { createTodoHandlers } from './handlers/todos'\nimport { createTranscriptHandlers } from './handlers/transcript'\nimport { createUsageHandlers } from './handlers/usage'\nimport { createWorkspaceHandlers } from './handlers/workspace'\nimport { createWorkspaceExecStreamHandlers } from './handlers/workspace-exec-stream'\nimport { evaluateHello } from './handshake'\nimport { resolveHostIdentity } from './identity'\nimport { IPC_BUILD_ID } from './lifecycle'\nimport { createPeerRegistry } from './peers'\nimport { createPrincipalWork } from './principal-work'\nimport { sendDedupFor } from './send-requests'\nimport { createSignalLog } from './signal-log'\nimport { createWorkspaceRoots } from './workspace-roots'\n\n/** Codes a machine error keeps over the wire (`MachineErrorCode`). */\nconst MACHINE_ERROR_CODES: ReadonlySet<number> = new Set(Object.values(MachineErrorCode))\n/** Terminals without a session: only hosts that advertise `HelloResult.projectTerminals` answer them. */\nconst PROJECT_TERMINAL_METHODS: ReadonlySet<string> = new Set(['terminal.projectState', 'terminal.openInProject', 'terminal.adopt', 'terminal.releaseDraft'])\n\nexport type { HostPeer } from './peers'\n\n/** Process lifecycle the transport owns; the dispatcher only asks for it. */\nexport interface DispatcherLifecycle {\n /** `daemon.shutdown`: drain and exit once the reply is out. */\n shutdown: () => void\n /** A newer client found this host mid-work: keep serving, exit at the first idle point. */\n retireWhenIdle: () => void\n isRetiring: () => boolean\n}\n\nexport interface HostDispatcherOptions {\n /**\n * Environment factory: the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n appVersion: string\n startedAt: number\n lifecycle: DispatcherLifecycle\n /**\n * What this host reports itself as in `ipc.hello` / `daemon.info`; the id\n * comes from the environment's data dir. Default: a `daemon` named after\n * the machine.\n */\n identity?: HostIdentityOptions\n /** Bounds of the per-session replay log `sessions.resume` reads (`./signal-log`). */\n replay?: SignalLogOptions\n /**\n * Lend this host as a machine to its clients' hosts (`machine.attach`,\n * `docs/MACHINES.md` § Reverse direction). A zidane-server's\n * `allowAsMachine`; absent: refused.\n */\n machineServe?: MachineServeOptions\n /** Its token store, for clients (`tokens.*`): a zidane-server's. Absent: refused. */\n tokens?: ServerTokensControl\n /** The tickets its media are served under (`files.mediaTicket`): a zidane-server's. Absent: refused. */\n media?: MediaTicketRegistry\n /** A zidane-server's self-update (`server.update.*`); read per call, set once it started. */\n update?: () => ServerUpdateControl | null\n /** Pacing of this host's machine links (tests shrink it). */\n machineLinks?: MachineLinksHandlerOptions['pacing']\n /** How long an `auth.oauth.*` sign-in waits for its code. Default 10 minutes. */\n oauthFlowTtlMs?: number\n /** It serves `SERVER_OAUTH_CALLBACK_PATH` (a zidane-server, `deliverOAuthCallback`): a browser client's MCP sign-in may come back there. */\n oauthCallback?: boolean\n /** Its log buffer, for clients (`logs.*`): a zidane-server's. Absent: refused. */\n logs?: RingBufferSink\n /**\n * Installs and removals from clients (`catalog.install` / `remove` /\n * `update`, `mcp.upsert` / `remove`): a zidane-server's `allowRemoteInstalls`\n * and its audit log. Absent: refused.\n */\n remoteInstalls?: RemoteInstallsOptions\n /**\n * Settings sync from a client's computer (`sync.*`): a zidane-server's\n * sync record and audit. Absent: refused.\n */\n sync?: SyncOptions\n /**\n * Workspace writes from clients: cloning (`git.clone`) and creating\n * folders (`fs.mkdir`) in the workspace roots. A zidane-server's\n * `allowClone` and `allowCreateFolders`. Absent: both allowed (the user's\n * own computer).\n */\n workspaceWrites?: WorkspaceWritesOptions\n /**\n * A call refused because the connection's token doesn't reach the method\n * (`../scopes`): a zidane-server writes it to its audit log.\n */\n onForbidden?: (peer: HostPeer, method: string, required: ClientScope) => void\n /**\n * Leave resuming the runs a dead process left to {@link HostDispatcher.resumeAfterRestart}:\n * a host that starts channels calls it once they are connected, so a\n * resumed run's events reach their conversation. Absent: resumed at once.\n */\n deferResume?: boolean\n}\n\n/** Which workspace writes a host takes from its clients, read per call. */\nexport interface WorkspaceWritesOptions {\n /** `git.clone`. */\n clone: () => boolean\n /** `fs.mkdir`. */\n createFolders: () => boolean\n}\n\n/** The workspace writes a host takes, read per call; both allowed without options (the user's own computer). */\nfunction workspaceWritesOf(options: WorkspaceWritesOptions | undefined) {\n const clone = (): boolean => options?.clone() ?? true\n const createFolders = (): boolean => options?.createFolders() ?? true\n return { clone, createFolders, flags: () => ({ clone: clone(), createFolders: createFolders() }) }\n}\n\n/** The home folder as the paths under it are stored: resolved (a symlinked home, `/var` → `/private/var`). */\nfunction homeFolder(): string {\n try {\n return realpathSync(homedir())\n }\n catch {\n return homedir()\n }\n}\n\n/** What the hello says this host offers its clients. */\nfunction hostOffers(options: HostDispatcherOptions, machineServe: boolean, writes: { clone: boolean, createFolders: boolean }): Partial<HelloResult> {\n return {\n ...(machineServe ? { machineServe: true } : {}),\n ...(remoteInstallsAllowed(options.remoteInstalls) ? { remoteInstalls: true } : {}),\n ...writes,\n ...(options.sync ? { sync: true, syncCategories: [...SYNC_CATEGORIES] } : {}),\n }\n}\n\n/** A request's outcome, ready for the transport to frame as a JSON-RPC response. */\nexport type DispatchOutcome\n = | { ok: true, result: unknown }\n | { ok: false, code: number, message: string, data?: unknown }\n\nexport interface HostDispatcher {\n host: ChatHost\n addPeer: (peer: HostPeer) => void\n /** The peer's connection ended: release what it registered and refresh presence. */\n removePeer: (peer: HostPeer) => void\n /** Forget every peer WITHOUT per-peer cleanup, and stop watching the settings file (the host is shutting down). */\n detachAll: () => void\n peerCount: () => number\n handleRequest: (method: string, params: unknown, peer: HostPeer) => Promise<DispatchOutcome>\n /** Resume the runs a dead process left (a host serving every window); see `HostDispatcherOptions.deferResume`. Only the first call does anything. */\n resumeAfterRestart: () => void\n /** Fire-and-forget: no response, errors swallowed, ignored before the handshake. */\n handleNotification: (method: string, params: unknown, peer: HostPeer) => Promise<void>\n /**\n * A principal's credential was revoked (a zidane-server token): interrupt\n * the runs, cancel the background work and close the terminals its peers\n * started (`./principal-work`).\n */\n stopPrincipalWork: (principal: string) => Promise<StoppedWork>\n /** The browser came back to the server's OAuth callback with this query: the MCP server it signs in to, `undefined` when no sign-in waits for it. */\n deliverOAuthCallback: (query: URLSearchParams) => string | undefined\n}\n\n/**\n * The refusal of a call the peer's token doesn't reach (`../scopes`), reported to `onForbidden`;\n * `undefined` when it may call. A peer without a grant (a local window) reaches everything; a\n * method outside the protocol's scope table needs `admin` (never wider than the table says).\n */\nfunction forbiddenCall(method: string, peer: HostPeer, onForbidden: HostDispatcherOptions['onForbidden']): DispatchOutcome | undefined {\n if (!peer.grant)\n return undefined\n const required = methodScope(method) ?? 'admin'\n if (scopeAllows(peer.grant, required))\n return undefined\n onForbidden?.(peer, method, required)\n return {\n ok: false,\n code: IpcErrorCode.Forbidden,\n message: `\"${method}\" needs ${required === 'chat' ? 'a' : 'an'} ${required} token; this connection's token is ${peer.grant}.`,\n data: { required, granted: peer.grant },\n }\n}\n\n/**\n * A connection's terms, set on the peer and reported by `ipc.hello`: the protocol version it\n * speaks, its token's scope (absent for a local window) and the methods this host handles\n * within it.\n */\nfunction connectionTerms(peer: HostPeer, negotiated: number, handled: (method: string) => boolean): Pick<HelloResult, 'minProtocolVersion' | 'negotiatedProtocolVersion' | 'scope' | 'methods'> {\n peer.protocolVersion = negotiated\n const methods = (Object.keys(METHOD_SCOPES) as IpcMethodName[])\n .filter(method => handled(method) && (!peer.grant || scopeAllows(peer.grant, METHOD_SCOPES[method])))\n return { minProtocolVersion: IPC_MIN_PROTOCOL_VERSION, negotiatedProtocolVersion: negotiated, ...(peer.grant ? { scope: peer.grant } : {}), methods }\n}\n\n/** Where this module (and, bundled, its sibling chunks) lives. */\nconst OWN_DIR = dirname(fileURLToPath(import.meta.url))\n\n/**\n * A lazy import of this process's own code failed: the files it was started\n * from were replaced on disk (a rebuild, an upgrade) while it ran.\n */\nexport function isReplacedBuildError(err: unknown): boolean {\n const message = err instanceof Error ? err.message : ''\n const missing = /^Cannot find module '([^']+)'/.exec(message)?.[1]\n // A relative chunk (Bun) or a file next to this one (Node resolves the path); a package an extension lacks is not ours.\n return missing !== undefined && (/^\\.{1,2}\\//.test(missing) || missing.startsWith(`${OWN_DIR}/`))\n}\n\nexport const REPLACED_BUILD_MESSAGE = 'zidane was rebuilt or upgraded while its background service ran. The service restarts once no run is active. To restart it now, quit zidane everywhere and reopen it.'\n\n/** A handler's throw, as the outcome its caller gets. */\nfunction failureOutcome(err: unknown, lifecycle: DispatcherLifecycle): DispatchOutcome {\n // Its own code is gone from disk: say so, and hand over to a fresh process at the first idle point.\n if (isReplacedBuildError(err)) {\n lifecycle.retireWhenIdle()\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: REPLACED_BUILD_MESSAGE }\n }\n if (err instanceof InvalidParamsError)\n return { ok: false, code: AcpErrorCode.InvalidParams, message: err.message }\n // A machine error keeps its code: a client tells \"busy, retry\" from \"refused\" by it.\n const code = (err as { code?: unknown } | null)?.code\n if (typeof code === 'number' && MACHINE_ERROR_CODES.has(code))\n return { ok: false, code, message: (err as Error).message }\n // A handler's own scope refusal (`PolicyScopeError`) answers like the dispatcher's: Forbidden, with what it needs.\n // A typed failure (`ExtensionInstallFailedError`) keeps its `data` too.\n if (code === IpcErrorCode.Forbidden || code === IpcErrorCode.HandlerFailed) {\n const data = (err as { data?: unknown }).data\n return { ok: false, code, message: (err as Error).message, ...(data !== undefined ? { data } : {}) }\n }\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: err instanceof Error ? err.message : String(err) }\n}\n\n/**\n * What a previous process left pending: approvals, and (for a host serving\n * every window) every session's durable runs a dead process left. An\n * in-process host resumes those per session, when a window opens it.\n */\nfunction recoverAfterRestart(host: ChatHost, kind: HostKind, deferResume: boolean): () => void {\n host.approvals.rehydrate()\n let resumed = kind === 'in-process'\n const resume = (): void => {\n if (resumed)\n return\n resumed = true\n void host.resumePending().catch(() => undefined)\n }\n if (!deferResume)\n resume()\n return resume\n}\n\nexport async function createHostDispatcher(options: HostDispatcherOptions): Promise<HostDispatcher> {\n const { appVersion, startedAt, lifecycle } = options\n\n const signalLog = createSignalLog(options.replay)\n // Paged transcripts, off this thread when the store is a SQLite file (the worker ends with the host).\n const transcripts = createHostTranscriptPager()\n let historySearch: HistoryHandlers | undefined\n // Every numbered signal passes here: the ones following a session change drop its cached replay and search index.\n const peers = createPeerRegistry({ sequence: (signal, json) => {\n transcripts.observe(signal)\n historySearch?.observe(signal)\n return signalLog.record(signal, json)\n } })\n peers.onClear(transcripts.close)\n const { broadcast, broadcastExcept } = peers\n\n const env = await (options.createEnvironment\n ? options.createEnvironment(broadcast)\n : createDaemonEnvironment({ broadcast }))\n // Resolved first: the host stamps its id on `ctx.sessions.list` rows.\n const identity = resolveHostIdentity(env.userDataDir(), options.identity ?? { kind: 'daemon' })\n const host = createChatHost(identity.id ? { ...env, hostId: identity.id } : env)\n peers.bindHost(host)\n // Live extension reloads wait for the runs of the sessions reading that folder's extensions.\n env.gateExtensionReloads?.(cwd => host.hasActiveRunsIn(cwd))\n\n const store = env.store\n historySearch = createHistoryHandlers({ host, store, onClose: peers.onClear })\n // With the home folder: clients show it as `~` in the paths they display.\n const identityFields = { ...(identity.id ? { hostId: identity.id } : {}), hostKind: identity.kind, hostName: identity.name, homeDir: homeFolder() }\n\n // The host's own confinement (it checks it at its entry points); `fs.*` lists with it.\n const workspace = createWorkspaceRoots(host.workspace)\n const drafts = createDraftHandlers({ broadcastExcept })\n const suggest = createSuggestHandlers({ env, broadcastExcept })\n const launchOverrides = createLaunchOverrideHandlers({ host })\n const browser = createBrowserHandlers({ host })\n const terminal = createTerminalHandlers({ host, isConnected: peers.has })\n // Terminals without a session are This computer's (v1): a server answers their methods \"unknown\".\n const projectTerminals = identity.kind !== 'server'\n // Commands streamed to a client: a workspace exec, and a reply's block run here.\n const execStreams = withBlockRunHandlers(createWorkspaceExecStreamHandlers({ host, isConnected: peers.has }), { host, isConnected: peers.has })\n const auth = createProviderAuth({ host, env })\n const mcpStatus = createMcpStatusTracker({ dataDir: () => env.userDataDir(), store: () => env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()), onChange: () => broadcast({ kind: 'catalog:changed', catalog: 'mcps' }), onCredentialsChanged: name => host.mcpServers.retire(name) })\n const oauth = createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected: peers.has, serverCallback: options.oauthCallback === true, ...(options.oauthFlowTtlMs !== undefined ? { ttlMs: options.oauthFlowTtlMs } : {}) })\n const settings = createSettingsHandlers({ host, env, broadcast, onClose: peers.onClear })\n const installs = createCatalogInstallHandlers({ host, env, broadcast, setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer), ...(options.remoteInstalls ? { options: options.remoteInstalls } : {}) })\n const authHandlers = createAuthHandlers({ auth })\n const sync = createSyncHandlers({\n host,\n env,\n broadcast,\n auth,\n setters: {\n setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer) as unknown as Record<string, unknown>,\n install: (p, peer) => installs['catalog.install'](p, peer),\n mcpUpsert: (p, peer) => installs['mcp.upsert'](p, peer),\n mcpRemove: (p, peer) => installs['mcp.remove'](p, peer),\n setApiKey: p => authHandlers['auth.setApiKey'](p, null as unknown as HostPeer),\n },\n ...(options.sync ? { options: options.sync } : {}),\n })\n const { markOverrides, ...syncMethods } = sync\n const principalWork = createPrincipalWork(host)\n const writes = workspaceWritesOf(options.workspaceWrites)\n const machineServe = createMachineServeHandlers({ host, dataDir: () => env.userDataDir(), hostName: identity.name, settings: () => env.readSettings(), isConnected: peers.has, ...(options.machineServe ? { options: options.machineServe } : {}) })\n\n // Peer-close cleanup, in this order: browser hosts, terminal viewers and views, launch overrides, a lent machine.\n for (const release of [browser.releasePeer, terminal.releasePeer, launchOverrides.releasePeer, machineServe.releasePeer, execStreams.releasePeer, oauth.releasePeer])\n peers.onClose(release)\n\n const forgetSession = (sessionId: string): void => {\n // `historySearch` is set before any session can be deleted.\n for (const forget of [drafts.forget, launchOverrides.forget, suggest.forget, signalLog.forget, transcripts.forget, historySearch!.forget])\n forget(sessionId)\n }\n\n /*\n * Exhaustive by `satisfies`: every `IpcMethodName` MUST have a handler\n * (compile error otherwise), each pinned to its `IpcMethods` signature\n * by the slice it comes from (see `./handlers/types`).\n */\n const methods = {\n ...createChatHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store), transforms: host.transformPrompt }),\n ...createQueueHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store), transforms: host.transformPrompt }),\n ...drafts.methods,\n ...suggest.methods,\n ...launchOverrides.methods,\n ...createSessionHandlers({ host, store, broadcast, forgetSession, hostId: identity.id, workspace }),\n ...createTitleHandlers({ host, broadcast }),\n ...createSessionReadHandlers({ host, store, snapshots: transcripts.replays }),\n ...createTranscriptHandlers({ host, store, broadcast, pages: transcripts }),\n ...createResumeHandlers({ log: signalLog }),\n ...createContextHandlers({ host }),\n ...createEnvironmentHandlers({ host, env, setSettings: settings['settings.set'] }),\n ...createWorkspaceHandlers({ host }),\n ...execStreams.methods,\n ...createGitHandlers({ host, store, workspace, isConnected: peers.has, onClose: peers.onClose, clone: writes.clone }),\n ...createFilesHandlers({ workspace, onClose: peers.onClose, ...(options.media ? { media: options.media } : {}) }),\n ...createFsHandlers({ workspace, environments: () => host.listEnvironments('', undefined, { machineOnly: true }), createFolders: writes.createFolders, allows: () => ({ remoteInstalls: remoteInstallsAllowed(options.remoteInstalls), asMachine: machineServe.allowed(), sync: Boolean(options.sync), ...writes.flags() }) }),\n ...authHandlers,\n ...oauth.methods,\n ...installs,\n ...createCatalogHandlers({ env, host, mcpStatus }),\n ...createClientStateHandlers({ env }),\n ...createExtensionUiHandlers({ host, env, onClose: peers.onClose, broadcastExcept }),\n ...createPanelHandlers({ host, env, store, onClose: peers.onClose }),\n ...createOnboardingHandlers({ host, env, broadcast, ...(options.remoteInstalls ? { installs: options.remoteInstalls } : {}) }),\n ...createArtifactHandlers({ store, broadcast, env, host }),\n ...createUsageHandlers({ store, scan: transcripts.usage, dataDir: () => env.userDataDir(), providers: () => env.config.providers }),\n ...historySearch.methods,\n ...createTodoHandlers({ host, store }),\n ...createOrchestrationHandlers({ host }),\n ...createHitlHandlers({ host, store, userDataDir: () => env.userDataDir() }),\n ...browser.methods,\n ...terminal.methods,\n ...settings,\n ...createPresenceHandlers({ env, peers }),\n ...createMachineHandlers({ host, broadcast }),\n ...machineServe.methods,\n ...createMachineLinkHandlers({ host, env, broadcast, hostId: identity.id, server: identity.kind === 'server', appVersion, ...(options.machineLinks ? { pacing: options.machineLinks } : {}) }),\n ...createPerfHandlers({ perf: lazyHostPerf({ kind: identity.kind, host, store }), onPeerClose: peers.onClose, onShutdown: peers.onClear }),\n ...createServerHandlers({ broadcast, onClose: peers.onClear, onPeerClose: peers.onClose, ...(options.logs ? { logs: options.logs } : {}), ...(options.tokens ? { tokens: options.tokens } : {}), ...(options.update ? { update: options.update } : {}) }),\n ...createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity: identityFields }),\n ...syncMethods,\n // A window's edit of a field the sync source set makes it a server override.\n ...(options.sync\n ? withSyncOverrides({\n 'settings.set': settings['settings.set'],\n 'mcp.upsert': installs['mcp.upsert'],\n 'mcp.remove': installs['mcp.remove'],\n 'catalog.remove': installs['catalog.remove'],\n 'catalog.update': installs['catalog.update'],\n ...authHandlers,\n }, { readSettings: () => env.readSettings(), markOverrides })\n : {}),\n } satisfies MethodTable\n\n /**\n * Widened view for the string-keyed lookup: the table is typed exhaustively\n * above; unknown wire methods fall out here. Own keys only: a wire method\n * named `constructor` / `__proto__` / `toString` is unknown, not a call into\n * `Object.prototype`.\n */\n const handlerFor = (method: string): ((params: unknown, peer: HostPeer) => unknown) | undefined =>\n Object.hasOwn(methods, method) && (projectTerminals || !PROJECT_TERMINAL_METHODS.has(method))\n ? (methods as Partial<Record<string, (params: unknown, peer: HostPeer) => unknown>>)[method]\n : undefined\n\n function hello(params: Partial<HelloParams>, peer: HostPeer): DispatchOutcome {\n const verdict = evaluateHello(params, { buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, hasActiveWork: host.hasActiveWork(), hostKind: identity.kind })\n if (!verdict.accept) {\n return {\n ok: false,\n code: IpcErrorCode.VersionMismatch,\n message: verdict.message,\n data: { daemon: { protocolVersion: IPC_PROTOCOL_VERSION, appVersion, pid: process.pid, startedAt, buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, ...identityFields } },\n }\n }\n if (verdict.retire)\n lifecycle.retireWhenIdle()\n peer.ready = true\n const result: HelloResult = {\n protocolVersion: IPC_PROTOCOL_VERSION,\n ...connectionTerms(peer, verdict.protocolVersion, method => handlerFor(method) !== undefined),\n appVersion,\n pid: process.pid,\n startedAt,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n ...identityFields,\n signalEpoch: signalLog.epoch,\n ...(lifecycle.isRetiring() ? { retiring: true } : {}),\n ...hostOffers(options, machineServe.allowed(), writes.flags()),\n ...(projectTerminals ? { projectTerminals: true } : {}),\n }\n return { ok: true, result }\n }\n\n async function route(method: string, params: unknown, peer: HostPeer): Promise<DispatchOutcome> {\n // Transport liveness (`../transports/client-core` heartbeat): answered by any host, handshake or not.\n if (method === PING_METHOD)\n return { ok: true, result: {} }\n if (method === 'ipc.hello')\n return hello((params ?? {}) as Partial<HelloParams>, peer)\n\n /*\n * `daemon.shutdown` / `daemon.info` are allowed pre-handshake: a\n * client that just got a VERSION_MISMATCH on `ipc.hello` (so it\n * never became `ready`) still needs to drain this stale daemon\n * before respawning a matching one.\n */\n if (!peer.ready && method !== 'daemon.shutdown' && method !== 'daemon.info')\n return { ok: false, code: IpcErrorCode.NotHandshaken, message: 'Handshake required: send ipc.hello first.' }\n\n const forbidden = forbiddenCall(method, peer, options.onForbidden)\n if (forbidden)\n return forbidden\n\n const handler = handlerFor(method)\n if (!handler && method.startsWith('machine.'))\n return { ok: false, code: MachineErrorCode.MethodNotAllowed, message: `\"${method}\" needs a machine connection (a machine-scoped token); this is a client connection.` }\n if (!handler)\n return { ok: false, code: AcpErrorCode.MethodNotFound, message: `Unknown method \"${method}\".` }\n\n try {\n checkParams(params)\n return { ok: true, result: (await principalWork.track(method, params, peer, () => handler(params, peer))) ?? null }\n }\n catch (err) {\n return failureOutcome(err, lifecycle)\n }\n }\n\n return {\n host,\n addPeer: peers.add,\n removePeer: peers.remove,\n detachAll: peers.clear,\n peerCount: peers.size,\n // What the previous process left (synchronous: nothing above awaited since the host was built).\n resumeAfterRestart: recoverAfterRestart(host, identity.kind, options.deferResume === true),\n\n handleRequest(method, params, peer) {\n // The stream so far goes out first: a handler reads (and a reply follows) every delta emitted before it.\n peers.flush()\n return route(method, params, peer).finally(peers.flush)\n },\n\n /*\n * Notification fast path: fire-and-forget writes with no response\n * bookkeeping. Used for per-keystroke draft sync, where a\n * request/response round-trip per key would be pure overhead.\n * Routed through the SAME handler table as requests; errors are\n * swallowed (there is nowhere to send them) and pre-handshake\n * notifications are ignored.\n */\n async handleNotification(method, params, peer) {\n if (!peer.ready)\n return\n if (forbiddenCall(method, peer, options.onForbidden))\n return\n const handler = handlerFor(method)\n if (!handler)\n return\n try {\n checkParams(params)\n await principalWork.track(method, params, peer, () => handler(params, peer))\n }\n catch {\n // fire-and-forget by contract\n }\n },\n stopPrincipalWork: principalWork.stop,\n deliverOAuthCallback: oauth.deliverCallback,\n }\n}\n","/**\n * Restart the daemon once it is idle after a newer zidane landed on disk.\n *\n * The daemon outlives upgrades: windows restart onto the new build, the\n * daemon keeps running the old one. It watches its own package the same way\n * windows do (`watchInstalledVersion`: the applied marker every install\n * writes, plus a slow poll). Once a newer version is installed it marks\n * itself retiring (`ipc.hello` / `daemon.info` say so) and exits at the\n * first point where it is fully idle: no run, compaction, command or\n * background task, no live terminal, no pending approval or question. Two\n * idle polls in a row, since a queue drain is scheduled just after a\n * dispatch releases and one poll could land in that gap. Windows reconnect\n * on their own and spawn a daemon from the new build.\n *\n * Loop guard: before it exits it records `{ from, to }` in the cache dir. A\n * daemon that starts on `from` again while `to` is still the installed\n * version (the client that respawned it runs an older binary than the one on\n * PATH) does not retire for `to` a second time.\n */\nimport type { CompanionSpec } from '../../chat/auto-update-companion'\nimport type { InstalledVersionState, InstalledVersionWatcher, WatchInstalledVersionOptions } from '../../chat/auto-update-restart'\nimport type { ChatHost } from '../../chat/host/engine'\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { writeJsonFileAtomic } from '../../atomic-write'\nimport { watchInstalledVersion } from '../../chat/auto-update-restart'\n\n/** File name of the loop guard inside the cache directory. */\nexport const DAEMON_UPDATE_RESTART_FILE = 'daemon-update-restart.json'\n\n/** The last restart the daemon made for an update. */\nexport interface DaemonUpdateRestartRecord {\n /** Version the daemon ran when it exited. */\n from: string\n /** Installed version it exited for. */\n to: string\n /** ms since epoch. */\n at: number\n}\n\n/** Options for {@link watchDaemonUpdate}. */\nexport interface WatchDaemonUpdateOptions {\n /** The daemon's package, e.g. `{ packageName: 'zidane-tui', binName: 'zidane' }`. */\n spec: CompanionSpec\n /** Version the daemon runs. An empty string turns the watch off. */\n currentVersion: string\n /** Where the applied marker and the loop guard live. */\n cacheDir: string\n /** No runs, compactions, commands, background tasks, live terminals or pending prompts. */\n isIdle: () => boolean\n /** A newer version is installed: the daemon now waits for idle. Called once. */\n onPending?: (version: string) => void\n /** Fully idle with a newer version installed: exit now. Called once. */\n retire: () => void\n /** One diagnostic line per event. */\n log?: (line: string) => void\n /** Idle poll interval. Default 1 s. */\n idlePollMs?: number\n /** Installed-version poll interval, passed to the watcher. Default 5 min. */\n pollMs?: number\n /** Injected for tests. Defaults to {@link watchInstalledVersion}. */\n watch?: (options: WatchInstalledVersionOptions) => InstalledVersionWatcher\n /** Injected for tests. Defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Handle returned by {@link watchDaemonUpdate}. */\nexport interface DaemonUpdateWatch {\n /** The installed version the daemon waits to restart for, or `null`. */\n pending: () => string | null\n /** Stops watching and waiting. */\n close: () => void\n}\n\n/**\n * Nothing a restart would cut short: no run, compaction, command or\n * background task, no live terminal (`hasActiveWork`), and no approval or\n * question waiting for an answer.\n *\n * @param host - The daemon's chat host.\n */\nexport function daemonFullyIdle(host: Pick<ChatHost, 'hasActiveWork' | 'interactions'>): boolean {\n return !host.hasActiveWork() && host.interactions.list().length === 0\n}\n\n/**\n * Reads the loop guard. `null` when there is none or it does not parse.\n *\n * @param cacheDir - Directory that holds the record.\n */\nexport function readDaemonUpdateRestart(cacheDir: string): DaemonUpdateRestartRecord | null {\n try {\n const raw = JSON.parse(readFileSync(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), 'utf8')) as Partial<DaemonUpdateRestartRecord>\n if (typeof raw.from === 'string' && typeof raw.to === 'string' && typeof raw.at === 'number')\n return { from: raw.from, to: raw.to, at: raw.at }\n return null\n }\n catch {\n return null\n }\n}\n\nfunction writeDaemonUpdateRestart(cacheDir: string, record: DaemonUpdateRestartRecord): void {\n try {\n writeJsonFileAtomic(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), record, { ensureDir: true })\n }\n catch {\n // Without the guard a respawn on the old build may retire once more; never worse.\n }\n}\n\n/**\n * Watches for a newer install of the daemon's own package and calls `retire`\n * at the first fully idle point after one lands.\n *\n * @param options - Package, running version, idle probe and callbacks.\n */\nexport function watchDaemonUpdate(options: WatchDaemonUpdateOptions): DaemonUpdateWatch {\n const log = options.log ?? (() => undefined)\n const now = options.now ?? Date.now\n let pending: string | null = null\n let idleTimer: ReturnType<typeof setInterval> | undefined\n let closed = false\n let watcher: InstalledVersionWatcher | null = null\n\n const onState = (state: InstalledVersionState): void => {\n if (closed || pending || !state.restartRequired || !state.installed)\n return\n const guard = readDaemonUpdateRestart(options.cacheDir)\n if (guard && guard.from === options.currentVersion && guard.to === state.installed) {\n log(`[ipc-daemon] zidane ${state.installed} is installed, but a restart for it came back on ${options.currentVersion}; staying up`)\n return\n }\n pending = state.installed\n log(`[ipc-daemon] zidane ${pending} is installed; restarting once idle`)\n options.onPending?.(pending)\n let idlePolls = 0\n idleTimer = setInterval(() => {\n // Another install started meanwhile: wait for it, the disk is changing.\n if (!options.isIdle() || watcher?.current().installing) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(idleTimer)\n idleTimer = undefined\n writeDaemonUpdateRestart(options.cacheDir, { from: options.currentVersion, to: pending!, at: now() })\n log(`[ipc-daemon] idle; restarting for zidane ${pending}`)\n options.retire()\n }, options.idlePollMs ?? 1000)\n // Never keep the process alive for this.\n if (typeof idleTimer === 'object' && 'unref' in idleTimer)\n idleTimer.unref()\n }\n\n watcher = (options.watch ?? watchInstalledVersion)({\n spec: options.spec,\n currentVersion: options.currentVersion,\n cacheDir: options.cacheDir,\n ...(options.pollMs !== undefined ? { pollMs: options.pollMs } : {}),\n onChange: onState,\n })\n onState(watcher.current())\n\n return {\n pending: () => pending,\n close: () => {\n closed = true\n clearInterval(idleTimer)\n watcher?.close()\n },\n }\n}\n","/**\n * Unix-socket JSON-RPC server around a `ChatHost`.\n *\n * One `net.Server`, one JSON-RPC connection per peer (NDJSON framing: a\n * `net.Socket` is both the Readable and the Writable). The method table,\n * per-peer state, signal fan-out and the `ipc.hello` handshake live in the\n * transport-free dispatcher (`./dispatcher`); this module owns only what is\n * specific to the socket and the process: framing, the socket file and its\n * permissions, idle exit, retiring, and draining. Write backpressure (the\n * slow-consumer bound, the reply size) is shared with the WebSocket server\n * (`../transports/send-budget`).\n *\n * Handshake: a peer's first request MUST be `ipc.hello` carrying its\n * protocol version. Mismatched peers get a structured error (code\n * `IpcErrorCode.VersionMismatch`) and can ask the daemon to drain via `daemon.shutdown`\n * before respawning a fresh one.\n */\nimport type { Server, Socket } from 'node:net'\nimport type { JsonRpcConnection } from '../../acp/json-rpc'\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal } from '../protocol'\nimport type { HostDispatcher } from './dispatcher'\nimport type { DaemonEnvironment } from './environment'\nimport type { WatchDaemonUpdateOptions } from './update-retire'\nimport { chmodSync, existsSync, mkdirSync, unlinkSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { basename, dirname } from 'node:path'\nimport { createJsonRpcConnection } from '../../acp/json-rpc'\nimport { connectIpcClient } from '../client'\nimport { createPacedWriter } from '../transports/paced-writer'\nimport { createRpcPeer, dispatcherHandlers, PEER_WRITE_HIGH_WATERMARK } from '../transports/peer-rpc'\nimport { createPeerSend } from '../transports/send-budget'\nimport { createHostDispatcher } from './dispatcher'\nimport { legacySocketPath, probeSocket } from './lifecycle'\nimport { daemonFullyIdle, watchDaemonUpdate } from './update-retire'\n\n// Canonical home is the protocol module (clients import the codes without\n// pulling the server's module graph); re-exported here for compatibility.\nexport { IpcErrorCode } from '../protocol'\n\n/** Options for {@link startIpcDaemon}. */\nexport interface IpcDaemonOptions {\n /** Path of the unix socket to listen on. Its directory is created with mode 0700 and the socket gets mode 0600. */\n socketPath: string\n /**\n * Environment factory — the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /**\n * zidane version reported in the handshake.\n * @default 'dev'\n */\n appVersion?: string\n /**\n * Milliseconds the daemon may have zero peers and no running session before\n * it calls `onIdle`. Unset or 0: never. Ignored with a shared `dispatcher`.\n */\n idleShutdownMs?: number\n /** Called when the daemon has had no peers for `idleShutdownMs` and no session is active, or when it retires after a newer client attached mid-work. The CLI exits the process; embedded servers ignore it. */\n onIdle?: () => void\n /** Receives one diagnostic line per event, such as peers connecting. */\n onLog?: (line: string) => void\n /**\n * Serve this already-built host instead of creating one: another front-end\n * (zidane-server's WebSocket) serves it too. Its owner drains it and owns\n * its lifecycle, so `createEnvironment`, `appVersion` and the idle options\n * are ignored, and `close()` only closes this socket's connections.\n */\n dispatcher?: HostDispatcher\n /** See `HostDispatcherOptions.deferResume`: the caller calls `dispatcher.resumeAfterRestart()`. Ignored with a shared `dispatcher`. */\n deferResume?: boolean\n /**\n * A peer with more than this of signals queued for sending (it stopped\n * reading) is dropped; it re-attaches and resumes. Replies are bounded by\n * `maxMessageBytes` instead (`../transports/send-budget`). Default\n * `PEER_WRITE_HIGH_WATERMARK` (8 MiB).\n */\n maxBufferedBytes?: number\n /** A bigger reply goes out as an `IpcErrorCode.ResponseTooLarge` error. Default {@link SOCKET_MAX_REPLY_BYTES}. */\n maxMessageBytes?: number\n /**\n * Watch this package for a newer install and restart (close, then\n * `onIdle`) at the first fully idle point after one lands. Only for a\n * daemon run from an installed build. Ignored with a shared `dispatcher`.\n */\n updateWatch?: Pick<WatchDaemonUpdateOptions, 'spec' | 'currentVersion' | 'cacheDir' | 'pollMs' | 'idlePollMs' | 'watch'>\n}\n\n/**\n * Largest reply on the socket by default. Generous: the peer is this user's\n * own window on this machine, and whole-session reads (`sessions.get`) of a\n * long local session with images must keep fitting. The bound is there so\n * one reply cannot grow the write buffer without limit.\n */\nconst SOCKET_MAX_REPLY_BYTES = 256 * 1024 * 1024\n\n/** A running unix-socket daemon. */\nexport interface IpcDaemon {\n /** Path of the socket it listens on. */\n socketPath: string\n /** The chat host it serves. */\n host: ChatHost\n /** The dispatcher it serves, to connect an in-process client to it (`../memory` `connectInProcess`). */\n dispatcher: HostDispatcher\n /** Number of connected peers. */\n peerCount: () => number\n /** Drains the host, disconnects every peer and removes the socket file. Calling it again returns the same promise. With a shared `dispatcher`, the host is left to its owner. */\n close: () => Promise<void>\n}\n\n/** One open socket connection; `close()` ends them all. */\ninterface SocketConnection {\n socket: Socket\n connection: JsonRpcConnection\n}\n\n/**\n * Starts a unix-socket daemon around a chat host. Each peer must open with `ipc.hello`.\n * A stale socket file left by a dead daemon is replaced. Throws when a live daemon already listens on `socketPath`.\n * @param options - Socket path, environment and lifecycle settings.\n * @returns The running daemon.\n * @example\n * ```ts\n * import { startIpcDaemon } from 'zidane/ipc'\n *\n * const daemon = await startIpcDaemon({\n * socketPath: '/tmp/zidane-demo/daemon/ipc.sock',\n * onLog: line => console.log(line),\n * })\n * console.log(daemon.peerCount())\n * await daemon.close()\n * ```\n */\nexport async function startIpcDaemon(options: IpcDaemonOptions): Promise<IpcDaemon> {\n const { socketPath } = options\n const log = options.onLog ?? (() => undefined)\n const startedAt = Date.now()\n const appVersion = options.appVersion ?? 'dev'\n const maxBuffered = options.maxBufferedBytes ?? PEER_WRITE_HIGH_WATERMARK\n const maxMessage = options.maxMessageBytes ?? SOCKET_MAX_REPLY_BYTES\n\n const connections = new Set<SocketConnection>()\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n // See `retireWhenIdle`.\n let retiring = false\n /** A newer zidane is installed and `./update-retire` waits for full idle; separate so `retireWhenIdle` still arms. */\n let updatePending = false\n let retireTimer: ReturnType<typeof setInterval> | undefined\n\n const shared = options.dispatcher\n const dispatcher = shared ?? await createHostDispatcher({\n ...(options.createEnvironment ? { createEnvironment: options.createEnvironment } : {}),\n appVersion,\n startedAt,\n identity: { kind: 'daemon' },\n ...(options.deferResume ? { deferResume: true } : {}),\n lifecycle: {\n shutdown: () => {\n void close().then(() => options.onIdle?.())\n },\n retireWhenIdle,\n isRetiring: () => retiring || updatePending,\n },\n })\n const host = dispatcher.host\n\n /* ----------------------------------------------------------------------\n * Socket plumbing\n * -------------------------------------------------------------------- */\n\n /*\n * Retire-when-idle: a NEWER client found this daemon mid-work. Draining\n * now would abort every window's runs (a dev edit under `src/ipc` or an\n * upgrade mid-`/review` did exactly that), so keep serving and exit at\n * the first idle point. Two consecutive idle polls: a queue drain is\n * scheduled just after a dispatch releases, and one poll could land in\n * that gap.\n */\n function retireWhenIdle(): void {\n if (retiring)\n return\n retiring = true\n log('[ipc-daemon] a newer client attached mid-work; retiring once idle')\n let idlePolls = 0\n retireTimer = setInterval(() => {\n if (host.hasActiveWork()) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(retireTimer)\n void close().then(() => options.onIdle?.())\n }, 1000)\n }\n\n // A newer zidane on disk: retire like above, but only once fully idle (`./update-retire`).\n const updates = options.updateWatch && !shared\n ? watchDaemonUpdate({ ...options.updateWatch, isIdle: () => daemonFullyIdle(host), onPending: () => { updatePending = true }, retire: () => void close().then(() => options.onIdle?.()), log })\n : null\n\n function armIdleTimer(): void {\n if (shared || !options.idleShutdownMs || !options.onIdle)\n return\n clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n if (dispatcher.peerCount() > 0)\n return // Peers reconnected — the next last-disconnect re-arms.\n /*\n * Never abort a live run just because every window detached — `/exit`\n * is explicitly \"the run keeps going\". Re-arm and check again later.\n */\n if (host.hasActiveWork()) {\n armIdleTimer()\n return\n }\n options.onIdle?.()\n }, options.idleShutdownMs)\n }\n\n function handleConnection(socket: Socket): void {\n // Assigned right below; a signal can only reach this peer after `ipc.hello`, i.e. once it is set.\n let connection: JsonRpcConnection | undefined\n const writer = createPacedWriter(socket)\n const budget = createPeerSend(\n {\n buffered: writer.buffered,\n // NDJSON: `JSON.stringify` escapes newlines, so a message is one line.\n write: (json) => {\n writer.write(`${json}\\n`)\n return true\n },\n },\n {\n maxBuffered,\n maxMessage,\n log,\n label: '[ipc-daemon]',\n stuck: (why) => {\n log(`[ipc-daemon] dropping peer: ${why}`)\n socket.destroy()\n },\n },\n )\n const peer = createRpcPeer({ rpc: () => connection })\n\n const rpc = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: budget.send,\n ...dispatcherHandlers(dispatcher, peer),\n onError: err => log(`[ipc-daemon] peer error: ${err.message}`),\n })\n\n connection = rpc\n const entry: SocketConnection = { socket, connection: rpc }\n connections.add(entry)\n dispatcher.addPeer(peer)\n rpc.start()\n log(`[ipc-daemon] peer connected (${dispatcher.peerCount()} total)`)\n\n const drop = (): void => {\n if (!connections.delete(entry))\n return\n rpc.close()\n dispatcher.removePeer(peer)\n log(`[ipc-daemon] peer disconnected (${dispatcher.peerCount()} left)`)\n if (dispatcher.peerCount() === 0)\n armIdleTimer()\n }\n\n socket.on('close', drop)\n socket.on('error', drop)\n }\n\n /*\n * Stale-socket recovery: a previous daemon that died without cleanup\n * leaves the socket file behind and `listen` would fail EADDRINUSE.\n * Probe before unlinking so a LIVE daemon is never yanked out from\n * under its peers.\n */\n if (existsSync(socketPath)) {\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n /*\n * Narrow the concurrent-spawn race: another daemon may have bound the\n * socket between the probe above and the unlink below (each probe is a\n * full connect attempt). Re-probe immediately before unlinking and\n * abort startup if something now answers — never yank a live daemon's\n * socket out from under its peers.\n */\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n unlinkSync(socketPath)\n }\n /*\n * The daemon speaks an unauthenticated RPC surface that can execute tools\n * as the daemon user — restrict access to the owner. The containing dir\n * is created 0700 (belt) and the socket is chmod'd to 0600 right after\n * `listen` (suspenders) so connectability never depends on ambient umask.\n *\n * `mkdirSync`'s mode only applies on CREATION — a pre-existing dir keeps\n * its old mode. When the dir is the DEDICATED daemon dir (the `daemon/`\n * subdir `defaultSocketPath` uses, or one we created fresh for an\n * explicit socket path) chmod it 0700 explicitly. A shared, pre-existing\n * dir (tests pointing the socket at a tmpdir) is left alone — never\n * tighten a directory that also holds unrelated state.\n */\n const socketDir = dirname(socketPath)\n const dedicatedSocketDir = basename(socketDir) === 'daemon' || !existsSync(socketDir)\n mkdirSync(socketDir, { recursive: true, mode: 0o700 })\n if (dedicatedSocketDir) {\n try {\n chmodSync(socketDir, 0o700)\n }\n catch {\n // Best-effort — mirrors the socket chmod below.\n }\n }\n\n const server: Server = createServer(handleConnection)\n await new Promise<void>((resolvePromise, reject) => {\n server.once('error', reject)\n server.listen(socketPath, () => {\n server.off('error', reject)\n resolvePromise()\n })\n })\n try {\n chmodSync(socketPath, 0o600)\n }\n catch {\n // Best-effort on platforms where socket chmod is a no-op (e.g. some\n // network filesystems); the 0700 dir still constrains access.\n }\n log(`[ipc-daemon] listening on ${socketPath}`)\n // We bound the socket, so we own the file — close() unlinks it exactly\n // once. Cleared after the unlink so a file later re-created by a NEW\n // daemon on the same path is never yanked by a stale close.\n let ownsSocketFile = true\n armIdleTimer()\n\n /*\n * Drain any daemon still serving the legacy socket path\n * (`<stateDir>/daemon.sock`). New clients never probe it,\n * so a `--idle-exit 0` service daemon there would run forever alongside\n * this one — two sets of live agents, run guards, and heartbeat writers\n * against the same sessions.db. Fire-and-forget: version mismatch is\n * the EXPECTED case (a legacy daemon speaks an older protocol) and\n * `drainOnMismatch: true` performs the shutdown for us; a same-version\n * survivor (explicit env overrides) gets an explicit daemon.shutdown.\n */\n const legacyPath = shared ? null : legacySocketPath(socketPath)\n if (legacyPath) {\n void (async () => {\n if (!(await probeSocket(legacyPath)))\n return\n log(`[ipc-daemon] draining legacy daemon on ${legacyPath}`)\n try {\n const survivor = await connectIpcClient({ socketPath: legacyPath, appVersion: `${appVersion}/legacy-drain`, drainOnMismatch: true })\n await survivor.request('daemon.shutdown', {}).catch(() => undefined)\n survivor.close()\n }\n catch {\n // IpcVersionMismatchError = drained by the handshake path; anything\n // else (raced exit, wedged socket) is best-effort — leave it.\n }\n })()\n }\n\n async function doClose(): Promise<void> {\n clearTimeout(idleTimer)\n clearInterval(retireTimer)\n updates?.close()\n // A shared host is its owner's to drain and detach (see `dispatcher`).\n if (!shared)\n await host.drain()\n // Stop accepting before closing what is open: a connection landing in\n // between would otherwise keep `server.close` waiting forever.\n const stopped = new Promise<void>((resolvePromise) => {\n server.close(() => resolvePromise())\n })\n for (const { connection, socket } of connections) {\n connection.close()\n socket.destroy()\n }\n connections.clear()\n if (!shared)\n dispatcher.detachAll()\n await stopped\n if (ownsSocketFile) {\n ownsSocketFile = false\n try {\n unlinkSync(socketPath)\n }\n catch {\n // already gone\n }\n }\n }\n\n /*\n * Idempotent close: `daemon.shutdown` runs close() and then onIdle, whose\n * CLI implementation calls daemon.close() again — both callers share one\n * drain instead of double-unlinking the socket. Memoized rather than\n * flag-guarded so the second caller awaits actual completion.\n */\n let closePromise: Promise<void> | null = null\n function close(): Promise<void> {\n closePromise ??= doClose()\n return closePromise\n }\n\n return {\n socketPath,\n host,\n dispatcher,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n","/**\n * Login-shell PATH for processes not started from a terminal.\n *\n * A Dock/Finder-launched GUI, or a daemon it spawns, inherits launchd's PATH\n * (`/usr/bin:/bin:/usr/sbin:/sbin`), so `node` / `bun` / `yarn` are invisible\n * to agent shell commands. Ask the user's login shell for its PATH and merge\n * it into `process.env.PATH`.\n *\n * Merge, don't replace: a terminal launch may have prepended entries the rc\n * files know nothing about (`nvm use`, direnv, `PATH=... zidane`), and those\n * must survive. Idempotent, so every surface (GUI, daemon) can call it and a\n * daemon spawned by an already-fixed GUI ends up with the same PATH.\n */\nimport { spawnSync } from 'node:child_process'\nimport { userInfo } from 'node:os'\nimport { delimiter } from 'node:path'\nimport process from 'node:process'\nimport { runBounded } from '../../contexts/run-bounded'\n\nconst DELIMITER = '_ZIDANE_SHELL_ENV_'\n\n/** A slow rc file costs startup time; a prompting one must never hang the process. */\nconst DEFAULT_TIMEOUT_MS = 3_000\n\nfunction defaultShell(env: NodeJS.ProcessEnv): string {\n try {\n const { shell } = userInfo()\n if (shell)\n return shell\n }\n catch {}\n return env.SHELL || (process.platform === 'darwin' ? '/bin/zsh' : '/bin/sh')\n}\n\nfunction parsePath(stdout: string): string | undefined {\n const body = stdout.split(DELIMITER)[1]\n if (body === undefined)\n return undefined\n // eslint-disable-next-line no-control-regex\n const clean = body.replace(/\\u001B\\[[0-9;]*[A-Z]/gi, '')\n for (const line of clean.split('\\n')) {\n if (line.startsWith('PATH='))\n return line.slice('PATH='.length) || undefined\n }\n return undefined\n}\n\n/**\n * Options for {@link shellPath} and {@link shellPathAsync}. Without `shell`,\n * the user's shell is tried first, then POSIX fallbacks for non-POSIX defaults\n * (nushell, xonsh) whose `-ilc` differs. An explicit `shell` is tried alone.\n * `timeoutMs` bounds each shell. Default 3000.\n */\nexport interface ShellPathOptions { env?: NodeJS.ProcessEnv, timeoutMs?: number, shell?: string }\n\n// `command env` sidesteps aliases/functions named `env`.\nconst SHELL_ARGS = ['-ilc', `echo -n \"${DELIMITER}\"; command env; echo -n \"${DELIMITER}\"; exit`]\n\nfunction shellCandidates(options: ShellPathOptions): { shells: string[], env: NodeJS.ProcessEnv, timeout: number } {\n const env = options.env ?? process.env\n return {\n shells: options.shell ? [options.shell] : [...new Set([defaultShell(env), '/bin/zsh', '/bin/bash'])],\n timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n env: {\n ...env,\n // Keep oh-my-zsh from blocking on its update prompt / tmux autostart.\n DISABLE_AUTO_UPDATE: 'true',\n ZSH_TMUX_AUTOSTARTED: 'true',\n ZSH_TMUX_AUTOSTART: 'false',\n },\n }\n}\n\n/**\n * Reads the PATH of the user's interactive login shell, blocking until it answers.\n * Tries the user's shell, then `/bin/zsh` and `/bin/bash`. Returns `undefined` on Windows, or when no shell answers in time.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport function shellPath(options: ShellPathOptions = {}): string | undefined {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const result = spawnSync(shell, SHELL_ARGS, {\n encoding: 'utf8',\n timeout,\n stdio: ['ignore', 'pipe', 'ignore'],\n env,\n })\n if (result.error || result.status !== 0)\n continue\n const path = parsePath(result.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * {@link shellPath} without blocking the event loop: same shells, args,\n * timeout and parsing, run with {@link runBounded} (a timeout ends the shell's\n * whole tree; under Bun its output survives a shell that exits before Bun\n * watches it). For hosts (the GUI main process) that can start on a cached\n * PATH and refresh in the background.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport async function shellPathAsync(options: ShellPathOptions = {}): Promise<string | undefined> {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const run = await runBounded(shell, SHELL_ARGS, { env, timeoutMs: timeout })\n if (run.code !== 0)\n continue\n const path = parsePath(run.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * Entries of `current` the shell doesn't know about (ad-hoc prepends from the\n * launching terminal) stay in front; then the shell's PATH in its own order.\n * From the Dock every launchd entry is already in the shell PATH, so the\n * result is exactly the shell PATH, with the shell's precedence intact.\n * @param current - The PATH of this process.\n * @param shell - The PATH reported by the login shell.\n * @returns The merged PATH string.\n */\nexport function mergePath(current: string | undefined, shell: string | undefined): string {\n const split = (path: string | undefined): string[] => (path ?? '').split(delimiter).filter(Boolean)\n const fromShell = split(shell)\n const known = new Set(fromShell)\n return [...new Set([...split(current).filter(entry => !known.has(entry)), ...fromShell])].join(delimiter)\n}\n\n/** Merge the login shell's PATH into `process.env.PATH`. No-op on Windows or when no shell answers. */\nexport function fixPath(): void {\n const extra = shellPath()\n if (extra)\n process.env.PATH = mergePath(process.env.PATH, extra)\n}\n","/**\n * In-process transport: the host dispatcher in the window's own process, and\n * `IpcClient`s that call it directly instead of over a unix socket.\n *\n * For a window that runs its own host (TUI local mode on the shared engine):\n * the same dispatcher, method table and signal fan-out a daemon serves, with\n * no socket, no spawn and no second process. A caller sees what a socket\n * client would, so the daemon-mode code paths run on it unchanged:\n * - params, results and signals are JSON copies (as on the wire: a top-level\n * `undefined` result arrives as `null`, nested `undefined` fields are\n * dropped, and nothing is shared between the window and the host);\n * - a failed request rejects with `JsonRpcRemoteError` carrying the\n * dispatcher's code; a closed connection rejects with\n * `JsonRpcConnectionClosedError`, in-flight requests included;\n * - responses and signals arrive asynchronously, through one queue in the\n * order the host produced them (a socket reads them in write order);\n * - `close()` detaches quietly; the host shutting down calls `onClose`.\n *\n * `connectInProcess` opens the same client on a dispatcher that already\n * serves other transports (a zidane-server's), optionally held to a client\n * scope like a WebSocket peer with that token.\n *\n * Two socket behaviors are deliberately absent. Request deadlines exist on\n * the socket to recover from a wedged daemon by dropping the connection and\n * reconnecting; in-process there is nothing to reconnect to. And\n * `daemon.shutdown` from a client does not stop the host: its lifetime\n * belongs to the embedding window (`InProcessHost.close()`).\n */\nimport type { ChatHost } from '../chat/host/engine'\nimport type { IpcClient } from './client'\nimport type { HostDispatcher, HostPeer } from './daemon/dispatcher'\nimport type { DaemonEnvironment } from './daemon/environment'\nimport type { HelloResult, HostSignal } from './protocol'\nimport type { ClientScope } from './scopes'\nimport type { SignalListener } from './transports/client-core'\nimport { JsonRpcConnectionClosedError, JsonRpcRemoteError } from '../acp/json-rpc'\nimport { ZIDANE_VERSION } from '../version'\nimport { createHostDispatcher } from './daemon/dispatcher'\nimport { IPC_BUILD_ID } from './daemon/lifecycle'\nimport { IPC_PROTOCOL_VERSION } from './protocol'\n\n/** Options for {@link startInProcessHost}. */\nexport interface InProcessHostOptions {\n /** The host's environment, given the broadcast sink wired to client fan-out. */\n createEnvironment: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /** Reported to clients as the host's `appVersion`. */\n appVersion?: string\n}\n\n/** Options for {@link InProcessHost.connect}. */\nexport interface InProcessClientOptions {\n /** Client version, surfaced in the host's diagnostics. */\n appVersion?: string\n /** Called when the host shuts down under a still-open client. */\n onClose?: () => void\n}\n\n/** Options for {@link connectInProcess}. */\nexport interface InProcessConnectOptions extends InProcessClientOptions {\n /** The client scope the dispatcher holds the client to (`./scopes`). Absent: every method, like a local window. */\n grant?: ClientScope\n}\n\n/** A chat host running in the caller's process, with clients that call it directly. */\nexport interface InProcessHost {\n /** The chat host. */\n host: ChatHost\n /** A new client, already past the `ipc.hello` handshake. */\n connect: (options?: InProcessClientOptions) => Promise<IpcClient>\n /** Number of open clients. */\n peerCount: () => number\n /**\n * Shut the host down: refuse new work, suspend and await every run\n * (`ChatHost.drain`), then close the clients still open (their `onClose`\n * fires). Idempotent.\n */\n close: () => Promise<void>\n}\n\n/** JSON round-trip: what crossing the socket does to a value. */\nfunction wire<T>(value: T): T {\n return value === undefined ? (null as T) : JSON.parse(JSON.stringify(value)) as T\n}\n\n/** One open client, from the host's side. */\ninterface Connection {\n peer: HostPeer\n /** The host is shutting down: reject what is pending, then tell the client. */\n hostClosed: () => void\n}\n\n/**\n * Opens one client on `dispatcher`; `connections` (the in-process host's)\n * tracks it until it closes, so the host can close it when it shuts down.\n */\nasync function openClient(dispatcher: HostDispatcher, options: InProcessConnectOptions, connections?: Set<Connection>): Promise<IpcClient> {\n const listeners = new Set<SignalListener>()\n const pending = new Set<(err: Error) => void>()\n let closed = false\n\n /*\n * Everything bound for the client goes through one FIFO drained in a\n * microtask: signals, and request outcomes once the dispatcher settles\n * them. A signal the host emits after answering a request is therefore\n * delivered after that answer, as a socket would read them.\n */\n const outbox: Array<() => void> = []\n let draining = false\n const deliver = (item: () => void): void => {\n outbox.push(item)\n if (draining)\n return\n draining = true\n queueMicrotask(() => {\n try {\n while (outbox.length > 0) {\n try {\n outbox.shift()!()\n }\n catch {\n // A throwing listener costs that one message, as on the socket\n // (the JSON-RPC reader catches it), never the connection.\n }\n }\n }\n finally {\n draining = false\n }\n })\n }\n\n const peer: HostPeer = {\n ready: false,\n watching: null,\n ...(options.grant ? { grant: options.grant } : {}),\n send(signal, seq, encoded) {\n if (closed)\n return\n const meta = seq === undefined ? undefined : { seq }\n let copy: HostSignal\n try {\n // The fan-out's one serialization, when it has one.\n const json = encoded ? encoded.json() : JSON.stringify(signal)\n if (json === undefined)\n return\n copy = JSON.parse(json) as HostSignal\n }\n catch {\n // Not JSON-able: the socket server drops it the same way, and a\n // bad signal must never break fan-out to the other clients.\n return\n }\n deliver(() => {\n if (closed)\n return\n for (const listener of listeners)\n listener(copy, meta)\n })\n },\n }\n\n const request = (method: string, params: unknown): Promise<unknown> => {\n if (closed)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return new Promise((resolve, reject) => {\n pending.add(reject)\n const settle = (outcome: () => void): void => {\n deliver(() => {\n if (!pending.delete(reject))\n return\n outcome()\n })\n }\n dispatcher.handleRequest(method, params === undefined ? undefined : wire(params), peer).then(\n (result) => {\n settle(() => {\n // The reject is already out of `pending`: a throw here (a result\n // that is not JSON-able) must fail the request, not hang it.\n try {\n if (result.ok)\n resolve(wire(result.result))\n else\n reject(new JsonRpcRemoteError(result.message, result.code, result.data))\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n }\n })\n },\n err => settle(() => reject(err)),\n )\n })\n }\n\n /** Stop delivering and fail what is in flight, as a socket closing does. */\n const shut = (): void => {\n closed = true\n listeners.clear()\n outbox.length = 0\n for (const reject of pending)\n reject(new JsonRpcConnectionClosedError())\n pending.clear()\n }\n\n const connection: Connection = {\n peer,\n hostClosed: () => {\n if (closed)\n return\n shut()\n options.onClose?.()\n },\n }\n\n dispatcher.addPeer(peer)\n connections?.add(connection)\n const detach = (): void => {\n if (closed)\n return\n shut()\n connections?.delete(connection)\n dispatcher.removePeer(peer)\n }\n\n let hello: HelloResult\n try {\n hello = await request('ipc.hello', {\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion: options.appVersion ?? 'dev',\n pid: process.pid,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n }) as HelloResult\n }\n catch (err) {\n detach()\n throw err\n }\n\n return {\n hello,\n request: request as IpcClient['request'],\n notify: (method, params) => {\n if (closed)\n return\n const copy = params === undefined ? undefined : wire(params)\n // Off the caller's stack, as a socket write would be.\n queueMicrotask(() => {\n if (!closed)\n void dispatcher.handleNotification(method, copy, peer)\n })\n },\n onSignal: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n close: detach,\n }\n}\n\n/**\n * Connects an in-process client to a dispatcher that already runs (a\n * zidane-server's, the daemon's), next to its socket and WebSocket peers.\n * With a `grant`, the dispatcher checks every call against it as it does for\n * a WebSocket peer whose token has that scope (`./scopes`); without one the\n * client reaches every method, like a local window.\n *\n * The dispatcher's owner closes such clients before it stops the host:\n * `onClose` fires only when the in-process host of {@link startInProcessHost}\n * shuts down under one.\n * @param dispatcher - The running dispatcher.\n * @param options - Scope and version.\n * @returns The client, already past the `ipc.hello` handshake.\n */\nexport function connectInProcess(dispatcher: HostDispatcher, options: InProcessConnectOptions = {}): Promise<IpcClient> {\n return openClient(dispatcher, options)\n}\n\n/**\n * Starts a chat host in this process. Clients from `connect` behave like socket clients, without a socket or a second process.\n * @param options - Environment factory and version.\n * @returns The host handle.\n */\nexport async function startInProcessHost(options: InProcessHostOptions): Promise<InProcessHost> {\n const connections = new Set<Connection>()\n let closing: Promise<void> | null = null\n\n const dispatcher = await createHostDispatcher({\n createEnvironment: options.createEnvironment,\n appVersion: options.appVersion ?? 'dev',\n startedAt: Date.now(),\n identity: { kind: 'in-process' },\n lifecycle: {\n // Owned by the embedding window, see the module header.\n shutdown: () => undefined,\n // Clients are this build by construction: never a newer one to retire for.\n retireWhenIdle: () => undefined,\n isRetiring: () => false,\n },\n })\n\n function connect(clientOptions: InProcessClientOptions = {}): Promise<IpcClient> {\n if (closing)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return openClient(dispatcher, clientOptions, connections)\n }\n\n function close(): Promise<void> {\n // Same order as the socket server's shutdown: drain the host, close\n // every connection, then forget the peers without per-peer cleanup.\n closing ??= (async () => {\n await dispatcher.host.drain()\n for (const connection of connections)\n connection.hostClosed()\n connections.clear()\n dispatcher.detachAll()\n })()\n return closing\n }\n\n return {\n host: dispatcher.host,\n connect,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,eAAe;;AA+BrB,IAAa,gBAAb,cAAmC,MAAM;CAKlB;CAA8B;;;;;CAAnD,YAAY,aAA8B,QAAoC;EAC5E,MAAM,GAAG,YAAY,oCAAoC,OAAO,KAAK,MAAM,GAAG;EAD3D,KAAA,cAAA;EAA8B,KAAA,SAAA;EAEjD,KAAK,OAAO;CACd;AACF;AAuBA,SAAS,OAAO,MAA+B;CAC7C,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK;AACvD;AAEA,SAAS,KAAK,MAAsB;CAClC,IAAI;EACF,OAAO,aAAa,IAAI;CAC1B,QACM;EACJ,OAAO;CACT;AACF;AAEA,SAAS,UAAU,MAAqC;CACtD,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;CAChD,QACM;EACJ;CACF;CACA,MAAM,OAAO;CACb,IAAI,CAAC,QAAQ,KAAK,WAAW,gBAAgB,OAAO,KAAK,SAAS,YAAY,OAAO,KAAK,SAAS,YAAY,CAAC,KAAK,UAAU,OAAO,KAAK,WAAW,UACpJ,OAAO,KAAA;CACT,OAAO;AACT;;AAGA,SAASA,gBAAc,QAAyC;CAC9D,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,GAC9C,IAAI;EACF,IAAI,OAAO,aAAa,IAAI,CAAC,MAAM,MACjC,OAAO;CACX,QACM;EACJ,OAAO;CACT;CAEF,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS;AACtC;AAEA,SAAS,UAAU,OAAwB;CACzC,IAAI,iBAAiB,OACnB,OAAO,MAAM;CACf,OAAO,OAAO,KAAK;AACrB;;;;;;;;;;;;;AAcA,eAAsB,eAAe,SAA0D;CAC7F,MAAM,MAAO,WAA0D;CACvE,IAAI,OAAO,KAAK,UAAU,YACxB,MAAM,IAAI,cAAc,QAAQ,aAAa,CAAC,4HAA4H,CAAC;CAC7K,MAAM,QAAQ,KAAK,QAAQ,QAAQ,KAAK,CAAC;CACzC,MAAM,OAAO,KAAK,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC;CAChE,MAAM,QAAQ,QAAQ,YAAY,CAAC;CACnC,MAAM,UAAU,IAAI,WAAW;CAC/B,MAAM,MAAM,OAAO,KAAK,UAAU;EAAC;EAAc;EAAS,QAAQ;EAAa;EAAO;EAAM,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK;CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE;CAC5H,MAAM,YAAY,QAAQ,QAAQ,UAAU,MAAM,IAAI,MAAM;CAE5D,MAAM,MAAM,UAAU,SAAS;CAC/B,IAAI,OAAO,IAAI,QAAQ,WAAWA,gBAAc,IAAI,MAAM,GACxD,OAAO;EAAE,MAAM,IAAI;EAAM,MAAM,IAAI;EAAM,UAAU,CAAC,GAAG,IAAI,QAAQ;EAAG,QAAQ;EAAM,QAAQ,IAAI;CAAO;CAEzG,MAAM,UAAoB,CAAC;CAC3B,MAAM,QAAQ;EACZ,MAAM;EACN,MAAM,OAA0J;GAC9J,MAAM,UAAU,EAAE,QAAQ,KAAK,IAAI,SAAS;IAC1C,MAAM,UAAU,iBAAiB,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK;IACtE,IAAI,QAAQ,SAAS,YACnB,OAAO;KAAE,MAAM,KAAK;KAAM,UAAU;IAAK;IAC3C,IAAI,QAAQ,SAAS,SAAS;KAC5B,QAAQ,KAAK,QAAQ,OAAO;KAE5B,OAAO;MAAE,MAAM,KAAK;MAAM,UAAU;KAAK;IAC3C;GAEF,CAAC;EACH;CACF;CAEA,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,IAAI,MAAM;GACvB,aAAa,CAAC,KAAK;GACnB;GACA,QAAQ;GACR,QAAQ;GACR,WAAW;GACX,UAAU;GACV,OAAO;GACP,SAAS,CAAC,KAAK;GACf,KAAK;IAAE,SAAS;IAAa,cAAc;IAAS,aAAa;GAAM;GACvE,QAAQ,EAAE,wBAAwB,iBAAe;EACnD,CAAC;CACH,SACO,OAAO;EACZ,MAAM,SAAS,iBAAiB,iBAAiB,MAAM,OAAO,IAAI,SAAS,IAAI,CAAC,UAAU,KAAK,CAAC;EAChG,MAAM,IAAI,cAAc,QAAQ,aAAa,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC;CACtE;CACA,MAAM,cAAc,OAAO,KAAK,QAAO,QAAO,IAAI,UAAU,OAAO,CAAC,CAAC,KAAI,QAAO,IAAI,OAAO;CAC3F,IAAI,QAAQ,SAAS,KAAK,CAAC,OAAO,WAAW,YAAY,SAAS,GAChE,MAAM,IAAI,cAAc,QAAQ,aAAa,CAAC,GAAG,SAAS,GAAG,WAAW,CAAC,CAAC,SAAS,IAAI,CAAC,GAAG,SAAS,GAAG,WAAW,IAAI,CAAC,sCAAsC,CAAC;CAChK,MAAM,SAAS,OAAO,QAAQ,MAAK,MAAK,EAAE,SAAS,aAAa,KAAK,OAAO,QAAQ;CACpF,IAAI,CAAC,UAAU,OAAO,QAAQ,WAAW,GACvC,MAAM,IAAI,cAAc,QAAQ,aAAa,CAAC,6CAA6C,OAAO,QAAQ,QAAQ,CAAC;CACrH,MAAM,OAAO,MAAM,OAAO,KAAK;CAC/B,MAAM,OAAO,OAAO,IAAI;CAExB,MAAM,WAAW,OAAO,KAAK,QAAO,QAAO,IAAI,UAAU,SAAS,CAAC,CAAC,KAAI,QAAO,IAAI,OAAO;CAC1F,MAAM,SAAiC,CAAC;CACxC,MAAM,qCAAqB,IAAI,IAAY;CAC3C,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,OAAO,UAAU,UAAU,CAAC,CAAC,GAAG;EAExE,MAAM,WAAW,QAAQ,QAAQ,IAAI,GAAG,IAAI;EAC5C,IAAI;GACF,OAAO,YAAY,OAAO,aAAa,QAAQ,CAAC;EAClD,QACM,CAEN;EACA,KAAK,MAAM,YAAY,KAAK,SAC1B,IAAI,SAAS,aAAa,SAAS,SAAS,YAAY,SAAS,KAAK,WAAW,SAAS,IACxF,mBAAmB,IAAI,SAAS,IAAI;CAE1C;CACA,KAAK,MAAM,aAAa,oBACtB,SAAS,KAAK,YAAY,UAAU,0EAA0E;CAEhH,MAAM,OAAkB;EAAE,QAAQ;EAAc,KAAK;EAAS;EAAQ;EAAM;EAAM;CAAS;CAC3F,IAAI;EACF,gBAAgB,WAAW,KAAK,UAAU,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CACtE,QACM,CAEN;CACA,OAAO;EAAE;EAAM;EAAM;EAAU,QAAQ;EAAO;CAAO;AACvD;;;;ACxNA,MAAM,cAAc;AAQpB,SAAgB,kBAAkB,QAA+B;CAC/D,MAAM,QAAkB,CAAC;CACzB,IAAI,cAAc;CAClB,IAAI,UAAU;;CAEd,IAAI,UAAoB,CAAC;CACzB,IAAI,eAAe;CACnB,IAAI,QAAQ;CAEZ,MAAM,oBAA0B;EAC9B,IAAI,QAAQ,WAAW,GACrB;EACF,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,IAAI,QAAQ,KAAM,QAAQ,KAAK,EAAE,CAAC;EAC/E,UAAU,CAAC;EACX,eAAe;EACf,MAAM,KAAK,KAAK;EAChB,eAAe,MAAM;CACvB;CAEA,MAAM,aAAmB;EACvB,UAAU;EACV,YAAY;EACZ,OAAO,MAAM,SAAS,GAAG;GACvB,IAAI,OAAO,aAAa,OAAO,eAAe;IAC5C,MAAM,SAAS;IACf,cAAc;IACd;GACF;GACA,MAAM,OAAO,MAAM;GACnB,MAAM,QAAQ,KAAK,SAAS,cAAc,KAAK,SAAS,GAAG,WAAW,IAAI;GAC1E,IAAI,UAAU,MACZ,MAAM,MAAM;QAEZ,MAAM,KAAK,KAAK,SAAS,WAAW;GACtC,eAAe,MAAM;GACrB,IAAI,CAAC,OAAO,MAAM,KAAK,GAAG;IACxB,UAAU;IACV,OAAO,KAAK,SAAS,IAAI;IACzB;GACF;EACF;CACF;CAEA,OAAO;EACL,MAAM,MAAM;GACV,IAAI,KAAK,UAAU,aAAa;IAC9B,YAAY;IACZ,MAAM,QAAQ,OAAO,KAAK,IAAI;IAC9B,MAAM,KAAK,KAAK;IAChB,eAAe,MAAM;IACrB,IAAI,CAAC,SACH,KAAK;IACP;GACF;GACA,QAAQ,KAAK,IAAI;GACjB,gBAAgB,OAAO,WAAW,IAAI;GAEtC,IAAI,SACF;GACF,IAAI,gBAAgB,aAAa;IAC/B,KAAK;IACL;GACF;GACA,IAAI,OACF;GACF,QAAQ;GACR,qBAAqB;IACnB,QAAQ;IACR,IAAI,CAAC,SACH,KAAK;GACT,CAAC;EACH;EACA,gBAAgB,eAAe,cAAc,OAAO;CACtD;AACF;;;;;;;;;;;;;;;;;;;;AC7CA,eAAsB,iBAAiB,SAA+C;CACpF,MAAM,SAAiB,MAAM,IAAI,SAAS,gBAAgB,WAAW;EACnE,MAAM,IAAI,QAAQ,QAAQ,UAAU;EACpC,EAAE,KAAK,iBAAiB;GACtB,EAAE,IAAI,SAAS,MAAM;GACrB,eAAe,CAAC;EAClB,CAAC;EACD,EAAE,KAAK,SAAS,MAAM;CACxB,CAAC;CAED,MAAM,UAAU,sBAAsB;CACtC,IAAI,SAAS;CAGb,MAAM,SAAS,kBAAkB,MAAM;CACvC,MAAM,aAAa,wBAAwB;EACzC,OAAO;EACP,QAAQ;EACR,OAAM,SAAQ,OAAO,MAAM,GAAG,KAAK,GAAG;EAEtC,YAAW,YAAW,cAAc,QAAQ,IAAI,kBAAkB,iCAAiC;EACnG,gBAAgB,QAAQ;CAC1B,CAAC;CACD,WAAW,MAAM;CAEjB,MAAM,cAAoB;EACxB,IAAI,QACF;EACF,SAAS;EACT,WAAW,MAAM;EACjB,OAAO,QAAQ;CACjB;CAEA,OAAO,GAAG,eAAe;EACvB,IAAI,QACF;EACF,SAAS;EACT,WAAW,MAAM;EACjB,QAAQ,UAAU;CACpB,CAAC;CACD,OAAO,GAAG,eAAe,CAEzB,CAAC;CAED,MAAM,UAAU,QAAQ,oBAAoB;CAC5C,OAAO,cAEL;EAAE,KAAK;EAAY;EAAO,aAAa,OAAO,QAAQ;EAAG,OAAO,QAAQ;CAAW,GACnF,QAAQ,WACR;EACE,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;EAC/D,OAAO,UAAU,eAAe;EAChC,YAAY,CAAC;CACf,CACF;AACF;;;;;;;;AASA,eAAsB,qBACpB,UAAsE,CAAC,GACnD;CACpB,MAAM,aAAa,MAAM,oBAAoB,OAAO;CACpD,IAAI;EACF,OAAO,MAAM,iBAAiB;GAAE,GAAG;GAAS;EAAW,CAAC;CAC1D,SACO,KAAK;EACV,IAAI,EAAE,eAAe,0BACnB,MAAM;EASR,MAAM,gBAAgB,KAAK,IAAI,IAAI;EACnC,OAAO,MAAM,YAAY,UAAU,GAAG;GACpC,IAAI,KAAK,IAAI,IAAI,eACf;GACF,MAAM,IAAI,SAAQ,MAAK,WAAW,GAAG,GAAG,CAAC;EAC3C;EACA,MAAM,YAAY,MAAM,oBAAoB,OAAO;EACnD,OAAO,iBAAiB;GAAE,GAAG;GAAS,YAAY;EAAU,CAAC;CAC/D;AACF;;;ACpHA,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,cAAc;;AAKpB,SAAgB,wBAAwB,MAA8B;CAEpE,IAAI,CAAC,MACH,OAAO;CACT,MAAM,QAAQ,KAAK,MAAM,OAAO;CAChC,IAAI,MAAM,MAAK,SAAQ,SAAS,kBAAkB,KAAK,WAAW,GAAG,CAAC,GACpE,OAAO;CACT,IAAI,MAAM,WAAW,KAAK,MAAM,OAAO,gBACrC,OAAO;CACT,OAAO,YAAY,KAAK,IAAI;AAC9B;AA0CA,MAAM,aAA+B,KAAK,WAAW,WACnDC,MAAQ,KAAK;CAAE;CAAW,YAAY;AAAM,IAAI,QAAQ,SAAS,OAAO,OAAO,OAAO,IAAI,IAAI,IAAI,CAAC;;;;;;;;;;AAWrG,SAAgB,sBAAsB,UAAoC,UAAuC,CAAC,GAAyB;CACzI,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,YAAY,QAAQ,oBAAoB;CAC9C,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,2BAAW,IAAI,IAAsC;CAC3D,MAAM,0BAAU,IAAI,IAAY;CAChC,IAAI;CACJ,IAAI,SAAS;CAEb,MAAM,YAAY,UAAwB;EACxC,aAAa,KAAK;EAClB,QAAQ,iBAAiB;GACvB,QAAQ,KAAA;GACR,IAAI,QACF;GACF,IAAI,CAAC,UAAU,GACb,OAAO,SAAS,OAAO;GACzB,MAAM,OAAO,CAAC,GAAG,OAAO;GACxB,QAAQ,MAAM;GACd,IAAI,KAAK,SAAS,GAChB,SAAS,IAAI;EACjB,GAAG,KAAK;EACR,MAAM,QAAQ;CAChB;CAEA,MAAM,WAAW,QAAsB;EACrC,QAAQ,IAAI,GAAG;EACf,SAAS,QAAQ;CACnB;CAEA,MAAM,WAAW,SAAiC,SAAA,yBAAkC,MAAM,SAAS,GAAG,wBAA6B,MAAM;CAEzI,MAAM,QAAQ,QAAsB;EAClC,MAAM,UAAU,SAAS,IAAI,GAAG;EAChC,SAAS,OAAO,GAAG;EACnB,IAAI;GACF,SAAS,MAAM;EACjB,QACM,CAAC;CACT;;CAGA,MAAM,QAAQ,KAAa,WAAoB,QAAuC,WAA6D;EACjJ,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,KAAK,YAAY,SAAS;IACxC,IAAI,QAAQ,IAAI,GAAG;KACjB,QAAQ,UAAU,GAAG;KACrB;IACF;IACA,OAAO,IAAI;GACb,CAAC;EACH,QACM;GACJ;EACF;EACA,QAAQ,GAAG,SAAS,MAAM;EAC1B,OAAO;CACT;;CAGA,MAAM,cAAc,UAAkB,SAA8B;EAElE,MAAM,QAAQ,MAAM,MAAM,OAAO,CAAC,CAAC;EACnC,IAAI,SAAS,CAAC,MAAM,WAAW,GAAG,GAChC,QAAQ,KAAK,MAAM,KAAK,CAAC;CAC7B;;;;;;CAOA,MAAM,aAAa,KAAa,SAAwC;EACtE,IAAI;;EAEJ,IAAI;;EAEJ,IAAI,UAAU;EACd,IAAI,OAAO;EACX,MAAM,QAAQ,KAAyB,SAAqD;GAC1F,IAAI;IACF,SAAS,MAAM;GACjB,QACM,CAAC;GACP,UAAU;GACV,UAAU,OAAO,MAAM,KAAA;EACzB;EACA,MAAM,SAAoB,EACxB,aAAa;GACX,OAAO;GACP,KAAK,KAAA,GAAW,KAAA,CAAS;EAC3B,EACF;;EAEA,SAAS,OAAa;GACpB,KAAK,KAAA,GAAW,KAAA,CAAS;GACzB,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,MAAM,QACpC,KAAK,GAAG;EACZ;;EAEA,SAAS,QAAiB;GACxB,IAAI,MACF,OAAO;GACT,IAAI,WAAW,IAAI,GAAG;IACpB,IAAI,YAAY,QAAQ,SACtB,OAAO;IACT,KAAK,MAAM,KAAK,MAAM,OAAO,WAAW,IAAI,GAAG,IAAI,CAAC;IACpD,IAAI,CAAC,SACH,OAAO;IACT,IAAI,CAAC,SACH,OAAO;IACT,UAAU;IAEV,IAAI;KACF,KAAK,MAAM,SAAS,YAAY,MAAM,EAAE,eAAe,KAAK,CAAC,GAC3D,IAAI,MAAM,YAAY,KAAK,CAAC,MAAM,KAAK,WAAW,GAAG,GACnD,QAAQ,KAAK,MAAM,MAAM,IAAI,CAAC;IAEpC,QACM,CAAC;IACP,OAAO;GACT;GACA,UAAU;GACV,IAAI,SAAS,QAAQ,IAAI;GACzB,OAAO,CAAC,WAAW,MAAM,KAAK,QAAQ,MAAM,MAAM,QAChD,SAAS,QAAQ,MAAM;GACzB,MAAM,OAAO,SAAS,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;GAC/C,IAAI,YAAY,UAAU,SACxB,OAAO;GACT,KAAK,QAAQ,KAAK,QAAQ,QAAQ,SAAS;IAEzC,IAAI,CAAC,QAAQ,KAAK,MAAM,OAAO,CAAC,CAAC,OAAO,MACtC,MAAM;GACV,GAAG,IAAI,CAAC;GAER,IAAI,WAAW,QAAQ,WAAW,KAAK,QAAQ,IAAI,CAAC,GAClD,OAAO,MAAM;GACf,OAAO,YAAY,KAAA;EACrB;EACA,OAAO,MAAM,IAAI,SAAS,KAAA;CAC5B;CAEA,MAAM,SAAS,KAAa,KAAa,cAA6B;EACpE,IAAI,CAAC,WAAW;GACd,MAAM,OAAO,UAAU,KAAK,GAAG;GAC/B,IAAI,MACF,SAAS,IAAI,KAAK,IAAI;GACxB;EACF;EACA,MAAM,UAAU,KAAK,KAAK,OAAO,SAAS;GACxC,IAAI,wBAAwB,IAAI,GAC9B,QAAQ,GAAG;EACf,SAAS;GACP,IAAI,SAAS,IAAI,GAAG,MAAM,SACxB,KAAK,GAAG;EACZ,CAAC;EACD,IAAI,SACF,SAAS,IAAI,KAAK,OAAO;CAC7B;CAEA,OAAO;EACL,OAAO,EAAE,MAAM,YAAY;GACzB,IAAI,QACF;GACF,MAAM,yBAAS,IAAI,IAAiD;GACpE,KAAK,MAAM,OAAO,MAChB,OAAO,IAAI,KAAK,OAAO;IAAE;IAAK,WAAW;GAAK,CAAC;GACjD,KAAK,MAAM,QAAQ,OACjB,OAAO,IAAI,KAAK,QAAQ;IAAE,KAAK;IAAM,WAAW;GAAM,CAAC;GACzD,KAAK,MAAM,OAAO,CAAC,GAAG,SAAS,KAAK,CAAC,GACnC,IAAI,CAAC,OAAO,IAAI,GAAG,GACjB,KAAK,GAAG;GAEZ,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,gBAAgB,QACtC,IAAI,CAAC,SAAS,IAAI,GAAG,GACnB,MAAM,KAAK,KAAK,SAAS;EAE/B;EACA,aAAa;GACX,SAAS;GACT,aAAa,KAAK;GAClB,QAAQ,MAAM;GACd,KAAK,MAAM,OAAO,CAAC,GAAG,SAAS,KAAK,CAAC,GACnC,KAAK,GAAG;EACZ;CACF;AACF;;;;;;;;;;;ACzRA,MAAM,cAAc;;AAEpB,MAAM,UAAU;AAEhB,SAAS,QAAQ,MAAsB;CACrC,IAAI;EACF,MAAM,QAAQ,SAAS,IAAI;EAC3B,OAAO,GAAG,MAAM,QAAQ,GAAG,MAAM;CACnC,QACM;EACJ,OAAO;CACT;AACF;;;;;;;;;;AAWA,SAAgB,iBAAiB,MAAc,UAAsB,UAAqD,CAAC,GAAe;CACxI,IAAI,QAAQ,QAAQ,IAAI;CACxB,IAAI;CACJ,IAAI;CACJ,IAAI,UAAU;CAEd,MAAM,cAAoB;EACxB,UAAU,KAAA;EACV,MAAM,MAAM,QAAQ,IAAI;EACxB,IAAI,QAAQ,OACV;EACF,QAAQ;EACR,SAAS;CACX;CAEA,MAAM,gBAAsB;EAC1B,aAAa,OAAO;EACpB,UAAU,WAAW,OAAO,WAAW;EACvC,QAAQ,QAAQ;CAClB;CACA,MAAM,YAAkB;EACtB,SAAS,MAAM;EACf,UAAU,KAAA;EACV,IAAI,SACF;EACF,IAAI;GACF,WAAW,QAAQ,SAAS,MAAA,CAAO,OAAO,UAAU;IAClD,QAAQ;IAER,IAAI,UAAU,UACZ,IAAI;GACR,CAAC;GACD,QAAQ,GAAG,eAAe,KAAA,CAAS;GACnC,QAAQ,MAAM;EAChB,QACM,CAEN;CACF;CAEA,IAAI;CAEJ,MAAM,OAAO,kBAAkB;EAC7B,IAAI,YAAY,KAAA,GACd,IAAI;EACN,IAAI,YAAY,KAAA,GACd,MAAM;CACV,GAAG,QAAQ,UAAU,OAAO;CAC5B,KAAK,QAAQ;CACb,aAAa;EACX,UAAU;EACV,aAAa,OAAO;EACpB,cAAc,IAAI;EAClB,SAAS,MAAM;EACf,UAAU,KAAA;CACZ;AACF;;;;ACrEA,MAAM,wBAAwB;AAwD9B,SAASC,aAAW,OAAsC;CACxD,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,IAAI,KAAA;AAC1I;;AAGA,SAAS,SAAS,IAAkC;CAClD,IAAI,GAAG,OAAO,UACZ,OAAO;CACT,MAAM,QAAQ,GAAG;CACjB,IAAI,MAAM,OAAM,MAAK,UAAU,CAAC,GAC9B,OAAO;EAAE,IAAI;EAAU,OAAQ,MAA6B,KAAI,OAAM,EAAE,MAAM,EAAE,KAAK,EAAE;CAAE;CAC3F,OAAO;EACL,IAAI;EACJ,OAAQ,MAAiE,KAAI,OAAM;GAAE,MAAM,EAAE;GAAM,UAAU,EAAE;GAAU,MAAM,OAAO,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,QAAQ;EAAE,EAAE;CAC1K;AACF;;;;;;AAOA,SAAgB,wBAAwB,UAAoC,CAAC,GAAsB;CACjG,MAAM,MAAM,QAAQ,OAAO,KAAK;CAChC,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,0BAAU,IAAI,IAA4B;CAChD,MAAM,uBAAO,IAAI,IAA0B;CAC3C,MAAM,0BAAU,IAAI,IAA2B;CAC/C,MAAM,2BAAW,IAAI,IAA4B;CACjD,IAAI,MAAM;;CAEV,IAAI,SAAS;CACb,MAAM,cAAuB,SAAS,KAAK,IAAI,IAAI,GAAG,SAAS,CAAC;CAEhE,MAAM,QAAQ,MAAgB,WAA6B,KAAK,KAAK,MAAM;;CAG3E,MAAM,OAAU,UAAkB,SAA0B,QAAyC,aAA4B;EAC/H,MAAM,SAAS,KAAK,IAAI,QAAQ;EAChC,IAAI,CAAC,UAAU,CAAC,OAAO,IACrB,OAAO,QAAQ,QAAQ,QAAQ;EACjC,MAAM,YAAY,IAAI,EAAE;EACxB,OAAO,IAAI,SAAY,YAAY;GACjC,MAAM,QAAQ,iBAAiB;IAC7B,SAAS,OAAO,SAAS;IACzB,QAAQ,QAAQ;GAClB,GAAG,YAAY;GACf,MAAM,QAAQ;GACd,SAAS,IAAI,WAAW;IACtB,MAAM,OAAO;IACb,UAAU,QAAQ;KAChB,aAAa,KAAK;KAClB,SAAS,OAAO,SAAS;KACzB,QAAQ,OAAO,GAAG,KAAK,QAAQ;IACjC;GACF,CAAC;GACD,KAAK,OAAO,MAAM;IAAE,MAAM;IAAa;IAAW;GAAQ,CAAC;EAC7D,CAAC;CACH;CACA,MAAM,aAAa,QAAuC,OAAO,QAAQ,YAAY,MAAM,KAAA;CAE3F,MAAM,mBAAmC,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAI,OAAM;EACvE,IAAI,EAAE;EACN,SAAS,EAAE,YAAY,EAAE,KAAK,WAAW,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC;EAC9D,cAAc,EAAE;EAChB,SAAS,EAAE;CACb,EAAE;CA+CF,OAAO;EACL,SAAS,MAAM,MAAM;GACnB,IAAI,SAAS,QAAQ,IAAI,IAAI;GAC7B,IAAI,CAAC,QAAQ;IACX,SAAS;KAAE,IAAI,IAAI,EAAE;KAAO;KAAM,cAAc,MAAM;KAAG,SAAS;KAAM,IAAI;IAAK;IACjF,QAAQ,IAAI,MAAM,MAAM;IACxB,KAAK,IAAI,OAAO,IAAI,MAAM;GAC5B;GACA,MAAM,UAAUA,aAAW,KAAK,OAAO;GACvC,IAAI,SACF,OAAO,UAAU;GACnB,IAAI,KAAK,WAAW,MAClB,OAAO,eAAe,MAAM;GAC9B,IAAI,OAAO,KAAK,YAAY,WAC1B,OAAO,UAAU,KAAK;GACxB,IAAI,OAAO,KAAK,OAAO,WACrB,OAAO,KAAK,KAAK;EACrB;EACA,OAAO,MAAM;GACX,MAAM,SAAS,QAAQ,IAAI,IAAI;GAC/B,IAAI,CAAC,QACH;GACF,QAAQ,OAAO,IAAI;GACnB,KAAK,OAAO,OAAO,EAAE;GACrB,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,GAAG,OAAO,GAAG;IACxC,IAAI,QAAQ,SAAS,MACnB;IACF,QAAQ,OAAO,EAAE;IACjB,QAAQ,OAAO,IAAI,UAAU,kCAAkC,CAAC;GAClE;GACA,KAAK,MAAM,WAAW,CAAC,GAAG,SAAS,OAAO,CAAC,GACzC,IAAI,QAAQ,SAAS,MACnB,QAAQ,QAAQ,KAAA,CAAS;EAE/B;EACA,SAAS;EACT,SAAQ,aAAY,KAAK,IAAI,QAAQ,CAAC,EAAE;EACxC,OAAM,SAAQ,QAAQ,IAAI,IAAI,CAAC,EAAE;EACjC,YAAA;GAlFA,SAAS;GACT,OAAO,UAAU,SAAS,QAAQ;IAChC,MAAM,SAAS,KAAK,IAAI,QAAQ;IAChC,IAAI,CAAC,QACH,OAAO,QAAQ,OAAO,IAAI,UAAU,QAAQ,IAAI,CAAC;IACnD,MAAM,WAAW,IAAI,EAAE;IACvB,OAAO,IAAI,SAAkB,SAAS,WAAW;KAC/C,MAAM,gBAAsB;MAC1B,IAAI,CAAC,QAAQ,OAAO,QAAQ,GAC1B;MACF,KAAK,OAAO,MAAM;OAAE,MAAM;OAAmB;MAAS,CAAC;KACzD;KACA,MAAM,aAAmB,IAAI,OAAO,oBAAoB,SAAS,OAAO;KACxE,QAAQ,IAAI,UAAU;MACpB,MAAM,OAAO;MACb,UAAU,WAAW;OACnB,KAAK;OACL,QAAQ,MAAM;MAChB;MACA,SAAS,UAAU;OACjB,KAAK;OACL,OAAO,KAAK;MACd;MACA,GAAI,IAAI,WAAW,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC;KACnD,CAAC;KACD,IAAI,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;KAC5D,KAAK,OAAO,MAAM;MAAE,MAAM;MAAa;MAAU,aAAa,IAAI;MAAa,GAAI,IAAI,YAAY,EAAE,WAAW,IAAI,UAAU,IAAI,CAAC;MAAI;KAAQ,CAAC;IAClJ,CAAC;GACH;EAsDS;EACT,cAAA;GAnDA,QAAQ,UAAU,YAAY,IAAI,UAAU;IAAE,IAAI;IAAS,GAAG;GAAQ,GAAG,WAAW,KAAK;GACzF,aAAa,UAAU,SAAS,IAAI,UAAU;IAAE,IAAI;IAAc,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;GAAG,IAAG,QAAOA,aAAW,GAAG,GAAG,CAAC,CAAsB;GAC7K,WAAW,UAAU,OAAO,IAAI,UAAU;IAAE,IAAI;IAAY;GAAG,GAAG,WAAW,KAAK;GAClF,WAAW,UAAU,IAAI,SAAS,IAAI,UAAU;IAAE,IAAI;IAAY,MAAM,SAAS,EAAE;IAAG,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;GAAG,GAAG,WAAW,KAAK;GAClK,SAAS,UAAU,iBAAiB;IAClC,MAAM,SAAS,KAAK,IAAI,QAAQ;IAChC,IAAI,QAAQ,IACV,KAAK,OAAO,MAAM;KAAE,MAAM;KAAa,SAAS;MAAE,IAAI;MAAU,GAAG;KAAa;IAAE,CAAC;GACvF;GACA,iBAAiB,UAAU,YAAY,IAAI,UAAU;IAAE,IAAI;IAAmB,GAAG;GAAQ,GAAG,WAAW,KAAK;EA0CjG;EACX,aAAa,MAAM,UAAU,QAAQ;GACnC,MAAM,UAAU,QAAQ,IAAI,QAAQ;GACpC,IAAI,CAAC,WAAW,QAAQ,SAAS,MAC/B,OAAO;GACT,QAAQ,OAAO,QAAQ;GACvB,QAAQ,QAAQ,MAAM;GACtB,OAAO;EACT;EACA,eAAe,MAAM,UAAU,KAAK,OAAO;GACzC,MAAM,UAAU,QAAQ,IAAI,QAAQ;GACpC,OAAO,WAAW,QAAQ,SAAS,OAAO,QAAQ,WAAW,KAAK,KAAK,IAAI,KAAA;EAC7E;EACA,MAAM,MAAM,WAAW,QAAQ;GAC7B,MAAM,UAAU,SAAS,IAAI,SAAS;GACtC,IAAI,CAAC,WAAW,QAAQ,SAAS,MAC/B,OAAO;GACT,QAAQ,QAAQ,MAAM;GACtB,OAAO;EACT;CACF;AACF;;;AC9MA,IAAM,qBAAN,cAAiC,MAAM;CACrC,cAAc;EACZ,MAAM,4BAA4B;EAClC,KAAK,OAAO;CACd;AACF;;;;;;;;AASA,SAAgB,gBAAgB,SAA4B,MAAkE;CAC5H,MAAM,CAAC,MAAM,GAAG,QAAQ;CACxB,IAAI,CAAC,MACH,OAAO,QAAQ,uBAAO,IAAI,MAAM,sBAAsB,CAAC;CACzD,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,SAAS,MAAM,MAAM;GAAE,QAAQ,KAAK;GAAQ,WAAW;GAAa,UAAU;EAAO,IAAI,OAAO,QAAQ,WAAW;GACjH,IAAI,SAAU,MAAgC,SAAS,aACrD,OAAO,OAAO,IAAI,mBAAmB,CAAC;GACxC,IAAI,SAAS,OAAQ,MAA6B,SAAS,UACzD,OAAO,OAAO,KAAK;GAErB,QAAQ;IAAE;IAAQ;IAAQ,UADb,QAAS,OAAQ,MAA6B,SAAS,WAAY,MAA2B,OAAO,IAAK;GAC9E,CAAC;EAC5C,CAAC;CACH,CAAC;AACH;;;;;;AAOA,SAAgB,mBAAmB,SAA4C;CAC7E,MAAM,0BAAU,IAAI,IAAqB;CACzC,IAAI,MAAM;CAEV,MAAM,WAAoC,QAAQ,OAAO,CAAC,MAAM;EAE9D,MAAM,QAAQ,KAAK,UAAU,KAAK,OAAO,UAAU,MAAM,KAAK,SAAS,KAAA;EACvE,IAAI,SAAS,SAAS,IAAI,EAAE;EAC5B,IAAI,gBAAgB,KAAK,iBAAiB;EAC1C,IAAI,OAAO;EACX,MAAM,QAAQ,MAAqC;GACjD,MAAM,OAAO,OAAO;GACpB,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,iCAAiC;GACnD,KAAK,KAAK;IAAE,MAAM;IAA+B;IAAQ;IAAe,MAAM;GAAE,CAAC;GACjF,OAAO;EACT;EACA,MAAM,OAAO,GAA6C,WAAiE;GACzH,MAAM,UAAU,IAAI,EAAE;GACtB,MAAM,OAAO,KAAK,EAAE,OAAO,CAAC;GAC5B,OAAO,IAAI,SAAS,SAAS,WAAW;IACtC,MAAM,gBAAsB;KAC1B,QAAQ,OAAO,OAAO;KACtB,OAAO,IAAI,mBAAmB,CAAC;IACjC;IACA,IAAI,QAAQ,SACV,OAAO,QAAQ;IACjB,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;IACzD,QAAQ,IAAI,SAAS;KACnB;KACA;KACA,UAAU,UAAU;MAClB,QAAQ,oBAAoB,SAAS,OAAO;MAC5C,QAAQ,OAAO,OAAO;MACtB,QAAQ,KAAK;KACf;IACF,CAAC;GACH,CAAC;EACH;EACA,MAAM,WAAW,OAAO,UAAwD;GAC9E,MAAM,MAAM,MAAM;GAClB,IAAI,QAAQ,KAAA,GACV,MAAM,IAAI,mBAAmB;GAC/B,OAAO;EACT;EAwBA,OAAO;GACL,MAAA;IAvBA,iBAAiB,YAAY;KAC3B,IAAI,CAAC,SAAS,MACZ,SAAS,IAAI,EAAE;KACjB,OAAO;KACP,gBAAgB,QAAQ;KACxB,OAAO;MACL,SAAQ,SAAQ,KAAK,KAAK;OAAE,MAAM;OAAQ,KAAK,KAAK;OAAK,GAAI,KAAK,eAAe,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;MAAG,CAAC;MAC5H,eAAc,SAAQ,KAAK,KAAK;OAAE,MAAM;OAAU,UAAU,KAAK;OAAU,iBAAiB,KAAK;OAAiB,GAAI,KAAK,qBAAqB,KAAA,IAAY,EAAE,kBAAkB,KAAK,iBAAiB,IAAI,CAAC;MAAG,CAAC;MAC/M,aAAY,YAAW,KAAK,KAAK;OAAE,MAAM;OAAY;MAAQ,CAAC;MAC9D,WAAU,WAAU,SAAS,KAAI,aAAY;OAAE,MAAM;OAAU;OAAS,SAAS,OAAO;OAAS,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;OAAI,GAAI,OAAO,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;MAAG,IAAI,QAAQ,MAAM,CAAC;MAC3O,WAAU,WAAU,KAAI,aAAY;OAAE,MAAM;OAAU;OAAS,SAAS,OAAO;OAAS,SAAS,OAAO,QAAQ,KAAI,OAAM;QAAE,IAAI,EAAE;QAAI,OAAO,EAAE;OAAM,EAAE;MAAE,IAAI,QAAQ,MAAM;MAC3K,GAAI,QAAQ,iBACR,CAAC,IACD;OACE,gBAAgB;OAChB,yBAAyB,SAAS,KAAI,aAAY;QAAE,MAAM;QAAe;OAAQ,IAAI,QAAQ,MAAM,CAAC;MACtG;MACJ,QAAQ,QAAQ;KAClB;IACF;IACA,YAAY,QAAQ,cAAc;GAG/B;GACH,IAAI,SAAS;IAAE,OAAO;GAAO;GAC7B,SAAS,YAAY;IAEnB,OAAG,CAAC,EAAE,KAAK;KAAE,MAAM;KAA+B;KAAQ;KAAe,MAAM;MAAE,MAAM;MAAQ,IAAI,QAAQ;MAAI,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;KAAG;IAAE,CAAC;GACvK;EACF;CACF;CAEA,OAAO;EACL;EACA,QAAQ,MAAM,QAAQ,SAAS,UAAU;GACvC,MAAM,IAAI,QAAQ,IAAI,OAAO;GAC7B,IAAI,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,WAAW,QACxC,OAAO;GACT,EAAE,QAAQ,KAAK;GACf,OAAO;EACT;EACA,UAAU,SAAS;GACjB,KAAK,MAAM,KAAK,CAAC,GAAG,QAAQ,OAAO,CAAC,GAClC,IAAI,EAAE,SAAS,MACb,EAAE,QAAQ,KAAA,CAAS;EAEzB;CACF;AACF;;;;;;;;;;;;;;;;;;;AChIA,SAAgB,YAAY,MAA8K;CACxM,MAAM,UAAU,KAAK,SAAS,QAAQ,SAAS,IAAI,KAAK,CAAC,CAAC,SAAS;CACnE,IAAI,CAAC,SACH,OAAO,CAAC;CACV,MAAM,UAAU,IAAI,IAAI,0BAA0B,KAAK,KAAK,KAAK,QAAQ,KAAK,QAAQ,CAAC,CAAC,KAAI,MAAK,EAAE,IAAI,CAAC;CACxG,MAAM,OAAO,IAAI,KAAK,KAAK,MAAM,WAAW,UAAU,KAAK,CAAC,EAAA,CAAG,QAAO,MAAK,CAAC,EAAE,YAAY,EAAE,QAAQ,KAAK,OAAO,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAI,MAAK,EAAE,IAAI,CAAC;CAC/I,MAAM,6BAAa,IAAI,IAA8B;CACrD,KAAK,MAAM,KAAK,KAAK,MAAM,WAAW,UAAU,KAAK,GAAG,KAAK,CAAC,GAC5D,IAAI,CAAC,WAAW,IAAI,EAAE,IAAI,GACxB,WAAW,IAAI,EAAE,MAAM,CAAC;CAE5B,MAAM,QAAQ,kBAAkB,EAAE,SAAS,KAAK,QAAQ,CAAC;CACzD,MAAM,MAAuB,CAAC;CAC9B,KAAK,MAAM,UAAU,QAAQ,OAAO;EAClC,MAAM,UAAU,WAAW,IAAI,OAAO,IAAI;EAC1C,WAAW,OAAO,OAAO,IAAI;EAC7B,MAAM,QAAQ,SAAS,SAAS,MAAM,OAAO,KAAK,EAAE,MAAM,KAAI,MAAK,EAAE,IAAI,KAAK,CAAC;EAC/E,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,SAC3B,IAAI,KAAK;GAAE,MAAM,OAAO;GAAM,QAAQ;GAAa;EAAM,CAAC;OACvD,IAAI,QAAQ,OAAO,OAAO,IAAI,CAAC,EAAE,SAAS,YAAY,CAAC,QAAQ,IAAI,OAAO,IAAI,GACjF,IAAI,KAAK;GAAE,MAAM,OAAO;GAAM,QAAQ;GAAY;EAAM,CAAC;CAC7D;CACA,KAAK,MAAM,KAAK,WAAW,OAAO,GAChC,IAAI,KAAK;EAAE,MAAM,EAAE;EAAM,QAAQ;EAAa,OAAO,EAAE;EAAO,GAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;EAAI,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;CAAG,CAAC;CAChJ,OAAO;AACT;;;;;;;;;;;;;AAcA,eAAsB,WACpB,KACA,kBACA,KACA,GAAG,MACiC;CACpC,MAAM,CAAC,QAAQ,MAAM,MAAM,QAAQ;CACnC,MAAM,SAAS,kBAAkB,OAAO,MAAM;CAC9C,IAAI,QACF,OAAO,iBAAkB,MAAM,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC,GAAG,IAAI;CACzE,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,uDAAuD,OAAO,WAAW,KAAK,GAAG;CACnG,MAAM,SAAS,MAAM,IAAI,SAAS,KAAK,QAAQ,MAAM,QAAQ,CAAC,GAAG;EAAE,GAAI,KAAK,cAAc,KAAA,IAAY,EAAE,SAAS,KAAK,UAAU,IAAI,CAAC;EAAI,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;CAAG,CAAC;CAC1L,OAAO;EAAE,SAAS,OAAO;EAAM,SAAS,OAAO;CAAQ;AACzD;;;;;;;;;;AAmBA,SAAgB,8BAA8B,SAAkG,SAAS,KAAiC;CACxL,MAAM,uBAAO,IAAI,IAAyG;CAC1H,MAAM,WAAW,QAAsB;EACrC,MAAM,QAAQ,KAAK,IAAI,GAAG;EAC1B,IAAI,CAAC,SAAS,EAAE,MAAM,OAAO,GAC3B;EACF,MAAM,QAAQ,iBAAiB;GAC7B,IAAI,KAAK,IAAI,GAAG,MAAM,OACpB;GACF,KAAK,OAAO,GAAG;GACf,MAAW,WAAW,MAAK,MAAK,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAClE,GAAG,MAAM;EACT,MAAM,MAAM,QAAQ;CACtB;CACA,OAAO;EACL,MAAM,OAAO,KAAK,QAAQ,MAAM,MAAM,SAAS;GAC7C,MAAM,OAAO,QAAQ;GACrB,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,+DAA+D,OAAO,KAAK,GAAG;GAChG,MAAM,MAAM,GAAG,IAAI,QAAQ,KAAK,UAAU,MAAM;GAChD,IAAI,QAAQ,KAAK,IAAI,GAAG;GACxB,IAAI,CAAC,OAAO;IACV,MAAM,aAAa,KAAK,CAAC,MAAM,GAAG,GAAG;IACrC,MAAM,UAAU;KAAE;KAAY,MAAM;IAAE;IACtC,QAAQ;IACR,KAAK,IAAI,KAAK,OAAO;IACrB,WAAW,YAAY;KACrB,IAAI,KAAK,IAAI,GAAG,MAAM,SACpB,KAAK,OAAO,GAAG;IACnB,CAAC;GACH;GACA,aAAa,MAAM,KAAK;GACxB,MAAM;GACN,IAAI;IAEF,MAAM,OAAM,MADa,MAAM,WAAA,CACR,MAAM,OAAO,OAAO,KAAK,GAAG;IACnD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,eAAe,OAAO,KAAK,oBAAoB,KAAK,sDAAsD;IAC5H,MAAM,WAAW,KAAK,cAAc,KAAA,IAAY,YAAY,QAAQ,KAAK,SAAS,IAAI,KAAA;IACtF,MAAM,SAAS,YAAY,KAAK,SAAS,YAAY,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,IAAI,YAAY,KAAK;IACrG,MAAM,MAAM;KAAE,QAAQ;KAAa,QAAQ,WAAW;KAAG,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;IAAG;IACvF,IAAI;KACF,OAAO;MAAE,SAAS,iBAAiB,MAAM,IAAI,QAAQ,MAAM,GAAG,CAAC;MAAG,SAAS;KAAM;IACnF,SACO,KAAK;KACV,OAAO;MAAE,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;MAAG,SAAS;KAAK;IACpF;GACF,UACQ;IACN,QAAQ,GAAG;GACb;EACF;EACA,SAAS,YAAY;GACnB,MAAM,UAAU,CAAC,GAAG,KAAK,OAAO,CAAC;GACjC,KAAK,MAAM;GACX,MAAM,QAAQ,IAAI,QAAQ,IAAI,OAAO,MAAM;IACzC,aAAa,EAAE,KAAK;IACpB,MAAM,EAAE,WAAW,MAAK,MAAK,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GAC/D,CAAC,CAAC;EACJ;CACF;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,cACd,WACA,cACA,eACA,QAA8B,YAAwB,GACzC;CACb,MAAM,gBAA6B;EACjC,MAAM,MAAM,UAAU;EACtB,MAAM,SAAS,uBAAuB,aAAa,GAAG,MAAK,QAAO,cAAc,KAAK,GAAkB,CAAC;EACxG,OAAO,cAAc;GAAE,WAAW,CAAC;GAAG;GAAQ;EAAM,CAAC,CAAC,CAAC,OAAO,KAAA,CAAS;CACzE;CACA,MAAM,WAAW,SAAgB,SAAkB,SAAS,KAAA,IAAY,QAAQ,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC,SAAS,IAAI;CACpH,OAAO,eAAe,QAAQ,aAAa,EAAE,WAAW,QAAQ,CAAC,CAAC,UAAU,CAAC;CAC7E,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,oBAAoB,MAAsC,KAAa,WAA4D;CACjJ,IAAI,CAAC,aAAa,CAAC,MACjB,OAAO,EAAE,IAAI;CACf,OAAO;EACL;EACA,OAAO,UAAU;GACf,KAAU,WAAW,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAChE;EACA,eAAe,OAAO,MAAM,SAAS;GACnC,MAAM,UAAU,KAAK,KAAK;GAC1B,IAAI,CAAC,SACH;GAEF,MAAM,UAAU,MAAM,YAAY,QAAQ,KAAK,MAAM;GACrD,MAAM,KAAK,YAAY,WAAW,CAAC;IAAE,IAAI,WAAW;IAAG,MAAM;IAAQ,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;IAAQ,CAAC;IAAG,WAAW,KAAK,IAAI;IAAG,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAAG,CAAC,CAAC;EAC1L;CACF;AACF;;;;ACrNA,MAAM,sBAAsB;AAE5B,MAAM,oBAAsD;CAC1D,aAAa;CACb,cAAc;CACd,cAAc;CACd,aAAa;AACf;;AA4BA,SAAS,UAAU,SAA+B,MAAsC;CACtF,MAAM,MAAM,KAAK,UAAU;CAC3B,MAAM,UAAU,kBAAkB,MAAK,QAAO,KAAK,cAAc,KAAK,GAAkB,CAAC;CACzF,MAAM,UAAU,QAAQ,SAAQ,MAAK,EAAE,OAAO,OAAO,KAAI,WAAU;EAAE,UAAU,EAAE;EAAU,QAAQ,EAAE;EAAQ;CAAM,EAAE,CAAC;CACtH,IAAI,QAAQ,WAAW,GACrB,MAAM,IAAI,MAAM,0HAA0H;CAC5I,MAAM,QAAQ,YAAoB,YAA6C,QAAQ,MAAK,MAAK,EAAE,aAAa,cAAc,EAAE,MAAM,OAAO,OAAO;CACpJ,IAAI,QAAQ,OAAO;EACjB,MAAM,QAAQ,KAAK,QAAQ,MAAM,YAAY,QAAQ,MAAM,OAAO;EAClE,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,mCAAmC,QAAQ,MAAM,WAAW,GAAG,QAAQ,MAAM,QAAQ,gBAAgB,QAAQ,KAAI,MAAK,GAAG,EAAE,SAAS,GAAG,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG;EACnL,OAAO;CACT;CACA,MAAM,aAAa,kBAAkB,KAAK,WAAW,CAAC;CACtD,MAAM,QAAQ,QAAQ;CACtB,QAAQ,cAAc,KAAK,WAAW,aAAa,WAAW,OAAO,MAAM,KAAK,MAAM,UAAU,MAAM,OAAO,YAAY,KAAK,QAAQ;AACxI;;AAGA,eAAe,cAAc,KAA6B,MAAkC;CAC1F,IAAI,EAAE,UAAU,MACd,OAAO;EAAE,WAAW,IAAI;EAAU,MAAM,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,QAAQ;CAAE;CACnF,MAAM,OAAO,WAAW,IAAI,IAAI,IAAI,IAAI,OAAO,QAAQ,MAAM,IAAI,IAAI;CACrE,MAAM,YAAY,kBAAkB,IAAI;CACxC,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,8BAA8B,IAAI,KAAK,uCAAuC;CAChG,KAAK,MAAM,KAAK,IAAI,EAAA,CAAG,OAAO,qBAC5B,MAAM,IAAI,MAAM,8BAA8B,IAAI,KAAK,YAAY,oBAAoB,OAAO;CAChG,OAAO;EAAE;EAAW,OAAO,MAAM,SAAS,IAAI,EAAA,CAAG,SAAS,QAAQ;CAAE;AACtE;;AAGA,SAAS,OAAO,QAAgB,KAAmB;CACjD,MAAM,OAAO,OAAO,YAAY,CAAC,CAAC,QAAQ,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK;CACzG,MAAM,OAAO,MAAsB,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CAC5D,MAAM,QAAQ,GAAG,IAAI,YAAY,IAAI,IAAI,IAAI,SAAS,IAAI,CAAC,IAAI,IAAI,IAAI,QAAQ,CAAC,EAAE,GAAG;EAAC,IAAI,SAAS;EAAG,IAAI,WAAW;EAAG,IAAI,WAAW;CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK;CAC5L,OAAO,GAAG,kBAAkB,GAAG,KAAK,GAAG;AACzC;;;;;;;AAQA,SAAgB,oBAAoB,MAA6D;;CAE/F,MAAM,aAAa,OAAO,YAAgF;EACxG,MAAM,YAAY,QAAQ,MAAM,aAAa,KAAK,QAAQ,QAAQ,CAAC,EAAE,YAAY,CAAC,EAAE;EACpF,IAAI,CAAC,WACH,OAAO,EAAE,KAAK,KAAK,OAAO;EAG5B,OAAO;GAAE,KAAK,OAFE,KAAK,QAAQ,eAAe,EAAA,EACjB,MAAM,QAAQ,WAAW,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,MAAK,MAAK,EAAE,WAAW,KAAA,CAAS,KACjF,KAAK;GAAQ;EAAU;CAC9C;CAEA,MAAM,SAAS,OAAO,aAA6C;EACjE,IAAI,KAAK,gBAAgB;GACvB,MAAM,KAAK,eAAe,QAAQ;GAClC;EACF;EACA,MAAM,QAAQ,KAAK,QAAQ,QAAQ,CAAC,EAAE,YAAY;EAElD,OADc,OAAO,UAAU,OAAO,MAAM,gBAAgB,KAAK,MAAM,KAAK,EAAA,GAC9D,QAAQ;CACxB;CAEA,OAAO,OAAO,YAA0C;EACtD,MAAM,SAAS,UAAU,SAAS,IAAI;EACtC,IAAI,QAAQ,WAAW,SAAS,KAAK,CAAC,OAAO,MAAM,MAAM,SAAS,OAAO,GACvE,MAAM,IAAI,MAAM,mBAAmB,OAAO,SAAS,GAAG,OAAO,MAAM,GAAG,gCAAgC;EACxG,MAAM,SAAS,QAAQ,OAAO,MAAM,WAAW,OAAO,IAAI,KAAA;EAC1D,MAAM,aAAa,MAAM,QAAQ,IAAI,QAAQ,WAAW,KAAI,QAAO,cAAc,KAAK,QAAQ,OAAO,KAAK,MAAM,CAAC,CAAC;EAClH,MAAM,WAAW,MAAM,OAAO,OAAO,SAAS;GAC5C,OAAO,OAAO,MAAM;GACpB,QAAQ,QAAQ;GAChB,GAAI,WAAW,SAAS,IAAI,EAAE,WAAW,IAAI,CAAC;GAC9C,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAgC,IAAI,CAAC;GACtF,OAAO,QAAQ;EACjB,GAAG,QAAQ,MAAM;EACjB,MAAM,SAAS,SAAS,OAAO,MAAM,GAAG,QAAQ,CAAC;EACjD,MAAM,SAA8B;GAClC,QAAQ,OAAO,KAAI,WAAU;IAAE,UAAU,MAAM;IAAW,MAAM,IAAI,WAAW,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;GAAE,EAAE;GACpH,YAAY,OAAO;GACnB,SAAS,SAAS,SAAS,OAAO,MAAM;GACxC,GAAI,SAAS,YAAY,KAAA,IAAY,EAAE,SAAS,SAAS,QAAQ,IAAI,CAAC;EACxE;EACA,IAAI,CAAC,QACH,OAAO;EACT,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,OAAO,OAAO,QAAQ,QAAQ,GAAG;EACvC,KAAK,MAAM,CAAC,GAAG,UAAU,OAAO,QAAQ,GAAG;GACzC,MAAM,MAAM,GAAG,OAAO,OAAO,SAAS,IAAI,IAAI,IAAI,MAAM,GAAG,GAAG,kBAAkB,MAAM,cAAc;GACpG,MAAM,OAAO,KAAK,OAAO,KAAK,GAAG;GACjC,MAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;GAC9C,MAAM,UAAU,MAAM,OAAO,OAAO,EAAE,CAAE,IAAI;GAC5C,MAAM,OAAO;IACX,QAAQ,QAAQ;IAChB,UAAU,OAAO;IACjB,OAAO,OAAO;IACd,WAAW,QAAQ;IACnB,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;IAClE,GAAI,SAAS,YAAY,KAAA,IAAY,EAAE,SAAS,SAAS,UAAU,OAAO,OAAO,IAAI,CAAC;IACtF,WAAW,IAAI,YAAY;GAC7B;GACA,MAAM,UAAU,GAAG,KAAK,QAAQ,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,GAAG;GACpE,OAAO,OAAO,EAAE,CAAE,OAAO;GACzB,IAAI,OAAO,WAAW;IACpB,MAAM,OAAO,oBAAoB,MAAM,IAAI;IAC3C,MAAM,KAAK,KAAK,IAAI;IACpB,MAAM,OAAO;KACX,IAAI,WAAW;KACf,WAAW,OAAO;KAClB,MAAM;KACN,KAAK,QAAQ;KACb,OAAO;KACP,MAAM,EAAE,MAAM,OAAO,GAAG,KAAK,MAAM,GAAG,KAAK,WAAW,MAAM,UAAU;KACtE,WAAW;KACX,WAAW;IACb,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GAC1B;EACF;EACA,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;ACzKA,MAAa,gCAAgC;AA6B7C,SAAS,MAAM,KAA6B;CAC1C,IAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GACtD,OAAO,CAAC;CACV,MAAM,MAAqB,CAAC;CAC5B,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,GAA8B,GACvE,IAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAC/D,IAAI,OAAO,EAAE,GAAI,OAA2B;CAEhD,OAAO;AACT;;;;;;AAOA,SAAgB,2BAA2B,UAAuC,CAAC,GAAyB;CAC1G,MAAM,wBAAQ,IAAI,IAA2B;CAC7C,MAAM,0BAAU,IAAI,IAA2B;CAC/C,MAAM,0BAAU,IAAI,IAAsB;CAC1C,MAAM,4BAAY,IAAI,IAAmC;CACzD,MAAM,UAAU,MAAc,UAAyB,QAAQ,UAAU,MAAM,KAAK;CACpF,MAAM,SAAY,SAA2B;EAC3C,QAAQ,IAAI,IAAI;EAChB,KAAU,cAAc,QAAQ,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CACrE;CAEA,MAAM,WAAW,cAA4B;EAC3C,IAAI,CAAC,QAAQ,QAAQ,QAAQ,IAAI,SAAS,GACxC;EACF,MAAM,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,aAAa;GACtD,MAAM,SAAS,MAAM,WAAW,8BAA8B;GAE9D,MAAM,UAAU,MAAM,IAAI,SAAS,KAAK,CAAC;GACzC,MAAM,SAAwB,EAAE,GAAG,OAAO;GAC1C,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,OAAO,GAChD,OAAO,OAAO;IAAE,GAAG,OAAO;IAAM,GAAG;GAAO;GAC5C,MAAM,IAAI,WAAW,MAAM;GAC3B,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,GAClC,KAAK,MAAM,YAAY,CAAC,GAAG,SAAS,GAClC,IAAI;IACF,SAAS,GAAG;GACd,QACM,CAAC;EAGb,IAAG,UAAS,OAAO,gBAAgB,aAAa,KAAK,CAAC;EACtD,QAAQ,IAAI,WAAW,IAAI;EAC3B,MAAM,IAAI;CACZ;CAEA,OAAO;EACL,MAAM,WAAW,QAAQ;GACvB,MAAM,SAAS,MAAM,IAAI,SAAS;GAClC,IAAI,CAAC,QACH,QAAQ,SAAS;GACnB,OAAO,SAAS;EAClB;EACA,MAAM,WAAW,KAAK,KAAK,UAAU;GACnC,MAAM,SAAS,EAAE,GAAG,MAAM,IAAI,SAAS,EAAE;GACzC,MAAM,MAAM,EAAE,GAAG,OAAO,KAAK;GAC7B,IAAI,UAAU,KAAA,GACZ,OAAO,IAAI;QAEX,IAAI,OAAO;GACb,IAAI,OAAO,KAAK,GAAG,CAAC,CAAC,WAAW,GAC9B,OAAO,OAAO;QAEd,OAAO,OAAO;GAChB,MAAM,IAAI,WAAW,MAAM;GAC3B,IAAI,QAAQ,MAAM;IAEhB,MAAM,SAAS,QAAQ,IAAI,SAAS,KAAK,QAAQ,QAAQ;IACzD,IAAI,CAAC,QAAQ,IAAI,SAAS,GACxB,QAAQ,SAAS;IACnB,MAAM,QAAQ,QAAQ,IAAI,SAAS,KAAK,OAAA,CAAQ,WAAW;KACzD,MAAM,MAAM,MAAM,IAAI,SAAS,KAAK,CAAC;KACrC,OAAO,QAAQ,KAAM,WAAW,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,IAAI,MAAM,KAAA,CAAS;IAC/E,CAAC,CAAC,CAAC,OAAM,UAAS,OAAO,gBAAgB,aAAa,KAAK,CAAC;IAC5D,MAAM,IAAI;GACZ;EACF;EACA,YAAY,aAAa;GACvB,UAAU,IAAI,QAAQ;GACtB,aAAa;IACX,UAAU,OAAO,QAAQ;GAC3B;EACF;EACA,SAAS,cAAc;GACrB,MAAM,OAAO,SAAS;GACtB,QAAQ,OAAO,SAAS;EAC1B;EACA,MAAM,YAAY;GAChB,OAAO,QAAQ,OAAO,GACpB,MAAM,QAAQ,WAAW,CAAC,GAAG,OAAO,CAAC;EACzC;CACF;AACF;;;;AC9GA,MAAa,0BAA0B;;AAGvC,MAAa,wBAAwB;AA4BrC,SAAS,SAAS,MAAmB;CACnC,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,CAAC;CACV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;EACpD,OAAO,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,IAAI,SAAgB,CAAC;CAC3F,QACM;EACJ,OAAO,CAAC;CACV;AACF;;;;;;;AAQA,SAAgB,mBAAmB,aAAqB,KAAqB;CAC3E,OAAO,GAAG,0BAA0B,YAAY,GAAG;AACrD;;;;;;AAOA,SAAgB,yBAAyB,SAAwD;CAC/F,MAAM,4BAAY,IAAI,IAA6B;CACnD,MAAM,WAAW,QAAQ,YAAY,2BAA2B;CAChE,MAAM,cAAc,QAAQ,aAAa,KAAK,QAAQ,YAAY,qBAAqB,IAAI,KAAA;CAC3F,IAAI;CACJ,IAAI;CACJ,MAAM,gBAAgB,QAA+D;EACnF,IAAI,CAAC,QAAQ,aACX,OAAO,KAAA;EACT,gBAAgB,QAAQ,YAAY;EACpC,MAAM,SAAS,YAAY,OAAO,GAAG;EACrC,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA;CACnD;CAEA,MAAM,mBAAyB,YAAY,cAAc,SAAS,WAAW,IAAI,CAAC;CAClF,MAAM,WAAW,QAA+D;EAC9E,MAAM,MAAM,QAAQ,aAAa,CAAC,CAAC;EACnC,OAAO,OAAO,OAAO,OAAO,KAAK,GAAG,IAAI,IAAI,OAAO,KAAA;CACrD;CACA,MAAM,UAAU,QAAsB;EACpC,KAAK,MAAM,YAAY,CAAC,GAAG,UAAU,IAAI,GAAG,KAAK,CAAC,CAAC,GACjD,IAAI;GACF,SAAS;EACX,QACM,CAAC;CAEX;CAEA,MAAM,eAAe,SAAS,UAAU,MAAM;CAC9C,MAAM,aAAa,KAAa,KAAa,UAAkD;EAC7F,MAAM,MAAM,EAAE,GAAG,QAAQ,aAAa,CAAC,CAAC,gBAAgB;EACxD,MAAM,MAAM,EAAE,GAAG,IAAI,KAAK;EAC1B,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,OAAO,KAAK,GAAG,GAChD;EACF,IAAI,UAAU,KAAA,GACZ,OAAO,IAAI;OAEX,IAAI,OAAO;EACb,IAAI,OAAO,KAAK,GAAG,CAAC,CAAC,WAAW,GAC9B,OAAO,IAAI;OAEX,IAAI,OAAO;EACb,QAAQ,cAAc,EAAE,iBAAiB,IAAI,CAAC;CAChD;CAEA,OAAO;EACL,OAAO,KAAa,OAAsB,cAAuB;GAC/D,QAAQ,OAAR;IACE,KAAK,QAAQ,OAAO,QAAQ,GAAG;IAC/B,KAAK,WAAW,OAAO,cAAc,WAAW,CAAC,CAAC,OAAO,KAAA;IACzD,KAAK,WAAW,OAAO,YAAY,SAAS,IAAI,WAAW,GAAG,IAAI,KAAA;IAClE,KAAK,UAAU,OAAO,aAAa,GAAG;IACtC,SAAS;GACX;EACF;EACA,QAAQ,KAAK,OAAO,KAAK,OAAuC,cAAc;GAC5E,IAAI,CAAC,gBAAgB,GAAG,GACtB,MAAM,IAAI,UAAU,uBAAuB,KAAK,UAAU,GAAG,GAAG;GAClE,IAAI,UAAU,QACZ,UAAU,KAAK,KAAK,UAAU,KAAA,IAAY,KAAA,IAAY,YAAY,KAAK,CAAC;QAErE,IAAI,UAAU,WAAW;IAC5B,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,mEAAmE;IACrF,MAAM,MAAM,EAAE,GAAG,SAAS,WAAW,EAAE;IACvC,MAAM,MAAM,EAAE,GAAG,IAAI,KAAK;IAC1B,IAAI,UAAU,KAAA,GACZ,OAAO,IAAI;SAEX,IAAI,OAAO;IACb,IAAI,OAAO;IACX,oBAAoB,aAAa,KAAK,UAAU;IAChD,UAAU;GACZ,OACK;IACH,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,mCAAmC;IACrD,SAAS,IAAI,WAAW,KAAK,KAAK,KAAK;GACzC;GACA,OAAO,GAAG;EACZ;EACA,YAAY,KAAK,aAAa;GAC5B,IAAI,MAAM,UAAU,IAAI,GAAG;GAC3B,IAAI,CAAC,KAAK;IACR,sBAAM,IAAI,IAAI;IACd,UAAU,IAAI,KAAK,GAAG;GACxB;GACA,IAAI,IAAI,QAAQ;GAChB,MAAM,MAAM;GACZ,aAAa;IACX,IAAI,OAAO,QAAQ;GACrB;EACF;EACA,SAAS;GACP,MAAM,KAAK,QAAQ;IACjB,MAAM,QAAQ,oBAAoB,QAAQ,SAAS,mBAAmB,KAAK,GAAG,CAAC;IAC/E,IAAI,OAAO,SAAS,YAAY,MAAM,OACpC,OAAO,MAAM;IAEf,MAAM,SAAS,QAAQ,GAAG,CAAC,GAAG;IAC9B,OAAO,OAAO,WAAW,YAAY,SAAS,SAAS,KAAA;GACzD;GACA,MAAM,KAAK,KAAK,UAAU;IACxB,qBAAqB,QAAQ,SAAS,mBAAmB,KAAK,GAAG,GAAG,UAAU,KAAA,IAAY,KAAA,IAAY;KAAE,MAAM;KAAU;IAAM,CAAC;IAC/H,UAAU,KAAK,KAAK,KAAA,CAAS;IAC7B,OAAO,GAAG;GACZ;EACF;EACA,eAAe;GACb,UAAU,KAAA;GACV,cAAc,KAAA;GACd,KAAK,MAAM,OAAO,UAAU,KAAK,GAC/B,OAAO,GAAG;EACd;EACA,SAAS;CACX;AACF;;;;;;;;ACjJA,SAAgB,qBAAqB,SAAgD;;CAEnF,MAAM,4BAAY,IAAI,IAAkD;CACxE,MAAM,2BAAW,IAAI,IAAuD;;CAE5E,MAAM,2BAAW,IAAI,IAAoB;CACzC,MAAM,YAAY,MAAc,MAAmB,QAAwB,GAAG,KAAK,QAAQ,KAAK,QAAQ;CACxG,MAAM,QAAQ,MAAc,MAAmB,QAAwB;EACrE,MAAM,IAAI,SAAS,MAAM,MAAM,GAAG;EAClC,MAAM,QAAQ,SAAS,IAAI,CAAC,KAAK,KAAK;EACtC,SAAS,IAAI,GAAG,IAAI;EACpB,OAAO;CACT;CAEA,MAAM,UAAU,MAAc,WAAgC;EAC5D,KAAK,MAAM,YAAY,CAAC,GAAG,UAAU,IAAI,IAAI,KAAK,CAAC,CAAC,GAClD,IAAI;GACF,SAAS,MAAM;EACjB,QACM,CAEN;CAEJ;CAEA,MAAM,YAAY,aAAiC,KAAsB,MAAmB,KAAa,OAAyB,aAA0D;EAC1L,MAAM;EACN,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,GAAI,IAAI,cAAc,KAAA,IAAY,EAAE,WAAW,IAAI,UAAU,IAAI,CAAC;EAClE,GAAI,gBAAgB,KAAA,KAAa,IAAI,UAAU,SAAS,EAAE,YAAY,IAAI,CAAC;EAC3E;EACA;EACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC;CACF;CAEA,MAAM,cAAc,gBAAmD;EACrE,MAAM,OAAO,SAAS,IAAI,eAAe,EAAE;EAC3C,IAAI,MACF,OAAO;EACT,MAAM,OAAO,sBAAsB;GACjC,MAAM,KAAK,QAAQ,SAAS,mBAAmB;GAC/C,GAAI,cAAc,EAAE,aAAa,KAAK,aAAa,QAAQ,QAAQ,mBAAmB,EAAE,IAAI,CAAC;GAC7F,OAAO;EACT,CAAC;EACD,MAAM,QAAQ,OAAO,KAAsB,MAAmB,KAAa,UAA6C;GACtH,IAAI,UAAU,KAAA,GACZ,MAAM,KAAK,OAAO,KAAK,MAAM,GAAG;QAEhC,MAAM,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK;GACvC,MAAM,UAAU,KAAK,KAAK,OAAO,GAAG,GAAG,MAAM,GAAG;GAChD,OAAO,KAAK,OAAO,GAAG,GAAG;IAAE;IAAM;IAAK;GAAM,CAAC;GAC7C,OAAO;EACT;EA8BA,MAAM,SAAS;GACb;GACA,MAAA;IA9BA,UAAU,KAAK;IACf,OAAM,QAAO,KAAK,KAAK,GAAG;IAC1B,MAAM,OAAO,KAAK,MAAM,KAAK,UAAU;KACrC,MAAM,UAAU,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK;KACjD,QAAQ,QAAQ,SAAS,aAAa,KAAK,MAAM,KAAK,OAAO,OAAO,CAAC;IACvE;IACA,QAAQ,OAAO,KAAK,MAAM,QAAQ;KAChC,MAAM,UAAU,MAAM,MAAM,KAAK,MAAM,KAAK,KAAA,CAAS;KACrD,QAAQ,QAAQ,SAAS,aAAa,KAAK,MAAM,KAAK,KAAA,GAAW,OAAO,CAAC;IAC3E;IACA,YAAY,KAAK,aAAyB;KACxC,MAAM,OAAO,KAAK,OAAO,GAAG;KAC5B,IAAI,MAAM,UAAU,IAAI,IAAI;KAC5B,IAAI,CAAC,KAAK;MACR,sBAAM,IAAI,IAAI;MACd,UAAU,IAAI,MAAM,GAAG;KACzB;KACA,IAAI,IAAI,QAAQ;KAChB,MAAM,MAAM;KACZ,OAAO,EACL,eAAe;MACb,IAAI,OAAO,QAAQ;MACnB,IAAI,IAAI,SAAS,KAAK,UAAU,IAAI,IAAI,MAAM,KAC5C,UAAU,OAAO,IAAI;KACzB,EACF;IACF;GAIG;GACH,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;GACrC,OAAO,QAAyB,KAAK,KAAK,GAAG;GAC7C,OAAO,OAAO,KAAsB,MAAmB,KAAa,UAA4B;IAC9F,MAAM,UAAU,MAAM,MAAM,KAAK,MAAM,KAAK,KAAK;IACjD,OAAO,SAAS,aAAa,KAAK,MAAM,KAAK,OAAO,OAAO;GAC7D;GACA,SAAS,OAAO,KAAsB,MAAmB,QAAgB;IAEvE,MAAM,WAAU,MADO,KAAK,KAAK,GAAG,EAAA,CACX;IACzB,MAAM,QAAQ,OAAO,OAAO,SAAS,GAAG,IAAI,QAAQ,OAAO,KAAA;IAC3D,OAAO;KAAE,SAAS,SAAS,IAAI,SAAS,KAAK,OAAO,GAAG,GAAG,MAAM,GAAG,CAAC,KAAK;KAAG,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;IAAG;GACxH;EACF;EACA,SAAS,IAAI,eAAe,IAAI,MAAM;EACtC,OAAO;CACT;CAEA,OAAO;EACL;EACA,aAAa;GACX,KAAK,MAAM,KAAK,SAAS,OAAO,GAC9B,EAAE,KAAK,MAAM;GACf,SAAS,MAAM;GACf,UAAU,MAAM;EAClB;CACF;AACF;;;;;;;;;;;;;;;;;;;;AChHA,MAAM,cAAc;;AAGpB,SAAS,cAAc,QAA+D;CACpF,IAAI,CAAC,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GAC5C,OAAO;CACT,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,GAC9C,IAAI;EACF,IAAI,WAAW,QAAQ,CAAC,CAAC,OAAO,aAAa,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,MACpE,OAAO;CACX,QACM;EACJ,OAAO;CACT;CAEF,OAAO;AACT;;;;;;;AAQA,SAAgB,oBAAoB,SAA8C;CAChF,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,0BAAU,IAAI,IAAoB;CACxC,MAAM,2BAAW,IAAI,IAAqC;;CAE1D,MAAM,2BAAW,IAAI,IAA4B;CAEjD,MAAM,QAAQ,WAAiC;EAC7C,QAAQ,OAAO,OAAO,IAAI;EAC1B,QAAQ,IAAI,OAAO,MAAM,OAAO,IAAI;EACpC,KAAK,MAAM,OAAO,QAAQ,KAAK,GAAG;GAChC,IAAI,QAAQ,QAAQ,aAClB;GACF,QAAQ,OAAO,GAAG;EACpB;CACF;CAEA,MAAM,SAAS,WAAmC;EAChD,IAAI,QAAQ,SAAS,SACnB,OAAO,GAAG,0BAA0B,GAAG,OAAO,KAAK;EACrD,MAAM,MAAM,KAAK,QAAQ,SAAS,GAAG,SAAS;EAC9C,MAAM,OAAO,KAAK,KAAK,GAAG,OAAO,KAAK,IAAI;EAG1C,IAAI,CAAC,WAAW,IAAI,GAAG;GACrB,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;GAClC,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,IAAI,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;GAC3E,cAAc,MAAM,OAAO,IAAI;GAC/B,WAAW,MAAM,IAAI;EACvB;EACA,OAAO,cAAc,IAAI,CAAC,CAAC;CAC7B;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW;GACxB,IAAI,CAAC,OAAO,KACV,OAAO,KAAA;GACT,MAAM,UAAU,iBAAiB,OAAO,KAAK,EAAE,IAAI,OAAO,GAAG,CAAC;GAC9D,IAAI,CAAC,QAAQ,IAAI;IACf,MAAM,SAAS,QAAQ,OAAO,QAAO,MAAK,EAAE,WAAW,KAAK,CAAC;IAC7D,OAAO,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,KAAA;GAC1C;GACA,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ,SAAS,IAAI,KAAK;GAChC,IAAI,SAAS,cAAc,MAAM,MAAM,GAAG;IACxC,KAAK,KAAK;IACV,OAAO;KAAE,MAAM,MAAM;KAAM,KAAK,MAAM,KAAK;IAAE;GAC/C;GACA,SAAS,OAAO,KAAK;GACrB,IAAI,UAAU,SAAS,IAAI,KAAK;GAChC,IAAI,CAAC,SAAS;IACZ,UAAU,QAAQ;KAAE;KAAO,aAAa,OAAO;KAAI,UAAU,QAAQ,SAAS;KAAG,KAAK,OAAO;IAAI,CAAC;IAClG,SAAS,IAAI,OAAO,OAAO;IAC3B,QAAa,cAAc,SAAS,OAAO,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GAC1E;GACA,IAAI;IACF,MAAM,SAAS,MAAM;IACrB,IAAI,OAAO,QAAQ;KACjB,SAAS,OAAO,KAAK;KACrB,SAAS,IAAI,OAAO,MAAM;KAC1B,KAAK,MAAM,OAAO,SAAS,KAAK,GAAG;MACjC,IAAI,SAAS,QAAQ,aACnB;MACF,SAAS,OAAO,GAAG;KACrB;IACF;IACA,KAAK,MAAM;IACX,OAAO;KAAE,MAAM,OAAO;KAAM,KAAK,MAAM,MAAM;IAAE;GACjD,SACO,KAAK;IACV,OAAO,EAAE,QAAQ,eAAe,gBAAgB,CAAC,GAAG,IAAI,MAAM,IAAI,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;GACvH;EACF;EACA,OAAM,SAAQ,QAAQ,IAAI,IAAI;CAChC;AACF;;;;ACsBA,SAAS,aAAa,IAA8B;CAClD,OAAO,GAAG,WAAW,CAAC,CAAC,KAAI,SAAQ,GAAG,KAAK,GAAG,GAAG,KAAK,OAAO,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,IAAI;AAC/F;;;;;AAMA,SAAS,eAAe,KAAa,IAAsB,SAAmD;CAC5G,IAAI,OAAO,aAAa,EAAE;CAC1B,aAAa;EACX,MAAM,MAAM,aAAa,EAAE;EAC3B,IAAI,QAAQ,MACV;EACF,OAAO;EACP,QAAQ;GAAE,MAAM;GAAsB;EAAI,CAAC;EAC3C,QAAQ;GAAE,MAAM;GAAmB,SAAS;EAAa,CAAC;CAC5D;AACF;;AAGA,SAAS,gBAAgB,IAA8B;CACrD,MAAM,EAAE,QAAQ,kBAAkB,GAAG,QAAQ,SAAS,UAAU,KAAK,CAAC,CAAC;CACvE,OAAO,KAAK,UAAU,CACpB,OAAO,MAAM,KAAI,MAAK;EAAC,EAAE;EAAY,EAAE;EAAI,EAAE;EAAM,EAAE;CAAO,CAAC,GAC7D,cAAc,MAAM,KAAI,MAAK;EAAC,EAAE;EAAY,EAAE;EAAS,EAAE;EAAI,EAAE;EAAM,EAAE;CAAO,CAAC,CACjF,CAAC;AACH;;;;;;;AAQA,SAAS,kBAAkB,IAAsB,SAAmD;CAClG,IAAI,OAAO,gBAAgB,EAAE;CAC7B,IAAI,SAAS;CACb,IAAI,UAAU;CACd,MAAM,MAAM,GAAG,QAAQ,SAAS,UAAU,gBAAgB;EACxD,IAAI,UAAU,SACZ;EACF,SAAS;EACT,qBAAqB;GACnB,SAAS;GACT,IAAI,SACF;GACF,MAAM,MAAM,gBAAgB,EAAE;GAC9B,IAAI,QAAQ,MACV;GACF,OAAO;GACP,QAAQ;IAAE,MAAM;IAAmB,SAAS;GAAS,CAAC;EACxD,CAAC;CACH,CAAC;CACD,aAAa;EACX,UAAU;EACV,IAAI;CACN;AACF;;AAGA,eAAe,UAAU,SAAyB,WAAiE;CACjH,MAAM,MAAoC,CAAC;CAC3C,MAAM,QAAQ,IAAI,QAAQ,QAAQ,WAAW,CAAC,CAAC,QAAO,SAAQ,KAAK,WAAW,QAAQ,CAAC,CAAC,IAAI,OAAO,SAAS;EAC1G,MAAM,MAAM,MAAM,UAAU,OAAO,WAAW,QAAQ,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAC9F,IAAI,OAAO,SAAS,KAClB,IAAI,KAAK,MAAM;CACnB,CAAC,CAAC;CACF,OAAO;AACT;;AAGA,SAAS,WAAW,IAAsB,IAA4B;CACpE,MAAM,SAAS,GAAG,IAAI,EAAE;CACxB,MAAM,MAAM,QAAQ,WAAA,EAA6C;CACjE,OAAO;EAAE;EAAI,GAAI,QAAQ,MAAM,MAAM,EAAE,KAAK,OAAO,MAAM,IAAI,IAAI,CAAC;EAAI,GAAI,OAAO,KAAA,IAAY,EAAE,GAAG,IAAI,CAAC;CAAG;AAC5G;;AAGA,SAAS,sBAAsB,IAAkC,MAA2C;CAC1G,MAAM,UAAU,IAAI,QAAQ,SAAS,IAAI,KAAK,CAAC,CAAC,SAAS;CACzD,OAAO,SAAS,OAAO,IAAI,CAAC,EAAE,SAAS,cAAc,QAAQ,IAAI,IAAI,IAAI,KAAA;AAC3E;;;;;;AAOA,eAAeC,mBAAiB,SAAyB,SAAuD;CAC9G,MAAM,EAAE,SAAS,aAAa;CAC9B,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,cAAc,MAAM,QAAQ,IAAI,QAAQ,WAAW,CAAC,CAAC,IAAI,OAAO,SAAsC;EAC1G,MAAM,SAAS,QAAQ,IAAI,KAAK,EAAE;EAClC,MAAM,MAAM,QAAQ,MAAM;EAC1B,IAAI,KACF,KAAK,IAAI,GAAG;EACd,MAAM,QAA4B;GAChC,IAAI,KAAK;GACT,aAAa,KAAK;GAClB,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;GAC9D,QAAQ,KAAK;GACb,QAAQ,KAAK;GACb,GAAI,KAAK,UAAU,KAAA,IAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;GACxD,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;EACvB;EACA,IAAI,KAAK,WAAW,YAAY,CAAC,KAC/B,OAAO;EACT,MAAM,MAAM,QAAQ;EACpB,MAAM,MAAM,iBAAiB,KAAK,EAAE,GAAI,KAAK,QAAQ,KAAA,IAAY,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,EAAG,CAAC,CAAC,CAAC;EAC3F,MAAM,KAAK,MAAM,QAAQ,OAAO,WAAW,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,SAAkB,EAAE,QAAQ,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE,EAAE;EACtJ,OAAO;GACL,GAAG;GACH,GAAI,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC;GAC/B,GAAI,MAAM,SAAS,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;GAC5C,GAAI,MAAM,YAAY,KAAK,EAAE,UAAU,GAAG,OAAO,IAAI,CAAC;EACxD;CACF,CAAC,CAAC;CACF,MAAM,UAAU,SAAS,SAAS,QAAO,MAAK,EAAE,UAAU,KAAA,MAAc,EAAE,QAAQ,KAAA,KAAa,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,OAA2B;EACxK,IAAI,EAAE;EACN,aAAa,EAAE,UAAU,eAAe,EAAE;EAC1C,QAAQ,EAAE;EACV,QAAQ;EACR,GAAI,EAAE,UAAU,KAAA,IAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;EAClD,GAAI,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;CAC9C,EAAE;CACF,OAAO,CAAC,GAAG,aAAa,GAAG,OAAO;AACpC;;AAGA,SAAS,kBAAkB,QAAgD;CACzE,MAAM,QAAQ,YAAwB;CACtC,MAAM,KAAK,mBAAkB,UAAS,OAAO,KAAK,kBAAkB,KAAK,CAAC;CAC1E,MAAM,KAAK,iBAAgB,UAAS,OAAO,KAAK,gBAAgB,KAAK,CAAC;CACtE,OAAO;AACT;;AAGA,eAAe,UAAU,SAAoC,QAAiB,QAAyB,QAAiC,WAAwF;CAC9N,MAAM,IAAK,UAAU,OAAO,WAAW,WAAW,SAAS,CAAC;CAC5D,MAAM,WAAW,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;CAC/D,MAAM,SAAS,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;CAGzD,MAAM,WAFQ,OAAO,EAAE,QAAQ,WAAW,QAAQ,MAAK,MAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,KAAA,MACvD,QAAQ,MAAK,MAAK,EAAE,QAAQ,QAAQ,IAAI,IAAI,QAAQ,CAAC,KAAK,QAAQ,GAAA,EACnE,QAAQ;CAC/B,IAAI,CAAC,QACH,OAAO;EAAE,IAAI;EAAO,OAAO;GAAE,MAAM,aAAa;GAAa,SAAS,0BAA0B,SAAS;EAAG;EAAG,MAAM;GAAE;GAAU;GAAQ,OAAO;EAAO;CAAE;CAC3J,MAAM,EAAE,KAAK,MAAM,GAAG,SAAS;CAC/B,OAAO,OAAO,KAAK,MAAM,QAAQ,QAAQ,SAAS;AACpD;;AAGA,SAAS,aAAa,SAAmC;CACvD,OAAO;EACL,YAAY,cAAc;GACxB,MAAM,MAAM,mBAAmB,QAAQ,CAAC,CAAC,CAAC;GAC1C,IAAI,OAAO,QAAQ,UACjB,OAAO;GACT,OAAO,MAAM,QAAQ,GAAG,IAAI,IAAI,QAAQ,MAAmB,OAAO,MAAM,QAAQ,IAAI,KAAA;EACtF;EACA,YAAW,aAAY,iBAAiB,gBAAgB,QAAQ,CAAC,GAAG,QAAQ;CAC9E;AACF;;AAGA,eAAe,gBAAgB,UAAuC,YAA6C;CACjH,MAAM,QAAQ,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,SAAQ,OAAM,SAAS,KAAI,OAAM,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC;AAC5F;AAEA,SAAS,QAAQ,SAAiC;CAChD,MAAM,IAAI,QAAQ,QAAQ;CAC1B,KAAK,MAAM,WAAW;EAAC,EAAE;EAAW,EAAE;EAAQ,EAAE;EAAQ,EAAE;EAAK,EAAE;EAAQ,EAAE;CAAK,GAC9E,QAAa,OAAO;AACxB;;;;;;AAOA,SAAgB,2BAA2B,SAA4D;CACrG,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,WAAW,QAAoB,SAA0B,SAAe;EAC5E,IAAI,QACF,OAAO,QAAQ,MAAM;OAErB,QAAQ,UAAU,MAAM;CAC5B;CACA,MAAM,UAAU,wBAAwB;CACxC,MAAM,UAAU,qBAAqB;EAAE,SAAS,QAAQ,QAAQ;EAAG,QAAQ,QAAQ;EAAQ;CAAQ,CAAC;CACpG,MAAM,QAAQ,mBAAmB,EAAE,gBAAgB,QAAQ,SAAS,SAAS,CAAC;CAC9E,MAAM,YAAY,oBAAoB;EACpC,gBAAgB,KAAK,QAAQ,QAAQ,GAAG,SAAS,cAAc;EAC/D,MAAM,QAAQ,SAAS,WAAW,UAAU;EAC5C,GAAI,QAAQ,YAAY,EAAE,SAAS,QAAQ,UAAU,IAAI,CAAC;CAC5D,CAAC;CACD,MAAM,eAAe,oCAAoC,UAAU,WAAW,OAAO;CACrF,MAAM,YAAY,2BAA2B,QAAQ,QAAQ,CAAC;CAC9D,MAAM,kBAAkB,2BAA2B;EACjD,GAAI,QAAQ,kBAAkB,EAAE,MAAM,QAAQ,gBAAgB,IAAI,CAAC;EACnE,MAAM,OAAO,WAAW,WAAW;GACjC,MAAM,UAAU,iBAAiB,WAAW,GAAG,gCAAgC,OAAO,CAAC;EACzF;EACA,UAAU,MAAM,UAAU,QAAQ,MAAM,kCAAkC,KAAK,IAAI,OAAO,KAAK,GAAG;CACpG,CAAC;CACD,MAAM,UAA4B,CAAC;CACnC,MAAM,2BAAW,IAAI,QAAuC;CAC5D,MAAM,gBAAgB,sBAAsB;EAAE,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;EAAI,aAAa,QAAQ;CAAQ,CAAC;;CAGrJ,MAAM,mBAAyC;EAC7C,MAAM,OAAO,QAAQ,QAAQ,CAAC,CAAC,QAAO,MAAK,EAAE,YAAY,KAAK,CAAC,CAAC,QAA0D,GAAG,MAAO,CAAC,KAAK,EAAE,eAAe,EAAE,eAAe,IAAI,GAAI,KAAA,CAAS;EAC7L,OAAO,OAAO,QAAQ,OAAO,KAAK,EAAE,IAAI,KAAA;CAC1C;CAEA,MAAM,mBAA+B,aAAa,QAAQ,OAAO;CAEjE,MAAM,gBAAgB,KAAa,cAAoE;EACrG,gBAAgB,SAAS;EACzB,mBAAmB,qBAAqB,mBAAmB,QAAQ,QAAQ,CAAC,CAAC;EAC7E,aAAa,SAAS,cAAc,oBAAoB,UAAU,KAAK,SAAS;EAChF,YAAY,OAAO,IAAI,EAAE,MAAM,gBAAgB;GAC7C,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,SAAS,KAAK,MAAK,MAAK,EAAE,OAAO,EAAE,GACjE,OAAO;GACT,MAAM,SAAS,SAAS,WAAW,IAAI,KAAK,OAAO,IAAI,SAAS,MAAM,KAAA,GAAW,KAAA,GAAW,EAAE;GAC9F,OAAO;EACT;EACA,aAAa,OAAO,MAAM,cAAc;GACtC,IAAI,aAAa,UACf,MAAM,SAAS,SAAS,WAAW,IAAI;EAC3C;CACF;CAEA,MAAM,aAAa,QAA0C,cAAuF,eAAqC,WAAqC;EAC5N,MAAM,SAAS,QAAQ;EACvB,OAAO;GACL,GAAI,SACA;IACE,UAAU,EAAE,gBAAgB,OAAO,eAAe;IAClD,WAAW,EAAE,SAAS,OAAO,QAAQ;IACrC,WAAW;KAAE,SAAS,OAAO;KAAS;IAAa;GACrD,IACA,CAAC;GACL,UAAU;IACR,QAAQ,oBAAoB,OAAO,CAAC,EAAE,aAAa,mBAAmB,QAAQ,cAAc,eAAe,aAAa;IACxH,OAAO,oBAAoB;KAAE,iBAAiB,OAAO,CAAC,EAAE,aAAa;KAAmB;KAAe,kBAAkB,QAAQ,aAAa,CAAC,CAAC;KAAY;KAAQ,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;KAAI,GAAI,QAAQ,iBAAiB,EAAE,gBAAgB,QAAQ,eAAe,IAAI,CAAC;IAAG,CAAC;IAClR,UAAU,UAAU;KAClB,MAAM,YAAY,OAAO,CAAC,EAAE,aAAa;KACzC,MAAM,OAAO,gBAAgB;MAC3B,MAAM,UAAU,oBAAoB,KAAA,GAAW,SAAS;MACxD,OAAO;OAAE,YAAY,QAAQ;OAAa,SAAS,QAAQ;MAAM;KACnE,EAAA,CAAG;KACH,IAAI,CAAC,OAAO,OAAO,WAAW,KAAK,UAAU,GAC3C,MAAM,IAAI,MAAM,0BAA0B,KAAK,WAAW,eAAe;KAC3E,OAAO;MAAE,GAAG;MAAM,UAAU,cAAc,WAAW,KAAK,UAAyB;KAAE;IACvF;GACF;EACF;CACF;CAEA,MAAM,WAAW,EAAE,KAAK,kBAAwE;EAC9F,IAAI;EACJ,IAAI;EACJ,MAAM,WAAgD,EAAE,MAAM,CAAC,EAAE;EACjE,MAAM,WAAW,yBAAyB;GACxC,cAAc,QAAQ;GACtB,eAAe,QAAQ;GACvB,SAAS,QAAQ,QAAQ;GACzB,GAAI,cAAc,EAAE,YAAY,KAAK,aAAa,QAAQ,MAAM,EAAE,IAAI,CAAC;GACvE,UAAU;GACV,mBAAmB;IACjB,MAAM,SAAS,qBAAqB;KAAE,YAAY,QAAQ,aAAa,QAAQ,QAAA,CAAS;KAAG;KAAK,QAAQ,QAAQ;IAAO,CAAC;IACxH,OAAO,0BAA0B,CAAC,OAAO,MAAM,OAAO,OAAO,CAAC;GAChE;EACF,CAAC;EACD,MAAM,SAAS,uBAAuB;EACtC,MAAM,gBAAgB,kBAAkB,MAAM;EAC9C,MAAM,gBAAgB,wBAAwB;EAC9C,MAAM,WAAW,mBAAmB;GAClC,wBAAwB,SAAS,QAAQ,SAAS;GAClD,gBAAgB,eAAe;IAC7B,MAAM,aAAa,SAAS,QAAQ,SAAS,UAAU,KAAK,CAAC,CAAC,SAAS,UAAU,IAAI,UAAU;IAC/F,OAAO,aAAa,gBAAgB,QAAQ,QAAQ,GAAG,UAAU,IAAI,KAAA;GACvE;GACA,kBAAkB;IAAE;IAAK,QAAQ,QAAQ;IAAQ,MAAM,QAAQ;GAAE;GACjE,KAAK;IACH,cAAc,YAAY;KAAE;KAAK;KAAS,QAAQ,QAAQ;KAAQ,UAAU,QAAQ,aAAa;KAAG,SAAS,QAAQ,QAAQ;KAAG,MAAM;IAAS,CAAC;IAChJ,OAAO,QAAQ,MAAM,MAAM,SAAS,WAAW,SAAS;KAAE,OAAO;KAAc,SAAQ,SAAQ,sBAAsB,SAAS,IAAI;IAAE,GAAG,KAAK,QAAQ,MAAM,MAAM,IAAI;GACtK;EACF,CAAC;EACD,MAAM,iBAAsC;GAC1C,MAAM,QAAQ;GACd,OAAO;IACL,SAAS,QAAQ,WAAW,WAAW,CAAC,CAAC;IACzC;IACA;IACA,kBAAkB,MAAM,QAAQ,UAAU,CAAC,CAAC;IAC5C,OAAO;KAAE,GAAG,OAAO;KAAM,iBAAiB;IAAK;IAC/C;IACA,UAAU,aAAa,KAAK,QAAQ;IACpC,QAAQ,WAAW;IACnB,SAAS,QAAQ;IACjB,UAAU,QAAQ;IAClB,cAAc,EAAE,UAAS,aAAY,QAAQ;KAAE,MAAM;KAAa;IAAS,CAAC,EAAE;IAC9E,MAAM,gBAAgB,QAAQ,cAAc,cAAc,eAAe,eAAe,GAAG;GAC7F;EACF;EACA,MAAM,SAAS,OAA0B,aAAoC;GAC3E,SAAS;GACT,UAAU,mBAAmB,KAAK;GAClC,uBAAuB,OAAO,MAAM;GACpC,IAAI,CAAC,SACH;GACF,MAAM,eAAe,cAAc,MAAM,KAAK;GAC9C,MAAM,KAAK;GACX,MAAM,QAAwB;IAAE;IAAK,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;IAAI,SAAS;IAAI,UAAU;IAAO;GAAS;GACrH,QAAQ,QAAQ,KAAK;GACrB,MAAM,EAAE,IAAI,UAAU,iBAAiB,GAAG;GAC1C,MAAM,QAAQ;IACZ,aAAa,GAAG,QAAQ,QAAQ;IAChC,kBAAkB,IAAI,OAAO;IAC7B,GAAG,WAAU,WAAU,QAAQ;KAAE,MAAM;KAAiB;KAAK;IAAO,CAAC,CAAC;IACtE,eAAe,KAAI,UAAS,QAAQ;KAAE,MAAM;KAAoB;KAAK,GAAG;IAAM,CAAC,CAAC;IAChF,SAAS,gBAAgB,QAAQ;KAAE,MAAM;KAAuB;IAAI,CAAC,CAAC;IACtE,SAAS,OAAO,gBAAgB,QAAQ;KAAE,MAAM;KAAqB;KAAK,GAAI,SAAS,OAAO,YAAY,IAAI,EAAE,MAAM,SAAS,OAAO,YAAY,EAAG,IAAI,CAAC;IAAG,CAAC,CAAC;IAC/J,aAAa,gBAAgB,QAAQ;KAAE,MAAM;KAA2B;IAAI,CAAC,CAAC;IAE9E,MAAM,UAAU,eAAe,KAAK,IAAI,OAAO,CAAC;GAClD;GACA,QAAQ,EAAE;GAEV,gBAAqB,CAAC,EAAE,GAAG,IAAI,IAAI,QAAQ,QAAQ,CAAC,CAAC,SAAQ,MAAK,EAAE,OAAO,CAAC,CAAC;GAC7E,UAAe,aAAa,GAAG,CAAC,CAAC,MAAM,SAAS;IAC9C,SAAS,OAAO,KAAK,KAAI,OAAM;KAAE,IAAI,EAAE;KAAM,OAAO,EAAE,eAAe,EAAE;KAAM,OAAO,EAAE;IAAK,EAAE;IAC7F,QAAQ;KAAE,MAAM;KAAuB;IAAI,CAAC;GAC9C,SAAS,KAAA,CAAS;GAClB,QAAQ;IAAE,MAAM;IAAiB;IAAK,QAAQ,EAAE,MAAM,QAAQ;GAAE,CAAC;GACjE,SAAS,IAAI,aAAa;IACxB,SAAS,OAAO,KAAK;IACrB,SAAS,QAAQ;IACjB,aAAa;IACb,KAAK,MAAM,QAAQ,OAAO,KAAK;IAC/B,MAAM,KAAK,QAAQ,QAAQ,KAAK;IAChC,IAAI,MAAM,GACR,QAAQ,OAAO,IAAI,CAAC;GACxB,CAAC;EACH;EACA,OAAO;GAAE,SAAS;GAAgB;EAAM;CAC1C;CAEA,OAAO;EACL,MAAM,QAAQ;EACd;EACA;EACA;EACA;EACA,UAAS,YAAW,UAAU,SAAS,SAAS;EAChD,UAAS,YAAWA,mBAAiB,SAAS,SAAS;EACvD,YAAY,UAAU;GACpB,SAAS,MAAM;EACjB;EACA,WAAW,SAAS;GAClB,WAAW;EACb;EACA,UAAU,QAAQ;GAChB,UAAU;EACZ;EACA;EACA,UAAS,aAAY,SAAS,IAAI,QAAQ,CAAC,GAAG;EAC9C,aAAY,QAAO,QAAQ,MAAK,MAAK,EAAE,QAAQ,GAAG;EAClD,gBAAgB,CAAC,GAAG,OAAO;EAC3B;EACA,gBAAgB,cAAc;GAC5B,gBAAgB,OAAO,SAAS;GAChC,KAAK,MAAM,KAAK,SACd,EAAE,QAAQ,QAAQ,GAAG,cAAc,SAAS;EAChD;EACA,gBAAe,cAAa,gBAAgB,QAAQ,KAAI,MAAK,EAAE,OAAO,GAAG,CAAC,SAAS,CAAC;EACpF,UAAU,QAAQ,QAAQ,QAAQ,cAAc,UAAU,SAAS,QAAQ,QAAQ,QAAQ,SAAS;EACpG,aAAa;GACX,QAAQ,MAAM;GACd,aAAkB,QAAQ;EAC5B;CACF;AACF;;;;;;;;;;AC/dA,SAAgB,yBAAyB,MAAqC;CAC5E,SAAS,OAA8B;EACrC,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,CAAC;EACV,IAAI;GACF,MAAM,SAAS,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;GACpD,OAAO,MAAM,QAAQ,MAAM,IAAK,SAAmC,CAAC;EACtE,QACM;GACJ,OAAO,CAAC;EACV;CACF;CAEA,SAAS,MAAM,MAAmC;EAChD,IAAI,KAAK,WAAW,GAAG;GACrB,IAAI;IACF,WAAW,IAAI;GACjB,QACM,CAEN;GACA;EACF;EAIA,oBAAoB,MAAM,MAAM,UAAU;CAC5C;CAEA,OAAO;EACL,OAAO,SAAS;GACd,MAAM,OAAO,KAAK,CAAC,CAAC,QAAO,MAAK,EAAE,OAAO,QAAQ,EAAE;GACnD,KAAK,KAAK,OAAO;GACjB,MAAM,IAAI;EACZ;EACA,OAAO,IAAI;GACT,MAAM,KAAK,CAAC,CAAC,QAAO,MAAK,EAAE,OAAO,EAAE,CAAC;EACvC;EACA,QAAQ;GACN,MAAM,CAAC,CAAC;EACV;EACA,OAAO;GACL,OAAO,KAAK;EACd;CACF;AACF;;;;;;AAqEA,SAAgB,wBAAwB,SAA6E;CAEnH,gCAAgC;CAChC,OAAO,sBAAsB,OAAO;AACtC;;;;;;;AAQA,eAAsB,sBAAsB,SAA6D;CACvG,MAAM,EAAE,WAAW;CACnB,MAAM,SAAS,QAAQ,UAAU,MAAM,iBAAiB,QAAQ,GAAG;CACnE,MAAM,QAAsB,OAAO;CAUnC,IAAI,CAAC,UAAU,OAAO,MAAM,YAC1B,QAAQ,OAAO,MACb,uEAAuE,OAAO,MAAM,GAAG,0IAGzF;CAYF,MAAM,sBAAoC;EACxC,GAAG;EACH,GAAG,OAAO;EACV,GAAG,mBAAmB,OAAO,WAAW,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC;CAC/D;;;;;;;CAQA,MAAM,uBAAuB,YAA0B,QAAsB,UAAwD;EACnI,MAAM,MAA6B,CAAC;EACpC,KAAK,MAAM,OAAO,kBAChB,IAAI,IAAI,YAAY,OAAO,IAAI,SAAS,SAAS,WAAW,IAAI,SAAS,SAAS,MAAM,IAAI,SAAS,OACnG,IAAI,IAAI,OAAO;EAEnB,OAAO;CACT;CAEA,MAAM,iBAAiB,OAA8B,QAAyC,CAAC,MAAoB;EAUjH,MAAM,QAAQ,OAAO,WAAW,KAAK;EAIrC,MAAM,UAAU,qBAAqB,MAAM,UAAU,OAAO,KAAK;EACjE,MAAM,aAA2B;GAAE,GAAG;GAAkB,GAAG,OAAO;GAAiB,GAAG,mBAAmB,OAAO;EAAE;EAClH,MAAM,SAAS,0BAA0B,UAAU;EACnD,MAAM,OAAO,qBAAqB,SAAS,oBAAoB,YAAY,QAAQ,KAAK,CAAC;EACzF,OAAO,WAAW,KAAK;GAAE,GAAG;GAAO,UAAU;EAAK,CAAC;EACnD,OAAO;CACT;CAEA,MAAM,oBAA4B,OAAO,MAAM;CAE/C,MAAM,qBAA2B;EAC/B,MAAM,MAAM,YAAY;EACxB,QAAQ,IAAI,0BAA0B,gBAAgB,GAAG;EAGzD,eAAe,KAAK,SAAS,OAAO,YAAY,iBAAiB;CACnE;CAGA,MAAM,cAAc,SAAS,KAAA,IAAY,iCAAiC;CAC1E,MAAM,oBAAoB,eAAe,kBAAkB,SAAS,QAAQ;EAAE;EAAc;EAAe;EAAc;EAAa;CAAM,CAAC;CAE7I,MAAM,OAAO;EAKX,cAAc,SAAS,OAAO,iBAAiB,OAAO;EACtD,YAAY,WAAuB;GAEjC,IAAI,OAAO,SAAS,sBAAsB,OAAO,OAAO,UACtD,mBAAmB,cAAc,OAAO,SAAS;GACnD,QAAQ,UAAU,MAAM;EAC1B;EACA;EACA;EACA;EACA,GAAI,OAAO,WAAW,OAAO,EAAE,gBAAgB,aAAyB,iBAAiB,OAAO,WAAW,MAAO,QAAQ,EAAE,IAAI,CAAC;EACjI;EACA,gBAAgB,OAAO,MAAM;EAM7B,GAAI,SACC,QAAQ,UAAU,EAAE,QAAQ,aAAa,QAAQ,OAAO,EAAE,IAAI,CAAC,IAChE,EAAE,QAAQ,aAAa,QAAQ,UAAU,WAAW,CAAC,QAAQ,SAAS,YAAY,CAAC,CAAC,IAAI,YAAY,CAAC,EAAE;EAC3G;EACA,0BAA0B,6BAA6B,YAAY,CAAC;EAOpE,sBAAsB,SAClB,2BAA2B,IAC3B,yBAAyB,KAAK,QAAQ,OAAO,MAAM,KAAK,GAAG,wBAAwB,CAAC;EACxF,GAAI,QAAQ,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;EAChF;CACF;CAIA,IAAI,QAAQ;EACV,MAAM,EAAE,SAAS,YAAY,WAAW,OAAO;EAC/C,OAAO;GACL,GAAG;GAEH,gBAAgB,OAAO,MAAM;GAC7B,eAAe;GACf,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;GAChE,GAAI,OAAO,kBAAkB,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;GAC5E,GAAI,OAAO,cAAc,KAAA,IAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;GACxE,yBAAyB,aAAa;GAGtC,qBAAqB,SAAS,YAAY,KAAA;EAC5C;CACF;CAmBA,MAAM,oBAAoB;CAC1B,MAAM,+BAAe,IAAI,IAAqC;CAG9D,MAAM,UAAU,uBAAuB;EACrC,QAAQ,OAAO;EACf;EACA,uBAAuB,6BAA6B,YAAY,CAAC;CACnE,CAAC;CACD,mBAAmB,QAAQ,OAAO;CAElC,MAAM,OAAO,QAAQ,UAAU,WAAW,CAAC,QAAQ,SAAS,YAAY,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,IAAI,KAAA;;CAElG,MAAM,0BAAU,IAAI,IAAgE;CACpF,MAAM,YAAY,aAAa,QAAQ,YAAY,EAAE,UAAU,OAAO,CAAC,CAAC;CACxE,MAAM,aAAa,QAAQ,yBAAyB,QAChD,KAAA,IACA,2BAA2B;EACzB,WAAW,OAAO,MAAM;EACxB,QAAQ,OAAO;EACf,MAAM,OAAO,YAAY,UAAU,MAAM,CAAC,OAAO;EACjD,OAAO;EACP,GAAI,QAAQ,wBAAwB,CAAC;CACvC,CAAC;;;;;;;CAQL,MAAM,kBAAkB,YAA2C;EACjE,QAAQ,IAAI,OAAO,CAAC,EAAE,MAAM;EAC5B,QAAQ,OAAO,OAAO;EACtB,QACG,MAAM,WAAW;GAChB,mBAAmB,QAAQ,OAAO,UAAU;GAC5C,OAAO,OAAO,WAAW,QAAQ;EACnC,CAAC,CAAC,CACD,YAAY,KAAA,CAAS;CAC1B;CAGA,IAAI,oBAA8C;CAClD,MAAM,gBAAgB,gBAAgB;EAAE,QAAQ,OAAO;EAAQ,OAAO;EAAc,SAAS;EAAgB,WAAW,KAAK;EAAW,cAAa,QAAO,YAAY,GAAG;EAAG,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EAAI,GAAI,QAAQ,oBAAoB,KAAA,IAAY,EAAE,OAAO,QAAQ,gBAAgB,IAAI,CAAC;EAAI,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;CAAG,CAAC;CAEtU,MAAM,cAAc,KAAa,aAAmC;EAClE;EACA,KAAK,UAAU,SAAS,qBAAqB,IAAI;EACjD,OAAO,SAAS,0BAA0B,IAAI;CAChD,CAAC,CAAC,KAAK,IAAQ;CACf,MAAM,YAAY,QAAwB,IAAI,MAAM,GAAG,IAAI,QAAQ,IAAQ,CAAC;CAE5E,MAAM,iBAAiB,QAAyC;EAC9D,MAAM,WAAW,aAAa;EAC9B,MAAM,MAAM,WAAW,KAAK,QAAQ;EAEpC,MAAM,WAAW,aAAa,IAAI,GAAG;EACrC,IAAI,UAAU;GAEZ,aAAa,OAAO,GAAG;GACvB,aAAa,IAAI,KAAK,QAAQ;GAC9B,OAAO;EACT;EAEA,MAAM,WAAW,mBAAmB,QAAQ;GAAE;GAAK,GAAI,MAAM,EAAE,aAAa,cAAc,GAAG,EAAE,IAAI,CAAC;EAAG,CAAC;EAExG,MAAM,OAA8C,CAAC;EACrD,MAAM,UAAU,KAAK,WAAW,YAAY;GAE1C,MAAM,WAAW,aACb,qBAAqB;IAAE,WAAW,OAAO,MAAM;IAAW,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;IAAI,QAAQ,OAAO;GAAO,GAAG,EAAE,cAAc,SAAS,0BAA0B,KAAK,CAAC,IACrK,KAAA;GACJ,MAAM,oBAAoB,MAAM,kCAAkC;IAChE;IACA;IACA,QAAQ,OAAO;IACf,GAAI,WAAW;KAAE,qBAAqB,SAAS;KAAO,gBAAgB,SAAS;IAAS,IAAI,CAAC;IAC7F,GAAI,SAAS,sBAAsB,KAAA,IAAY,EAAE,kBAAkB,CAAC,GAAG,SAAS,iBAAiB,EAAE,IAAI,CAAC;IACxG,wBAAwB,SAAS,0BAA0B;IAC3D;IACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;IACvB,GAAI,WAAW,EAAE,SAAS,SAAS,QAAQ,IAAI,CAAC;GAClD,CAAC;GACD,MAAM,WAAW,cAAc;IAC7B;IACA;IACA,aAAa;GACf,CAAC;GAGD,IAAI,aAAa,IAAI,GAAG,MAAM,KAAK,SACjC,UAAU,MAAM,mBAAmB,QAAQ;GAC7C,OAAO;EACT,EAAA,CAAG;EAEH,QAAa,MAAK,aAAY,MAAM,aAAa,IAAI,GAAG,MAAM,WAAW,QAAQ,IAAI,SAAS,cAAc,SAAS,YAAY;GAAE;GAAK;GAAS;GAAK;EAAS,CAAC,CAAC,UAAU,KAAA,CAAS;EAEpL,aAAa,IAAI,KAAK,OAAO;EAC7B,OAAO,aAAa,OAAO,mBAAmB;GAC5C,MAAM,SAAS,CAAC,GAAG,aAAa,KAAK,CAAC,CAAC,CAAC,MAAK,UAAS,UAAU,OAAO,CAAC,YAAY,SAAS,KAAK,CAAC,CAAC;GACpG,IAAI,WAAW,KAAA,GACb;GACF,MAAM,UAAU,aAAa,IAAI,MAAM;GACvC,aAAa,OAAO,MAAM;GAC1B,IAAI,SACF,eAAe,OAAO;EAC1B;EACA,QAAQ,YAAY;GAClB,IAAI,aAAa,IAAI,GAAG,MAAM,SAC5B,aAAa,OAAO,GAAG;EAC3B,CAAC;EACD,OAAO;CACT;CAEA,OAAO;EACL,GAAG;EACH;EACA,oBAAmB,QAAO,aAAa,IAAI,WAAW,KAAK,aAAa,CAAC,CAAC;EAC1E,uBAAuB,UAAU;GAC/B,cAAc;EAChB;EACA,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;EACrC,GAAI,oBAAoB,EAAE,kBAAkB,IAAI,CAAC;EACjD,GAAI,aAAa,EAAE,sBAAsB,WAAW,IAAI,CAAC;EACzD,yBAAyB;GACvB,KAAK,MAAM,SAAS,aAAa,OAAO,GACtC,eAAe,KAAK;GACtB,aAAa,MAAM;EACrB;EACA,qBAAqB;GACnB,MAAM,UAAU,CAAC,GAAG,aAAa,OAAO,CAAC;GACzC,aAAa,MAAM;GACnB,aAAa;IACX,KAAK,MAAM,SAAS,SAClB,eAAe,KAAK;GACxB;EACF;CACF;AACF;;AAGA,eAAe,iBAAiB,KAAkD;CAOhF,MAAM,EAAE,mBAAmB,MAAM,OAAO;CAKxC,OAAO,cAAc;EACnB,GAAI,QAAQ,KAAA,IAAY,EAAE,IAAI,IAAI,CAAC;EACnC,QAAO,aAAY,eAAe,SAAS,EAAE;CAC/C,CAAC;AACH;;AAGA,SAAS,kBACP,SACA,QACA,MACsB;CACtB,OAAO,2BAA2B;EAChC,MAAM,QAAQ,kBAAkB;EAChC,eAAe,OAAO,MAAM;EAC5B,iBAAiB,OAAO,MAAM;EAC9B,iBAAiB,OAAM,eAAc,MAAM,kBAAkB,KAAK,OAAO,SAAS,EAAA,EAAI;EACtF,MAAK,YAAW,QAAQ,KAAK,OAAO;EACpC,QAAQ,OAAO;EACf,cAAc,KAAK;EACnB,gBAAe,UAAS,KAAK,KAAK,cAAc,KAAK;EACrD,WAAW,QAAQ;EACnB,aAAa,KAAK;EAClB,cAAc,KAAK;EAEnB,gBAAgB,OAAO,aAAa;GAClC,IAAI,KAAK,aAAa,CAAC,CAAC,cAAc,SAAS,CAAC,KAAK,MAAM,gBACzD;GACF,MAAM,SAAS,MAAM,KAAK,MAAM,eAAe,QAAQ;GACvD,IAAI,QACF,QAAQ,UAAU;IAAE,MAAM;IAAoB,WAAW,OAAO;IAAW,IAAI;IAAU,YAAY,OAAO;IAAI,UAAU;GAAO,CAAC;EACtI;CACF,CAAC;AACH;;;;;;;;;;;;;AAwBA,SAAS,gBAAgB,MAW2E;CAClG,QAAQ,UAAU,EAAE,KAAK,SAAS,KAAK,eAAe;EACpD,IAAI,KAAK,UAAU,SAAS,CAAC,KAAK,YAChC,OAAO,KAAA;EACT,MAAM,gBAAyB,KAAK,MAAM,IAAI,GAAG,MAAM;EAEvD,MAAM,aAAmB;GACvB,KAAK,MAAM,OAAO,GAAG;GACrB,KAAK,QAAQ,OAAO;GACpB,KAAK,UAAU;IAAE,MAAM;IAAmB,SAAS;GAAa,CAAC;EACnE;EACA,MAAM,OAAO;GAAE;GAAK,QAAQ,KAAK;GAAQ,wBAAwB,SAAS,0BAA0B;EAAK;EACzG,MAAM,cAA8D,0BAA0B;GAAE;GAAK,QAAQ,KAAK;EAAO,CAAC;EAC1H,MAAM,gBAAqD;GACzD,MAAM,UAAU,mBAAmB,QAAQ;GAC3C,MAAM,uBAAO,IAAI,IAAY;GAC7B,KAAK,MAAM,QAAQ,SAAS,WAAW,KAAK,CAAC,GAAG;IAC9C,MAAM,MAAM,QAAS,IAAI,KAAK,EAAE,CAAC,EAAE,MAAM;IACzC,IAAI,KACF,KAAK,IAAI,GAAG;GAChB;GACA,KAAK,MAAM,SAAS,SAAS,UAC3B,IAAI,MAAM,KACR,KAAK,IAAI,MAAM,GAAG;GAEtB,OAAO;IAAE,MAAM,CAAC,GAAG,IAAI;IAAG,OAAO,MAAM,CAAC,CAAC,KAAI,SAAQ,KAAK,IAAI;GAAE;EAClE;EACA,MAAM,WAAW,OAAwB,SAAS,sBAAsB,KAAA,KAAa,SAAS,kBAAkB,SAAS,EAAE;EAC3H,MAAM,YAAY,QAA8E;GAC9F,MAAM,OAAO,MAAM,CAAC,CAAC,MAAK,MAAK,EAAE,SAAS,QAAQ,GAAG,CAAC;GACtD,IAAI,CAAC,QAAQ,CAAC,sBAAsB,IAAI,CAAC,CAAC,SAAS,GAAG,GACpD,OAAO,KAAA;GACT,OAAO;IAAE,QAAQ,KAAK;IAAQ,SAAS,QAAQ,SAAS,GAAG,CAAC;GAAE;EAChE;EACA,MAAM,eAAe,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,CAAC;EACpE,IAAI,QAAuB,QAAQ,QAAQ;EAE3C,MAAM,UAAU,YAA8B;GAC5C,OAAO,KAAK,YAAY,GAAG,KAAK,QAAQ,GACtC,MAAM,IAAI,SAAQ,YAAW,WAAW,SAAS,aAAa,WAAW,GAAI,CAAC;GAChF,OAAO,QAAQ;EACjB;EACA,MAAM,WAAW,SAA6C;GAC5D,QAAQ,MAAM,KAAK,YAAY;IAC7B,IAAI,QAAQ,GACV,MAAM,KAAK;GACf,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GACxB,OAAO;EACT;EACA,MAAM,QAAQ,KAAK,UAAU,QACzB,KAAA,IACA,uBAAuB,SAAS;GAC9B,QAAa,YAAY;IACvB,IAAI,CAAC,MAAM,QAAQ,GACjB;IAEF,KAAI,MADiB,wBAAwB,UAAU,MAAM;KAAE;KAAU,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;IAAG,CAAC,EAAA,CACzG,cACT,OAAO,KAAK;IACd,OAAO,KAAK,QAAQ,CAAC;GACvB,CAAC;EACH,GAAG;GAAE,iBAAiB,CAAC,KAAK,YAAY,GAAG;GAAG,GAAG;EAAa,CAAC;EACnE,OAAO,KAAK,QAAQ,CAAC;EACrB,MAAM,SAAS,KAAK,YAAY,OAAO;GACrC;GACA,oBAAoB,SAAS,0BAA0B;GACvD,QAAO,WAAU,QAAQ,YAAY;IACnC,IAAI,CAAC,MAAM,QAAQ,GACjB;IACF,MAAM,SAAS,MAAM,4BAA4B,UAAU,QAAQ;KAAE;KAAU;KAAS,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;IAAG,CAAC;IACnI,IAAI,OAAO,cACT,OAAO,KAAK;IACd,OAAO,KAAK,QAAQ,CAAC;IAErB,KAAK,UAAU;KAAE,MAAM;KAAsB;IAAI,CAAC;IAGlD,IAAI,CAAC,OAAO,UAAU,OAAO,OAAO,SAAS,OAAO,SAAS,SAAS,OAAO,SAAS,SAAS,GAC7F,KAAK,UAAU;KAAE,MAAM;KAAmB,SAAS;IAAa,CAAC;GACrE,CAAC;EACH,CAAC;EACD,OAAO,EACL,aAAa;GACX,OAAO,MAAM;GACb,SAAS;EACX,EACF;CACF;AACF;;;AC7pBA,MAAM,eAAe;AACrB,MAAM,QAA4B;CAAE,QAAQ,CAAC;CAAG,MAAM,CAAC;AAAE;;AAuBzD,SAAS,qBAAwC;CAC/C,MAAM,eAAsB;EAC1B,MAAM,IAAI,MAAM,8HAA8H;CAChJ;CACA,OAAO;EAAE,wBAAwB;EAAQ,uBAAuB;EAAQ,sBAAsB;EAAQ,yBAAyB;CAAO;AACxI;;;;;;;AAQA,SAAgB,0BAA0B,SAAwD;CAChG,IAAI,QAAQ,QACV,OAAO,mBAAmB;CAC5B,MAAM,EAAE,MAAM,KAAK,cAAc;CACjC,IAAI;CACJ,IAAI;CAEJ,MAAM,eAAwB,gBAAgB,UAAU,IAAI,aAAa,CAAC;CAE1E,MAAM,aAAmB;EACvB,MAAM,UAAU;EAChB,QAAQ,KAAA;EACR,cAAc,SAAS;EACvB,YAAY,KAAA;EACZ,SAAc,MAAK,MAAK,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EACxD,UAAU;GAAE,MAAM;GAAiB,OAAO;EAAM,CAAC;CACnD;CAEA,MAAM,aAAoC;EACxC,UAAU,OAAO,sBAAsB,CAAC,MAAM,EAAE,wBAAwB,kBAAkB;GACxF,SAAS,IAAI,YAAY;GACzB,UAAU,KAAK;GACf,QAAQ,QAAQ;GAChB,YAAY,QAAQ;GACpB,gBAAgB,IAAI,aAAa;GACjC,WAAU,WAAU,UAAU;IAAE,MAAM;IAAiB,OAAO;GAAO,CAAC;GACtE,GAAG,QAAQ;EACb,CAAC,CAAC;EAEF,cAAc,kBAAkB;GAC9B,IAAI,CAAC,OAAO,GACV,KAAK;EACT,GAAG,QAAQ,QAAQ,UAAU,YAAY;EACzC,UAAU,QAAQ;EAClB,OAAO;CACT;CAEA,MAAM,iBAAwC;EAC5C,IAAI,CAAC,OAAO,GACV,MAAM,IAAI,MAAM,uBAAuB,gBAAgB,SAAS,IAAI,KAAK,gBAAgB,cAAc,OAAO,GAAG,6BAA6B;EAChJ,OAAO,KAAK;CACd;CAEA,MAAM,OAAO,OAAgB,SAAyB;EACpD,IAAI,OAAO,UAAU,YAAY,UAAU,IACzC,MAAM,IAAI,mBAAmB,IAAI,KAAK,8BAA8B;EACtE,OAAO;CACT;CAGA,IAAI,OAAO,KAAK,WAAW,KAAK,IAAI,YAAY,GAAG,oBAAoB,CAAC,GACtE,KAAU,CAAC,CAAC,YAAY,KAAA,CAAS;CACnC,KAAK,SAAS,cAAc;EAC1B,MAAM,UAAU;EAChB,QAAQ,KAAA;EACR,cAAc,SAAS;EACvB,SAAc,MAAK,MAAK,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CAC1D,CAAC;CAED,OAAO;EACL,wBAAwB,OAAO,MAAM;GACnC,IAAI,CAAC,MAAM,QAAQ,EAAE,KAAK,GACxB,MAAM,IAAI,mBAAmB,sCAAoC;GAEnE,IAAI,KAAK,UAAU,UACjB,KAAK,MAAM,QAAQ,EAAE,OACnB,KAAK,UAAU,cAAc,OAAO,IAAI,CAAC;GAE7C,QAAQ,MAAM,SAAS,EAAA,CAAG,WAAW;IAAE,QAAQ,IAAI,EAAE,QAAQ,QAAQ;IAAG,MAAM,IAAI,EAAE,MAAM,MAAM;IAAG,OAAO,EAAE;IAAO,GAAI,OAAO,EAAE,UAAU,WAAW,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;GAAG,CAAC;EACjL;EACA,uBAAuB,OAAM,OAAM,MAAM,SAAS,EAAA,CAAG,UAAU,IAAI,EAAE,QAAQ,QAAQ,CAAC;EACtF,sBAAsB,OAAO,MAAM;GACjC,IAAI,OAAO,EAAE,YAAY,WACvB,MAAM,IAAI,mBAAmB,gCAA8B;GAC7D,QAAQ,MAAM,SAAS,EAAA,CAAG,OAAO,IAAI,EAAE,QAAQ,QAAQ,GAAG,EAAE,OAAO;EACrE;EACA,yBAAyB,YAAa,OAAO,KAAK,MAAM,KAAK,EAAA,CAAG,OAAO,IAAI;CAC7E;AACF;;;;AC7HA,MAAM,WAAW;;;;;;;AAQjB,SAAgB,sBAAsB,EAAE,MAAM,aAA+I;CAC3L,OAAO;EACL,uBAAuB,KAAK,SAAS,KAAK;EAC1C,oBAAoB,MAAM;GACxB,IAAI,OAAO,EAAE,cAAc,UACzB,MAAM,IAAI,mBAAmB,kDAAgD;GAC/E,MAAM,UAAU,KAAK,SAAS,IAAI,EAAE,SAAS;GAC7C,MAAM,YAAY,KAAK,SAAS,OAAO,EAAE,SAAS;GAClD,IAAI,aAAa,SACf,UAAU;IAAE,MAAM;IAAkB,WAAW,QAAQ;IAAI,MAAM,QAAQ;IAAM,QAAQ;GAAU,CAAC;GACpG,OAAO,EAAE,UAAU;EACrB;EACA,qBAAqB,OAAO,MAAM;GAChC,IAAI,OAAO,EAAE,cAAc,UACzB,MAAM,IAAI,mBAAmB,oDAAkD;GACjF,MAAM,UAAU,KAAK,SAAS,IAAI,EAAE,SAAS;GAC7C,MAAM,OAAO,KAAK,SAAS,KAAK,EAAE,SAAS;GAC3C,IAAI,CAAC,WAAW,CAAC,MACf,MAAM,IAAI,MAAM,oBAAoB,EAAE,UAAU,GAAG;GACrD,MAAM,QAAQ,QAAQ,MAAM,KAAI,SAAQ,KAAK,IAAI;GAEjD,MAAM,QAAQ,EAAE,SAAS,KAAA,KAAa,EAAE,SAAS,KAAK,MAAM,KAAM,EAAE;GACpE,IAAI,OAAO,UAAU,YAAY,CAAC,oBAAoB,QAAQ,OAAO,KAAK,GACxE,MAAM,IAAI,MAAM,GAAG,OAAO,KAAK,EAAE,cAAc,QAAQ,KAAK,UAAU;GACxE,MAAM,OAAO,MAAM,UAAU,KAAK;GAClC,MAAM,OAAO,MAAM,MAAK,MAAK,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;GAErE,MAAM,EAAE,YAAY,MAAM,KAAK,KAAK,WAAW;IAAE,QAAQ;KAAE,IAAI;KAAkB,KAAK;IAAK;IAAG;GAAK,GAAG,EAAE,MAAM,MAAM,CAAC;GAOrH,OAAO;IAAE;IAAM,MANF,QACV,KAAI,UAAU,OAAO,UAAU,WAAW,QAAQ,MAAM,IAAK,CAAC,CAC9D,QAAO,SAAQ,KAAK,SAAS,GAAG,CAAC,CAAC,CAClC,KAAI,SAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAChD,KAAK,CAAC,CACN,MAAM,GAAG,QACM;IAAG;GAAM;EAC7B;CACF;AACF;;ACpBA,MAAM,iBAAiC;CAAE,SAAS;CAAO,QAAQ;AAAa;;;;;;;AAQ9E,SAAgB,YAAY,QAAoB,MAAc,KAA6C;CACzG,IAAI,QAAQ,KAAA,GACV,OAAO,mDAAmD,KAAK;CACjE,IAAI,KAAK,UAAU,KAAK,KAAK,OAAO,OAAO,CAAC,KAAK,SAAS,GAAG,KAAK,OAAO,OAAO,QAAA,MAAwB,GACtG,OAAO,KAAA;CACT,OAAO,mDAAmD,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,iBAAiB,IAAI,IAAI;AAC3G;AAEA,SAAgB,cAAc,SAAmC;CAC/D,OAAO;EACL,OAAO;EACP,UAAU;EACV,KAAK,QAAQ,KAAK,SAAS;GACzB,IAAI;IACF,MAAM,MAAM,QAAQ,IAAI;IACxB,IAAI,CAAC,KACH;IACF,IAAI,WAAW,IAAI,gBAAgB;KACjC,MAAM,OAAO,QAAQ,KAAK;KAC1B,IAAI,SAAS,KAAA,GACX;KACF,QAAQ,UAAU,YAAY,QAAQ,MAAM,GAAG;KAC/C,IAAI,QAAQ,UAAU,KAAA,GAAW;MAC/B,IAAI,eAAe,QAAQ,OAAO,cAAc;MAChD;KACF;IACF;IACA,IAAI,iBAAiB,cAAc,QAAQ,KAAA,IAAY,SAAS;KAAE,GAAG;MAAS,mBAAmB;IAAI,CAAC;GACxG,QACM,CAEN;EACF;CACF;AACF;;AAGA,SAAgB,mBAAmB,YAA4B,MAAgF;CAC7I,OAAO;EACL,WAAW,OAAO,YAAsD;GACtE,MAAM,UAAU,MAAM,WAAW,cAAc,QAAQ,QAAQ,QAAQ,QAAQ,IAAI;GACnF,OAAO,QAAQ,KACX,gBAAgB,QAAQ,IAAI,QAAQ,MAAM,IAC1C,cAAc,QAAQ,IAAI,QAAQ,MAAM,QAAQ,SAAS,QAAQ,IAAI;EAC3E;EACA,iBAAgB,YAAW,WAAW,mBAAmB,QAAQ,QAAQ,QAAQ,QAAQ,IAAI;CAC/F;AACF;;;AC3BA,SAAS,QAAQ,SAAkC;CACjD,OAAO,QAAQ,WAAW,QAAQ,OAAO,KAAA,KAAa,QAAQ,OAAO,SAAS,YAAY,WAAW,WAAW;AAClH;AAEA,SAAgB,eAAe,QAAoB,QAA8B;CAC/E,MAAM,EAAE,aAAa,YAAY,KAAK,UAAU;CAChD,IAAI,eAAe;CACnB,IAAI,QAAQ;CACZ,MAAM,aAAa,QAAsB;EACvC,IAAI,OACF;EACF,QAAQ;EACR,OAAO,MAAM,GAAG;CAClB;CACA,MAAM,gBAAwB;EAC5B,MAAM,WAAW,OAAO,SAAS;EACjC,eAAe,KAAK,IAAI,cAAc,QAAQ;EAC9C,OAAO,WAAW;CACpB;CACA,MAAM,QAAQ,MAAc,YAAkC;EAC5D,IAAI,OACF;EACF,IAAI,CAAC,QAAQ,OAAO,GAAG;GACrB,IAAI,CAAC,OAAO,MAAM,IAAI,KAAK,QAAQ,IAAI,aACrC,UAAU,aAAa,YAAY,yBAAyB;GAC9D;EACF;EACA,IAAI,OAAO;EACX,IAAI,QAAQ,OAAO,WAAW,IAAI;EAClC,IAAI,QAAQ,YAAY;GACtB,MAAM,KAAM,QAAoC;GAChD,IAAI,GAAG,MAAM,YAAY,OAAO,EAAE,EAAE,MAAM,MAAM,YAAY,WAAW,mCAAmC;GAC1G,OAAO,KAAK,UAAU,cAAc,IAAI,aAAa,kBAAkB,qBAAqB,WAAW,uDAAuD;IAAE;IAAO,UAAU;GAAW,CAAC,CAAC;GAC9L,QAAQ,OAAO,WAAW,IAAI;EAChC;EACA,IAAI,CAAC,OAAO,MAAM,IAAI,GAAG;GACvB,UAAU,gCAAgC;GAC1C;EACF;EACA,gBAAgB;EAChB,IAAI,OAAO,SAAS,IAAI,cAAc,IAAI,YACxC,UAAU,aAAa,cAAc,IAAI,WAAW,cAAc;CACtE;CACA,OAAO;EAAE;EAAS;EAAM;CAAU;AACpC;;;;AC9DA,IAAa,yBAAb,cAA4C,MAAM;CAKV;;;;;CAAtC,YAAY,SAAiB,UAA4B;EACvD,MAAM,OAAO;EADuB,KAAA,WAAA;EAEpC,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,qBAAb,cAAwC,MAAM;CAKvB;;;;;CAArB,YAAY,YAA6B,SAAiB;EACxD,MAAM,OAAO;EADM,KAAA,aAAA;EAEnB,KAAK,OAAO;CACd;AACF;;AAyCA,SAAS,OAAO,QAAoB,IAAkF;CACpH,IAAI,OAAO,OAAO,OAAO,YAAY;EACnC,OAAO,GAAG,YAAW,SAAQ,GAAG,QAAQ,IAAI,CAAC;EAC7C,OAAO,GAAG,UAAS,QAAO,GAAG,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,CAAC;EACrF,OAAO,GAAG,SAAQ,SAAQ,GAAG,OAAO,oBAAoB,OAAO,IAAI,GAAG,CAAC;EACvE;CACF;CACA,OAAO,mBAAmB,YAAW,UAAS,GAAG,QAAS,MAAuB,IAAI,CAAC;CACtF,OAAO,mBAAmB,UAAS,UAAS,GAAG,OAAQ,MAAqB,WAAW,cAAc,CAAC;CAEtG,OAAO,mBAAmB,UAAS,UAAS,GAAG,OAAO,oBAAqB,MAA4B,QAAQ,KAAK,CAAC;AACvH;;;;;AAMA,SAAgB,sBAAgC,SAA4D;CAC1G,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,UAAU,QAAQ,aAAa;EAAE,MAAM;EAAK,KAAK;CAAO;CAC9D,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,0BAAU,IAAI,IAAqB;CACzC,IAAI,SAAS;CACb,IAAI,SAA4B;CAChC,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,WAA0B;CAC9B,IAAI,SAAS;CAEb,SAAS,QAAQ,QAAwB;EACvC,WAAW;EACX,QAAQ,aAAa,MAAM;EAC3B,OAAO;CACT;CAEA,SAAS,UAAU,QAAsB;EACvC,MAAM,QAAQ,IAAI,uBAAuB,QAAQ,aAAa,QAAQ,MAAM;EAC5E,KAAK,MAAM,CAAC,IAAI,UAAU,SAAS;GACjC,aAAa,MAAM,KAAK;GACxB,QAAQ,OAAO,EAAE;GACjB,MAAM,OAAO,KAAK;EACpB;CACF;;CAGA,SAAS,KAAK,QAAoB,QAAsB;EACtD,IAAI,WAAW,QACb;EACF,MAAM,WAAW;EACjB,SAAS;EACT,QAAQ;EACR,IAAI;GACF,OAAY,UAAU;EACxB,QACM,CAEN;EACA;EACA,IAAI,CAAC,YAAY,WAAW,YAC1B,QAAQ,GAAG,KAAK,gBAAgB,WAAW,GAAG,QAAQ,qBAAqB,mBAAmB,IAAI,OAAO,EAAE;EAC7G,UAAU,KAAK,IAAI,IAAI,KAAK,IAAI,QAAQ,OAAO,MAAM,UAAU,IAAI,QAAQ,GAAG;EAC9E,UAAU,YAAY,mBAAmB,QAAQ;CACnD;CAEA,SAAS,UAAU,MAAkB,MAAqB;EACxD,IAAI,SAAS,UAAU,OAAO,SAAS,YAAY,SAAS,MAC1D;EACF,MAAM,UAAU;EAChB,IAAI,WAAW,SAAS;GACtB,QAAQ;GACR;EACF;EACA,IAAI,WAAW,SAAS;GACtB,QAAQ;GACR,KAAK,MAAM,QAAQ,KAAK;GACxB;EACF;EACA,IAAI,WAAW,SAAS;GACtB,QAAQ,UAAU,QAAQ,KAAK;GAC/B;EACF;EACA,MAAM,QAAQ,QAAQ,IAAI,QAAQ,EAAE;EACpC,IAAI,CAAC,OACH;EACF,QAAQ,OAAO,QAAQ,EAAE;EACzB,aAAa,MAAM,KAAK;EACxB,UAAU;EACV,IAAI,QAAQ,SAAS,GACnB,KAAK,QAAQ;EACf,IAAI,QAAQ,IACV,MAAM,QAAQ,QAAQ,MAAM;OAE5B,MAAM,OAAO,IAAI,mBAAmB,QAAQ,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC;CAClF;CAEA,SAAS,eAA2B;EAClC,IAAI,QACF,MAAM,IAAI,uBAAuB,wBAAwB,IAAI;EAC/D,IAAI,aAAa,MACf,MAAM,IAAI,uBAAuB,UAAU,IAAI;EACjD,IAAI,QACF,OAAO;EACT,IAAI,KAAK,IAAI,IAAI,SACf,MAAM,IAAI,uBAAuB,mCAAmC,KAAK;EAC3E,IAAI;EACJ,IAAI;GACF,UAAU,QAAQ,OAAO;EAC3B,SACO,KAAK;GACV,MAAM,IAAI,uBAAuB,QAAQ,GAAG,KAAK,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,GAAG,GAAG,IAAI;EAC5H;EACA,SAAS;EACT,OAAO,SAAS;GAAE,UAAS,SAAQ,UAAU,SAAS,IAAI;GAAG,SAAQ,WAAU,KAAK,SAAS,MAAM;EAAE,CAAC;EAEtG,QAAQ,QAAQ;EAChB,QAAQ,YAAY,EAAE,MAAM,QAAQ,KAAK,CAAsB;EAC/D,OAAO;CACT;CAEA,OAAO;EACL,QAAQ,SAAS,iBAAiB,CAAC,GAAG;GACpC,OAAO,IAAI,SAAc,SAAS,WAAW;IAC3C,IAAI;IACJ,IAAI;KACF,SAAS,aAAa;IACxB,SACO,KAAK;KACV,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;KAC1D;IACF;IACA,MAAM,KAAK;IACX,MAAM,OAAO,eAAe,aAAa;IACzC,MAAM,QAAQ,WAAW,MAAM,MAAM,QAAQ,eAAe,KAAK,IAAI;IACrE,QAAQ,IAAI,IAAI;KAAW;KAAqC;KAAQ;IAAM,CAAC;IAC/E,OAAO,MAAM;IACb,IAAI;KACF,OAAO,YAAY;MAAE;MAAI;KAAQ,CAAsB;IACzD,SACO,KAAK;KAEV,QAAQ,OAAO,EAAE;KACjB,aAAa,KAAK;KAClB,IAAI,QAAQ,SAAS,GACnB,OAAO,QAAQ;KACjB,OAAO,IAAI,uBAAuB,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KAAK,KAAK,CAAC;IAC7H;GACF,CAAC;EACH;EACA,OAAO,SAAS;GACd,IAAI;IACF,QAAQ,YAAY,EAAE,QAAQ,CAAsB;GACtD,QACM,CAEN;EACF;EACA,kBAAkB,aAAa;EAC/B,QAAQ;GACN,IAAI,QACF;GACF,SAAS;GACT,MAAM,UAAU;GAChB,SAAS;GACT,UAAU,sBAAsB;GAChC,IAAI;IACF,SAAc,UAAU;GAC1B,QACM,CAEN;EACF;CACF;AACF;;;;ACvPA,MAAa,6BAA6B;;;;;;;AAqB1C,SAAgB,mBAAwB;CACtC,IAAI,OAAO,QAAQ,eAAgB,IAAwD,wBACzF,OAAO,IAAI,IAAI,+BAA+B,YAAY,GAAG;CAC/D,OAAO,IAAI,IAAI,YAAY,IAAI,SAAS,KAAK,IAAI,gBAAgB,uBAAuB,YAAY,GAAG;AACzG;;AAGA,SAAS,qBAAiC;CACxC,OAAO,IAAI,OAAO,iBAAiB,CAAC,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/D;;;;;;AA0BA,SAAgB,8BAA8B,SAIsE;CAClH,MAAM,EAAE,QAAQ,SAAS,oBAAoB,GAAG,SAAS;CACzD,MAAM,SAAS,sBAAqD;EAAE,MAAM;EAAkB;EAAQ,MAAM,EAAE,OAAO;EAA+B,GAAG;CAAK,CAAC;CAC7J,OAAO;EACL,MAAM,KAAK,WAAW,QAAQ;GAC5B,IAAI;IACF,OAAO,MAAM,OAAO,QAAQ;KAAE,IAAI;KAAQ;KAAW;IAAO,CAAC;GAC/D,SACO,KAAK;IACV,IAAI,eAAe,oBACjB,MAAM,IAAI,eAAe,uBAAuB,IAAI,mBAAmB,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,OAAO;IAC7G,MAAM;GACR;EACF;EACA,OAAO,WAAW,SAAS,OAAO,OAAO;GAAE,IAAI;GAAQ;GAAW,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EAAG,CAAC;EAC7F,OAAO,YAAY,MAAM,OAAO,QAAQ,EAAE,IAAI,QAAQ,CAAC;EACvD,YAAY,OAAO;EACnB,OAAO,OAAO;CAChB;AACF;;;;;;AAuBA,MAAM,8BAAc,IAAI,IAAwB;CAAC;CAAa;CAAY;AAAc,CAAC;AAEzF,MAAM,gBAA0C,QAAQ,IAAI,gBACxD,UAAS,QAAQ,MAAM,0EAA0E,KAAK,UAChG,CAAC;;;;;;;;;AAUX,SAAgB,0BAA0B,UAGtC,CAAC,GAAwB;CAC3B,MAAM,UAAU,QAAQ,WAAW,4BAA4B;CAC/D,MAAM,aAAa,QAAQ,YAAW,WAAU,8BAA8B,EAAE,OAAO,CAAC;CACxF,IAAI,SAAmE;CACvE,IAAI,SAAS;CAEb,MAAM,UAAU,UAA2F;EACzG,MAAM,OAAO,gBAAgB,KAAK;EAClC,IAAI,UAAU,CAAC,QAAQ,QAAQ,IAAA,gCAAoC,KACjE,OAAO;EACT,WAAW;GAAE,QAAQ,WAAW,KAAK,IAAI;GAAG,MAAM,KAAK;EAAK;EAC5D,OAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,OAAO,OAAO,WAAW,IAAI;GAAE,QAAQ,OAAO;GAAQ;EAAK,IAAI;CACtG;CACA,MAAM,QAAQ,WAAmB,SAAyB,QAAQ,OAAO,KAAK,WAAW,IAAI;CAE7F,OAAO;EACL;EACA,MAAM,KAAK,OAAO,WAAW,QAAQ;GACnC,MAAM,SAAS,OAAO,KAAK;GAC3B,IAAI,QAAQ;IAEV,MAAM,OAAO,KAAK,QAAQ;IAC1B,IAAI;KACF,OAAO,MAAM,OAAO,OAAO,KAAK,WAAW,MAAM;IACnD,SACO,KAAK;KACV,IAAI,EAAE,eAAe,yBACnB,MAAM;KACR,cAAc,GAAG;IACnB;GACF;GACA,OAAO,QAAQ,KAAK,OAAO,WAAW,MAAM;EAC9C;EACA,QAAQ,QAAQ;GACd,QAAQ,QAAQ,MAAM;GACtB,MAAM,YAAY,iBAAiB,MAAM;GACzC,IAAI,cAAc,KAAA,GAChB,KAAK,WAAW,YAAY,IAAI,OAAO,IAAI,CAAC;EAChD;EACA,OAAO,WAAW;GAChB,QAAQ,OAAO,SAAS;GACxB,KAAK,SAAS;EAChB;EACA,MAAM,MAAM,OAAO;GACjB,MAAM,OAAO,gBAAgB,KAAK;GAClC,IAAI,CAAC,MACH,OAAO;GACT,MAAM,KAAK,QAAQ;GACnB,MAAM,SAAS,OAAO,KAAK;GAC3B,IAAI,QACF,IAAI;IACF,OAAO,MAAM,OAAO,OAAO,MAAM;GACnC,SACO,KAAK;IACV,IAAI,EAAE,eAAe,yBACnB,MAAM;IACR,cAAc,GAAG;GACnB;GAEF,MAAM,KAAK,MAAM,mBAAmB,KAAK,IAAI;GAC7C,IAAI;IACF,OAAO,mBAAmB,EAAE;GAC9B,UACQ;IACN,GAAG,MAAM;GACX;EACF;EACA,QAAQ;GACN,SAAS;GACT,QAAQ,OAAO,MAAM;GACrB,SAAS;EACX;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;ACvMA,MAAM,+BAAe,IAAI,IAAI;CAAC;CAAM;CAAY;AAAW,CAAC;AAC5D,MAAM,aAAa;AACnB,MAAM,SAAS;AACf,MAAM,YAAY;;AAElB,MAAM,kBAAkB;;AAExB,MAAM,cAAc;AAEpB,MAAM,oBAAoB,UAA0B,MAAM,QAAQ,aAAa,QAAQ;AAEvF,SAAS,YAAY,MAAsB;CACzC,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,SAAS;EACnC,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,OAAO,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG;CACjD,CAAC,CAAC,CAAC,KAAK,GAAG;AACb;;;;;AAMA,SAAgB,UAAU,KAAqB;CAC7C,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,GAAG;CACnB,QACM;EACJ,OAAO;CACT;CACA,MAAM,cAAc,IAAI,aAAa,MAAM,IAAI,aAAa,KAAK,GAAG,SAAS,KAAK;CAClF,MAAM,OAAO,IAAI,SAAS,MAAM,GAAG,CAAC,CAAC,KAAI,YAAW,oBAAoB,OAAO,IAAI,WAAW,OAAO,CAAC,CAAC,KAAK,GAAG;CAC/G,MAAM,OAAO,CAAC,GAAG,IAAI,aAAa,KAAK,CAAC;CACxC,MAAM,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,KAAI,QAAO,GAAG,mBAAmB,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC,KAAK,GAAG,MAAM;CAC5G,MAAM,WAAW,IAAI,KAAK,MAAM,CAAC;CACjC,MAAM,OAAO,aAAa,KAAK,KAAK,SAAS,SAAS,GAAG,IAAI,IAAI,YAAY,QAAQ,MAAM,gBAAgB,QAAQ,IAAI,IAAI,aAAa,IAAI;CAC5I,MAAM,YAAY,IAAI,SAAS,MAAM,IAAI,SAAS,IAAI,IAAI,KAAK,cAAc,IAAI,SAAS;CAC1F,OAAO,iBAAiB,GAAG,IAAI,WAAW,YAAY,OAAO,QAAQ,MAAM;AAC7E;AAEA,SAAS,aAAa,OAAuB;CAC3C,MAAM,QAAQ,OAAO,KAAK,KAAK;CAC/B,OAAO,QAAQ,GAAG,MAAM,GAAG,GAAG,MAAM,KAAK,aAAa;AACxD;;AAGA,SAAS,YAAY,OAAuB;CAC1C,IAAI,WAAW,KAAK,KAAK,GACvB,OAAO,UAAU,KAAK;CACxB,MAAM,SAAS,OAAO,KAAK,KAAK;CAChC,IAAI,UAAU,aAAa,OAAO,EAAG,GACnC,OAAO,aAAa,KAAK;CAC3B,MAAM,OAAO,YAAY,KAAK,KAAK,IAAI,WAAW,KAAK,IAAI;CAC3D,IAAI,SAAS,MACX,OAAO;CACT,IAAI,gBAAgB,KAAK,KAAK,GAC5B,OAAO,qBAAqB,KAAK;CACnC,MAAM,OAAO,UAAU,KAAK,KAAK;CACjC,IAAI,MACF,OAAO,GAAG,KAAK,GAAG,GAAG,aAAa,KAAK,EAAG,IAAI,WAAW,YAAY,KAAK,EAAG;CAC/E,IAAI,gBAAgB,KAAK,GACvB,OAAO;CACT,OAAO,iBAAiB,KAAK;AAC/B;;AAGA,SAAS,qBAAqB,OAAuB;CACnD,OAAO,MAAM,MAAM,QAAQ,CAAC,CAAC,KAAK,SAAS;EACzC,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,KAAK,GACP,OAAO;EACT,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE;EAC7B,OAAO,GAAG,KAAK,GAAG,aAAa,KAAK,KAAK,CAAC,IAAI,WAAW,YAAY,KAAK,MAAM,KAAK,CAAC,CAAC;CACzF,CAAC,CAAC,CAAC,KAAK,EAAE;AACZ;;AAGA,SAAS,WAAW,OAA8B;CAChD,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,KAAK;CAC3B,QACM;EACJ,OAAO;CACT;CACA,IAAI,WAAW,QAAQ,OAAO,WAAW,UACvC,OAAO;CACT,MAAM,QAAQ,SAA2B;EACvC,IAAI,OAAO,SAAS,UAClB,OAAO,YAAY,IAAI;EACzB,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,KAAK,IAAI,IAAI;EACtB,IAAI,SAAS,QAAQ,OAAO,SAAS,UACnC,OAAO,OAAO,YAAY,OAAO,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,aAAa,GAAG,IAAI,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC;EACzH,OAAO;CACT;CACA,OAAO,KAAK,UAAU,KAAK,MAAM,CAAC;AACpC;;AAGA,SAAgB,WAAW,MAAmC;CAC5D,MAAM,MAAgB,CAAC;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,IAAI,WAAW,GAAG,GAAG;GACxB,IAAI,KAAK,YAAY,GAAG,CAAC;GACzB;EACF;EACA,MAAM,KAAK,IAAI,QAAQ,GAAG;EAC1B,MAAM,OAAO,KAAK,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI;EACzC,IAAI,KAAK,GAAG;GACV,MAAM,QAAQ,IAAI,MAAM,KAAK,CAAC;GAC9B,IAAI,KAAK,GAAG,KAAK,GAAG,aAAa,IAAI,IAAI,IAAI,aAAa,KAAK,IAAI,aAAa,IAAI,IAAI,WAAW,YAAY,KAAK,GAAG;GACvH;EACF;EACA,IAAI,KAAK,iBAAiB,GAAG,CAAC;EAC9B,MAAM,OAAO,KAAK,IAAI;EACtB,IAAI,SAAS,KAAA,KAAa,KAAK,WAAW,GAAG,GAC3C;EACF,IAAI,aAAa,IAAI,IAAI,GAAG;GAC1B,IAAI,KAAK,aAAa,IAAI,CAAC;GAC3B;EACF,OACK,IAAI,aAAa,IAAI,GAAG;GAC3B,IAAI,KAAK,QAAQ;GACjB;EACF;CACF;CACA,OAAO;AACT;;;ACxIA,MAAM,UAAU,MAAqC,SAA0B,SAAS,KAAA,KAAa,KAAK,SAAS,IAAI;;;;;;AAOvH,SAAgB,aAAa,OAAwJ;CACnL,MAAM,yBAAS,IAAI,IAA8B;CACjD,MAAM,OAAO,OAAoB,WAA6C;EAC5E,MAAM,gBAAgB,WAAW,WAAW,MAAM,WAAW,mBAAmB,WAAW,cAAc,MAAM,WAAW,sBAAsB,KAAA;EAChJ,OAAO,IAAI,MAAM,MAAM;GACrB,MAAM,MAAM;GACZ,aAAa,MAAM;GACnB,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;GAC/C,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACrD;GACA,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;GACzC,SAAS,WAAW,SAAS,OAAO,MAAM,SAAS,eAAe,MAAM,IAAI,IAAI;GAChF,YAAY,WAAW;EACzB,CAAC;CACH;CACA,KAAK,MAAM,SAAS,MAAM,MACxB,IAAI,OAAO,MAAM;CACnB,KAAK,MAAM,SAAS,MAAM,QACxB,IAAI,OAAO,QAAQ;CACrB,KAAK,MAAM,SAAS,MAAM,WACxB,IAAI,OAAO,WAAW;CACxB,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACzE;AAEA,SAAS,aAAa,QAA0F;CAC9G,IAAI,CAAC,QACH,OAAO,KAAA;CACT,OAAO,OAAO,YAAY,OAAO,KAAK,MAAM,CAAC,CAAC,KAAI,QAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AAC3E;AAEA,SAAgB,WAAW,SAAmC,QAAmC,UAAwB,UAA2G;CAClO,OAAO;EACL,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,WAAW;GACjD,MAAM,MAAM,aAAa,OAAO,GAAG;GACnC,MAAM,UAAU,aAAa,OAAO,OAAO;GAC3C,MAAM,SAAS,SAAS,IAAI,OAAO,IAAI;GACvC,OAAO;IACL,MAAM,OAAO;IACb,WAAW,OAAO;IAClB;IACA;IACA,SAAS,OAAO,SAAS,aAAa,OAAO,IAAI;IACjD,YAAY;IACZ,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;IAClE,GAAI,OAAO,OAAO,EAAE,MAAM,WAAW,OAAO,IAAI,EAAE,IAAI,CAAC;IACvD,GAAI,OAAO,QAAQ,KAAA,IAAY,EAAE,KAAK,UAAU,OAAO,GAAG,EAAE,IAAI,CAAC;IACjE,GAAI,OAAO,QAAQ,KAAA,IAAY,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC;IAEtD,GAAI,OAAO,cAAc,UAAU,EAAE,OAAO,OAAO,UAAU,YAAY,YAAqB,OAAgB,IAAI,CAAC;IACnH,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;IAC/D,GAAI,OAAO,SAAS,KAAA,IAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;IACzD,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;IACrB,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;IAC7B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;GAC7B;EACF,CAAC;EACD,QAAQ,OAAO,KAAI,OAAM;GAAE,MAAM,EAAE;GAAM,QAAQ,EAAE;GAAQ,SAAS,EAAE;GAAS,GAAI,EAAE,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC;EAAG,EAAE;CACvI;AACF;AAEA,SAAS,aAAa,eAAwE;CAC5F,MAAM,SAAmB,CAAC;CAC1B,MAAM,OAAO,OAAe,YAA2B;EACrD,IAAI,SACF,OAAO,KAAK,KAAK;CACrB;CACA,IAAI,UAAU,OAAO,KAAK,cAAc,MAAM,CAAC,CAAC,SAAS,CAAC;CAC1D,IAAI,aAAa,OAAO,KAAK,cAAc,SAAS,CAAC,CAAC,SAAS,CAAC;CAChE,IAAI,SAAS,OAAO,KAAK,cAAc,KAAK,CAAC,CAAC,SAAS,CAAC;CACxD,IAAI,SAAS,OAAO,OAAO,cAAc,KAAK,CAAC,CAAC,MAAK,aAAY,aAAa,KAAA,KAAa,SAAS,SAAS,CAAC,CAAC;CAC/G,IAAI,QAAQ,cAAc,WAAW,SAAS,CAAC;CAC/C,IAAI,UAAU,cAAc,OAAO,SAAS,CAAC;CAC7C,IAAI,YAAY,cAAc,SAAS,SAAS,CAAC;CACjD,IAAI,eAAe,cAAc,oBAAoB,SAAS,CAAC;CAC/D,IAAI,UAAU,OAAO,KAAK,cAAc,MAAM,CAAC,CAAC,SAAS,CAAC;CAC1D,OAAO;AACT;;;;;;;;AASA,SAAgB,sBAAsB,KAAqF;CACzH,MAAM,cAAc,IAAI,YAAY,aAAa,KAAK,KAAK,IAAI,UAAU,aAAa,KAAK;CAC3F,MAAM,OAAO,IAAI,YAAY,QAAQ,IAAI,UAAU;CACnD,MAAM,MAAM,MAAM,KAAK,KAAK,IAAI,KAAK,MAAM,KAAA;CAC3C,MAAM,MAAM,MAAM,KAAK,KAAK,IAAI,KAAK,MAAM,KAAA;CAC3C,MAAM,SAAS,IAAI,MAAM,2BAA2B,IAAI,GAAG,IAAI;CAC/D,OAAO;EACL,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;EACrC,GAAI,QAAQ,KAAA,KAAa,QAAQ,KAAA,IAAY,EAAE,MAAM;GAAE,GAAI,QAAQ,KAAA,IAAY,EAAE,IAAI,IAAI,CAAC;GAAI,GAAI,QAAQ,KAAA,IAAY,EAAE,IAAI,IAAI,CAAC;EAAG,EAAE,IAAI,CAAC;EAC3I,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;CAC7B;AACF;;AAGA,SAAgB,iBAAiB,QAAoC,UAAsC,UAAgD;CACzJ,MAAM,uBAAO,IAAI,IAAkC;CACnD,KAAK,MAAM,OAAO,CAAC,GAAG,QAAQ,GAAG,QAAQ,GAAG;EAC1C,IAAI,KAAK,IAAI,IAAI,IAAI,GACnB;EACF,KAAK,IAAI,IAAI,MAAM;GACjB,GAAG,sBAAsB,GAAG;GAC5B,MAAM,IAAI;GACV,QAAQ,IAAI;GACZ,SAAS,CAAC,IAAI,SAAS,OAAO,SAAS,mBAAmB,IAAI,IAAI;GAClE,YAAY,CAAC,IAAI;GACjB,GAAI,IAAI,YAAY,UAAU,EAAE,SAAS,IAAI,WAAW,QAAQ,IAAI,CAAC;GACrE,GAAI,IAAI,YAAY,cAAc,EAAE,aAAa,IAAI,WAAW,YAAY,IAAI,CAAC;GACjF,GAAI,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC;GAClC,GAAI,IAAI,QAAQ,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;GACxC,GAAI,IAAI,gBAAgB,EAAE,cAAc,aAAa,IAAI,aAAa,EAAE,IAAI,CAAC;EAC/E,CAAC;CACH;CACA,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACvE;;AAKA,SAAgB,cAAc,MAAmC,gBAA+C,UAA6C;CAC3J,MAAM,UAA0B,CAC9B,GAAG,KAAK,KAAI,OAAM;EAAE,QAAQ,EAAE;EAAQ,MAAM,EAAE;EAAM,QAAQ;GAAE,MAAM;GAAiB,OAAO,EAAE;GAAQ,KAAK,EAAE;EAAK;CAAE,EAAE,GACtH,GAAG,eAAe,KAAI,OAAM;EAAE,QAAQ,EAAE;EAAQ,MAAM,EAAE;EAAM,QAAQ;GAAE,MAAM;GAAsB,eAAe,EAAE;GAAe,KAAK,EAAE;EAAI;CAAE,EAAE,CACrJ;CACA,MAAM,uBAAO,IAAI,IAA+B;CAChD,KAAK,MAAM,EAAE,QAAQ,MAAM,YAAY,SAAS;EAC9C,IAAI,KAAK,IAAI,IAAI,GACf;EACF,MAAM,QAAQ,OAAO,KAAK,KAAA,IAAY,OAAO,YAAY,MAAK,MAAK,EAAE,aAAa,OAAO,CAAC,EAAE;EAC5F,KAAK,IAAI,MAAM;GACb;GACA;GACA,IAAI,OAAO;GACX,SAAS,OAAO,MAAM,OAAO,SAAS,gBAAgB,IAAI;GAC1D,YAAY,OAAO;GACnB,GAAI,OAAO,UAAU,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,SAAS,QAAQ,IAAI,CAAC;GACrF,GAAI,OAAO,UAAU,gBAAgB,KAAA,IAAY,EAAE,aAAa,OAAO,SAAS,YAAY,IAAI,CAAC;GACjG,QAAQ,OAAO,OAAO,KAAI,MAAK,EAAE,IAAI;GACrC,YAAY,OAAO,WAAW,KAAI,MAAK,EAAE,IAAI;GAC7C,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAC3B,CAAC;CACH;CACA,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACvE;;;ACzIA,MAAM,UAAU,SAAuC,OAAO,SAAS,WAAW,OAAO,KAAA;;;;;;AAOzF,SAAgB,cAAc,EAAE,KAAK,QAAgG,KAAc,MAAwB;CACzK,IAAI,QAAQ,KAAA,KAAa,OAAO,QAAQ,UACtC,MAAM,IAAI,MAAM,uBAAuB;CACzC,IAAI,CAAC,KACH,OAAO,SAAS,EAAE;CACpB,MAAM,SAAS,KAAK,cAAc,KAAK,OAAO,IAAI,CAAC;CACnD,OAAO,OAAO,UAAU,oBAAoB,IAAI,YAAY,CAAC,IAAI,SAAS,OAAO,GAAG;AACtF;;AAGA,SAAS,aAAa,IAAY,OAAe,QAAiB,KAAa,UAAsE;CACnJ,OAAO;EAAE;EAAI;EAAO;EAAQ,GAAI,QAAQ,WAAW,EAAE,QAAQ,KAAK,MAAM,GAAG,EAAiC,IAAI,CAAC;CAAG;AACtH;AAEA,SAAgB,sBAAsB,EAAE,KAAK,MAAM,aAIvB;CAC1B,MAAM,YAAY,KAAc,SAA2B,cAAc;EAAE;EAAK;CAAK,GAAG,KAAK,IAAI;;CAEjG,MAAM,YAAY,OAAO,KAAc,MAAe,WAAuE;EAC3H,IAAI,OAAO,QAAQ,YAAY,CAAC,OAAO,CAAC,KAAK,cAAc,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,SAC5E,OAAO,EAAE,KAAK,SAAS,KAAK,IAAI,EAAE;EACpC,MAAM,EAAE,cAAc,YAAY,MAAM,KAAK,cAAc,KAAK,OAAO,IAAI,GAAG,MAAM;EACpF,OAAO;GAAE,KAAK;GAAc,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAAG;CAC9D;CACA,MAAM,kBAAkB;EACtB,MAAM,WAAW,IAAI,aAAa;EAClC,OAAO;GAAE;GAAU,eAAe,SAAS,yBAAyB;GAAM,OAAO,SAAS,uBAAuB;EAAM;CACzH;;CAEA,MAAM,SAAS,OAAO,KAAc,SAAkB;EACpD,MAAM,EAAE,KAAK,YAAY,MAAM,UAAU,KAAK,MAAM,IAAI,OAAO,MAAM;EACrE,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;EAC1C,MAAM,EAAE,eAAe,UAAU,UAAU;EAC3C,MAAM,EAAE,SAAS,OAAO,WAAW,oBAAoB;GAAE,KAAK;GAAK,QAAQ,OAAO;GAAQ;GAAe;EAAM,CAAC;EAChH,MAAM,eAAe,IAAI,KAAK,SAAS,QAAQ,CAAC,EAAA,CAAG,KAAI,WAAU,OAAO,OAAO,IAAI,CAAC;EACpF,OAAO;GAAE,SAAS,CAAC,GAAI,SAAS,QAAQ,CAAC,GAAI,GAAG,MAAM,QAAO,WAAU,CAAC,aAAa,IAAI,OAAO,OAAO,IAAI,CAAC,CAAC;GAAG;EAAO;CACzH;CACA,MAAM,UAAU,OAAO,KAAa,WAAwD;EAC1F,MAAM,EAAE,SAAS,UAAU,MAAM,uBAAuB;GACtD,KAAK;GACL,QAAQ,OAAO;GACf,GAAI,OAAO,gBAAgB,SAAS,IAAI,EAAE,YAAY,OAAO,gBAAgB,IAAI,CAAC;EACpF,CAAC;EACD,OAAO;CACT;CAEA,OAAO;EACL,kBAAkB,OAAO,MAAM;GAC7B,MAAM,EAAE,KAAK,YAAY,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,IAAI,OAAO,MAAM;GAC3E,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;GAC1C,MAAM,EAAE,UAAU,eAAe,UAAU,UAAU;GACrD,MAAM,CAAC,OAAO,cAAc,MAAM,QAAQ,IAAI,CAC5C,sBAAsB;IAAE,KAAK;IAAK,QAAQ,OAAO;IAAQ;IAAe;GAAM,CAAC,GAC/E,QAAQ,KAAK,MAAM,CACrB,CAAC;GAED,MAAM,eAAe,IAAI,KAAK,SAAS,UAAU,CAAC,EAAA,CAAG,KAAI,UAAS,MAAM,IAAI,CAAC;GAC7E,MAAM,OAAO,CAAC,GAAI,SAAS,UAAU,CAAC,GAAI,GAAG,MAAM,QAAO,UAAS,CAAC,aAAa,IAAI,MAAM,IAAI,CAAC,CAAC;GACjG,MAAM,eAAe,yBAAyB;IAAE;IAAY,GAAI,SAAS,mBAAmB,KAAA,IAAY,EAAE,SAAS,SAAS,eAAe,IAAI,CAAC;GAAG,CAAC,CAAC,CAAC;GAEtJ,OAAO,EAAE,QAAQ,aAAa;IAAE;IAAM,QAAQ;IAAc,WAD/C,sBAAsB,OAAO,YAAY,SAAS,gBAAgB,IAAI,IAAI,WAAW,KAAI,MAAK,EAAE,IAAI,CAAC,CAC3C,CAAA,CAAK;IAAQ;GAAS,CAAC,EAAE;EAClG;EACA,gBAAgB,OAAO,MAAM;GAC3B,MAAM,EAAE,SAAS,WAAW,MAAM,OAAO,GAAG,KAAK,GAAG,IAAI;GACxD,OAAO,WAAW,SAAS,QAAQ,IAAI,aAAa,GAAG,UAAU,SAAS,QAAQ,KAAI,WAAU,OAAO,MAAM,CAAC,CAAC;EACjH;EACA,YAAY,OAAO,MAAM;GACvB,MAAM,OAAO,eAAe,EAAE,MAAM,MAAM;GAC1C,MAAM,SAAS,MAAM,OAAO,EAAE,KAAK,EAAE,IAAI,EAAA,CAAG,QAAQ,MAAK,WAAU,OAAO,OAAO,SAAS,IAAI;GAC9F,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,kBAAkB,KAAK,4BAA4B;GACrE,MAAM,UAAU,KAAK,MAAM,MAAM;GACjC,OAAO,UAAU,SAAS,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI;EACpD;EACA,gBAAgB,MAAM;GACpB,UAAU,QAAQ,eAAe,EAAE,MAAM,MAAM,CAAC;EAClD;EACA,kBAAiB,MAAK,KAAK,WAAW,UAAUC,iBAAe,GAAG,KAAK,KAAK,CAAC;EAC7E,eAAe,OAAM,OAAM,EACzB,WAAW,MAAM,KAAK,WAAW,QAAQ,eAAe,GAAG,MAAM,MAAM,GAAGA,iBAAe,GAAG,KAAK,KAAK,CAAC,EACzG;EACA,sBAAsB,OAAO,MAAM;GACjC,MAAM,SAAS,MAAM,IAAI,cAAc,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC;GAChE,OAAO,EAAE,YAAY,iBAAiB,OAAO,WAAW,QAAQ,OAAO,WAAW,UAAU,IAAI,aAAa,CAAC,EAAE;EAClH;EACA,mBAAmB,OAAO,MAAM;GAC9B,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,IAAI;GACpC,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;GAC1C,OAAO,EAAE,SAAS,cAAc,MAAM,QAAQ,KAAK,MAAM,GAAG,OAAO,WAAW,SAAS,IAAI,aAAa,CAAC,EAAE;EAC7G;EAEA,eAAe,OAAO,MAAM;GAC1B,MAAM,SAAS,MAAM,IAAI,cAAc,SAAS,EAAE,GAAG,CAAC;GACtD,OAAO,OAAO,OAAO,gBAAgB,kBAAkB,MAAM,GAAG,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC,KAAI,OAAM;IAAE,IAAI,EAAE;IAAI,OAAO,EAAE;IAAO,aAAa,EAAE;IAAa,QAAQ,EAAE,UAAU;GAAS,EAAE;EACxL;EACA,eAAe,OAAO,MAAM;GAC1B,MAAM,SAAS,GAAG,MAAM,MAAM,IAAI,cAAc,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;GAC/E,MAAM,SAAS,WAAW,IAAI,YAAY,GAAG,OAAO,SAAS,CAAC,CAAC,QAAO,SAAQ,KAAK,SAAS;GAE5F,IAAI,eAAe;GACnB,MAAM,iBAAiB,mBAAmB;IAAE,WAAW,OAAO;IAAW;GAAO,CAAC;GACjF,MAAM,cAAc,gBAAgB;IAAE,WAAW,OAAO;IAAW;GAAO,CAAC;GA2B3E,OAAO,EAAE,WA1B8B,OAAO,KAAK,SAAS;IAC1D,MAAM,YAAY,eACf,QAAO,UAAS,MAAM,gBAAgB,KAAK,GAAG,CAAC,CAC/C,KAAI,WAAU;KAAE,IAAI,MAAM;KAAS,WAAW,MAAM;KAAW,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;IAAG,EAAE;IACtH,MAAM,SAAS,YACZ,QAAO,UAAS,MAAM,gBAAgB,KAAK,GAAG,CAAC,CAC/C,KAAI,WAAU;KACb,IAAI,MAAM;KACV,MAAM,MAAM;KACZ,YAAY,MAAM;KAClB,cAAc,MAAM;KACpB,WAAW,MAAM;KACjB,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;KAC/C,GAAI,MAAM,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;IAC/C,EAAE;IAEJ,MAAM,SAAS,KAAK,UAAU,OAAO,UAAU,KAAK,GAAG,CAAC;IACxD,OAAO;KACL,KAAK,KAAK;KACV,OAAO,OAAO,UAAU,KAAK,IAAI,EAAE,SAAS,KAAK;KACjD,QAAQ,KAAK,MAAM,MAAM;KACzB,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,SAAS,KAAK,EAAE,IAAI,OAAO,aAAa,aAAa,IAAI,OAAO,QAAQ,KAAK,UAAU,OAAO,UAAU,KAAK,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC;KAC3K,GAAI,UAAU,SAAS,IAAI,EAAE,gBAAgB,UAAU,IAAI,CAAC;KAC5D,GAAI,OAAO,SAAS,IAAI,EAAE,aAAa,OAAO,IAAI,CAAC;IACrD;GACF,CACiB,EAAE;EACrB;EACA,eAAe,OAAO,MAAM;GAC1B,IAAI,OAAO,GAAG,UAAU,YAAY,CAAC,EAAE,OACrC,MAAM,IAAI,MAAM,4CAA0C;GAC5D,MAAM,SAAS,EAAE,MAAM,MAAM,IAAI,cAAc,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;GAC9E,MAAM,QAAQ,sBAAsB,GAAG;GACvC,OAAO,UAAU;IACf,WAAW,OAAO;IAClB,gBAAgB,KAAK,YAAY,MAAM,OAAO,WAAW,KAAoB,OAAO;IACpF,OAAO,EAAE;GACX,CAAC;EACH;EACA,kBAAkB,OAAO,MAAM;GAC7B,MAAM,SAAS,GAAG,MAAM,MAAM,IAAI,cAAc,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;GAC/E,IAAI,eAAe;GACnB,MAAM,QAAQ,OAAO,GAAG,UAAU,WAAW,EAAE,QAAQ,IAAI,aAAa,CAAC,CAAC;GAC1E,OAAO,kBAAkB;IACvB,WAAW,OAAO;IAClB,gBAAgB,QAAQ;KACtB,MAAM,aAAa,OAAO,UAAU;KACpC,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,aAAa,IAAI,oBAAoB;KACvD,OAAO,WAAW,QAAQ;IAC5B;IACA,GAAI,QAAQ,EAAE,eAAe,MAAM,IAAI,CAAC;GAC1C,CAAC;EACH;CACF;AACF;;;;AC1LA,SAAS,aAAa,KAAkC;CACtD,OAAO,OAAO,UAAU,GAAG,KAAM,MAAiB,IAAI,KAAK,IAAI,KAAe,GAAI,IAAI,KAAA;AACxF;AAEA,SAAgB,uBAAuB,EAAE,OAAO,WAAW,KAAK,QAK2E;;CAEzI,MAAM,aAAa,OAAO,gBAA4E;EACpG,IAAI;GACF,QAAQ,MAAM,IAAI,cAAc,cAAc;IAAE;IAAK;GAAK,GAAG,eAAe,EAAE,CAAC,EAAA,CAAG;EACpF,QACM;GACJ;EACF;CACF;CACA,OAAO;EACL,sBAAsB,OAAO,MAAM;GACjC,IAAI,CAAC,MAAM,eACT,OAAO,CAAC;GACV,OAAO,MAAM,cAAc;IACzB,WAAW,EAAE;IACb,GAAI,OAAO,EAAE,SAAS,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrD,GAAI,aAAa,EAAE,KAAK,MAAM,KAAA,IAAY,EAAE,OAAO,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC;GAChF,CAAC;EACH;EACA,kBAAkB,OAAO,MAAM;GAC7B,IAAI,CAAC,MAAM,eACT,OAAO,CAAC;GACV,OAAO,MAAM,cAAc;IAEzB,GAAI,EAAE,gBAAgB,QAAQ,OAAO,EAAE,gBAAgB,WAAW,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;IACpG,GAAI,OAAO,EAAE,SAAS,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrD,GAAI,OAAO,EAAE,QAAQ,WAAW,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;IAClD,GAAI,OAAO,EAAE,UAAU,YAAY,OAAO,SAAS,EAAE,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpF,GAAI,aAAa,EAAE,KAAK,MAAM,KAAA,IAAY,EAAE,OAAO,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC;GAChF,CAAC;EACH;EACA,oBAAoB,OAAO,MAAM;GAC/B,IAAI,CAAC,MAAM,gBACT,OAAO;GACT,MAAM,MAAM,eAAe,EAAE,WAAW,EAAE,UAAU;GACpD,UAAU;IAAE,MAAM;IAAoB,WAAW,EAAE;IAAW,IAAI;IAAU,YAAY,EAAE;GAAW,CAAC;GACtG,OAAO;EACT;EACA,oBAAoB,OAAO,MAAM;GAC/B,IAAI,CAAC,MAAM,gBACT,OAAO;GAIT,MAAM,aAAa,uBAAuB,EAAE,QAAQ;GACpD,IAAI,CAAC,cAAc,OAAO,EAAE,UAAU,cAAc,YAAY,OAAO,EAAE,UAAU,OAAO,UACxF,OAAO;GACT,MAAM,MAAM,KAAK,IAAI;GACrB,MAAM,SAAS,MAAM,MAAM,eAAe;IACxC,GAAG;IACH,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,SAAS;IACtB,GAAI,OAAO,EAAE,SAAS,UAAU,WAAW,EAAE,OAAO,EAAE,SAAS,MAAM,IAAI,CAAC;IAC1E,GAAI,OAAO,EAAE,SAAS,WAAW,WAAW,EAAE,QAAQ,EAAE,SAAS,OAAO,IAAI,CAAC;IAC7E,WAAW,OAAO,EAAE,SAAS,cAAc,WAAW,EAAE,SAAS,YAAY;IAC7E,WAAW;GACb,CAAC;GACD,IAAI,QACF,UAAU;IAAE,MAAM;IAAoB,WAAW,OAAO;IAAW,IAAI;IAAU,YAAY,OAAO;IAAI,UAAU;GAAO,CAAC;GAC5H,OAAO;EACT;EACA,qBAAqB,OAAO,MAAM;GAChC,MAAM,YAAY,YAAY,CAAC;GAC/B,IAAI,CAAC,MAAM,iBAAiB,CAAC,MAAM,gBACjC,OAAO;GACT,MAAM,YAAY,MAAM,MAAM,cAAc,EAAE,UAAU,CAAC,EAAA,CAAG,MAAK,MAAK,EAAE,OAAO,EAAE,UAAU;GAC3F,IAAI,CAAC,UACH,OAAO;GACT,MAAM,UAAU,MAAM,gBAAgB,UAAU,MAAM,WAAW,SAAS,WAAW,GAAG,EAAE,UAAU,OAAO,EAAE,OAAO,KAAK,IAAI,KAAA,CAAS;GACtI,IAAI,CAAC,SACH,OAAO;GACT,MAAM,SAAS,MAAM,MAAM,eAAe,OAAO;GACjD,IAAI,QACF,UAAU;IAAE,MAAM;IAAoB,WAAW,OAAO;IAAW,IAAI;IAAU,YAAY,OAAO;IAAI,UAAU;GAAO,CAAC;GAC5H,OAAO;EACT;EACA,oBAAoB,OAAO,MAAM;GAC/B,MAAM,MAAe,EAAE;GACvB,IAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAA,OAAgC,IAAI,MAAK,OAAM,OAAO,OAAO,QAAQ,GAClG,MAAM,IAAI,mBAAmB,yDAA4E;GAC3G,IAAI,CAAC,MAAM,eACT,OAAO,CAAC;GACV,MAAM,OAAO,MAAM,cAAc,KAAK,KAAK;GAC3C,MAAM,QAAQ,OAAO,YAAY,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,IAAI,GAAe,CAAC,CAAC,CAAC,IAAI,OAAM,cAAa,CAAC,WAAW,MAAM,KAAK,EAAE,UAAU,CAAC,CAAC,CAAU,CAAC,CAAC;GACzJ,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAI,MAAK,EAAE,eAAe,EAAE,CAAC,CAAC;GACpF,MAAM,aAAa,IAAI,IAAI,MAAM,QAAQ,IAAI,MAAM,IAAI,OAAM,SAAQ,CAAC,MAAM,MAAM,WAAW,IAAI,CAAC,CAAU,CAAC,CAAC;GAC9G,OAAO,eAAe,QAAO,SAAQ,WAAW,IAAI,IAAI,CAAC;EAC3D;CACF;AACF;;;;ACjGA,MAAMC,mBAAiB;;AAEvB,MAAM,mBAAmB;;AAKzB,SAAgB,mBAAmB,EAAE,MAAM,OAA6E;CACtH,MAAM,iBAA+D,IAAI,OAAO;CAChF,MAAM,gBAAwB,IAAI,YAAY;CAE9C,MAAM,gBAAgB,aAA0C;EAC9D,MAAM,aAAa,OAAO,aAAa,WAAW,SAAS,CAAC,CAAC,YAAY,KAAA;EACzE,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,qBAAqB,OAAO,QAAQ,EAAE,GAAG;EAC3D,OAAO;CACT;CAEA,MAAM,YAAY,QAAkC;EAClD,MAAM,aAAa,SAAS,CAAC,CAAC;EAC9B,MAAM,OAAO,WAAW,QAAQ,GAAG,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC;EAC1D,MAAM,eAAe,mBAAmB,UAAU;EAClD,MAAM,mBAAmB,yBAAyB,QAAQ,GAAG,UAAU;EACvE,OAAO;GACL,KAAK,KAAK;GACV,OAAO,KAAK;GACZ,YAAY,KAAK;GACjB,OAAO,cAAc,UAAU;GAC/B,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;GAC7C,SAAS,KAAK,QAAQ,KAAI,OAAM;IAC9B,QAAQ,EAAE;IACV,QAAQ,EAAE,WAAW;IACrB,GAAI,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;IAC5C,GAAI,EAAE,UAAU,KAAA,IAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;IAClD,QAAQ,EAAE;GACZ,EAAE;GACF,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;GACvC,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EACjD;CACF;;CAGA,MAAM,cAAc,eAClB,wBAAwB,QAAQ,GAAG,UAAU,CAAC,CAAC,SAAQ,MAAK,EAAE,WAAW,SAAS,YAAY,EAAE,WAAW,QAAQ,CAAC,EAAE,WAAW,KAAK,IAAI,CAAC,CAAC;;CAG9I,MAAM,WAAW,YAAgC,cAAiC,CAAC,MAAY;EAC7F,IAAI,IAAI,cACN,IAAI,aAAa;OAEjB,eAAe,QAAQ,GAAG,SAAS,GAAG,EAAE,WAAW,KAAA,EAAU,CAAC;EAGhE,MAAM,SAAS,WAAW;EAC1B,IAAI,UAAU,YAAY,SAAS,QAAQ,IAAI,WAAW,EAAE,KAAK,CAAC,WAAW,UAAU,CAAC,CAAC,SAAS,QAAQ,IAAI,OAAQ,GACpH,OAAO,QAAQ,IAAI;EACrB,KAAU,iBAAiB,CAAC,CAAC,YAAY,KAAA,CAAS;CACpD;CAEA,OAAO;EAAE;EAAU;EAAS;EAAc;EAAU;EAAY;CAAQ;AAC1E;AAEA,SAAgB,mBAAmB,EAAE,QAAqJ;CACxL,MAAM,EAAE,UAAU,SAAS,cAAc,UAAU,YAAY,YAAY;CAC3E,OAAO;EACL,sBAAsB,EAAE,WAAW,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE;EACzE,mBAAmB,MAAM;GACvB,MAAM,aAAa,aAAa,EAAE,QAAQ;GAC1C,MAAM,MAAM,OAAO,EAAE,QAAQ,WAAW,EAAE,IAAI,KAAK,IAAI;GACvD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,uBAAuB;GACzC,IAAI,IAAI,SAASA,kBACf,MAAM,IAAI,MAAM,8BAA8BA,iBAAe,aAAa;GAC5E,sBAAsB,QAAQ,GAAG,YAAY;IAAE,MAAM;IAAU,OAAO;GAAI,CAAC;GAC3E,QAAQ,UAAU;GAClB,OAAO,SAAS,WAAW,GAAG;EAChC;EACA,mBAAmB,MAAM;GACvB,MAAM,aAAa,aAAa,EAAE,QAAQ;GAC1C,IAAI,EAAE,UAAU,KAAA,MAAc,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,SAASA,mBAC5E,MAAM,IAAI,mBAAmB,qCAAqCA,iBAAe,aAAa;GAChG,MAAM,SAAS,EAAE,gBAAgB,CAAC;GAClC,IAAI,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,KAAK,OAAO,OAAO,MAAM,CAAC,CAAC,MAAK,MAAK,OAAO,MAAM,YAAY,EAAE,SAASA,gBAAc,GAC3I,MAAM,IAAI,mBAAmB,8CAA8C;GAC7E,4BAA4B,QAAQ,GAAG,YAAY;IAAE,GAAI,EAAE,UAAU,KAAA,IAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;IAAI,cAAc;GAAO,CAAC;GACjI,QAAQ,UAAU;GAClB,OAAO,SAAS,WAAW,GAAG;EAChC;EACA,gBAAgB,MAAM;GACpB,MAAM,aAAa,aAAa,EAAE,QAAQ;GAC1C,MAAM,SAAS,WAAW,UAAU;GACpC,IAAI;GACJ,IAAI,OAAO,EAAE,YAAY,UACvB,UAAU,uBAAuB,QAAQ,GAAG,YAAY,EAAE,OAAO;QAE9D;IACH,UAAU,wBAAwB,QAAQ,GAAG,UAAU,CAAC,CAAC,SAAS;IAClE,yBAAyB,QAAQ,GAAG,UAAU;GAChD;GACA,IAAI,SACF,QAAQ,YAAY,OAAO,QAAO,MAAK,CAAC,WAAW,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;GAC7E,OAAO;IAAE;IAAS,UAAU,SAAS,WAAW,GAAG;GAAE;EACvD;EACA,sBAAsB,MAAM;GAC1B,MAAM,aAAa,aAAa,EAAE,QAAQ;GAC1C,MAAM,SAAS,EAAE;GACjB,MAAM,MAAM,OAAO,WAAW,YAAY,WAAW,OAAQ,OAA6B,MAAM,KAAA;GAChG,IAAI,WAAW,YAAY,WAAW,WAAW,OAAO,QAAQ,UAC9D,MAAM,IAAI,mBAAmB,kDAA8C;GAC7E,MAAM,UAAU,uBAAuB,QAAQ,GAAG,YAAY,OAAO,QAAQ,WAAW,EAAE,IAAI,IAAI,MAA4B;GAC9H,IAAI,YAAY,cACd,MAAM,IAAI,MAAM,aAAa,OAAO,QAAQ,WAAW,cAAc,QAAQ,GAAG,OAAO,MAAM,EAAE,aAAa,OAAO,WAAW,MAAM,EAAE;GACxI,IAAI,YAAY,kBACd,QAAQ,UAAU;GACpB,OAAO,SAAS,WAAW,GAAG;EAChC;EACA,gBAAgB,MAAM;GACpB,MAAM,aAAa,aAAa,EAAE,QAAQ;GAC1C,IAAI,OAAO,EAAE,YAAY,YAAY,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,SAAS,kBACnF,MAAM,IAAI,mBAAmB,0DAA0D,iBAAiB,aAAa;GACvH,IAAI,CAAC,mBAAmB,QAAQ,GAAG,YAAY,EAAE,SAAS,EAAE,KAAK,GAC/D,MAAM,IAAI,MAAM,2BAA2B,EAAE,QAAQ,OAAO,WAAW,MAAM,EAAE;GACjF,OAAO,SAAS,WAAW,GAAG;EAChC;CACF;AACF;;;AC/HA,MAAa,mBAAmB;;AAE9B,eAAe,EACjB;AAOA,SAAS,SAAS,OAAgB,MAAsB;CACtD,IAAI,OAAO,UAAU,YAAY,UAAU,IACzC,MAAM,IAAI,mBAAmB,GAAG,KAAK,6BAA6B;CACpE,OAAO;AACT;AAEA,SAAgB,uBAAuB,EAAE,MAAM,aAAa,SAAS,oBAQnE;CACA,MAAM,0BAAU,IAAI,IAAqB;CACzC,MAAM,0BAAU,IAAI,QAA+B;CACnD,MAAM,QAAQ,MAAgB,WAA6B;EACzD,IAAI,YAAY,IAAI,GAClB,KAAK,KAAK,MAAM;CACpB;CAEA,OAAO;EACL,SAAS;GACP,sBAAsB,GAAG,SAAS;IAChC,MAAM,YAAY,SAAS,EAAE,WAAW,WAAW;IACnD,MAAM,SAAS,SAAS,EAAE,QAAQ,QAAQ;IAC1C,MAAM,OAAO,SAAS,EAAE,MAAM,MAAM;IACpC,MAAM,WAAW,SAAS,EAAE,UAAU,UAAU;IAChD,IAAI,KAAK,SAAA,OACP,MAAM,IAAI,mBAAmB,uBAAuB,sBAAsB,aAAa;IACzF,MAAM,MAAM,QAAQ,IAAI,IAAI,qBAAK,IAAI,IAAY;IACjD,QAAQ,IAAI,MAAM,GAAG;IACrB,IAAI,IAAI,QAAQ,OAAO,eACrB,MAAM,IAAI,MAAM,gCAAgC,IAAI,KAAK,mBAAmB,OAAO,cAAc,mBAAmB;IACtH,MAAM,QAAQ,WAAW;IACzB,MAAM,aAAa,IAAI,gBAAgB;IACvC,IAAI,IAAI,KAAK;IACb,QAAQ,IAAI,OAAO;KAAE;KAAM;IAAW,CAAC;IACvC,KAAU,SAAS,WAAW;KAAE;KAAQ;KAAM;IAAS,GAAG;KACxD,QAAQ,WAAW;KACnB,WAAW,QAAQ,UAAU,KAAK,MAAM;MAAE,MAAM;MAAkB;MAAO;MAAQ;KAAM,CAAC;IAC1F,CAAC,CAAC,CAAC,MACD,QAAO,KAAK,MAAM;KAAE,MAAM;KAAiB;KAAO;IAAI,CAAC,IACtD,QAAiB,KAAK,MAAM;KAAE,MAAM;KAAiB;KAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IAAE,CAAC,CACxH,CAAC,CAAC,cAAc;KACd,IAAI,OAAO,KAAK;KAChB,QAAQ,OAAO,KAAK;IACtB,CAAC;IACD,OAAO,EAAE,MAAM;GACjB;GACA,4BAA4B,GAAG,SAAS;IACtC,MAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,QAAQ,IAAI,EAAE,KAAK,IAAI,KAAA;IACnE,IAAI,CAAC,SAAS,MAAM,SAAS,MAC3B,OAAO,EAAE,WAAW,MAAM;IAC5B,MAAM,WAAW,MAAM;IACvB,OAAO,EAAE,WAAW,KAAK;GAC3B;GACA,sBAAsB,OAAM,OAAM,EAAE,MAAM,MAAM,KAAK,cAAc,SAAS,EAAE,WAAW,WAAW,CAAC,EAAE;GACvG,2BAA2B,OAAO,MAAM;IACtC,MAAM,KAAK,eAAe,SAAS,EAAE,WAAW,WAAW,GAAG,SAAS,EAAE,KAAK,KAAK,CAAC;GACtF;EACF;EACA,YAAY,MAAM;GAChB,KAAK,MAAM,SAAS,QAAQ,IAAI,IAAI,KAAK,CAAC,GACxC,QAAQ,IAAI,KAAK,CAAC,EAAE,WAAW,MAAM;EACzC;CACF;AACF;;;;;;;;;AAUA,SAAgB,qBACd,SACA,MAC8G;CAC9G,MAAM,SAAS,uBAAuB,IAAI;CAC1C,OAAO;EACL,SAAS;GAAE,GAAG,QAAQ;GAAS,GAAG,OAAO;EAAQ;EACjD,YAAY,MAAM;GAChB,QAAQ,YAAY,IAAI;GACxB,OAAO,YAAY,IAAI;EACzB;CACF;AACF;;;AChHA,SAAgB,sBAAsB,EAAE,QAItC;CACA,OAAO;EACL,SAAS;GACP,yBAAyB,GAAG,SAAS;IAClC,CAAC,KAAK,iCAAiB,IAAI,IAAI,EAAA,CAAG,IAAI,EAAE,MAAM;IAC/C,KAAK,QAAQ,aAAa,EAAE,MAAM;IAClC,OAAO,EAAE,IAAI,KAAK;GACpB;GACA,2BAA2B,GAAG,SAAS;IACrC,KAAK,cAAc,OAAO,EAAE,MAAM;IAClC,KAAK,QAAQ,eAAe,EAAE,MAAM;IACpC,OAAO,EAAE,IAAI,KAAK;GACpB;GACA,oBAAoB,GAAG,SAAS,KAAK,QAAQ,QAAQ,EAAE,WAAW,EAAE,UAAU,KAAK,gCAAgB,IAAI,IAAI,CAAC;EAC9G;EACA,YAAY,MAAM;GAChB,KAAK,MAAM,UAAU,KAAK,gBAAgB,CAAC,GACzC,KAAK,QAAQ,eAAe,MAAM;EACtC;CACF;AACF;;;AC6BA,MAAMC,uBAAqB;AAC3B,MAAM,kBAAkB;AACxB,MAAM,uBAAuB;AAC7B,MAAMC,YAAU;AAChB,MAAM,iCAAiB,IAAI,IAAI;CAAC;CAAS;CAAO;AAAiB,CAAC;AAElE,MAAM,cAAc;;AAGpB,IAAa,8BAAb,cAAiD,MAAM;CACrD,OAAgB,aAAa;CAC7B;CACA,YAAY,SAAiB,MAAiC;EAC5D,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;CACd;AACF;;AAGA,SAAS,eAAe,KAAuB;CAC7C,IAAI,eAAe,yBAAyB,IAAI,YAC9C,OAAO,IAAI,4BAA4B,IAAI,SAAS;EAAE,cAAc,IAAI;EAAM,YAAY,CAAC,GAAG,IAAI,UAAU;CAAE,CAAC;CACjH,OAAO;AACT;;AAGA,SAAS,UAAU,MAAuB;CACxC,IAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,IAC9C,MAAM,IAAI,mBAAmB,kCAAkC;CACjE,MAAM,QAAQ,KAAK,KAAK;CACxB,IAAI,MAAM,SAAS,iBACjB,MAAM,IAAI,mBAAmB,uBAAuB,gBAAgB,aAAa;CACnF,MAAM,WAAW,MAAM,MAAM,QAAQ;CACrC,IAAI,sBAAsB,KAAK,KAAK,KAAK,MAAM,SAAS,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,SAAS,SAAS,IAAI,GAC/G,MAAM,IAAI,mBAAmB,IAAI,MAAM,mFAAmF;CAC5H,OAAO;AACT;AAEA,SAAS,UAAU,MAAe,MAAsB;CACtD,IAAI,OAAO,SAAS,YAAY,CAACA,UAAQ,KAAK,IAAI,KAAK,SAAS,OAAO,SAAS,MAC9E,MAAM,IAAI,mBAAmB,GAAG,KAAK,qDAAqD;CAC5F,OAAO;AACT;AAEA,SAAS,aAAa,MAAuB;CAC3C,IAAI,CAAC,gBAAgB,IAAI,GACvB,MAAM,IAAI,mBAAmB,gFAAgF;CAC/G,OAAO;AACT;AAEA,SAAS,UAAU,MAAsC;CACvD,IAAI,SAAS,WAAW,SAAS,aAC/B,MAAM,IAAI,mBAAmB,0CAAsC;CACrE,OAAO;AACT;AAEA,SAAS,eAAe,OAAiD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC,CAAC,OAAM,MAAK,OAAO,MAAM,QAAQ;AACtI;AAEA,SAAS,eAAe,QAAkC;CACxD,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GACvE,MAAM,IAAI,mBAAmB,sCAAsC;CACrE,IAAI,KAAK,UAAU,MAAM,CAAC,CAAC,SAAS,sBAClC,MAAM,IAAI,mBAAmB,yBAAyB,qBAAqB,QAAQ;CACrF,MAAM,IAAI;CACV,aAAa,EAAE,IAAI;CACnB,IAAI,EAAE,cAAc,KAAA,KAAa,CAAC,eAAe,IAAI,EAAE,SAAmB,GACxE,MAAM,IAAI,mBAAmB,kDAAkD;CACjF,MAAM,aAAa,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,KAAK,MAAM;CACzE,IAAI,SAAS;CACb,IAAI,OAAO,EAAE,QAAQ,UAAU;EAC7B,IAAI;GACF,SAAS,CAAC,SAAS,QAAQ,CAAC,CAAC,SAAS,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ;EAC/D,QACM,CAAC;EACP,IAAI,CAAC,QACH,MAAM,IAAI,mBAAmB,6BAA6B;CAC9D;CACA,IAAI,CAAC,cAAc,CAAC,QAClB,MAAM,IAAI,mBAAmB,iDAAiD;CAChF,IAAI,EAAE,SAAS,KAAA,MAAc,CAAC,MAAM,QAAQ,EAAE,IAAI,KAAK,CAAC,EAAE,KAAK,OAAM,MAAK,OAAO,MAAM,QAAQ,IAC7F,MAAM,IAAI,mBAAmB,uBAAuB;CACtD,KAAK,MAAM,OAAO,CAAC,OAAO,SAAS,GACjC,IAAI,EAAE,SAAS,KAAA,KAAa,CAAC,eAAe,EAAE,IAAI,GAChD,MAAM,IAAI,mBAAmB,GAAG,IAAI,4BAA4B;CAEpE,OAAO;AACT;;AAGA,SAAS,gBAA4E;CACnF,MAAM,WAAqB,CAAC;CAC5B,OAAO;EACL;EACA,aAAa,SAAS;GACpB,IAAI,SAAS,SAAS,KACpB,SAAS,KAAK,IAAI;EACtB;CACF;AACF;;AAGA,MAAM,oBAAoB;;;;;;AAO1B,eAAe,QAAW,KAA0C,IAAY,MAA0B;CACxG,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,OAAO,IAAI,WAAW,MAAM;CAClC,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,MAAM,IAAI,SAAgB,GAAG,WAAW;GACjE,QAAQ,iBAAiB;IACvB,WAAW,MAAM;IACjB,uBAAO,IAAI,MAAM,GAAG,KAAK,oBAAoB,KAAK,MAAM,KAAK,GAAI,EAAE,mBAAmB,CAAC;GACzF,GAAG,EAAE;EACP,CAAC,CAAC,CAAC;CACL,SACO,KAAK;EACV,IAAI,WAAW,OAAO,SAAS;GAC7B,IAAI;GACJ,MAAM,QAAQ,KAAK,CAAC,KAAK,YAAY,KAAA,CAAS,GAAG,IAAI,SAAS,YAAY;IACxE,QAAQ,WAAW,SAAS,iBAAiB;GAC/C,CAAC,CAAC,CAAC;GACH,aAAa,KAAK;EACpB;EACA,MAAM;CACR,UACQ;EACN,aAAa,KAAK;CACpB;AACF;;;;;;AAOA,eAAsB,eAAkB,SAA4C,MAAgB,OAAe,QAAiC,KAAuC;CACzL,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,+FAA+F;CACjH,IAAI,CAAC,QAAQ,QAAQ,GAAG;EACtB,QAAQ,QAAQ,MAAM;GAAE;GAAO,GAAG;GAAQ,IAAI;GAAO,SAAS;EAA6B,CAAC;EAC5F,MAAM,IAAI,MAAM,WAAW;CAC7B;CACA,IAAI;EACF,MAAM,SAAS,MAAM,IAAI;EACzB,QAAQ,QAAQ,MAAM;GAAE;GAAO,GAAG;GAAQ,IAAI;EAAK,CAAC;EACpD,OAAO;CACT,SACO,KAAK;EACV,QAAQ,QAAQ,MAAM;GAAE;GAAO,GAAG;GAAQ,IAAI;GAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EAAE,CAAC;EAC9G,MAAM;CACR;AACF;AAEA,SAAgB,6BAA6B,EAAE,MAAM,KAAK,WAAW,aAAa,WAOtD;CAC1B,MAAM,YAAY,SAAS,aAAaD;CACxC,MAAM,KAAK,SAAS;CACpB,MAAM,eAAuB,IAAI,OAAO;;CAExC,MAAM,aAAa,YACjB,iBAAiB;EAAE;EAAS,KAAK,QAAQ;EAAG,MAAM,QAAQ;EAAG,QAAQ,OAAO;CAAE,CAAC,CAAC,CAAC,QAAO,MAAK,EAAE,WAAW,MAAM,CAAC,CAAC,KAAI,MAAK,EAAE,IAAI;CAEnI,MAAM,WAAc,MAAgB,OAAe,QAAiC,QAClF,eAAe,SAAS,MAAM,OAAO,QAAQ,GAAG;CAElD,MAAM,WAAW,YAAmC,UAAU;EAAE,MAAM;EAAmB;CAAQ,CAAC;;CAGlG,MAAM,gBAAsB;EAC1B,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CACxE;;CAGA,MAAM,yBAA+B;EACnC,MAAM,aAAa,IAAI,cAAc;EACrC,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,UAAU;CAC9E;;CAGA,MAAM,aAAa,KAA4C,MAAc,YAA8B;EACzG,MAAM,OAAO,IAAI,aAAa,CAAC,CAAC;EAChC,IAAI,SAAS,KAAA,KAAa,KAAK,SAAS,IAAI,MAAM,SAChD,OAAO;EACT,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,MAAM,IAAI,IAAI,KAAK,QAAO,MAAK,MAAM,IAAI,EAAE,CAAC;EAC/E,OAAO;CACT;;CAGA,MAAM,WAAW,SAAiB,MAAc,WAC9C,UAAU,OAAO,CAAC,CAAC,KAAI,SAAQ,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,MAAK,QAAO,WAAW,SAAS,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC;CAE3G,OAAO;EACL,oBAAoB,GAAG,SAAS,QAAQ,MAAM,mBAAmB;GAAE,MAAM,EAAE;GAAM,MAAM,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,eAAe,IAAI,KAAA;EAAU,GAAG,YAAY;GAC9K,MAAM,OAAO,UAAU,EAAE,IAAI;GAC7B,MAAM,OAAO,UAAU,EAAE,IAAI;GAC7B,IAAI,EAAE,UAAU,KAAA,KAAa,EAAE,UAAU,QACvC,MAAM,IAAI,mBAAmB,6DAA2D;GAC1F,MAAM,EAAE,UAAU,eAAe,cAAc;GAC/C,MAAM,OAAO,QAAQ;GACrB,IAAI,SAAS,SAAS;IACpB,MAAM,SAAS,MAAM,SAAQ,WAAU,qBAAqB;KAC1D,QAAQ;KACR,OAAO;KACP,KAAK;KACL;KACA,QAAQ,OAAO;KACf;KACA,IAAI,mBAAmB,IAAI,MAAM;KACjC,GAAI,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,QAAQ,EAAE,OAAO,QAAO,MAAK,OAAO,MAAM,QAAQ,EAAE,IAAI,CAAC;KACzF,GAAI,EAAE,QAAQ,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;KACtC,GAAI,EAAE,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACpD,CAAC,GAAG,WAAW,cAAc,MAAM;IACnC,QAAQ;IACR,QAAQ,QAAQ;IAChB,MAAM,UAAU,OAAO,SAAS,SAAS,uBAAuB,OAAO,QAAQ,KAAK,IAAI,MAAM;IAC9F,OAAO;KAAE,WAAW,CAAC,GAAG,OAAO,SAAS;KAAG,SAAS,aAAa,OAAO,UAAU,KAAK,IAAI,EAAE,IAAI,OAAO,cAAc,OAAO,OAAO,GAAG;KAAW;IAAS;GAC7J;GACA,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,SAAQ,WAAU,yBAAyB;KACxD,QAAQ;KACR,OAAO;KACP,KAAK;KACL;KACA,QAAQ,OAAO;KACf;KACA,IAAI,mBAAmB,IAAI,MAAM;KACjC,GAAI,OAAO,EAAE,cAAc,WAAW,EAAE,WAAW,EAAE,UAAU,IAAI,CAAC;KACpE,GAAI,EAAE,cAAc,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACpD,CAAC,GAAG,WAAW,cAAc,MAAM;GACrC,SACO,KAAK;IACV,IAAI,eAAe,yBAAyB,IAAI,SAAS,UACvD,MAAM,IAAI,MAAM,6DAA6D;IAC/E,MAAM,eAAe,GAAG;GAC1B;GAEA,IAAI,CAAC,UAAU,qBAAqB,OAAO,MAAM,IAAI,GACnD,iBAAiB;GACnB,QAAQ,YAAY;GACpB,MAAM,OAAO,OAAO,SAAS,SAAS,IAAI,KAAK,OAAO,SAAS,KAAK,IAAI,MAAM;GAC9E,OAAO;IAAE,WAAW,CAAC,OAAO,IAAI;IAAG,SAAS,cAAc,OAAO,KAAK,KAAK,OAAO,WAAW,GAAG;IAAQ;GAAS;EACnH,CAAC;EAED,mBAAmB,GAAG,SAAS,QAAQ,MAAM,kBAAkB;GAAE,MAAM,EAAE;GAAM,MAAM,EAAE;EAAK,GAAG,YAAY;GACzG,MAAM,OAAO,UAAU,EAAE,IAAI;GAC7B,MAAM,OAAO,UAAU,EAAE,MAAM,MAAM;GACrC,IAAI,SAAS,SAAS;IACpB,MAAM,MAAM,QAAQ,UAAU,MAAM,UAAU;IAC9C,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,wBAAwB,KAAK,6DAA6D;IAC5G,OAAO,KAAK;KAAE,WAAW;KAAM,OAAO;IAAK,CAAC;IAC5C,UAAU,iBAAiB,MAAM,KAAK;IACtC,QAAQ;IACR,QAAQ,QAAQ;IAChB,OAAO;KAAE,SAAS;KAAM,SAAS,YAAY,KAAK;IAAG;GACvD;GACA,MAAM,MAAM,QAAQ,cAAc,IAAI;GACtC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,4BAA4B,KAAK,kBAAkB;GACrE,yBAAyB;IAAE;IAAK,KAAK,QAAQ;IAAG,MAAM,QAAQ;IAAG,QAAQ,OAAO;GAAE,CAAC;GACnF,IAAI,CAAC,UAAU,qBAAqB,MAAM,KAAK,GAC7C,iBAAiB;GACnB,QAAQ,YAAY;GACpB,OAAO;IAAE,SAAS;IAAM,SAAS,YAAY,KAAK;GAAG;EACvD,CAAC;EAED,mBAAmB,GAAG,SAAS,QAAQ,MAAM,kBAAkB;GAAE,MAAM,EAAE;GAAM,MAAM,EAAE;EAAK,GAAG,YAAY;GACzG,MAAM,OAAO,UAAU,EAAE,IAAI;GAC7B,MAAM,OAAO,UAAU,EAAE,MAAM,MAAM;GACrC,IAAI,SAAS,SACX,MAAM,IAAI,MAAM,gEAAgE;GAClF,MAAM,MAAM,QAAQ,cAAc,IAAI;GACtC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,4BAA4B,KAAK,kBAAkB;GACrE,MAAM,SAAS,MAAM,SAAQ,WAAU,yBAAyB;IAAE;IAAK,KAAK,QAAQ;IAAG,MAAM,QAAQ;IAAG,QAAQ,OAAO;IAAG,IAAI,mBAAmB,IAAI,MAAM;GAAE,CAAC,GAAG,WAAW,YAAY,MAAM;GAC9L,IAAI,OAAO,UACT,OAAO;IAAE,SAAS,OAAO;IAAM,UAAU;IAAM,SAAS,IAAI,OAAO,KAAK,yBAAyB,OAAO,SAAS,KAAK,OAAO,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK;GAAK;GAC5J,iBAAiB;GACjB,QAAQ,YAAY;GACpB,OAAO;IAAE,SAAS,OAAO;IAAM,UAAU;IAAO,SAAS,YAAY,OAAO,KAAK,MAAM,OAAO;GAAa;EAC7G,CAAC;EAED,4BAA4B,GAAG,SAAS,QAAQ,MAAM,2BAA2B;GAAE,MAAM,EAAE;GAAM,MAAM,OAAO,EAAE,WAAW,WAAW,EAAE,OAAO,MAAM,GAAG,eAAe,IAAI,KAAA;EAAU,GAAG,YAAY;GAClM,MAAM,OAAO,UAAU,EAAE,MAAM,MAAM;GACrC,MAAM,OAAO,UAAU,EAAE,MAAM;GAC/B,IAAI,EAAE,UAAU,QACd,MAAM,IAAI,mBAAmB,oEAAkE;GACjG,MAAM,MAAM,QAAQ,cAAc,IAAI;GACtC,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,4BAA4B,KAAK,kBAAkB;GACrE,MAAM,EAAE,UAAU,eAAe,cAAc;GAC/C,MAAM,SAAS,MAAM,SAAQ,WAAU,sBAAsB;IAAE;IAAK,QAAQ;IAAM,KAAK,QAAQ;IAAG,MAAM,QAAQ;IAAG,QAAQ,OAAO;IAAG;IAAY,IAAI,mBAAmB,IAAI,MAAM;GAAE,CAAC,GAAG,WAAW,cAAc,KAAK,QAAQ,MAAM,CAAC,CAClO,OAAO,QAAiB;IACvB,MAAM,eAAe,GAAG;GAC1B,CAAC;GACH,iBAAiB;GACjB,QAAQ,YAAY;GACpB,MAAM,OAAO,OAAO,SAAS,SAAS,IAAI,KAAK,OAAO,SAAS,KAAK,IAAI,MAAM;GAC9E,OAAO;IAAE,MAAM,OAAO;IAAM,QAAQ,OAAO;IAAQ,SAAS,IAAI,OAAO,KAAK,mBAAmB,OAAO,OAAO,MAAM,IAAI,OAAO,WAAW,GAAG;IAAQ;GAAS;EAC/J,CAAC;EAED,eAAe,GAAG,SAAS,QAAQ,MAAM,cAAc;GAAE,MAAO,EAAE,QAA2C;GAAM,OAAO,EAAE,SAAS;EAAO,SAAS;GACnJ,MAAM,SAAS,eAAe,EAAE,MAAM;GACtC,IAAI,EAAE,UAAU,KAAA,KAAa,EAAE,UAAU,UAAU,EAAE,UAAU,WAC7D,MAAM,IAAI,mBAAmB,wCAAoC;GACnE,IAAI,EAAE,iBAAiB,KAAA,MAAc,OAAO,EAAE,iBAAiB,YAAY,EAAE,aAAa,SAAS,uBACjG,MAAM,IAAI,mBAAmB,gCAAgC;GAC/D,IAAI,EAAE,UAAU,cAAc,OAAO,EAAE,QAAQ,YAAY,CAAC,EAAE,MAC5D,MAAM,IAAI,mBAAmB,+CAAgD;GAE/E,MAAM,SAAS,EAAE,UAAU,YAAY,KAAK,UAAU,cAAc,EAAE,GAAI,IAAI,QAAQ;GACtF,MAAM,MAAM,EAAE,UAAU,YAAY,KAAK,UAAU,cAAc,YAAY,MAAM,KAAK,MAAM,IAAI;GAClG,MAAM,SAAS,gBAAgB,cAAc,EAAE,SAAS,QAAQ;IAAE,MAAM,QAAQ;IAAG;IAAK,QAAQ,OAAO;GAAE,CAAC,GAAG,MAAM;GACnH,MAAM,QAAQ,IAAI,qBAAqB,KAAK,6BAA6B,IAAI,YAAY,CAAC;GAE1F,IAAI,CAAC,OAAO,OACV,oBAAoB,OAAO,OAAO,MAAM,KAAA,CAAS;QAC9C,IAAI,EAAE,cACT,oBAAoB,OAAO,OAAO,MAAM,EAAE,YAAY;GAExD,MAAM,UAAU,OAAO,WAAW,UAAU,gBAAgB,IAAI,aAAa,CAAC,CAAC,aAAa,OAAO,IAAI,IAAI,KAAA;GAC3G,IAAI,SACF,YAAY,EAAE,aAAa,QAAQ,CAAC;GAEtC,KAAK,WAAW,OAAO,OAAO,IAAI;GAClC,QAAQ;GACR,QAAQ,MAAM;GACd,OAAO;IAAE,MAAM,OAAO;IAAM,SAAS,OAAO,WAAW;GAAQ;EACjE,CAAC;EAED,eAAe,GAAG,SAAS,QAAQ,MAAM,cAAc,EAAE,MAAM,EAAE,KAAK,SAAS;GAC7E,MAAM,OAAO,aAAa,EAAE,IAAI;GAChC,MAAM,OAAO,cAAc,QAAQ;IAAE,MAAM,QAAQ;IAAG,KAAK,QAAQ;IAAG,QAAQ,OAAO;GAAE,CAAC;GACxF,IAAI;IACF,gBAAgB,MAAM,IAAI;GAC5B,SACO,KAAK;IAEV,IAAI,CAAC,WAAW,IAAI,KAAK,iBAAiB,KAAK,eAAe,QAAQ,IAAI,UAAU,EAAE,GACpF,OAAO,EAAE,SAAS,MAAM;IAC1B,MAAM;GACR;GACA,MAAM,UAAU,mBAAmB,IAAI,aAAa,CAAC,CAAC,aAAa,IAAI;GACvE,IAAI,SACF,YAAY,EAAE,aAAa,QAAQ,CAAC;GACtC,KAAK,WAAW,OAAO,IAAI;GAC3B,QAAQ;GACR,QAAQ,MAAM;GACd,OAAO,EAAE,SAAS,KAAK;EACzB,CAAC;EAED,sBAAsB,GAAG,SAAS,QAAQ,MAAM,qBAAqB;GAAE,MAAM,EAAE;GAAM,OAAO,EAAE,SAAS;EAAO,SAAS;GACrH,IAAI,EAAE,UAAU,KAAA,KAAa,EAAE,UAAU,UAAU,EAAE,UAAU,WAC7D,MAAM,IAAI,mBAAmB,wCAAoC;GACnE,MAAM,UAAU,EAAE,UAAU;GAC5B,IAAI,YAAY,OAAO,EAAE,QAAQ,YAAY,CAAC,EAAE,MAC9C,MAAM,IAAI,mBAAmB,8CAA+C;GAC9E,MAAM,SAAS,gBAAgB;IAAE,MAAM,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;IAAI,GAAI,UAAU;KAAE,OAAO;KAAW,KAAK,EAAE;IAAI,IAAI,CAAC;GAAG,GAAG;IACvI,SAAS,KAAK,QAAQ,GAAG,OAAO,CAAC;IAEjC,sBAAsB,QAAQ;KAC5B,MAAM,SAAS,KAAK,UAAU,cAAc,GAAG;KAC/C,OAAO,KAAK,UAAU,cAAc,YAAY,MAAM,KAAK,MAAM;IACnE;GACF,CAAC;GAED,IAAI,WAAW,CAAC,UAAU,qBAAqB,OAAO,MAAM,IAAI,GAC9D,iBAAiB;GACnB,QAAQ,YAAY;GACpB,OAAO;EACT,CAAC;CAEH;AACF;;AAGA,SAAgB,sBAAsB,SAAqD;CACzF,OAAO,SAAS,QAAQ,MAAM;AAChC;;;;AChbA,MAAM,kBAAkB;AAExB,MAAM,oBAAuC;CAAC;CAAQ;CAAU;AAAO;AAEvE,SAAS,QAAQ,OAAiC;CAChD,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,UAAU;AAC1E;;;;;;;;AASA,SAAgB,aAAa,OAAqC;CAChE,IAAI,CAAC,SAAS,OAAO,UAAU,UAC7B,OAAO;CACT,MAAM,EAAE,MAAM,QAAQ,QAAQ,cAAc;CAC5C,IAAI,OAAO,SAAS,YAAY,CAAC,kBAAkB,SAAS,IAAI,KAAK,CAAC,QAAQ,MAAM,GAClF,OAAO;CACT,IAAI,cAAc,KAAA,KAAa,CAAC,QAAQ,SAAS,GAC/C,OAAO;CACT,IAAI,WAAW,KAAA,GACb,OAAO;CACT,IAAI,CAAC,UAAU,OAAO,WAAW,UAC/B,OAAO;CACT,MAAM,EAAE,IAAI,SAAS;CACrB,OAAO,QAAQ,EAAE,MAAM,SAAS,KAAA,KAAa,QAAQ,IAAI;AAC3D;;;;ACnBA,MAAM,wBAAwB;;AAG9B,MAAM,8BAAc,IAAI,IAAI;CAAC;CAAa;CAAa;CAAa;AAAM,CAAC;;AAG3E,IAAa,0BAAb,cAA6C,MAAM;CACjD,YAAY,WAAmB;EAC7B,MAAM,iBAAiB,UAAU,wKAAwK;EACzM,KAAK,OAAO;CACd;AACF;AASA,SAAgB,gBAAgB,EAAE,SAA6C;CAC7E,MAAM,QAAQ,sBAAsB;CACpC,MAAM,QAAQ,OAAO,WAAmB,WAAmB,OACzD,MAAM,mBAAmB,MAAM,iBAAiB,WAAW,WAAW,EAAE,IAAI,MAAM,MAAM,WAAW,WAAW,EAAE;CAClH,MAAM,SAAS,OAAO,WAAmB,WAAmB,WAA4C;EACtG,IAAI,MAAM,mBACR,MAAM,MAAM,kBAAkB,WAAW,WAAW,MAAM;OAE1D,MAAM,OAAO,WAAW,WAAW,MAAM;CAC7C;;CAEA,MAAM,0BAAU,IAAI,IAAgE;;CAEpF,MAAM,6BAAa,IAAI,IAAY;CAEnC,MAAM,eAAe,QAAgB,WAA2B;EAC9D,MAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC;EAClG,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,WAAW;GAAE;GAAQ,GAAG;EAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK;CACrF;CAEA,MAAM,UAAU,cAA6B;EAC3C,MAAM,IAAI,mBAAmB,cAAc,UAAU,8FAA8F;CACrJ;CAEA,OAAO;EACL;EACA,MAAM,IAAO,QAAgB,QAAoD,MAAoC;GACnH,MAAM,EAAE,WAAW,cAAc;GACjC,IAAI,cAAc,KAAA,GAChB,OAAO,KAAK;GACd,IAAI,OAAO,cAAc,YAAY,UAAU,WAAW,KAAK,UAAU,SAAS,uBAChF,MAAM,IAAI,mBAAmB,mDAAmD,sBAAsB,aAAa;GACrH,MAAM,KAAK,YAAY,QAAQ,MAAM;GACrC,MAAM,MAAM,GAAG,UAAU,IAAI;GAE7B,MAAM,OAAO,QAAQ,IAAI,GAAG;GAC5B,IAAI,MAAM;IACR,IAAI,KAAK,gBAAgB,IACvB,OAAO,SAAS;IAClB,OAAO,KAAK;GACd;GAIA,MAAM,WAAW,YAAY;IAC3B,MAAM,UAAU,MAAM,MAAM,WAAW,WAAW,EAAE;IACpD,IAAI,CAAC,QAAQ,SAAS;KACpB,IAAI,QAAQ,OAAO,gBAAgB,IACjC,OAAO,SAAS;KAClB,IAAI,QAAQ,OAAO,WAAW,KAAA,GAC5B,OAAO,QAAQ,OAAO;KACxB,IAAI,CAAC,WAAW,IAAI,GAAG,GACrB,MAAM,IAAI,wBAAwB,SAAS;IAC/C;IACA,WAAW,OAAO,GAAG;IACrB,IAAI;IACJ,IAAI;KACF,SAAS,MAAM,KAAK;IACtB,SACO,KAAK;KAIV,IAAI,EAFY,MAAM,OAAO,WAAW,WAAW,IAAI,CAAC,CAAC,WAAW,YAAY,KAAK,KAChF,MAAM,OAAO,WAAW,WAAW,IAAI,CAAC,CAAC,WAAW,YAAY,KAAK,IAExE,WAAW,IAAI,GAAG;KACpB,MAAM;IACR;IAEA,MAAM,OAAO,WAAW,WAAW,MAAmB,CAAC,CAAC,YAAY,KAAA,CAAS;IAC7E,OAAO;GACT,EAAA,CAAG;GACH,QAAQ,IAAI,KAAK;IAAE,aAAa;IAAI;GAAQ,CAAC;GAC7C,IAAI;IACF,OAAO,MAAM;GACf,UACQ;IACN,QAAQ,OAAO,GAAG;GACpB;EACF;CACF;AACF;AAEA,MAAM,+BAAe,IAAI,QAAiC;;AAG1D,SAAgB,aAAa,OAAgC;CAC3D,IAAI,QAAQ,aAAa,IAAI,KAAK;CAClC,IAAI,CAAC,OAAO;EACV,QAAQ,gBAAgB,EAAE,MAAM,CAAC;EACjC,aAAa,IAAI,OAAO,KAAK;CAC/B;CACA,OAAO;AACT;;AAGA,eAAsB,QAAW,OAA8B,QAAgB,QAAoD,MAAoC;CACrK,OAAO,QAAQ,MAAM,IAAI,QAAQ,QAAQ,IAAI,IAAI,KAAK;AACxD;;AAGA,SAAS,WAAW,OAAwB;CAC1C,OAAO,KAAK,UAAU,QAAQ,MAAM,MAAe;EACjD,IAAI,CAAC,KAAK,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,GAChD,OAAO;EACT,OAAO,OAAO,YAAY,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE,CAAC;CAC9F,CAAC;AACH;;;ACxIA,SAAgB,mBAAmB,EAAE,MAAM,YAAY,OAAO,cAOrC;CAEvB,MAAM,SAAS,wBAAwB,MAAM,UAAU;CACvD,MAAM,QAAQ,SAAsB,OAAO,KAAK,IAAI;CACpD,OAAO;EACL,aAAa,OAAO,GAAG,SAAS;GAI9B,MAAM,EAAE,MAAM,WAAW,WAAW,WAAW,KAAK,QAAQ,SAAS,SAAS,UAAU,iBAAiB,kBAAkB,UAAU,WAAW,GAAG,WAAW;GAC9J,MAAM,SAAS,MAAM,QAAQ,OAAO,aAAa,SAAS,KAAK;IAAE,GAAG;IAAQ,GAAG,aAAa,CAAC;GAAE,CAAC,CAAC;GAKjG,IAAI,CAAC,WACH,WAAW,EAAE,WAAW,IAAI;GAC9B,OAAO;EACT;EACA,mBAAkB,MAAK,KAAK,UAAU,EAAE,SAAS;EACjD,eAAc,MAAK,OAAO,MAAM,EAAE,WAAW,EAAE,SAAS,gBAAgB,EAAE,eAAe,CAAC;EAC1F,kBAAiB,MAAK,OAAO,SAAS,EAAE,WAAW,EAAE,SAAS,gBAAgB,EAAE,eAAe,CAAC;EAChG,mBAAmB,OAAO,GAAG,SAAS;GACpC,MAAM,SAAS,MAAM,QAAQ,OAAO,mBAAmB,SAAS,OAAO,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,aAAa,CAAC,CAAC,CAAC;GAC7I,IAAI,CAAC,EAAE,WACL,WAAW,EAAE,WAAW,IAAI;GAC9B,OAAO;EACT;EACA,mBAAkB,MAAK,KAAK,iBAAiB,EAAE,SAAS;EACxD,sBAAqB,MAAK,KAAK,uBAAuB,EAAE,SAAS;EACjE,kBAAiB,MAAK,KAAK,gBAAgB,EAAE,WAAW,EAAE,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,KAAA,CAAS;EAC5G,oBAAmB,MAAK,KAAK,kBAAkB,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM;EAE1E,kBAAiB,MAAK,KAAK,aAAa,EAAE,KAAK,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO,KAAA,CAAS;EAC9F,0BAAyB,MAAK,KAAK,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO,KAAA,CAAS;CACrI;AACF;;AAGA,SAAgB,aAAa,GAA+G;CAC1I,IAAI,EAAE,WAAW,KAAA,KAAa,CAAC,aAAa,EAAE,MAAM,GAClD,MAAM,IAAI,mBAAmB,sJAA4J;CAC3L,MAAM,KAAK,gBAAgB,EAAE,eAAe;CAC5C,MAAM,WAAW,eAAe,EAAE,QAAQ;CAC1C,OAAO;EACL,GAAI,EAAE,WAAW,KAAA,IAAY,EAAE,QAAQ,kBAAkB,EAAE,MAAM,EAAE,IAAI,CAAC;EACxE,GAAI,EAAE,YAAY,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;EAC9C,GAAI,OAAO,KAAA,IAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;EAClD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;CACjC;AACF;;AAGA,MAAM,4BAA4B;;AAGlC,SAAS,eAAe,OAAgD;CACtE,IAAI,UAAU,KAAA,GACZ,OAAO,KAAA;CACT,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D,MAAM,IAAI,mBAAmB,kCAAkC;CACjE,MAAM,OAAO,KAAK,UAAU,KAAK;CACjC,IAAI,KAAK,SAAS,2BAChB,MAAM,IAAI,mBAAmB,6BAA6B,0BAA0B,gBAAgB;CACtG,MAAM,SAAS,KAAK,MAAM,IAAI;CAC9B,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA;AACnD;;AAGA,SAAS,kBAAkB,EAAE,MAAM,QAAQ,QAAQ,aAAqC;CACtF,OAAO;EACL;EACA;EACA,GAAI,SAAS,EAAE,QAAQ;GAAE,IAAI,OAAO;GAAI,GAAI,OAAO,SAAS,KAAA,IAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;EAAG,EAAE,IAAI,CAAC;EAC3G,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;CACjD;AACF;;AAGA,SAAS,gBAAgB,OAAoC;CAC3D,IAAI,UAAU,KAAA,GACZ,OAAO,KAAA;CACT,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,KACpE,MAAM,IAAI,mBAAmB,wEAAwE;CACvG,OAAO;AACT;;;AChGA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;AAGA,MAAM,cAAyF;CAC7F,oBAAmB,MAAK,SAAS,CAAC,KAAK,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,eAAe;CAC7E,0BAAyB,MAAK,SAAS,CAAC,KAAK,OAAO,OAAO,CAAC,CAAC,CAAC,OAAM,YAAW,SAAS,OAAO,KAAK,OAAO,OAAO,OAAO,CAAC,CAAC,OAAM,OAAM,OAAO,OAAO,SAAS,CAAC;CAC/J,iBAAgB,MAAK,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAM,UAAS,SAAS,KAAK,KAAK,OAAO,MAAM,aAAa,YAAY,OAAO,MAAM,UAAU,aAAa,MAAM,YAAY,KAAA,KAAa,OAAO,MAAM,YAAY,SAAS;AAC1N;AACA,MAAM,YAAY,OAAO,KAAK,WAAW;;AAGzC,MAAM,eAAe;;AAErB,MAAM,gBAAgB;;AAEtB,MAAM,YAAY;AAElB,SAAS,UAAU,OAAwB;CACzC,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,cACpE,MAAM,IAAI,mBAAmB,iDAAiD,aAAa,aAAa;CAC1G,OAAO;AACT;AAEA,SAAgB,0BAA0B,EAAE,OAAgF;CAC1H,MAAM,EAAE,eAAe,IAAI;CAC3B,OAAO;EACL,mBAAmB;GACjB,MAAM,QAAQ,WAAW,KAAK;GAC9B,MAAM,QAA2B,OAAO,YAAY,UAAU,SAAQ,QAAQ,MAAM,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,CAAE,CAAC;GACnI,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,IAAI,QAAQ;EACjD;EACA,cAAc,MAAM;GAClB,MAAM,QAAiB,EAAE;GACzB,IAAI,CAAC,SAAS,KAAK,GACjB,MAAM,IAAI,mBAAmB,0BAA0B;GACzD,MAAM,MAAM,UAAU,MAAK,QAAO,OAAO,SAAS,CAAC,YAAY,IAAI,CAAC,MAAM,IAAI,CAAC;GAC/E,IAAI,KACF,MAAM,IAAI,mBAAmB,SAAS,IAAI,sBAAsB;GAClE,WAAW,KAAK;IAAE,GAAG,WAAW,KAAK;IAAG,GAAG,OAAO,YAAY,UAAU,SAAQ,QAAQ,OAAO,QAAQ,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,CAAE,CAAC;GAAE,CAAC;EACtI;EACA,0BAA0B,WAAW,KAAK,CAAC,CAAC,gBAAgB,CAAC;EAC7D,oBAAoB,MAAM;GACxB,MAAM,UAAU,UAAU,EAAE,OAAO;GACnC,IAAI,CAAC,SAAS,EAAE,IAAI,GAClB,MAAM,IAAI,mBAAmB,yBAAyB;GACxD,IAAI,KAAK,UAAU,EAAE,IAAI,CAAC,CAAC,SAAS,eAClC,MAAM,IAAI,mBAAmB,wBAAwB,cAAc,qBAAqB;GAC1F,MAAM,QAAQ,WAAW,KAAK;GAC9B,MAAM,QAAQ,MAAM,gBAAgB,CAAC;GACrC,IAAI,EAAE,WAAW,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,UAAU,WACtD,MAAM,IAAI,MAAM,gCAAgC,UAAU,iBAAiB;GAC7E,WAAW,KAAK;IAAE,GAAG;IAAO,cAAc;KAAE,GAAG;MAAQ,UAAU,EAAE;IAAK;GAAE,CAAC;EAC7E;EACA,0BAA0B,WAAW,KAAK,CAAC,CAAC,kBAAkB;EAC9D,qBAAqB,MAAM;GACzB,MAAM,iBAAiB,UAAU,EAAE,OAAO;GAC1C,WAAW,KAAK;IAAE,GAAG,WAAW,KAAK;IAAG;GAAe,CAAC;EAC1D;CACF;AACF;;;ACrEA,SAAgB,sBAAsB,EAAE,QAA0M;CAChP,OAAO;EACL,sBAAqB,MAAK,KAAK,gBAAgB,EAAE,SAAS;EAC1D,6BAA4B,MAAK,KAAK,mBAAmB,EAAE,SAAS;EACpE,kCAAiC,MAAK,KAAK,qBAAqB,EAAE,SAAS;EAC3E,8BAA6B,MAAK,KAAK,oBAAoB,EAAE,SAAS;EACtE,yBAAwB,MAAK,KAAK,YAAY,EAAE,WAAW,kBAAkB,EAAE,MAAM,CAAC;EACtF,yBAAwB,MAAK,KAAK,YAAY,EAAE,WAAW,eAAe,EAAE,OAAO,OAAO,CAAC;CAC7F;AACF;AAEA,SAAS,kBAAkB,OAAmC;CAC5D,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,MAAM,IAAI,mBAAmB,2BAA2B;CAC1D,MAAM,MAAM;CACZ,MAAM,SAA4B,CAAC;CACnC,MAAM,UAAUE,iBAAe,IAAI,SAAS,gBAAgB;CAC5D,MAAM,cAAcA,iBAAe,IAAI,aAAa,oBAAoB;CACxE,MAAM,UAAUA,iBAAe,IAAI,SAAS,gBAAgB;CAC5D,MAAM,SAASA,iBAAe,IAAI,QAAQ,eAAe;CACzD,IAAI,WAAW,KAAA,KAAa,CAAE,gBAAsC,SAAS,MAAM,GACjF,MAAM,IAAI,mBAAmB,yCAAyC;CACxE,IAAI,YAAY,KAAA,GACd,OAAO,UAAU;CACnB,IAAI,gBAAgB,KAAA,GAClB,OAAO,cAAc;CACvB,IAAI,YAAY,KAAA,GACd,OAAO,UAAU;CACnB,IAAI,WAAW,KAAA,GACb,OAAO,SAAS;CAClB,OAAO;AACT;;;AC9BA,SAAgB,qBAAqB,EAAE,MAAM,YAAY,WAAW,WAAW,YAOuB;CACpG,OAAO;EACL,sBAAmC;GACjC,iBAAA;GACA;GACA,KAAK,QAAQ;GACb;GACA,GAAG;GACH,YAAY,KAAK,cAAc;GAE/B,GAAI,UAAU,aAAa,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;EACvD;EACA,+BAA+B,mBAAmB;EAClD,iCAAiC,qBAAqB;EACtD,mBAAmB,OAAO,MAAM;GAE9B,IAAI,GAAG,aAAa,QAAQ,KAAK,cAAc,GAAG;IAChD,UAAU,eAAe;IACzB,OAAO,EAAE,UAAU,KAAK;GAC1B;GAEA,aAAa,UAAU,QAAQ;EACjC;CACF;AACF;;;;;;;;ACvBA,SAAgB,iBAAiB,MAAqC;CACpE,IAAI,SAAS;CACb,MAAM,MAA0B,CAAC;CACjC,KAAK,MAAM,SAAS,MAAM;EACxB,MAAM,IAAI;EACV,IAAI,OAAO,GAAG,cAAc,YAAY,OAAO,GAAG,SAAS,UACzD;EACF,UAAU,EAAE,KAAK;EACjB,IAAI,SAAS,GACX;EAGF,IAAI,KAAK;GAAE,WAAW,EAAE;GAAW,MAAM,EAAE;GAAM,GAAI,OAAO,EAAE,SAAS,WAAW,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;EAAG,CAAC;CAC1H;CACA,OAAO;AACT;AAEA,SAAgB,oBAAoB,EAAE,mBAQpC;;;;;CAKA,MAAM,yBAAS,IAAI,IAAwB;;CAG3C,SAAS,uBAA+B;EACtC,IAAI,QAAQ;EACZ,KAAK,MAAM,SAAS,OAAO,OAAO,GAChC,KAAK,MAAM,cAAc,MAAM,eAAe,CAAC,GAC7C,SAAS,WAAW,KAAK;EAE7B,OAAO;CACT;CAEA,SAAS,WAAW,WAAmB,QAA+B;EACpE,MAAM,QAAQ,OAAO,IAAI,SAAS;EAClC,IAAI,CAAC,OACH;EACF,OAAO,OAAO,SAAS;EACvB,IAAI,MAAM,MACR,gBAAgB,QAAQ;GAAE,MAAM;GAAiB;GAAW,MAAM;EAAG,CAAC;EACxE,IAAI,MAAM,aAAa,QACrB,gBAAgB,QAAQ;GAAE,MAAM;GAAqB;GAAW,aAAa,CAAC;EAAE,CAAC;CACrF;;CAGA,SAAS,aAAa,WAAmB,OAAyB;EAChE,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,SAAS,CAAC,MAAM,aAAa,UAAU,CAAC,MAAM,QAAQ,QAC9E,OAAO,OAAO,SAAS;OAEvB,OAAO,IAAI,WAAW,KAAK;CAC/B;CAqEA,OAAO;EACL,SAAA;GAnEA,eAAe,MAAM;IACnB,MAAM,QAAQ,OAAO,IAAI,EAAE,SAAS;IACpC,OAAO;KACL,MAAM,OAAO,QAAQ;KACrB,GAAI,OAAO,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;KACtC,GAAI,OAAO,aAAa,SAAS,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;KACvE,GAAI,OAAO,QAAQ,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;IAC1D;GACF;GACA,eAAe,GAAG,SAAS;IAIzB,MAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,KAAS,IAAI;IAKvE,MAAM,YAAY,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,SAAS,KAAK;IAKrE,IAAI,CAAC,OAAO,IAAI,EAAE,SAAS,KAAK,OAAO,QAAQ,KAC7C;IACF,MAAM,QAAQ,OAAO,IAAI,EAAE,SAAS,KAAK,CAAC;IAC1C,MAAM,OAAO,KAAK,SAAS,IAAI,OAAO,KAAA;IAEtC,MAAM,QAAQ,EAAE,UAAU,OAAO,OAAO,KAAA;IACxC,aAAa,EAAE,WAAW,KAAK;IAC/B,gBAAgB,YAAY,OAAO,MAAM;KAAE,MAAM;KAAiB,WAAW,EAAE;KAAW;KAAM,GAAI,EAAE,UAAU,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAAG,CAAC;GAChJ;GACA,eAAe,GAAG,SAAS;IAEzB,MAAM,SAAS,EAAE,WAAW;IAC5B,MAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,EAAE,MAAM,MAAM,GAAG,IAAQ,IAAI;IACzE,IAAI,CAAC,OAAO,IAAI,EAAE,SAAS,KAAK,OAAO,QAAQ,KAC7C;IACF,MAAM,QAAQ,OAAO,IAAI,EAAE,SAAS,KAAK,CAAC;IAC1C,MAAM,SAAS,UAAU,MAAM,SAAS,IAAI;KAAE;KAAQ;IAAM,IAAI,KAAA;IAChE,aAAa,EAAE,WAAW,KAAK;IAC/B,gBAAgB,MAAM;KAAE,MAAM;KAAkB,WAAW,EAAE;KAAW;KAAQ;IAAM,CAAC;GACzF;GACA,0BAA0B,GAAG,SAAS;IAQpC,MAAM,UAAU,MAAM,QAAQ,EAAE,WAAW,IAAI,iBAAiB,EAAE,WAAW,IAAI,CAAC;IAClF,IAAI,CAAC,OAAO,IAAI,EAAE,SAAS,KAAK,OAAO,QAAQ,KAC7C;IAEF,MAAM,gBADU,OAAO,IAAI,EAAE,SAAS,CAAC,EAAE,eAAe,CAAC,EAAA,CAC5B,QAAQ,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;IACtE,MAAM,gBAAgB,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;IACvE,IAAI,qBAAqB,IAAI,eAAe,gBAAgB,WAC1D;IACF,MAAM,QAAQ,OAAO,IAAI,EAAE,SAAS,KAAK,CAAC;IAC1C,MAAM,cAAc,QAAQ,SAAS,IAAI,UAAU,KAAA;IACnD,aAAa,EAAE,WAAW,KAAK;IAC/B,gBAAgB,MAAM;KAAE,MAAM;KAAqB,WAAW,EAAE;KAAW,aAAa;IAAQ,CAAC;GACnG;EAIM;EACN;EACA,SAAS,cAAc;GACrB,OAAO,OAAO,SAAS;EACzB;CACF;AACF;;;AC3IA,SAAgB,0BAA0B,EAAE,MAAM,KAAK,eAKvB;CAC9B,OAAO;EACL,6BAA6B,OAAO,MAAM;GACxC,MAAM,YAAY,IAAI,OAAO,EAAE,SAAS;GAIxC,MAAM,KAAK,iBAAiB,EAAE,WAAW,EAAE,YAAY,KAAK,CAAC;EAC/D;EACA,4BAA4B,OAAO,MAAM;GACvC,MAAM,YAAY,IAAI,OAAO,EAAE,SAAS;GACxC,OAAO,KAAK,uBAAuB,EAAE,WAAW,EAAE,aAAa,OAAO,EAAE,QAAQ,WAAW,EAAE,MAAM,KAAA,GAAW,EAAE,sBAAsB,OAAO,EAAE,mBAAmB,KAAK,IAAI,KAAA,CAAS;EACtL;EACA,gCAA+B,MAAK,KAAK,uBAAuB,EAAE,SAAS;EAC3E,kCAAiC,MAAK,KAAK,qBAAqB,EAAE,WAAW,EAAE,QAAQ;EACvF,sBAAqB,MAAK,KAAK,iBAAiB,EAAE,OAAO,IAAI,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO,KAAA,CAAS;EAC5G,wBAAuB,MAAK,KAAK,kBAAkB,EAAE,IAAI;EACzD,uBAAuB,OAAO,GAAG,SAAS;GACxC,MAAM,QAAQ,+BAA+B,KAAK,cAAc,IAAI,aAAa,GAAG,CAAC;GACrF,KAAK,MAAM,UAAU,MAAM,SACzB,KAAK,mBAAmB,IAAI,EAAE,MAAM,OAAO,KAAK,OAAO,KAAK;GAG9D,MAAM,YAAY,EAAE,OAAO,MAAM,cAAuC,GAAG,IAAI;EACjF;CACF;AACF;;;;ACzBA,IAAa,mBAAb,cAAsC,MAAM;CAC1C,OAAgB,aAAa;CAC7B;;;;;;;CAOA,YAAY,QAAgB,MAAc,SAAsB,WAAwB,WAAW;EACjG,MAAM,IAAI,OAAO,IAAI,KAAK,SAAS,aAAa,SAAS,MAAM,KAAK,GAAG,SAAS,qCAAqC,QAAQ,EAAE;EAC/H,KAAK,OAAO;EACZ,KAAK,OAAO;GAAE;GAAU;EAAQ;CAClC;AACF;;;;;;;;;;;AAYA,eAAsB,iBACpB,OACA,MACA,QACA,kBAAgE,CAAC,IACzC;CACxB,IAAI;CACJ,IAAI;EACF,SAAS,mBAAmB,OAAO,QAAQ;CAC7C,SACO,KAAK;EACV,MAAM,eAAe,qBAAqB,IAAI,mBAAmB,IAAI,OAAO,IAAI;CAClF;CACA,MAAM,QAAQ,MAAM;CACpB,IAAI,SAAS,CAAC,YAAY,OAAO,SAAS,GAAG;EAC3C,MAAM,WAAW,gBAAgB,MAAM,SAAS,GAAG,MAAM;EACzD,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,iBAAiB,QAAQ,UAAU,KAAK;CACtD;CACA,OAAO;AACT;;;ACTA,MAAM,yBAA8B,IAAI,IAAkB;CAAC;CAAQ;CAAW;AAAS,CAAC;AACxF,MAAM,wBAA6B,IAAI,IAAiB,CAAC,MAAM,QAAQ,CAAC;AACxE,MAAM,gCAAqC,IAAI,IAAI;CAAC;CAAS;CAAU;CAAa;CAAU;CAAa;CAAO;AAAQ,CAAC;AAE3H,SAAS,gBAA4B;CACnC,OAAO,OAAO,YAAY,eAAe,KAAI,MAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5D;AAEA,SAAS,eAAe,OAAgB,MAAkC;CACxE,IAAI,UAAU,KAAA,GACZ,OAAO,KAAA;CACT,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,MACpE,MAAM,IAAI,mBAAmB,GAAG,KAAK,6BAA6B;CACpE,OAAO;AACT;;AAGA,SAAgB,gBAAgB,OAA0C;CACxE,MAAM,EAAE,SAAS;CACjB,OAAO;EACL,IAAI,KAAK;EACT,MAAM,KAAK;EACX,GAAI,KAAK,gBAAgB,KAAA,IAAY,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;EAC1E,aAAa,MAAM;EACnB,SAAS,KAAK,QAAQ,KAAK,MAA6B;GACtD,IAAI,EAAE,SAAS,UAAU;IACvB,MAAM,EAAE,SAAS,UAAU,SAAS,UAAU,GAAG,SAAS;IAC1D,OAAO;GACT;GACA,IAAI,EAAE,SAAS,SACb,OAAO,EAAE,GAAG,EAAE;GAChB,MAAM,EAAE,cAAc,SAAS,GAAG,SAAS;GAC3C,OAAO;EACT,CAAC;EACD,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;EAC3D,aAAa,MAAM;CACrB;AACF;;AAGA,SAAS,WAAW,SAAqC,WAAsD;CAC7G,IAAI,CAAC,SACH,OAAO;EAAE,GAAG,kBAAkB,CAAC,CAAC;EAAG,SAAS,CAAC;CAAE;CACjD,MAAM,EAAE,YAAY;CACpB,MAAM,UAAyC,CAAC;CAChD,KAAK,MAAM,QAAQ,QAAQ,WAAW,GAAG;EACvC,MAAM,OAAO,QAAQ,IAAI,KAAK,EAAE,CAAC,EAAE;EACnC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,MAAM,OAAO,SAAS,CAAC,CAAC,GAAG;GAClE,IAAI,CAAC,eAAe,IAAI,GACtB;GACF,MAAM,SAAS,KAAM,OAAO,KAAK,YAAY,EAAE,UAAU,IAAI,CAAC,CAAC;GAC/D,IAAI,QACF,QAAQ,GAAG,KAAK,GAAG,GAAG,SAAS;EACnC;CACF;CACA,OAAO;EAAE,GAAG,oBAAoB,SAAS,YAAY,EAAE,UAAU,IAAI,CAAC,CAAC;EAAG;CAAQ;AACpF;;AAGA,SAAS,WAAW,SAAyB,WAAoF;CAC/H,MAAM,WAAW,QAAQ,QAAQ,QAAQ;CACzC,MAAM,OAAO,IAAI,IAAI,SAAS,OAAO,KAAK,CAAC,CAAC,KAAI,MAAK,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;CACtE,MAAM,WAAW,SAAS,KAAK,CAAC,CAAC,KAAK,YAAkC;EACtE,MAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE;EACrC,MAAM,MAAM,KAAK,IAAI,QAAQ,EAAE;EAC/B,MAAM,OAAO,CAAC,GAAI,KAAK,UAAU,QAAQ,QAAQ,CAAC,CAAE;EACpD,IAAI,CAAC,OACH,OAAO;GAAE,IAAI,QAAQ;GAAI,OAAO,QAAQ;GAAO,MAAM;GAAU,SAAS;GAAM,SAAS;GAAM;GAAM,OAAO,KAAK,SAAS;GAAU,UAAU,KAAK,YAAY;GAAO,MAAM;GAAO,GAAI,QAAQ,QAAQ,EAAE,OAAO;IAAE,MAAM,QAAQ;IAAO,SAAS,CAAC;GAAE,EAAE,IAAI,CAAC;EAAG;EAC7P,MAAM,OAAO,MAAM;EACnB,MAAM,cAAc,MAAM,YAAY;EACtC,OAAO;GACL,IAAI,MAAM;GACV,aAAa,MAAM;GACnB,OAAO,MAAM,MAAM;GACnB,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;GACnD,OAAO,KAAK,SAAS,MAAM;GAC3B,GAAI,KAAK,aAAa,KAAA,IAAY,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;GACjE,GAAI,KAAK,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,KAAK,EAAE,IAAI,CAAC;GAC9C,MAAM,KAAK,QAAQ;GACnB,SAAS,MAAM,QAAQ;GACvB,SAAS,KAAK,YAAY,KAAA,IAAY,OAAO,OAAO,KAAK,YAAY,YAAY,KAAK,UAAU,EAAE,GAAG,KAAK,QAAQ;GAClH;GACA,GAAI,KAAK,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;GAC9C,OAAO,KAAK,SAAS,KAAK,SAAS;GACnC,UAAU,KAAK,YAAY,KAAK,aAAa;GAC7C,GAAI,KAAK,SAAS,KAAA,IAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;GACrD,MAAM,KAAK,SAAS;GACpB,GAAI,MAAM,QAAQ,EAAE,OAAO;IAAE,MAAM,MAAM,MAAM;IAAM,SAAS,CAAC,GAAG,MAAM,MAAM,OAAO;IAAG,GAAI,MAAM,MAAM,iBAAiB,KAAA,IAAY,EAAE,cAAc,MAAM,MAAM,aAAa,IAAI,CAAC;GAAG,EAAE,IAAI,CAAC;EAC/L;CACF,CAAC;CACD,MAAM,OAAO,SAAS,OAAO,YAAY,SAAS;CAClD,OAAO;EAAE;EAAU,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CAAG;AAC7D;;AAGA,SAAS,WAAW,GAAqF;CACvG,MAAM,cAAc,eAAe,EAAE,aAAa,aAAa;CAC/D,IAAI,OAAO,EAAE,UAAU,YAAY,CAAC,OAAO,IAAI,EAAE,KAAK,GACpD,MAAM,IAAI,mBAAmB,yCAAyC;CACxE,MAAM,QAAQ,EAAE;CAChB,IAAI,UAAU,WACZ,OAAO;EAAE;EAAa;EAAO,WAAW,eAAe,EAAE,WAAW,WAAW;CAAE;CACnF,OAAO;EAAE;EAAa;CAAM;AAC9B;;AAGA,eAAe,SAAS,SAAyB,QAAgB,GAAyE;CACxI,MAAM,KAAK,QAAQ,QAAQ,QAAQ;CACnC,QAAQ,EAAE,IAAV;EACE,KAAK,cACH,OAAO,GAAG,UAAU,eAAe,EAAE,SAAS,SAAS,GAAG,EAAE,KAAK,MAAM;EACzE,KAAK,gBACH,OAAO,GAAG,YAAY,eAAe,EAAE,SAAS,SAAS,GAAG,eAAe,EAAE,UAAU,UAAU,GAAG,OAAO,EAAE,OAAO,IAAI,EAAE,UAAuB,KAAA,GAAW,EAAE,KAAK,MAAM;EAC3K,KAAK,qBACH,OAAO,GAAG,iBAAiB,eAAe,EAAE,YAAY,YAAY,GAAG,eAAe,EAAE,KAAK,KAAK,CAAC;EACrG,KAAK,cAAc;GACjB,MAAM,SAAS,qBAAqB,EAAE,MAAM;GAC5C,OAAO,SAAS,GAAG,UAAU,MAAM,IAAI,CAAC;EAC1C;EACA,KAAK,aAAa;GAChB,MAAM,SAAS,qBAAqB,EAAE,MAAM;GAC5C,IAAI,CAAC,QACH,OAAO,EAAE,QAAQ,iBAAiB;GACpC,MAAM,YAAY,eAAe,EAAE,WAAW,WAAW,KAAK,OAAO;GACrE,OAAO,GAAG,eAAe,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,UAAU,UAAU,GAAG,QAAQ;IAAE,KAAK;IAAQ,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG,CAAC;EACnK;EACA,KAAK,kBACH,OAAQ,MAAM,GAAG,cAAc,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,KAAK,KAAK,CAAC,KAAM;EACvG,KAAK,oBACH,OAAO,GAAG,gBAAgB,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,KAAK,KAAK,GAAG,EAAE,KAAK,KAAK;EAC1G,SACE,MAAM,IAAI,mBAAmB,cAAc,KAAK,UAAW,EAAuB,EAAE,EAAE,EAAE;CAC5F;AACF;AAeA,SAAS,iBAAiB,MAAuC,KAA0C;CACzG,MAAM,YAAY,QAAyB,cAAc;EAAE;EAAK;CAAK,GAAG,eAAe,KAAK,KAAK,CAAC;CAClG,MAAM,YAAY,OAAO,QAAsD;EAC7E,MAAM,SAAS,SAAS,GAAG;EAC3B,MAAM,IAAI,cAAc,MAAM;EAC9B,OAAO,IAAI,mBAAmB,WAAW,MAAM;CACjD;CACA,OAAO;EACL;EACA;EACA,eAAe;GACb,IAAI,CAAC,IAAI,mBACP,MAAM,IAAI,MAAM,oCAAoC;GACtD,OAAO,IAAI;EACb;EACA;EACA,gBAAgB,OAAO,QAAQ;GAC7B,MAAM,UAAU,MAAM,UAAU,GAAG;GACnC,IAAI,CAAC,SACH,MAAM,IAAI,mBAAmB,gCAAgC;GAC/D,OAAO;EACT;CACF;AACF;AASA,SAAS,iBAAiB,EAAE,KAAK,UAAU,SAAS,WAAW,kBAAoC,EAAE,OAAO,WAAmP;;CAE7V,MAAM,iCAAiB,IAAI,IAAY;CACvC,OAAO;EACL,YAAY,OAAO,GAAG,SAAS;GAC7B,MAAM,SAAS,eAAe,EAAE,QAAQ,QAAQ;GAChD,MAAM,aAAa,IAAI,gBAAgB;GACvC,IAAI,OAAO,MAAM,IAAI,IAAI;GACzB,IAAI,QAAQ;IACV,IAAI,CAAC,MAAM;KACT,uBAAO,IAAI,IAAI;KACf,MAAM,IAAI,MAAM,IAAI;IACtB;IACA,KAAK,IAAI,QAAQ,UAAU;GAC7B;GACA,IAAI;IACF,MAAM,WAAW,IAAI,mBAAmB,QAAQ,KAAK,IAAI,KAAK,KAAK,aAAa;IAChF,MAAM,EAAE,QAAQ,KAAK,GAAG,WAAW;IACnC,IAAI,CAAC,IAAI,mBACP,OAAO;KAAE,IAAI;KAAO,OAAO;MAAE,MAAM;MAAmB,SAAS;KAAqC;KAAG,MAAM;MAAE,UAAU,OAAO,EAAE,YAAY,EAAE;MAAG,QAAQ,OAAO,EAAE,UAAU,EAAE;MAAG,OAAO;KAAO;IAAE;IAErM,IAAI,OAAO,OAAO,QAAQ,UACxB,MAAM,UAAU,OAAO,GAAG;IAE5B,MAAM,QAAQ,KAAK;IACnB,OAAO,MAAM,IAAI,kBAAkB,QACjC,OAAO,OAAO,QAAQ,WAAW;KAAE,GAAG;KAAQ,KAAK,SAAS,OAAO,GAAG;IAAE,IAAI,QAC5E;KAAE,MAAM;KAAU;IAAS,GAC3B,WAAW,QACX,SAAQ,UAAS,YAAY,OAAO,KAAK,IAAI,KAAA,CAC/C;GACF,UACQ;IACN,IAAI,UAAU,MAAM,IAAI,MAAM,MAAM,YAClC,KAAK,OAAO,MAAM;GACtB;EACF;EACA,eAAe,GAAG,SAAS;GACzB,MAAM,aAAa,MAAM,IAAI,IAAI,CAAC,EAAE,IAAI,eAAe,EAAE,QAAQ,QAAQ,CAAC;GAC1E,YAAY,MAAM;GAClB,OAAO,eAAe,KAAA;EACxB;EAEA,sBAAsB,OAAO,MAAM;GACjC,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,IAAI,CAAC,SACH,OAAO;IAAE,GAAG,cAAc;IAAG,SAAS,CAAC;GAAE;GAC3C,MAAM,UAAU,MAAM,QAAQ,CAAC,CAAC,QAAQ,OAAO;GAC/C,OAAO;IAAE,GAAG,QAAQ,QAAQ,QAAQ,GAAG,SAAS;IAAG;GAAQ;EAC7D;EACA,sBAAsB,OAAO,MAAM;GACjC,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,OAAO,UAAU,QAAQ,CAAC,CAAC,QAAQ,OAAO,IAAI,CAAC;EACjD;EACA,wBAAwB,OAAO,GAAG,SAAS;GACzC,MAAM,EAAE,KAAK,GAAG,SAAS;GACzB,MAAM,UAAU;GAChB,MAAM,UAAU,MAAM,eAAe,GAAG;GACxC,MAAM,SAAS,SAAS,GAAG;GAC3B,IAAI,QAAQ,OAAO,kBACjB,OAAO,SAAS,SAAS,QAAQ,OAAO;GAC1C,MAAM,SAAS,eAAe,QAAQ,QAAQ,QAAQ;GACtD,MAAM,MAAM,eAAe,QAAQ,KAAK,KAAK;GAE7C,MAAM,WAAW,QAAQ,QAAQ,QAAQ,GAAG,mBAAmB,QAAQ,GAAG,KAAK;GAC/E,IAAI,KAAK,SAAS,CAAC,YAAY,KAAK,OAAO,QAAQ,GACjD,MAAM,IAAI,iBAAiB,wBAAwB,6BAA6B,IAAI,IAAI,KAAK,OAAO,QAAQ;GAC9G,MAAM,QAAQ,GAAG,OAAO,QAAQ,OAAO,QAAQ;GAC/C,IAAI,eAAe,IAAI,KAAK,GAC1B,MAAM,IAAI,MAAM,4BAA4B;GAC9C,MAAM,aAAa,IAAI,gBAAgB;GACvC,IAAI,OAAO,QAAQ,IAAI,IAAI;GAC3B,IAAI,CAAC,MAAM;IACT,uBAAO,IAAI,IAAI;IACf,QAAQ,IAAI,MAAM,IAAI;GACxB;GACA,KAAK,IAAI,UAAU;GACnB,eAAe,IAAI,KAAK;GACxB,IAAI;IACF,OAAQ,MAAM,QAAQ,QAAQ,QAAQ,GAAG,iBAAiB,QAAQ,KAAK,WAAW,MAAM,KAAM;GAChG,UACQ;IACN,eAAe,OAAO,KAAK;IAC3B,KAAK,OAAO,UAAU;GACxB;EACF;EAEA,yBAAyB,OAAO,MAAM;GACpC,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,IAAI,CAAC,SACH,OAAO,EAAE,SAAS,MAAM;GAC1B,MAAM,YAAY,eAAe,EAAE,WAAW,WAAW;GACzD,MAAM,SAAS,eAAe,EAAE,QAAQ,QAAQ;GAChD,OAAO,QAAQ,QAAQ,QAAQ,GAAG,SAAS;IACzC,KAAK,eAAe,EAAE,KAAK,KAAK;IAChC,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;IACjC,GAAI,SAAS,EAAU,OAAqB,IAAI,CAAC;GACnD,CAAC;EACH;EAEA,uBAAuB,GAAG,SAAS;GACjC,MAAM,OAAO,QAAQ;GACrB,MAAM,KAAK,KAAK,QAAQ,KAAK,IAAI;GACjC,MAAM,SAAS,IAAI,IAAI,KAAK,KAAK,QAAQ,QAAQ,CAAC,CAAC,MAAK,MAAK,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;GACvF,KAAK,QAAQ,SAAS,MAAM,KAAK,CAAC,CAAC;GAEnC,KAAK,MAAM,aAAa,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,UAAU,CAAC,GAC/D,IAAI,OAAO,cAAc,YAAY,CAAC,OAAO,IAAI,SAAS,GACxD,KAAU,cAAc,SAAS;EAEvC;EACA,oBAAoB,GAAG,SAAS,QAAQ,CAAC,CAAC,QAAQ,MAAM,MAAM,eAAe,EAAE,WAAW,WAAW,GAAG,EAAE,MAAM;EAChH,qBAAqB,GAAG,SAAS,QAAQ,CAAC,CAAC,QAAQ,aAAa,MAAM,eAAe,EAAE,UAAU,UAAU,GAAG,EAAE,MAAM;EACtH,uBAAuB,GAAG,SAAS,QAAQ,CAAC,CAAC,QAAQ,eAAe,MAAM,eAAe,EAAE,UAAU,UAAU,GAAG,eAAe,EAAE,KAAK,KAAK,GAAG,EAAE,KAAK,KAAK;CAC9J;AACF;AAEA,SAAS,2BAA2B,EAAE,UAAU,SAAS,WAAW,kBAAwJ;CAC1N,OAAO;EACL,2BAA2B,OAAO,MAAM;GACtC,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,MAAM,UAAU,QAAQ,CAAC,CAAC,QAAQ,WAAW,SAAS,cAAc,MAAM,IAAI,KAAA,CAAS;GAEvF,OAAO;IAAE,GAAG,MADW,QAAQ,KAAK,WAAW,CAAC,CAAC;IAC3B,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GAAG;EAC7F;EACA,0BAA0B,OAAO,GAAG,SAAS;GAC3C,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,MAAM,MAAM,WAAW,CAAC;GACxB,IAAI,OAAO,EAAE,SAAS,YAAY,CAAC,MAAM,IAAI,EAAE,IAAI,GACjD,MAAM,IAAI,mBAAmB,4BAA4B;GAC3D,MAAM,MAAM,eAAe,EAAE,KAAK,KAAK;GACvC,IAAI,CAAC,gBAAgB,GAAG,GACtB,MAAM,IAAI,mBAAmB,+BAA+B;GAC9D,IAAI,EAAE,UAAU,KAAA,KAAa,CAAC,OAAO,EAAE,KAAK,GAC1C,MAAM,IAAI,mBAAmB,qBAAqB;GACpD,MAAM,OAAO,QAAQ;GACrB,MAAM,OAAO,EAAE;GACf,MAAM,UAAU,KAAK,QAAQ,WAAW,SAAS,cAAc,MAAM,IAAI,KAAA,CAAS;GAElF,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,MAAM,SAAS,UAAU,MAAM,QAAQ,QAAQ,kBAAkB,KAAK,MAAM,KAAK,EAAE,KAAK,IAAI,KAAA;GAC5F,IAAI,WAAW,KAAA,GACb,OAAO;IAAE,UAAU;IAAO;IAAQ,GAAG,MAAM,QAAQ,QAAQ,KAAK,MAAM,GAAG;GAAE;GAC7E,MAAM,SAAS,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,EAAE,KAAK;GAC1D,KAAK,QAAQ,QAAQ,IAAI;GACzB,OAAO;IAAE,UAAU;IAAM,SAAS,OAAO;IAAS,GAAI,EAAE,UAAU,KAAA,IAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;GAAG;EACzG;EAEA,uBAAuB,OAAM,MAAK,WAAW,MAAM,UAAU,EAAE,GAAG,GAAG,eAAe,EAAE,WAAW,WAAW,CAAC;EAC7G,2BAA2B,OAAO,MAAM;GAEtC,MAAM,YAAW,MADK,eAAe,EAAE,GAAG,EAAA,CACjB,QAAQ,IAAI,eAAe,EAAE,WAAW,WAAW,CAAC,CAAC,EAAE;GAChF,IAAI,CAAC,UACH,MAAM,IAAI,mBAAmB,wBAAwB,EAAE,UAAU,kBAAkB;GACrF,MAAM,YAAY,eAAe,EAAE,WAAW,WAAW;GACzD,IAAI;IACF,MAAM,SAAS,IAAI,eAAe,EAAE,KAAK,KAAK,GAAG,EAAE,OAAO;KAAE,OAAO,EAAE;KAAO,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;IAAG,CAAC;GACnH,SACO,KAAK;IACV,IAAI,eAAe,oBACjB,MAAM,IAAI,mBAAmB,IAAI,OAAO;IAC1C,MAAM;GACR;EACF;CACF;AACF;AAEA,SAAS,gBAAgB,EAAE,WAAW,kBAAoC,EAAE,SAAgK;CAC1O,IAAI,UAAU;CACd,OAAO;EACL,uBAAuB,OAAO,MAAM;GAClC,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,OAAO,UAAU,WAAW,SAAS,eAAe,EAAE,WAAW,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE;EAClG;EACA,0BAA0B,OAAO,MAAM;GACrC,MAAM,UAAU,MAAM,eAAe,EAAE,GAAG;GAC1C,MAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;GACnD,MAAM,YAAY,eAAe,EAAE,WAAW,WAAW;GACzD,OAAO,QAAQ,QAAQ,QAAQ,SAAS,IAAI,eAAe,EAAE,IAAI,IAAI,GAAG;IAAE;IAAM,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG,CAAC;EACvH;EACA,0BAA0B,OAAO,GAAG,SAAS;GAC3C,MAAM,UAAU,MAAM,eAAe,EAAE,GAAG;GAC1C,MAAM,YAAY,eAAe,EAAE,WAAW,WAAW;GACzD,MAAM,OAAO,QAAQ,QAAQ,QAAQ,SAAS,OAAO,SAAS,eAAe,EAAE,MAAM,MAAM,GAAG;IAC5F,GAAI,OAAO,EAAE,aAAa,YAAY,OAAO,SAAS,EAAE,QAAQ,IAAI,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC;IAChG,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GACnC,CAAC;GACD,MAAM,SAAS,IAAI,EAAE;GACrB,IAAI,OAAO,MAAM,IAAI,IAAI;GACzB,IAAI,CAAC,MAAM;IACT,uBAAO,IAAI,IAAI;IACf,MAAM,IAAI,MAAM,IAAI;GACtB;GACA,KAAK,IAAI,QAAQ,IAAI;GACrB,OAAO;EACT;EACA,0BAA0B,OAAO,MAAM;GACrC,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,IAAI,CAAC,SACH,OAAO;IAAE,SAAS,CAAC;IAAG,QAAQ,CAAC;GAAE;GACnC,MAAM,WAAW,QAAQ,QAAQ,QAAQ;GACzC,OAAO;IAAE,SAAS,SAAS,cAAc,CAAC,CAAC,KAAI,OAAM;KAAE,GAAG;KAAG,UAAU,CAAC,GAAG,EAAE,QAAQ;IAAE,EAAE;IAAG,QAAQ,CAAC,GAAG,SAAS,OAAO,YAAY,eAAe,EAAE,WAAW,WAAW,CAAC,CAAC;GAAE;EACjL;EACA,0BAA0B,GAAG,SAAS;GACpC,MAAM,SAAS,eAAe,EAAE,QAAQ,QAAQ;GAChD,MAAM,OAAO,MAAM,IAAI,IAAI,CAAC,EAAE,IAAI,MAAM;GACxC,IAAI,CAAC,MACH,OAAO;GACT,MAAM,IAAI,IAAI,CAAC,CAAE,OAAO,MAAM;GAC9B,KAAK,QAAQ;GACb,OAAO;EACT;CACF;AACF;AAEA,SAAS,oBAAoB,EAAE,KAAK,UAAU,SAAS,WAAW,kBAA8S;CAC9W,OAAO;EACL,gCAAgC,OAAO,MAAM;GAC3C,MAAM,UAAU,MAAM,UAAU,EAAE,GAAG;GACrC,OAAO,UAAU,QAAQ,QAAQ,QAAQ,aAAa,KAAK,CAAC,CAAC,IAAI,eAAe,IAAI,CAAC;EACvF;EACA,sCAAsC,OAAO,MAAM;GACjD,MAAM,gBAAgB,MAAM,eAAe,EAAE,GAAG,EAAA,CAAG,QAAQ,QAAQ;GACnE,MAAM,KAAK,eAAe,EAAE,eAAe,eAAe;GAC1D,MAAM,aAAa,WAAW,IAAI,eAAe,EAAE,KAAK,KAAK,GAAG,eAAe,EAAE,UAAU,UAAU,CAAC;GACtG,MAAM,QAAQ,aAAa,IAAI,EAAE;GACjC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,gBAAgB,GAAG,WAAW;GAChD,OAAO,gBAAgB,KAAK;EAC9B;EACA,iCAAiC,OAAO,GAAG,SAAS;GAClD,MAAM,gBAAgB,MAAM,eAAe,EAAE,GAAG,EAAA,CAAG,QAAQ,QAAQ;GACnE,MAAM,KAAK,eAAe,EAAE,eAAe,eAAe;GAC1D,MAAM,SAAS,eAAe,EAAE,QAAQ,QAAQ;GAChD,MAAM,OAAO,QAAQ,CAAC,CAAC,MAAM,cAAc,MAAM;IAAE,eAAe;IAAI,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;GAAG,CAAC;GACrG,IAAI;IACF,MAAM,aAAa,MAAM,IAAI,eAAe,EAAE,UAAU,UAAU,GAAG,KAAK,IAAI;IAC9E,KAAK,OAAO,EAAE,IAAI,KAAK,CAAC;GAC1B,SACO,KAAK;IACV,KAAK,OAAO;KAAE,IAAI;KAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IAAE,CAAC;IAClF,MAAM;GACR;GACA,MAAM,QAAQ,aAAa,IAAI,EAAE;GACjC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,gBAAgB,GAAG,WAAW;GAChD,OAAO,gBAAgB,KAAK;EAC9B;EACA,sCAAsC,GAAG,SAAS,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,SAAS,SAAS,GAAG,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,KAAA,CAAS;EACzM,sCAAsC,OAAO,MAAM;GACjD,OAAO,MAAM,eAAe,EAAE,GAAG,EAAA,CAAG,QAAQ,QAAQ,aAAa,WAAW,eAAe,EAAE,eAAe,eAAe,GAAG,eAAe,EAAE,SAAS,SAAS,CAAC;EACpK;EACA,sCAAsC,OAAO,MAAM;GACjD,OAAO,MAAM,eAAe,EAAE,GAAG,EAAA,CAAG,QAAQ,QAAQ,aAAa,WAAW,eAAe,EAAE,eAAe,eAAe,GAAG,eAAe,EAAE,SAAS,SAAS,CAAC;EACpK;EAEA,kCAAkC,OAAO,MAAM;GAC7C,IAAI,OAAO,EAAE,SAAS,YAAY,CAAC,cAAc,IAAI,EAAE,IAAI,GACzD,MAAM,IAAI,mBAAmB,8BAA8B;GAC7D,MAAM,SAAS,MAAM,IAAI,cAAc,SAAS,EAAE,GAAG,CAAC;GACtD,OAAO,CAAC,GAAG,oBAAoB,OAAO,WAAW,SAAS,EAAE,IAAiD,CAAC;EAChH;CACF;AACF;;;;;;;;AASA,SAAgB,yBAAyB,EAAE,MAAM,KAAK,SAAS,mBAKhC;CAC7B,IAAI,mBAAmB,UAAU,EAAE,gBAAgB,CAAC;CACpD,IAAI,mBAAmB,SAAS,IAAI;CACpC,MAAM,MAAM,iBAAiB,MAAM,GAAG;CACtC,MAAM,QAAmB;EAAE,uBAAO,IAAI,IAAI;EAAG,yBAAS,IAAI,IAAI;EAAG,uBAAO,IAAI,IAAI;CAAE;CAClF,SAAS,SAAS;EAChB,KAAK,MAAM,cAAc,MAAM,MAAM,IAAI,IAAI,CAAC,EAAE,OAAO,KAAK,CAAC,GAC3D,WAAW,MAAM;EACnB,MAAM,MAAM,OAAO,IAAI;EACvB,KAAK,MAAM,cAAc,MAAM,QAAQ,IAAI,IAAI,KAAK,CAAC,GACnD,WAAW,MAAM;EACnB,MAAM,QAAQ,OAAO,IAAI;EACzB,KAAK,MAAM,QAAQ,MAAM,MAAM,IAAI,IAAI,CAAC,EAAE,OAAO,KAAK,CAAC,GACrD,KAAK,QAAQ;EACf,MAAM,MAAM,OAAO,IAAI;EACvB,IAAI,mBAAmB,QAAQ,OAAO,IAAI;EAC1C,IAAI,mBAAmB,MAAM,QAAQ,IAAI;CAC3C,CAAC;CACD,OAAO;EACL,GAAG,iBAAiB,KAAK,KAAK;EAC9B,GAAG,2BAA2B,GAAG;EACjC,GAAG,gBAAgB,KAAK,KAAK;EAC7B,GAAG,oBAAoB,GAAG;CAC5B;AACF;;;;AC5eA,MAAM,cAAc;;AAEpB,MAAM,iBAAiB;;AAGvB,SAAS,aAAa,GAA2E;CAC/F,IAAI,OAAO,EAAE,SAAS,YAAY,OAAO,EAAE,WAAW,YAAY,CAAC,OAAO,cAAc,EAAE,MAAM,KAAK,EAAE,SAAS,KAAK,EAAE,SAAS,EAAE,KAAK,QACrI,MAAM,IAAI,mBAAmB,oDAAoD;CACnF,OAAO;EAAE,MAAM,EAAE;EAAM,QAAQ,EAAE;CAAO;AAC1C;;AAGA,SAAS,SAA8B,MAAwC;CAC7E,MAAM,uBAAO,IAAI,QAAc;CAC/B,QAAQ,UAAU;EAChB,IAAI,QAAQ,KAAK,IAAI,KAAK;EAC1B,IAAI,UAAU,KAAA,GAAW;GACvB,QAAQ,KAAK,KAAK;GAClB,KAAK,IAAI,OAAO,KAAK;EACvB;EACA,OAAO;CACT;AACF;AAEA,SAAgB,0BAA0B,EAAE,MAAM,KAAK,SAAS,mBAMb;CACjD,MAAM,YAAY,QAAyB,cAAc;EAAE;EAAK;CAAK,GAAG,GAAG;CAC3E,MAAM,YAAY,QAAiB,IAAI,cAAc,SAAS,GAAG,CAAC;CAClE,MAAM,aAAa,OAAO,SAA8C,MAAM,SAAS,GAAG,EAAA,CAAG;;CAE7F,MAAM,WAAW,eAA2C,uBAAuB,CAAC;;CAEpF,MAAM,aAAa,UAA+C,aAAY,wBAAwB,QAAQ,CAAC;;CAE/G,MAAM,0BAAU,IAAI,IAAY;CAEhC,OAAO;EACL,GAAG,yBAAyB;GAAE;GAAM;GAAK;GAAS;EAAgB,CAAC;EACnE,yBAAyB,OAAM,MAAK,6BAA6B,MAAM,WAAW,EAAE,GAAG,EAAA,CAAG,mBAAmB;EAC7G,uBAAuB,OAAO,GAAG,SAAS;GACxC,MAAM,UAAU,aAAa,CAAC;GAC9B,IAAI,OAAO,EAAE,eAAe,YAAY,OAAO,EAAE,UAAU,UACzD,MAAM,IAAI,mBAAmB,uCAAuC;GACtE,MAAM,MAAM,SAAS,EAAE,GAAG;GAC1B,MAAM,YAAY,MAAM,IAAI,cAAc,GAAG,EAAA,CAAG,WAAW,oBAAoB,MAAK,MAAK,EAAE,OAAO,EAAE,UAAU;GAC9G,IAAI,CAAC,YAAY,OAAO,SAAS,YAAY,YAC3C,OAAO,CAAC;GACV,OAAO,SAAS,IAAI,CAAC,CAAC,QAAQ,GAAG,IAAI,QAAQ,SAAS,MAAM,UAAU,EAAE,OAAO,OAAO;EACxF;EACA,sBAAsB,OAAO,GAAG,SAAS;GACvC,MAAM,EAAE,MAAM,WAAW,aAAa,CAAC;GACvC,MAAM,SAAS,IAAI,CAAC,CAAC,QAAQ,MAAM,WAAW,EAAE,GAAG,EAAA,CAAG,qBAAqB,MAAM,MAAM;EACzF;EAEA,wBAAwB,OAAO,MAAM;GACnC,IAAI,EAAE,SAAS,MACb,OAAO,uBAAuB,MAAM,WAAW,EAAE,GAAG,CAAC;GACvD,MAAM,SAAS,IAAI,oBAAoB,SAAS,EAAE,GAAG,CAAC;GACtD,OAAO,SAAS,wBAAwB,MAAM,OAAA,CAAQ,UAAU,IAAI;EACtE;EACA,sBAAsB,OAAO,MAAM;GACjC,MAAM,QAAQ,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,MAAM,MAAM,GAAG,WAAW,IAAI,CAAC;GACxE,MAAM,WAAW,WAAW,MAAM,WAAW,EAAE,GAAG,CAAC;GACnD,OAAO,QAAQ,IAAI,MAAM,KAAK,SAAS;IACrC,MAAM,EAAE,YAAY,QAAS,QAAQ,CAAC;IACtC,IAAI,OAAO,eAAe,YAAY,OAAO,QAAQ,YAAY,IAAI,SAAS,gBAC5E,OAAO;IACT,OAAO,SAAS,QAAQ,YAAY,GAAG;GACzC,CAAC,CAAC;EACJ;EACA,kBAAkB,OAAO,MAAM;GAC7B,MAAM,SAAS,qBAAqB,EAAE,MAAM;GAC5C,OAAO,SAAS,sBAAsB,QAAQ,MAAM,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC;EAC5E;EACA,cAAc,OAAO,MAAM;GACzB,MAAM,SAAS,qBAAqB,EAAE,MAAM;GAC5C,IAAI,CAAC,UAAU,OAAO,EAAE,WAAW,YAAY,OAAO,EAAE,OAAO,UAC7D,OAAO,EAAE,QAAQ,iBAAiB;GACpC,MAAM,MAAM;IACV,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;IAC1D,GAAI,OAAO,EAAE,QAAQ,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;GAC7D;GACA,OAAO,eAAe,EAAE,QAAQ,EAAE,IAAI,QAAQ,MAAM,WAAW,EAAE,GAAG,GAAG,GAAG;EAC5E;EAEA,2BAA2B,OAAO,MAAM;GACtC,MAAM,SAAS,MAAM,SAAS,EAAE,GAAG;GACnC,OAAO,mBAAmB;IAAE,kBAAkB,OAAO;IAA2B,aAAa,OAAO;GAAqB,CAAC;EAC5H;EACA,sBAAsB,OAAO,MAAM;GACjC,MAAM,SAAS,MAAM,SAAS,EAAE,GAAG;GACnC,OAAO,oBAAoB,OAAO,2BAA2B,OAAO,oBAAoB;EAC1F;EACA,6BAA6B,OAAM,MAAK,qBAAqB,MAAM,SAAS,EAAE,GAAG,EAAA,CAAG,oBAAoB;EACxG,wBAAwB,OAAO,GAAG,SAAS;GACzC,IAAI,OAAO,EAAE,cAAc,YAAY,OAAO,EAAE,QAAQ,UACtD,MAAM,IAAI,mBAAmB,oCAAoC;GACnE,MAAM,MAAM,SAAS,EAAE,GAAG;GAC1B,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;GAE1C,IAAI,KAAK,OAAO;IACd,MAAM,WAAW,IAAI,mBAAmB,WAAW,GAAG,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC,EAAE,UAAU,OAAO,MAAM,EAAE;IAC5G,MAAM,WAAW,UAAU,SAAS,WAAW,YAAY,QAAQ,IAAI;IACvE,IAAI,CAAC,YAAY,KAAK,OAAO,QAAQ,GACnC,MAAM,IAAI,iBAAiB,wBAAwB,OAAO,EAAE,UAAU,KAAK,EAAE,IAAI,IAAI,KAAK,OAAO,QAAQ;GAC7G;GACA,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,UAAU,QAAQ,EAAE;GACnD,IAAI,QAAQ,IAAI,KAAK,GACnB,MAAM,IAAI,MAAM,4BAA4B;GAC9C,QAAQ,IAAI,KAAK;GACjB,IAAI;IAEF,MAAM,oBAAoB,IAAI,mBAAmB,WAAW,GAAG,CAAC,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC,EAAE;IAC5F,IAAI,mBACF,OAAO,MAAM,kBAAkB,UAAU,EAAE,GAAG;IAChD,OAAO,MAAM,mBAAmB,OAAO,sBAAsB,EAAE,WAAW,EAAE,GAAG;GACjF,UACQ;IACN,QAAQ,OAAO,KAAK;GACtB;EACF;CACF;AACF;;;;AC7IA,MAAM,eAAe;;AAGrB,MAAM,mBAAmB;;AAEzB,MAAM,YAAY;AAElB,SAAS,WAAW,OAAgB,MAAc,MAAM,UAAoB;CAC1E,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,OAAO,MAAM,MAAK,MAAK,OAAO,MAAM,QAAQ,GACtF,MAAM,IAAI,mBAAmB,GAAG,KAAK,+BAA+B,IAAI,UAAU;CACpF,OAAO;AACT;AAEA,SAAgB,oBAAoB,EAAE,WAAW,OAAO,WAK9B;CACxB,IAAI,OACF,SAAQ,SAAQ,MAAM,QAAQ,IAAI,CAAC;CACrC,MAAM,UAAU,QAAyB;EACvC,IAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,GAC5C,MAAM,IAAI,mBAAmB,iCAAiC;EAChE,OAAO,UAAU,cAAc,GAAG;CACpC;CAEA,MAAM,gCAAgB,IAAI,QAA0B;CACpD,MAAM,gBAAgB,SAA2B;EAC/C,IAAI,KAAK,cAAc,IAAI,IAAI;EAC/B,IAAI,CAAC,IACH,cAAc,IAAI,MAAM,KAAK,WAAW,CAAC;EAC3C,OAAO;CACT;CACA,OAAO;EACL,eAAc,MAAK,iBAAiB,EAAE,KAAK,OAAO,EAAE,GAAG,EAAE,CAAC;EAC1D,mBAAkB,MAAK,eAAe,OAAO,EAAE,GAAG,CAAC;EACnD,iBAAiB,GAAG,SAAS;GAC3B,IAAI,OAAO,EAAE,UAAU,UACrB,MAAM,IAAI,mBAAmB,yBAAyB;GACxD,OAAO,gBAAgB,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,MAAM,GAAG,gBAAgB,GAAG;IACxE,eAAe,EAAE,kBAAkB;IACnC,UAAU,GAAG,aAAa,IAAI,EAAE,GAAGC,iBAAe,EAAE,UAAU,UAAU,KAAK;GAC/E,CAAC;EACH;EACA,uBAAsB,MAAK,aAAa,OAAO,EAAE,GAAG,GAAG,WAAW,EAAE,OAAO,SAAS,SAAS,CAAC;EAC9F,sBAAqB,MAAK,eAAe,OAAO,EAAE,GAAG,GAAG,WAAW,EAAE,OAAO,OAAO,GAAG;GACpF,UAAU,EAAE,aAAa,KAAA,IAAY,CAAC,IAAI,WAAW,EAAE,UAAU,UAAU;GAC3E,GAAI,OAAO,EAAE,cAAc,WAAW,EAAE,WAAW,EAAE,UAAU,IAAI,CAAC;EACtE,CAAC;EACD,gCAAgC,MAAM;GACpC,sBAAsB,OAAO,EAAE,GAAG,CAAC;EACrC;EACA,2BAA0B,MAAK,qBAAqB,OAAO,EAAE,GAAG,CAAC;EACjE,sBAAsB,GAAG,SAAS;GAChC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,wDAAwD;GAC1E,IAAI,OAAO,EAAE,WAAW,YAAY,CAAC,aAAa,KAAK,EAAE,MAAM,GAC7D,MAAM,IAAI,mBAAmB,+CAA+C;GAC9E,MAAM,SAAS,EAAE,QAAQ,IAAI;EAC/B;CACF;AACF;;;;AC/EA,MAAa,6BAA6B;AAE1C,SAAgB,iBAAiB,EAAE,WAAW,cAAc,QAAQ,sBAAsB,QAQI;CAC5F,MAAM,QAAQ,sBAAsB;EAClC,cAAc,aAAa,OAAO,eAAe,KAAK,QAAQ,QAAQ,CAAC,CAAC,GAAA,CACrE,QAAO,MAAK,EAAE,OAAO,CAAC,CACtB,KAAI,OAAM;GAAE,MAAM,EAAE;GAAM,OAAO,EAAE;GAAO,WAAW,EAAE;GAAW,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;EAAG,EAAE;EACjH,aAAa,UAAU,SAAS,CAAC,CAAC;EAClC,QAAQ,kBAAkB;GAAE,gBAAgB;GAAO,WAAW;GAAO,MAAM;GAAO,OAAO;GAAM,eAAe,cAAc;EAAE;CAChI,CAAC;CACD,OAAO;EACL,kBAAkB,UAAU,SAAS;EACrC,gBAAe,MAAK,UAAU,KAAKC,iBAAe,GAAG,MAAM,MAAM,CAAC;EAClE,aAAa,MAAM;GACjB,IAAI,CAAC,cAAc,GACjB,MAAM,IAAI,MAAM,0BAA0B;GAC5C,OAAO,UAAU,MAAM,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,MAAM,MAAM,CAAC;EAC3F;EACA,kBAAiB,MAAK,UAAU,OAAO,eAAe,EAAE,OAAO,OAAO,GAAGA,iBAAe,EAAE,MAAM,MAAM,CAAC;EACvG,sBAAqB,MAAK,MAAM,GAAG,YAAY,IAAI;CACrD;AACF;;;AChBA,SAAgB,sBAAsB,EAAE,MAAM,OAAO,WAAW,eAAe,QAAQ,aAU3D;CAC1B,MAAM,SAAS,QAAgC,SAAS;EAAE,GAAG;EAAK;CAAO,IAAI;;CAE7E,MAAM,+BAAe,IAAI,IAA8B;;;;;;;;;;;CAWvD,eAAe,iBACb,WACA,OACA,OAAoC,CAAC,GACtB;EAKf,MAAM,KAAK,iBAAiB,WAAW,OAAO,IAAI;EAClD,UAAU;GAAE,MAAM;GAAoB,IAAI;GAAU;EAAU,CAAC;CACjE;CAEA,eAAe,aACb,WACA,QACe;EACf,MAAM,OAAO,MAAM,YAAY,OAAO,SAAS;EAC/C,OAAO,IAAI;EACX,KAAK,YAAY,KAAK,IAAI;EAC1B,MAAM,MAAM,KAAK,IAAI;EACrB,UAAU;GAAE,MAAM;GAAoB,IAAI;GAAU;EAAU,CAAC;CACjE;CAEA,eAAe,iBAAiB,QAA6B,QAA6C;EAMxG,MAAM,WAAW,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI;GAAE,GAAG,iBAAiB,MAAM;IAAI,qBAAqB;EAAO,IAAI,iBAAiB,MAAM;EAEnJ,MAAM,YAAY,OAAO,aAAa,OAAO,KAAK,aAAa,IAAI,OAAO,YAAY,IAAI,CAAC,EAAE,gBAAgB,KAAA,IAAY;EACzH,MAAM,MAAM,WAAW,SAAS,CAAC,CAAC,YAAY,CAAC,YAAY,UAAU,cAAc,OAAO,OAAO,EAAE,IAAI,OAAO;EAC9G,MAAM,KAAK,MAAM,KAAK,cAAc;GAClC;GACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;GAC/B,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;GAC9C,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;GACpD,GAAI,OAAO,eAAe,OAAO,UAAU;IAAE,aAAa,OAAO;IAAa,SAAS,OAAO;GAAQ,IAAI,CAAC;GAC3G,GAAI,OAAO,eAAe,OAAO,WAAW,OAAO,OAAO,YAAY,YAAY,OAAO,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;GAClI,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;GAC1D,GAAI,OAAO,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC;GACtD,GAAI,OAAO,WAAW,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,UAAU,KAAK,EAAE,IAAI,CAAC;GAC/E,GAAI,OAAO,OAAO,YAAY,YAAY,OAAO,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;GAC1F,GAAI,OAAO,OAAO,WAAW,YAAY,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;GACtF,GAAI,OAAO,aAAa,OACpB,EACE,aAAa;IACX,MAAM,OAAO,YAAY;IACzB,GAAI,OAAO,YAAY,SAAS,EAAE,QAAQ,OAAO,YAAY,OAAO,IAAI,CAAC;IACzE,GAAI,OAAO,YAAY,OAAO,EAAE,MAAM,OAAO,YAAY,KAAK,IAAI,CAAC;GACrE,EACF,IACA,CAAC;EACP,CAAC;EACD,MAAM,OAAO,MAAM,YAAY,OAAO,EAAE;EACxC,UAAU;GAAE,MAAM;GAAoB,IAAI;GAAU,WAAW;EAAG,CAAC;EACnE,OAAO,MAAM,MAAM,MAAM,IAAI,CAAC;CAChC;CAEA,OAAO;EACL,iBAAiB,OAAM,OAAM,MAAM,gBAAgB,MAAM,OAAO,CAAC,EAAA,CAAG,IAAI,KAAK;EAE7E,mBAAmB,OAAO,GAAG,SAAS,MAAM,iBAAiB,GAAG,EAAE,WAAW,KAAA,IAAY,KAAA,IAAY,MAAM,iBAAiB,EAAE,QAAQ,MAAM,iBAAiB,CAAC;EAC9J,mBAAmB,OAAO,MAAM;GAC9B,cAAc,EAAE,SAAS;GAEzB,MAAM,EAAE,gBAAgB,MAAM,KAAK,cAAc,EAAE,SAAS;GAC5D,UAAU;IAAE,MAAM;IAAoB,IAAI;IAAU,WAAW,EAAE;GAAU,CAAC;GAC5E,OAAO,YAAY,WAAW,CAAC,YAAY,SAAS,CAAC,IAAI,EAAE,YAAY;EACzE;EACA,wBAAwB,OAAO,MAAM;GACnC,MAAM,QAAQ,OAAO,OAAuD;IAC1E,MAAM,OAAO,KAAK,MAAM,MAAM,KAAK,EAAE,IAAI;IACzC,OAAO,OAAO,MAAM,MAAM,MAAM,IAAI,CAAC,IAAI;GAC3C;GACA,MAAM,CAAC,MAAM,UAAU,MAAM,QAAQ,IAAI,CAAC,MAAM,MAAM,kBAAkB,OAAO,EAAE,SAAS,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC,CAAC;GACjH,OAAO;IAAE;IAAM;GAAO;EACxB;EAIA,sBAAqB,MAAK,iBAAiB,EAAE,WAAW;GAAE,OAAO,EAAE;IAAQ,mBAAmB;EAAO,GAAG,EAAE,eAAe,MAAM,CAAC;EAChI,wBAAwB,OAAO,MAAM;GACnC,MAAM,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC;GAG5D,IAAI,EAAE,UACJ,KAAU,UAAU,eAAe,EAAE,SAAS;EAClD;EAEA,yBAAwB,MAAK,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,GAAG,EAAE,eAAe,MAAM,CAAC;EAE7G,uBAAuB,GAAG,SAAS;GACjC,MAAM,QAAQ,YAA2B;IAEvC,MAAM,UAAU,YAAY,iBAAiB,KAAK,eAAe,EAAE,SAAS,KAAK,MAAM,YAAY,OAAO,EAAE,SAAS,EAAA,CAAG,QAAQ;IAChI,MAAM,SAAS,MAAM,iBAAiB,EAAE,QAAQ,MAAM,sBAAsB,OAAO;IACnF,OAAO,iBAAiB,EAAE,WAAW,GAAG,qBAAqB,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA,EAAU,GAAG,EAAE,eAAe,MAAM,CAAC;GAC9I;GACA,MAAM,QAAQ,aAAa,IAAI,EAAE,SAAS,KAAK,QAAQ,QAAQ,EAAA,CAAG,KAAK,OAAO,KAAK;GACnF,MAAM,UAAU,KAAK,YAAY,KAAA,CAAS;GAC1C,aAAa,IAAI,EAAE,WAAW,OAAO;GACrC,QAAa,WAAW;IACtB,IAAI,aAAa,IAAI,EAAE,SAAS,MAAM,SACpC,aAAa,OAAO,EAAE,SAAS;GACnC,CAAC;GACD,OAAO;EACT;EAIA,sBAAqB,MAAK,iBACxB,EAAE,WACF,GAAG,qBAAqB,OAAO,EAAE,YAAY,YAAY,EAAE,UAAU,EAAE,UAAU,iBAAiB,GAClG,EAAE,eAAe,MAAM,CACzB;EACA,uBAAuB,OAAO,MAAM;GAYlC,MAAM,UAAU,KAAK,oBAAoB,EAAE,WAAW,EAAE,OAAO;GAC/D,IAAI,MAAM,KAAK,sBAAsB,EAAE,WAAW,EAAE,OAAO,GACzD,UAAU;IAAE,MAAM;IAAoB,IAAI;IAAU,WAAW,EAAE;GAAU,CAAC;QAG5E,MAAM,aAAa,EAAE,YAAY,MAAM;IACrC,EAAE,UAAU,EAAE;GAChB,CAAC;GAEH,IAAI,SACF,KAAK,uBAAuB,EAAE,SAAS;EAC3C;EACA,uBAAsB,MAAK,iBAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC;EAC7E,qBAAqB,OAAO,MAAM;GAIhC,MAAM,KAAK,gBAAgB,EAAE,WAAW;IACtC,aAAa,EAAE;IACf,SAAS,EAAE;IACX,GAAI,OAAO,EAAE,YAAY,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;IAC3E,GAAI,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,IAAI,CAAC;IAChD,GAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;IACvC,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,IAAI,CAAC;GAC3D,CAAC;GACD,UAAU;IAAE,MAAM;IAAoB,IAAI;IAAU,WAAW,EAAE;GAAU,CAAC;EAC9E;EACA,6BAA4B,MAAK,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,CAAC;EAC1F,uBAAuB,MAAM;GAC3B,MAAM,MAAM,OAAO,EAAE,QAAQ,WAAW,EAAE,MAAM;GAEhD,OAAO,KAAK,iBAAiB,EAAE,WAAW,GAAG;EAC/C;CACF;AACF;;AAGA,SAAS,iBAAiB,QAAkE;CAC1F,MAAM,WAAoC,CAAC;CAC3C,IAAI,OAAO,OAAO,WAAW,UAC3B,SAAS,SAAS,OAAO;CAC3B,IAAI,OAAO,gBAAgB,OAAO,OAAO,iBAAiB,UAAU;EAClE,MAAM,UAAU,OAAO,YAAY,OAAO,QAAQ,OAAO,YAAY,CAAC,CAAC,QAAQ,GAAG,QAAQ,OAAO,OAAO,SAAS,CAAC;EAClH,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,GAChC,SAAS,eAAe;CAC5B;CACA,IAAI,MAAM,QAAQ,OAAO,YAAY,GAAG;EACtC,MAAM,OAAO,iBAAiB,OAAO,aAAa,MAAM,GAAG,EAAE,CAAC;EAC9D,IAAI,KAAK,OAAO,GACd,SAAS,0BAA0B,kBAAkB,IAAI;CAC7D;CACA,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,IAAI,WAAW,KAAA;AACvD;AAEA,eAAsB,gBAAgB,MAAgB,OAAqB,GAAsD;CAC/H,MAAM,SACF,GAAG,gBAAgB,KAAA,IAAY,EAAE,aAAa,EAAE,YAA6B,IAAI,KAAA;CAErF,MAAM,gBAAgB,SAAqC;EACzD,MAAM,WAAW,KAAK,QAAQ,QAAQ;GACpC,IAAI,GAAG,YAAY,UACjB,OAAO,CAAC,IAAI;GACd,IAAI,GAAG,YAAY,YACjB,OAAO,IAAI;GACb,OAAO;EACT,CAAC;EACD,SAAS,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;EACjD,OAAO;CACT;CAOA,IAAI,MAAM,UAER,OAAO,cAAa,MADA,MAAM,SAAS,MAAM,EAAA,CACf,QAAO,SAAQ,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS;EACpF,MAAM,KAAK,KAAK;EAIhB,MAAM,QAAQ,mBAAmB,KAAK,gBAAgB,CAAC,KAAK,aAAa,IAAI,CAAC,GAAG,EAAE;EACnF,MAAM,UAAU,KAAK,iBAAiB,KAAK,EAAE;EAC7C,MAAM,MAAM,OAAO,GAAG,QAAQ,WAAW,GAAG,MAAO,KAAK,eAAe;EACvE,OAAO;GACL,IAAI,KAAK;GACT;GAEA,GAAI,cAAc,EAAE,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;GAC5C,GAAI,mBAAmB,EAAE,IAAI,EAAE,SAAS,mBAAmB,EAAE,EAAE,IAAI,CAAC;GACpE,aAAa,KAAK,eAAe;GACjC;GACA,GAAG,aAAa,KAAK,eAAe,GAAG;GACvC,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;GAGhD,QAAQ,UACJ,YACA,iBAAiB,KAAK,QAAQ,KAAK,WAAW,KAAK,IAAI,GAAG,KAAK,QAAQ,IACrE,SACC,KAAK,UAAU;GACtB,GAAI,UAAU,WAAW,MAAM,KAAK,EAAE,IAAI,CAAC;GAC3C,WAAW,KAAK,aAAa;GAC7B,WAAW,KAAK;GAChB,UAAU,GAAG,aAAa;GAC1B,GAAI,GAAG,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;GACjD,UAAU;IACR,MAAM,cAAc,0BAA0B,EAAE;IAChD,OAAO,cAAc,EAAE,YAAY,IAAI,CAAC;GAC1C,EAAA,CAAG;GACH,GAAI,OAAO,GAAG,gBAAgB,WAAW,EAAE,aAAa,GAAG,YAAY,IAAI,CAAC;GAC5E,GAAI,OAAO,GAAG,YAAY,WAAW,EAAE,SAAS,GAAG,QAAQ,IAAI,CAAC;GAChE,GAAI,mBAAmB,EAAE,IAAI,EAAE,SAAS,mBAAmB,EAAE,EAAE,IAAI,CAAC;GACpE,GAAI,OAAO,GAAG,WAAW,WAAW,EAAE,QAAQ,GAAG,OAA+B,IAAI,CAAC;GACrF,GAAI,GAAG,gBAAgB,OAAO,GAAG,iBAAiB,WAC9C,EAAE,cAAc,GAAG,aAAwC,IAC3D,CAAC;GACL,UAAU;IACR,MAAM,YAAY,sBAAsB,EAAE;IAC1C,OAAO,YAAY,EAAE,gBAAgB,UAAU,IAAI,CAAC;GACtD,EAAA,CAAG;GACH,GAAG,YAAY,EAAE;EACnB;CACF,CAAC,CAAC;CAGJ,MAAM,MAAM,MAAM,MAAM,KAAK,MAAM;CACnC,MAAM,OAAqB,CAAC;CAC5B,KAAK,MAAM,MAAM,KAAK;EACpB,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;EAChC,IAAI,CAAC,QAAQ,cAAc,KAAK,QAAQ,GACtC;EACF,KAAK,KAAK,MAAM,MAAM,IAAI,CAAC;CAC7B;CACA,OAAO,aAAa,IAAI;AAC1B;;AAGA,eAAe,kBAAkB,OAAqB,UAA+C;CAOnG,QANa,MAAM,YACd,MAAM,MAAM,SAAS,EAAA,CAAG,KAAI,SAAQ;EAAE,IAAI,IAAI;EAAI,UAAU,IAAI;EAAU,WAAW,IAAI;CAAU,EAAE,IACrG,MAAM,QAAQ,KAAK,MAAM,MAAM,KAAK,EAAA,CAAG,IAAI,OAAO,OAAO;EACxD,MAAM,OAAO,MAAM,MAAM,KAAK,EAAE;EAChC,OAAO;GAAE;GAAI,UAAU,MAAM;GAAU,WAAW,MAAM,aAAa;EAAE;CACzE,CAAC,CAAC,EAAA,CAEH,QAAO,QAAO,IAAI,OAAO,YAAY,kBAAkB,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAClF,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,EAAE,EAC3C;AACN;;AAGA,SAAS,aAAa,QAAkD;CACtE,MAAM,UAAU,SAAS,gBAAgB,MAAM,IAAI;CACnD,OAAO,UAAU,EAAE,QAAQ,IAAI,CAAC;AAClC;;;;;AAMA,SAAS,WAAW,MAAgB,WAAsE;CACxG,MAAM,OAAO,KAAK,eAAe,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtD,MAAM,MAAM,cAAc,IAAI;CAC9B,MAAM,YAAY,qBAAqB,IAAI;CAC3C,OAAO;EACL,GAAI,MAAM,EAAE,cAAc,IAAI,UAAU,IAAI,CAAC;EAC7C,GAAI,UAAU,SAAS,IAAI,EAAE,cAAc,UAAU,IAAI,CAAC;CAC5D;AACF;AAEA,SAAS,MAAM,MAAgB,MAA+B;CAC5D,MAAM,OAAO,KAAK,YAAY,CAAC;CAG/B,MAAM,QAAQ,mBAAmB,KAAK,OAAO,IAAI;CACjD,MAAM,UAAU,KAAK,iBAAiB,KAAK,EAAE;CAE7C,OAAO;EACL,IAAI,KAAK;EACT;EACA,GAAI,cAAc,IAAI,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;EAC9C,GAAI,mBAAmB,IAAI,IAAI,EAAE,SAAS,mBAAmB,IAAI,EAAE,IAAI,CAAC;EACxE,aAAa,KAAK,eAAe;EACjC,KAAK,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAO,KAAK,eAAe;EACpE,GAAG,aAAa,KAAK,gBAAgB,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,GAAG;EAClF,GAAI,OAAO,KAAK,YAAY,WAAW,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EACpE,QAAQ,UACJ,YACA,iBAAiB,KAAK,QAAQ,KAAK,WAAW,KAAK,IAAI,GAAG,KAAK,QAAQ,IACrE,SACA,KAAK;EACX,GAAI,UAAU,WAAW,MAAM,KAAK,EAAE,IAAI,CAAC;EAC3C,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,UAAU,KAAK,aAAa;EAC5B,GAAI,KAAK,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;EACnD,UAAU;GACR,MAAM,cAAc,0BAA0B,IAAI;GAClD,OAAO,cAAc,EAAE,YAAY,IAAI,CAAC;EAC1C,EAAA,CAAG;EACH,GAAI,OAAO,KAAK,gBAAgB,WAAW,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;EAChF,GAAI,OAAO,KAAK,YAAY,WAAW,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EACpE,GAAI,mBAAmB,IAAI,IAAI,EAAE,SAAS,mBAAmB,IAAI,EAAE,IAAI,CAAC;EACxE,GAAI,OAAO,KAAK,WAAW,WAAW,EAAE,QAAQ,KAAK,OAA+B,IAAI,CAAC;EACzF,GAAI,KAAK,gBAAgB,OAAO,KAAK,iBAAiB,WAClD,EAAE,cAAc,KAAK,aAAwC,IAC7D,CAAC;EACL,UAAU;GACR,MAAM,YAAY,sBAAsB,IAAI;GAC5C,OAAO,YAAY,EAAE,gBAAgB,UAAU,IAAI,CAAC;EACtD,EAAA,CAAG;EACH,GAAG,YAAY,IAAI;CACrB;AACF;;AAGA,SAAS,YAAY,UAAsE;CACzF,MAAM,SAAS,kBAAkB,QAAQ;CACzC,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AACxD;;;;ACrXA,MAAa,oBAAoB;;AAOjC,SAAS,WAAW,QAA+B;CACjD,IAAI;EACF,MAAM,OAAO,aAAa,OAAO,MAAM;EACvC,OAAO,YAAY,IAAI,KAAK;CAC9B,QACM;EACJ,OAAO;CACT;AACF;AAEA,SAAgB,kBAAkB,EAAE,MAAM,OAAO,WAAW,aAAa,SAAS,cAAc,QASxE;CACtB,MAAM,yBAAS,IAAI,IAAwB;CAC3C,SAAQ,SAAQ,OAAO,IAAI,IAAI,CAAC,EAAE,OAAO,CAAC;CAE1C,MAAM,OAAO,kBAA4B,KAAK,WAAW;EACvD,gBAAgB,KAAK,WAAW,SAAS,aAAa,YAAY;EAClE,IAAI,WAAW,QACb,KAAK,MAAM,QAAQ,KAAK,OAAO,GAAG,GAChC,KAAK,KAAK;GAAE,MAAM;GAAY;EAAI,CAAC;CAEzC,CAAC;CACD,SAAQ,SAAQ,KAAK,QAAQ,IAAI,CAAC;CAClC,MAAM,UAAU,QAAyB,UAAU,cAAc,eAAe,KAAK,KAAK,CAAC;;CAE3F,MAAM,cAAc,QAAyB;EAC3C,MAAM,KAAK,OAAO,GAAG;EACrB,UAAU,cAAc,YAAY,EAAE,KAAK,EAAE;EAC7C,OAAO;CACT;;CAGA,eAAe,mBAAmB,KAAa,QAAoC;EACjF,MAAM,WAAW,WAAW,GAAG;EAC/B,IAAI,CAAC,UACH,OAAO,CAAC;EAEV,QAAO,MADY,gBAAgB,MAAM,OAAO,EAAE,SAAS,SAAS,CAAC,EAAA,CACzD,QAAO,QAAO,IAAI,OAAO,UAAU,IAAI,OAAO,WAAW,IAAI,GAAG,MAAM,QAAQ,CAAC,CAAC,KAAI,QAAO,IAAI,EAAE;CAC/G;;CAGA,eAAe,YAAY,KAAa,WAAiD;EACvF,IAAI,aAAa,KAAK,iBAAiB,SAAS,GAC9C,OAAO;EACT,QAAQ,MAAM,mBAAmB,KAAK,SAAS,EAAA,CAAG,MAAK,OAAM,KAAK,iBAAiB,EAAE,CAAC;CACxF;CAEA,OAAO;EACL,eAAc,MAAK,QAAQ,OAAO,EAAE,GAAG,CAAC;EACxC,iBAAgB,MAAK,YAAY,OAAO,EAAE,GAAG,CAAC;EAC9C,qBAAoB,MAAK,UAAU,OAAO,EAAE,GAAG,GAAGC,iBAAe,EAAE,QAAQ,QAAQ,GAAG,EAAE,UAAU,IAAI;EACtG,0BAAyB,MAAK,MAAM,OAAO,EAAE,GAAG,GAAG,eAAe,EAAE,QAAQ,QAAQ,GAAG,EAAE,UAAU,IAAI;EACvG,eAAc,MAAK,UAAU,WAAW,EAAE,GAAG,GAAG,eAAe,EAAE,KAAK,KAAK,CAAC;EAC5E,mBAAkB,MAAK,UAAU,WAAW,EAAE,GAAG,CAAC;EAClD,aAAa,MAAM;GACjB,IAAI,EAAE,YAAY,KAAA,KAAa,EAAE,YAAY,SAAS,OAAO,EAAE,YAAY,YAAY,EAAE,UAAU,IACjG,MAAM,IAAI,mBAAmB,gDAAgD;GAC/E,OAAO,QAAQ,WAAW,EAAE,GAAG,GAAGA,iBAAe,EAAE,MAAM,MAAM,GAAG,EAAE,YAAY,OAAO,WAAW,EAAE,OAAO;EAC7G;EACA,gBAAgB,OAAO,MAAM;GAC3B,MAAM,MAAM,OAAO,EAAE,GAAG;GACxB,MAAM,SAAS,EAAE;GACjB,MAAM,KAAK,OAAO,WAAW,YAAY,WAAW,OAAQ,OAA4B,KAAK,KAAA;GAC7F,IAAI,OAAO,WAAW,YAAY,OAAO,OAAO,UAC9C,MAAM,IAAI,mBAAmB,iDAAiD;GAChF,MAAM,YAAYA,iBAAe,EAAE,WAAW,WAAW;GACzD,MAAM,SAAS,MAAM,UAAU,KAAK,OAAO,WAAW,WAAW,SAAS,EAAM,GAAa,GAAG,MAAM,YAAY,KAAK,SAAS,CAAC;GACjI,IAAI,OAAO,MAAM,CAAC,OAAO,UACvB,OAAO;GAET,MAAM,UAAU,UAAU,SAAS,CAAC,CAAC,MAAM,MAAK,SAAQ,SAAS,MAAM,OAAO,QAAS,CAAC;GACxF,OAAO;IAAE,GAAG;IAAQ,OAAO,UAAU,MAAM,mBAAmB,OAAO,UAAU,SAAS,IAAI,CAAC;GAAE;EACjG;EACA,oBAAoB,OAAO,MAAM;GAC/B,MAAM,MAAM,OAAO,EAAE,GAAG;GACxB,OAAO,gBAAgB,KAAK,eAAe,EAAE,MAAM,MAAM,GAAG,MAAM,YAAY,KAAKA,iBAAe,EAAE,WAAW,WAAW,CAAC,CAAC;EAC9H;EACA,YAAY,OAAO,MAAM;GACvB,MAAM,MAAM,OAAO,EAAE,GAAG;GACxB,OAAO,QAAQ,KAAK,MAAM,YAAY,KAAKA,iBAAe,EAAE,WAAW,WAAW,CAAC,CAAC;EACtF;EACA,aAAa,OAAO,GAAG,SAAS;GAC9B,IAAI,CAAC,MAAM,GACT,MAAM,IAAI,MAAM,iBAAiB;GACnC,MAAM,QAAQ,eAAe,EAAE,OAAO,OAAO;GAC7C,MAAM,SAAS,UAAU,cAAc,eAAe,EAAE,QAAQ,QAAQ,CAAC;GAEzE,MAAM,OAAO,eAAe,KAAK;GACjC,IAAI,QAAQ,UAAU,KAAK,KAAK,QAAQ,GAAG;IACzC,MAAM,SAAS,IAAI,IAAI,KAAK,QAAQ;IACpC,IAAI,OAAO,QAAQ,OAAO,SAAS,aACjC,MAAM,IAAI,mBAAmB,2CAA2C;IAC1E,UAAU,cAAc,mBAAmB,OAAO,QAAQ,CAAC;GAC7D;GACA,IAAI,OAAO,IAAI,IAAI,GACjB,OAAO;IAAE,IAAI;IAAO,OAAO;GAA8B;GAC3D,MAAM,MAAM,gBAAgB,OAAO,SAAS,EAAE,OAAO,cAAc;IACjE,IAAI,YAAY,IAAI,GAClB,KAAK,KAAK;KAAE,MAAM;KAAsB;KAAO;IAAQ,CAAC;GAC5D,CAAC;GACD,OAAO,IAAI,MAAM,GAAG;GACpB,IAAI;IACF,OAAO,MAAM,IAAI;GACnB,UACQ;IACN,OAAO,OAAO,IAAI;GACpB;EACF;EACA,oBAAoB,IAAI,SAAS;GAC/B,OAAO,IAAI,IAAI,CAAC,EAAE,OAAO;EAC3B;EACA,cAAc,GAAG,SAAS;GACxB,OAAO,EAAE,GAAG;GACZ,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI;EAC/B;EACA,gBAAgB,GAAG,SAAS;GAC1B,KAAK,QAAQ,MAAM,eAAe,EAAE,KAAK,KAAK,CAAC;EACjD;CACF;AACF;;;AC3IA,MAAM,+BAA+B;AACrC,MAAM,uBAAuB;AAuB7B,SAAgB,sBAAsB,EAAE,MAAM,OAAO,SAAS,WAAW,8BAA8B,SAAS,wBAO5F;;CAElB,MAAM,oCAAoB,IAAI,QAA0B;;CAExD,MAAM,mCAAmB,IAAI,IAAsD;CACnF,IAAI,cAAc;CAClB,IAAI;;CAEJ,MAAM,2BAAW,IAAI,IAAuC;CAE5D,SAAS,OAAO,WAAyB;EACvC,KAAK,MAAM,SAAS,SAAS,IAAI,SAAS,KAAK,CAAC,GAC9C,MAAM,UAAU;EAClB,MAAM,SAAS,iBAAiB,IAAI,SAAS;EAC7C,IAAI,CAAC,QACH;EACF,eAAe,OAAO,MAAM;EAC5B,iBAAiB,OAAO,SAAS;CACnC;CAEA,SAAS,QAAc;EACrB,aAAa,SAAS;EACtB,YAAY,KAAA;EACZ,KAAK,MAAM,UAAU,SAAS,OAAO,GACnC,KAAK,MAAM,SAAS,QAClB,MAAM,UAAU;EAEpB,iBAAiB,MAAM;EACvB,cAAc;CAChB;;CAGA,SAAS,QAAc;EACrB,aAAa,SAAS;EACtB,YAAY,WAAW,OAAO,MAAM;EACpC,UAAU,QAAQ;CACpB;CAEA,UAAU,KAAK;CAEf,SAAS,KAAK,WAAmB,KAAa,OAA+B;EAC3E,OAAO,SAAS;EAEhB,IAAI,MAAM,QAAQ,UAChB;EACF,iBAAiB,IAAI,WAAW;GAAE;GAAK;EAAM,CAAC;EAC9C,eAAe,MAAM;EACrB,KAAK,MAAM,CAAC,IAAI,WAAW,kBAAkB;GAC3C,IAAI,eAAe,YAAY,OAAO,WACpC;GACF,iBAAiB,OAAO,EAAE;GAC1B,eAAe,OAAO,MAAM;EAC9B;CACF;CAEA,eAAe,cAAc,WAAkD;EAC7E,MAAM;EACN,MAAM,YAAY,KAAK,aAAa,SAAS;EAC7C,IAAI;EACJ,IAAI;EACJ,IAAI,WAAW;GAOb,QAAQ,CAAC,GAAG,SAAS;GACrB,MAAM,QAAQ,MAAM,OAAO,GAAG,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM;EACpD,OACK;GACH,MAAM,OAAO,MAAM,MAAM,KAAK,SAAS;GACvC,IAAI,CAAC,MACH,OAAO;GACT,QAAQ,KAAK;GACb,MAAM,SAAS,KAAK,UAAU,GAAG,KAAK,MAAM;EAC9C;EAEA,MAAM,SAAS,iBAAiB,IAAI,SAAS;EAC7C,IAAI,QAAQ,QAAQ,KAAK;GAEvB,iBAAiB,OAAO,SAAS;GACjC,iBAAiB,IAAI,WAAW,MAAM;GACtC,OAAO;IAAE,OAAO,OAAO;IAAO;GAAM;EACtC;EAEA,MAAM,QAAQ,EAAE,SAAS,MAAM;EAC/B,MAAM,SAAS,SAAS,IAAI,SAAS,qBAAK,IAAI,IAAI;EAClD,SAAS,IAAI,WAAW,OAAO,IAAI,KAAK,CAAC;EACzC,IAAI;GACF,MAAM,QAAQ,MAAM,2BAA2B,KAAK;GACpD,IAAI,CAAC,MAAM,SACT,KAAK,WAAW,KAAK,KAAK;GAC5B,OAAO;IAAE;IAAO;GAAM;EACxB,UACQ;GACN,OAAO,OAAO,KAAK;GACnB,IAAI,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,MAAM,QACnD,SAAS,OAAO,SAAS;EAC7B;CACF;CAkEA,OAAO;EACL,SAAA;GAhEA,yBAAyB,OAAO,MAAM;IACpC,MAAM,SAAS,MAAM,cAAc,EAAE,SAAS;IAC9C,IAAI,CAAC,QACH,OAAO,CAAC;IACV,MAAM,EAAE,OAAO,UAAU;IAGzB,MAAM,QAAQ,OAAO,UAAU,EAAE,KAAK,KAAM,EAAE,QAAmB,IAC7D,KAAK,IAAI,EAAE,OAAiB,MAAM,MAAM,MAAM,IAC9C,MAAM,MAAM;IAChB,IAAI,UAAU,MAAM,4BAA4B,OAAO,OAAO,EAAE,OAAO,KAAK;IAC5E,IAAI,CAAC,SAAS;KAEZ,OAAO,EAAE,SAAS;KAClB,UAAU,MAAM,wBAAwB,MAAM,6BAA6B,KAAK,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC;IACvG;IAGA,MAAM,QAAQ,IAAI,IAAI,MAAM,KAAK,MAAM,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IAC1D,QAAQ,MAAM,GAAG,OAAO,MAAM,IAAI,EAAE,KAAK,EAAE,KAAK,MAAM,MAAM,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;IAChF,OAAO;GACT;GACA,qBAAqB,OAAO,GAAG,SAAS;IAStC,MAAM,cAAc,kBAAkB,IAAI,IAAI,KAAK,KAAK;IACxD,kBAAkB,IAAI,MAAM,UAAU;IAEtC,MAAM,UAA+C,CAAC;IAItD,MAAM,MAAM,MAAM,QAAQ,EAAE,UAAU,IAAI,EAAE,WAAW,MAAM,GAAG,GAAG,IAAI,CAAC;IACxE,MAAM,eAAe,EAAE,gBAAgB;IACvC,KAAK,MAAM,aAAa,KAAK;KAC3B,IAAI,kBAAkB,IAAI,IAAI,MAAM,YAClC;KACF,IAAI;MACF,MAAM,SAAS,MAAM,cAAc,SAAS;MAC5C,IAAI,CAAC,QACH;MACF,IAAI,QAAQ,MAAM,mCAAmC,OAAO,OAAO,OAAO,OAAO,EAAE,OAAO,YAAY;MACtG,IAAI,UAAU,KAAA,GAAW;OACvB,OAAO,SAAS;OAChB,QAAQ,MAAM,+BAA+B,MAAM,6BAA6B,OAAO,KAAK,GAAG,EAAE,OAAO,YAAY;MACtH;MACA,IAAI,OACF,QAAQ,aAAa;KACzB,QACM,CAEN;IACF;IACA,OAAO;GACT;EAIM;EACN,QAAQ,QAAQ;GACd,MAAM,YAAY,iBAAiB,MAAM;GACzC,IAAI,cAAc,KAAA,GAChB,OAAO,SAAS;EACpB;EACA;EACA,cAAc;GAAE,UAAU,iBAAiB,OAAO,SAAS;GAAM,OAAO;EAAY;EACpF,OAAO;CACT;AACF;;;;ACpNA,MAAM,mBAAmB;;;;;;AAOzB,eAAe,iBAAiB,OAAqB,WAAqC;CACxF,IAAI,CAAC,MAAM,SACT,OAAO;CACT,MAAM,OAAO,MAAM,MAAM,QAAQ,SAAS;CAC1C,IAAI,CAAC,MACH,OAAO;CAET,MAAM,OAAO,MAAM,MAAM,SAAS,WAAW,KAAK,IAAI,IAAI,KAAK,aAAa,KAAK,gBAAgB,CAAC;CAClG,OAAO,6BAA6B,IAAI,CAAC,CAAC,SAAS;AACrD;AAEA,SAAgB,mBAAmB,EAAE,MAAM,OAAO,eAAyG;CACzJ,OAAO;EACL,sBAAqB,MAAK,KAAK,aAAa,KAAK,GAAG,SAAS;EAC7D,yBAAwB,MAAK,KAAK,aAAa,QAAQ,EAAE,WAAW,EAAE,QAAQ;EAC9E,wBAAuB,MAAK,KAAK,aAAa,OAAO,EAAE,WAAW,EAAE,MAAM;EAE1E,0BAA0B,OAAO,MAAM;GACrC,MAAM,KAAK,cAAc,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GAC1E,OAAO,KAAK,aAAa,UAAU,EAAE,SAAS;EAChD;EAEA,kCAAkC,OAAO,MAAM;GAC7C,MAAM,MAA4B,CAAC;GACnC,KAAK,MAAM,aAAa,MAAM,QAAQ,EAAE,UAAU,IAAI,EAAE,aAAa,CAAC,GAAG;IACvE,IAAI,OAAO,cAAc,YAAY,KAAK,iBAAiB,SAAS,GAClE;IACF,MAAM,KAAK,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;IAC7D,IAAI,MAAM,iBAAiB,OAAO,SAAS,CAAC,CAAC,YAAY,KAAK,GAC5D,IAAI,KAAK,GAAG,MAAM,KAAK,aAAa,UAAU,SAAS,CAAC;GAC5D;GACA,OAAO;EACT;EAEA,sBAAsB,MAAM;GAC1B,KAAK,UAAU,QAAQ,EAAE,WAAW,EAAE,QAAQ;EAChD;EACA,sBAAqB,MAAK,KAAK,UAAU,QAAQ,GAAG,SAAS;EAC7D,+BAA+B,KAAK,UAAU,YAAY;EAE1D,wBAAwB,EAAE,UAAU,cAAc,YAAY,CAAC,EAAE;EACjE,oBAAmB,OAAM,EAAE,SAAS,mBAAmB,YAAY,GAAG,eAAe,EAAE,SAAS,SAAS,GAAG,eAAe,EAAE,OAAO,OAAO,CAAC,EAAE;CAChJ;AACF;;;;;;;;ACzDA,SAAgB,6BAA6B,EAAE,QAM7C;;;;;;CAMA,MAAM,wCAAwB,IAAI,IAAmD;;CAGrF,MAAM,wBAAwB,cAA4B;EACxD,MAAM,UAAU,sBAAsB,IAAI,SAAS;EACnD,MAAM,SAAS,UAAU,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,KAAA;EACxD,IAAI,CAAC,QACH,sBAAsB,OAAO,SAAS;EACxC,KAAK,mBAAmB,WAAW,UAAU,IAAI;CACnD;CAEA,OAAO;EACL,SAAS,EACP,gCAAgC,GAAG,SAAS;GAC1C,MAAM,EAAE,WAAW,GAAG,SAAS;GAC/B,MAAM,OAAO,yBAAyB,IAAI;GAC1C,MAAM,UAAU,sBAAsB,IAAI,SAAS,qBAAK,IAAI,IAAsC;GAElG,QAAQ,OAAO,IAAI;GACnB,IAAI,MACF,QAAQ,IAAI,MAAM,IAAI;GACxB,sBAAsB,IAAI,WAAW,OAAO;GAC5C,qBAAqB,SAAS;EAChC,EACF;EACA,YAAY,MAAM;GAChB,KAAK,MAAM,CAAC,WAAW,YAAY,uBACjC,IAAI,QAAQ,OAAO,IAAI,GACrB,qBAAqB,SAAS;EAEpC;EACA,OAAO,WAAW;GAChB,sBAAsB,OAAO,SAAS;EACxC;CACF;AACF;;;;;;;;;;AC3BA,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAO3B,IAAM,oBAAN,cAAgC,MAAM;CACpC,OAAwB,iBAAiB;AAC3C;;AAGA,IAAM,wBAAN,cAAoC,kBAAkB;CACpD,OAAiC,iBAAiB;AACpD;;AASA,MAAM,eAAe,SAA2B,KAAK,aAAa;AAElE,SAAgB,2BAA2B,OAOoG;CAC7I,MAAM,EAAE,SAAS;CACjB,MAAM,gBAAyB,MAAM,SAAS,QAAQ,MAAM;CAC5D,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,yBAAS,IAAI,IAAsB;CAEzC,MAAM,cAAwB;EAC5B,MAAM,EAAE,OAAO,MAAM,aAAa,KAAK;EACvC,IAAI,CAAC,YAAY,KAAK,WAAW,GAC/B,MAAM,IAAI,kBAAkB,2CAA2C;EACzE,OAAO,CAAC,GAAG,IAAI;CACjB;;CAGA,MAAM,YAAY,cAA4B;EAC5C,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,GAAG,WAAW,MAAM,cAAc,SAAS;EAC3E,IAAI,IAAI,SAAS,qBAAqB,OAAO,OAAO,oBAClD;EACF,MAAM,OAAO,IAAI,MAAM,GAAG,WAAW,MAAM,SAAS,IAAI;EACxD,IAAI,CAAC,MACH,MAAM,IAAI,sBAAsB,IAAI,UAAU,oBAAoB,0BAA0B,kBAAkB,yBAAyB,uCAAuC,mBAAmB,QAAQ;EAC3M,OAAO,OAAO,KAAK,EAAE;EACrB,KAAU,EAAE,CAAC,SAAS,MAAM;CAC9B;CAEA,eAAe,YAAY,QAAgB,MAA0C;EACnF,MAAM,YAAY,YAAY,IAAI;EAClC,MAAM,MAAM,GAAG,UAAU,GAAG;EAC5B,MAAM,WAAW,OAAO,IAAI,GAAG;EAC/B,IAAI,UAAU;GACZ,MAAM,WAAW,SAAS;GAC1B,IAAI,YAAY,aAAa,MAC3B,OAAO,OAAO,QAAQ;GACxB,SAAS,OAAO;GAChB,OAAO,SAAS;EAClB;EACA,SAAS,SAAS;EAClB,MAAM,EAAE,0BAA0B,MAAM,OAAO;EAC/C,MAAM,QAAgB;GAAE;GAAM;GAAW,UAAU,KAAA;EAAwC;EAC3F,MAAM,WAAW,sBAAsB;GACrC,OAAO,MAAM,CAAC,CAAC,KAAI,UAAS,EAAE,KAAK,EAAE;GACrC,SAAS,KAAK,MAAM,QAAQ,GAAG,cAAc;GAE7C,SAAS,MAAM,SAAS;GACxB,oBAAoB,MAAM,QAAQ;GAClC,SAAS,QAAQ,WAAW;IAC1B,MAAM,SAAS,MAAM;IACrB,IAAI,CAAC,UAAU,CAAC,MAAM,YAAY,MAAM,GACtC,OAAO;IACT,OAAO,KAAK;KAAE,MAAM;KAAwB;KAAgB;IAAoB,CAAC;IACjF,OAAO;GACT;EACF,CAAC;EACD,OAAO,IAAI,KAAK,KAAK;EACrB,OAAO,MAAM;CACf;CAEA,MAAM,cAAc,SAA2B;EAC7C,MAAM,MAAM,OAAO,IAAI,IAAI;EAC3B,MAAM,QAAQ,MAAM,OAAO,IAAI,GAAG,IAAI,KAAA;EACtC,IAAI,CAAC,SAAS,MAAM,SAAS,MAC3B,MAAM,IAAI,kBAAkB,+CAA+C;EAC7E,OAAO;CACT;CAEA,OAAO;EACL;EACA,SAAS;GACP,kBAAkB,OAAO,GAAG,SAAS;IACnC,IAAI,CAAC,QAAQ,GACX,MAAM,IAAI,kBAAkB,wEAAwE;IACtG,IAAI,OAAO,EAAE,WAAW,YAAY,CAAC,gBAAgB,KAAK,EAAE,MAAM,GAChE,MAAM,IAAI,kBAAkB,6EAAuE;IACrG,MAAM,WAAW,MAAM,YAAY,EAAE,QAAQ,IAAI;IACjD,OAAO,IAAI,MAAM,GAAG,YAAY,IAAI,EAAE,GAAG,EAAE,QAAQ;IACnD,SAAS,OAAO;IAChB,MAAM,EAAE,oBAAoB,MAAM,OAAO,yBAAyB,CAAA,MAAA,MAAA,EAAA,CAAA;IASlE,OAAO;KAPL,WAAW,gBAAgB,KAAK,MAAM,QAAQ,GAAG,cAAc,CAAC;KAChE,MAAM,cAAc,MAAM,QAAQ;KAClC,OAAO,MAAM,CAAC,CAAC,KAAI,UAAS,EAAE,KAAK,EAAE;KACrC,cAAc;MAAE,OAAO;MAAM,WAAW,OAAQ,WAAiC,QAAQ;MAAa,YAAY;MAAM,WAAW;MAAM,QAAQ;MAAM,WAAW,SAAS,QAAQ;KAAG;KACtL,SAAS;KACT,iBAAA;IAEU;GACd;GACA,gBAAgB,OAAO,GAAG,SAAS;IACjC,IAAI,CAAC,QAAQ,GACX,MAAM,IAAI,kBAAkB,wEAAwE;IACtG,IAAI,OAAO,EAAE,WAAW,UACtB,MAAM,IAAI,kBAAkB,4CAA0C;IACxE,OAAQ,MAAM,WAAW,IAAI,CAAC,CAAC,SAAS,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;GACzE;GACA,mBAAmB,IAAI,SAAS;IAC9B,MAAM,MAAM,OAAO,IAAI,IAAI;IAC3B,IAAI,CAAC,KACH,OAAO,EAAE,UAAU,MAAM;IAC3B,OAAO,OAAO,IAAI;IAClB,MAAM,QAAQ,OAAO,IAAI,GAAG;IAC5B,IAAI,OAAO,SAAS,MAAM;KACxB,MAAM,OAAO;KACb,MAAM,SAAS,SAAS;IAC1B;IACA,OAAO,EAAE,UAAU,KAAK;GAC1B;EACF;EACA,YAAY,MAAM;GAChB,MAAM,MAAM,OAAO,IAAI,IAAI;GAC3B,IAAI,CAAC,KACH;GACF,OAAO,OAAO,IAAI;GAClB,MAAM,QAAQ,OAAO,IAAI,GAAG;GAC5B,IAAI,OAAO,SAAS,MAAM;IACxB,MAAM,OAAO;IACb,MAAM,SAAS,SAAS;GAC1B;EACF;CACF;AACF;;;;ACxIA,MAAa,oBAAoB;;AAEjC,MAAM,qBAAqB;;AAE3B,MAAM,mBAAmB;AAuCzB,SAAS,YAAY,QAAkC;CACrD,IAAI;CACJ,MAAM,UAAgD,CAAC;CACvD,OAAO;EACL,MAAK,SAAQ,IAAI,SAAS,SAAS,WAAW;GAC5C,IAAI,OAAO,SACT,OAAO,uBAAO,IAAI,MAAM,4BAA4B,CAAC;GACvD,MAAM,OAAO;IAAE,GAAG;IAAM,IAAI,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW;GAAE;GACjE,UAAU;IAAE,MAAM;IAAM;GAAQ;GAChC,OAAO,iBAAiB,eAAe,uBAAO,IAAI,MAAM,4BAA4B,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;GACtG,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,GACnC,OAAO,IAAI;EACf,CAAC;EACD,eAAe,SAAS;EACxB,YAAa,UAAU,QAAQ,QAAQ,QAAQ,IAAI,IAAI,IAAI,SAAQ,YAAW,QAAQ,KAAK,OAAO,CAAC;EACnG,OAAO,QAAQ,OAAO;GACpB,MAAM,OAAO,SAAS;GACtB,IAAI,CAAC,QAAQ,KAAK,OAAO,QACvB,MAAM,IAAI,MAAM,kFAAkF;GACpG,IAAI,KAAK,SAAS,YAAY,UAAU,KAAA,KAAa,CAAC,KAAK,QAAQ,MAAK,WAAU,OAAO,OAAO,KAAK,GACnG,MAAM,IAAI,mBAAmB,IAAI,MAAM,6BAA6B;GACtE,IAAI,KAAK,SAAS,aAAa,UAAU,KAAA,KAAc,MAAM,KAAK,MAAM,MAAM,CAAC,KAAK,aAClF,MAAM,IAAI,mBAAmB,gCAAgC;GAC/D,MAAM,EAAE,YAAY;GACpB,UAAU,KAAA;GACV,QAAQ,KAAK;EACf;CACF;AACF;AAOA,SAAS,WAA2B;CAClC,IAAI;CAIJ,OAAO;EAAE,SAAA,IAHW,SAAY,MAAM;GACpC,UAAU;EACZ,CACe;EAAG;CAAQ;AAC5B;AAEA,MAAM,iCAAiB,IAAI,IAAI;CAAC;CAAa;CAAa;CAAS;AAAK,CAAC;;;;;;AAOzE,SAAS,YAAY,KAAc,gBAAyD;CAC1F,IAAI;CACJ,IAAI;EACF,MAAM,OAAO,QAAQ,WAAW,IAAI,IAAI,GAAG,IAAI,KAAA;CACjD,QACM,CAAC;CACP,MAAM,QAAQ,QAAQ,KAAA,KAAa,CAAC,IAAI,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI,UAAU,CAAC,IAAI;CACzF,IAAI,SAAS,mBAAmB,IAAK,aAAa,YAAY,IAAK,aAAa,YAAY,IAAK,aAAA,0BAC/F,OAAO;EAAE,KAAK,IAAK,SAAS;EAAG,MAAM;CAAK;CAC5C,IAAI,CAAC,SAAS,IAAK,aAAa,WAAW,CAAC,eAAe,IAAI,IAAK,QAAQ,KAAK,CAAC,IAAK,MACrF,MAAM,IAAI,mBAAmB,sFAAsF,iBAAiB,qBAAqB,+BAA+B,GAAG,EAAE;CAC/L,OAAO;EAAE,KAAK,IAAK,SAAS;EAAG,MAAM;CAAM;AAC7C;;AAGA,SAAS,QAAQ,OAAmC;CAClD,MAAM,QAAQ,MAAM,KAAK;CACzB,IAAI;EACF,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,aAAa,IAAI,OAAO,KAAK,KAAA;CACrD,QACM,CAAC;CACP,IAAI,MAAM,SAAS,GAAG,GACpB,OAAO,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC;CAC7B,IAAI,MAAM,SAAS,QAAQ,GACzB,OAAO,IAAI,gBAAgB,KAAK,CAAC,CAAC,IAAI,OAAO,KAAK,KAAA;AAEtD;;AAGA,SAAS,OAAO,OAAmC;CACjD,MAAM,QAAQ,MAAM,KAAK;CACzB,IAAI;EACF,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,aAAa,IAAI,MAAM,KAAK,KAAA;CACpD,QACM,CAAC;CACP,IAAI,MAAM,SAAS,GAAG,GACpB,OAAO,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC;CAC7B,IAAI,MAAM,SAAS,OAAO,GACxB,OAAO,IAAI,gBAAgB,KAAK,CAAC,CAAC,IAAI,MAAM,KAAK,KAAA;CACnD,OAAO,SAAS,KAAA;AAClB;AAEA,SAAS,cAAc,KAAmC;CACxD,IAAI,CAAC,KACH,OAAO;CACT,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,GAAG;EACvB,OAAO,IAAI,aAAa,WAAW,eAAe,IAAI,IAAI,QAAQ;CACpE,QACM;EACJ,OAAO;CACT;AACF;;AAGA,SAAS,YAAY,UAAoB,aAAyC;CAChF,IAAI,WAAW,UACb,OAAO,SAAS;CAClB,MAAM,QAAQ,IAAI,gBAAgB;EAAE,MAAM,SAAS;EAAM,GAAI,SAAS,UAAU,KAAA,IAAY,EAAE,OAAO,SAAS,MAAM,IAAI,CAAC;CAAG,CAAC,CAAC,CAAC,SAAS;CACxI,OAAO,cAAc,GAAG,YAAY,GAAG,UAAU;AACnD;;AAGA,eAAe,QAAW,SAAqB,OAAyB,QAAiC;CACvG,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK;GACxB;GACA,MAAM,WAAW;IACf,MAAM,IAAI,MAAM,mEAAmE;GACrF,CAAC;GACD,IAAI,SAAgB,GAAG,WAAW;IAChC,QAAQ,WAAW,QAAQ,kCAAkB,IAAI,MAAM,2DAA2D,mBAAmB,IAAK,GAAG,CAAC;IAC9I,OAAO,iBAAiB,eAAe,uBAAO,IAAI,MAAM,4BAA4B,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC;GACxG,CAAC;EACH,CAAC;CACH,UACQ;EACN,aAAa,KAAK;CACpB;AACF;;;;;;AAOA,SAAS,mBAAmB,MAAoB,UAAmB;CACjE,MAAM,aAAa,KAAK,aAAa,QAAQ;CAC7C,MAAM,iBAAiB,uBAAuB,UAAU;CACxD,IAAI,CAAC,WAAW,iBAAiB,CAAC,gBAChC,MAAM,IAAI,MAAM,2BAA2B,WAAW,MAAM,IAAI,WAAW,IAAI,2BAA2B;CAE5G,IAAI,CAAC,kBAAkB,WAAW,iBAAiB,CAAC,kBAAkB,WAAW,aAAa,GAC5F,MAAM,IAAI,MAAM,GAAG,WAAW,MAAM,6JAA6J;CACnM,MAAM,QAAQ,IAAI,gBAAgB;CAClC,MAAM,OAAO,SAAiB;CAC9B,MAAM,QAAQ,YAAY,MAAM,MAAM;CACtC,MAAM,MAAM,SAAmF;CAC/F,MAAM,SAAS,iBAAiB,uBAAuB,cAAA,CAAe,YAAY;EAChF,QAAQ,GAAG,iBAAiB,IAAI,QAAQ;GAAE,KAAK;GAAG,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;EAAG,CAAC;EAC7F,eAAc,SAAQ,IAAI,QAAQ;GAAE,KAAK,KAAK;GAAiB,UAAU,KAAK;GAAU,QAAQ;EAAK,CAAC;EAEtG,yBAAyB,KAAK;EAE9B,WAAU,WAAU,MAAM,IAAI;GAAE,MAAM;GAAU,SAAS,OAAO;GAAS,GAAI,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;GAAI,GAAI,OAAO,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;EAAG,CAAC,CAAC,CAAC,MAAK,UAAS,SAAS,EAAE;EAC5N,WAAU,WAAU,MAAM,IAAI;GAAE,MAAM;GAAU,SAAS,OAAO;GAAS,SAAS,OAAO,QAAQ,KAAI,YAAW;IAAE,IAAI,OAAO;IAAI,OAAO,OAAO;GAAM,EAAE;EAAE,CAAC;EAC1J,QAAQ,MAAM;EACd,gBAAgB;EAChB,aAAa;CACf,CAAC;CACD,MAAM,YAAY,KAAA,CAAS;CAE3B,IAAI;CACJ,MAAM,UAAU,IAAI,QAAQ,MAAM,UAAwD;EACxF,IAAI,CAAC,MAAM,QAAQ;GACjB,MAAM,WAAW,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,aAAa,IAAI,cAAc;GACnE,IAAI,cAAc,QAAQ,GACxB,cAAc;EAClB;EACA,OAAO;GACL,KAAK,MAAM;GACX,MAAM,MAAM,SAAS,WAAW,cAAc,aAAa;GAC3D,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;GACrC,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACrD,GAAI,MAAM,eAAe,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;EACnE;CACF,CAAC;CACD,QAAQ,YAAY,KAAA,CAAS;CAQ7B,OAAO;EAAE;EAAO;EAAO,QAPR,MAAM,MAAM,gBAAmC;GAE5D,IAAI,CAAC,gBACH,sBAAsB,KAAK,QAAQ,GAAG,YAAY;IAAE,MAAM;IAAS,GAAI;GAA0D,CAAC;GACpI,KAAK,QAAQ,UAAU;GACvB,OAAO,EAAE,UAAU,KAAK,SAAS,WAAW,GAAG,EAAE;EACnD,CAC4B;EAAG;EAAO;EAAS,UAAU,aAAuB,KAAK,QAAQ,YAAY,UAAU,WAAW,CAAC;CAAE;AACnI;;AAGA,SAAS,OAAO,OAAkC,QAAiB,MAAsB;CACvF,MAAM,OAAO,OAAO,WAAW,WAAW,MAAM,IAAI,MAAM,IAAI,KAAA;CAC9D,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,iFAAiF;CACnG,IAAI,KAAK,SAAS,MAChB,MAAM,IAAI,MAAM,6CAA6C;CAC/D,OAAO;AACT;;AAGA,SAAS,YAAY,MAAY,GAAyD,KAAiD;CACzI,MAAM,OAAO,OAAO,EAAE,SAAS,YAAY,EAAE,SAAS,KAAK,EAAE,OAAO,KAAA;CACpE,MAAM,QAAQ,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,KAAK,MAAM,KAAK,EAAE,QAAQ,KAAA;CAC/E,IAAI,SAAS,KAAA,KAAa,UAAU,KAAA,GAClC;CACF,IAAI,KAAK,WACP,MAAM,IAAI,MAAM,yCAAyC;CAC3D,MAAM,QAAQ,SAAS,KAAA,IAAa,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,KAAA,IAAa,QAAQ,KAAM;CAEvG,IAAI,KAAK,kBAAkB,KAAA,MAAc,UAAU,KAAA,KAAa,SAAS,KAAA,MAAc,UAAU,KAAK,eAAe;EACnH,IAAI,MAAM,uBAAuB;EACjC,MAAM,IAAI,MAAM,gEAAgE;CAClF;CACA,KAAK,YAAY;CACjB,KAAK,QAAQ,SAAS,KAAA,IAAY;EAAE;EAAM,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;CAAG,IAAI,EAAS,MAAO,CAAC;AAC3G;;AAGA,SAAS,gBAAgB,OAAkC,OAAwB,KAA+D;CAChJ,MAAM,QAAQ,MAAM,IAAI,OAAO;CAC/B,MAAM,OAAO,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,MAAK,MAAK,EAAE,QAAQ,EAAE,kBAAkB,KAAK,IAAI,KAAA;CAC1F,IAAI,CAAC,MAAM,QAAQ,KAAK,WACtB,OAAO,KAAA;CACT,MAAM,OAAO,MAAM,IAAI,MAAM;CAC7B,IAAI,CAAC,MAAM;EACT,IAAI,MAAM,MAAM,IAAI,mBAAmB,KAAK,MAAM,IAAI,OAAO,KAAK,0BAA0B;EAC5F,OAAO,KAAK;CACd;CACA,KAAK,YAAY;CACjB,KAAK,QAAQ;EAAE;EAAa;CAAO,CAAC;CACpC,OAAO,KAAK;AACd;AAEA,SAAgB,wBAAwB,EAAE,MAAM,KAAK,MAAM,WAAW,aAAa,iBAAiB,OAAO,QAAQ,qBAejH;CACA,MAAM,wBAAQ,IAAI,IAAkB;CAEpC,MAAM,OAAO,MAAY,WAAyB;EAChD,aAAa,KAAK,KAAK;EACvB,MAAM,OAAO,KAAK,EAAE;EACpB,IAAI,CAAC,KAAK,MAAM,OAAO,SACrB,KAAK,MAAM,MAAM,IAAI,MAAM,MAAM,CAAC;CACtC;;CAGA,SAAS,SAAS,MAAgB,OAAoN;EACpP,MAAM,KAAK,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;EAC/C,MAAM,OAAa;GACjB;GACA;GACA,WAAW,KAAK,IAAI,IAAI;GACxB,WAAW;GACX,GAAG;GACH,OAAO,KAAA;EACT;EACA,KAAK,QAAQ,WAAW,KAAK,OAAO,MAAM,sBAAsB;EAChE,KAAK,MAAM,QAAQ;EAEnB,KAAK,OAAO,YAAY,KAAA,CAAS;EACjC,MAAM,IAAI,IAAI,IAAI;EAClB,OAAO;CACT;CAEA,MAAM,YAAY,SAA2B,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,QAAO,SAAQ,KAAK,SAAS,IAAI;;CAElG,MAAM,8BAAc,IAAI,IAAsB;CAE9C,eAAe,cAAc,MAAgB,UAA4C;EACvF,MAAM,EAAE,OAAO,GAAG,UAAU,mBAAmB,MAAM,QAAQ;EAC7D,MAAM,OAAO,SAAS,MAAM,KAAK;EACjC,IAAI;GACF,OAAO,MAAM,QAAQ,MAAM,KAAK;EAClC,SACO,KAAK;GACV,IAAI,MAAM,4BAA4B;GACtC,MAAM;EACR;CACF;;CAGA,eAAe,QAAQ,MAAY,OAAkD;EACnF,MAAM,QAAQ,KAAK;EACnB,MAAM,OAAO,MAAM,QACjB,QAAQ,KAAK,CAAC,KAAK,QAAS,MAAK,WAAU,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,CAAC,MAAK,UAAS,EAAE,KAAK,EAAE,CAAC,CAAC,GAC9F,OACA,KAAK,MAAM,MACb;EACA,IAAI,UAAU,MACZ,OAAO;GAAE,QAAQ,KAAK;GAAI,KAAK;GAAI,MAAM;GAAQ,MAAM,KAAK;GAAM,WAAW,KAAK;EAAU;EAC9F,MAAM,QAAQ,KAAK;EACnB,KAAK,QAAQ;EACb,IAAI,MAAM,SAAS,UAAU;GAE3B,KAAK,gBAAgB,IADC,IAAI,MAAM,GACH,CAAC,CAAC,aAAa,IAAI,OAAO,KAAK,KAAA;GAC5D,IAAI,MAAM,aACR,KAAK,cAAc,MAAM;EAC7B;EACA,OAAO;GAAE,QAAQ,KAAK;GAAI,GAAG;GAAO,WAAW,KAAK;EAAU;CAChE;CAEA,eAAe,SAAS,MAAgB,GAAsG;EAC5I,MAAM,QAAQ,YAAY,EAAE,aAAa,cAAc;EACvD,MAAM,MAAM,cAAc;GAAE;GAAK;EAAK,GAAG,EAAE,KAAK,EAAE,IAAI;EACtD,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;EAC1C,MAAM,WAAW,IAAI,aAAa;EAClC,MAAM,EAAE,YAAY,oBAAoB;GAAE,KAAK;GAAK,QAAQ,OAAO;GAAQ,eAAe,SAAS,yBAAyB;GAAM,OAAO,SAAS,uBAAuB;EAAM,CAAC;EAChL,MAAM,QAAqC,QAAQ,MAAK,WAAU,OAAO,OAAO,SAAS,EAAE,SAAS,CAAC,EAAE;EACvG,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,kBAAkB,EAAE,UAAU,4BAA4B;EAI5E,MAAM,cAAc,qBAAqB,KAAK,KAAK,MAAM;EACzD,MAAM,OAAO,gBAAgB,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,KAAA;EACpE,MAAM,QAAQ,IAAI,gBAAgB;EAClC,MAAM,QAAQ,YAAY,EAAE,CAAC,CAAC,SAAS,WAAW;EAClD,MAAM,eAAe,SAA2C;EAChE,MAAM,UAAU,SAA0B;EAC1C,MAAM,QAAQ,eAAe,OAAO;GAClC,OAAO,IAAI,qBAAqB,KAAK,6BAA6B,IAAI,YAAY,CAAC;GACnF,QAAQ,MAAM;GACd;GACA,WAAW;GAEX,UAAU;IAAE;IAAa,SAAS,aAAa;IAAS,OAAO,YAAY,KAAA;GAAU;GACrF,qBAAoB,QAAO,QAAQ,QAAQ,EAAE,KAAK,IAAI,SAAS,EAAE,CAAC;EACpE,CAAC;EACD,MAAM,YAAY,KAAA,CAAS;EAC3B,MAAM,QAAQ,MAAM,QAAQ,QAAQ,SAAS,OAAO,MAAM,MAAM,CAAC,CAAC,OAAO,QAAQ;GAC/E,MAAM,MAAM;GACZ,MAAM;EACR,CAAC;EACD,MAAM,SAAS,MAAM,WAAW;GAC9B,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GACtE,OAAO,EAAE,WAAW,MAAM,KAAK;EACjC,CAAC;EACD,UAAe,UAAU,MAAM,MAAM,OAAO,MAAM,MAAM;EACxD,MAAM,OAAO,SAAS,MAAM;GAC1B;GACA;GACA,eAAe;GACf;GACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;GACvB,UAAU,aAAa;IACrB,IAAI,WAAW,UAAU;KACvB,MAAM,OAAO,OAAO,SAAS,KAAK;KAClC,MAAM,cAAc,QAAQ,SAAS,KAAK;KAC1C,IAAI,MACF,aAAa,QAAQ;MAAE;MAAM,GAAI,gBAAgB,KAAA,IAAY,EAAE,OAAO,YAAY,IAAI,CAAC;KAAG,CAAC;KAC7F;IACF;IACA,aAAa,QAAQ,QAAQ;GAC/B;EACF,CAAC;EACD,OAAO;GAAE,QAAQ,KAAK;GAAI,KAAK,MAAM;GAAK,GAAI,OAAO,EAAE,MAAM,UAAU,IAAI;IAAE,MAAM;IAAY;GAAY;GAAI,WAAW,KAAK;EAAU;CAC3I;CAEA,OAAO;EACL,SAAS;GACP,oBAAoB,OAAO,GAAG,SAAS;IACrC,MAAM,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,QAAO,UAAS,UAAU,KAAA,CAAS;IAC5E,IAAI,OAAO,WAAW,KAAK,OAAO,OAAO,OAAO,YAAY,OAAO,OAAO,IACxE,MAAM,IAAI,mBAAmB,sEAAkE;IACjG,IAAI,SAAS,IAAI,CAAC,CAAC,UAAU,YAAY,IAAI,IAAI,KAAK,MAAM,oBAC1D,MAAM,IAAI,MAAM,+BAA+B,mBAAmB,4CAA4C;IAChH,IAAI;IACJ,IAAI,EAAE,aAAa,KAAA,GACjB,QAAQ,MAAM,cAAc,MAAM,EAAE,QAAQ;SAEzC;KAEH,YAAY,IAAI,OAAO,YAAY,IAAI,IAAI,KAAK,KAAK,CAAC;KACtD,IAAI;MACF,QAAQ,MAAM,SAAS,MAAM;OAAE,WAAW,EAAE;OAAY,GAAI,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;OAAI,GAAI,EAAE,SAAS,KAAA,IAAY,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;OAAI,GAAI,EAAE,gBAAgB,KAAA,IAAY,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;MAAG,CAAC;KACrO,UACQ;MACN,MAAM,QAAQ,YAAY,IAAI,IAAI,KAAK,KAAK;MAC5C,IAAI,OAAO,GACT,YAAY,IAAI,MAAM,IAAI;WAE1B,YAAY,OAAO,IAAI;KAC3B;IACF;IAEA,IAAI,CAAC,YAAY,IAAI,GAAG;KACtB,MAAM,OAAO,MAAM,IAAI,MAAM,MAAM;KACnC,IAAI,MACF,IAAI,MAAM,wBAAwB;IACtC;IACA,OAAO;GACT;GAEA,uBAAuB,OAAO,GAAG,SAAS;IACxC,MAAM,OAAO,OAAO,OAAO,EAAE,QAAQ,IAAI;IACzC,YAAY,MAAM,GAAG,GAAG;IACxB,IAAI,SAAS;IACb,IAAI;KAEF,MAAM,UAAU,OAAO,KAAK,QACxB,QAAQ,KAAK,CAAC,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC,CAAC,MAAK,UAAS,EAAE,KAAK,EAAE,CAAC,CAAC,IACtE,KAAK;KACT,SAAS,QAAQ,SAAS,KAAA;KAC1B,OAAO;IACT,SACO,KAAK;KACV,MAAM,IAAI,MAAM,KAAK,MAAM,OAAO,WAAW,KAAK,MAAM,OAAO,kBAAkB,QAAQ,KAAK,MAAM,OAAO,OAAO,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;IAC9K,UACQ;KACN,IAAI,CAAC,QACH,IAAI,MAAM,uBAAuB;IACrC;GACF;GAEA,sBAAsB,OAAO,GAAG,SAAS;IACvC,MAAM,OAAO,OAAO,OAAO,EAAE,QAAQ,IAAI;IACzC,IAAI,CAAC,KAAK,SAAS,OAAO,EAAE,WAAW,UACrC,MAAM,IAAI,mBAAmB,iDAAgD;IAC/E,IAAI,EAAE,UAAU,KAAA,KAAa,OAAO,EAAE,UAAU,UAC9C,MAAM,IAAI,mBAAmB,6BAA2B;IAC1D,MAAM,YAAY,EAAE,UAAU,KAAA,KAAa,KAAK,MAAM,QAAQ,CAAC,EAAE,SAAS;IAC1E,KAAK,MAAM,OAAO,EAAE,QAAQ,EAAE,KAAK;IACnC,IAAI,WAAW;KACb,IAAI,MAAM,4BAA4B;KACtC,MAAM,IAAI,MAAM,6CAA6C;IAC/D;IAEA,OAAO,KAAK,QAAQ;KAAE,QAAQ,KAAK;KAAI,GAAG,KAAK;KAAO,WAAW,KAAK;IAAU,IAAI,QAAQ,MAAM,KAAK,MAAM;GAC/G;GAEA,sBAAsB,GAAG,SAAS;IAChC,MAAM,OAAO,OAAO,EAAE,WAAW,WAAW,MAAM,IAAI,EAAE,MAAM,IAAI,KAAA;IAClE,IAAI,CAAC,QAAQ,KAAK,SAAS,MACzB,OAAO,EAAE,WAAW,MAAM;IAC5B,IAAI,MAAM,4BAA4B;IACtC,OAAO,EAAE,WAAW,KAAK;GAC3B;EACF;EACA,YAAY,MAAM;GAChB,KAAK,MAAM,QAAQ,SAAS,IAAI,GAC9B,IAAI,MAAM,wBAAwB;EACtC;EACA,kBAAiB,UAAS,gBAAgB,OAAO,OAAO,GAAG;CAC7D;AACF;;;;ACxgBA,MAAM,oBAAoB;AAE1B,SAAgB,yBAAyB,EAAE,MAAM,KAAK,WAAW,YAMlC;CAC7B,MAAM,YAAY,QAAyB,cAAc;EAAE;EAAK;CAAK,GAAG,GAAG;;CAE3E,MAAM,aAAa,OAAO,YAAoB,MAAM,IAAI,cAAc,MAAM,EAAA,CAAG;CAC/E,MAAM,cAAc,YAA8B;EAChD,IAAI;GACF,QAAQ,MAAM,IAAI,MAAM,KAAK,EAAE,OAAO,EAAE,CAAC,EAAA,CAAG,SAAS;EACvD,QACM;GAEJ,OAAO;EACT;CACF;CAEA,OAAO;EACL,qBAAqB,OAAO,MAAM;GAChC,MAAM,MAAM,SAAS,EAAE,GAAG;GAC1B,OAAO,4BAA4B;IACjC,SAAS,IAAI,YAAY;IACzB,UAAU,MAAM,WAAW,GAAG;IAC9B,OAAO,IAAI,OAAO,WAAW,KAAK;IAClC,UAAU,MAAM,YAAY;IAE5B,iBAAiB;IACjB;GACF,CAAC;EACH;EACA,wBAAwB,OAAO,MAAM;GACnC,MAAM,WAAW,MAAM,WAAW,SAAS,EAAE,GAAG,CAAC;GACjD,OAAO,oBAAoB,UAAU,WAAW,IAAI,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,aAAa;IAC9F,MAAM,eAAe,SAAS,SAAS,IAAI,EAAE;IAC7C,OAAO,eAAe;KAAE,GAAG;KAAU;IAAa,IAAI;GACxD,CAAC;EACH;EACA,wBAAwB,MAAM;GAC5B,IAAI,CAAC,mBAAmB,GACtB,OAAO;IAAE,WAAW;IAAO,QAAQ;KAAE,SAAS;KAAG,KAAK;IAAE;GAAE;GAC5D,OAAO;IAAE,WAAW;IAAM,QAAQ,wBAAwB,EAAE,KAAK,SAAS,EAAE,GAAG,EAAE,CAAC;GAAE;EACtF;EACA,yBAAwB,MAAK,oBAAoB;GAAE,KAAK,SAAS,EAAE,GAAG;GAAG,QAAQ,IAAI,OAAO;EAAO,CAAC;EACpG,qBAAqB,GAAG,SAAS,eAAe,UAAU,MAAM,oBAAoB;GAAE,UAAU,EAAE,aAAa;GAAM,MAAM,EAAE,SAAS;GAAM,QAAQ,EAAE,WAAW;GAAM,UAAU,EAAE,aAAa;EAAK,GAAG,YAAY;GAClN,MAAM,WAAW,EAAE,aAAa;GAChC,MAAM,UAAU,MAAM,qBAAqB,IAAI,OAAO;IACpD,KAAK,SAAS,EAAE,GAAG;IACnB,QAAQ,IAAI,OAAO;IACnB,UAAU,EAAE,aAAa;IACzB,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,WAAW;IACrB;IACA,QAAQ,OAAO,EAAE,WAAW,YAAY,EAAE,SAAS;IACnD,aAAa,EAAE,gBAAgB;GACjC,CAAC;GAED,IAAI,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,QAC5C,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GACxE,IAAI,QAAQ,MACV,UAAU;IAAE,MAAM;IAAmB,SAAS;GAAO,CAAC;GACxD,IAAI,QAAQ,QACV,UAAU;IAAE,MAAM;IAAmB,SAAS;GAAS,CAAC;GAC1D,OAAO;EACT,CAAC;EAED,iBAAiB,OAAO,MAAM;GAC5B,IAAI,OAAO,EAAE,WAAW,YAAY,EAAE,OAAO,KAAK,MAAM,MAAM,EAAE,OAAO,SAAS,mBAC9E,MAAM,IAAI,mBAAmB,gDAAgD,kBAAkB,aAAa;GAC9G,MAAM,SAAS,MAAM,qBAAqB,EAAA,EAAI;GAC9C,OAAO,kBAAkB,EAAE,QAAQ,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;EAC3D;EAEA,qBAAqB,OAAO,MAAM;GAChC,IAAI,OAAO,EAAE,WAAW,YAAY,EAAE,OAAO,KAAK,MAAM,MAAM,EAAE,OAAO,SAAS,mBAC9E,MAAM,IAAI,mBAAmB,gDAAgD,kBAAkB,aAAa;GAC9G,MAAM,SAAS,MAAM,qBAAqB,EAAA,EAAI;GAC9C,OAAO,oBAAoB,EAAE,QAAQ;IAAE,KAAK,QAAQ;IAAG,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;GAAG,CAAC;EACtF;CACF;AACF;;;;ACjGA,SAAgB,WAAW,MAAwB;CACjD,OAAO;EAAE,MAAM;EAAU,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;EAAI,GAAI,KAAK,gBAAgB,EAAE,MAAM,KAAK,cAAc,IAAI,CAAC;CAAG;AACjJ;AAEA,SAAgB,4BAA4B,EAAE,QAA2D;CACvG,MAAM,IAAI,KAAK;CACf,OAAO;EACL,4BAA4B,EAAE,WAAW;EACzC,+BAA+B,QAAQ,SAAS;GAC9C,IAAI,OAAO,QAAQ,QAAQ,UACzB,MAAM,IAAI,mBAAmB,wCAAwC;GAEvE,MAAM,QAAQ,MAAM;GACpB,IAAI,SAAS,CAAC,YAAY,OAAO,SAAS,KAAK,MAAM,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,cAAc,GAChH,MAAM,IAAI,iBAAiB,8BAA8B,gCAAgC,KAAK;GAChG,OAAO,EAAE,OAAO,WAAW,IAAI,GAAG,MAAM;EAC1C;EACA,uBAAuB,GAAG,SAAS,EAAE,KAAK,WAAW,IAAI,GAAG,eAAe,GAAG,OAAO,OAAO,CAAC;EAC7F,uBAAuB,GAAG,SAAS,EAAE,KAAK,WAAW,IAAI,GAAG,YAAY,CAAC,CAAC;EAC1E,uBAAuB,GAAG,SAAS,EAAE,KAAK,WAAW,IAAI,GAAG,YAAY,CAAC,GAAG,eAAe,EAAE,QAAQ,QAAQ,CAAC;EAC9G,wBAAwB,GAAG,SAAS,EAAE,MAAM,WAAW,IAAI,GAAG,YAAY,CAAC,GAAG,eAAe,EAAE,SAAS,SAAS,CAAC;EAClH,yBAAyB,GAAG,SAAS,EAAE,OAAO,WAAW,IAAI,GAAG,YAAY,CAAC,CAAC;EAC9E,6BAA6B,GAAG,SAAS,EAAE,WAAW,WAAW,IAAI,GAAG,YAAY,CAAC,GAAG,eAAe,EAAE,OAAO,OAAO,CAAC;EACxH,uBAAuB,GAAG,SAAS,EAAE,KAAK,WAAW,IAAI,GAAG,YAAY,CAAC,GAAG,eAAe,EAAE,YAAY,YAAY,CAAC;EACtH,yBAAyB,GAAG,SAAS,EAAE,OAAO,WAAW,IAAI,GAAG;GAAE,GAAI,KAAK,CAAC;GAAI,GAAI,GAAG,UAAU,KAAA,IAAY,EAAE,OAAO,eAAe,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC;GAAI,GAAI,GAAG,UAAU,KAAA,IAAY,EAAE,OAAO,eAAe,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC;EAAG,CAAC;EAChP,0BAA0B,GAAG,SAAS,EAAE,QAAQ,WAAW,IAAI,GAAG,GAAG,SAAS;EAC9E,yBAAyB,GAAG,SAAS;GACnC,MAAM,WAAW,EAAE;GACnB,IAAI,CAAC,YAAY,OAAO,aAAa,YAAa,SAAS,SAAS,UAAU,SAAS,SAAS,YAC9F,MAAM,IAAI,mBAAmB,+CAA+C;GAC9E,OAAO,EAAE,OAAO,WAAW,IAAI,GAAG,eAAe,EAAE,WAAW,WAAW,GAAG,EAAE,QAAQ;EACxF;EACA,0BAA0B,GAAG,SAAS;GACpC,IAAI,EAAE,aAAa,KAAA,KAAa,EAAE,aAAa,MAC7C,MAAM,IAAI,mBAAmB,uBAAuB;GACtD,OAAO,EAAE,QAAQ,WAAW,IAAI,GAAG,eAAe,EAAE,WAAW,WAAW,GAAG,EAAE,QAAQ;EACzF;CACF;AACF;;;AC3BA,SAAgB,oBAAoB,EAAE,MAAM,KAAK,OAAO,WAK9B;CACxB,MAAM,YAAY,QAAyB,cAAc;EAAE;EAAK;CAAK,GAAG,eAAe,KAAK,KAAK,CAAC;CAClG,MAAM,aAAa,OAAO,YAAoB,MAAM,IAAI,cAAc,MAAM,EAAA,CAAG;CAC/E,MAAM,UAAU,OAAO,QAAgB,aAAsB,MAAM,WAAW,MAAM,EAAA,CAAG,OAAO,MAAK,MAAK,EAAE,OAAO,OAAO;CACxH,MAAM,OAAsB;EAC1B,GAAI,IAAI,cAAc,EAAE,aAAa,IAAI,YAAY,IAAI,CAAC;EAC1D,eAAe,OAAM,UAAU,MAAM,MAAM,gBAAgB,KAAK,KAAM,CAAC;EACvE,wBAAwB,IAAI,aAAa,CAAC,CAAC,cAAc;EACzD;CACF;CACA,MAAM,kBAAkB,QAAiB;EACvC,IAAI,CAAC,iBAAiB,GAAG,GACvB,MAAM,IAAI,mBAAmB,gCAAgC;EAC/D,OAAO;CACT;CAGA,MAAM,eAAe,oBAA8B;CACnD,MAAM,iBAAiB,oBAA8B;CACrD,SAAS,SAAS;EAChB,aAAa,QAAQ,IAAI;EACzB,eAAe,QAAQ,IAAI;CAC7B,CAAC;CACD,MAAM,YAAY,KAAa,YAA4B,GAAG,IAAI,QAAQ;CAE1E,OAAO;EACL,eAAe,OAAM,MAAK,gBAAgB,MAAM,WAAW,SAAS,EAAE,GAAG,CAAC,EAAA,CAAG,MAAM;EACnF,eAAe,OAAO,MAAM;GAC1B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,OAAO,mBAAmB,MAAM,QAAQ,QAAQ,EAAE,OAAO,GAAG,EAAE,KAAK,QAAQ,IAAI;EACjF;EACA,iBAAiB,OAAO,MAAM;GAC5B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,OAAO,wBAAwB,MAAM,QAAQ,QAAQ,EAAE,OAAO,GAAG,eAAe,EAAE,UAAU,UAAU,GAAG,EAAE,SAAS,EAAE,KAAK,QAAQ,IAAI;EACzI;EACA,iBAAiB,GAAG,SAAS;GAC3B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,MAAM,UAAU,eAAe,EAAE,SAAS,SAAS;GACnD,MAAM,MAAM,SAAS,EAAE,KAAK,OAAO;GACnC,OAAO,aAAa,MAAM,KAAK,MAAM,YAAY,wBAAwB,MAAM,QAAQ,QAAQ,OAAO,SAAS;IAC7G,KAAK,MAAM,WAAW,aAAa,OAAO,GAAG,GAC3C,QAAQ,KAAK;KAAE,MAAM;KAAiB,KAAK,EAAE;KAAK;IAAQ,CAAC;GAC/D,CAAC,CAAC;EACJ;EACA,mBAAmB,GAAG,SAAS;GAC7B,aAAa,QAAQ,SAAS,eAAe,EAAE,KAAK,KAAK,GAAG,eAAe,EAAE,SAAS,SAAS,CAAC,GAAG,IAAI;EACzG;EAEA,gBAAgB,OAAO,MAAM;GAC3B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,OAAO,2BAA2B,MAAM,WAAW,MAAM,EAAA,CAAG,SAAS,QAAQ,eAAe,EAAE,GAAG,CAAC;EACpG;EACA,eAAe,OAAO,MAAM;GAC1B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,OAAO,yBAAyB,MAAM,WAAW,MAAM,EAAA,CAAG,SAAS,eAAe,EAAE,QAAQ,QAAQ,GAAG,eAAe,EAAE,QAAQ,QAAQ,GAAG,QAAQ,eAAe,EAAE,GAAG,CAAC;EAC1K;EACA,kBAAkB,GAAG,SAAS;GAC5B,MAAM,SAAS,SAAS,EAAE,GAAG;GAC7B,OAAO,eAAe,MAAM,EAAE,KAAK,MAAM,YAAY,2BAA2B,MAAM,WAAW,MAAM,EAAA,CAAG,eAAe;IACvH,KAAK,MAAM,WAAW,eAAe,OAAO,EAAE,GAAG,GAC/C,QAAQ,KAAK;KAAE,MAAM;KAAmB,KAAK,EAAE;IAAI,CAAC;GACxD,CAAC,CAAC;EACJ;EACA,oBAAoB,GAAG,SAAS;GAC9B,eAAe,QAAQ,eAAe,EAAE,KAAK,KAAK,GAAG,IAAI;EAC3D;CACF;AACF;;;;AC/EA,MAAM,QAAkC;CAAE,UAAU;CAAU,UAAU;CAAU,cAAc;AAAO;;;;;;;;;;AAWvG,SAAgB,aAAa,EAAE,MAAM,MAAM,SAAuH;CAChK,IAAI,UAA2B;CAC/B,aAAa,YAAY,eAAe;EACtC,OAAO,MAAM;EACb,oBAAoB,KAAK,WAAW,UAAU;EAC9C,cAAc,OAAO,cAAc;GACjC,MAAM,SAAS,MAAM,MAAM,UAAU,SAAS,EAAA,EAAI,SAAS;GAC3D,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,QAAQ,KAAA;EAC7D;CACF,CAAC;AACH;AAEA,SAAgB,mBAAmB,EAAE,MAAM,aAAa,cAOsB;CAC5E,MAAM,WAAW,oBAA8B;CAC/C,aAAY,SAAQ,SAAS,QAAQ,IAAI,CAAC;CAC1C,iBAAiB,SAAS,MAAM,CAAC;CACjC,OAAO;EACL,eAAe,IAAI,SAAS,SAAS,MAAM,QAAQ,MAAM,YAAY,KAAK,CAAC,CAAC,OAAO,WAAW;GAC5F,KAAK,MAAM,WAAW,SAAS,OAAO,MAAM,GAC1C,QAAQ,KAAK;IAAE,MAAM;IAAe;GAAO,CAAC;EAChD,CAAC,CAAC;EACF,iBAAiB,IAAI,SAAS;GAC5B,SAAS,QAAQ,QAAQ,IAAI;EAC/B;EACA,uBAAuB,EAAE,SAAS,KAAK,CAAC,CAAC,QAAQ,EAAE;EACnD,gBAAgB,OAAO,MAAM;GAC3B,IAAI,CAAC,OAAO,UAAU,GAAG,GAAG,KAAK,EAAE,OAAO,GACxC,MAAM,IAAI,mBAAmB,6CAA2C;GAC1E,OAAO,EAAE,SAAS,MAAM,KAAK,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE;EAChD;CACF;AACF;;;;ACvBA,SAAgB,0BAA0B,MAAoB,KAAK,KAA0B;CAC3F,MAAM,0BAAU,IAAI,IAAwD;;CAG5E,SAAS,IAAI,OAAiB,OAAkC;EAC9D,MAAM,WAAW,QAAQ,IAAI,MAAM,IAAI,CAAC,EAAE;EAC1C,MAAM,OAAwB;GAC5B,MAAM,MAAM;GACZ,MAAM,MAAM;GACZ,OAAO,MAAM;GACb,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;GAC7D,OAAO,YAAY,SAAS,UAAU,MAAM,QAAQ,SAAS,QAAQ,IAAI;EAC3E;EACA,QAAQ,IAAI,MAAM,MAAM;GAAE;GAAO;EAAK,CAAC;EACvC,OAAO,CAAC,YAAY,SAAS,SAAS,KAAK,QAAQ,SAAS,UAAU,KAAK,SAAS,SAAS,WAAW,KAAK;CAC/G;CAEA,OAAO;EACL,SAAS,MAAM,OAAO;GACpB,MAAM,WAAW,QAAQ,IAAI,MAAM,IAAI;GACvC,IAAI,YAAY,SAAS,UAAU,MACjC,MAAM,IAAI,MAAM,gBAAgB,MAAM,KAAK,uCAAuC;GACpF,IAAI,CAAC,YAAY,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,QAAO,MAAK,EAAE,UAAU,IAAI,CAAC,CAAC,UAAA,IACnE,MAAM,IAAI,MAAM,uEAAiG;GACnH,OAAO,IAAI,MAAM,KAAK;EACxB;EACA,OAAO,MAAM,OAAO;GAClB,MAAM,WAAW,QAAQ,IAAI,MAAM,IAAI;GACvC,IAAI,CAAC,YAAY,SAAS,UAAU,MAClC,MAAM,IAAI,MAAM,gBAAgB,MAAM,KAAK,wCAAwC;GACrF,OAAO,IAAI,MAAM;IAAE,GAAG;IAAO,MAAM,SAAS,KAAK;GAAK,CAAC;EACzD;EACA,YAAY,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAI,WAAU,EAAE,GAAG,MAAM,KAAK,EAAE;EAClE,QAAQ,MAAM;GACZ,IAAI,UAAU;GACd,KAAK,MAAM,CAAC,MAAM,UAAU,SAC1B,IAAI,MAAM,UAAU,MAAM;IACxB,QAAQ,OAAO,IAAI;IACnB,UAAU;GACZ;GAEF,OAAO;EACT;CACF;AACF;;;;AC5EA,MAAM,kBAAkB;;AAExB,MAAM,oBAAoB;AAE1B,SAAS,cAAc,OAAgB,MAAc,KAAqB;CACxE,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,KACpE,MAAM,IAAI,mBAAmB,GAAG,KAAK,yCAAyC,IAAI,aAAa;CACjG,OAAO,UAAU,OAAO,IAAI;AAC9B;;AAGA,SAAS,UAAU,OAAe,MAAsB;CACtD,IAAI,qBAAqB,KAAK,GAC5B,MAAM,IAAI,mBAAmB,GAAG,KAAK,sCAAsC;CAC7E,OAAO;AACT;;AAGA,SAAS,QAAQ,MAAgB,MAAsB;CACrD,IAAI,KAAK,WAAA,UAA8B,KAAK,KAAK,SAAS,CAAC,YAAY,KAAK,OAAO,SAAS,GAC1F,MAAM,IAAI,iBAAiB,yBAAyB,cAAc,oBAAoB,KAAK,KAAK,KAAK;CACvG,OAAO;AACT;AAEA,SAAS,QAAQ,OAAkC;CACjD,IAAI,CAAC,mBAAmB,KAAK,GAC3B,MAAM,IAAI,mBAAmB,wBAAwB,mBAAmB,KAAK,IAAI,EAAE,EAAE;CACvF,OAAO;AACT;AAEA,SAAS,SAAS,OAAqC;CACrD,IAAI,UAAU,KAAA,GACZ,OAAO,CAAC;CACV,IAAI,OAAO,UAAU,YAAY,MAAM,SAAS,mBAC9C,MAAM,IAAI,mBAAmB,sCAAsC,kBAAkB,aAAa;CACpG,OAAO,EAAE,QAAQ,UAAU,OAAO,QAAQ,EAAE;AAC9C;AAEA,SAAgB,0BAA0B,EAAE,WAAW,SAAS,WAAW,0BAA0B,KAKjB;CAClF,MAAM,WAAW,cAA6B;EAC5C,IAAI,WACF,UAAU;GAAE,MAAM;GAAwB,cAAc,SAAS,KAAK;EAAE,CAAC;CAC7E;CACA,SAAQ,SAAQ,QAAQ,SAAS,QAAQ,IAAI,CAAC,CAAC;CAE/C,OAAO;EACL,0BAA0B,GAAG,SAAS;GACpC,QAAQ,SAAS,SAAS,MAAM;IAC9B,MAAM,cAAc,GAAG,MAAM,QAAQ,eAAe;IACpD,MAAM,QAAQ,MAAM,cAAc,GAAG,MAAM,QAAQ,eAAe,CAAC;IACnE,OAAO,QAAQ,GAAG,KAAK;IACvB,GAAG,SAAS,GAAG,MAAM;GACvB,CAAC,CAAC;EACJ;EACA,wBAAwB,GAAG,SAAS;GAClC,QAAQ,SAAS,OAAO,MAAM;IAC5B,MAAM,cAAc,GAAG,MAAM,QAAQ,eAAe;IACpD,OAAO,QAAQ,GAAG,KAAK;IACvB,GAAG,SAAS,GAAG,MAAM;GACvB,CAAC,CAAC;EACJ;EACA,2BAA2B,SAAS,KAAK;CAC3C;AACF;;;ACvEA,SAAgB,uBAAuB,EAAE,KAAK,SAG2E;CACvH,OAAO;EACL,GAAG,0BAA0B;GAAE,WAAW,MAAM;GAAW,SAAS,MAAM;EAAQ,CAAC;EACnF,uBAAuB,MAAM,gBAAgB;EAC7C,mBAAmB,GAAG,SAAS;GAC7B,KAAK,WAAW,EAAE;GAClB,MAAM,kBAAkB;GAMxB,IAAS,MAAM,KAAK,EAAE,SAAS,CAAC,CAAC,MAAM,SAAS;IAC9C,IAAI,CAAC,MACH;IACF,MAAM,OAAO,KAAK,YAAY,CAAC;IAC/B,MAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAO,KAAK,eAAe;IAC3E,OAAO,IAAI,cAAc,GAAG;GAC9B,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAC1B;CACF;AACF;;;ACtBA,SAAgB,oBAAoB,EAAE,MAAM,YAAY,OAAO,cAOoD;CACjH,MAAM,SAAS,wBAAwB,MAAM,UAAU;CACvD,OAAO;EACL,eAAc,MAAK,KAAK,UAAU,EAAE,SAAS;EAC7C,aAAa,OAAO,GAAG,SAAS;GAG9B,MAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,KAAS,IAAI;GACvE,MAAM,kBAAkB,MAAM,QAAQ,EAAE,eAAe,IACnD,EAAE,gBAAgB,QAAQ,SAAyB,OAAO,SAAS,QAAQ,IAC3E,KAAA;GACJ,MAAM,cAAc,MAAM,QAAQ,EAAE,WAAW,IAC3C,iBAAiB,EAAE,WAAW,IAC9B,KAAA;GACJ,MAAM,YAAY,OAAO,EAAE,cAAc,WAAW,EAAE,UAAU,MAAM,GAAG,GAAG,IAAI,KAAA;GAChF,MAAM,SAAS,aAAa,CAAC;GAC7B,MAAM,WAAW,EAAE,aAAa,WAAW,EAAE,aAAa,aAAa,EAAE,WAAW,KAAA;GACpF,MAAM,SAAS,MAAM,QAAQ,OAAO,aAAa,SAAS,OAAO,SAAS,EAAE,WAAW,MAAM,iBAAiB,aAAa,WAAW,QAAQ,QAAQ,CAAC;GAGvJ,IAAI,EAAE,cAAc,MAClB,WAAW,EAAE,WAAW,IAAI;GAC9B,OAAO;EACT;EACA,iBAAgB,MAAK,KAAK,YAAY,EAAE,WAAW,EAAE,EAAE;EACvD,iBAAgB,MAAK,KAAK,YACxB,EAAE,WACF,EAAE,IACF,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,KAAS,IAAI,IAC1D,mBAAmB,EAAE,WAAW,CAClC;EACA,sBAAqB,MAAK,KAAK,iBAAiB,EAAE,WAAW,EAAE,EAAE;EACjE,kBAAiB,MAAK,KAAK,aAAa,EAAE,WAAW,EAAE,EAAE;CAC3D;AACF;;;;;;AAOA,SAAS,mBAAmB,MAAgE;CAC1F,IAAI,CAAC,MAAM,QAAQ,IAAI,GACrB,OAAO,KAAA;CACT,MAAM,UAAU,iBAAiB,IAAI;CACrC,IAAI,QAAQ,WAAW,KAAK,QAC1B,MAAM,IAAI,mBAAmB,iEAAiE;CAChG,OAAO;AACT;;;AC/DA,SAAgB,qBAAqB,EAAE,OAAkF;CACvH,OAAO,EACL,oBAAoB,MAAM;EACxB,IAAI,EAAE,UAAU,IAAI,OAClB,OAAO;GAAE,IAAI;GAAO,QAAQ;EAAQ;EACtC,MAAM,UAAU,OAAO,EAAE,aAAa,WAAW,IAAI,OAAO,EAAE,WAAW,EAAE,QAAQ,IAAI;EACvF,OAAO,UAAU;GAAE,IAAI;GAAM;EAAQ,IAAI;GAAE,IAAI;GAAO,QAAQ;EAAM;CACtE,EACF;AACF;;;ACFA,MAAM,UAAU;;AAGhB,SAAS,UAAU,OAAyB;CAC1C,IAAI,iBAAiB,OACnB,OAAO,MAAM;CACf,IAAI;EACF,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,MAAM;CACnD,QACM;EACJ,OAAO,OAAO,KAAK;CACrB;AACF;;AAGA,SAAS,WAAW,QAA8B;CAChD,OAAO;EAAE,GAAG;EAAQ,OAAO,OAAO,YAAY,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC;CAAE;AAC7H;AAEA,SAAgB,kBAAkB,EAAE,MAAM,WAGgB;CACxD,MAAM,eAA+B;EACnC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,OAAO;EACzB,OAAO;CACT;CACA,MAAM,YAAY,oBAA8B;CAChD,SAAQ,SAAQ,UAAU,QAAQ,IAAI,CAAC;CACvC,OAAO;EACL,oBAAoB,EAAE,SAAS,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,UAAU,EAAE;EACrE,eAAe,IAAI,SAAS;GAC1B,MAAM,OAAO,OAAO;GACpB,OAAO,UAAU,MAAM,OAAO,MAAM,YAAY,KAAK,gBAAgB;IACnE,MAAM,OAAO,KAAK,WAAW,CAAC,CAAC,GAAG,EAAE;IACpC,IAAI,CAAC,MACH;IACF,MAAM,SAAS,WAAW,IAAI;IAC9B,KAAK,MAAM,YAAY,UAAU,OAAO,KAAK,GAC3C,SAAS,KAAK;KAAE,MAAM;KAAe;IAAO,CAAC;GACjD,CAAC,CAAC;EACJ;EACA,iBAAiB,IAAI,SAAS;GAC5B,UAAU,QAAQ,OAAO,IAAI;EAC/B;CACF;AACF;;;;ACnBA,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AAExB,MAAM,aAAa;AACnB,MAAM,YAAY;AAElB,SAAS,UAAU,QAAgB,MAAuB;CACxD,IAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,IAC9C,MAAM,IAAI,mBAAmB,GAAG,OAAO,qCAAqC;CAC9E,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG;AACjC;AAEA,SAAgB,qBAAqB,EAAE,QAAQ,QAAQ,MAAM,WAAW,SAAS,eASiO;CAChT,MAAM,gBAAqC;EACzC,MAAM,UAAU,SAAS;EACzB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,UAAU;EAC5B,OAAO;CACT;CACA,MAAM,cAAmC;EACvC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,SAAS;EAC3B,OAAO;CACT;CAEA,IAAI,QACF,QAAQ,OAAO,eAAe,UAAU,EAAE,MAAM,iBAAiB,CAAC,CAAC,CAAC;CACtE,OAAO;EAEL,8BAA8B,GAAG,SAAS,MAAM,CAAC,CAAC,mBAAmB,UAAU,6BAA6B,EAAE,IAAI,GAAG,KAAK,SAAS;EACnI,qBAAqB,MAAM,CAAC,CAAC,KAAK;EAClC,kBAAkB,GAAG,SAAS;GAC5B,MAAM,OAAO,UAAU,iBAAiB,EAAE,IAAI;GAC9C,IAAI,EAAE,UAAU,aAAa,CAAC,cAAc,EAAE,KAAK,GACjD,MAAM,IAAI,mBAAmB,mFAAyE;GACxG,OAAO,MAAM,CAAC,CAAC,OAAO,MAAM,EAAE,OAAO,KAAK,SAAS;EACrD;EACA,kBAAkB,GAAG,SAAS;GAC5B,IAAI,OAAO,EAAE,OAAO,YAAY,EAAE,OAAO,IACvC,MAAM,IAAI,mBAAmB,2CAAyC;GACxE,MAAM,UAAU,MAAM,CAAC,CAAC,OAAO,EAAE,IAAI,KAAK,SAAS;GACnD,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,6BAA6B,EAAE,GAAG,GAAG;GACvD,OAAO,EAAE,QAAQ;EACnB;EACA,sBAAsB,IAAI,SAAS;GACjC,IAAI,CAAC,KAAK,WACR,MAAM,IAAI,MAAM,yCAAyC;GAC3D,MAAM,UAAU,MAAM,CAAC,CAAC,OAAO,KAAK,WAAW,KAAK,SAAS;GAC7D,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,4CAA6C;GAC/D,OAAO,EAAE,QAAQ;EACnB;EACA,gBAAgB,GAAG,SAAS;GAC1B,IAAI,CAAC,cAAc,EAAE,KAAK,GACxB,MAAM,IAAI,mBAAmB,oEAA4D;GAC3F,IAAI,EAAE,UAAU,KAAA,MAAc,CAAC,OAAO,UAAU,EAAE,KAAK,KAAK,EAAE,QAAQ,mBAAmB,EAAE,QAAQ,kBACjG,MAAM,IAAI,mBAAmB,gDAAgD,gBAAgB,MAAM,gBAAgB,EAAE;GACvH,IAAI,EAAE,SAAS,KAAA,KAAa,OAAO,EAAE,SAAS,UAC5C,MAAM,IAAI,mBAAmB,yCAAuC;GACtE,OAAO,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,KAAK,KAAA,GAAW,KAAK,SAAS;EACnF;EACA,yBAAyB,GAAG,SAAS;GACnC,IAAI,EAAE,UAAU,KAAA,MAAc,CAAC,OAAO,UAAU,EAAE,KAAK,KAAK,EAAE,QAAQ,mBAAmB,EAAE,QAAQ,kBACjG,MAAM,IAAI,mBAAmB,yDAAyD,gBAAgB,MAAM,gBAAgB,EAAE;GAChI,MAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,KAAK,IAAI,EAAE;GAC5D,IAAI,SAAS,KAAA,MAAc,OAAO,SAAS,YAAa,SAAS,MAAM,CAAC,mBAAmB,IAAI,IAC7F,MAAM,IAAI,mBAAmB,+GAA6G;GAC5I,OAAO,MAAM,CAAC,CAAC,cAAc,EAAE,OAAO,QAAQ,KAAA,GAAW,KAAK,SAAS;EACzE;EACA,8BAA8B,QAAQ,CAAC,CAAC,OAAO;EAC/C,4BAA4B,MAAM;GAChC,IAAI,OAAO,GAAG,YAAY,WACxB,MAAM,IAAI,mBAAmB,6DAA2D;GAC1F,OAAO,QAAQ,CAAC,CAAC,UAAU,EAAE,OAAO;EACtC;EACA,6BAA6B,QAAQ,CAAC,CAAC,MAAM;EAC7C,+BAA+B,QAAQ,CAAC,CAAC,WAAW;EACpD,GAAG,kBAAkB;GAAE,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;GAAI,SAAS;EAAY,CAAC;CAC1E;AACF;;;AC3GA,SAAS,UAAU,OAAgB,MAAc,UAAkB,KAAqB;CACtF,OAAO,KAAK,IAAI,eAAe,OAAO,IAAI,KAAK,UAAU,GAAG;AAC9D;;;;;;AAOA,SAAS,SAAS,MAA4B;CAC5C,OAAO;EACL,IAAI,KAAK;EACT,GAAI,KAAK,YAAY,KAAA,IAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EAC9D,GAAI,KAAK,gBAAgB,KAAA,IAAY,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;EAC1E,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,WAAW,KAAK;EAChB,WAAW,KAAK;CAClB;AACF;AAEA,SAAgB,0BAA0B,EAAE,MAAM,OAAO,aAAuI;;CAE9L,MAAM,aAAa,OAAO,cAAmD;EAC3E,MAAM,OAAO,KAAK,eAAe,SAAS;EAC1C,IAAI,MACF,OAAO,KAAK,OAAO;EAGrB,MAAM,SAAS,MAAM,YAAY,OAAO,WAAW,EAAE,aAAa,MAAM,CAAC;EACzE,OAAO,SAAS,OAAO,OAAO,IAAI;CACpC;CACA,OAAO;EACL,sBAAsB,MAAM;GAC1B,MAAM,cAAc,GAAG;GACvB,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,QAAQ,OAAO,gBAAgB,UAC9E,MAAM,IAAI,mBAAmB,uCAAuC;GACtE,OAAO,gBAAgB,OAAO,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,KAAA,CAAS;EACvF;EACA,qBAAoB,MAAK,eAAe,OAAO,YAAY,CAAC,CAAC;EAC7D,mBAAmB,OAAO,MAAM;GAC9B,MAAM,YAAY,YAAY,CAAC;GAC/B,IAAI,EAAE,WAAW,cAAc,EAAE,WAAW,QAC1C,MAAM,IAAI,mBAAmB,0CAAsC;GACrE,MAAM,OAAO,MAAM,WAAW,SAAS;GACvC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,YAAY,UAAU,aAAa;GACrD,OAAO;IAAE,UAAU,eAAe,WAAW,EAAE,MAAM;IAAG,SAAS,cAAc,MAAM,EAAE,MAAM;GAAE;EACjG;EACA,gBAAgB,OAAO,MAAM;GAC3B,MAAM,YAAY,YAAY,CAAC;GAC/B,IAAI,EAAE,UAAU,OACd,OAAO,WAAW,SAAS;GAI7B,MAAM,WAAW,MAAM,UAAU,SAAS,OAAO,WAAW,KAAK,eAAe,SAAS,CAAC;GAC1F,OAAO,YAAY;IAAE,GAAG,SAAS;IAAM,OAAO,CAAC;IAAG,SAAS,SAAS;GAAQ;EAC9E;EACA,qBAAqB,OAAO,MAAM;GAEhC,MAAM,YAAY,YAAY,CAAC;GAC/B,MAAM,WAAW,MAAM,UAAU,SAAS,OAAO,WAAW,KAAK,eAAe,SAAS,CAAC;GAC1F,IAAI,CAAC,UACH,OAAO;GACT,MAAM,OAAO,UAAU,EAAE,MAAM,QAAQ,GAAG,OAAO,gBAAgB;GACjE,MAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,EAAE,OAAO,SAAA,KAA6B,sBAAsB,CAAC;GACjG,MAAM,EAAE,UAAU,SAAS;GAC3B,OAAO;IAAE,OAAO,MAAM,MAAM,MAAM,OAAO,KAAK;IAAG,OAAO,MAAM;IAAQ,SAAS,SAAS;GAAQ;EAClG;EACA,0BAA0B,OAAO,MAAM;GACrC,MAAM,YAAY,YAAY,CAAC;GAC/B,IAAI,OAAO,EAAE,WAAW,YAAY,EAAE,OAAO,WAAW,GACtD,MAAM,IAAI,mBAAmB,oCAAoC;GAEnE,MAAM,OAAO,KAAK,eAAe,SAAS;GAC1C,MAAM,QAAQ,OAAO,KAAK,SAAS,MAAM,UAAU,SAAS,OAAO,WAAW,IAAI,EAAA,EAAI,KAAK;GAC3F,IAAI,CAAC,OACH,OAAO;GACT,MAAM,YAAY,SAA0C;IAC1D,KAAK,MAAM,SAAS,KAAK,SACvB,IAAI,MAAM,SAAS,iBAAiB,MAAM,WAAW,EAAE,QACrD,OAAO,eAAe,MAAM,MAAM;GAGxC;GAEA,IAAI,OAAO,EAAE,WAAW,UACtB,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,OAAO,KAAK,OAAO,EAAE,SAAS,SAAS,IAAI,IAAI,KAAA;IACrD,IAAI,SAAS,KAAA,GACX,OAAO;GACX;GAEF,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;IAC1C,MAAM,OAAO,SAAS,MAAM,EAAG;IAC/B,IAAI,SAAS,KAAA,GACX,OAAO;GACX;GACA,OAAO;EACT;EACA,wBAAwB,OAAO,MAAM;GACnC,MAAM,YAAY,YAAY,CAAC;GAC/B,MAAM,OAAO,KAAK,eAAe,SAAS;GAC1C,MAAM,SAAS,OAAO,eAAe,SAAS,IAAI,CAAC,IAAI,MAAM,iBAAiB,OAAO,SAAS;GAC9F,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,YAAY,UAAU,aAAa;GACrD,OAAO,oBAAoB,OAAO,QAAQ;EAC5C;EACA,sBAAsB,OAAO,MAAM;GACjC,MAAM,YAAY,YAAY,CAAC;GAC/B,MAAM,OAAO,KAAK,eAAe,SAAS;GAC1C,IAAI,EAAE,UAAU,MACd,OAAO,OAAO,eAAe,SAAS,IAAI,CAAC,IAAI,iBAAiB,OAAO,SAAS;GAElF,MAAM,OAAO,OAAO,SAAS,IAAI,IAAI,MAAM,MAAM,KAAK,SAAS;GAC/D,IAAI,CAAC,MACH,OAAO;GACT,MAAM,SAAS,OAAO,eAAe,IAAI,IAAK,MAAM,iBAAiB,OAAO,SAAS,KAAM,eAAe;IAAE,GAAG;IAAM,IAAI;GAAU,CAAC;GAEpI,MAAM,MAAM,QAAQ,KAAK,iBAAiB,SAAS,IAAI,YAAY,IAAI,IAAI,KAAA;GAC3E,OAAO;IACL,GAAG;IACH,eAAe,yBAAyB,KAAK,OAAO,KAAK,IAAI;IAC7D,SAAS,YAAY,KAAK,IAAI;IAC9B,GAAI,MAAM;KAAE,cAAc,IAAI;KAAW,iBAAiB,IAAI;IAAa,IAAI,CAAC;GAClF;EACF;EACA,8BAA8B,OAAO,MAAM;GACzC,MAAM,YAAY,YAAY,CAAC;GAC/B,IAAI,OAAO,EAAE,cAAc,YAAY,OAAO,EAAE,QAAQ,UACtD,MAAM,IAAI,mBAAmB,oCAAoC;GAGnE,MAAM,UAAU,KAAK,eAAe,SAAS,KAAK,MAAM,YAAY,OAAO,WAAW,EAAE,aAAa,MAAM,CAAC;GAC5G,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,YAAY,UAAU,aAAa;GAErD,IAAI,EAAE,UAAU,KAAA,GACd,MAAM,4BAA4B,SAAS,EAAE,WAAW,EAAE,GAAG;QAE7D,MAAM,yBAAyB,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;EACvE;CACF;AACF;;;AC9JA,MAAM,YAAY,UAAoC,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;;;;;;;AAQzH,MAAM,iBAAiB;CAAC;CAAe;CAAoB;CAAiB;CAAkB;CAAwB;AAAoB;AAE1I,SAAgB,uBAAuB,EAAE,MAAM,KAAK,WAAW,WAM0B;CAOvF,IAAI,UAAU,IAAI,aAAa;;;;;;;CAQ/B,SAAS,MAAM,MAAoB;EACjC,MAAM,SAAS;EACf,UAAU;EACV,MAAM,WAAW,QACf,KAAK,UAAU,OAAO,IAAI,MAAM,KAAK,UAAU,KAAK,IAAI;EAO1D,IAAI,QAAQ,mBAAmB,KAAK,QAAQ,uBAAuB,GAAG;GACpE,MAAM,aAAa,IAAI,cAAc;GACrC,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,UAAU;EAC9E,OACK,IAAI,eAAe,KAAK,OAAO,GAElC,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAMxE,IAAI,QAAQ,iBAAiB,KAAK,KAAK,oBAAoB,QACzD,KAAK,aAAa,qBAAqB;EAGzC,KAAK,mBAAmB,QAAQ,IAAI;EAEpC,MAAM,OAAO,eAAe,IAAI;EAChC,UAAU;GAAE,MAAM;GAAoB,UAAU;EAAK,CAAC;EACtD,OAAO;CACT;CAGA,MAAM,eAAe,IAAI,sBAAsB;EAC7C,IAAI;GACF,MAAM,OAAO,IAAI,aAAa;GAC9B,IAAI,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,OAAO,GACjD,MAAM,IAAI;EACd,SACO,KAAK;GACV,QAAQ,MAAM,6DAA6D,GAAG;EAChF;CACF,CAAC;CACD,IAAI,cACF,UAAU,YAAY;CAExB,OAAO;EACL,wBAAwB;GAKtB,MAAM,aAAa,IAAI,cAAc;GACrC,KAAU,iBAAiB,CAAC,CAAC,KAAK,YAAY,UAAU;EAC1D;EAGA,sBAAsB,eAAe,IAAI,aAAa,CAAC;EACvD,iBAAiB,MAAM;GACrB,MAAM,QAAiB,GAAG;GAC1B,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GACpE,MAAM,IAAI,mBAAmB,sCAAsC;GACrE,OAAO,MAAM,IAAI,cAAc,EAAE,KAAK,CAAC;EACzC;EACA,wBAAwB,MAAM;GAC5B,MAAM,EAAE,KAAK,UAAU,GAAG,YAAY,CAAC;GACvC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAK,QAAO,OAAO,QAAQ,QAAQ,GACtF,MAAM,IAAI,mBAAmB,kFAAkF;GACjH,IAAI,CAAC,SAAS,EAAE,OAAO,GACrB,MAAM,IAAI,mBAAmB,4BAA4B;GAC3D,MAAM,OAAO,MAAM,IAAI,cAAc,KAAK,KAAK,CAAC;GAChD,MAAM,EAAE,eAAe,IAAI;GAC3B,MAAM,QAAQ,WAAW,KAAK;GAC9B,WAAW,KAAK;IAAE,GAAG;IAAO,YAAY,qBAAqB,MAAM,YAAY,EAAE,OAAO;GAAE,CAAC;GAC3F,OAAO;EACT;CACF;AACF;;;AC/GA,SAAgB,sBAAsB,EAAE,KAAK,mBAO3C;;;;;;;;;;;CAWA,MAAM,2BAAW,IAAI,IAAiE;CAuEtF,OAAO;EACL,SAAA,EArEA,mBAAmB,OAAO,GAAG,SAAS;GACpC,MAAM,YAAY,OAAO,EAAE,SAAS;GACpC,MAAM,MAAM,OAAO,EAAE,QAAQ,WAAW,EAAE,MAAM;GAEhD,MAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,KAAS,IAAI;GACvE,MAAM,QAAQ,OAAO,EAAE,UAAU,WAC7B,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,EAAE,KAAK,GAAG,KAAK,MAAM,CAAC,IACtD,KAAK;GAET,MAAM,OAAO,SAAS,IAAI,SAAS;GAInC,IAAI,QAAQ,MAAM,KAAK,KACrB,OAAO;IAAE,YAAY;IAAM;GAAI;GAEjC,MAAM,YAAY,MAAM;GAExB,MAAM,aAAa,IAAI,gBAAgB;GACvC,MAAM,QAAQ;IAAE;IAAiB;GAAqC;GACtE,SAAS,OAAO,SAAS;GACzB,SAAS,IAAI,WAAW,KAAK;GAC7B,IAAI,SAAS,OAAO,KAAK;IACvB,MAAM,CAAC,QAAQ,WAAW,SAAS,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;IACpD,QAAQ,YAAY,MAAM;IAC1B,SAAS,OAAO,MAAM;GACxB;GAEA,IAAI;IAIF,MAAM,OAAO,MAAM,YAAY,IAAI,OAAO,SAAS;IACnD,MAAM,OAAO,KAAK,YAAY,CAAC;IAC/B,MAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAO,KAAK,eAAe;IAC3E,MAAM,SAAS,MAAM,IAAI,cAAc,GAAG;IAK1C,MAAM,YAAY,CAChB,+BAA+B,EAAE,WAAW,IAAI,CAAC,GACjD,GAAG,OAAO,WAAW,2BACvB;IACA,MAAM,SAAS,MAAM,wBAAwB,WAAW;KAAE;KAAM,QAAQ;KAAO;KAAK,QAAQ,WAAW;IAAO,CAAC;IAE/G,IAAI,WAAW,OAAO,WAAW,SAAS,IAAI,SAAS,MAAM,OAC3D,OAAO;KAAE,YAAY;KAAM;IAAI;IAIjC,MAAM,aAAa,SAAS,CAAC,GAAG,OAAO,QAAQ,IAAI,CAAC;IACpD,MAAM,aAAa,WAAW,MAAM;IAIpC,gBAAgB,MAAM;KAAE,MAAM;KAAmB;KAAW;KAAK,OAAO;KAAM;KAAO;KAAY,GAAI,WAAW,SAAS,IAAI,EAAE,WAAW,IAAI,CAAC;IAAG,CAAC;IACnJ,OAAO;KAAE;KAAY;KAAK,GAAI,WAAW,SAAS,IAAI,EAAE,WAAW,IAAI,CAAC;IAAG;GAC7E,UACQ;IAGN,IAAI,SAAS,IAAI,SAAS,MAAM,OAC9B,MAAM,aAAa;GACvB;EACF,EAIM;EACN,SAAS,cAAc;GACrB,SAAS,IAAI,SAAS,CAAC,EAAE,YAAY,MAAM;GAC3C,SAAS,OAAO,SAAS;EAC3B;CACF;AACF;;;ACzDA,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAE5B,MAAM,iBAAiB;AAEvB,MAAM,kBAAkB;AAExB,MAAM,kBAAkB;AAExB,MAAM,kBAAkB;AAExB,MAAM,aAAa;AAEnB,MAAM,iBAAiB;AAEvB,MAAM,uBAAuB;AAE7B,MAAM,mBAAmB;AAEzB,MAAM,UAAU;AAEhB,MAAM,aAAa;;AAGnB,SAAS,kBAAkB,MAA8B;CACvD,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,WAAW,IAAI,KAAK,KAAK,SAAS,IAAI,GACnF,OAAO;CACT,MAAM,WAAW,KAAK,MAAM,GAAG;CAC/B,IAAI,SAAS,SAAS,kBAAkB,SAAS,MAAK,MAAK,MAAM,OAAO,MAAM,QAAQ,CAAC,WAAW,KAAK,CAAC,CAAC,GACvG,OAAO;CACT,OAAO,SAAS,KAAK,GAAG;AAC1B;;AAGA,SAAS,iBAAiB,SAA0B;CAClD,MAAM,cAAc,SAA0B;EAC5C,IAAI;GACF,WAAW,MAAM,UAAU,IAAI;GAC/B,OAAO,SAAS,IAAI,CAAC,CAAC,OAAO;EAC/B,QACM;GACJ,OAAO;EACT;CACF;CACA,IAAI,QAAQ,SAAS,GAAG,GACtB,OAAO,WAAW,OAAO,KAAK,WAAW,OAAO;CAClD,QAAQC,UAAQ,IAAI,QAAQ,GAAA,CAAI,MAAM,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,MAAK,QAAO,WAAW,KAAK,KAAK,OAAO,CAAC,CAAC;AAC7G;;AAGA,SAAS,QAAQ,KAA4B;CAC3C,IAAI;CACJ,IAAI;EACF,OAAO,UAAU,GAAG;CACtB,QACM;EACJ,OAAO;CACT;CACA,IAAI,CAAC,KAAK,YAAY,GACpB,OAAO,gBAAgB,KAAK;CAC9B,MAAM,OAAO,WAAW,QAAQ;CAChC,MAAM,QAAQ,IAAY,UAAwB;EAChD,IAAI,QAAQ,GACV;EACF,KAAK,MAAM,QAAQ,YAAY,EAAE,CAAC,CAAC,KAAK,GAAG;GACzC,MAAM,OAAO,KAAK,IAAI,IAAI;GAC1B,MAAM,MAAM,SAAS,KAAK,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;GACnD,MAAM,IAAI,UAAU,IAAI;GACxB,IAAI,EAAE,YAAY,GAChB,KAAK,MAAM,QAAQ,CAAC;QAEjB,IAAI,EAAE,OAAO,GAAG;IACnB,KAAK,OAAO,KAAK,IAAI,GAAG;IACxB,KAAK,OAAO,aAAa,IAAI,CAAC;IAC9B,KAAK,OAAO,IAAI;GAClB,OAEE,KAAK,OAAO,KAAK,IAAI,GAAG,EAAE,KAAK,GAAG;EAEtC;CACF;CACA,KAAK,KAAK,CAAC;CACX,OAAO,KAAK,OAAO,KAAK;AAC1B;;AAGA,SAAS,UAAU,OAA2D;CAC5E,MAAM,OAAO,WAAW,QAAQ;CAEhC,MAAM,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC;CACzE,KAAK,MAAM,QAAQ,QAAQ;EACzB,KAAK,OAAO,KAAK,KAAK,KAAK,GAAG;EAC9B,KAAK,OAAO,KAAK,KAAK;EACtB,KAAK,OAAO,IAAI;CAClB;CACA,OAAO,KAAK,OAAO,KAAK;AAC1B;;AAGA,SAAS,iBAAiB,GAAW,GAAmB;CACtD,MAAM,KAAK,EAAE,MAAM,GAAG;CACtB,MAAM,KAAK,EAAE,MAAM,GAAG;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,MAAM,GAAG,KAClD,IAAI,GAAG,OAAO,GAAG,IAEf,OAAO,GAAG,KAAM,GAAG,KAAM,KAAK;CAGlC,OAAO,GAAG,SAAS,GAAG;AACxB;AAEA,SAAS,eAAe,KAA+B;CAGrD,OAFa,iBAAiB;EAAE,SAAS;EAAU,KAAK,IAAI,KAAK;EAAG,MAAM,IAAI,KAAK;EAAG,QAAQ,IAAI,OAAO;CAAE,CAAC,CAAC,CAC1G,MAAK,MAAK,EAAE,WAAW,UAAU,EAAE,KAAK,SAAS,IAAI,IAAI,OAAO,CAAC,CAAC,QAAQ,OAAO,EAAE,GAAG,CAC/E,CAAC,CAAE;AACf;AACA,SAAS,aAAa,KAA+B;CACnD,OAAO,cAAc,QAAQ;EAAE,MAAM,IAAI,KAAK;EAAG,KAAK,IAAI,KAAK;EAAG,QAAQ,IAAI,OAAO;CAAE,CAAC;AAC1F;AACA,SAAS,kBAAkB,KAAuB,MAAwB;CACxE,OAAO,iBAAiB;EAAE,SAAS;EAAc,KAAK,IAAI,KAAK;EAAG,MAAM,IAAI,KAAK;EAAG,QAAQ,IAAI,OAAO;CAAE,CAAC,CAAC,CAAC,QAAO,MAAK,EAAE,WAAW,MAAM,CAAC,CAAC,KAAI,MAAK,KAAK,EAAE,MAAM,IAAI,CAAC;AAC1K;;AAGA,SAAS,SAAS,QAAoB,OAAe,aAA4B,QAAiC;CAChH,IAAI,OAAO,UAAU,QAAQ;EAC3B,OAAO,QAAQ,KAAK;GAAE;GAAO,QAAQ;EAAW,CAAC;EACjD,OAAO;CACT;CACA,MAAM,QAAQ,OAAO,OAAO;CAC5B,IAAI,OAAO,SAAS,KAAA,KAAa,MAAM,UAAU,eAAe,WAAW;EACzE,OAAO,UAAU,SAAS,EAAE,IAAI,KAAK,IAAI,EAAE;EAC3C,OAAO,QAAQ,KAAK;GAAE;GAAO,QAAQ;EAAW,CAAC;EACjD,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAS,KAAK,QAAoB,OAAe,UAAwB,QAA8D;CACrI,OAAO,OAAO,SAAS;EAAE;EAAU,UAAU,KAAK,IAAI;EAAG,GAAG;CAAO;AACrE;AAGA,SAAgB,aAAa,KAAuB,QAAoB,SAAmC,QAA8B;CACvI,IAAI,CAACC,WAAS,SAAS,MAAM,GAC3B,MAAM,IAAI,mBAAmB,6CAA6C;CAC5E,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC,SAAS,oBAC1C,MAAM,IAAI,mBAAmB,yBAAyB,mBAAmB,QAAQ;CACnF,MAAM,WAAW,IAAI,IAAI,aAAa;CACtC,MAAM,UAAU;CAChB,MAAM,QAAiC,CAAC;CACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,iBAAiB,QAAQ,QAAQ,SAAS,YAAY,CAAC,GAAG;EAClG,MAAM,QAAQ,aAAa,GAAG;EAC9B,IAAI,CAAC,OAAO,OAAO,kBAAkB,GAAG,GAAG;GACzC,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAgB,CAAC;GACtD;EACF;EACA,IAAI,CAAC,kBAAkB,GAAG,GAAG;GAC3B,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,oBAAoB,GAAG,IAAI,wBAAwB;GAAa,CAAC;GACtG;EACF;EACA,MAAM,cAAc,UAAU,QAAQ,IAAI;EAC1C,IAAI,CAAC,SAAS,QAAQ,OAAO,aAAa,MAAM,GAC9C;EACF,IAAI,UAAU,KAAK,MAAM,aAAa;GACpC,KAAK,QAAQ,OAAO,YAAY;IAAE,MAAM;IAAa,MAAM;GAAY,CAAC;GACxE,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,MAAM,OAAO;CACf;CACA,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GAChC;CACF,MAAM,OAAO,IAAI,QAAQ,YAAY,KAAK;CAC1C,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GAAG;EACpC,KAAK,QAAQ,aAAa,GAAG,GAAG,YAAY;GAAE,MAAM,UAAU,KAAK,IAAI;GAAG,MAAM,UAAU,MAAM,IAAI;EAAE,CAAC;EACvG,OAAO,QAAQ,KAAK,aAAa,GAAG,CAAC;CACvC;AACF;;AAIA,SAAS,YAAY,KAAuB,YAAmC;CAC7E,MAAM,SAAS,IAAI,IAAI,kBAAkB,CAAC,EAAA,CAAG,KAAK,SAAS;EACzD,IAAI;GACF,OAAO,aAAa,IAAI;EAC1B,QACM;GACJ,OAAO;EACT;CACF,CAAC,CAAC,CAAC,QAAQ,MAAmB,MAAM,IAAI;CACxC,MAAM,UAAU,SAA0B,MAAM,MAAK,SAAQ,SAAS,QAAQ,KAAK,WAAW,OAAO,GAAG,CAAC;CACzG,MAAM,SAAS,SAA0B,SAAS,MAAM,EAAE,gBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,MAAM;CACtG,IAAI,WAAW,UAAU,KAAK,MAAM,UAAU,GAAG;EAC/C,MAAM,OAAO,aAAa,UAAU;EACpC,IAAI,OAAO,IAAI,GACb,OAAO,mBAAmB,IAAI;CAClC;CACA,MAAM,OAAO,SAAS,UAAU;CAChC,IAAI,CAAC,QAAQ,SAAS,OAAO,SAAS,MACpC,OAAO;CACT,MAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,KAAI,SAAQ,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAI,SAAQ,aAAa,IAAI,CAAC,CAAC,CAAC;CAC5G,OAAO,MAAM,WAAW,IAAI,mBAAmB,MAAM,EAAG,IAAI;AAC9D;AAEA,SAAgB,cAAc,KAAuB,QAAoB,SAAoC,QAA8B;CACzI,IAAI,CAACA,WAAS,SAAS,QAAQ,GAC7B,MAAM,IAAI,mBAAmB,wDAAwD;CACvF,MAAM,UAAU,IAAI,IAAI,YAAY;CACpC,MAAM,OAAO,aAAa,OAAO;CACjC,IAAI,QAAQ;CACZ,KAAK,MAAM,CAAC,YAAY,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAG;EACpE,MAAM,QAAQ,YAAY;EAC1B,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,wBAAwB,CAAC,QAAQ,OAAM,MAAK,OAAO,MAAM,YAAY,EAAE,UAAU,gBAAgB,GAAG;GAClJ,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAkB,CAAC;GACxD;EACF;EACA,MAAM,SAAS,YAAY,KAAK,UAAU;EAC1C,IAAI,CAAC,QAAQ;GACX,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAiD,CAAC;GACvF;EACF;EAEA,MAAM,WAAW,OAAO,OAAO,MAAM,EAAE,WAAW,SAAU,OAAO,OAAO,MAAM,EAAE,WAAW,CAAC,IAAK,CAAC;EACpG,MAAM,UAAU,KAAK,OAAO,EAAE,YAAY,CAAC;EAC3C,MAAM,OAAO,QAAQ,QAAO,UAAS,CAAC,SAAS,SAAS,KAAK,KAAK,QAAQ,SAAS,KAAK,CAAC;EACzF,KAAK,MAAM,SAAS,SAClB,IAAI,CAAC,KAAK,SAAS,KAAK,GACtB,KAAK,KAAK,KAAK;EAEnB,KAAK,QAAQ,OAAO,aAAa;GAAE;GAAQ,SAAS,CAAC,GAAG,OAAO;EAAE,CAAC;EAClE,IAAI,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,OAAO,GAAG;GACpD,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,KAAK,UAAU;GAAE,GAAG,KAAK;GAAS,UAAU;EAAK;EACjD,QAAQ;EACR,OAAO,QAAQ,KAAK,KAAK;CAC3B;CACA,IAAI,OACF,cAAc,SAAS,IAAI;AAC/B;;AAIA,SAAS,WAAW,OAAgH;CAClI,MAAM,OAAOA,WAAS,KAAK,KAAK,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;CAC9E,MAAM,QAAQ,SAAS;CACvB,IAAI,CAAC,QAAQ,KAAK,IAAI,GACpB,OAAO;EAAE;EAAO,QAAQ;CAAyB;CACnD,MAAM,QAAQA,WAAS,KAAK,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,QAAsB;CAC1F,IAAI,CAAC,SAAS,MAAM,WAAW,KAAK,MAAM,SAAS,iBACjD,OAAO;EAAE;EAAO,QAAQ,cAAc,gBAAgB;CAAQ;CAChE,MAAM,MAAyC,CAAC;CAChD,IAAI,QAAQ;CACZ,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,OAAO,kBAAkBA,WAAS,IAAI,IAAI,KAAK,OAAO,KAAA,CAAS;EACrE,IAAI,CAAC,MACH,OAAO;GAAE;GAAO,QAAQ;EAA2C;EACrE,IAAI,OAAO,KAAK,SAAS,UACvB,OAAO;GAAE;GAAO,QAAQ,GAAG,KAAK;EAAW;EAC7C,MAAM,QAAQ,OAAO,KAAK,KAAK,MAAM,QAAQ;EAC7C,IAAI,MAAM,SAAS,gBACjB,OAAO;GAAE;GAAO,QAAQ,GAAG,KAAK,kBAAkB,eAAe;EAAQ;EAC3E,SAAS,MAAM;EACf,IAAI,IAAI,MAAK,MAAK,EAAE,SAAS,QAAQ,EAAE,KAAK,WAAW,GAAG,KAAK,EAAE,KAAK,KAAK,WAAW,GAAG,EAAE,KAAK,EAAE,CAAC,GACjG,OAAO;GAAE;GAAO,QAAQ,GAAG,KAAK;EAAgB;EAClD,IAAI,KAAK;GAAE;GAAM;EAAM,CAAC;CAC1B;CACA,IAAI,QAAQ,iBACV,OAAO;EAAE;EAAO,QAAQ,eAAe,gBAAgB;CAAQ;CACjE,OAAO;EAAE;EAAM,OAAO;CAAI;AAC5B;;AAGA,SAAS,cAAc,MAAc,MAAc,OAAyD;CAC1G,UAAU,MAAM,EAAE,WAAW,KAAK,CAAC;CACnC,MAAM,MAAM,KAAK,MAAM,IAAI;CAC3B,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,QAAQD,UAAQ,IAAI,GAAG,KAAK,IAAI,GAAG;CACrE,UAAU,KAAK;CACf,IAAI;EACF,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,SAAS,QAAQ,OAAO,KAAK,IAAI;GACvC,IAAI,CAAC,OAAO,WAAW,QAAQ,GAAG,GAChC,MAAM,IAAI,MAAM,GAAG,KAAK,KAAK,8BAA8B;GAC7D,UAAU,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;GAC9C,cAAc,QAAQ,KAAK,KAAK;EAClC;EACA,MAAM,SAAS,WAAW,GAAG,IAAI,GAAG,MAAM,QAAQ;EAClD,IAAI,QACF,WAAW,KAAK,MAAM;EACxB,WAAW,OAAO,GAAG;EACrB,IAAI,QACF,OAAO,QAAQ;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CACnD,UACQ;EACN,OAAO,OAAO;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CAChD;AACF;AAEA,SAAgB,UAAU,KAAuB,QAAoB,SAAgC,QAAiC;CACpI,IAAI,CAACC,WAAS,OAAO,KAAK,CAAC,MAAM,QAAQ,QAAQ,MAAM,KAAK,QAAQ,OAAO,SAAS,cAAe,QAAQ,aAAa,QAAQ,OAAO,QAAQ,aAAa,UAC1J,MAAM,IAAI,mBAAmB,oEAAoE;CACnG,IAAI,UAAU;CACd,IAAI,QAAQ;CAGZ,MAAM,SAAS,iBAAiB;EAAE,MAAM,IAAI,KAAK;EAAG,QAAQ,IAAI,OAAO;CAAE,CAAC;CAC1E,MAAM,YAAY,WAAW,MAAM,IAAI,aAAa,QAAQ,MAAM,IAAI;CACtE,MAAM,gBAAgB,cAAc,OAAO,OAAO,UAAU,SAAS;CACrE,IAAI,QAAQ,aAAa,QAAQ,OAAO,WAAW,QAAQ,QAAQ,IAAI,qBACrE,OAAO,QAAQ,KAAK;EAAE,OAAO;EAAiB,QAAQ,eAAe,oBAAoB;CAAQ,CAAC;MAE/F,IAAI,QAAQ,aAAa,QAAQ,OAAO,OAAA,cACvC;MAAA,SAAS,QAAA,aAAyB,eAAe,MAAM,GAAG;GAC5D,IAAI,QAAQ,aAAa,MAAM;IAE7B,OAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,OAAO,OAAO;IACrB,OAAO,QAAQ,KAAK,eAAe;IACnC,UAAU;GACZ,OACK,IAAI,UAAU,QAAQ,QAAQ,MAAM,eAAe;IACtD,KAAK,QAAQ,iBAAiB,SAAS,EAAE,MAAM,cAAc,CAAC;IAC9D,OAAO,UAAU,KAAK,eAAe;GACvC,OACK;IACH,SAAS,OAAO,WAAW,QAAQ,QAAQ;IAC3C,gBAAgB,QAAQ,QAAQ,UAAU,EAAE,WAAW,KAAK,CAAC;IAC7D,KAAK,QAAQ,iBAAiB,SAAS,EAAE,MAAM,UAAU,QAAQ,QAAQ,EAAE,CAAC;IAC5E,OAAO,QAAQ,KAAK,eAAe;IACnC,UAAU;GACZ;EACF;;CAIF,MAAM,OAAO,eAAe,GAAG;CAC/B,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,OAAO,QAAQ,QAAQ;EAChC,MAAM,QAAQ,WAAW,GAAG;EAC5B,IAAI,YAAY,OAAO;GACrB,OAAO,QAAQ,KAAK,KAAK;GACzB;EACF;EACA,MAAM,QAAQ,SAAS,MAAM;EAC7B,KAAK,IAAI,KAAK;EACd,MAAM,QAAQ,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,QAAQ,CAAC;EAChE,IAAI,QAAQ,QAAQ,iBAAiB;GACnC,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,YAAY,gBAAgB;GAAyB,CAAC;GAC3F;EACF;EACA,MAAM,MAAM,KAAK,MAAM,MAAM,IAAI;EACjC,IAAI,WAAW,GAAG,KAAK,UAAU,GAAG,CAAC,CAAC,eAAe,GAAG;GACtD,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAoC,CAAC;GAC1E;EACF;EACA,MAAM,cAAc,QAAQ,GAAG;EAC/B,IAAI,CAAC,SAAS,QAAQ,OAAO,aAAa,MAAM,GAC9C;EACF,MAAM,SAAS,UAAU,MAAM,KAAK;EACpC,IAAI,WAAW,aAAa;GAC1B,KAAK,QAAQ,OAAO,SAAS,EAAE,MAAM,OAAO,CAAC;GAC7C,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,SAAS;EACT,cAAc,MAAM,MAAM,MAAM,MAAM,KAAK;EAC3C,KAAK,QAAQ,OAAO,SAAS,EAAE,MAAM,QAAQ,GAAG,KAAK,OAAO,CAAC;EAC7D,OAAO,QAAQ,KAAK,KAAK;EACzB,UAAU;CACZ;CAEA,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,OAAO,MAAM,GAAG;EAC1D,IAAI,MAAM,aAAa,WAAW,CAAC,MAAM,WAAW,QAAQ,KAAK,KAAK,IAAI,KAAK,GAC7E;EACF,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,CAAe,CAAC;EACnD,IAAI,CAAC,SAAS,QAAQ,OAAO,QAAQ,GAAG,GAAG,MAAM,GAC/C;EACF,OAAO,KAAK;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EAC5C,OAAO,OAAO,OAAO;EACrB,OAAO,QAAQ,KAAK,KAAK;EACzB,UAAU;CACZ;CACA,OAAO;AACT;AAGA,SAAS,aAAa,KAA0C;CAC9D,MAAM,OAAO,aAAa,GAAG;CAC7B,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,CAAC;CACV,IAAI;EACF,OAAO,cAAc,aAAa,MAAM,MAAM,CAAC;CACjD,QACM;EACJ,OAAO,CAAC;CACV;AACF;AAEA,eAAsB,SAAS,KAAuB,QAAoB,SAA+B,MAAgB,QAAuC;CAC9J,IAAI,CAACA,WAAS,OAAO,KAAK,CAAC,MAAM,QAAQ,QAAQ,OAAO,GACtD,MAAM,IAAI,mBAAmB,uCAAuC;CACtE,MAAM,UAAU,SAAgC;EAC9C,MAAM,QAAQ,aAAa,GAAG,CAAC,CAAC,MAAK,MAAK,EAAE,SAAS,IAAI;EACzD,OAAO,QAAQ,UAAU,KAAK,IAAI;CACpC;CACA,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,UAAU,QAAQ,SAAS;EACpC,MAAM,OAAOA,WAAS,MAAM,KAAK,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;EACjF,MAAM,QAAQ,OAAO;EACrB,IAAI,CAAC,gBAAgB,IAAI,GAAG;GAC1B,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAA0B,CAAC;GAChE;EACF;EACA,KAAK,IAAI,KAAK;EACd,MAAM,cAAc,OAAO,IAAI;EAC/B,IAAI,CAAC,SAAS,QAAQ,OAAO,aAAa,MAAM,GAC9C;EACF,MAAM,SAAS,UAAU,MAAM;EAC/B,IAAI,OAAO,OAAO,MAAM,EAAE,SAAS,UAAU,gBAAgB,MAAM;GACjE,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,IAAI;GACF,MAAM,IAAI,QAAQ,UAAU,EAAU,OAAqC,GAAG,IAAI;EACpF,SACO,KAAK;GACV,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAC;GACvF;EACF;EACA,KAAK,QAAQ,OAAO,QAAQ;GAAE,MAAM,OAAO,IAAI,KAAK;GAAQ,MAAM;EAAO,CAAC;EAC1E,OAAO,QAAQ,KAAK,KAAK;EACzB,IAAI,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,MAAM,MAAM,CAAC,iBAAiB,OAAO,QAAQ,KAAK,CAAC,GAC/G,OAAO,SAAS,KAAK;GAAE;GAAO,SAAS,IAAI,OAAO,QAAQ;EAA+D,CAAC;CAC9H;CACA,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,OAAO,MAAM,GAAG;EAC1D,IAAI,MAAM,aAAa,UAAU,KAAK,IAAI,KAAK,GAC7C;EACF,MAAM,OAAO,MAAM,MAAM,CAAa;EACtC,IAAI,CAAC,SAAS,QAAQ,OAAO,OAAO,IAAI,GAAG,MAAM,GAC/C;EACF,IAAI;GACF,MAAM,IAAI,QAAQ,UAAU,EAAE,KAAK,GAAG,IAAI;EAC5C,SACO,KAAK;GACV,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAC;GACvF;EACF;EACA,OAAO,OAAO,OAAO;EACrB,OAAO,QAAQ,KAAK,KAAK;CAC3B;AACF;AAGA,eAAsB,eAAe,KAAuB,QAAoB,SAAqC,MAAgB,QAAuC;CAC1K,IAAI,CAACA,WAAS,OAAO,KAAK,CAAC,MAAM,QAAQ,QAAQ,UAAU,GACzD,MAAM,IAAI,mBAAmB,gDAAgD;CAC/E,KAAK,MAAM,SAAS,QAAQ,YAAY;EACtC,MAAM,OAAOA,WAAS,KAAK,KAAK,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;EAC9E,MAAM,QAAQ,aAAa;EAC3B,IAAI,CAAC,QAAQ,KAAK,IAAI,KAAK,OAAO,MAAM,SAAS,UAAU;GACzD,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAuC,CAAC;GAC7E;EACF;EACA,IAAI,OAAO,UAAU,QAAQ;GAC3B,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAW,CAAC;GACjD;EACF;EAEA,IAAI,kBAAkB,KAAK,IAAI,CAAC,CAAC,MAAK,QAAO,WAAW,GAAG,CAAC,GAAG;GAC7D,IAAI,CAAC,OAAO,OAAO,QACjB,KAAK,QAAQ,OAAO,cAAc,CAAC,CAAC;GACtC,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,IAAI;GACF,MAAM,IAAI,QAAQ,QAAQ;IAAE,MAAM;IAAa,MAAM,MAAM;IAAM,OAAO;IAAQ,GAAI,OAAO,MAAM,cAAc,WAAW,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;GAAG,GAAG,IAAI;EACxK,SACO,KAAK;GACV,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAC;GACvF;EACF;EACA,KAAK,QAAQ,OAAO,cAAc,CAAC,CAAC;EACpC,OAAO,QAAQ,KAAK,KAAK;CAC3B;AACF;;;;;;;;AAWA,SAAgB,iBAAiB,KAAuB,QAAoB,SAAuC,QAA8B;CAC/I,IAAI,CAACA,WAAS,OAAO,KAAK,CAAC,MAAM,QAAQ,QAAQ,KAAK,GACpD,MAAM,IAAI,mBAAmB,6CAA6C;CAC5E,MAAM,eAAe,SAAyB;EAC5C,MAAM,WAAW,wBAAwB,IAAI,IAAI,aAAa,CAAC;EAC/D,OAAO,UAAU;GAAE,QAAQ,SAAS,OAAO,SAAS,CAAC;GAAG,SAAS,SAAS,QAAQ,SAAS,IAAI;GAAG,UAAU,SAAS,SAAS,SAAS,IAAI;EAAE,CAAC;CAChJ;CACA,KAAK,MAAM,SAAS,QAAQ,OAAO;EACjC,MAAM,OAAOA,WAAS,KAAK,KAAK,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;EAC9E,MAAM,QAAQ,eAAe;EAC7B,IAAI,CAAC,2BAA2B,SAAS,IAAI,GAAG;GAC9C,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAsB,CAAC;GAC5D;EACF;EACA,IAAI,CAAC,SAAS,QAAQ,OAAO,YAAY,IAAI,GAAG,MAAM,GACpD;EACF,MAAM,SAAS,UAAU,KAAK;EAC9B,IAAI,OAAO,OAAO,MAAM,EAAE,SAAS,QAAQ;GACzC,OAAO,UAAU,KAAK,KAAK;GAC3B;EACF;EACA,MAAM,SAASA,WAAS,MAAM,MAAM,IAAI,MAAM,SAAS,CAAC;EACxD,MAAM,UAAUA,WAAS,MAAM,OAAO,IAAI,MAAM,UAAU,CAAC;EAC3D,IAAI;GACF,MAAM,QAAQ,+BAA+B,IAAI,cAAc,IAAI,IAAI,aAAa,GAAG;IACrF;IACA,GAAI,OAAO,MAAM,YAAY,YAAY,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;IACvE,QAAQ;KAAE,GAAG;KAAQ,GAAG;IAAQ;GAClC,CAAC;GACD,KAAK,MAAM,UAAU,MAAM,SACzB,IAAI,mBAAmB,IAAI,MAAM,OAAO,KAAK,OAAO,KAAK;GAC3D,IAAI,QAAQ,YAAY,MAAM,aAAa;EAC7C,SACO,KAAK;GACV,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAC;GACvF;EACF;EACA,KAAK,QAAQ,OAAO,gBAAgB;GAAE,MAAM,YAAY,IAAI;GAAG,MAAM;EAAO,CAAC;EAC7E,OAAO,QAAQ,KAAK,KAAK;CAC3B;AACF;AAEA,SAAgB,SAAS,KAAuB,QAAoB,SAA+B,QAA8B;CAC/H,IAAI,CAACA,WAAS,OAAO,KAAK,CAAC,MAAM,QAAQ,QAAQ,IAAI,GACnD,MAAM,IAAI,mBAAmB,oCAAoC;CACnE,KAAK,MAAM,SAAS,QAAQ,MAAM;EAChC,MAAM,WAAWA,WAAS,KAAK,KAAK,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAC1F,MAAM,QAAQ,OAAO;EACrB,IAAI,CAAC,OAAO,KAAK,SAAS,QAAQ,GAAG;GACnC,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAA4B,CAAC;GAClE;EACF;EACA,IAAI,OAAO,UAAU,QAAQ;GAC3B,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ;GAAW,CAAC;GACjD;EACF;EACA,IAAI;GACF,IAAI,OAAO,MAAM,QAAQ,YAAY,MAAM,IAAI,KAAK,MAAM,IACxD,MAAM,IAAI,MAAM,WAAW;GAC7B,IAAI,IAAI,KAAK,WAAW,IAAI,KAAK,aAAa,QAAQ,CAAC,CAAC,CAAC,SAAS,MAAM,IAAI,KAAK,CAAC,GAAG;IACnF,IAAI,CAAC,OAAO,OAAO,QACjB,KAAK,QAAQ,OAAO,QAAQ,CAAC,CAAC;IAChC,OAAO,UAAU,KAAK,KAAK;IAC3B;GACF;GACA,IAAI,QAAQ,UAAU;IAAE;IAAU,KAAK,MAAM;GAAI,CAAC;EACpD,SACO,KAAK;GACV,OAAO,QAAQ,KAAK;IAAE;IAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAAE,CAAC;GACvF;EACF;EACA,KAAK,QAAQ,OAAO,QAAQ,CAAC,CAAC;EAC9B,OAAO,QAAQ,KAAK,KAAK;CAC3B;AACF;;;ACvkBA,MAAa,YAAY;AAEzB,SAAgB,kBAA8B;CAC5C,OAAO;EAAE,SAAS;EAAG,QAAQ;EAAM,YAAY,CAAC;EAAG,MAAM,CAAC;EAAG,QAAQ,CAAC;EAAG,WAAW,CAAC;CAAE;AACzF;AAEA,MAAM,kBAAkB,aAAa,UAAU;AAC/C,MAAM,sBAAsB,aAAa,cAAc;;;;;;AAOvD,SAAS,qBAAqB,QAAgC;CAC5D,MAAM,GAAG,kBAAkB,UAAU,GAAG,cAAc,OAAO;CAC7D,MAAM,GAAG,kBAAkB,QAAQ,GAAG,WAAW,OAAO;CACxD,IAAI,YAAY,CAAC,UAAU,sBACzB,UAAU,uBAAuB;CACnC,OAAO;EAAE,GAAG;EAAQ;EAAQ;CAAU;AACxC;AAQA,SAAgB,gBAAgB,SAA4B;CAC1D,MAAM,OAAO,KAAK,SAAS,SAAS;CACpC,OAAO;EACL;EACA,YAAY;GACV,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,gBAAgB;GACzB,IAAI;IACF,MAAM,MAAe,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;IAC1D,IAAI,CAACC,WAAS,GAAG,GACf,OAAO,gBAAgB;IAIzB,OAAO,qBAAqB;KAC1B,SAAS;KACT,QALaA,WAAS,IAAI,MAAM,KAAK,OAAO,IAAI,OAAO,aAAa,YAAY,OAAO,IAAI,OAAO,eAAe,WAC/G,IAAI,SACJ;KAIF,YAAY,MAAM,QAAQ,IAAI,UAAU,IAAI,IAAI,WAAW,QAAQ,MAAyB,gBAAgB,SAAS,CAAiB,CAAC,IAAI,CAAC;KAC5I,MAAM,MAAM,QAAQ,IAAI,IAAI,IAAI,IAAI,KAAK,QAAQ,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;KAC9F,QAAQA,WAAS,IAAI,MAAM,IAAI,IAAI,SAA4C,CAAC;KAChF,WAAWA,WAAS,IAAI,SAAS,IAAI,IAAI,YAA8C,CAAC;KACxF,GAAI,OAAO,IAAI,eAAe,WAAW,EAAE,YAAY,IAAI,WAAW,IAAI,CAAC;IAC7E,CAAC;GACH,QACM;IAEJ,OAAO,gBAAgB;GACzB;EACF;EACA,QAAO,WAAU,oBAAoB,MAAM,QAAQ,UAAU;CAC/D;AACF;;AAGA,SAAgB,aAAa,QAAgC;CAC3D,OAAO;EACL,QAAQ,OAAO;EACf,YAAY,CAAC,GAAG,OAAO,UAAU;EACjC,MAAM,CAAC,GAAG,OAAO,IAAI;EACrB,QAAQ,OAAO,YAAY,OAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,OAAO;GAAE,UAAU,EAAE;GAAU,UAAU,EAAE;EAAS,CAAC,CAAC,CAAC;EACrI,WAAW,EAAE,GAAG,OAAO,UAAU;EACjC,GAAI,OAAO,eAAe,KAAA,IAAY,EAAE,YAAY,OAAO,WAAW,IAAI,CAAC;CAC7E;AACF;;;ACrDA,MAAM,mBAAmB;AAEzB,MAAM,eAAe;AAErB,SAAS,YAAY,GAAiD,UAA6D;CACjI,IAAI,OAAO,EAAE,aAAa,YAAY,EAAE,SAAS,KAAK,MAAM,MAAM,EAAE,SAAS,SAAS,kBACpF,MAAM,IAAI,mBAAmB,sCAAsC;CACrE,IAAI,aAAa,OAAO,EAAE,eAAe,YAAY,EAAE,WAAW,KAAK,MAAM,MAAM,EAAE,WAAW,SAAS,mBACvG,MAAM,IAAI,mBAAmB,wCAAwC;CACvE,OAAO;EAAE,UAAU,EAAE;EAAU,YAAY,OAAO,EAAE,eAAe,WAAW,EAAE,WAAW,KAAK,IAAI;CAAG;AACzG;AAEA,SAAS,gBAAgB,OAA4C;CACnE,IAAI,UAAU,KAAA,GACZ,OAAO,KAAA;CACT,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,OAAM,MAAK,gBAAgB,SAAS,CAAiB,CAAC,GACxF,MAAM,IAAI,mBAAmB,+BAA+B,gBAAgB,KAAK,IAAI,EAAE,EAAE;CAC3F,OAAO,gBAAgB,QAAO,MAAK,MAAM,SAAS,CAAC,CAAC;AACtD;AAEA,SAAgB,mBAAmB,EAAE,MAAM,KAAK,WAAW,SAAS,MAAM,WAOiB;CACzF,MAAM,QAAQ,gBAAgB,IAAI,YAAY,CAAC;CAC/C,MAAM,MAAwB;EAAE;EAAK;EAAS;EAAM,cAAc,KAAK;EAAc,oBAAoB,KAAK;EAAoB,YAAY,QAAQ;EAAG,cAAc,IAAI,OAAO;CAAO;;CAGzL,IAAI,QAA0B,QAAQ,QAAQ;CAC9C,MAAM,aAAgB,SAA2C;EAC/D,MAAM,OAAO,MAAM,KAAK,MAAM,IAAI;EAClC,QAAQ,KAAK,YAAY,KAAA,CAAS;EAClC,OAAO;CACT;CAEA,MAAM,gBAAsB,UAAU,EAAE,MAAM,eAAe,CAAC;CAC9D,MAAM,SAAS,MAAgB,UAAyC,SAAS,QAAQ,MAAM,KAAK;CAEpG,SAAS,iBAAuB;EAC9B,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,YAAY;CAChC;;CAGA,MAAM,iBAAiB,WAA6C;EAClE,IAAI,CAAC,WAAW,OAAO,WAAW,GAChC,OAAO,QAAQ,QAAQ;EACzB,OAAO,gBAAgB;GACrB,MAAM,SAAS,MAAM,KAAK;GAC1B,MAAM,SAAS,OAAO,QAAO,UAAS,OAAO,OAAO,UAAU,CAAC,OAAO,UAAU,MAAM;GACtF,IAAI,OAAO,WAAW,GACpB;GACF,MAAM,KAAK,KAAK,IAAI;GACpB,KAAK,MAAM,SAAS,QAClB,OAAO,UAAU,SAAS,EAAE,GAAG;GACjC,MAAM,MAAM,MAAM;GAClB,QAAQ;EACV,CAAC;CACH;;CAGA,MAAM,YAAY,QAAoB,UAAkB,SACtD,OAAO,WAAW,QAAQ,OAAO,OAAO,aAAa,YAAY,OAAO,OAAO,YAAY,KAAK;;CAGlG,SAAS,cAAc,QAAoB,UAAkB,MAAsB;EACjF,IAAI,CAAC,OAAO,QACV,MAAM,IAAI,MAAM,8DAA8D;EAChF,IAAI,CAAC,SAAS,QAAQ,UAAU,IAAI,GAClC,MAAM,IAAI,MAAM,8BAA8B,OAAO,OAAO,aAAa,OAAO,OAAO,aAAa,WAAW,wBAAwB,GAAG,oCAAoC;CAClL;CAEA,MAAM,gBAAsB;EAC1B,KAAU,iBAAiB,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;CACxE;CAEA,OAAO;EACL;EAEA,qBAAiC;GAC/B,eAAe;GACf,OAAO,aAAa,MAAM,KAAK,CAAC;EAClC;EAEA,eAAe,GAAG,SAAS,gBAAgB;GACzC,eAAe;GACf,MAAM,EAAE,UAAU,eAAe,YAAY,GAAG,IAAI;GACpD,MAAM,aAAa,gBAAgB,EAAE,UAAU;GAC/C,IAAI,EAAE,SAAS,KAAA,MAAc,CAAC,MAAM,QAAQ,EAAE,IAAI,KAAK,CAAC,EAAE,KAAK,OAAM,MAAK,OAAO,MAAM,QAAQ,IAC7F,MAAM,IAAI,mBAAmB,8BAA8B;GAC7D,MAAM,WAAW,EAAE,aAAa;GAChC,MAAM,SAAS,MAAM,KAAK;GAC1B,MAAM,QAAQ,OAAO,WAAW,QAAQ,CAAC,SAAS,QAAQ,UAAU,IAAI;GACxE,IAAI,SAAS,CAAC,UAAU;IACtB,MAAM,MAAM;KAAE,OAAO;KAAc;KAAU;KAAY;KAAU,SAAS;KAAO,IAAI;IAAK,CAAC;IAC7F,OAAO;KAAE,SAAS;KAAO,QAAQ,aAAa,MAAM;IAAE;GACxD;GACA,MAAM,OAAmB,QACrB;IAAE,SAAS;IAAG,QAAQ;IAAM,YAAY,CAAC;IAAG,MAAM,CAAC;IAAG,QAAQ,CAAC;IAAG,WAAW,CAAC;GAAE,IAChF;GACJ,KAAK,SAAS;IACZ;IACA;IACA,WAAW,SAAS,CAAC,OAAO,SAAS,KAAK,IAAI,IAAI,OAAO,OAAO;IAChE,GAAI,KAAK,YAAY,EAAE,SAAS,KAAK,UAAU,IAAI,CAAC;GACtD;GACA,IAAI,YACF,KAAK,aAAa;GACpB,IAAI,EAAE,SAAS,KAAA,GACb,KAAK,OAAO,CAAC,GAAG,IAAI,IAAI,EAAE,IAAI,CAAC;GACjC,MAAM,MAAM,IAAI;GAChB,QAAQ;GACR,MAAM,MAAM;IAAE,OAAO;IAAc;IAAU;IAAY;IAAU,SAAS;IAAM,YAAY,KAAK;IAAY,MAAM,KAAK;IAAM,IAAI;GAAK,CAAC;GAC1I,OAAO;IAAE,SAAS;IAAM,QAAQ,aAAa,IAAI;GAAE;EACrD,CAAC;EAED,cAAc,GAAG,SAAS,UAAU,YAAY;GAC9C,eAAe;GACf,MAAM,EAAE,aAAa,YAAY,GAAG,KAAK;GACzC,MAAM,WAAW,EAAE;GACnB,MAAM,SAAS;IAAE,OAAO;IAAa;IAAU;GAAS;GACxD,IAAI;IACF,IAAI,CAAC,gBAAgB,SAAS,QAAQ,GACpC,MAAM,IAAI,mBAAmB,4BAA4B,gBAAgB,KAAK,IAAI,EAAE,EAAE;IACxF,MAAM,SAAS,MAAM,KAAK;IAC1B,cAAc,QAAQ,UAAU,IAAI;IACpC,IAAI,CAAC,OAAO,WAAW,SAAS,QAAQ,GACtC,MAAM,IAAI,MAAM,IAAI,SAAS,8DAA8D;IAC7F,MAAM,SAAyB;KAAE,SAAS,CAAC;KAAG,WAAW,CAAC;KAAG,SAAS,CAAC;KAAG,UAAU,CAAC;IAAE;IACvF,MAAM,UAAU,EAAE;IAClB,IAAI,aAAa,YACf,aAAa,KAAK,QAAQ,SAAqC,MAAM;SAElE,IAAI,aAAa,aACpB,cAAc,KAAK,QAAQ,SAAsC,MAAM;SAEpE,IAAI,aAAa,SAChB;SAAA,UAAU,KAAK,QAAQ,SAAkC,MAAM,GAAG;MACpE,QAAQ;MACR,UAAU;OAAE,MAAM;OAAmB,SAAS;MAAS,CAAC;KAC1D;WAEG,IAAI,aAAa,QACpB,MAAM,SAAS,KAAK,QAAQ,SAAiC,MAAM,MAAM;SAEtE,IAAI,aAAa,cACpB,MAAM,eAAe,KAAK,QAAQ,SAAuC,MAAM,MAAM;SAElF,IAAI,aAAa,gBACpB,iBAAiB,KAAK,QAAQ,SAAyC,MAAM;SAG7E,SAAS,KAAK,QAAQ,SAAiC,MAAM;IAE/D,OAAO,aAAa,KAAK,IAAI;IAC7B,MAAM,MAAM,MAAM;IAClB,QAAQ;IACR,MAAM,MAAM;KAAE,GAAG;KAAQ,SAAS,OAAO,QAAQ;KAAQ,WAAW,OAAO,UAAU;KAAQ,SAAS,OAAO,QAAQ;KAAQ,IAAI;IAAK,CAAC;IACvI,OAAO;GACT,SACO,KAAK;IACV,MAAM,MAAM;KAAE,GAAG;KAAQ,IAAI;KAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;IAAE,CAAC;IAC7F,MAAM;GACR;EACF,CAAC;EAED,eAAe,GAAG,SAAS,gBAAgB;GACzC,eAAe;GACf,IAAI,OAAO,EAAE,UAAU,YAAY,EAAE,UAAU,IAC7C,MAAM,IAAI,mBAAmB,kCAAkC;GACjE,MAAM,SAAS,MAAM,KAAK;GAC1B,MAAM,QAAQ,QAAQ,OAAO,UAAU,EAAE,MAAM;GAC/C,IAAI,OAAO;IACT,OAAO,OAAO,UAAU,EAAE;IAE1B,MAAM,QAAQ,OAAO,OAAO,EAAE;IAC9B,IAAI,OAAO;KACT,OAAO,MAAM;KACb,OAAO,MAAM;IACf;IACA,MAAM,MAAM,MAAM;IAClB,QAAQ;GACV;GACA,MAAM,MAAM;IAAE,OAAO;IAAc,OAAO,EAAE;IAAO;IAAO,IAAI;GAAK,CAAC;GACpE,OAAO,EAAE,MAAM;EACjB,CAAC;EAED,iBAAiB,GAAG,SAAS,gBAAgB;GAC3C,eAAe;GACf,MAAM,EAAE,aAAa,YAAY,GAAG,KAAK;GACzC,MAAM,SAAS,MAAM,KAAK;GAC1B,IAAI,CAAC,OAAO,QACV,OAAO,EAAE,UAAU,MAAM;GAC3B,cAAc,QAAQ,UAAU,IAAI;GAEpC,MAAM,MAAM;IAAE,SAAS;IAAG,QAAQ;IAAM,YAAY,CAAC;IAAG,MAAM,CAAC;IAAG,QAAQ,CAAC;IAAG,WAAW,CAAC;GAAE,CAAC;GAC7F,QAAQ;GACR,MAAM,MAAM;IAAE,OAAO;IAAgB;IAAU,IAAI;GAAK,CAAC;GACzD,OAAO,EAAE,UAAU,KAAK;EAC1B,CAAC;CACH;AACF;;;;;AAQA,SAAgB,kBACd,UACA,EAAE,cAAc,iBACW;CAC3B,MAAM,QAAQ,OAAU,MAA4B,WAAgD;EAClG,MAAM,SAAS,MAAM,KAAK;EAC1B,MAAM,cAAc,OAAO,MAAM,CAAC;EAClC,OAAO;CACT;CACA,OAAO;EACL,gBAAgB,OAAO,GAAG,SAAS;GACjC,MAAM,SAAS,aAAa;GAC5B,OAAO,YAAY,SAAS,eAAe,CAAC,GAAG,IAAI,IAAG,SAAQ,OAAO,KAAKC,WAAS,GAAG,KAAK,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CACzG,QAAO,QAAO,KAAK,UAAU,OAAO,IAAI,MAAM,KAAK,UAAW,KAA4C,IAAI,CAAC,CAAC,CAChH,IAAI,YAAY,CAAC;EACtB;EACA,eAAe,GAAG,SAAS,YAAY,SAAS,aAAa,CAAC,GAAG,IAAI,IAAG,MAAM,EAAE,UAAU,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAE;EAC7H,eAAe,GAAG,SAAS,YAAY,SAAS,aAAa,CAAC,GAAG,IAAI,IAAG,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAE;EACjH,mBAAmB,GAAG,SAAS,YAAY,SAAS,iBAAiB,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,CAAC;EAC7G,mBAAmB,GAAG,SAAS,YAAY,SAAS,iBAAiB,CAAC,GAAG,IAAI,SAAS,CAAC,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,CAAC;EAC7G,mBAAmB,GAAG,SAAS,YAAY,SAAS,iBAAiB,CAAC,GAAG,IAAI,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC;EAC3G,mBAAmB,GAAG,SAAS,YAAY,SAAS,iBAAiB,CAAC,GAAG,IAAI,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC;EAC3G,gBAAgB,GAAG,SAAS,YAAY,SAAS,cAAc,CAAC,GAAG,IAAI,IAAG,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,IAAI,CAAC,CAAE;EACvH,sBAAsB,GAAG,SAAS,YAAY,SAAS,oBAAoB,CAAC,GAAG,IAAI,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC;CACnH;AACF;;;ACxRA,SAAgB,uBAAuB,EAAE,MAAM,eAO7C;CACA,OAAO;EACL,SAAS;GACP,mBAAkB,MAAK,KAAK,UAAU,MAAM,EAAE,SAAS;GACvD,kBAAiB,MAAK,KAAK,UAAU,KAAK,CAAC;GAC3C,mBAAmB,OAAO,GAAG,SAAS;IAEpC,MAAM,WAAW,eAAe,EAAE,UAAU,UAAU,KAAK,KAAA;IAC3D,MAAM,SAAS,MAAM,KAAK,UAAU,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC;IAGjF,IAAI,CAAC,YAAY,IAAI,GAAG;KACtB,KAAK,UAAU,OAAO,EAAE,YAAY,EAAE,QAAQ;KAC9C,OAAO;IACT;IACA,MAAM,QAAS,KAAK,kCAAkB,IAAI,IAAI;IAC9C,MAAM,IAAI,EAAE,aAAa,MAAM,IAAI,EAAE,UAAU,qBAAK,IAAI,IAAI,EAAA,CAAG,IAAI,EAAE,QAAQ,CAAC;IAC9E,OAAO;GACT;GACA,oBAAoB,GAAG,SAAS;IAC9B,MAAM,QAAQ,KAAK,eAAe,IAAI,EAAE,UAAU;IAClD,OAAO,OAAO,EAAE,QAAQ;IACxB,IAAI,OAAO,SAAS,GAClB,KAAK,eAAe,OAAO,EAAE,UAAU;IACzC,KAAK,UAAU,OAAO,EAAE,YAAY,EAAE,QAAQ;GAChD;GACA,mBAAkB,MAAK,KAAK,UAAU,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW;IAAE,UAAU,EAAE;IAAU,GAAI,EAAE,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;GAAG,IAAI,KAAA,CAAS;GAC9J,oBAAmB,MAAK,KAAK,UAAU,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;GAC/F,iBAAgB,MAAK,KAAK,UAAU,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM;GAC1E,qBAAoB,MAAK,KAAK,UAAU,QAAQ,EAAE,UAAU;GAC5D,mBAAkB,MAAK,KAAK,UAAU,MAAM,EAAE,UAAU;GACxD,uBAAsB,MAAK,KAAK,UAAU,UAAU,EAAE,YAAY,EAAE,MAAM;GAC1E,0BAAyB,MAAK,KAAK,UAAU,aAAa,CAAC;GAC3D,0BAA0B,OAAO,GAAG,SAAS;IAC3C,IAAI,EAAE,SACJ,CAAC,KAAK,mCAAmB,IAAI,IAAI,EAAA,CAAG,IAAI,EAAE,OAAO;IACnD,MAAM,SAAS,MAAM,KAAK,UAAU,cAAc,CAAC;IAEnD,IAAI,EAAE,WAAW,CAAC,YAAY,IAAI,GAChC,KAAK,UAAU,aAAa,EAAE,OAAO;IACvC,OAAO;GACT;GACA,kBAAkB,OAAO,GAAG,SAAS;IACnC,MAAM,SAAS,MAAM,KAAK,UAAU,MAAM,CAAC;IAC3C,KAAK,gBAAgB,OAAO,EAAE,OAAO;IACrC,OAAO;GACT;GACA,0BAA0B,GAAG,SAAS;IACpC,KAAK,gBAAgB,OAAO,EAAE,OAAO;IACrC,KAAK,UAAU,aAAa,EAAE,OAAO;GACvC;GACA,4BAA4B,GAAG,SAAS;IACrC,CAAC,KAAK,oCAAoB,IAAI,IAAI,EAAA,CAAG,IAAI,EAAE,QAAQ;IACpD,KAAK,UAAU,eAAe,EAAE,QAAQ;IACxC,OAAO,EAAE,IAAI,KAAK;GACpB;GACA,8BAA8B,GAAG,SAAS;IACxC,KAAK,iBAAiB,OAAO,EAAE,QAAQ;IACvC,KAAK,UAAU,iBAAiB,EAAE,QAAQ;IAC1C,OAAO,EAAE,IAAI,KAAK;GACpB;EACF;EACA,YAAY,MAAM;GAEhB,KAAK,MAAM,WAAW,KAAK,kBAAkB,CAAC,GAC5C,KAAK,UAAU,aAAa,OAAO;GACrC,KAAK,MAAM,YAAY,KAAK,mBAAmB,CAAC,GAC9C,KAAK,UAAU,iBAAiB,QAAQ;GAC1C,KAAK,MAAM,CAAC,YAAY,YAAY,KAAK,iBAAiB,CAAC,GACzD,KAAK,MAAM,YAAY,SACrB,KAAK,UAAU,OAAO,YAAY,QAAQ;EAEhD;CACF;AACF;;;ACvFA,SAAgB,oBAAoB,EAAE,MAAM,aAGL;CACrC,OAAO,EACL,0BAA0B,OAAO,MAAM;EACrC,MAAM,YAAY,YAAY,CAAC;EAC/B,MAAM,cAAcC,iBAAe,EAAE,aAAa,aAAa;EAC/D,MAAM,QAAQA,iBAAe,EAAE,OAAO,OAAO;EAC7C,MAAM,QAAQ,MAAM,KAAK,qBAAqB,WAAW;GACvD,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;GACnD,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACzC,CAAC;EAED,UAAU;GAAE,MAAM;GAAoB,IAAI;GAAU;EAAU,CAAC;EAC/D,OAAO,EAAE,MAAM;CACjB,EACF;AACF;;;ACdA,SAAgB,mBAAmB,EAAE,MAAM,SAAuF;CAChI,OAAO;EACL,cAAc,MAA4B;GACxC,MAAM,QAAQ,KAAK,iBAAiB,EAAE,SAAS;GAC/C,OAAO,QAAQ,gBAAgB,KAAK,IAAI;EAC1C;EAUA,aAAa,OAAO,MAAqC;GACvD,MAAM,QAAQ,MAAM,KAAK,SAAS,EAAE,WAAW,EAAE,KAAK;GACtD,IAAI,OACF,OAAO,gBAAgB,KAAK;GAC9B,IAAI,EAAE,gBAAgB,QAAQ,KAAK,eAAe,EAAE,SAAS,GAC3D,OAAO;GACT,OAAO,iBAAiB,OAAO,EAAE,WAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,QAAQ,CAAC,CAAC;EACnF;CACF;AACF;;AAGA,eAAe,iBAAiB,OAAqB,WAAmB,OAA2D;CACjI,MAAM,UAAU,MAAM,YAAY,OAAO,WAAW,EAAE,aAAa,MAAM,CAAC;CAC1E,IAAI,CAAC,SACH,OAAO;CAET,eAAe,SAAS,kBAAkB,OAAO,CAAC,CAAC,OAAO,OAAO,EAAE,cAAc,KAAK,CAAC;CACvF,MAAM,QAAQ,KAAK;CACnB,OAAO,gBAAgB,kBAAkB,OAAO,CAAC;AACnD;;;AC7BA,SAAgB,yBAAyB,EAAE,MAAM,OAAO,WAAW,SAMpC;CAC7B,OAAO;EACL,uBAAuB,OAAO,MAAM;GAClC,MAAM,SAAS;GACf,IAAI,YAAY,MAAM,GAGpB,OAAO,MAAM,MAAM,KAAK,OAAO,EAAE,WAAW,MAAM;GAEpD,MAAM,OAAO,MAAM,YAAY,OAAO,EAAE,SAAS;GAGjD,OAAO,gBAAgB,KAAK,OAAO,KAAK,IAAI;EAC9C;EACA,oBAAoB,OAAO,MAAM;GAE/B,QAAO,MADY,MAAM,KAAK,EAAE,SAAS,EAAA,EAC5B,MAAM,MAAK,MAAK,EAAE,OAAO,EAAE,MAAM,KAAK;EACrD;EAGA,mBAAmB,MAAM;GACvB,UAAU;IAAE,MAAM;IAAoB,IAAI;IAAU,WAAW,EAAE;GAAU,CAAC;EAC9E;EACA,iBAAiB,OAAO,MAAM;GAC5B,MAAM,SAAS,MAAM,KAAK,YAAY;IACpC,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,GAAI,OAAO,EAAE,UAAU,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;GACnF,CAAC;GACD,IAAI,CAAC,OAAO,IACV,MAAM,IAAI,MAAM,oBAAoB,OAAO,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC;GAC3E,UAAU;IAAE,MAAM;IAAoB,IAAI;IAAU,WAAW,OAAO;GAAG,CAAC;GAC1E,OAAO,EAAE,IAAI,OAAO,GAAG;EACzB;EACA,wBAAuB,MAAK,KAAK,WAAW,EAAE,WAAW,EAAE,MAAM;EAEjE,0BAAyB,MAAK,KAAK,aAAa,EAAE,WAAW,EAAE,QAAQ,OAAO,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,GAAG,KAAS,IAAI,EAAE;EACnI,oBAAmB,MAAK,KAAK,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,KAAK,CAAC;EACrG,yBAAwB,MAAK,KAAK,YAAY,EAAE,WAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,KAAK,CAAC;EACnI,wBAAuB,MAAK,KAAK,WAC/B,EAAE,WACF,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,QAAO,UAAS,OAAO,OAAO,SAAS,QAAQ,IAAI,CAAC,CACzF;EACA,qBAAoB,MAAK,KAAK,kBAAkB,EAAE,SAAS;CAC7D;AACF;;;;AC5CA,MAAM,iBAAiB;AAEvB,SAAgB,oBAAoB,EAAE,OAAO,MAAM,SAAS,aAQO;CACjE,IAAI,SAAuD;CAC3D,IAAI,UAAwC;CAC5C,MAAM,WAAW,QAAuC;EACtD,IAAI,UAAU,MAAM,OAAO,KAAK,gBAC9B,OAAO,QAAQ,QAAQ,OAAO,OAAO;EACvC,YAAY,KAAK,KAAK,CAAC,CAAC,MAAM,YAAY;GACxC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mDAAoD;GACtE,SAAS;IAAE,SAAS;IAAS,IAAI,KAAK,IAAI;GAAE;GAC5C,OAAO;EACT,CAAC,CAAC,CAAC,cAAc;GACf,UAAU;EACZ,CAAC;EACD,OAAO;CACT;CACA,OAAO;EACL,iBAAiB,OAAO,MAAM;GAC5B,IAAI,CAAC,aAAa,SAAS,EAAE,KAAmB,GAC9C,MAAM,IAAI,mBAAmB,wBAAwB,aAAa,KAAK,IAAI,EAAE,EAAE;GACjF,MAAM,sBAAM,IAAI,KAAK;GACrB,OAAO,eAAe,MAAM,QAAQ,IAAI,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC;EACtE;EACA,oBAAmB,MAAK,sBAAsB,QAAQ,GAAG,UAAU,GAAG,EAAE,SAAS,GAAG,YAAY,KAAK,CAAC;EACtG,iBAAgB,MAAK,iBAAiB,EAAE,OAAO,GAAG,UAAU,KAAK,CAAC;CACpE;AACF;;;;AC/CA,MAAM,aAAa,UAA4B,OAAO,UAAU,WAAW,QAAQ;AAEnF,SAAgB,wBAAwB,EAAE,QAAuD;CAC/F,OAAO;EACL,2BAA0B,MAAK,KAAK,cAAc,EAAE,WAAW,EAAE,SAAS;GACxE,GAAI,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;GAC5C,GAAI,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;GAC5C,GAAI,EAAE,mBAAmB,KAAA,IAAY,EAAE,gBAAgB,EAAE,eAAe,IAAI,CAAC;EAC/E,CAAC;EACD,+BAA8B,MAAK,KAAK,kBAAkB,EAAE,WAAW,EAAE,IAAI;EAC7E,gCAA+B,MAAK,KAAK,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO;EAC1F,gCAA+B,MAAK,KAAK,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO;EAC1F,+BAA8B,MAAK,KAAK,kBAAkB,EAAE,WAAW,EAAE,IAAI;EAC7E,6BAA6B,MAAM;GACjC,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,OAClC,MAAM,IAAI,MAAM,mCAA+B;GACjD,IAAI,EAAE,YAAY,KAAA,KAAa,OAAO,EAAE,YAAY,UAClD,MAAM,IAAI,MAAM,8BAA8B;GAChD,OAAO,KAAK,gBAAgB,EAAE,WAAW,UAAU,EAAE,IAAI,GAAG,EAAE,MAAM;IAClE,GAAI,EAAE,YAAY,KAAA,IAAY,EAAE,SAAS,IAAI,WAAW,OAAO,KAAK,EAAE,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC;IAC/F,GAAI,EAAE,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;GAClD,CAAC;EACH;EACA,2BAA0B,MAAK,KAAK,cAAc,EAAE,WAAW,UAAU,EAAE,IAAI,GAAG,UAAU,EAAE,EAAE,CAAC;EACjG,2BAA0B,MAAK,KAAK,cAAc,EAAE,WAAW,UAAU,EAAE,IAAI,GAAG,UAAU,EAAE,KAAK,CAAC;EACpG,6BAA4B,MAAK,KAAK,gBAAgB,EAAE,WAAW,UAAU,EAAE,IAAI,CAAC;EACpF,gCAA+B,MAAK,KAAK,mBAAmB,EAAE,SAAS;CACzE;AACF;;;ACpBA,MAAa,+BAA+B;;CAE1C,eAAe;;CAEf,YAAY;;CAEZ,gBAAgB;;CAEhB,kBAAkB;;CAElB,wBAAwB;AAC1B;;AAcA,SAAS,WAAW,MAAc,KAAuB;CACvD,IAAI,OAAO,WAAW,IAAI,KAAK,KAC7B,OAAO,CAAC,IAAI;CACd,MAAM,SAAmB,CAAC;CAC1B,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,OAAO,OAAO,WAAW,IAAI;EACnC,IAAI,QAAQ,OAAO,KAAK;GACtB,OAAO,KAAK,OAAO;GACnB,UAAU;GACV,QAAQ;EACV;EACA,WAAW;EACX,SAAS;CACX;CACA,IAAI,SACF,OAAO,KAAK,OAAO;CACrB,OAAO;AACT;;AAGA,SAAS,WAAW,MAAc,KAAqB;CACrD,IAAI,QAAQ;CACZ,IAAI,MAAM;CACV,KAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,OAAO,OAAO,WAAW,IAAI;EACnC,IAAI,QAAQ,OAAO,KACjB;EACF,SAAS;EACT,OAAO,KAAK;CACd;CACA,OAAO,KAAK,MAAM,GAAG,GAAG;AAC1B;AAEA,SAAgB,kCAAkC,EAAE,MAAM,aAAa,SAAS,gCAQ9E;CACA,MAAM,0BAAU,IAAI,IAAyB;CAC7C,MAAM,0BAAU,IAAI,QAA+B;CAEnD,MAAM,QAAQ,MAAgB,WAA6B;EACzD,IAAI,YAAY,IAAI,GAClB,KAAK,KAAK,MAAM;CACpB;;CAGA,SAAS,WAAW,QAAgB,MAAgB,OAAmB;EACrE,IAAI,QAAQ;EACZ,IAAI,SAAS;EACb,OAAO;GACL,cAAc;GACd,KAAK,QAA6B,MAAoB;IACpD,IAAI,UAAU,SAAS,IACrB;IACF,IAAI,QAAQ;IACZ,IAAI,QAAQ,OAAO,WAAW,KAAK,IAAI,OAAO,gBAAgB;KAC5D,QAAQ,WAAW,OAAO,OAAO,iBAAiB,KAAK;KACvD,SAAS;IACX;IACA,SAAS,OAAO,WAAW,KAAK;IAChC,KAAK,MAAM,SAAS,QAAQ,WAAW,OAAO,OAAO,UAAU,IAAI,CAAC,GAClE,KAAK,MAAM;KAAE,MAAM;KAAuB;KAAQ;KAAQ;IAAM,CAAC;IACnE,IAAI,QACF,MAAM;GACV;EACF;CACF;CAEA,eAAe,KAAK,QAAgB,MAAgB,QAAsB,OAAmC;EAC3G,MAAM,OAAO,WAAW,QAAQ,YAAY,MAAM,KAAK,CAAC;EACxD,MAAM,QAAQ,OAAO,QAA+C,SAA6C;GAC/G,IAAI,CAAC,QACH;GACF,MAAM,UAAU,IAAI,YAAY;GAChC,IAAI;IACF,WAAW,MAAM,SAAS,QACxB,KAAK,KAAK,MAAM,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;IACzD,KAAK,KAAK,MAAM,QAAQ,OAAO,CAAC;GAClC,QACM,CAEN;EACF;EACA,MAAM,CAAC,QAAQ,MAAM,QAAQ,IAAI;GAAC,OAAO;GAAQ,MAAM,OAAO,QAAQ,QAAQ;GAAG,MAAM,OAAO,QAAQ,QAAQ;EAAC,CAAC;EAEhH,MAAM,SAAS,MAAM,eAAe;EACpC,MAAM,OAAmB;GACvB,MAAM;GACN;GACA,MAAM,SAAS,OAAO;GACtB,QAAQ,SAAS,YAAY;GAC7B,GAAI,KAAK,OAAO,IAAI,EAAE,WAAW,KAAc,IAAI,CAAC;GACpD,GAAI,MAAM,aAAa,SAAS,EAAE,WAAW,KAAc,IAAI,CAAC;EAClE;EACA,KAAK,MAAM,IAAI;CACjB;;CAGA,eAAe,SAAS,QAAgB,MAAgB,OAAoB,KAAyF;EACnK,IAAI,UAAU;EACd,MAAM,aAAa;GACjB,UAAU;EACZ;EACA,MAAM,OAAO,WAAW,QAAQ,YAAY,KAAA,CAAS;EACrD,IAAI;GACF,MAAM,SAAS,MAAM,IAAI;GACzB,IAAI,CAAC,SAAS;IACZ,KAAK,KAAK,UAAU,OAAO,MAAM;IACjC,KAAK,KAAK,UAAU,OAAO,MAAM;GACnC;GACA,KAAK,MAAM;IACT,MAAM;IACN;IACA,MAAM,UAAU,OAAO,OAAO;IAC9B,QAAQ,UAAU,YAAY;IAC9B,GAAI,KAAK,OAAO,IAAI,EAAE,WAAW,KAAc,IAAI,CAAC;IACpD,GAAI,MAAM,YAAY,EAAE,WAAW,KAAc,IAAI,CAAC;GACxD,CAAC;EACH,SACO,KAAK;GACV,KAAK,KAAK,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;GACpE,KAAK,MAAM;IAAE,MAAM;IAAuB;IAAQ,MAAM;IAAM,QAAQ;IAAM,GAAI,MAAM,YAAY,EAAE,WAAW,KAAc,IAAI,CAAC;GAAG,CAAC;EACxI;CACF;CAEA,OAAO;EACL,SAAS;GACP,gCAAgC,OAAO,GAAG,SAAS;IACjD,IAAI,OAAO,EAAE,cAAc,YAAY,EAAE,cAAc,IACrD,MAAM,IAAI,mBAAmB,uCAAuC;IACtE,IAAI,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,KAAK,MAAM,IACxD,MAAM,IAAI,mBAAmB,qCAAqC;IACpE,IAAI,EAAE,QAAQ,SAAS,OAAO,kBAC5B,MAAM,IAAI,mBAAmB,0BAA0B,OAAO,iBAAiB,aAAa;IAC9F,IAAI,EAAE,QAAQ,KAAA,KAAa,OAAO,EAAE,QAAQ,UAC1C,MAAM,IAAI,mBAAmB,uBAAuB;IACtD,MAAM,MAAM,QAAQ,IAAI,IAAI,qBAAK,IAAI,IAAY;IACjD,QAAQ,IAAI,MAAM,GAAG;IACrB,IAAI,IAAI,QAAQ,OAAO,eACrB,MAAM,IAAI,MAAM,gCAAgC,IAAI,KAAK,2BAA2B,OAAO,cAAc,mBAAmB;IAC9H,MAAM,SAAS,WAAW;IAE1B,IAAI,IAAI,MAAM;IACd,MAAM,QAAqB;KAAE;KAAM,YAAY,KAAA;KAAW,WAAW;IAAM;IAC3E,QAAQ,IAAI,QAAQ,KAAK;IACzB,MAAM,aAAmB;KACvB,IAAI,OAAO,MAAM;KACjB,QAAQ,OAAO,MAAM;IACvB;IACA,MAAM,UAAU,EAAE,QAAQ,KAAA,IAAY,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;IACxD,IAAI;IACJ,IAAI;KACF,SAAS,MAAM,KAAK,oBAAoB,EAAE,WAAW,EAAE,SAAS,OAAO;IACzE,SACO,KAAK;KACV,KAAK;KACL,MAAM;IACR;IACA,IAAI,QAAQ;KACV,MAAM,OAAO;KACb,IAAI,SAAS;KACb,KAAU,OAAO,WAAW;MAC1B,SAAS;KACX,SAAS;MACP,SAAS;KACX,CAAC;KACD,MAAM,aAAa;MACjB,IAAI,CAAC,QACH,MAAM,aAAa;MACrB,KAAU,KAAK;KACjB;KAEA,IAAI,CAAC,YAAY,IAAI,GACnB,MAAM,KAAK;KACb,KAAU,QAAQ,MAAM,MAAM,KAAK,CAAC,CAAC,QAAQ,IAAI;IACnD,OAEE,SAAc,QAAQ,MAAM,aAAa,KAAK,cAAc,EAAE,WAAW,EAAE,SAAS;KAAE,GAAG;KAAS,gBAAgB,OAAO;IAAuB,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI;IAElK,OAAO,EAAE,OAAO;GAClB;GACA,iCAAiC,GAAG,SAAS;IAC3C,MAAM,QAAQ,OAAO,EAAE,WAAW,WAAW,QAAQ,IAAI,EAAE,MAAM,IAAI,KAAA;IACrE,IAAI,CAAC,SAAS,MAAM,SAAS,MAC3B,OAAO,EAAE,WAAW,MAAM;IAC5B,MAAM,YAAY;IAClB,MAAM,KAAK;IACX,OAAO,EAAE,WAAW,KAAK;GAC3B;EACF;EACA,YAAY,MAAM;GAChB,KAAK,MAAM,UAAU,QAAQ,IAAI,IAAI,KAAK,CAAC,GAAG;IAC5C,MAAM,QAAQ,QAAQ,IAAI,MAAM;IAChC,IAAI,OAAO;KACT,MAAM,YAAY;KAClB,MAAM,KAAK;IACb;GACF;EACF;CACF;AACF;;;;;;;ACrNA,SAAS,oBAAoB,QAA4C;CACvE,MAAM,SAAS,OAAO,OAAO,oBAAoB,WAAW,OAAO,kBAAkB,KAAA;CACrF,MAAM,YAAY,OAAO,OAAO,uBAAuB,WAAW,KAAK,IAAI,OAAO,oBAAoB,UAAU,QAAQ,IAAI;CAC5H,IAAI,WAAW,KAAA,KAAa,cAAc,KAAA,KAAa,aAAA,MAAqC,UAAA,IAC1F,OAAO;EAAE,QAAQ;EAAM,QAAQ;EAAO,iBAAiB,KAAK,IAAI,QAAA,EAA4B;CAAE;CAGhG,OAAO;EACL,QAAQ;EACR,SAAS,wEAAuE,UAAU,IAAI,gBAJhF,WAAW,KAAA,KAAa,SAAA,KAAgC,WAAW,SAIqC;CACxH;AACF;AAEA,SAAgB,cAAc,QAA8B,KAAiC;CAC3F,IAAI,IAAI,aAAa,UACnB,OAAO,oBAAoB,MAAM;CASnC,MAAM,cAAc,OAAO,OAAO,OAAO;CACzC,MAAM,cAAc,OAAO,IAAI,OAAO;CACtC,MAAM,aACF,OAAO,YAAY,KAAA,KAChB,OAAO,YAAY,aACnB,IAAI,YAAY,aAChB,OAAO,SAAS,WAAW,KAC3B,OAAO,SAAS,WAAW,KAC3B,cAAc;CAQrB,MAAM,eACF,OAAO,OAAO,gBAAgB,YAC3B,gBAAgB,OAAO,aAAa,IAAI,WAAW,IAAI;CAQ9D,MAAM,kBAAkB,OAAO,oBAAA;CAC/B,IAAI,oBAAoB,cAAc,iBAAiB,IAAI,eACzD,OAAO;EAAE,QAAQ;EAAM,QAAQ;EAAM,iBAAA;CAAsC;CAC7E,IAAI,CAAC,mBAAmB,cAAc,cACpC,OAAO;EACL,QAAQ;EACR,SAAS,eACL,gCAAgC,IAAI,YAAY,uBAAuB,OAAO,YAAY,2BAC1F,aACE,sEAAsE,IAAI,QAAQ,WAAW,OAAO,QAAQ,4BAC5G,8DAAmF,OAAO,mBAAmB,IAAI;CACzH;CAEF,OAAO;EAAE,QAAQ;EAAM,QAAQ;EAAO,iBAAA;CAAsC;AAC9E;;;AC5EA,MAAM,OAAO;AAEb,SAAgB,oBAAoB,SAAiB,SAA4C;CAC/F,OAAO;EACL,IAAI,uBAAuB,KAAK,SAAS,IAAI,CAAC;EAC9C,MAAM,QAAQ;EACd,MAAM,QAAQ,QAAQ,SAAS;CACjC;AACF;;;ACPA,SAAgB,aAAa,QAAmC;CAC9D,IAAI;CACJ,IAAI,OAAO;CACX,OAAO,EACL,YAAY;EACV,IAAI,CAAC,MAAM;GACT,OAAO;GACP,IAAI;IACF,OAAO,KAAK,UAAU,MAAM;GAC9B,QACM;IACJ,OAAO,KAAA;GACT;EACF;EACA,OAAO;CACT,EACF;AACF;;AAkFA,MAAM,+BAAoC,IAAI,IAAI;CAAC;CAAQ;CAAQ;CAAa;CAAU;CAAW;AAAO,CAAC;;;;;;;;;AAY7G,SAAS,SAAS,QAAmC;CACnD,IAAI,OAAO,SAAS,SAClB,OAAO;CACT,MAAM,QAAQ,OAAO;CACrB,IAAI,MAAM,SAAS,aAAa,MAAM,cAAc,OAAO,MAAM,SAAS,YACxE,OAAO;CACT,IAAI,OAAO,MAAM,SAAS,UACxB,OAAO;CACT,KAAK,MAAM,OAAO,QAChB,IAAI,QAAQ,UAAU,QAAQ,eAAe,QAAQ,SACnD,OAAO;CAEX,KAAK,MAAM,OAAO,OAChB,IAAI,CAAC,aAAa,IAAI,GAAG,GACvB,OAAO;CAEX,OAAO,KAAK,UAAU;EAAC,OAAO;EAAW,MAAM;EAAM,MAAM,aAAa;EAAM,MAAM,WAAW;EAAM,MAAM,SAAS;EAAM,MAAM,UAAU;CAAI,CAAC;AACjJ;AAEA,SAAgB,mBAAmB,UAA+B,CAAC,GAAiB;CAClF,MAAM,wBAAQ,IAAI,IAAc;CAChC,IAAI,YAAmC;CACvC,MAAM,gBAAiD,CAAC;CACxD,MAAM,iBAAoC,CAAC;;CAG3C,MAAM,kCAAkB,IAAI,IAAY;;CAGxC,IAAI,OAAqE;CACzE,IAAI,aAAa;CAEjB,MAAM,cAAoB;EACxB,MAAM,UAAU;EAChB,IAAI,CAAC,SACH;EACF,OAAO;EACP,KAAK,QAAQ,MAAM;CACrB;CAEA,MAAM,aAAa,WAA6B;EAC9C,MAAM,MAAM,SAAS,MAAM;EAC3B,IAAI,QAAQ,QAAQ,MAAM,QAAQ,KAAK;GACrC,MAAM,QAAQ;GACd,IAAI,CAAC,KAAK,QAAQ;IAEhB,KAAK,SAAS;KAAE,GAAG,KAAK;KAAQ,OAAO,EAAE,GAAG,KAAK,OAAO,MAAM;IAAE;IAChE,KAAK,SAAS;GAChB;GACA,MAAM,QAAQ,KAAK,OAAO;GAC1B,MAAM,QAAS,MAAM,MAA2B;GAChD;EACF;EACA,MAAM;EACN,IAAI,QAAQ,MAAM;GAChB,KAAK,MAAM;GACX;EACF;EACA,OAAO;GAAE;GAAa;GAAuB,QAAQ;EAAM;EAC3D,IAAI,CAAC,YAAY;GACf,aAAa;GACb,mBAAmB;IACjB,aAAa;IACb,MAAM;GACR,CAAC;EACH;CACF;CAEA,SAAS,KAAK,QAA0B;EAEtC,IAAI,OAAO,SAAS,qBAAqB,OAAO,SAAS,kBAAkB;GACzE,MAAM,UAAU,aAAa,MAAM;GACnC,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,SAAS,KAAK,eAAe,IAAI,OAAO,UAAU,GACzD,KAAK,KAAK,QAAQ,KAAA,GAAW,OAAO;GAExC;EACF;EAEA,OAAO,MAAM,QAAQ,IAAI;EAOzB,QAAQ,OAAO,MAAf;GACE,KAAK;IAIH,gBAAgB,IAAI,OAAO,SAAS;IACpC,kBAAkB;IAClB;GACF,KAAK;IACH,gBAAgB,OAAO,OAAO,SAAS;IACvC,kBAAkB;IAClB;GACF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,wBACH,kBAAkB;EAItB;CACF;;CAGA,SAAS,OAAO,QAAyB,QAAoB,UAAyB;EAEpF,WAAW,QAAQ,QAAQ,MAAM;EACjC,MAAM,UAAU,aAAa,MAAM;EACnC,MAAM,MAAM,WAAW,QAAQ,WAAW,QAAQ,QAAQ,IAAI,IAAI,KAAA;EAClE,KAAK,MAAM,QAAQ,OAAO;GACxB,IAAI,CAAC,KAAK,SAAS,SAAS,QAC1B;GACF,KAAK,KAAK,QAAQ,KAAK,OAAO;EAChC;CACF;CAEA,SAAS,gBAAgB,QAAyB,QAA0B;EAC1E,MAAM;EACN,OAAO,QAAQ,QAAQ,KAAK;CAC9B;;;;;;CAOA,SAAS,kBAAqC;EAC5C,MAAM,OAAO;EACb,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,0CAA0C;EAC5D,MAAM,+BAAe,IAAI,IAAoB;EAC7C,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,SAAS,KAAK,UACrB,aAAa,IAAI,KAAK,WAAW,aAAa,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC;EAG9E,MAAM,4BAAY,IAAI,IAAY;EAClC,KAAK,MAAM,WAAW,KAAK,UAAU,YAAY,GAC/C,UAAU,IAAI,QAAQ,SAAS;EACjC,KAAK,MAAM,WAAW,KAAK,aAAa,KAAK,GAC3C,UAAU,IAAI,QAAQ,SAAS;EAIjC,MAAM,OAAO,IAAI,IAAI,KAAK,iBAAiB,CAAC,CAAC,KAAI,UAAS,CAAC,MAAM,WAAW,MAAM,OAAO,CAAC,CAAC;EAG3F,OAAO,CAAC,mBAAG,IADK,IAAY;GAAC,GAAG,aAAa,KAAK;GAAG,GAAG;GAAW,GAAG,KAAK,KAAK;GAAG,GAAG;EAAe,CACxF,CAAC,CAAC,CAAC,KAAI,eAAc;GAChC;GACA,SAAS,aAAa,IAAI,SAAS,KAAK;GACxC,SAAS,gBAAgB,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,MAAM;GACnE,WAAW,UAAU,IAAI,SAAS;EACpC,EAAE;CACJ;CAEA,SAAS,oBAA0B;EACjC,gBAAgB,MAAM;GAAE,MAAM;GAAoB,UAAU,gBAAgB;EAAE,CAAC;CACjF;CAEA,OAAO;EACL,IAAI,MAAM;GACR,MAAM;GACN,MAAM,IAAI,IAAI;EAChB;EACA,MAAK,SAAQ,MAAM,IAAI,IAAI;EAC3B,OAAO,MAAM;GACX,MAAM;GACN,IAAI,CAAC,MAAM,OAAO,IAAI,GACpB;GACF,KAAK,MAAM,WAAW,eACpB,QAAQ,IAAI;GAEd,IAAI,KAAK,UACP,kBAAkB;EACtB;EACA,QAAQ,SAAS;GACf,cAAc,KAAK,OAAO;EAC5B;EACA,QAAQ;GACN,MAAM;GACN,MAAM,MAAM;GACZ,KAAK,MAAM,QAAQ,eAAe,OAAO,CAAC,GACxC,KAAK;EACT;EACA,QAAQ,MAAM;GACZ,eAAe,KAAK,IAAI;EAC1B;EACA,YAAY,MAAM;EAClB;EACA;EACA;EACA;EACA;EACA,SAAS,MAAM;GACb,YAAY;EACd;CACF;AACF;;;;AC7TA,MAAM,0BAA+B,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAiBD,SAAgB,oBAAoB,MAA+B;CACjE,MAAM,2BAAW,IAAI,IAAyB;CAC9C,MAAM,4BAAY,IAAI,IAAyB;;CAE/C,MAAM,0BAAU,IAAI,IAAY;CAEhC,MAAM,OAAO,KAA+B,WAAmB,OAAqB;EAClF,IAAI,MAAM,IAAI,IAAI,SAAS;EAC3B,IAAI,CAAC,KACH,IAAI,IAAI,WAAW,sBAAM,IAAI,IAAI,CAAC;EACpC,IAAI,IAAI,EAAE;CACZ;CAEA,MAAM,kBAAkB,eAA6B;EACnD,KAAK,MAAM,OAAO,UAAU,OAAO,GACjC,IAAI,OAAO,UAAU;CACzB;;;;;;;;CASA,MAAM,cAAc,OAAO,cAAwC;EACjE,MAAM,SAAS,KAAK,UAAU,SAAS;EACvC,KAAK,MAAM,QAAQ,QACjB,KAAK,YAAY,WAAW,KAAK,EAAE;EACrC,MAAM,UAAU,KAAK,iBAAiB,SAAS;EAC/C,MAAM,aAAa,KAAK,gBAAgB,SAAS,CAAC,CAAC,SAAS;EAC5D,IAAI,SACF,KAAK,UAAU,SAAS;EAC1B,IAAI,YACF,MAAM,KAAK,kBAAkB,WAAW,OAAO,wCAAwC,CAAC,CAAC,YAAY,KAAK;EAC5G,OAAO,WAAW,cAAc,OAAO,SAAS;CAClD;CAEA,MAAM,gBAAgB,OAAO,eAAyC;EACpE,IAAI;GACF,MAAM,KAAK,UAAU,MAAM,UAAU;GACrC,OAAO;EACT,QACM;GAEJ,OAAO;EACT;CACF;;CAGA,MAAM,SAAS,QAAgB,QAAiB,SAAyB;EACvE,MAAM,YAAY,KAAK;EACvB,MAAM,YAAa,QAA2C;EAC9D,IAAI,cAAc,KAAA,KAAa,CAAC,QAAQ,IAAI,SAAS,KAAK,QAAQ,IAAI,MAAM,KAAK,OAAO,cAAc,UACpG,IAAI,UAAU,WAAW,SAAS;CACtC;;CAGA,MAAM,UAAU,QAAgB,QAAiB,QAAiB,SAAyB;EACzF,MAAM,YAAY,KAAK;EACvB,IAAI,cAAc,KAAA,GAChB;EACF,MAAM,IAAK,UAAU,CAAC;EACtB,MAAM,SAAU,QAAoC;EACpD,MAAM,OAAO,QAAQ,IAAI,SAAS;EAClC,IAAI,QAAQ,IAAI,MAAM,KAAK,OAAO,EAAE,cAAc,UAAU;GAC1D,IAAI,MACF,YAAiB,EAAE,SAAS,CAAC,CAAC,YAAY,KAAK;QAE/C,IAAI,UAAU,WAAW,EAAE,SAAS;EACxC,OACK,IAAI,WAAW,gCAAgC,OAAO,WAAW,UAAU;GAC9E,IAAI,MACF,YAAiB,MAAM,CAAC,CAAC,YAAY,KAAK;QAE1C,IAAI,UAAU,WAAW,MAAM;EACnC,OACK,IAAI,WAAW,mBAAmB,OAAO,WAAW,UAAU;GACjE,IAAI,MACF,cAAmB,MAAM;QAEzB,IAAI,WAAW,WAAW,MAAM;EACpC,OACK,IAAI,WAAW,oBAAoB,OAAO,EAAE,eAAe,UAC9D,eAAe,EAAE,UAAU;CAE/B;CAEA,OAAO;EACL,MAAM,MAAM,QAAQ,QAAQ,MAAM,MAAM;GACtC,MAAM,QAAQ,QAAQ,IAAI;GAC1B,MAAM,SAAS,MAAM,KAAK;GAC1B,OAAO,QAAQ,QAAQ,QAAQ,IAAI;GACnC,OAAO;EACT;EAEA,MAAM,KAAK,WAAW;GACpB,QAAQ,IAAI,SAAS;GACrB,MAAM,SAAS,SAAS,IAAI,SAAS,qBAAK,IAAI,IAAY;GAC1D,MAAM,SAAS,UAAU,IAAI,SAAS,qBAAK,IAAI,IAAY;GAC3D,SAAS,OAAO,SAAS;GACzB,UAAU,OAAO,SAAS;GAC1B,IAAI,OAAO;GACX,KAAK,MAAM,aAAa,QACtB,IAAI,MAAM,YAAY,SAAS,GAC7B;GAEJ,IAAI,SAAS;GACb,KAAK,MAAM,cAAc,QACvB,IAAI,MAAM,cAAc,UAAU,GAChC;GAEJ,OAAO;IAAE;IAAM,WAAW;GAAO;EACnC;CACF;AACF;ACtFA,SAAS,UAAU,QAAwC;CACzD,IAAI;EACF,OAAO,KAAK,UAAU,MAAM;CAC9B,QACM;EACJ;CACF;AACF;AAEA,SAAS,UAAU,QAAwC;CACzD,MAAM,KAAM,OAAmC;CAC/C,OAAO,OAAO,OAAO,WAAW,KAAK,KAAA;AACvC;AAEA,SAAgB,gBAAgB,UAA4B,CAAC,GAAc;CACzE,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,QAAQ,WAAW;;CAEzB,MAAM,uBAAO,IAAI,IAAwB;;;;;;CAMzC,MAAM,4BAAY,IAAI,IAAgD;;CAEtE,IAAI,QAAQ;CACZ,IAAI,aAAa;CAEjB,MAAM,cAAc,QAA0B;EAC5C,cAAc,IAAI,QAAQ,IAAI,KAAK,CAAE;EACrC,IAAI,SAAS,IAAI,QAAQ,IAAI,KAAK,CAAE;EACpC,IAAI;EACJ,IAAI,IAAI,OAAO,QAAQ,IAAI,OAAO,IAAI,IAAI,QAAQ,QAAQ;GACxD,IAAI,UAAU,IAAI,QAAQ,MAAM,IAAI,IAAI;GACxC,IAAI,OAAO;EACb;CACF;CAEA,MAAM,SAAS,QAA0B;EACvC,cAAc,IAAI;EAClB,IAAI,UAAU,CAAC;EACf,IAAI,OAAO;EACX,IAAI,QAAQ;CACd;;CAGA,MAAM,UAAU,WAAmB,KAAiB,YAA2B;EAC7E,MAAM,GAAG;EACT,KAAK,OAAO,SAAS;EACrB,UAAU,IAAI,WAAW;GAAE,MAAM,IAAI;GAAM;EAAQ,CAAC;EACpD,OAAO,UAAU,OAAO,cAAc;GACpC,MAAM,CAAC,QAAQ,EAAE,UAAU,UAAU,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;GACtD,UAAU,OAAO,MAAM;GACvB,QAAQ,KAAK,IAAI,OAAO,IAAI;EAC9B;CACF;CAEA,OAAO;EACL;EACA,OAAO,QAAQ,kBAAkB,UAAU,MAAM,GAAG;GAClD,MAAM,YAAY,UAAU,MAAM;GAClC,IAAI,cAAc,KAAA,GAChB,OAAO,KAAA;GACT,IAAI,MAAM,KAAK,IAAI,SAAS;GAC5B,IAAI,KACF,KAAK,OAAO,SAAS;QAElB;IACH,MAAM;KAAE,MAAM,UAAU,IAAI,SAAS,CAAC,EAAE,QAAQ;KAAO,SAAS,CAAC;KAAG,MAAM;KAAG,OAAO;IAAE;IACtF,UAAU,OAAO,SAAS;GAC5B;GACA,KAAK,IAAI,WAAW,GAAG;GAEvB,MAAM,MAAM,IAAI;GAChB,MAAM,OAAO,UAAU;GACvB,IAAI,SAAS,KAAA,GAAW;IAEtB,MAAM,GAAG;IACT,OAAO;GACT;GACA,MAAM,QAAQ,OAAO,WAAW,IAAI,IAAA;GACpC,IAAI,QAAQ,KAAK;IAAE;IAAK;IAAM;GAAM,CAAC;GACrC,IAAI,SAAS;GACb,cAAc;GACd,OAAO,IAAI,QAAQ,SAAS,IAAI,OAAO,cAAe,IAAI,QAAQ,YAAY,IAAI,QAAQ,SAAS,IAAI,OAAO,GAC5G,WAAW,GAAG;GAChB,KAAK,MAAM,CAAC,IAAI,UAAU,MAAM;IAC9B,IAAI,cAAc,iBAAiB,OAAO,WACxC;IACF,OAAO,IAAI,OAAO,IAAI;GACxB;GACA,OAAO;EACT;EACA,OAAO,WAAW,UAAU;GAC1B,MAAM,MAAM,KAAK,IAAI,SAAS;GAC9B,IAAI,CAAC,KAAK;IACR,MAAM,OAAO,UAAU,IAAI,SAAS;IACpC,OAAO,MAAM,WAAW,aAAa,KAAK,OAAO,IAAI,CAAC,IAAI;GAC5D;GACA,IAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW,GAChD,OAAO;GACT,MAAM,OAAO,IAAI,OAAO;GACxB,IAAI,WAAW,QAAQ,WAAW,GAChC,OAAO;GACT,IAAI,aAAa,MACf,OAAO,CAAC;GACV,MAAM,QAAQ,IAAI,QAAQ,IAAI,KAAK,EAAE;GACrC,IAAI,UAAU,KAAA,KAAa,QAAQ,WAAW,GAC5C,OAAO;GACT,MAAM,MAAyB,CAAC;GAChC,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,QAAQ,QAAQ,KAAK;IAClD,MAAM,QAAQ,IAAI,QAAQ;IAC1B,IAAI,MAAM,MAAM,UACd,IAAI,KAAK;KAAE,KAAK,MAAM;KAAK,QAAQ,KAAK,MAAM,MAAM,IAAI;IAAgB,CAAC;GAC7E;GACA,OAAO;EACT;EACA,OAAO,WAAW;GAChB,MAAM,MAAM,KAAK,IAAI,SAAS;GAC9B,IAAI,KAAK;IACP,OAAO,WAAW,KAAK,KAAK;IAC5B;GACF;GACA,MAAM,UAAU,UAAU,IAAI,SAAS;GACvC,IAAI,SAAS;IACX,UAAU,OAAO,SAAS;IAC1B,UAAU,IAAI,WAAW;KAAE,MAAM,QAAQ;KAAM,SAAS;IAAM,CAAC;GACjE;EACF;EACA,oBAAoB,KAAK,OAAO,UAAU;CAC5C;AACF;;;;;;;;;;;;ACvMA,MAAM,kBAAkB;;AAOxB,MAAM,mBAAmB;;AAEzB,MAAM,8BAAc,IAAI,IAAI,CAAC,cAAc,CAAC;;AAG5C,SAAS,gBAAgB,MAAsB;CAC7C,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,4BAA4B;CAC9C,IAAI,QAAQ,SAAS,KACnB,MAAM,IAAI,MAAM,+BAA+B;CAEjD,IAAI,qBAAqB,KAAK,OAAO,GACnC,MAAM,IAAI,MAAM,gEAA4D;CAC9E,IAAI,QAAQ,WAAW,GAAG,GACxB,MAAM,IAAI,MAAM,wCAAwC;CAC1D,OAAO;AACT;;AAGA,SAAS,WAAW,OAAmB,OAAe,OAAuB;CAC3E,MAAM,OAAO,MAAM,KAAK,YAAY;CAEpC,QADa,SAAS,QAAQ,IAAI,KAAK,WAAW,KAAK,IAAI,IAAI,KACjD,MAAM;AACtB;AAiBA,SAAgB,qBAAqB,aAAmD;CACtF,MAAM,EAAE,UAAU,OAAO,kBAAkB;CAC3C,OAAO;EACL,iBAAiB;GAAE,OAAO,CAAC,GAAG,KAAK;GAAG;EAAS;EAC/C;EACA,aAAa,YAAY;EACzB,eAAe,YAAY;EAC3B,KAAK,MAAM;GACT,MAAM,MAAM,cAAc,QAAQ,MAAM,EAAG;GAC3C,MAAM,UAAwB,CAAC;GAC/B,IAAI,YAAY;GAChB,MAAM,QAAQ,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,CAAC,CACpD,QAAO,MAAK,CAAC,EAAE,KAAK,WAAW,GAAG,MAAM,EAAE,YAAY,KAAK,EAAE,eAAe,EAAE,CAAC,CAC/E,KAAI,MAAK,EAAE,IAAI,CAAC,CAChB,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;GACpC,KAAK,MAAM,QAAQ,OAAO;IACxB,IAAI;IACJ,IAAI;KAEF,OAAO,aAAa,OAAO,KAAK,KAAK,IAAI,CAAC;KAC1C,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,YAAY,GAC9B;IACJ,QACM;KACJ;IACF;IAEA,IAAI,CAAC,MAAM,MAAK,SAAQ,SAAS,MAAM,IAAI,CAAC,GAC1C;IACF,IAAI,QAAQ,UAAU,iBAAiB;KACrC,YAAY;KACZ;IACF;IACA,QAAQ,KAAK;KAAE;KAAM,MAAM;KAAM,WAAW,WAAW,KAAK,MAAM,MAAM,CAAC;IAAE,CAAC;GAC9E;GACA,MAAM,SAAS,MAAM,SAAS,GAAG;GACjC,OAAO;IAAE,OAAO,CAAC,GAAG,KAAK;IAAG,MAAM;IAAK,QAAQ,SAAS,OAAO,QAAQ,GAAG;IAAG;IAAS,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG;EAC5H;EACA,MAAM,QAAQ,MAAM;GAClB,MAAM,MAAM,cAAc,MAAM;GAChC,MAAM,SAAS,gBAAgB,IAAI;GACnC,MAAM,SAAS,KAAK,KAAK,MAAM;GAC/B,IAAI;IACF,UAAU,MAAM;GAClB,SACO,KAAK;IACV,IAAK,IAA8B,SAAS,UAC1C,MAAM,IAAI,MAAM,GAAG,OAAO,qBAAqB,IAAI,EAAE;IACvD,MAAM;GACR;GACA,OAAO;IAAE,MAAM;IAAQ,MAAM,aAAa,OAAO,MAAM;IAAG,WAAW;GAAM;EAC7E;EACA,MAAM,OAAO,OAAO,MAAM;GACxB,MAAM,SAAS,MAAM,KAAK,CAAC,CAAC,YAAY;GACxC,IAAI,CAAC,QACH,OAAO,EAAE,SAAS,CAAC,EAAE;GACvB,MAAM,SAAS,SAAS,KAAA,IAAY,CAAC,GAAG,KAAK,IAAI,CAAC,cAAc,IAAI,CAAC;GACrE,MAAM,QAAgD,CAAC;GACvD,MAAM,uBAAO,IAAI,IAAY;GAC7B,IAAI,QAAQ;GACZ,IAAI,YAAY;GAEhB,IAAI,QAAQ,OAAO,KAAI,SAAQ;IAAE;IAAK,OAAO;GAAE,EAAE;GACjD,OAAO,MAAM,SAAS,GAAG;IACvB,MAAM,OAAqB,CAAC;IAC5B,KAAK,MAAM,EAAE,KAAK,WAAW,OAAO;KAClC,IAAI,SAAS,kBAAkB;MAC7B,YAAY;MACZ;KACF;KACA;KACA,IAAI;KACJ,IAAI;MACF,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;KACtD,QACM;MACJ;KACF;KAEA,KAAK,MAAM,UAAU,SAAS;MAC5B,IAAI,CAAC,OAAO,YAAY,KAAK,OAAO,KAAK,WAAW,GAAG,KAAK,YAAY,IAAI,OAAO,IAAI,GACrF;MACF,MAAM,QAAQ,KAAK,KAAK,OAAO,IAAI;MACnC,IAAI,KAAK,IAAI,KAAK,GAChB;MACF,KAAK,IAAI,KAAK;MACd,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,GAC3C,MAAM,KAAK;OAAE,OAAO;QAAE,MAAM,OAAO;QAAM,MAAM;QAAO,WAAW,WAAW,KAAK,OAAO,MAAM,CAAC;OAAE;OAAG;MAAM,CAAC;MAC7G,IAAI,QAAQ,IAAA,GACV,KAAK,KAAK;OAAE,KAAK;OAAO,OAAO,QAAQ;MAAE,CAAC;KAC9C;IACF;IACA,IAAI,SAAS,kBAAkB;KAC7B,IAAI,KAAK,SAAS,GAChB,YAAY;KACd;IACF;IACA,QAAQ;GACV;GACA,MAAM,MAAM,GAAG,MAAM,WAAW,EAAE,OAAO,QAAQ,EAAE,KAAK,IAAI,WAAW,EAAE,OAAO,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,KAAK,cAAc,EAAE,MAAM,IAAI,CAAC;GAC5I,IAAI,MAAM,SAAA,KACR,YAAY;GAEd,OAAO;IAAE,SADO,MAAM,MAAM,GAAA,GAAqB,CAAC,CAAC,KAAI,MAAK,EAAE,KAC/C;IAAG,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG;EACxD;CACF;AACF;;;;ACnEA,MAAM,sBAA2C,IAAI,IAAI,OAAO,OAAO,gBAAgB,CAAC;;AAExF,MAAM,2CAAgD,IAAI,IAAI;CAAC;CAAyB;CAA0B;CAAkB;AAAuB,CAAC;;AA2F5J,SAAS,kBAAkB,SAA6C;CACtE,MAAM,cAAuB,SAAS,MAAM,KAAK;CACjD,MAAM,sBAA+B,SAAS,cAAc,KAAK;CACjE,OAAO;EAAE;EAAO;EAAe,cAAc;GAAE,OAAO,MAAM;GAAG,eAAe,cAAc;EAAE;CAAG;AACnG;;AAGA,SAAS,aAAqB;CAC5B,IAAI;EACF,OAAO,aAAa,QAAQ,CAAC;CAC/B,QACM;EACJ,OAAO,QAAQ;CACjB;AACF;;AAGA,SAAS,WAAW,SAAgC,cAAuB,QAA0E;CACnJ,OAAO;EACL,GAAI,eAAe,EAAE,cAAc,KAAK,IAAI,CAAC;EAC7C,GAAI,sBAAsB,QAAQ,cAAc,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;EAChF,GAAG;EACH,GAAI,QAAQ,OAAO;GAAE,MAAM;GAAM,gBAAgB,CAAC,GAAG,eAAe;EAAE,IAAI,CAAC;CAC7E;AACF;;;;;;AAmCA,SAAS,cAAc,QAAgB,MAAgB,aAAgF;CACrI,IAAI,CAAC,KAAK,OACR,OAAO,KAAA;CACT,MAAM,WAAW,YAAY,MAAM,KAAK;CACxC,IAAI,YAAY,KAAK,OAAO,QAAQ,GAClC,OAAO,KAAA;CACT,cAAc,MAAM,QAAQ,QAAQ;CACpC,OAAO;EACL,IAAI;EACJ,MAAM,aAAa;EACnB,SAAS,IAAI,OAAO,UAAU,aAAa,SAAS,MAAM,KAAK,GAAG,SAAS,qCAAqC,KAAK,MAAM;EAC3H,MAAM;GAAE;GAAU,SAAS,KAAK;EAAM;CACxC;AACF;;;;;;AAOA,SAAS,gBAAgB,MAAgB,YAAoB,SAAmI;CAC9L,KAAK,kBAAkB;CACvB,MAAM,UAAW,OAAO,KAAK,aAAa,CAAC,CACxC,QAAO,WAAU,QAAQ,MAAM,MAAM,CAAC,KAAK,SAAS,YAAY,KAAK,OAAO,cAAc,OAAO,EAAE;CACtG,OAAO;EAAE,oBAAA;EAA8C,2BAA2B;EAAY,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;EAAI;CAAQ;AACtJ;;AAGA,MAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;;;;;AAMtD,SAAgB,qBAAqB,KAAuB;CAC1D,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;CACrD,MAAM,UAAU,gCAAgC,KAAK,OAAO,CAAC,GAAG;CAEhE,OAAO,YAAY,KAAA,MAAc,aAAa,KAAK,OAAO,KAAK,QAAQ,WAAW,GAAG,QAAQ,EAAE;AACjG;AAEA,MAAa,yBAAyB;;AAGtC,SAAS,eAAe,KAAc,WAAiD;CAErF,IAAI,qBAAqB,GAAG,GAAG;EAC7B,UAAU,eAAe;EACzB,OAAO;GAAE,IAAI;GAAO,MAAM,aAAa;GAAe,SAAS;EAAuB;CACxF;CACA,IAAI,eAAe,oBACjB,OAAO;EAAE,IAAI;EAAO,MAAA;EAAkC,SAAS,IAAI;CAAQ;CAE7E,MAAM,OAAQ,KAAmC;CACjD,IAAI,OAAO,SAAS,YAAY,oBAAoB,IAAI,IAAI,GAC1D,OAAO;EAAE,IAAI;EAAO;EAAM,SAAU,IAAc;CAAQ;CAG5D,IAAI,SAAS,aAAa,aAAa,SAAS,aAAa,eAAe;EAC1E,MAAM,OAAQ,IAA2B;EACzC,OAAO;GAAE,IAAI;GAAO;GAAM,SAAU,IAAc;GAAS,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EAAG;CACrG;CACA,OAAO;EAAE,IAAI;EAAO,MAAM,aAAa;EAAe,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;CAAE;AAClH;;;;;;AAOA,SAAS,oBAAoB,MAAgB,MAAgB,aAAkC;CAC7F,KAAK,UAAU,UAAU;CACzB,IAAI,UAAU,SAAS;CACvB,MAAM,eAAqB;EACzB,IAAI,SACF;EACF,UAAU;EACV,KAAU,cAAc,CAAC,CAAC,YAAY,KAAA,CAAS;CACjD;CACA,IAAI,CAAC,aACH,OAAO;CACT,OAAO;AACT;AAEA,eAAsB,qBAAqB,SAAyD;CAClG,MAAM,EAAE,YAAY,WAAW,cAAc;CAE7C,MAAM,YAAY,gBAAgB,QAAQ,MAAM;CAEhD,MAAM,cAAc,0BAA0B;CAC9C,IAAI;CAEJ,MAAM,QAAQ,mBAAmB,EAAE,WAAW,QAAQ,SAAS;EAC7D,YAAY,QAAQ,MAAM;EAC1B,eAAe,QAAQ,MAAM;EAC7B,OAAO,UAAU,OAAO,QAAQ,IAAI;CACtC,EAAE,CAAC;CACH,MAAM,QAAQ,YAAY,KAAK;CAC/B,MAAM,EAAE,WAAW,oBAAoB;CAEvC,MAAM,MAAM,OAAO,QAAQ,oBACvB,QAAQ,kBAAkB,SAAS,IACnC,wBAAwB,EAAE,UAAU,CAAC;CAEzC,MAAM,WAAW,oBAAoB,IAAI,YAAY,GAAG,QAAQ,YAAY,EAAE,MAAM,SAAS,CAAC;CAC9F,MAAM,OAAO,eAAe,SAAS,KAAK;EAAE,GAAG;EAAK,QAAQ,SAAS;CAAG,IAAI,GAAG;CAC/E,MAAM,SAAS,IAAI;CAEnB,IAAI,wBAAuB,QAAO,KAAK,gBAAgB,GAAG,CAAC;CAE3D,MAAM,QAAQ,IAAI;CAClB,gBAAgB,sBAAsB;EAAE;EAAM;EAAO,SAAS,MAAM;CAAQ,CAAC;CAE7E,MAAM,iBAAiB;EAAE,GAAI,SAAS,KAAK,EAAE,QAAQ,SAAS,GAAG,IAAI,CAAC;EAAI,UAAU,SAAS;EAAM,UAAU,SAAS;EAAM,SAAS,WAAW;CAAE;CAGlJ,MAAM,YAAY,qBAAqB,KAAK,SAAS;CACrD,MAAM,SAAS,oBAAoB,EAAE,gBAAgB,CAAC;CACtD,MAAM,UAAU,sBAAsB;EAAE;EAAK;CAAgB,CAAC;CAC9D,MAAM,kBAAkB,6BAA6B,EAAE,KAAK,CAAC;CAC7D,MAAM,UAAU,sBAAsB,EAAE,KAAK,CAAC;CAC9C,MAAM,WAAW,uBAAuB;EAAE;EAAM,aAAa,MAAM;CAAI,CAAC;CAExE,MAAM,mBAAmB,SAAS,SAAS;CAE3C,MAAM,cAAc,qBAAqB,kCAAkC;EAAE;EAAM,aAAa,MAAM;CAAI,CAAC,GAAG;EAAE;EAAM,aAAa,MAAM;CAAI,CAAC;CAC9I,MAAM,OAAO,mBAAmB;EAAE;EAAM;CAAI,CAAC;CAC7C,MAAM,YAAY,uBAAuB;EAAE,eAAe,IAAI,YAAY;EAAG,aAAa,IAAI,qBAAqB,KAAK,6BAA6B,IAAI,YAAY,CAAC;EAAG,gBAAgB,UAAU;GAAE,MAAM;GAAmB,SAAS;EAAO,CAAC;EAAG,uBAAsB,SAAQ,KAAK,WAAW,OAAO,IAAI;CAAE,CAAC;CAC9S,MAAM,QAAQ,wBAAwB;EAAE;EAAM;EAAK;EAAM;EAAW,aAAa,MAAM;EAAK,gBAAgB,QAAQ,kBAAkB;EAAM,GAAI,QAAQ,mBAAmB,KAAA,IAAY,EAAE,OAAO,QAAQ,eAAe,IAAI,CAAC;CAAG,CAAC;CAChO,MAAM,WAAW,uBAAuB;EAAE;EAAM;EAAK;EAAW,SAAS,MAAM;CAAQ,CAAC;CACxF,MAAM,WAAW,6BAA6B;EAAE;EAAM;EAAK;EAAW,cAAa,UAAS,SAAS,eAAe,CAAC,EAAE,MAAM,GAAG,IAA2B;EAAG,GAAI,QAAQ,iBAAiB,EAAE,SAAS,QAAQ,eAAe,IAAI,CAAC;CAAG,CAAC;CACtO,MAAM,eAAe,mBAAmB,EAAE,KAAK,CAAC;CAehD,MAAM,EAAE,eAAe,GAAG,gBAdb,mBAAmB;EAC9B;EACA;EACA;EACA;EACA,SAAS;GACP,cAAa,UAAS,SAAS,eAAe,CAAC,EAAE,MAAM,GAAG,IAA2B;GACrF,UAAU,GAAG,SAAS,SAAS,kBAAkB,CAAC,GAAG,IAAI;GACzD,YAAY,GAAG,SAAS,SAAS,aAAa,CAAC,GAAG,IAAI;GACtD,YAAY,GAAG,SAAS,SAAS,aAAa,CAAC,GAAG,IAAI;GACtD,YAAW,MAAK,aAAa,iBAAiB,CAAC,GAAG,IAA2B;EAC/E;EACA,GAAI,QAAQ,OAAO,EAAE,SAAS,QAAQ,KAAK,IAAI,CAAC;CAClD,CAC6C;CAC7C,MAAM,gBAAgB,oBAAoB,IAAI;CAC9C,MAAM,SAAS,kBAAkB,QAAQ,eAAe;CACxD,MAAM,eAAe,2BAA2B;EAAE;EAAM,eAAe,IAAI,YAAY;EAAG,UAAU,SAAS;EAAM,gBAAgB,IAAI,aAAa;EAAG,aAAa,MAAM;EAAK,GAAI,QAAQ,eAAe,EAAE,SAAS,QAAQ,aAAa,IAAI,CAAC;CAAG,CAAC;CAGnP,KAAK,MAAM,WAAW;EAAC,QAAQ;EAAa,SAAS;EAAa,gBAAgB;EAAa,aAAa;EAAa,YAAY;EAAa,MAAM;CAAW,GACjK,MAAM,QAAQ,OAAO;CAEvB,MAAM,iBAAiB,cAA4B;EAEjD,KAAK,MAAM,UAAU;GAAC,OAAO;GAAQ,gBAAgB;GAAQ,QAAQ;GAAQ,UAAU;GAAQ,YAAY;GAAQ,cAAe;EAAM,GACtI,OAAO,SAAS;CACpB;CAOA,MAAM,UAAU;EACd,GAAG,mBAAmB;GAAE;GAAM,YAAY,OAAO;GAAY,OAAO,aAAa,KAAK;GAAG,YAAY,KAAK;EAAgB,CAAC;EAC3H,GAAG,oBAAoB;GAAE;GAAM,YAAY,OAAO;GAAY,OAAO,aAAa,KAAK;GAAG,YAAY,KAAK;EAAgB,CAAC;EAC5H,GAAG,OAAO;EACV,GAAG,QAAQ;EACX,GAAG,gBAAgB;EACnB,GAAG,sBAAsB;GAAE;GAAM;GAAO;GAAW;GAAe,QAAQ,SAAS;GAAI;EAAU,CAAC;EAClG,GAAG,oBAAoB;GAAE;GAAM;EAAU,CAAC;EAC1C,GAAG,0BAA0B;GAAE;GAAM;GAAO,WAAW,YAAY;EAAQ,CAAC;EAC5E,GAAG,yBAAyB;GAAE;GAAM;GAAO;GAAW,OAAO;EAAY,CAAC;EAC1E,GAAG,qBAAqB,EAAE,KAAK,UAAU,CAAC;EAC1C,GAAG,sBAAsB,EAAE,KAAK,CAAC;EACjC,GAAG,0BAA0B;GAAE;GAAM;GAAK,aAAa,SAAS;EAAgB,CAAC;EACjF,GAAG,wBAAwB,EAAE,KAAK,CAAC;EACnC,GAAG,YAAY;EACf,GAAG,kBAAkB;GAAE;GAAM;GAAO;GAAW,aAAa,MAAM;GAAK,SAAS,MAAM;GAAS,OAAO,OAAO;EAAM,CAAC;EACpH,GAAG,oBAAoB;GAAE;GAAW,SAAS,MAAM;GAAS,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAAG,CAAC;EAChH,GAAG,iBAAiB;GAAE;GAAW,oBAAoB,KAAK,iBAAiB,IAAI,KAAA,GAAW,EAAE,aAAa,KAAK,CAAC;GAAG,eAAe,OAAO;GAAe,eAAe;IAAE,gBAAgB,sBAAsB,QAAQ,cAAc;IAAG,WAAW,aAAa,QAAQ;IAAG,MAAM,QAAQ,QAAQ,IAAI;IAAG,GAAG,OAAO,MAAM;GAAE;EAAG,CAAC;EAC7T,GAAG;EACH,GAAG,MAAM;EACT,GAAG;EACH,GAAG,sBAAsB;GAAE;GAAK;GAAM;EAAU,CAAC;EACjD,GAAG,0BAA0B,EAAE,IAAI,CAAC;EACpC,GAAG,0BAA0B;GAAE;GAAM;GAAK,SAAS,MAAM;GAAS;EAAgB,CAAC;EACnF,GAAG,oBAAoB;GAAE;GAAM;GAAK;GAAO,SAAS,MAAM;EAAQ,CAAC;EACnE,GAAG,yBAAyB;GAAE;GAAM;GAAK;GAAW,GAAI,QAAQ,iBAAiB,EAAE,UAAU,QAAQ,eAAe,IAAI,CAAC;EAAG,CAAC;EAC7H,GAAG,uBAAuB;GAAE;GAAO;GAAW;GAAK;EAAK,CAAC;EACzD,GAAG,oBAAoB;GAAE;GAAO,MAAM,YAAY;GAAO,eAAe,IAAI,YAAY;GAAG,iBAAiB,IAAI,OAAO;EAAU,CAAC;EAClI,GAAG,cAAc;EACjB,GAAG,mBAAmB;GAAE;GAAM;EAAM,CAAC;EACrC,GAAG,4BAA4B,EAAE,KAAK,CAAC;EACvC,GAAG,mBAAmB;GAAE;GAAM;GAAO,mBAAmB,IAAI,YAAY;EAAE,CAAC;EAC3E,GAAG,QAAQ;EACX,GAAG,SAAS;EACZ,GAAG;EACH,GAAG,uBAAuB;GAAE;GAAK;EAAM,CAAC;EACxC,GAAG,sBAAsB;GAAE;GAAM;EAAU,CAAC;EAC5C,GAAG,aAAa;EAChB,GAAG,0BAA0B;GAAE;GAAM;GAAK;GAAW,QAAQ,SAAS;GAAI,QAAQ,SAAS,SAAS;GAAU;GAAY,GAAI,QAAQ,eAAe,EAAE,QAAQ,QAAQ,aAAa,IAAI,CAAC;EAAG,CAAC;EAC7L,GAAG,mBAAmB;GAAE,MAAM,aAAa;IAAE,MAAM,SAAS;IAAM;IAAM;GAAM,CAAC;GAAG,aAAa,MAAM;GAAS,YAAY,MAAM;EAAQ,CAAC;EACzI,GAAG,qBAAqB;GAAE;GAAW,SAAS,MAAM;GAAS,aAAa,MAAM;GAAS,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;GAAI,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GAAI,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EAAG,CAAC;EACxP,GAAG,qBAAqB;GAAE;GAAM;GAAY;GAAW;GAAW,UAAU;EAAe,CAAC;EAC5F,GAAG;EAEH,GAAI,QAAQ,OACR,kBAAkB;GAChB,gBAAgB,SAAS;GACzB,cAAc,SAAS;GACvB,cAAc,SAAS;GACvB,kBAAkB,SAAS;GAC3B,kBAAkB,SAAS;GAC3B,GAAG;EACL,GAAG;GAAE,oBAAoB,IAAI,aAAa;GAAG;EAAc,CAAC,IAC5D,CAAC;CACP;;;;;;;CAQA,MAAM,cAAc,WAClB,OAAO,OAAO,SAAS,MAAM,MAAM,oBAAoB,CAAC,yBAAyB,IAAI,MAAM,KACtF,QAAkF,UACnF,KAAA;CAEN,SAAS,MAAM,QAA8B,MAAiC;EAC5E,MAAM,UAAU,cAAc,QAAQ;GAAE,SAAS;GAAc,aAAa;GAAgB,eAAe,KAAK,cAAc;GAAG,UAAU,SAAS;EAAK,CAAC;EAC1J,IAAI,CAAC,QAAQ,QACX,OAAO;GACL,IAAI;GACJ,MAAM,aAAa;GACnB,SAAS,QAAQ;GACjB,MAAM,EAAE,QAAQ;IAAE,iBAAA;IAAuC;IAAY,KAAK,QAAQ;IAAK;IAAW,SAAS;IAAc,aAAa;IAAgB,GAAG;GAAe,EAAE;EAC5K;EAEF,IAAI,QAAQ,QACV,UAAU,eAAe;EAC3B,KAAK,QAAQ;EAeb,OAAO;GAAE,IAAI;GAAM,QAAA;IAbjB,iBAAA;IACA,GAAG,gBAAgB,MAAM,QAAQ,kBAAiB,WAAU,WAAW,MAAM,MAAM,KAAA,CAAS;IAC5F;IACA,KAAK,QAAQ;IACb;IACA,SAAS;IACT,aAAa;IACb,GAAG;IACH,aAAa,UAAU;IACvB,GAAI,UAAU,WAAW,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACnD,GAAG,WAAW,SAAS,aAAa,QAAQ,GAAG,OAAO,MAAM,CAAC;IAC7D,GAAI,mBAAmB,EAAE,kBAAkB,KAAK,IAAI,CAAC;GAE/B;EAAE;CAC5B;CAEA,eAAe,MAAM,QAAgB,QAAiB,MAA0C;EAE9F,IAAI,WAAA,UACF,OAAO;GAAE,IAAI;GAAM,QAAQ,CAAC;EAAE;EAChC,IAAI,WAAW,aACb,OAAO,MAAO,UAAU,CAAC,GAA4B,IAAI;EAQ3D,IAAI,CAAC,KAAK,SAAS,WAAW,qBAAqB,WAAW,eAC5D,OAAO;GAAE,IAAI;GAAO,MAAM,aAAa;GAAe,SAAS;EAA4C;EAE7G,MAAM,YAAY,cAAc,QAAQ,MAAM,QAAQ,WAAW;EACjE,IAAI,WACF,OAAO;EAET,MAAM,UAAU,WAAW,MAAM;EACjC,IAAI,CAAC,WAAW,OAAO,WAAW,UAAU,GAC1C,OAAO;GAAE,IAAI;GAAO,MAAM,iBAAiB;GAAkB,SAAS,IAAI,OAAO;EAAqF;EACxK,IAAI,CAAC,SACH,OAAO;GAAE,IAAI;GAAO,MAAA;GAAmC,SAAS,mBAAmB,OAAO;EAAI;EAEhG,IAAI;GACF,YAAY,MAAM;GAClB,OAAO;IAAE,IAAI;IAAM,QAAS,MAAM,cAAc,MAAM,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,IAAI,CAAC,KAAM;GAAK;EACpH,SACO,KAAK;GACV,OAAO,eAAe,KAAK,SAAS;EACtC;CACF;CAEA,OAAO;EACL;EACA,SAAS,MAAM;EACf,YAAY,MAAM;EAClB,WAAW,MAAM;EACjB,WAAW,MAAM;EAEjB,oBAAoB,oBAAoB,MAAM,SAAS,MAAM,QAAQ,gBAAgB,IAAI;EAEzF,cAAc,QAAQ,QAAQ,MAAM;GAElC,MAAM,MAAM;GACZ,OAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,CAAC,QAAQ,MAAM,KAAK;EACxD;EAUA,MAAM,mBAAmB,QAAQ,QAAQ,MAAM;GAC7C,IAAI,CAAC,KAAK,OACR;GACF,IAAI,cAAc,QAAQ,MAAM,QAAQ,WAAW,GACjD;GACF,MAAM,UAAU,WAAW,MAAM;GACjC,IAAI,CAAC,SACH;GACF,IAAI;IACF,YAAY,MAAM;IAClB,MAAM,cAAc,MAAM,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,IAAI,CAAC;GAC7E,QACM,CAEN;EACF;EACA,mBAAmB,cAAc;EACjC,sBAAsB,MAAM;CAC9B;AACF;;;;ACvjBA,MAAa,6BAA6B;;;;;;;;AAqD1C,SAAgB,gBAAgB,MAAiE;CAC/F,OAAO,CAAC,KAAK,cAAc,KAAK,KAAK,aAAa,KAAK,CAAC,CAAC,WAAW;AACtE;;;;;;AAOA,SAAgB,wBAAwB,UAAoD;CAC1F,IAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,KAAK,UAAU,0BAA0B,GAAG,MAAM,CAAC;EACvF,IAAI,OAAO,IAAI,SAAS,YAAY,OAAO,IAAI,OAAO,YAAY,OAAO,IAAI,OAAO,UAClF,OAAO;GAAE,MAAM,IAAI;GAAM,IAAI,IAAI;GAAI,IAAI,IAAI;EAAG;EAClD,OAAO;CACT,QACM;EACJ,OAAO;CACT;AACF;AAEA,SAAS,yBAAyB,UAAkB,QAAyC;CAC3F,IAAI;EACF,oBAAoB,KAAK,UAAU,0BAA0B,GAAG,QAAQ,EAAE,WAAW,KAAK,CAAC;CAC7F,QACM,CAEN;AACF;;;;;;;AAQA,SAAgB,kBAAkB,SAAsD;CACtF,MAAM,MAAM,QAAQ,cAAc,KAAA;CAClC,MAAM,MAAM,QAAQ,OAAO,KAAK;CAChC,IAAI,UAAyB;CAC7B,IAAI;CACJ,IAAI,SAAS;CACb,IAAI,UAA0C;CAE9C,MAAM,WAAW,UAAuC;EACtD,IAAI,UAAU,WAAW,CAAC,MAAM,mBAAmB,CAAC,MAAM,WACxD;EACF,MAAM,QAAQ,wBAAwB,QAAQ,QAAQ;EACtD,IAAI,SAAS,MAAM,SAAS,QAAQ,kBAAkB,MAAM,OAAO,MAAM,WAAW;GAClF,IAAI,uBAAuB,MAAM,UAAU,mDAAmD,QAAQ,eAAe,aAAa;GAClI;EACF;EACA,UAAU,MAAM;EAChB,IAAI,uBAAuB,QAAQ,oCAAoC;EACvE,QAAQ,YAAY,OAAO;EAC3B,IAAI,YAAY;EAChB,YAAY,kBAAkB;GAE5B,IAAI,CAAC,QAAQ,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,YAAY;IACtD,YAAY;IACZ;GACF;GACA,aAAa;GACb,IAAI,YAAY,GACd;GACF,cAAc,SAAS;GACvB,YAAY,KAAA;GACZ,yBAAyB,QAAQ,UAAU;IAAE,MAAM,QAAQ;IAAgB,IAAI;IAAU,IAAI,IAAI;GAAE,CAAC;GACpG,IAAI,4CAA4C,SAAS;GACzD,QAAQ,OAAO;EACjB,GAAG,QAAQ,cAAc,GAAI;EAE7B,IAAI,OAAO,cAAc,YAAY,WAAW,WAC9C,UAAU,MAAM;CACpB;CAEA,WAAW,QAAQ,SAAS,sBAAA,CAAuB;EACjD,MAAM,QAAQ;EACd,gBAAgB,QAAQ;EACxB,UAAU,QAAQ;EAClB,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACjE,UAAU;CACZ,CAAC;CACD,QAAQ,QAAQ,QAAQ,CAAC;CAEzB,OAAO;EACL,eAAe;EACf,aAAa;GACX,SAAS;GACT,cAAc,SAAS;GACvB,SAAS,MAAM;EACjB;CACF;AACF;;;;;;;;;AC9EA,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;AAuC/B,eAAsB,eAAe,SAA+C;CAClF,MAAM,EAAE,eAAe;CACvB,MAAM,MAAM,QAAQ,gBAAgB,KAAA;CACpC,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,cAAc,QAAQ,oBAAA;CAC5B,MAAM,aAAa,QAAQ,mBAAmB;CAE9C,MAAM,8BAAc,IAAI,IAAsB;CAC9C,IAAI;CAEJ,IAAI,WAAW;;CAEf,IAAI,gBAAgB;CACpB,IAAI;CAEJ,MAAM,SAAS,QAAQ;CACvB,MAAM,aAAa,UAAU,MAAM,qBAAqB;EACtD,GAAI,QAAQ,oBAAoB,EAAE,mBAAmB,QAAQ,kBAAkB,IAAI,CAAC;EACpF;EACA;EACA,UAAU,EAAE,MAAM,SAAS;EAC3B,GAAI,QAAQ,cAAc,EAAE,aAAa,KAAK,IAAI,CAAC;EACnD,WAAW;GACT,gBAAgB;IACd,MAAW,CAAC,CAAC,WAAW,QAAQ,SAAS,CAAC;GAC5C;GACA;GACA,kBAAkB,YAAY;EAChC;CACF,CAAC;CACD,MAAM,OAAO,WAAW;CAcxB,SAAS,iBAAuB;EAC9B,IAAI,UACF;EACF,WAAW;EACX,IAAI,mEAAmE;EACvE,IAAI,YAAY;EAChB,cAAc,kBAAkB;GAC9B,IAAI,KAAK,cAAc,GAAG;IACxB,YAAY;IACZ;GACF;GACA,aAAa;GACb,IAAI,YAAY,GACd;GACF,cAAc,WAAW;GACzB,MAAW,CAAC,CAAC,WAAW,QAAQ,SAAS,CAAC;EAC5C,GAAG,GAAI;CACT;CAGA,MAAM,UAAU,QAAQ,eAAe,CAAC,SACpC,kBAAkB;EAAE,GAAG,QAAQ;EAAa,cAAc,gBAAgB,IAAI;EAAG,iBAAiB;GAAE,gBAAgB;EAAK;EAAG,cAAc,KAAK,MAAM,CAAC,CAAC,WAAW,QAAQ,SAAS,CAAC;EAAG;CAAI,CAAC,IAC5L;CAEJ,SAAS,eAAqB;EAC5B,IAAI,UAAU,CAAC,QAAQ,kBAAkB,CAAC,QAAQ,QAChD;EACF,aAAa,SAAS;EACtB,YAAY,iBAAiB;GAC3B,IAAI,WAAW,UAAU,IAAI,GAC3B;GAKF,IAAI,KAAK,cAAc,GAAG;IACxB,aAAa;IACb;GACF;GACA,QAAQ,SAAS;EACnB,GAAG,QAAQ,cAAc;CAC3B;CAEA,SAAS,iBAAiB,QAAsB;EAE9C,IAAI;EACJ,MAAM,SAAS,kBAAkB,MAAM;EACvC,MAAM,SAAS,eACb;GACE,UAAU,OAAO;GAEjB,QAAQ,SAAS;IACf,OAAO,MAAM,GAAG,KAAK,GAAG;IACxB,OAAO;GACT;EACF,GACA;GACE;GACA;GACA;GACA,OAAO;GACP,QAAQ,QAAQ;IACd,IAAI,+BAA+B,KAAK;IACxC,OAAO,QAAQ;GACjB;EACF,CACF;EACA,MAAM,OAAO,cAAc,EAAE,WAAW,WAAW,CAAC;EAEpD,MAAM,MAAM,wBAAwB;GAClC,OAAO;GACP,QAAQ;GACR,MAAM,OAAO;GACb,GAAG,mBAAmB,YAAY,IAAI;GACtC,UAAS,QAAO,IAAI,4BAA4B,IAAI,SAAS;EAC/D,CAAC;EAED,aAAa;EACb,MAAM,QAA0B;GAAE;GAAQ,YAAY;EAAI;EAC1D,YAAY,IAAI,KAAK;EACrB,WAAW,QAAQ,IAAI;EACvB,IAAI,MAAM;EACV,IAAI,gCAAgC,WAAW,UAAU,EAAE,QAAQ;EAEnE,MAAM,aAAmB;GACvB,IAAI,CAAC,YAAY,OAAO,KAAK,GAC3B;GACF,IAAI,MAAM;GACV,WAAW,WAAW,IAAI;GAC1B,IAAI,mCAAmC,WAAW,UAAU,EAAE,OAAO;GACrE,IAAI,WAAW,UAAU,MAAM,GAC7B,aAAa;EACjB;EAEA,OAAO,GAAG,SAAS,IAAI;EACvB,OAAO,GAAG,SAAS,IAAI;CACzB;CAQA,IAAI,WAAW,UAAU,GAAG;EAC1B,IAAI,MAAM,YAAY,UAAU,GAC9B,MAAM,IAAI,MAAM,2CAA2C,WAAW,EAAE;EAQ1E,IAAI,MAAM,YAAY,UAAU,GAC9B,MAAM,IAAI,MAAM,2CAA2C,WAAW,EAAE;EAC1E,WAAW,UAAU;CACvB;CAcA,MAAM,YAAY,QAAQ,UAAU;CACpC,MAAM,qBAAqB,SAAS,SAAS,MAAM,YAAY,CAAC,WAAW,SAAS;CACpF,UAAU,WAAW;EAAE,WAAW;EAAM,MAAM;CAAM,CAAC;CACrD,IAAI,oBACF,IAAI;EACF,UAAU,WAAW,GAAK;CAC5B,QACM,CAEN;CAGF,MAAM,SAAiB,aAAa,gBAAgB;CACpD,MAAM,IAAI,SAAe,gBAAgB,WAAW;EAClD,OAAO,KAAK,SAAS,MAAM;EAC3B,OAAO,OAAO,kBAAkB;GAC9B,OAAO,IAAI,SAAS,MAAM;GAC1B,eAAe;EACjB,CAAC;CACH,CAAC;CACD,IAAI;EACF,UAAU,YAAY,GAAK;CAC7B,QACM,CAGN;CACA,IAAI,6BAA6B,YAAY;CAI7C,IAAI,iBAAiB;CACrB,aAAa;CAYb,MAAM,aAAa,SAAS,OAAO,iBAAiB,UAAU;CAC9D,IAAI,YACF,CAAM,YAAY;EAChB,IAAI,CAAE,MAAM,YAAY,UAAU,GAChC;EACF,IAAI,0CAA0C,YAAY;EAC1D,IAAI;GACF,MAAM,WAAW,MAAM,iBAAiB;IAAE,YAAY;IAAY,YAAY,GAAG,WAAW;IAAgB,iBAAiB;GAAK,CAAC;GACnI,MAAM,SAAS,QAAQ,mBAAmB,CAAC,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;GACnE,SAAS,MAAM;EACjB,QACM,CAGN;CACF,EAAA,CAAG;CAGL,eAAe,UAAyB;EACtC,aAAa,SAAS;EACtB,cAAc,WAAW;EACzB,SAAS,MAAM;EAEf,IAAI,CAAC,QACH,MAAM,KAAK,MAAM;EAGnB,MAAM,UAAU,IAAI,SAAe,mBAAmB;GACpD,OAAO,YAAY,eAAe,CAAC;EACrC,CAAC;EACD,KAAK,MAAM,EAAE,YAAY,YAAY,aAAa;GAChD,WAAW,MAAM;GACjB,OAAO,QAAQ;EACjB;EACA,YAAY,MAAM;EAClB,IAAI,CAAC,QACH,WAAW,UAAU;EACvB,MAAM;EACN,IAAI,gBAAgB;GAClB,iBAAiB;GACjB,IAAI;IACF,WAAW,UAAU;GACvB,QACM,CAEN;EACF;CACF;CAQA,IAAI,eAAqC;CACzC,SAAS,QAAuB;EAC9B,iBAAiB,QAAQ;EACzB,OAAO;CACT;CAEA,OAAO;EACL;EACA;EACA;EACA,iBAAiB,WAAW,UAAU;EACtC;CACF;AACF;;;;;;;;;;;;;;;;ACpZA,MAAM,YAAY;;AAGlB,MAAM,qBAAqB;AAE3B,SAAS,aAAa,KAAgC;CACpD,IAAI;EACF,MAAM,EAAE,UAAU,SAAS;EAC3B,IAAI,OACF,OAAO;CACX,QACM,CAAC;CACP,OAAO,IAAI,UAAUC,UAAQ,aAAa,WAAW,aAAa;AACpE;AAEA,SAAS,UAAU,QAAoC;CACrD,MAAM,OAAO,OAAO,MAAM,SAAS,CAAC,CAAC;CACrC,IAAI,SAAS,KAAA,GACX,OAAO,KAAA;CAET,MAAM,QAAQ,KAAK,QAAQ,0BAA0B,EAAE;CACvD,KAAK,MAAM,QAAQ,MAAM,MAAM,IAAI,GACjC,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO,KAAK,MAAM,CAAc,KAAK,KAAA;AAG3C;AAWA,MAAM,aAAa,CAAC,QAAQ,YAAY,UAAU,2BAA2B,UAAU,QAAQ;AAE/F,SAAS,gBAAgB,SAA0F;CACjH,MAAM,MAAM,QAAQ,OAAOA,UAAQ;CACnC,OAAO;EACL,QAAQ,QAAQ,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,mBAAG,IAAI,IAAI;GAAC,aAAa,GAAG;GAAG;GAAY;EAAW,CAAC,CAAC;EACnG,SAAS,QAAQ,aAAa;EAC9B,KAAK;GACH,GAAG;GAEH,qBAAqB;GACrB,sBAAsB;GACtB,oBAAoB;EACtB;CACF;AACF;;;;;;;AAQA,SAAgB,UAAU,UAA4B,CAAC,GAAuB;CAC5E,IAAIA,UAAQ,aAAa,SACvB,OAAO,KAAA;CACT,MAAM,EAAE,QAAQ,KAAK,YAAY,gBAAgB,OAAO;CACxD,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,SAAS,UAAU,OAAO,YAAY;GAC1C,UAAU;GACV;GACA,OAAO;IAAC;IAAU;IAAQ;GAAQ;GAClC;EACF,CAAC;EACD,IAAI,OAAO,SAAS,OAAO,WAAW,GACpC;EACF,MAAM,OAAO,UAAU,OAAO,MAAM;EACpC,IAAI,MACF,OAAO;CACX;AAEF;;;;;;;;;;AAWA,eAAsB,eAAe,UAA4B,CAAC,GAAgC;CAChG,IAAIA,UAAQ,aAAa,SACvB,OAAO,KAAA;CACT,MAAM,EAAE,QAAQ,KAAK,YAAY,gBAAgB,OAAO;CACxD,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,MAAM,MAAM,WAAW,OAAO,YAAY;GAAE;GAAK,WAAW;EAAQ,CAAC;EAC3E,IAAI,IAAI,SAAS,GACf;EACF,MAAM,OAAO,UAAU,IAAI,MAAM;EACjC,IAAI,MACF,OAAO;CACX;AAEF;;;;;;;;;;AAWA,SAAgB,UAAU,SAA6B,OAAmC;CACxF,MAAM,SAAS,UAAwC,QAAQ,GAAA,CAAI,MAAM,SAAS,CAAC,CAAC,OAAO,OAAO;CAClG,MAAM,YAAY,MAAM,KAAK;CAC7B,MAAM,QAAQ,IAAI,IAAI,SAAS;CAC/B,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,QAAO,UAAS,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;AAC1G;;AAGA,SAAgB,UAAgB;CAC9B,MAAM,QAAQ,UAAU;CACxB,IAAI,OACF,UAAQ,IAAI,OAAO,UAAUA,UAAQ,IAAI,MAAM,KAAK;AACxD;;;;AChEA,SAAS,KAAQ,OAAa;CAC5B,OAAO,UAAU,KAAA,IAAa,OAAa,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAC7E;;;;;AAaA,eAAe,WAAW,YAA4B,SAAkC,aAAmD;CACzI,MAAM,4BAAY,IAAI,IAAoB;CAC1C,MAAM,0BAAU,IAAI,IAA0B;CAC9C,IAAI,SAAS;CAQb,MAAM,SAA4B,CAAC;CACnC,IAAI,WAAW;CACf,MAAM,WAAW,SAA2B;EAC1C,OAAO,KAAK,IAAI;EAChB,IAAI,UACF;EACF,WAAW;EACX,qBAAqB;GACnB,IAAI;IACF,OAAO,OAAO,SAAS,GACrB,IAAI;KACF,OAAO,MAAM,CAAC,CAAE;IAClB,QACM,CAGN;GAEJ,UACQ;IACN,WAAW;GACb;EACF,CAAC;CACH;CAEA,MAAM,OAAiB;EACrB,OAAO;EACP,UAAU;EACV,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChD,KAAK,QAAQ,KAAK,SAAS;GACzB,IAAI,QACF;GACF,MAAM,OAAO,QAAQ,KAAA,IAAY,KAAA,IAAY,EAAE,IAAI;GACnD,IAAI;GACJ,IAAI;IAEF,MAAM,OAAO,UAAU,QAAQ,KAAK,IAAI,KAAK,UAAU,MAAM;IAC7D,IAAI,SAAS,KAAA,GACX;IACF,OAAO,KAAK,MAAM,IAAI;GACxB,QACM;IAGJ;GACF;GACA,cAAc;IACZ,IAAI,QACF;IACF,KAAK,MAAM,YAAY,WACrB,SAAS,MAAM,IAAI;GACvB,CAAC;EACH;CACF;CAEA,MAAM,WAAW,QAAgB,WAAsC;EACrE,IAAI,QACF,OAAO,QAAQ,OAAO,IAAI,6BAA6B,CAAC;EAC1D,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,QAAQ,IAAI,MAAM;GAClB,MAAM,UAAU,YAA8B;IAC5C,cAAc;KACZ,IAAI,CAAC,QAAQ,OAAO,MAAM,GACxB;KACF,QAAQ;IACV,CAAC;GACH;GACA,WAAW,cAAc,QAAQ,WAAW,KAAA,IAAY,KAAA,IAAY,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,MACrF,WAAW;IACV,aAAa;KAGX,IAAI;MACF,IAAI,OAAO,IACT,QAAQ,KAAK,OAAO,MAAM,CAAC;WAE3B,OAAO,IAAI,mBAAmB,OAAO,SAAS,OAAO,MAAM,OAAO,IAAI,CAAC;KAC3E,SACO,KAAK;MACV,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;KAC5D;IACF,CAAC;GACH,IACA,QAAO,aAAa,OAAO,GAAG,CAAC,CACjC;EACF,CAAC;CACH;;CAGA,MAAM,aAAmB;EACvB,SAAS;EACT,UAAU,MAAM;EAChB,OAAO,SAAS;EAChB,KAAK,MAAM,UAAU,SACnB,OAAO,IAAI,6BAA6B,CAAC;EAC3C,QAAQ,MAAM;CAChB;CAEA,MAAM,aAAyB;EAC7B;EACA,kBAAkB;GAChB,IAAI,QACF;GACF,KAAK;GACL,QAAQ,UAAU;EACpB;CACF;CAEA,WAAW,QAAQ,IAAI;CACvB,aAAa,IAAI,UAAU;CAC3B,MAAM,eAAqB;EACzB,IAAI,QACF;EACF,KAAK;EACL,aAAa,OAAO,UAAU;EAC9B,WAAW,WAAW,IAAI;CAC5B;CAEA,IAAI;CACJ,IAAI;EACF,QAAQ,MAAM,QAAQ,aAAa;GACjC,iBAAA;GACA,YAAY,QAAQ,cAAc;GAClC,KAAK,QAAQ;GACb,SAAS;GACT,aAAa;EACf,CAAC;CACH,SACO,KAAK;EACV,OAAO;EACP,MAAM;CACR;CAEA,OAAO;EACL;EACS;EACT,SAAS,QAAQ,WAAW;GAC1B,IAAI,QACF;GACF,MAAM,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,KAAK,MAAM;GAE3D,qBAAqB;IACnB,IAAI,CAAC,QACH,WAAgB,mBAAmB,QAAQ,MAAM,IAAI;GACzD,CAAC;EACH;EACA,WAAW,aAAa;GACtB,UAAU,IAAI,QAAQ;GACtB,aAAa,UAAU,OAAO,QAAQ;EACxC;EACA,OAAO;CACT;AACF;;;;;;;;;;;;;;;AAgBA,SAAgB,iBAAiB,YAA4B,UAAmC,CAAC,GAAuB;CACtH,OAAO,WAAW,YAAY,OAAO;AACvC;;;;;;AAOA,eAAsB,mBAAmB,SAAuD;CAC9F,MAAM,8BAAc,IAAI,IAAgB;CACxC,IAAI,UAAgC;CAEpC,MAAM,aAAa,MAAM,qBAAqB;EAC5C,mBAAmB,QAAQ;EAC3B,YAAY,QAAQ,cAAc;EAClC,WAAW,KAAK,IAAI;EACpB,UAAU,EAAE,MAAM,aAAa;EAC/B,WAAW;GAET,gBAAgB,KAAA;GAEhB,sBAAsB,KAAA;GACtB,kBAAkB;EACpB;CACF,CAAC;CAED,SAAS,QAAQ,gBAAwC,CAAC,GAAuB;EAC/E,IAAI,SACF,OAAO,QAAQ,OAAO,IAAI,6BAA6B,CAAC;EAC1D,OAAO,WAAW,YAAY,eAAe,WAAW;CAC1D;CAEA,SAAS,QAAuB;EAG9B,aAAa,YAAY;GACvB,MAAM,WAAW,KAAK,MAAM;GAC5B,KAAK,MAAM,cAAc,aACvB,WAAW,WAAW;GACxB,YAAY,MAAM;GAClB,WAAW,UAAU;EACvB,EAAA,CAAG;EACH,OAAO;CACT;CAEA,OAAO;EACL,MAAM,WAAW;EACjB;EACA,iBAAiB,WAAW,UAAU;EACtC;CACF;AACF"}