opensentinel 3.6.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/README.md +12 -0
  2. package/dist/{agent-manager-7N7REQZQ.js → agent-manager-JZ4IM7XI.js} +8 -8
  3. package/dist/{agent-processor-I23VWQY3.js → agent-processor-DDDHC2SO.js} +22 -21
  4. package/dist/{agent-processor-I23VWQY3.js.map → agent-processor-DDDHC2SO.js.map} +1 -1
  5. package/dist/{alerting-4I37GG4U.js → alerting-LK7VVYTX.js} +4 -4
  6. package/dist/alerting-LK7VVYTX.js.map +1 -0
  7. package/dist/analyzer-OTWE3ARE.js +22 -0
  8. package/dist/{archiver-XLRIIXPY.js → archiver-FPGKRP6P.js} +16 -85
  9. package/dist/archiver-FPGKRP6P.js.map +1 -0
  10. package/dist/{audit-logger-AU3TMWKI.js → audit-logger-CI4WZQPD.js} +5 -5
  11. package/dist/bot-VDHBGUVI.js +47 -0
  12. package/dist/{brain-SLA474EU.js → brain-6QTXN4QP.js} +18 -17
  13. package/dist/{chunk-AR34B6XR.js → chunk-2I5QHYG6.js} +3 -3
  14. package/dist/chunk-2I5QHYG6.js.map +1 -0
  15. package/dist/chunk-3AWAWRWB.js +143 -0
  16. package/dist/chunk-3AWAWRWB.js.map +1 -0
  17. package/dist/{chunk-PUNIMPMY.js → chunk-4KIHDIXZ.js} +13 -2
  18. package/dist/chunk-4KIHDIXZ.js.map +1 -0
  19. package/dist/{chunk-GUKKW7JI.js → chunk-4WH6MFEW.js} +2 -2
  20. package/dist/chunk-4WH6MFEW.js.map +1 -0
  21. package/dist/{chunk-M7YLQHFP.js → chunk-56UJS2LA.js} +6 -6
  22. package/dist/{chunk-S4NJJS5C.js → chunk-5BTVJR7R.js} +3 -3
  23. package/dist/{chunk-HKOPRRDJ.js → chunk-5JJTLWOR.js} +3 -3
  24. package/dist/chunk-5JJTLWOR.js.map +1 -0
  25. package/dist/chunk-66SAOZPU.js +236 -0
  26. package/dist/chunk-66SAOZPU.js.map +1 -0
  27. package/dist/chunk-6HGMRR4J.js +113 -0
  28. package/dist/chunk-6HGMRR4J.js.map +1 -0
  29. package/dist/{chunk-BMOUYXLX.js → chunk-6ZNCY2GI.js} +5 -5
  30. package/dist/chunk-7BNFELEK.js +31 -0
  31. package/dist/chunk-7BNFELEK.js.map +1 -0
  32. package/dist/{chunk-KABG5PG3.js → chunk-BBN4VCNK.js} +4 -4
  33. package/dist/chunk-BBN4VCNK.js.map +1 -0
  34. package/dist/{chunk-4YJRBMMA.js → chunk-BNZHWAZC.js} +2 -2
  35. package/dist/{chunk-TAAZB5KN.js → chunk-CWT6CAE5.js} +2 -2
  36. package/dist/{chunk-UWUIJTT4.js → chunk-CZTMGHUC.js} +1 -1
  37. package/dist/chunk-CZTMGHUC.js.map +1 -0
  38. package/dist/chunk-DTISLIMB.js +89 -0
  39. package/dist/chunk-DTISLIMB.js.map +1 -0
  40. package/dist/{chunk-VKMFUIVA.js → chunk-GBVJTRXS.js} +2 -2
  41. package/dist/{chunk-MFK34XSY.js → chunk-GJETKBOY.js} +15 -15
  42. package/dist/chunk-GJETKBOY.js.map +1 -0
  43. package/dist/{chunk-HTF2GIQC.js → chunk-GW6V4D43.js} +2 -2
  44. package/dist/chunk-GW6V4D43.js.map +1 -0
  45. package/dist/{chunk-2RGPWU77.js → chunk-HJSEEFO3.js} +2 -2
  46. package/dist/{chunk-JOA5A3G3.js → chunk-HQZQFEAX.js} +5 -5
  47. package/dist/{chunk-45YXODSB.js → chunk-J4JW73TT.js} +2 -2
  48. package/dist/{chunk-KT7NLIXP.js → chunk-JHYYFPKX.js} +2 -2
  49. package/dist/{chunk-XMCVRVTF.js → chunk-P64EV4YY.js} +1 -1
  50. package/dist/chunk-P64EV4YY.js.map +1 -0
  51. package/dist/chunk-PBOCSGNL.js +84 -0
  52. package/dist/chunk-PBOCSGNL.js.map +1 -0
  53. package/dist/{chunk-H3BOLSTS.js → chunk-PD3CTDO6.js} +2 -2
  54. package/dist/{chunk-6UZPE35A.js → chunk-QPY3WRVM.js} +10 -87
  55. package/dist/chunk-QPY3WRVM.js.map +1 -0
  56. package/dist/{chunk-AD6YEH6U.js → chunk-S2EOIVF4.js} +590 -91
  57. package/dist/chunk-S2EOIVF4.js.map +1 -0
  58. package/dist/chunk-SDLOMKCW.js +213 -0
  59. package/dist/chunk-SDLOMKCW.js.map +1 -0
  60. package/dist/{chunk-7MZN73J2.js → chunk-TKBVW7ZJ.js} +4 -4
  61. package/dist/{chunk-A24GPVLY.js → chunk-V3OKHQUX.js} +5 -5
  62. package/dist/{chunk-NMSHVO5O.js → chunk-WMDVOWN6.js} +4 -4
  63. package/dist/{chunk-643M3AP5.js → chunk-WMFYI7XC.js} +7 -7
  64. package/dist/{chunk-6LTLIYAQ.js → chunk-YEDEAX6Y.js} +3 -3
  65. package/dist/{chunk-NYVBXUGD.js → chunk-ZIBRVA3Y.js} +60 -1
  66. package/dist/chunk-ZIBRVA3Y.js.map +1 -0
  67. package/dist/{chunk-6JY4HNUH.js → chunk-ZMML6T63.js} +361 -24
  68. package/dist/chunk-ZMML6T63.js.map +1 -0
  69. package/dist/{chunk-FFV2SXFD.js → chunk-ZVHG4KF2.js} +4 -4
  70. package/dist/cli.js.map +1 -1
  71. package/dist/commands/setup.js +1 -1
  72. package/dist/commands/start.js +2 -2
  73. package/dist/commands/status.js +1 -1
  74. package/dist/commands/stop.js +1 -1
  75. package/dist/commands/utils.js +1 -1
  76. package/dist/{cost-tracker-EMOIOYH7.js → cost-tracker-KZQSTSE2.js} +2 -2
  77. package/dist/{db-LRIOKQBO.js → db-I7MNG6CL.js} +10 -4
  78. package/dist/{discord-NKR3X4AV.js → discord-6UQHCN27.js} +24 -23
  79. package/dist/{documents-EYIYLZK2.js → documents-PFHSK7SZ.js} +19 -19
  80. package/dist/{email-EAQNULVD.js → email-6OIN4SYL.js} +22 -21
  81. package/dist/email-6OIN4SYL.js.map +1 -0
  82. package/dist/{enhanced-retrieval-OGHT6TS5.js → enhanced-retrieval-JWX2HWU4.js} +7 -6
  83. package/dist/{enhanced-retrieval-OGHT6TS5.js.map → enhanced-retrieval-JWX2HWU4.js.map} +1 -1
  84. package/dist/enrichment-pipeline-7FE5R5ZI.js +14 -0
  85. package/dist/{entity-resolution-4X4JU43O.js → entity-resolution-7Z6STVXX.js} +5 -5
  86. package/dist/{env-CHOFICED.js → env-GN5VHI43.js} +2 -2
  87. package/dist/{error-tracker-SVQSDQDW.js → error-tracker-64DEH3D7.js} +6 -6
  88. package/dist/{github-KGNILDWJ.js → github-DUWSXCNP.js} +4 -4
  89. package/dist/graph-client-NB475AK5.js +17 -0
  90. package/dist/{imessage-V2XNDDHT.js → imessage-DSGSGUZS.js} +19 -18
  91. package/dist/{inbox-summarizer-DKKRYXDR.js → inbox-summarizer-F2KAU72V.js} +19 -18
  92. package/dist/{incident-response-ZTIKUWEO.js → incident-response-E3UGMX5G.js} +5 -5
  93. package/dist/incident-response-E3UGMX5G.js.map +1 -0
  94. package/dist/{knowledge-base-J7PJ7MZ3.js → knowledge-base-5SMMOGQJ.js} +5 -5
  95. package/dist/lib.d.ts +21 -0
  96. package/dist/lib.js +64 -57
  97. package/dist/lib.js.map +1 -1
  98. package/dist/{matrix-XHTR53VQ.js → matrix-WYGEOZL5.js} +18 -17
  99. package/dist/{matrix-XHTR53VQ.js.map → matrix-WYGEOZL5.js.map} +1 -1
  100. package/dist/{mcp-3C2TN67D.js → mcp-DJ2QDA6A.js} +2 -2
  101. package/dist/{metrics-VJDWQWU7.js → metrics-BH3ZLGEV.js} +5 -5
  102. package/dist/{multi-user-S56GUD6L.js → multi-user-XAEMB244.js} +4 -4
  103. package/dist/oauth-UPJYFOVU.js +34 -0
  104. package/dist/{ocr-LGUIPKVZ.js → ocr-UONKTQU7.js} +4 -4
  105. package/dist/{presentations-HXTAMGHT.js → presentations-UOET2FVZ.js} +2 -2
  106. package/dist/{providers-H6YIC3MG.js → providers-2YQ6E3IF.js} +3 -3
  107. package/dist/{scheduler-CA5UNHZV.js → scheduler-6PLLAQI7.js} +21 -20
  108. package/dist/{schema-ALJ67YVG.js → schema-ETY7L2VA.js} +8 -2
  109. package/dist/sharepoint-V5P4Q62L.js +30 -0
  110. package/dist/{signal-X7IQJGRQ.js → signal-7D5EPGVL.js} +19 -18
  111. package/dist/{slack-P2LFUJUQ.js → slack-KSS6YK5Z.js} +23 -22
  112. package/dist/slack-KSS6YK5Z.js.map +1 -0
  113. package/dist/{sms-4VME2HUL.js → sms-CSUCC7HL.js} +3 -3
  114. package/dist/sms-CSUCC7HL.js.map +1 -0
  115. package/dist/{src-S5KX4YEV.js → src-GO7GGW7O.js} +48 -41
  116. package/dist/{src-S5KX4YEV.js.map → src-GO7GGW7O.js.map} +1 -1
  117. package/dist/token-store-SEWRX6RE.js +20 -0
  118. package/dist/token-store-SEWRX6RE.js.map +1 -0
  119. package/dist/{tools-FGPN522P.js → tools-PJZ6RI4P.js} +18 -17
  120. package/dist/tools-PJZ6RI4P.js.map +1 -0
  121. package/dist/{whatsapp-KRPQ4YUX.js → whatsapp-DWXK25V2.js} +19 -18
  122. package/dist/whatsapp-DWXK25V2.js.map +1 -0
  123. package/dist/{word-document-D6N2C47N.js → word-document-AV3YB4L2.js} +2 -2
  124. package/dist/{workflow-store-ZYAYE5P6.js → workflow-store-5Y56GUP7.js} +4 -4
  125. package/drizzle/0002_mushy_master_mold.sql +139 -139
  126. package/drizzle/0003_overjoyed_rhodey.sql +46 -0
  127. package/drizzle/meta/0002_snapshot.json +3636 -3636
  128. package/drizzle/meta/0003_snapshot.json +3946 -0
  129. package/drizzle/meta/_journal.json +7 -0
  130. package/package.json +110 -110
  131. package/dist/alerting-4I37GG4U.js.map +0 -1
  132. package/dist/archiver-XLRIIXPY.js.map +0 -1
  133. package/dist/bot-MU2TJQ3Y.js +0 -46
  134. package/dist/chunk-6JY4HNUH.js.map +0 -1
  135. package/dist/chunk-6UZPE35A.js.map +0 -1
  136. package/dist/chunk-AD6YEH6U.js.map +0 -1
  137. package/dist/chunk-AR34B6XR.js.map +0 -1
  138. package/dist/chunk-GUKKW7JI.js.map +0 -1
  139. package/dist/chunk-HKOPRRDJ.js.map +0 -1
  140. package/dist/chunk-HTF2GIQC.js.map +0 -1
  141. package/dist/chunk-KABG5PG3.js.map +0 -1
  142. package/dist/chunk-MFK34XSY.js.map +0 -1
  143. package/dist/chunk-NYVBXUGD.js.map +0 -1
  144. package/dist/chunk-PUNIMPMY.js.map +0 -1
  145. package/dist/chunk-UWUIJTT4.js.map +0 -1
  146. package/dist/chunk-XMCVRVTF.js.map +0 -1
  147. package/dist/email-EAQNULVD.js.map +0 -1
  148. package/dist/enrichment-pipeline-CMUVBDC7.js +0 -14
  149. package/dist/incident-response-ZTIKUWEO.js.map +0 -1
  150. /package/dist/{agent-manager-7N7REQZQ.js.map → agent-manager-JZ4IM7XI.js.map} +0 -0
  151. /package/dist/{audit-logger-AU3TMWKI.js.map → analyzer-OTWE3ARE.js.map} +0 -0
  152. /package/dist/{bot-MU2TJQ3Y.js.map → audit-logger-CI4WZQPD.js.map} +0 -0
  153. /package/dist/{brain-SLA474EU.js.map → bot-VDHBGUVI.js.map} +0 -0
  154. /package/dist/{cost-tracker-EMOIOYH7.js.map → brain-6QTXN4QP.js.map} +0 -0
  155. /package/dist/{chunk-M7YLQHFP.js.map → chunk-56UJS2LA.js.map} +0 -0
  156. /package/dist/{chunk-S4NJJS5C.js.map → chunk-5BTVJR7R.js.map} +0 -0
  157. /package/dist/{chunk-BMOUYXLX.js.map → chunk-6ZNCY2GI.js.map} +0 -0
  158. /package/dist/{chunk-4YJRBMMA.js.map → chunk-BNZHWAZC.js.map} +0 -0
  159. /package/dist/{chunk-TAAZB5KN.js.map → chunk-CWT6CAE5.js.map} +0 -0
  160. /package/dist/{chunk-VKMFUIVA.js.map → chunk-GBVJTRXS.js.map} +0 -0
  161. /package/dist/{chunk-2RGPWU77.js.map → chunk-HJSEEFO3.js.map} +0 -0
  162. /package/dist/{chunk-JOA5A3G3.js.map → chunk-HQZQFEAX.js.map} +0 -0
  163. /package/dist/{chunk-45YXODSB.js.map → chunk-J4JW73TT.js.map} +0 -0
  164. /package/dist/{chunk-KT7NLIXP.js.map → chunk-JHYYFPKX.js.map} +0 -0
  165. /package/dist/{chunk-H3BOLSTS.js.map → chunk-PD3CTDO6.js.map} +0 -0
  166. /package/dist/{chunk-7MZN73J2.js.map → chunk-TKBVW7ZJ.js.map} +0 -0
  167. /package/dist/{chunk-A24GPVLY.js.map → chunk-V3OKHQUX.js.map} +0 -0
  168. /package/dist/{chunk-NMSHVO5O.js.map → chunk-WMDVOWN6.js.map} +0 -0
  169. /package/dist/{chunk-643M3AP5.js.map → chunk-WMFYI7XC.js.map} +0 -0
  170. /package/dist/{chunk-6LTLIYAQ.js.map → chunk-YEDEAX6Y.js.map} +0 -0
  171. /package/dist/{chunk-FFV2SXFD.js.map → chunk-ZVHG4KF2.js.map} +0 -0
  172. /package/dist/{db-LRIOKQBO.js.map → cost-tracker-KZQSTSE2.js.map} +0 -0
  173. /package/dist/{discord-NKR3X4AV.js.map → db-I7MNG6CL.js.map} +0 -0
  174. /package/dist/{enrichment-pipeline-CMUVBDC7.js.map → discord-6UQHCN27.js.map} +0 -0
  175. /package/dist/{documents-EYIYLZK2.js.map → documents-PFHSK7SZ.js.map} +0 -0
  176. /package/dist/{entity-resolution-4X4JU43O.js.map → enrichment-pipeline-7FE5R5ZI.js.map} +0 -0
  177. /package/dist/{env-CHOFICED.js.map → entity-resolution-7Z6STVXX.js.map} +0 -0
  178. /package/dist/{error-tracker-SVQSDQDW.js.map → env-GN5VHI43.js.map} +0 -0
  179. /package/dist/{imessage-V2XNDDHT.js.map → error-tracker-64DEH3D7.js.map} +0 -0
  180. /package/dist/{github-KGNILDWJ.js.map → github-DUWSXCNP.js.map} +0 -0
  181. /package/dist/{inbox-summarizer-DKKRYXDR.js.map → graph-client-NB475AK5.js.map} +0 -0
  182. /package/dist/{knowledge-base-J7PJ7MZ3.js.map → imessage-DSGSGUZS.js.map} +0 -0
  183. /package/dist/{mcp-3C2TN67D.js.map → inbox-summarizer-F2KAU72V.js.map} +0 -0
  184. /package/dist/{metrics-VJDWQWU7.js.map → knowledge-base-5SMMOGQJ.js.map} +0 -0
  185. /package/dist/{ocr-LGUIPKVZ.js.map → mcp-DJ2QDA6A.js.map} +0 -0
  186. /package/dist/{providers-H6YIC3MG.js.map → metrics-BH3ZLGEV.js.map} +0 -0
  187. /package/dist/{multi-user-S56GUD6L.js.map → multi-user-XAEMB244.js.map} +0 -0
  188. /package/dist/{scheduler-CA5UNHZV.js.map → oauth-UPJYFOVU.js.map} +0 -0
  189. /package/dist/{schema-ALJ67YVG.js.map → ocr-UONKTQU7.js.map} +0 -0
  190. /package/dist/{presentations-HXTAMGHT.js.map → presentations-UOET2FVZ.js.map} +0 -0
  191. /package/dist/{signal-X7IQJGRQ.js.map → providers-2YQ6E3IF.js.map} +0 -0
  192. /package/dist/{slack-P2LFUJUQ.js.map → scheduler-6PLLAQI7.js.map} +0 -0
  193. /package/dist/{sms-4VME2HUL.js.map → schema-ETY7L2VA.js.map} +0 -0
  194. /package/dist/{tools-FGPN522P.js.map → sharepoint-V5P4Q62L.js.map} +0 -0
  195. /package/dist/{whatsapp-KRPQ4YUX.js.map → signal-7D5EPGVL.js.map} +0 -0
  196. /package/dist/{word-document-D6N2C47N.js.map → word-document-AV3YB4L2.js.map} +0 -0
  197. /package/dist/{workflow-store-ZYAYE5P6.js.map → workflow-store-5Y56GUP7.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/inputs/api/server.ts","../src/core/security/api-key-manager.ts","../src/core/security/session-manager.ts","../src/core/security/gateway-utils.ts","../src/core/security/auth-middleware.ts","../src/inputs/api/routes/osint.ts","../src/inputs/api/routes/email.ts","../src/inputs/api/routes/sdk.ts","../src/inputs/api/routes/admin.ts","../src/core/security/rate-limiter.ts","../src/inputs/api/routes/brain.ts","../src/inputs/api/routes/scheduler.ts","../src/inputs/api/routes/alerts.ts","../src/inputs/api/routes/webhooks.ts","../src/inputs/api/routes/github.ts","../src/inputs/api/routes/metrics.ts","../src/inputs/api/routes/mcp.ts","../src/inputs/api/routes/bots.ts","../src/inputs/api/routes/users.ts"],"sourcesContent":["import { Hono } from \"hono\";\r\nimport { cors } from \"hono/cors\";\r\nimport { logger } from \"hono/logger\";\r\n// Use platform-appropriate static file serving\r\nlet serveStatic: any;\r\ntry {\r\n // Bun runtime\r\n serveStatic = require(\"hono/bun\").serveStatic;\r\n} catch {\r\n // Fallback: no static file serving (API-only mode)\r\n serveStatic = () => async (_c: any, next: any) => next();\r\n}\r\nimport { chat, chatWithTools, streamChat, type Message } from \"../../core/brain\";\r\nimport { transcribeAudio } from \"../../outputs/stt\";\r\nimport { textToSpeech } from \"../../outputs/tts\";\r\nimport { db, conversations, messages, memories } from \"../../db\";\r\nimport { desc, eq } from \"drizzle-orm\";\r\nimport { searchMemories, storeMemory, updateMemory, deleteMemory, exportMemories, getMemoryById } from \"../../core/memory\";\r\nimport { authMiddleware, requirePermission, getAuthUserId } from \"../../core/security/auth-middleware\";\r\nimport { decryptField } from \"../../core/security/field-encryption\";\r\n\r\nconst app = new Hono();\r\n\r\n// Middleware\r\napp.use(\"*\", logger());\r\napp.use(\"/api/*\", cors());\r\napp.use(\"/api/*\", authMiddleware());\r\n\r\n// Health check\r\napp.get(\"/health\", (c) => {\r\n return c.json({ status: \"ok\", timestamp: new Date().toISOString() });\r\n});\r\n\r\n// ===== Chat API =====\r\n\r\n// Simple chat endpoint (no tools)\r\napp.post(\"/api/chat\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n messages: Message[];\r\n systemPrompt?: string;\r\n }>();\r\n\r\n if (!body.messages || !Array.isArray(body.messages)) {\r\n return c.json({ error: \"messages array is required\" }, 400);\r\n }\r\n\r\n const response = await chat(body.messages, body.systemPrompt);\r\n\r\n return c.json({\r\n content: response.content,\r\n usage: {\r\n inputTokens: response.inputTokens,\r\n outputTokens: response.outputTokens,\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"Chat API error:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// Chat with tools endpoint\r\napp.post(\"/api/chat/tools\", requirePermission(\"chat:tools\" as any), async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n messages: Message[];\r\n userId?: string;\r\n }>();\r\n\r\n if (!body.messages || !Array.isArray(body.messages)) {\r\n return c.json({ error: \"messages array is required\" }, 400);\r\n }\r\n\r\n const toolsUsed: string[] = [];\r\n const response = await chatWithTools(body.messages, body.userId, (tool) => {\r\n toolsUsed.push(tool);\r\n });\r\n\r\n return c.json({\r\n content: response.content,\r\n toolsUsed,\r\n usage: {\r\n inputTokens: response.inputTokens,\r\n outputTokens: response.outputTokens,\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"Chat with tools API error:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// Simple single message chat\r\napp.post(\"/api/ask\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n message: string;\r\n systemPrompt?: string;\r\n useTools?: boolean;\r\n }>();\r\n\r\n if (!body.message) {\r\n return c.json({ error: \"message is required\" }, 400);\r\n }\r\n\r\n const messages: Message[] = [{ role: \"user\", content: body.message }];\r\n\r\n const response = body.useTools\r\n ? await chatWithTools(messages)\r\n : await chat(messages, body.systemPrompt);\r\n\r\n return c.json({\r\n content: response.content,\r\n toolsUsed: response.toolsUsed,\r\n usage: {\r\n inputTokens: response.inputTokens,\r\n outputTokens: response.outputTokens,\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"Ask API error:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Conversations API =====\r\n\r\napp.get(\"/api/conversations\", async (c) => {\r\n try {\r\n const convos = await db\r\n .select()\r\n .from(conversations)\r\n .orderBy(desc(conversations.updatedAt))\r\n .limit(50);\r\n\r\n return c.json(convos);\r\n } catch (error) {\r\n console.error(\"Error fetching conversations:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\napp.get(\"/api/conversations/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const convo = await db\r\n .select()\r\n .from(conversations)\r\n .where(eq(conversations.id, id))\r\n .limit(1);\r\n\r\n if (convo.length === 0) {\r\n return c.json({ error: \"Conversation not found\" }, 404);\r\n }\r\n\r\n const msgs = await db\r\n .select()\r\n .from(messages)\r\n .where(eq(messages.conversationId, id))\r\n .orderBy(messages.createdAt);\r\n\r\n // Decrypt encrypted messages\r\n const decryptedMsgs = msgs.map((m) => {\r\n if ((m as any).encrypted && m.content) {\r\n try {\r\n return { ...m, content: decryptField(m.content) ?? m.content };\r\n } catch {\r\n return m;\r\n }\r\n }\r\n return m;\r\n });\r\n\r\n return c.json({ conversation: convo[0], messages: decryptedMsgs });\r\n } catch (error) {\r\n console.error(\"Error fetching conversation:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Memories API =====\r\n\r\napp.get(\"/api/memories\", async (c) => {\r\n try {\r\n const userId = c.req.query(\"userId\");\r\n const limit = parseInt(c.req.query(\"limit\") || \"50\");\r\n\r\n let query = db.select().from(memories).orderBy(desc(memories.createdAt)).limit(limit);\r\n\r\n const mems = await query;\r\n return c.json(mems);\r\n } catch (error) {\r\n console.error(\"Error fetching memories:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\napp.post(\"/api/memories/search\", async (c) => {\r\n try {\r\n const body = await c.req.json<{ query: string; userId?: string; limit?: number }>();\r\n\r\n if (!body.query) {\r\n return c.json({ error: \"query is required\" }, 400);\r\n }\r\n\r\n const results = await searchMemories(body.query, body.userId, body.limit || 5);\r\n return c.json(results);\r\n } catch (error) {\r\n console.error(\"Error searching memories:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\napp.post(\"/api/memories\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n content: string;\r\n type?: \"episodic\" | \"semantic\" | \"procedural\";\r\n importance?: number;\r\n userId?: string;\r\n }>();\r\n\r\n if (!body.content) {\r\n return c.json({ error: \"content is required\" }, 400);\r\n }\r\n\r\n const memory = await storeMemory({\r\n content: body.content,\r\n type: body.type || \"semantic\",\r\n importance: body.importance || 5,\r\n userId: body.userId,\r\n source: \"api\",\r\n provenance: \"api:manual\",\r\n });\r\n\r\n return c.json(memory);\r\n } catch (error) {\r\n console.error(\"Error storing memory:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// Get a single memory by ID\r\napp.get(\"/api/memories/export\", async (c) => {\r\n try {\r\n const userId = c.req.query(\"userId\");\r\n const format = (c.req.query(\"format\") || \"markdown\") as \"markdown\" | \"json\";\r\n\r\n const exported = await exportMemories(userId || undefined, format);\r\n\r\n if (format === \"json\") {\r\n return c.json(JSON.parse(exported));\r\n }\r\n\r\n return c.text(exported);\r\n } catch (error) {\r\n console.error(\"Error exporting memories:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\napp.get(\"/api/memories/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const memory = await getMemoryById(id);\r\n\r\n if (!memory) {\r\n return c.json({ error: \"Memory not found\" }, 404);\r\n }\r\n\r\n return c.json(memory);\r\n } catch (error) {\r\n console.error(\"Error fetching memory:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// Update a memory\r\napp.put(\"/api/memories/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const body = await c.req.json<{\r\n content?: string;\r\n type?: string;\r\n importance?: number;\r\n }>();\r\n\r\n const updated = await updateMemory(id, body);\r\n\r\n if (!updated) {\r\n return c.json({ error: \"Memory not found or no changes\" }, 404);\r\n }\r\n\r\n return c.json(updated);\r\n } catch (error) {\r\n console.error(\"Error updating memory:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// Delete a memory (soft-delete to archive)\r\napp.delete(\"/api/memories/:id\", requirePermission(\"memories:delete\" as any), async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const deleted = await deleteMemory(id);\r\n\r\n if (!deleted) {\r\n return c.json({ error: \"Memory not found\" }, 404);\r\n }\r\n\r\n return c.json({ success: true, id });\r\n } catch (error) {\r\n console.error(\"Error deleting memory:\", error);\r\n return c.json({ error: \"Internal server error\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Autonomy API =====\r\n\r\napp.get(\"/api/autonomy\", async (c) => {\r\n try {\r\n const { autonomyManager } = await import(\"../../core/security/autonomy\");\r\n const userId = c.req.query(\"userId\");\r\n return c.json({\r\n level: userId ? autonomyManager.getLevel(userId) : autonomyManager.getDefaultLevel(),\r\n stats: autonomyManager.getStats(),\r\n });\r\n } catch (error) {\r\n return c.json({ error: \"Autonomy system not available\" }, 500);\r\n }\r\n});\r\n\r\napp.put(\"/api/autonomy\", async (c) => {\r\n try {\r\n const { autonomyManager } = await import(\"../../core/security/autonomy\");\r\n const body = await c.req.json<{ level: string; userId?: string }>();\r\n const level = body.level as \"readonly\" | \"supervised\" | \"autonomous\";\r\n\r\n if (![\"readonly\", \"supervised\", \"autonomous\"].includes(level)) {\r\n return c.json({ error: \"Invalid level. Must be: readonly, supervised, or autonomous\" }, 400);\r\n }\r\n\r\n if (body.userId) {\r\n autonomyManager.setLevel(body.userId, level);\r\n } else {\r\n autonomyManager.setDefaultLevel(level);\r\n }\r\n\r\n return c.json({ success: true, level });\r\n } catch (error) {\r\n return c.json({ error: \"Autonomy system not available\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Prometheus Metrics =====\r\n\r\napp.get(\"/metrics\", async (c) => {\r\n try {\r\n const { prometheusExporter } = await import(\"../../core/observability/prometheus\");\r\n const text = prometheusExporter.toTextFormat();\r\n return c.text(text, 200, { \"Content-Type\": \"text/plain; version=0.0.4; charset=utf-8\" });\r\n } catch (error) {\r\n return c.text(\"# Prometheus metrics not available\\n\", 500);\r\n }\r\n});\r\n\r\napp.get(\"/api/metrics/prometheus\", async (c) => {\r\n try {\r\n const { prometheusExporter } = await import(\"../../core/observability/prometheus\");\r\n const text = prometheusExporter.toTextFormat();\r\n return c.text(text, 200, { \"Content-Type\": \"text/plain; version=0.0.4; charset=utf-8\" });\r\n } catch (error) {\r\n return c.text(\"# Prometheus metrics not available\\n\", 500);\r\n }\r\n});\r\n\r\n// ===== Pairing API =====\r\n\r\napp.post(\"/api/pair\", async (c) => {\r\n try {\r\n const { pairingManager } = await import(\"../../core/security/pairing\");\r\n const body = await c.req.json<{ code: string; deviceInfo?: string }>();\r\n\r\n if (!body.code) {\r\n return c.json({ error: \"code is required\" }, 400);\r\n }\r\n\r\n const result = pairingManager.pair(body.code, body.deviceInfo || \"Unknown device\");\r\n\r\n if (!result.success) {\r\n return c.json({ error: result.error }, 401);\r\n }\r\n\r\n return c.json({ token: result.token });\r\n } catch (error) {\r\n return c.json({ error: \"Pairing system not available\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Providers API =====\r\n\r\napp.get(\"/api/providers\", async (c) => {\r\n try {\r\n const { providerRegistry } = await import(\"../../core/providers\");\r\n return c.json({\r\n providers: providerRegistry.listProviders(),\r\n default: providerRegistry.getDefaultId(),\r\n });\r\n } catch (error) {\r\n return c.json({ error: \"Provider system not available\" }, 500);\r\n }\r\n});\r\n\r\n// ===== OSINT API =====\r\nimport { osintRoutes } from \"./routes/osint\";\r\napp.route(\"/api/osint\", osintRoutes);\r\n\r\nimport { emailRoutes } from \"./routes/email\";\r\napp.route(\"/api/email\", emailRoutes);\r\n\r\n// ===== SDK API (External App Integration) =====\r\nimport { sdkRoutes } from \"./routes/sdk\";\r\napp.route(\"/api/sdk\", sdkRoutes);\r\n\r\n// ===== Admin API (Audit Logs, Incidents) =====\r\nimport adminRouter from \"./routes/admin\";\r\napp.route(\"/api/admin\", adminRouter);\r\n\r\n// ===== Dashboard Audit Logs (no admin auth required) =====\r\napp.get(\"/api/audit-logs\", async (c) => {\r\n try {\r\n const { queryAuditLogs } = await import(\"../../core/security/audit-logger\");\r\n const url = new URL(c.req.url);\r\n const options: Record<string, unknown> = {};\r\n const userId = url.searchParams.get(\"userId\");\r\n if (userId) options.userId = userId;\r\n const action = url.searchParams.get(\"action\");\r\n if (action) options.action = action;\r\n const resource = url.searchParams.get(\"resource\");\r\n if (resource) options.resource = resource;\r\n const startDate = url.searchParams.get(\"startDate\");\r\n if (startDate) options.startDate = new Date(startDate);\r\n const endDate = url.searchParams.get(\"endDate\");\r\n if (endDate) options.endDate = new Date(endDate);\r\n const limit = url.searchParams.get(\"limit\");\r\n if (limit) options.limit = parseInt(limit);\r\n const offset = url.searchParams.get(\"offset\");\r\n if (offset) options.offset = parseInt(offset);\r\n const logs = await queryAuditLogs(options as any);\r\n return c.json({ success: true, logs });\r\n } catch (err: any) {\r\n return c.json({ success: false, error: err?.message || \"Failed to query audit logs\", logs: [] });\r\n }\r\n});\r\n\r\napp.get(\"/api/audit-logs/integrity\", async (c) => {\r\n try {\r\n const { getAuditChainIntegrity } = await import(\"../../core/security/audit-logger\");\r\n const integrity = await getAuditChainIntegrity();\r\n return c.json({ success: true, ...integrity });\r\n } catch (err: any) {\r\n return c.json({ success: false, error: err?.message, chainValid: false, totalEntries: 0, lastSequence: 0 });\r\n }\r\n});\r\n\r\n// ===== Clear History Endpoints =====\r\n\r\n// DELETE /api/audit-logs — Clear all audit logs\r\napp.delete(\"/api/audit-logs\", async (c) => {\r\n try {\r\n const { auditLogs } = await import(\"../../db/schema\");\r\n await db.delete(auditLogs);\r\n return c.json({ success: true });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to clear audit logs\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/conversations — Clear all sessions/conversations\r\napp.delete(\"/api/conversations\", async (c) => {\r\n try {\r\n await db.delete(messages);\r\n await db.delete(conversations);\r\n return c.json({ success: true });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to clear sessions\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/conversations/:id — Delete a single conversation and its messages\r\napp.delete(\"/api/conversations/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const convo = await db\r\n .select()\r\n .from(conversations)\r\n .where(eq(conversations.id, id))\r\n .limit(1);\r\n\r\n if (convo.length === 0) {\r\n return c.json({ error: \"Conversation not found\" }, 404);\r\n }\r\n\r\n await db.delete(messages).where(eq(messages.conversationId, id));\r\n await db.delete(conversations).where(eq(conversations.id, id));\r\n return c.json({ success: true, id });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to delete conversation\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Brain Dashboard API (Telemetry, Pipeline, Agents) =====\r\nimport brainRouter from \"./routes/brain\";\r\napp.route(\"/api/brain\", brainRouter);\r\n\r\n// ===== Scheduler API (Cron Jobs) =====\r\nimport schedulerRouter from \"./routes/scheduler\";\r\napp.route(\"/api/scheduler\", schedulerRouter);\r\n\r\n// ===== Alerts API =====\r\nimport alertsRouter from \"./routes/alerts\";\r\napp.route(\"/api/alerts\", alertsRouter);\r\n\r\n// ===== Webhooks API =====\r\nimport webhooksRouter from \"./routes/webhooks\";\r\napp.route(\"/api/webhooks\", webhooksRouter);\r\n\r\n// ===== GitHub API =====\r\nimport githubRouter from \"./routes/github\";\r\napp.route(\"/api/github\", githubRouter);\r\n\r\n// ===== Metrics API (authenticated routes for external use) =====\r\nimport metricsRouter from \"./routes/metrics\";\r\napp.route(\"/api/metrics\", metricsRouter);\r\n\r\n// ===== Metrics Overview (dashboard-accessible, no API key required) =====\r\napp.get(\"/api/metrics/overview\", async (c) => {\r\n try {\r\n const { getMetricAggregates } = await import(\"../../core/observability/metrics\");\r\n const { getErrorStats } = await import(\"../../core/observability/error-tracker\");\r\n const now = new Date();\r\n const dayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);\r\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\r\n\r\n const [latencyDay, inputDay, outputDay, errorsDay, inputWeek, outputWeek] = await Promise.allSettled([\r\n getMetricAggregates(\"response_latency\" as any, dayAgo, now),\r\n getMetricAggregates(\"token_usage_input\" as any, dayAgo, now),\r\n getMetricAggregates(\"token_usage_output\" as any, dayAgo, now),\r\n getErrorStats(dayAgo, now),\r\n getMetricAggregates(\"token_usage_input\" as any, weekAgo, now),\r\n getMetricAggregates(\"token_usage_output\" as any, weekAgo, now),\r\n ]);\r\n\r\n const val = (r: PromiseSettledResult<any>, key: string) =>\r\n r.status === \"fulfilled\" ? (r.value?.[key] ?? 0) : 0;\r\n\r\n return c.json({\r\n last24h: {\r\n inputTokens: val(inputDay, \"sum\"),\r\n outputTokens: val(outputDay, \"sum\"),\r\n requests: val(latencyDay, \"count\"),\r\n avgLatencyMs: val(latencyDay, \"avg\"),\r\n errors: errorsDay.status === \"fulfilled\" ? (errorsDay.value?.total ?? 0) : 0,\r\n },\r\n last7d: {\r\n inputTokens: val(inputWeek, \"sum\"),\r\n outputTokens: val(outputWeek, \"sum\"),\r\n },\r\n });\r\n } catch {\r\n return c.json({ last24h: {}, last7d: {} });\r\n }\r\n});\r\n\r\n// ===== MCP Servers API =====\r\nimport mcpRouter from \"./routes/mcp\";\r\napp.route(\"/api/mcp\", mcpRouter);\r\n\r\n// ===== Bots API =====\r\nimport botsRouter from \"./routes/bots\";\r\napp.route(\"/api/bots\", botsRouter);\r\n\r\n// ===== Users API =====\r\nimport usersRouter from \"./routes/users\";\r\napp.route(\"/api/users\", usersRouter);\r\n\r\n// ===== Incident Response API =====\r\n\r\napp.get(\"/api/incidents\", requirePermission(\"admin:settings\" as any), async (c) => {\r\n try {\r\n const { getOpenIncidents } = await import(\"../../core/security/incident-response\");\r\n const severity = c.req.query(\"severity\") as any;\r\n const type = c.req.query(\"type\") as any;\r\n const incidents = await getOpenIncidents({ severity, type, limit: 50 });\r\n return c.json(incidents);\r\n } catch (error) {\r\n return c.json({ error: \"Incident system not available\" }, 500);\r\n }\r\n});\r\n\r\napp.get(\"/api/incidents/:id\", requirePermission(\"admin:settings\" as any), async (c) => {\r\n try {\r\n const { generateIncidentReport } = await import(\"../../core/security/incident-response\");\r\n const id = c.req.param(\"id\");\r\n const report = await generateIncidentReport(id);\r\n return c.json(report);\r\n } catch (error) {\r\n return c.json({ error: \"Incident not found\" }, 404);\r\n }\r\n});\r\n\r\napp.post(\"/api/incidents/:id/status\", requirePermission(\"admin:settings\" as any), async (c) => {\r\n try {\r\n const { updateIncidentStatus } = await import(\"../../core/security/incident-response\");\r\n const id = c.req.param(\"id\");\r\n const body = await c.req.json<{ status: string; notes?: string }>();\r\n const userId = getAuthUserId(c);\r\n const updated = await updateIncidentStatus(id, body.status as any, userId, body.notes);\r\n return c.json(updated);\r\n } catch (error) {\r\n return c.json({ error: \"Failed to update incident\" }, 500);\r\n }\r\n});\r\n\r\napp.post(\"/api/incidents/:id/resolve\", requirePermission(\"admin:settings\" as any), async (c) => {\r\n try {\r\n const { resolveIncident } = await import(\"../../core/security/incident-response\");\r\n const id = c.req.param(\"id\");\r\n const body = await c.req.json<{ notes: string }>();\r\n const userId = getAuthUserId(c);\r\n const resolved = await resolveIncident(id, body.notes, userId);\r\n return c.json(resolved);\r\n } catch (error) {\r\n return c.json({ error: \"Failed to resolve incident\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Audit Chain Integrity API =====\r\n\r\napp.get(\"/api/audit/integrity\", requirePermission(\"admin:settings\" as any), async (c) => {\r\n try {\r\n const { getAuditChainIntegrity } = await import(\"../../core/security/audit-logger\");\r\n const integrity = await getAuditChainIntegrity();\r\n return c.json(integrity);\r\n } catch (error) {\r\n return c.json({ error: \"Audit system not available\" }, 500);\r\n }\r\n});\r\n\r\n// ===== Voice API (STT / TTS) =====\r\n\r\napp.post(\"/api/transcribe\", async (c) => {\r\n try {\r\n const formData = await c.req.formData();\r\n const audioFile = formData.get(\"audio\");\r\n\r\n if (!audioFile || !(audioFile instanceof File)) {\r\n return c.json({ error: \"audio file is required\" }, 400);\r\n }\r\n\r\n const buffer = Buffer.from(await audioFile.arrayBuffer());\r\n const text = await transcribeAudio(buffer);\r\n\r\n if (!text) {\r\n return c.json({ error: \"Could not transcribe audio\" }, 500);\r\n }\r\n\r\n return c.json({ text });\r\n } catch (error) {\r\n console.error(\"Transcribe API error:\", error);\r\n return c.json({ error: \"Transcription failed\" }, 500);\r\n }\r\n});\r\n\r\napp.post(\"/api/tts\", async (c) => {\r\n try {\r\n const body = await c.req.json<{ text: string }>();\r\n\r\n if (!body.text) {\r\n return c.json({ error: \"text is required\" }, 400);\r\n }\r\n\r\n const audioBuffer = await textToSpeech(body.text);\r\n\r\n if (!audioBuffer) {\r\n return c.json({ error: \"Text-to-speech failed\" }, 500);\r\n }\r\n\r\n return new Response(new Uint8Array(audioBuffer), {\r\n headers: {\r\n \"Content-Type\": \"audio/mpeg\",\r\n \"Content-Length\": String(audioBuffer.length),\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"TTS API error:\", error);\r\n return c.json({ error: \"TTS failed\" }, 500);\r\n }\r\n});\r\n\r\n// ===== System API =====\r\n\r\napp.get(\"/api/system/status\", async (c) => {\r\n return c.json({\r\n status: \"online\",\r\n version: \"3.4.0\",\r\n uptime: process.uptime(),\r\n memory: process.memoryUsage(),\r\n });\r\n});\r\n\r\n// ===== Spotify OAuth Callback =====\r\n\r\napp.get(\"/api/callbacks/spotify\", async (c) => {\r\n try {\r\n const code = c.req.query(\"code\");\r\n const error = c.req.query(\"error\");\r\n\r\n if (error) {\r\n return c.html(`<h1>Spotify Authorization Failed</h1><p>Error: ${error}</p><p>Go back and try again.</p>`);\r\n }\r\n\r\n if (!code) {\r\n return c.html(`<h1>Missing Authorization Code</h1><p>No code received from Spotify.</p>`);\r\n }\r\n\r\n const { env: appEnv } = await import(\"../../config/env\");\r\n if (!appEnv.SPOTIFY_CLIENT_ID || !appEnv.SPOTIFY_CLIENT_SECRET) {\r\n return c.html(`<h1>Spotify Not Configured</h1><p>Set SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET in .env</p>`);\r\n }\r\n\r\n const { createSpotifyAuth } = await import(\"../../integrations/spotify/auth\");\r\n const auth = createSpotifyAuth({\r\n clientId: appEnv.SPOTIFY_CLIENT_ID,\r\n clientSecret: appEnv.SPOTIFY_CLIENT_SECRET,\r\n redirectUri: appEnv.SPOTIFY_REDIRECT_URI || `http://localhost:${appEnv.PORT}/api/callbacks/spotify`,\r\n });\r\n\r\n const tokens = await auth.exchangeCode(code);\r\n\r\n return c.html(`\r\n <html><body style=\"font-family: system-ui; max-width: 600px; margin: 40px auto; padding: 20px;\">\r\n <h1>Spotify Connected!</h1>\r\n <p>Add this to your <code>.env</code> file:</p>\r\n <pre style=\"background: #f0f0f0; padding: 16px; border-radius: 8px; word-break: break-all; white-space: pre-wrap;\">SPOTIFY_REFRESH_TOKEN=${tokens.refreshToken}</pre>\r\n <p>Then restart OpenSentinel. You can close this page.</p>\r\n </body></html>\r\n `);\r\n } catch (err) {\r\n console.error(\"Spotify callback error:\", err);\r\n return c.html(`<h1>Spotify Auth Error</h1><p>${err instanceof Error ? err.message : String(err)}</p>`);\r\n }\r\n});\r\n\r\napp.get(\"/api/spotify/authorize\", async (c) => {\r\n try {\r\n const { env: appEnv } = await import(\"../../config/env\");\r\n if (!appEnv.SPOTIFY_CLIENT_ID || !appEnv.SPOTIFY_CLIENT_SECRET) {\r\n return c.json({ error: \"Spotify not configured. Set SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET in .env\" }, 400);\r\n }\r\n\r\n const { createSpotifyAuth, DEFAULT_SCOPES } = await import(\"../../integrations/spotify/auth\");\r\n const auth = createSpotifyAuth({\r\n clientId: appEnv.SPOTIFY_CLIENT_ID,\r\n clientSecret: appEnv.SPOTIFY_CLIENT_SECRET,\r\n redirectUri: appEnv.SPOTIFY_REDIRECT_URI || `http://localhost:${appEnv.PORT}/api/callbacks/spotify`,\r\n });\r\n\r\n const url = auth.getAuthorizationUrl(DEFAULT_SCOPES, undefined, true);\r\n return c.json({ url });\r\n } catch (err) {\r\n return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);\r\n }\r\n});\r\n\r\n// ===== File Download & Upload =====\r\n\r\nimport { getDownloadEntry } from \"./download-registry\";\r\nimport { tmpdir } from \"os\";\r\nimport { resolve, join, basename } from \"path\";\r\nimport { randomBytes } from \"crypto\";\r\n\r\n// Secure file download via token (generated by file-gen tools)\r\napp.get(\"/api/files/download/:token\", async (c) => {\r\n const token = c.req.param(\"token\");\r\n const entry = getDownloadEntry(token);\r\n if (!entry) {\r\n return c.json({ error: \"Download link expired or invalid\" }, 404);\r\n }\r\n // Security: only serve files from temp directory\r\n const tmp = resolve(tmpdir());\r\n if (!entry.filePath.startsWith(tmp)) {\r\n return c.json({ error: \"Access denied\" }, 403);\r\n }\r\n try {\r\n const file = Bun.file(entry.filePath);\r\n if (!(await file.exists())) {\r\n return c.json({ error: \"File not found\" }, 404);\r\n }\r\n return new Response(file, {\r\n headers: {\r\n \"Content-Type\": entry.contentType,\r\n \"Content-Disposition\": `attachment; filename=\"${entry.filename}\"`,\r\n },\r\n });\r\n } catch {\r\n return c.json({ error: \"Failed to serve file\" }, 500);\r\n }\r\n});\r\n\r\n// File upload for document parsing (stores to temp dir, returns path)\r\napp.post(\"/api/files/upload\", async (c) => {\r\n try {\r\n const formData = await c.req.formData();\r\n const file = formData.get(\"file\");\r\n if (!file || !(file instanceof File)) {\r\n return c.json({ error: \"file field is required\" }, 400);\r\n }\r\n if (file.size > 50 * 1024 * 1024) {\r\n return c.json({ error: \"File too large (50MB max)\" }, 413);\r\n }\r\n const ext = file.name.split(\".\").pop() || \"bin\";\r\n const id = randomBytes(8).toString(\"hex\");\r\n const filename = `sentinel-upload-${id}.${ext}`;\r\n const filePath = join(tmpdir(), filename);\r\n const buffer = Buffer.from(await file.arrayBuffer());\r\n await Bun.write(filePath, buffer);\r\n return c.json({ filePath, originalName: file.name });\r\n } catch {\r\n return c.json({ error: \"Upload failed\" }, 500);\r\n }\r\n});\r\n\r\n// Serve static files from web/dist\r\napp.use(\"/*\", serveStatic({ root: \"./src/web/dist\" }));\r\n\r\n// Fallback to index.html for SPA routing\r\napp.get(\"/*\", serveStatic({ path: \"./src/web/dist/index.html\" }));\r\n\r\nexport { app };\r\n","import { db } from \"../../db\";\nimport { apiKeys, NewApiKey } from \"../../db/schema\";\nimport { eq, and, isNull } from \"drizzle-orm\";\nimport { randomBytes, createHash } from \"crypto\";\n\nconst KEY_PREFIX = \"mb_\";\nconst KEY_LENGTH = 32;\n\nexport type Permission =\n | \"chat:basic\"\n | \"chat:tools\"\n | \"tools:shell\"\n | \"tools:files\"\n | \"tools:browser\"\n | \"tools:web_search\"\n | \"agents:spawn\"\n | \"agents:manage\"\n | \"memories:read\"\n | \"memories:write\"\n | \"memories:delete\"\n | \"admin:users\"\n | \"admin:settings\"\n | \"*\"; // All permissions\n\nexport const PERMISSION_GROUPS: Record<string, Permission[]> = {\n readonly: [\"chat:basic\", \"memories:read\"],\n standard: [\n \"chat:basic\",\n \"chat:tools\",\n \"tools:files\",\n \"tools:web_search\",\n \"memories:read\",\n \"memories:write\",\n ],\n full: [\n \"chat:basic\",\n \"chat:tools\",\n \"tools:shell\",\n \"tools:files\",\n \"tools:browser\",\n \"tools:web_search\",\n \"agents:spawn\",\n \"agents:manage\",\n \"memories:read\",\n \"memories:write\",\n \"memories:delete\",\n ],\n admin: [\"*\"],\n};\n\nexport interface ApiKeyInfo {\n id: string;\n name: string;\n prefix: string;\n permissions: Permission[];\n createdAt: Date;\n lastUsedAt: Date | null;\n expiresAt: Date | null;\n isRevoked: boolean;\n}\n\nexport interface CreateApiKeyOptions {\n userId: string;\n name: string;\n permissions?: Permission[];\n permissionGroup?: keyof typeof PERMISSION_GROUPS;\n expiresInDays?: number;\n}\n\nfunction generateApiKey(): string {\n const random = randomBytes(KEY_LENGTH).toString(\"base64url\");\n return `${KEY_PREFIX}${random}`;\n}\n\nfunction hashApiKey(key: string): string {\n return createHash(\"sha256\").update(key).digest(\"hex\");\n}\n\nfunction getKeyPrefix(key: string): string {\n // Return first 12 characters including the prefix\n return key.slice(0, 12);\n}\n\nexport async function createApiKey(\n options: CreateApiKeyOptions\n): Promise<{ apiKey: ApiKeyInfo; rawKey: string }> {\n const {\n userId,\n name,\n permissions,\n permissionGroup,\n expiresInDays,\n } = options;\n\n // Determine permissions\n let finalPermissions: Permission[];\n if (permissions) {\n finalPermissions = permissions;\n } else if (permissionGroup) {\n finalPermissions = PERMISSION_GROUPS[permissionGroup] || PERMISSION_GROUPS.standard;\n } else {\n finalPermissions = PERMISSION_GROUPS.standard;\n }\n\n const rawKey = generateApiKey();\n const keyHash = hashApiKey(rawKey);\n const keyPrefix = getKeyPrefix(rawKey);\n\n const expiresAt = expiresInDays\n ? new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1000)\n : null;\n\n const [created] = await db\n .insert(apiKeys)\n .values({\n userId,\n name,\n keyHash,\n keyPrefix,\n permissions: finalPermissions as string[],\n expiresAt,\n })\n .returning();\n\n return {\n apiKey: {\n id: created.id,\n name: created.name,\n prefix: created.keyPrefix,\n permissions: (created.permissions as Permission[]) || [],\n createdAt: created.createdAt,\n lastUsedAt: created.lastUsedAt,\n expiresAt: created.expiresAt,\n isRevoked: !!created.revokedAt,\n },\n rawKey, // Only returned once during creation\n };\n}\n\nexport async function validateApiKey(\n rawKey: string\n): Promise<{ valid: boolean; apiKey?: ApiKeyInfo; userId?: string }> {\n if (!rawKey.startsWith(KEY_PREFIX)) {\n return { valid: false };\n }\n\n const keyHash = hashApiKey(rawKey);\n const now = new Date();\n\n const [key] = await db\n .select()\n .from(apiKeys)\n .where(\n and(\n eq(apiKeys.keyHash, keyHash),\n isNull(apiKeys.revokedAt)\n )\n )\n .limit(1);\n\n if (!key) {\n return { valid: false };\n }\n\n // Check expiration\n if (key.expiresAt && key.expiresAt < now) {\n return { valid: false };\n }\n\n // Update last used timestamp\n await db\n .update(apiKeys)\n .set({ lastUsedAt: now })\n .where(eq(apiKeys.id, key.id));\n\n return {\n valid: true,\n apiKey: {\n id: key.id,\n name: key.name,\n prefix: key.keyPrefix,\n permissions: (key.permissions as Permission[]) || [],\n createdAt: key.createdAt,\n lastUsedAt: now,\n expiresAt: key.expiresAt,\n isRevoked: false,\n },\n userId: key.userId,\n };\n}\n\nexport function hasPermission(\n apiKeyPermissions: Permission[],\n requiredPermission: Permission\n): boolean {\n // Wildcard grants all permissions\n if (apiKeyPermissions.includes(\"*\")) {\n return true;\n }\n\n return apiKeyPermissions.includes(requiredPermission);\n}\n\nexport function hasAnyPermission(\n apiKeyPermissions: Permission[],\n requiredPermissions: Permission[]\n): boolean {\n return requiredPermissions.some((p) => hasPermission(apiKeyPermissions, p));\n}\n\nexport function hasAllPermissions(\n apiKeyPermissions: Permission[],\n requiredPermissions: Permission[]\n): boolean {\n return requiredPermissions.every((p) => hasPermission(apiKeyPermissions, p));\n}\n\nexport async function revokeApiKey(keyId: string): Promise<boolean> {\n const [revoked] = await db\n .update(apiKeys)\n .set({ revokedAt: new Date() })\n .where(eq(apiKeys.id, keyId))\n .returning();\n\n return !!revoked;\n}\n\nexport async function getUserApiKeys(userId: string): Promise<ApiKeyInfo[]> {\n const keys = await db\n .select()\n .from(apiKeys)\n .where(eq(apiKeys.userId, userId))\n .orderBy(apiKeys.createdAt);\n\n return keys.map((k) => ({\n id: k.id,\n name: k.name,\n prefix: k.keyPrefix,\n permissions: (k.permissions as Permission[]) || [],\n createdAt: k.createdAt,\n lastUsedAt: k.lastUsedAt,\n expiresAt: k.expiresAt,\n isRevoked: !!k.revokedAt,\n }));\n}\n\nexport async function rotateApiKey(\n keyId: string\n): Promise<{ apiKey: ApiKeyInfo; rawKey: string } | null> {\n // Get existing key info\n const [existing] = await db\n .select()\n .from(apiKeys)\n .where(eq(apiKeys.id, keyId))\n .limit(1);\n\n if (!existing || existing.revokedAt) {\n return null;\n }\n\n // Revoke old key\n await revokeApiKey(keyId);\n\n // Create new key with same settings\n return createApiKey({\n userId: existing.userId,\n name: existing.name,\n permissions: existing.permissions as Permission[],\n expiresInDays: existing.expiresAt\n ? Math.ceil((existing.expiresAt.getTime() - Date.now()) / (24 * 60 * 60 * 1000))\n : undefined,\n });\n}\n\n// Delete permanently (use revoke in most cases)\nexport async function deleteApiKey(keyId: string): Promise<boolean> {\n await db.delete(apiKeys).where(eq(apiKeys.id, keyId));\n return true;\n}\n","import { db } from \"../../db\";\nimport { sessions, users } from \"../../db/schema\";\nimport { eq, and, gt, lt } from \"drizzle-orm\";\nimport { randomBytes, createHash } from \"crypto\";\n\nconst SESSION_DURATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\nconst TOKEN_LENGTH = 32;\n\nexport interface SessionInfo {\n userId: string;\n sessionId: string;\n expiresAt: Date;\n deviceInfo?: {\n userAgent?: string;\n platform?: string;\n browser?: string;\n };\n}\n\nexport interface CreateSessionOptions {\n userId: string;\n deviceInfo?: {\n userAgent?: string;\n platform?: string;\n browser?: string;\n };\n ipAddress?: string;\n durationMs?: number;\n}\n\nfunction generateToken(): string {\n return randomBytes(TOKEN_LENGTH).toString(\"hex\");\n}\n\nfunction hashToken(token: string): string {\n return createHash(\"sha256\").update(token).digest(\"hex\");\n}\n\nexport async function createSession(\n options: CreateSessionOptions\n): Promise<{ session: SessionInfo; token: string }> {\n const { userId, deviceInfo, ipAddress, durationMs = SESSION_DURATION_MS } = options;\n\n const token = generateToken();\n const tokenHash = hashToken(token);\n const expiresAt = new Date(Date.now() + durationMs);\n\n const [session] = await db\n .insert(sessions)\n .values({\n userId,\n token: tokenHash,\n deviceInfo,\n ipAddress,\n expiresAt,\n })\n .returning();\n\n return {\n session: {\n userId: session.userId,\n sessionId: session.id,\n expiresAt: session.expiresAt,\n deviceInfo: session.deviceInfo as SessionInfo[\"deviceInfo\"],\n },\n token, // Return the raw token to the client (only time it's available)\n };\n}\n\nexport async function validateSession(token: string): Promise<SessionInfo | null> {\n const tokenHash = hashToken(token);\n const now = new Date();\n\n const [session] = await db\n .select()\n .from(sessions)\n .where(and(eq(sessions.token, tokenHash), gt(sessions.expiresAt, now)))\n .limit(1);\n\n if (!session) {\n return null;\n }\n\n // Update last active time\n await db\n .update(sessions)\n .set({ lastActiveAt: now })\n .where(eq(sessions.id, session.id));\n\n return {\n userId: session.userId,\n sessionId: session.id,\n expiresAt: session.expiresAt,\n deviceInfo: session.deviceInfo as SessionInfo[\"deviceInfo\"],\n };\n}\n\nexport async function invalidateSession(sessionId: string): Promise<boolean> {\n const result = await db.delete(sessions).where(eq(sessions.id, sessionId));\n return true;\n}\n\nexport async function invalidateAllUserSessions(userId: string): Promise<number> {\n const result = await db.delete(sessions).where(eq(sessions.userId, userId));\n return 0; // Drizzle doesn't return affected rows easily\n}\n\nexport async function getUserSessions(userId: string): Promise<SessionInfo[]> {\n const now = new Date();\n\n const userSessions = await db\n .select()\n .from(sessions)\n .where(and(eq(sessions.userId, userId), gt(sessions.expiresAt, now)))\n .orderBy(sessions.lastActiveAt);\n\n return userSessions.map((s) => ({\n userId: s.userId,\n sessionId: s.id,\n expiresAt: s.expiresAt,\n deviceInfo: s.deviceInfo as SessionInfo[\"deviceInfo\"],\n }));\n}\n\nexport async function refreshSession(\n sessionId: string,\n durationMs = SESSION_DURATION_MS\n): Promise<SessionInfo | null> {\n const newExpiresAt = new Date(Date.now() + durationMs);\n\n const [updated] = await db\n .update(sessions)\n .set({\n expiresAt: newExpiresAt,\n lastActiveAt: new Date(),\n })\n .where(eq(sessions.id, sessionId))\n .returning();\n\n if (!updated) {\n return null;\n }\n\n return {\n userId: updated.userId,\n sessionId: updated.id,\n expiresAt: updated.expiresAt,\n deviceInfo: updated.deviceInfo as SessionInfo[\"deviceInfo\"],\n };\n}\n\nexport async function cleanupExpiredSessions(): Promise<number> {\n const now = new Date();\n await db.delete(sessions).where(lt(sessions.expiresAt, now));\n return 0; // Cleanup completed\n}\n\n// Parse user agent string into device info\nexport function parseUserAgent(userAgent?: string): SessionInfo[\"deviceInfo\"] {\n if (!userAgent) return undefined;\n\n const info: SessionInfo[\"deviceInfo\"] = { userAgent };\n\n // Simple platform detection\n if (userAgent.includes(\"Windows\")) {\n info.platform = \"Windows\";\n } else if (userAgent.includes(\"Mac\")) {\n info.platform = \"macOS\";\n } else if (userAgent.includes(\"Linux\")) {\n info.platform = \"Linux\";\n } else if (userAgent.includes(\"Android\")) {\n info.platform = \"Android\";\n } else if (userAgent.includes(\"iPhone\") || userAgent.includes(\"iPad\")) {\n info.platform = \"iOS\";\n }\n\n // Simple browser detection\n if (userAgent.includes(\"Firefox\")) {\n info.browser = \"Firefox\";\n } else if (userAgent.includes(\"Chrome\")) {\n info.browser = \"Chrome\";\n } else if (userAgent.includes(\"Safari\")) {\n info.browser = \"Safari\";\n } else if (userAgent.includes(\"Edge\")) {\n info.browser = \"Edge\";\n }\n\n return info;\n}\n","/**\n * Gateway Token Utilities\n *\n * Shared helpers for gateway token authentication (OpenClaw-style).\n * Used by both the HTTP auth middleware and the WebSocket upgrade handler.\n */\n\nimport { env } from \"../../config/env\";\n\n/**\n * Read the configured gateway token. Returns undefined if not set,\n * which means auth is disabled (open access mode).\n */\nexport function getGatewayToken(): string | undefined {\n const token = env.GATEWAY_TOKEN;\n return token || undefined;\n}\n\n/**\n * Constant-time string comparison to prevent timing side-channel attacks.\n * Always compares the full length of `b` regardless of early mismatches.\n */\nexport function timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n // Still iterate to maintain roughly constant time\n let result = 1;\n for (let i = 0; i < b.length; i++) {\n result |= b.charCodeAt(i) ^ (a.charCodeAt(i % (a.length || 1)) || 0);\n }\n return false;\n }\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","/**\n * Auth Middleware — Gateway Token (OpenClaw-style)\n *\n * When GATEWAY_TOKEN is not set: all routes pass through (open mode for self-hosted).\n * When GATEWAY_TOKEN is set: requires Bearer token matching the gateway token,\n * with fallback to session tokens and API keys for programmatic access.\n */\n\nimport type { Context, MiddlewareHandler, Next } from \"hono\";\nimport { validateApiKey, hasPermission, type Permission } from \"./api-key-manager\";\nimport { validateSession } from \"./session-manager\";\nimport { logAudit } from \"./audit-logger\";\nimport { getGatewayToken, timingSafeEqual } from \"./gateway-utils\";\n\n// Routes that never require auth\nconst PUBLIC_ROUTES = [\"/health\", \"/api/system/status\", \"/api/pair\", \"/api/sdk/register\"];\n\n// SDK routes have their own internal sdkAuth middleware\nconst SDK_PREFIX = \"/api/sdk/\";\n\nexport function authMiddleware(): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const path = c.req.path;\n\n // 1. Public routes — always pass through\n if (PUBLIC_ROUTES.includes(path)) {\n return next();\n }\n\n // 2. SDK routes (except register) — skip, SDK's own sdkAuth handles them\n if (path.startsWith(SDK_PREFIX) && path !== \"/api/sdk/register\") {\n return next();\n }\n\n // 3. If GATEWAY_TOKEN is not configured, auth is disabled (open mode)\n const gatewayToken = getGatewayToken();\n if (!gatewayToken) {\n c.set(\"userId\", \"local\");\n c.set(\"permissions\", [\"*\"]);\n c.set(\"authMethod\", \"none\");\n return next();\n }\n\n // 4. GATEWAY_TOKEN is set — require authentication\n const authHeader = c.req.header(\"Authorization\");\n\n if (!authHeader || !authHeader.startsWith(\"Bearer \")) {\n return c.json({ error: \"Missing or invalid authorization header\" }, 401);\n }\n\n const token = authHeader.slice(7);\n\n // 4a. Check gateway token (fast, constant-time comparison)\n if (timingSafeEqual(token, gatewayToken)) {\n c.set(\"userId\", \"gateway\");\n c.set(\"permissions\", [\"*\"]);\n c.set(\"authMethod\", \"gateway\");\n\n logAudit({\n userId: \"gateway\",\n action: \"login\",\n resource: \"session\",\n details: { method: \"gateway_token\", path },\n }).catch(() => {});\n\n return next();\n }\n\n // 4b. Fall back to session validation\n const sessionInfo = await validateSession(token);\n if (sessionInfo) {\n c.set(\"userId\", sessionInfo.userId);\n c.set(\"permissions\", [\"*\"]);\n c.set(\"authMethod\", \"session\");\n\n logAudit({\n userId: sessionInfo.userId,\n action: \"login\",\n resource: \"session\",\n details: { method: \"session\", path },\n }).catch(() => {});\n\n return next();\n }\n\n // 4c. Fall back to API key validation\n const apiKeyResult = await validateApiKey(token);\n if (apiKeyResult.valid && apiKeyResult.apiKey && apiKeyResult.userId) {\n c.set(\"userId\", apiKeyResult.userId);\n c.set(\"permissions\", apiKeyResult.apiKey.permissions);\n c.set(\"authMethod\", \"api_key\");\n\n logAudit({\n userId: apiKeyResult.userId,\n action: \"login\",\n resource: \"api_key\",\n details: { method: \"api_key\", keyId: apiKeyResult.apiKey.id, path },\n }).catch(() => {});\n\n return next();\n }\n\n return c.json({ error: \"Invalid or expired credentials\" }, 401);\n };\n}\n\nexport function requirePermission(\n ...requiredPermissions: Permission[]\n): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const permissions = c.get(\"permissions\") as Permission[] | undefined;\n\n if (!permissions) {\n return c.json({ error: \"Not authenticated\" }, 401);\n }\n\n // Full access wildcard\n if (permissions.includes(\"*\")) {\n return next();\n }\n\n for (const required of requiredPermissions) {\n if (!hasPermission(permissions, required)) {\n return c.json({ error: \"Insufficient permissions\" }, 403);\n }\n }\n\n return next();\n };\n}\n\nexport function getAuthUserId(c: Context): string | undefined {\n return c.get(\"userId\") as string | undefined;\n}\n","/**\r\n * OSINT API Routes\r\n *\r\n * Provides REST endpoints for the Graph Explorer frontend component.\r\n * Queries the Postgres-backed knowledge graph (graphEntities / graphRelationships)\r\n * and exposes enrichment, entity-resolution, and analytics helpers.\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\nimport { db } from \"../../../db\";\r\nimport { graphEntities, graphRelationships } from \"../../../db/schema\";\r\nimport { eq, sql, desc, ilike, and } from \"drizzle-orm\";\r\nimport { env } from \"../../../config/env\";\r\nimport { createPublicRecords } from \"../../../integrations/public-records\";\r\nimport {\r\n resolveEntity,\r\n type EntityCandidate,\r\n} from \"../../../core/intelligence/entity-resolution\";\r\nimport { brainTelemetry } from \"../../../core/observability/brain-telemetry\";\r\nimport { audit } from \"../../../core/security/audit-logger\";\r\n\r\n// Lazy-init the public records facade (avoid startup cost if OSINT is disabled)\r\nlet _publicRecords: ReturnType<typeof createPublicRecords> | null = null;\r\nfunction getPublicRecords() {\r\n if (!_publicRecords) _publicRecords = createPublicRecords();\r\n return _publicRecords;\r\n}\r\n\r\nconst osint = new Hono();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Middleware — gate every route behind OSINT_ENABLED\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.use(\"*\", async (c, next) => {\r\n if (!env.OSINT_ENABLED) {\r\n return c.json({ error: \"OSINT features are disabled\" }, 403);\r\n }\r\n await next();\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /graph — graph data for D3 force-directed visualisation\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.get(\"/graph\", async (c) => {\r\n try {\r\n const graphStart = Date.now();\r\n const userId = c.req.query(\"userId\") || \"system\";\r\n const limit = Math.min(parseInt(c.req.query(\"limit\") || \"200\", 10), 1000);\r\n const since = c.req.query(\"since\"); // ISO date string for temporal filtering\r\n const until = c.req.query(\"until\"); // ISO date string for temporal filtering\r\n\r\n brainTelemetry.emitEvent({\r\n type: \"tool_start\", timestamp: graphStart,\r\n requestId: `osint-graph-${graphStart}`,\r\n data: { toolName: \"osint_graph_load\", since, until, limit },\r\n });\r\n\r\n // Build conditions for temporal filtering\r\n const conditions = [];\r\n if (since) {\r\n conditions.push(sql`${graphEntities.createdAt} >= ${new Date(since)}`);\r\n }\r\n if (until) {\r\n conditions.push(sql`${graphEntities.createdAt} <= ${new Date(until)}`);\r\n }\r\n\r\n // Fetch entities\r\n const query = db\r\n .select({\r\n id: graphEntities.id,\r\n name: graphEntities.name,\r\n type: graphEntities.type,\r\n importance: graphEntities.importance,\r\n description: graphEntities.description,\r\n attributes: graphEntities.attributes,\r\n aliases: graphEntities.aliases,\r\n createdAt: graphEntities.createdAt,\r\n })\r\n .from(graphEntities);\r\n\r\n const entities = conditions.length > 0\r\n ? await query.where(and(...conditions)).orderBy(desc(graphEntities.importance)).limit(limit)\r\n : await query.orderBy(desc(graphEntities.importance)).limit(limit);\r\n\r\n const entityIds = entities.map((e) => e.id);\r\n\r\n if (entityIds.length === 0) {\r\n return c.json({ nodes: [], edges: [] });\r\n }\r\n\r\n // Fetch relationships where both source and target are in the entity set\r\n const relationships = await db\r\n .select({\r\n id: graphRelationships.id,\r\n source: graphRelationships.sourceEntityId,\r\n target: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n })\r\n .from(graphRelationships)\r\n .where(\r\n and(\r\n sql`${graphRelationships.sourceEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map(id => sql`${id}`), sql`, `)}]::uuid[]`})`,\r\n sql`${graphRelationships.targetEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map(id => sql`${id}`), sql`, `)}]::uuid[]`})`\r\n )\r\n );\r\n\r\n brainTelemetry.emitEvent({\r\n type: \"tool_complete\", timestamp: Date.now(),\r\n requestId: `osint-graph-${graphStart}`,\r\n data: { toolName: \"osint_graph_load\", success: true, latencyMs: Date.now() - graphStart, nodeCount: entities.length, edgeCount: relationships.length },\r\n });\r\n\r\n return c.json({\r\n nodes: entities,\r\n edges: relationships,\r\n stats: {\r\n totalEntities: entities.length,\r\n totalRelationships: relationships.length,\r\n totalSources: new Set(\r\n entities.flatMap((e) => {\r\n const srcs = (e.attributes as any)?.sources;\r\n return Array.isArray(srcs) ? srcs.map((s: any) => s.type || \"unknown\") : [];\r\n })\r\n ).size,\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"[OSINT API] /graph error:\", error);\r\n return c.json({ error: \"Failed to fetch graph data\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /entity/:id — single entity with relationships\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.get(\"/entity/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n\r\n const results = await db\r\n .select()\r\n .from(graphEntities)\r\n .where(eq(graphEntities.id, id))\r\n .limit(1);\r\n\r\n if (results.length === 0) {\r\n return c.json({ error: \"Entity not found\" }, 404);\r\n }\r\n\r\n const entity = results[0];\r\n\r\n // Relationships where this entity is the source\r\n const outgoing = await db\r\n .select({\r\n id: graphRelationships.id,\r\n sourceEntityId: graphRelationships.sourceEntityId,\r\n targetEntityId: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n context: graphRelationships.context,\r\n attributes: graphRelationships.attributes,\r\n targetName: graphEntities.name,\r\n })\r\n .from(graphRelationships)\r\n .innerJoin(graphEntities, eq(graphRelationships.targetEntityId, graphEntities.id))\r\n .where(eq(graphRelationships.sourceEntityId, id));\r\n\r\n // Relationships where this entity is the target\r\n const incoming = await db\r\n .select({\r\n id: graphRelationships.id,\r\n sourceEntityId: graphRelationships.sourceEntityId,\r\n targetEntityId: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n context: graphRelationships.context,\r\n attributes: graphRelationships.attributes,\r\n sourceName: graphEntities.name,\r\n })\r\n .from(graphRelationships)\r\n .innerJoin(graphEntities, eq(graphRelationships.sourceEntityId, graphEntities.id))\r\n .where(eq(graphRelationships.targetEntityId, id));\r\n\r\n return c.json({\r\n entity,\r\n relationships: {\r\n outgoing,\r\n incoming,\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"[OSINT API] /entity/:id error:\", error);\r\n return c.json({ error: \"Failed to fetch entity\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// External API search helper\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Normalize FEC-style names from \"LAST, FIRST MIDDLE\" to \"First Middle Last\".\r\n */\r\nfunction normalizeFECName(raw: string): string {\r\n if (!raw.includes(\",\")) return toTitleCase(raw);\r\n const [last, ...rest] = raw.split(\",\").map((s) => s.trim());\r\n const first = rest.join(\" \").trim();\r\n if (!first) return toTitleCase(last);\r\n return toTitleCase(`${first} ${last}`);\r\n}\r\n\r\nfunction toTitleCase(s: string): string {\r\n return s\r\n .toLowerCase()\r\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\r\n}\r\n\r\n/**\r\n * Query FEC and OpenCorporates for a search term, resolve results into\r\n * the local knowledge graph, and return the newly-created entity IDs.\r\n */\r\nasync function searchExternalAPIs(query: string): Promise<string[]> {\r\n const pr = getPublicRecords();\r\n const newEntityIds: string[] = [];\r\n\r\n // Run FEC (candidates + committees) and OpenCorporates in parallel.\r\n // Each call is wrapped so a single API failure doesn't kill the whole search.\r\n const [fecCandidates, fecCommittees, ocCompanies] = await Promise.all([\r\n pr.fec\r\n .searchCandidates(query)\r\n .then((r) => r.slice(0, 10))\r\n .catch((err) => {\r\n console.warn(\"[OSINT API] FEC candidates search failed:\", err.message);\r\n return [] as any[];\r\n }),\r\n pr.fec\r\n .searchCommittees(query)\r\n .then((r) => r.slice(0, 10))\r\n .catch((err) => {\r\n console.warn(\"[OSINT API] FEC committees search failed:\", err.message);\r\n return [] as any[];\r\n }),\r\n pr.opencorporates\r\n .searchCompanies(query, \"us\")\r\n .then((r) => r.slice(0, 10))\r\n .catch((err) => {\r\n console.warn(\"[OSINT API] OpenCorporates search failed:\", err.message);\r\n return [] as any[];\r\n }),\r\n ]);\r\n\r\n // Build entity candidates\r\n const candidates: EntityCandidate[] = [];\r\n\r\n for (const c of fecCandidates) {\r\n candidates.push({\r\n name: normalizeFECName(c.name),\r\n type: \"person\",\r\n source: \"fec\",\r\n identifiers: { fecId: c.candidateId },\r\n attributes: {\r\n party: c.party,\r\n office: c.office,\r\n state: c.state,\r\n district: c.district,\r\n cycles: c.cycles,\r\n },\r\n });\r\n }\r\n\r\n for (const c of fecCommittees) {\r\n candidates.push({\r\n name: toTitleCase(c.name),\r\n type: \"committee\",\r\n source: \"fec\",\r\n identifiers: { fecId: c.committeeId },\r\n attributes: {\r\n designation: c.designation,\r\n committeeType: c.type,\r\n party: c.party,\r\n state: c.state,\r\n treasurerName: c.treasurerName,\r\n },\r\n });\r\n }\r\n\r\n for (const c of ocCompanies) {\r\n candidates.push({\r\n name: c.name,\r\n type: \"organization\",\r\n source: \"opencorporates\",\r\n attributes: {\r\n companyNumber: c.companyNumber,\r\n jurisdiction: c.jurisdictionCode,\r\n status: c.status,\r\n companyType: c.companyType,\r\n incorporationDate: c.incorporationDate,\r\n registeredAddress: c.registeredAddress,\r\n openCorporatesUrl: c.openCorporatesUrl,\r\n },\r\n });\r\n }\r\n\r\n // Resolve each candidate (dedup / insert) — run sequentially to avoid\r\n // DB race conditions on the same entity name\r\n for (const candidate of candidates) {\r\n try {\r\n const resolved = await resolveEntity(candidate);\r\n newEntityIds.push(resolved.entityId);\r\n } catch (err: any) {\r\n console.warn(`[OSINT API] Entity resolution failed for \"${candidate.name}\":`, err.message);\r\n }\r\n }\r\n\r\n return [...new Set(newEntityIds)]; // deduplicate\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /search — search entities by name\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.get(\"/search\", async (c) => {\r\n try {\r\n const q = c.req.query(\"q\");\r\n const type = c.req.query(\"type\");\r\n const limit = Math.min(parseInt(c.req.query(\"limit\") || \"25\", 10), 100);\r\n\r\n if (!q) {\r\n return c.json({ error: \"Query parameter 'q' is required\" }, 400);\r\n }\r\n\r\n const searchStart = Date.now();\r\n brainTelemetry.emitEvent({\r\n type: \"tool_start\", timestamp: searchStart,\r\n requestId: `osint-search-${searchStart}`,\r\n data: { toolName: \"osint_search\", query: q, entityType: type },\r\n });\r\n\r\n // 1. Local DB search\r\n let query = db\r\n .select()\r\n .from(graphEntities)\r\n .where(\r\n type\r\n ? and(ilike(graphEntities.name, `%${q}%`), eq(graphEntities.type, type as any))\r\n : ilike(graphEntities.name, `%${q}%`)\r\n )\r\n .orderBy(desc(graphEntities.importance))\r\n .limit(limit);\r\n\r\n let results = await query;\r\n let externalSearched = false;\r\n\r\n // 2. If local results are sparse, search external APIs and re-query\r\n if (results.length < 3 && q.length >= 2) {\r\n try {\r\n console.log(`[OSINT API] Local results (${results.length}) < 3 for \"${q}\", querying external APIs...`);\r\n const externalIds = await searchExternalAPIs(q);\r\n externalSearched = true;\r\n\r\n if (externalIds.length > 0) {\r\n // Re-run local search: match by name OR by the newly-ingested entity IDs\r\n // (needed because FEC names like \"PELOSI, NANCY\" get normalized to \"Nancy Pelosi\"\r\n // but the ILIKE may still not match all variations)\r\n const nameCondition = type\r\n ? and(ilike(graphEntities.name, `%${q}%`), eq(graphEntities.type, type as any))\r\n : ilike(graphEntities.name, `%${q}%`);\r\n\r\n const idCondition = sql`${graphEntities.id} = ANY(${sql`ARRAY[${sql.join(externalIds.map((id: string) => sql`${id}`), sql`, `)}]::uuid[]`})`;\r\n\r\n results = await db\r\n .select()\r\n .from(graphEntities)\r\n .where(sql`(${nameCondition}) OR (${idCondition})`)\r\n .orderBy(desc(graphEntities.importance))\r\n .limit(limit);\r\n }\r\n } catch (extErr: any) {\r\n console.warn(\"[OSINT API] External search failed (graceful):\", extErr.message);\r\n }\r\n }\r\n\r\n // 3. Fetch relationships between matched entities for graph view\r\n const entityIds = results.map((e: any) => e.id);\r\n let edges: any[] = [];\r\n if (entityIds.length > 1) {\r\n edges = await db\r\n .select({\r\n id: graphRelationships.id,\r\n source: graphRelationships.sourceEntityId,\r\n target: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n })\r\n .from(graphRelationships)\r\n .where(\r\n and(\r\n sql`${graphRelationships.sourceEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id: string) => sql`${id}`), sql`, `)}]::uuid[]`})`,\r\n sql`${graphRelationships.targetEntityId} = ANY(${sql`ARRAY[${sql.join(entityIds.map((id: string) => sql`${id}`), sql`, `)}]::uuid[]`})`\r\n )\r\n );\r\n }\r\n\r\n const searchLatency = Date.now() - searchStart;\r\n brainTelemetry.emitEvent({\r\n type: \"tool_complete\", timestamp: Date.now(),\r\n requestId: `osint-search-${searchStart}`,\r\n data: { toolName: \"osint_search\", success: true, latencyMs: searchLatency, resultCount: results.length, externalSearched },\r\n });\r\n\r\n // Audit log the search\r\n audit.toolUse(\"web:dashboard\", \"osint_search\", { query: q, entityType: type, resultCount: results.length, externalSearched, latencyMs: searchLatency }, true).catch(() => {});\r\n\r\n return c.json({ results, edges, total: results.length, externalSearched });\r\n } catch (error: any) {\r\n console.error(\"[OSINT API] /search error:\", error);\r\n brainTelemetry.emitEvent({\r\n type: \"tool_complete\", timestamp: Date.now(),\r\n requestId: `osint-search-${Date.now()}`,\r\n data: { toolName: \"osint_search\", success: false },\r\n });\r\n audit.toolUse(\"web:dashboard\", \"osint_search\", { query: c.req.query(\"q\"), error: error?.message }, false).catch(() => {});\r\n return c.json({ error: \"Search failed\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// POST /enrich — trigger enrichment for an entity\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.post(\"/enrich\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n entityId: string;\r\n sources?: string[];\r\n depth?: number;\r\n }>();\r\n\r\n if (!body.entityId) {\r\n return c.json({ error: \"entityId is required\" }, 400);\r\n }\r\n\r\n // Verify entity exists\r\n const entity = await db\r\n .select()\r\n .from(graphEntities)\r\n .where(eq(graphEntities.id, body.entityId))\r\n .limit(1);\r\n\r\n if (entity.length === 0) {\r\n return c.json({ error: \"Entity not found\" }, 404);\r\n }\r\n\r\n const enrichStart = Date.now();\r\n const entityName = (entity[0] as any).name || body.entityId;\r\n brainTelemetry.emitEvent({\r\n type: \"tool_start\", timestamp: enrichStart,\r\n requestId: `osint-enrich-${enrichStart}`,\r\n data: { toolName: \"osint_enrich\", entityId: body.entityId, entityName, sources: body.sources, depth: body.depth ?? 1 },\r\n });\r\n\r\n // Dynamic import — the enrichment pipeline may not be built yet\r\n const { enrichEntity } = await import(\r\n \"../../../core/intelligence/enrichment-pipeline\"\r\n );\r\n\r\n const result = await enrichEntity(body.entityId, body.sources, body.depth ?? 1);\r\n\r\n const enrichLatency = Date.now() - enrichStart;\r\n brainTelemetry.emitEvent({\r\n type: \"tool_complete\", timestamp: Date.now(),\r\n requestId: `osint-enrich-${enrichStart}`,\r\n data: { toolName: \"osint_enrich\", success: true, latencyMs: enrichLatency, entityName, newEntities: result?.newEntitiesCreated, newRelationships: result?.newRelationshipsCreated },\r\n });\r\n\r\n // Audit log the enrichment\r\n audit.toolUse(\"web:dashboard\", \"osint_enrich\", { entityId: body.entityId, entityName, sources: body.sources, depth: body.depth, newEntities: result?.newEntitiesCreated, newRelationships: result?.newRelationshipsCreated, latencyMs: enrichLatency }, true).catch(() => {});\r\n\r\n return c.json({ success: true, result });\r\n } catch (error: any) {\r\n // Distinguish \"module not found\" from runtime errors\r\n if (error?.code === \"MODULE_NOT_FOUND\" || error?.message?.includes(\"Cannot find module\")) {\r\n return c.json({ error: \"Enrichment pipeline is not available\" }, 501);\r\n }\r\n console.error(\"[OSINT API] /enrich error:\", error);\r\n brainTelemetry.emitEvent({\r\n type: \"tool_complete\", timestamp: Date.now(),\r\n requestId: `osint-enrich-${Date.now()}`,\r\n data: { toolName: \"osint_enrich\", success: false, error: error?.message },\r\n });\r\n audit.toolUse(\"web:dashboard\", \"osint_enrich\", { error: error?.message }, false).catch(() => {});\r\n return c.json({ error: \"Enrichment failed\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /financial-flow — Sankey diagram data\r\n// ---------------------------------------------------------------------------\r\n\r\nconst FINANCIAL_REL_TYPES = [\"donated_to\", \"funded\", \"awarded_contract\", \"grant_to\", \"paid\"];\r\n\r\nosint.get(\"/financial-flow\", async (c) => {\r\n try {\r\n const entityId = c.req.query(\"entityId\");\r\n\r\n if (!entityId) {\r\n return c.json({ error: \"Query parameter 'entityId' is required\" }, 400);\r\n }\r\n\r\n // Verify entity exists\r\n const rootEntity = await db\r\n .select({ id: graphEntities.id, name: graphEntities.name })\r\n .from(graphEntities)\r\n .where(eq(graphEntities.id, entityId))\r\n .limit(1);\r\n\r\n if (rootEntity.length === 0) {\r\n return c.json({ error: \"Entity not found\" }, 404);\r\n }\r\n\r\n // Fetch financial relationships involving this entity (outgoing and incoming)\r\n const outgoing = await db\r\n .select({\r\n id: graphRelationships.id,\r\n sourceEntityId: graphRelationships.sourceEntityId,\r\n targetEntityId: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n attributes: graphRelationships.attributes,\r\n })\r\n .from(graphRelationships)\r\n .where(\r\n and(\r\n eq(graphRelationships.sourceEntityId, entityId),\r\n sql`${graphRelationships.type} = ANY(${sql`ARRAY[${sql.join(FINANCIAL_REL_TYPES.map(t => sql`${t}`), sql`, `)}]::text[]`})`\r\n )\r\n );\r\n\r\n const incoming = await db\r\n .select({\r\n id: graphRelationships.id,\r\n sourceEntityId: graphRelationships.sourceEntityId,\r\n targetEntityId: graphRelationships.targetEntityId,\r\n type: graphRelationships.type,\r\n strength: graphRelationships.strength,\r\n attributes: graphRelationships.attributes,\r\n })\r\n .from(graphRelationships)\r\n .where(\r\n and(\r\n eq(graphRelationships.targetEntityId, entityId),\r\n sql`${graphRelationships.type} = ANY(${sql`ARRAY[${sql.join(FINANCIAL_REL_TYPES.map(t => sql`${t}`), sql`, `)}]::text[]`})`\r\n )\r\n );\r\n\r\n const allRels = [...outgoing, ...incoming];\r\n\r\n // Collect unique entity IDs referenced in the relationships\r\n const relatedIds = new Set<string>();\r\n relatedIds.add(entityId);\r\n for (const rel of allRels) {\r\n relatedIds.add(rel.sourceEntityId);\r\n relatedIds.add(rel.targetEntityId);\r\n }\r\n\r\n // Fetch details for all involved entities\r\n const relatedEntities = await db\r\n .select({\r\n id: graphEntities.id,\r\n name: graphEntities.name,\r\n type: graphEntities.type,\r\n })\r\n .from(graphEntities)\r\n .where(sql`${graphEntities.id} = ANY(${sql`ARRAY[${sql.join([...relatedIds].map(id => sql`${id}`), sql`, `)}]::uuid[]`})`);\r\n\r\n // Build nodes with id, name, type, and aggregated value\r\n const entityMap = new Map(relatedEntities.map((e) => [e.id, e]));\r\n\r\n // Calculate total value flowing through each node\r\n const nodeValues = new Map<string, number>();\r\n for (const rel of allRels) {\r\n const attrs = (rel.attributes as Record<string, unknown>) || {};\r\n const amount = (attrs.amount as number) || rel.strength || 1;\r\n nodeValues.set(rel.sourceEntityId, (nodeValues.get(rel.sourceEntityId) || 0) + amount);\r\n nodeValues.set(rel.targetEntityId, (nodeValues.get(rel.targetEntityId) || 0) + amount);\r\n }\r\n\r\n const nodes = relatedEntities.map((e) => ({\r\n id: e.id,\r\n name: e.name,\r\n type: e.type,\r\n value: nodeValues.get(e.id) || 0,\r\n }));\r\n\r\n // Build links with string IDs\r\n const links = allRels\r\n .filter((rel) => entityMap.has(rel.sourceEntityId) && entityMap.has(rel.targetEntityId))\r\n .map((rel) => {\r\n const attrs = (rel.attributes as Record<string, unknown>) || {};\r\n return {\r\n source: rel.sourceEntityId,\r\n target: rel.targetEntityId,\r\n value: (attrs.amount as number) || rel.strength || 1,\r\n description: `${rel.type.replace(/_/g, \" \")}${attrs.period ? ` (${attrs.period})` : \"\"}`,\r\n };\r\n });\r\n\r\n return c.json({ nodes, links });\r\n } catch (error) {\r\n console.error(\"[OSINT API] /financial-flow error:\", error);\r\n return c.json({ error: \"Failed to fetch financial flow data\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /duplicates — find potential duplicate entities\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.get(\"/duplicates\", async (c) => {\r\n try {\r\n const threshold = parseFloat(c.req.query(\"threshold\") || \"0.85\");\r\n\r\n const { findDuplicates } = await import(\r\n \"../../../core/intelligence/entity-resolution\"\r\n );\r\n\r\n const duplicates = await findDuplicates(threshold);\r\n\r\n return c.json({ duplicates, total: duplicates.length });\r\n } catch (error) {\r\n console.error(\"[OSINT API] /duplicates error:\", error);\r\n return c.json({ error: \"Failed to find duplicates\" }, 500);\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /stats — OSINT graph statistics\r\n// ---------------------------------------------------------------------------\r\n\r\nosint.get(\"/stats\", async (c) => {\r\n try {\r\n // Total entities\r\n const totalEntitiesResult = await db\r\n .select({ count: sql<number>`count(*)::int` })\r\n .from(graphEntities);\r\n const totalEntities = totalEntitiesResult[0]?.count ?? 0;\r\n\r\n // Total relationships\r\n const totalRelsResult = await db\r\n .select({ count: sql<number>`count(*)::int` })\r\n .from(graphRelationships);\r\n const totalRelationships = totalRelsResult[0]?.count ?? 0;\r\n\r\n // Entities by type\r\n const entitiesByType = await db\r\n .select({\r\n type: graphEntities.type,\r\n count: sql<number>`count(*)::int`,\r\n })\r\n .from(graphEntities)\r\n .groupBy(graphEntities.type)\r\n .orderBy(desc(sql`count(*)`));\r\n\r\n // Top entities by mention count\r\n const topEntities = await db\r\n .select({\r\n id: graphEntities.id,\r\n name: graphEntities.name,\r\n type: graphEntities.type,\r\n mentionCount: graphEntities.mentionCount,\r\n importance: graphEntities.importance,\r\n })\r\n .from(graphEntities)\r\n .orderBy(desc(graphEntities.mentionCount))\r\n .limit(20);\r\n\r\n return c.json({\r\n totalEntities,\r\n totalRelationships,\r\n entitiesByType,\r\n topEntities,\r\n });\r\n } catch (error) {\r\n console.error(\"[OSINT API] /stats error:\", error);\r\n return c.json({ error: \"Failed to fetch statistics\" }, 500);\r\n }\r\n});\r\n\r\nexport { osint as osintRoutes };\r\n","/**\r\n * Email API Routes\r\n *\r\n * Provides REST endpoints for reading, sending, searching, and managing emails\r\n * via IMAP and SMTP. Supports Dovecot master-user auth and direct credential auth.\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\nimport { env } from \"../../../config/env\";\r\nimport {\r\n ImapClient,\r\n type EmailMessage,\r\n type EmailAttachment,\r\n} from \"../../../integrations/email/imap-client\";\r\nimport { SmtpClient } from \"../../../integrations/email/smtp-client\";\r\n\r\nconst email = new Hono();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n// Connect to IMAP with fallback: local Dovecot → remote IMAP server.\r\n// Matches the tool-level connectImapWithFallback() in src/tools/index.ts.\r\nasync function connectImapClientWithFallback(emailAddress: string): Promise<ImapClient> {\r\n if (env.EMAIL_MASTER_USER && env.EMAIL_MASTER_PASSWORD) {\r\n const authUser = `${emailAddress}*${env.EMAIL_MASTER_USER}`;\r\n\r\n // Try local Dovecot first\r\n const localClient = new ImapClient({\r\n host: env.EMAIL_LOCAL_IMAP_HOST || \"127.0.0.1\",\r\n port: env.EMAIL_LOCAL_IMAP_PORT || 993,\r\n secure: true,\r\n user: authUser,\r\n password: env.EMAIL_MASTER_PASSWORD,\r\n tls: { rejectUnauthorized: false },\r\n });\r\n\r\n try {\r\n await localClient.connect();\r\n return localClient;\r\n } catch (localErr: any) {\r\n // Fall back to remote IMAP server\r\n const remoteHost = env.EMAIL_IMAP_HOST;\r\n const remotePort = env.EMAIL_IMAP_PORT || 993;\r\n\r\n if (!remoteHost) throw localErr;\r\n\r\n console.log(\r\n `[Email API] Local IMAP unavailable (${localErr.code || localErr.message}), falling back to ${remoteHost}:${remotePort}`\r\n );\r\n\r\n const remoteClient = new ImapClient({\r\n host: remoteHost,\r\n port: remotePort,\r\n secure: true,\r\n user: authUser,\r\n password: env.EMAIL_MASTER_PASSWORD,\r\n tls: { rejectUnauthorized: false },\r\n });\r\n\r\n await remoteClient.connect();\r\n return remoteClient;\r\n }\r\n } else if (env.EMAIL_USER && env.EMAIL_PASSWORD) {\r\n const client = new ImapClient({\r\n host: env.EMAIL_IMAP_HOST || \"imap.gmail.com\",\r\n port: env.EMAIL_IMAP_PORT || 993,\r\n secure: env.EMAIL_IMAP_SECURE !== false,\r\n user: env.EMAIL_USER,\r\n password: env.EMAIL_PASSWORD,\r\n });\r\n await client.connect();\r\n return client;\r\n }\r\n throw new Error(\"Email not configured\");\r\n}\r\n\r\nfunction createSmtpClient(fromAddress: string): SmtpClient {\r\n if (env.EMAIL_MASTER_USER) {\r\n return new SmtpClient(\r\n {\r\n host: env.EMAIL_LOCAL_SMTP_HOST || \"127.0.0.1\",\r\n port: env.EMAIL_LOCAL_SMTP_PORT || 25,\r\n secure: false,\r\n auth: { user: \"\", pass: \"\" },\r\n tls: { rejectUnauthorized: false },\r\n },\r\n fromAddress\r\n );\r\n } else if (env.EMAIL_USER && env.EMAIL_PASSWORD) {\r\n return new SmtpClient(\r\n {\r\n host: env.EMAIL_SMTP_HOST || \"smtp.gmail.com\",\r\n port: env.EMAIL_SMTP_PORT || 587,\r\n secure: env.EMAIL_SMTP_SECURE === true,\r\n auth: { user: env.EMAIL_USER, pass: env.EMAIL_PASSWORD },\r\n },\r\n fromAddress\r\n );\r\n }\r\n throw new Error(\"Email not configured\");\r\n}\r\n\r\nfunction serializeEmail(email: EmailMessage, includeBody: boolean): Record<string, unknown> {\r\n const serialized: Record<string, unknown> = {\r\n id: email.id,\r\n uid: email.uid,\r\n messageId: email.messageId,\r\n subject: email.subject,\r\n from: email.from,\r\n to: email.to,\r\n cc: email.cc,\r\n bcc: email.bcc,\r\n date: email.date.toISOString(),\r\n text: includeBody ? email.text : email.snippet,\r\n html: includeBody ? email.html : \"\",\r\n snippet: email.snippet,\r\n attachments: email.attachments.map((a) => ({\r\n filename: a.filename,\r\n contentType: a.contentType,\r\n size: a.size,\r\n contentId: a.contentId,\r\n hasContent: !!a.content,\r\n })),\r\n flags: email.flags,\r\n labels: email.labels,\r\n threadId: email.threadId,\r\n inReplyTo: email.inReplyTo,\r\n references: email.references,\r\n headers: Object.fromEntries(email.headers),\r\n };\r\n\r\n return serialized;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Middleware — gate every route behind email config check\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.use(\"*\", async (c, next) => {\r\n if (!env.EMAIL_MASTER_USER && !env.EMAIL_USER) {\r\n return c.json(\r\n { error: \"Email not configured. Set EMAIL_MASTER_USER or EMAIL_USER in .env\" },\r\n 503\r\n );\r\n }\r\n await next();\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /folders — list all mail folders\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.get(\"/folders\", async (c) => {\r\n const emailAddress = c.req.query(\"email_address\");\r\n if (!emailAddress) {\r\n return c.json({ error: \"Query parameter 'email_address' is required\" }, 400);\r\n }\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(emailAddress);\r\n const folders = await imap.listFolders();\r\n return c.json(folders);\r\n } catch (error) {\r\n console.error(\"[Email API] /folders error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to list folders\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /inbox — list emails in a folder\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.get(\"/inbox\", async (c) => {\r\n const emailAddress = c.req.query(\"email_address\");\r\n if (!emailAddress) {\r\n return c.json({ error: \"Query parameter 'email_address' is required\" }, 400);\r\n }\r\n\r\n const folder = c.req.query(\"folder\") || \"INBOX\";\r\n const limit = c.req.query(\"limit\") || \"20\";\r\n const offset = c.req.query(\"offset\") || \"0\";\r\n const unreadOnly = c.req.query(\"unread_only\") === \"true\";\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(emailAddress);\r\n\r\n let emails: EmailMessage[];\r\n if (unreadOnly) {\r\n emails = await imap.searchEmails({\r\n folder,\r\n seen: false,\r\n limit: parseInt(limit),\r\n });\r\n } else {\r\n emails = await imap.fetchEmails(folder, {\r\n limit: parseInt(limit),\r\n offset: parseInt(offset),\r\n });\r\n }\r\n\r\n return c.json({\r\n emails: emails.map((e) => serializeEmail(e, false)),\r\n folder,\r\n });\r\n } catch (error) {\r\n console.error(\"[Email API] /inbox error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to fetch emails\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /message/:uid — fetch a single email by UID\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.get(\"/message/:uid\", async (c) => {\r\n const emailAddress = c.req.query(\"email_address\");\r\n if (!emailAddress) {\r\n return c.json({ error: \"Query parameter 'email_address' is required\" }, 400);\r\n }\r\n\r\n const uid = parseInt(c.req.param(\"uid\"));\r\n const folder = c.req.query(\"folder\") || \"INBOX\";\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(emailAddress);\r\n\r\n const emailMsg = await imap.fetchEmail(uid, folder);\r\n if (!emailMsg) {\r\n return c.json({ error: \"Email not found\" }, 404);\r\n }\r\n\r\n await imap.markAsRead(uid, folder);\r\n\r\n return c.json(serializeEmail(emailMsg, true));\r\n } catch (error) {\r\n console.error(\"[Email API] /message/:uid error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to fetch email\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// GET /attachment/:uid/:index — download an attachment\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.get(\"/attachment/:uid/:index\", async (c) => {\r\n const emailAddress = c.req.query(\"email_address\");\r\n if (!emailAddress) {\r\n return c.json({ error: \"Query parameter 'email_address' is required\" }, 400);\r\n }\r\n\r\n const uid = parseInt(c.req.param(\"uid\"));\r\n const index = parseInt(c.req.param(\"index\"));\r\n const folder = c.req.query(\"folder\") || \"INBOX\";\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(emailAddress);\r\n\r\n const emailMsg = await imap.fetchEmail(uid, folder);\r\n if (!emailMsg) {\r\n return c.json({ error: \"Email not found\" }, 404);\r\n }\r\n\r\n const attachment = emailMsg.attachments[index];\r\n if (!attachment) {\r\n return c.json({ error: \"Attachment not found\" }, 404);\r\n }\r\n\r\n if (!attachment.content) {\r\n return c.json({ error: \"Attachment content not available\" }, 404);\r\n }\r\n\r\n return new Response(new Uint8Array(attachment.content) as any, {\r\n headers: {\r\n \"Content-Type\": attachment.contentType || \"application/octet-stream\",\r\n \"Content-Disposition\": `attachment; filename=\"${attachment.filename}\"`,\r\n \"Content-Length\": String(attachment.size || attachment.content.length),\r\n },\r\n });\r\n } catch (error) {\r\n console.error(\"[Email API] /attachment/:uid/:index error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to fetch attachment\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// POST /send — send a new email\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.post(\"/send\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n from: string;\r\n to: string | string[];\r\n cc?: string | string[];\r\n bcc?: string | string[];\r\n subject: string;\r\n text?: string;\r\n html?: string;\r\n attachments?: { filename: string; content: string; contentType: string }[];\r\n }>();\r\n\r\n if (!body.from || !body.to || !body.subject) {\r\n return c.json({ error: \"Fields 'from', 'to', and 'subject' are required\" }, 400);\r\n }\r\n\r\n const smtp = createSmtpClient(body.from);\r\n\r\n const convertedAttachments = body.attachments?.map((a) => ({\r\n filename: a.filename,\r\n contentType: a.contentType,\r\n size: Buffer.from(a.content, \"base64\").length,\r\n content: Buffer.from(a.content, \"base64\"),\r\n }));\r\n\r\n const result = await smtp.send({\r\n to: body.to,\r\n cc: body.cc,\r\n bcc: body.bcc,\r\n subject: body.subject,\r\n text: body.text,\r\n html: body.html,\r\n attachments: convertedAttachments,\r\n });\r\n\r\n return c.json(result);\r\n } catch (error) {\r\n console.error(\"[Email API] /send error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to send email\" },\r\n 500\r\n );\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// POST /reply — reply to an existing email\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.post(\"/reply\", async (c) => {\r\n const body = await c.req.json<{\r\n email_address: string;\r\n email_uid: number;\r\n folder?: string;\r\n body: string;\r\n html?: string;\r\n reply_all?: boolean;\r\n attachments?: { filename: string; content: string; contentType: string }[];\r\n }>();\r\n\r\n if (!body.email_address || !body.email_uid || !body.body) {\r\n return c.json(\r\n { error: \"Fields 'email_address', 'email_uid', and 'body' are required\" },\r\n 400\r\n );\r\n }\r\n\r\n const folder = body.folder || \"INBOX\";\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(body.email_address);\r\n\r\n const originalEmail = await imap.fetchEmail(body.email_uid, folder);\r\n if (!originalEmail) {\r\n return c.json({ error: \"Original email not found\" }, 404);\r\n }\r\n\r\n const smtp = createSmtpClient(body.email_address);\r\n\r\n const convertedAttachments = body.attachments?.map((a) => ({\r\n filename: a.filename,\r\n contentType: a.contentType,\r\n size: Buffer.from(a.content, \"base64\").length,\r\n content: Buffer.from(a.content, \"base64\"),\r\n }));\r\n\r\n let result;\r\n if (body.reply_all) {\r\n result = await smtp.replyAll(\r\n originalEmail,\r\n { text: body.body, html: body.html, attachments: convertedAttachments },\r\n body.email_address\r\n );\r\n } else {\r\n result = await smtp.reply(originalEmail, {\r\n text: body.body,\r\n html: body.html,\r\n attachments: convertedAttachments,\r\n });\r\n }\r\n\r\n return c.json(result);\r\n } catch (error) {\r\n console.error(\"[Email API] /reply error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to send reply\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// POST /search — search emails\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.post(\"/search\", async (c) => {\r\n const body = await c.req.json<{\r\n email_address: string;\r\n from?: string;\r\n to?: string;\r\n subject?: string;\r\n body?: string;\r\n since?: string;\r\n before?: string;\r\n unread_only?: boolean;\r\n folder?: string;\r\n limit?: number;\r\n }>();\r\n\r\n if (!body.email_address) {\r\n return c.json({ error: \"Field 'email_address' is required\" }, 400);\r\n }\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(body.email_address);\r\n\r\n const searchOptions = {\r\n folder: body.folder || \"INBOX\",\r\n from: body.from,\r\n to: body.to,\r\n subject: body.subject,\r\n body: body.body,\r\n since: body.since ? new Date(body.since) : undefined,\r\n before: body.before ? new Date(body.before) : undefined,\r\n seen: body.unread_only ? false : undefined,\r\n limit: body.limit,\r\n };\r\n\r\n const emails = await imap.searchEmails(searchOptions);\r\n\r\n return c.json({\r\n emails: emails.map((e) => serializeEmail(e, false)),\r\n });\r\n } catch (error) {\r\n console.error(\"[Email API] /search error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Search failed\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// POST /flag — flag/unflag/read/unread/delete an email\r\n// ---------------------------------------------------------------------------\r\n\r\nemail.post(\"/flag\", async (c) => {\r\n const body = await c.req.json<{\r\n email_address: string;\r\n uid: number;\r\n folder?: string;\r\n action: \"read\" | \"unread\" | \"flag\" | \"unflag\" | \"delete\";\r\n }>();\r\n\r\n if (!body.email_address || !body.uid || !body.action) {\r\n return c.json(\r\n { error: \"Fields 'email_address', 'uid', and 'action' are required\" },\r\n 400\r\n );\r\n }\r\n\r\n const folder = body.folder || \"INBOX\";\r\n\r\n let imap: ImapClient | null = null;\r\n try {\r\n imap = await connectImapClientWithFallback(body.email_address);\r\n\r\n switch (body.action) {\r\n case \"read\":\r\n await imap.markAsRead(body.uid, folder);\r\n break;\r\n case \"unread\":\r\n await imap.markAsUnread(body.uid, folder);\r\n break;\r\n case \"flag\":\r\n await imap.flagEmail(body.uid, folder);\r\n break;\r\n case \"unflag\":\r\n await imap.unflagEmail(body.uid, folder);\r\n break;\r\n case \"delete\":\r\n await imap.deleteEmail(body.uid, folder);\r\n break;\r\n default:\r\n return c.json({ error: `Unknown action: ${body.action}` }, 400);\r\n }\r\n\r\n return c.json({ success: true });\r\n } catch (error) {\r\n console.error(\"[Email API] /flag error:\", error);\r\n return c.json(\r\n { error: error instanceof Error ? error.message : \"Failed to perform action\" },\r\n 500\r\n );\r\n } finally {\r\n if (imap) {\r\n await imap.disconnect().catch(() => {});\r\n }\r\n }\r\n});\r\n\r\nexport { email as emailRoutes };\r\n","import { Hono } from \"hono\";\nimport { executeTool, TOOLS } from \"../../../tools\";\nimport { chatWithTools, type Message, type ChatOptions } from \"../../../core/brain\";\nimport { prioritizeTools, getAppProfile } from \"../../../core/app-profiles\";\nimport { storeMemory, searchMemories } from \"../../../core/memory\";\nimport { env } from \"../../../config/env\";\n\ntype SdkEnv = {\n Variables: {\n sdkApp: RegisteredApp;\n };\n};\n\n// In-memory app registry (production would use DB)\ninterface RegisteredApp {\n id: string;\n name: string;\n type: string;\n apiKey: string;\n callbackUrl?: string;\n registeredAt: Date;\n lastSeen: Date;\n}\n\nconst registeredApps = new Map<string, RegisteredApp>();\n\n// Generate a simple UUID-like key\nfunction generateApiKey(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n const segments = [8, 4, 4, 4, 12];\n return \"osk_\" + segments\n .map((len) => Array.from({ length: len }, () => chars[Math.floor(Math.random() * chars.length)]).join(\"\"))\n .join(\"-\");\n}\n\n// Auth middleware - validates API key\nasync function sdkAuth(c: any, next: any) {\n const authHeader = c.req.header(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer osk_\")) {\n return c.json({ error: \"Invalid or missing API key. Register at POST /api/sdk/register\" }, 401);\n }\n\n const apiKey = authHeader.slice(7);\n const app = Array.from(registeredApps.values()).find((a) => a.apiKey === apiKey);\n\n if (!app) {\n return c.json({ error: \"Unknown API key. Register at POST /api/sdk/register\" }, 401);\n }\n\n app.lastSeen = new Date();\n c.set(\"sdkApp\", app);\n await next();\n}\n\nconst sdkRoutes = new Hono<SdkEnv>();\n\n// Registration endpoint (no auth required)\nsdkRoutes.post(\"/register\", async (c) => {\n try {\n const body = await c.req.json<{\n name: string;\n type: string;\n callbackUrl?: string;\n }>();\n\n if (!body.name || !body.type) {\n return c.json({ error: \"name and type are required\" }, 400);\n }\n\n // Check if app already registered — do not re-expose API key\n const existing = Array.from(registeredApps.values()).find(\n (a) => a.name === body.name && a.type === body.type\n );\n if (existing) {\n return c.json({\n id: existing.id,\n message: \"App already registered. Use your existing API key; it is not re-sent for security.\",\n });\n }\n\n const id = crypto.randomUUID();\n const apiKey = generateApiKey();\n const app: RegisteredApp = {\n id,\n name: body.name,\n type: body.type,\n apiKey,\n callbackUrl: body.callbackUrl,\n registeredAt: new Date(),\n lastSeen: new Date(),\n };\n\n registeredApps.set(id, app);\n\n return c.json({\n id,\n apiKey,\n message: \"App registered successfully. Use this API key in Authorization: Bearer header.\",\n endpoints: {\n chat: \"POST /api/sdk/chat\",\n notify: \"POST /api/sdk/notify\",\n memory_store: \"POST /api/sdk/memory\",\n memory_search: \"POST /api/sdk/memory/search\",\n tools_list: \"GET /api/sdk/tools\",\n tools_execute: \"POST /api/sdk/tools/execute\",\n agent_spawn: \"POST /api/sdk/agent/spawn\",\n status: \"GET /api/sdk/status\",\n },\n });\n } catch (error) {\n return c.json({ error: \"Registration failed\" }, 500);\n }\n});\n\n// All remaining routes require auth\nsdkRoutes.use(\"/*\", sdkAuth);\n\n// Chat - AI-powered conversation with OpenSentinel\nsdkRoutes.post(\"/chat\", async (c) => {\n try {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const body = await c.req.json<{\n message: string;\n context?: string;\n useTools?: boolean;\n systemPrompt?: string;\n }>();\n\n if (!body.message) {\n return c.json({ error: \"message is required\" }, 400);\n }\n\n const messages: Message[] = [];\n if (body.context) {\n messages.push({\n role: \"user\",\n content: `[Context from ${app.name} (${app.type})]: ${body.context}`,\n });\n messages.push({\n role: \"assistant\",\n content: \"Understood, I have the context. How can I help?\",\n });\n }\n messages.push({ role: \"user\", content: body.message });\n\n const toolsUsed: string[] = [];\n const response = body.useTools !== false\n ? await chatWithTools(messages, `sdk:${app.id}`, (tool) => toolsUsed.push(tool), { appType: app.type })\n : await (await import(\"../../../core/brain\")).chat(messages, body.systemPrompt);\n\n // Store interaction in memory for cross-app intelligence\n await storeMemory({\n content: `[${app.name}] User asked: ${body.message.slice(0, 200)}`,\n type: \"episodic\",\n importance: 5,\n userId: `sdk:${app.id}`,\n source: `sdk:${app.name}`,\n provenance: `sdk:${app.type}`,\n }).catch(() => {}); // Non-blocking\n\n return c.json({\n content: response.content,\n toolsUsed,\n usage: {\n inputTokens: response.inputTokens,\n outputTokens: response.outputTokens,\n },\n app: app.name,\n });\n } catch (error) {\n console.error(\"SDK chat error:\", error);\n return c.json({ error: \"Chat failed\" }, 500);\n }\n});\n\n// Notify - Send notification through OpenSentinel channels\nsdkRoutes.post(\"/notify\", async (c) => {\n try {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const body = await c.req.json<{\n channel: \"telegram\" | \"discord\" | \"slack\" | \"email\" | \"all\";\n message: string;\n recipient?: string;\n priority?: \"low\" | \"normal\" | \"high\" | \"urgent\";\n }>();\n\n if (!body.channel || !body.message) {\n return c.json({ error: \"channel and message are required\" }, 400);\n }\n\n const sent: string[] = [];\n const prefix = `[${app.name}] `;\n const fullMessage = prefix + body.message;\n\n const channels = body.channel === \"all\"\n ? [\"telegram\", \"discord\", \"slack\"]\n : [body.channel];\n\n for (const ch of channels) {\n try {\n switch (ch) {\n case \"telegram\": {\n const { Bot } = await import(\"grammy\");\n const bot = new Bot(env.TELEGRAM_BOT_TOKEN);\n await bot.api.sendMessage(env.TELEGRAM_CHAT_ID, fullMessage);\n sent.push(\"telegram\");\n break;\n }\n case \"discord\": {\n const { createDiscordBot } = await import(\"../../discord\");\n const discord = createDiscordBot({\n token: env.DISCORD_BOT_TOKEN || \"\",\n clientId: env.DISCORD_CLIENT_ID || \"\",\n });\n if (body.recipient) {\n await discord.sendMessage(body.recipient, fullMessage);\n }\n sent.push(\"discord\");\n break;\n }\n case \"slack\": {\n const { createSlackBot } = await import(\"../../slack\");\n const slack = createSlackBot({\n token: env.SLACK_BOT_TOKEN || \"\",\n signingSecret: env.SLACK_SIGNING_SECRET || \"\",\n });\n if (body.recipient) {\n await slack.sendMessage(body.recipient, fullMessage);\n }\n sent.push(\"slack\");\n break;\n }\n case \"email\": {\n const { SmtpClient } = await import(\"../../../integrations/email\");\n const smtp = new SmtpClient({\n host: env.EMAIL_SMTP_HOST || \"localhost\",\n port: env.EMAIL_SMTP_PORT || 587,\n secure: env.EMAIL_SMTP_SECURE || false,\n auth: { user: env.EMAIL_USER || \"\", pass: env.EMAIL_PASSWORD || \"\" },\n });\n await smtp.send({\n to: body.recipient || \"\",\n subject: `${app.name} Notification`,\n text: body.message,\n });\n sent.push(\"email\");\n break;\n }\n }\n } catch (err) {\n // Channel not configured, skip\n }\n }\n\n return c.json({ sent, message: `Notification sent via: ${sent.join(\", \") || \"none (no channels configured)\"}` });\n } catch (error) {\n return c.json({ error: \"Notification failed\" }, 500);\n }\n});\n\n// Memory Store\nsdkRoutes.post(\"/memory\", async (c) => {\n try {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const body = await c.req.json<{\n content: string;\n type?: \"episodic\" | \"semantic\" | \"procedural\";\n importance?: number;\n metadata?: Record<string, any>;\n }>();\n\n if (!body.content) {\n return c.json({ error: \"content is required\" }, 400);\n }\n\n const memory = await storeMemory({\n content: body.content,\n type: body.type || \"semantic\",\n importance: body.importance || 5,\n userId: `sdk:${app.id}`,\n source: `sdk:${app.name}`,\n provenance: `sdk:${app.type}`,\n });\n\n return c.json(memory);\n } catch (error) {\n return c.json({ error: \"Memory store failed\" }, 500);\n }\n});\n\n// Memory Search\nsdkRoutes.post(\"/memory/search\", async (c) => {\n try {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const body = await c.req.json<{\n query: string;\n limit?: number;\n crossApp?: boolean;\n }>();\n\n if (!body.query) {\n return c.json({ error: \"query is required\" }, 400);\n }\n\n // Cross-app search uses no userId filter; app-specific uses sdk:appId\n const userId = body.crossApp ? undefined : `sdk:${app.id}`;\n const results = await searchMemories(body.query, userId, body.limit || 5);\n\n return c.json(results);\n } catch (error) {\n return c.json({ error: \"Memory search failed\" }, 500);\n }\n});\n\n// List available tools (prioritized for app type)\nsdkRoutes.get(\"/tools\", (c) => {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const ordered = prioritizeTools(TOOLS as any[], app.type);\n const profile = getAppProfile(app.type);\n const prioritySet = new Set(profile.priorityTools);\n\n const toolList = ordered.map((t: any) => ({\n name: t.name,\n description: t.description,\n priority: prioritySet.has(t.name),\n }));\n return c.json({ tools: toolList, count: toolList.length, appType: app.type });\n});\n\n// Execute a specific tool\nsdkRoutes.post(\"/tools/execute\", async (c) => {\n try {\n const body = await c.req.json<{\n tool: string;\n input: Record<string, any>;\n }>();\n\n if (!body.tool || !body.input) {\n return c.json({ error: \"tool and input are required\" }, 400);\n }\n\n const result = await executeTool(body.tool, body.input);\n return c.json({ tool: body.tool, result });\n } catch (error) {\n return c.json({ error: \"Tool execution failed\" }, 500);\n }\n});\n\n// Spawn a sub-agent\nsdkRoutes.post(\"/agent/spawn\", async (c) => {\n try {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const body = await c.req.json<{\n type: \"research\" | \"coding\" | \"writing\" | \"analysis\";\n task: string;\n context?: string;\n }>();\n\n if (!body.type || !body.task) {\n return c.json({ error: \"type and task are required\" }, 400);\n }\n\n // Use chat with tools to delegate to an agent\n const agentPrompt = `As a ${body.type} agent for ${app.name}, complete this task: ${body.task}${body.context ? `\\n\\nContext: ${body.context}` : \"\"}`;\n\n const messages: Message[] = [{ role: \"user\", content: agentPrompt }];\n const toolsUsed: string[] = [];\n const response = await chatWithTools(messages, `sdk:${app.id}:agent:${body.type}`, (tool) => toolsUsed.push(tool), { appType: app.type });\n\n return c.json({\n agent: body.type,\n result: response.content,\n toolsUsed,\n usage: {\n inputTokens: response.inputTokens,\n outputTokens: response.outputTokens,\n },\n });\n } catch (error) {\n return c.json({ error: \"Agent spawn failed\" }, 500);\n }\n});\n\n// Status\nsdkRoutes.get(\"/status\", (c) => {\n const app = c.get(\"sdkApp\") as RegisteredApp;\n const allApps = Array.from(registeredApps.values()).map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n registeredAt: a.registeredAt,\n lastSeen: a.lastSeen,\n }));\n\n return c.json({\n opensentinel: {\n status: \"online\",\n version: \"2.2.1\",\n uptime: process.uptime(),\n },\n currentApp: {\n id: app.id,\n name: app.name,\n type: app.type,\n },\n registeredApps: allApps,\n tools: (TOOLS as any[]).length,\n });\n});\n\nexport { sdkRoutes };\n","import { Hono } from \"hono\";\r\nimport {\r\n queryAuditLogs,\r\n getAuditChainIntegrity,\r\n type AuditQueryOptions,\r\n type AuditAction,\r\n type AuditResource,\r\n} from \"../../../core/security/audit-logger\";\r\nimport { checkRateLimit } from \"../../../core/security/rate-limiter\";\r\nimport { getGatewayToken, timingSafeEqual } from \"../../../core/security/gateway-utils\";\r\n\r\nconst adminRouter = new Hono();\r\n\r\n// Middleware for admin authentication — accepts API key, gateway Bearer token, or open mode\r\nasync function requireAdminAuth(c: any, next: () => Promise<void>) {\r\n // If no gateway token configured, open mode — allow all admin access\r\n const gatewayToken = getGatewayToken();\r\n if (!gatewayToken) {\r\n return next();\r\n }\r\n\r\n // Check x-api-key header first\r\n const apiKey = c.req.header(\"x-api-key\");\r\n if (apiKey) {\r\n const rateLimitResult = await checkRateLimit(apiKey, \"api/admin\");\r\n if (!rateLimitResult.allowed) {\r\n return c.json(\r\n { error: \"Rate limit exceeded\", retryAfter: rateLimitResult.retryAfterMs },\r\n 429\r\n );\r\n }\r\n return next();\r\n }\r\n\r\n // Fall back to gateway Bearer token (used by web dashboard)\r\n const authHeader = c.req.header(\"Authorization\");\r\n if (authHeader?.startsWith(\"Bearer \")) {\r\n const token = authHeader.slice(7);\r\n if (timingSafeEqual(token, gatewayToken)) {\r\n return next();\r\n }\r\n }\r\n\r\n return c.json({ error: \"API key required\" }, 401);\r\n}\r\n\r\nadminRouter.use(\"*\", requireAdminAuth);\r\n\r\n// GET /api/admin/audit-logs — Query audit logs with filters\r\nadminRouter.get(\"/audit-logs\", async (c) => {\r\n try {\r\n const url = new URL(c.req.url);\r\n const options: AuditQueryOptions = {};\r\n\r\n const userId = url.searchParams.get(\"userId\");\r\n if (userId) options.userId = userId;\r\n\r\n const action = url.searchParams.get(\"action\");\r\n if (action) options.action = action as AuditAction;\r\n\r\n const resource = url.searchParams.get(\"resource\");\r\n if (resource) options.resource = resource as AuditResource;\r\n\r\n const startDate = url.searchParams.get(\"startDate\");\r\n if (startDate) options.startDate = new Date(startDate);\r\n\r\n const endDate = url.searchParams.get(\"endDate\");\r\n if (endDate) options.endDate = new Date(endDate);\r\n\r\n const limit = url.searchParams.get(\"limit\");\r\n options.limit = limit ? Math.min(parseInt(limit, 10), 500) : 100;\r\n\r\n const offset = url.searchParams.get(\"offset\");\r\n options.offset = offset ? parseInt(offset, 10) : 0;\r\n\r\n const logs = await queryAuditLogs(options);\r\n\r\n return c.json({\r\n success: true,\r\n logs,\r\n count: logs.length,\r\n limit: options.limit,\r\n offset: options.offset,\r\n });\r\n } catch (err: any) {\r\n return c.json({ error: err.message || \"Failed to query audit logs\" }, 500);\r\n }\r\n});\r\n\r\n// GET /api/admin/audit-logs/integrity — Check audit chain integrity\r\nadminRouter.get(\"/audit-logs/integrity\", async (c) => {\r\n try {\r\n const integrity = await getAuditChainIntegrity();\r\n return c.json({ success: true, ...integrity });\r\n } catch (err: any) {\r\n return c.json({ error: err.message || \"Failed to check integrity\" }, 500);\r\n }\r\n});\r\n\r\n// GET /api/admin/incidents — Get recent security incidents (failed actions, errors)\r\nadminRouter.get(\"/incidents\", async (c) => {\r\n try {\r\n const url = new URL(c.req.url);\r\n const limit = Math.min(parseInt(url.searchParams.get(\"limit\") || \"50\", 10), 200);\r\n\r\n // Get failed/error audit entries as incidents\r\n const incidents = await queryAuditLogs({\r\n action: \"error\",\r\n limit,\r\n });\r\n\r\n return c.json({\r\n success: true,\r\n incidents,\r\n count: incidents.length,\r\n });\r\n } catch (err: any) {\r\n return c.json({ error: err.message || \"Failed to query incidents\" }, 500);\r\n }\r\n});\r\n\r\nexport default adminRouter;\r\n","import Redis from \"ioredis\";\r\nimport { env } from \"../../config/env\";\r\n\r\n// Redis connection for rate limiting\r\nconst redis = new Redis(env.REDIS_URL, {\r\n maxRetriesPerRequest: 3,\r\n} as any);\r\n\r\nexport interface RateLimitConfig {\r\n windowMs: number; // Time window in milliseconds\r\n maxRequests: number; // Max requests per window\r\n}\r\n\r\nexport interface RateLimitResult {\r\n allowed: boolean;\r\n remaining: number;\r\n resetAt: Date;\r\n retryAfterMs?: number;\r\n}\r\n\r\n// Default rate limits by endpoint\r\nconst DEFAULT_LIMITS: Record<string, RateLimitConfig> = {\r\n \"api/chat\": { windowMs: 60000, maxRequests: 30 },\r\n \"api/chat/tools\": { windowMs: 60000, maxRequests: 20 },\r\n \"api/ask\": { windowMs: 60000, maxRequests: 30 },\r\n \"tool/shell\": { windowMs: 60000, maxRequests: 10 },\r\n \"tool/browser\": { windowMs: 60000, maxRequests: 10 },\r\n \"tool/file_write\": { windowMs: 60000, maxRequests: 20 },\r\n \"agent/spawn\": { windowMs: 3600000, maxRequests: 5 }, // 5 agents per hour\r\n default: { windowMs: 60000, maxRequests: 60 },\r\n};\r\n\r\nfunction getKey(identifier: string, endpoint: string): string {\r\n return `ratelimit:${identifier}:${endpoint}`;\r\n}\r\n\r\nexport async function checkRateLimit(\r\n identifier: string, // userId, IP, or API key\r\n endpoint: string,\r\n customConfig?: RateLimitConfig\r\n): Promise<RateLimitResult> {\r\n const config = customConfig || DEFAULT_LIMITS[endpoint] || DEFAULT_LIMITS.default;\r\n const { windowMs, maxRequests } = config;\r\n\r\n const key = getKey(identifier, endpoint);\r\n const now = Date.now();\r\n\r\n try {\r\n // Use Redis MULTI for atomic operations\r\n const multi = redis.multi();\r\n\r\n // Remove expired entries\r\n multi.zremrangebyscore(key, 0, now - windowMs);\r\n\r\n // Count current requests in window\r\n multi.zcard(key);\r\n\r\n // Add current request\r\n multi.zadd(key, now.toString(), `${now}:${Math.random()}`);\r\n\r\n // Set expiry on the key\r\n multi.pexpire(key, windowMs);\r\n\r\n const results = await multi.exec();\r\n\r\n if (!results) {\r\n // Redis error, allow request but log\r\n console.warn(\"[RateLimiter] Redis transaction failed, allowing request\");\r\n return {\r\n allowed: true,\r\n remaining: maxRequests,\r\n resetAt: new Date(now + windowMs),\r\n };\r\n }\r\n\r\n const currentCount = (results[1]?.[1] as number) || 0;\r\n const resetAt = new Date(now + windowMs);\r\n\r\n if (currentCount >= maxRequests) {\r\n // Remove the request we just added since we're rejecting\r\n await redis.zrem(key, `${now}:${Math.random()}`);\r\n\r\n return {\r\n allowed: false,\r\n remaining: 0,\r\n resetAt,\r\n retryAfterMs: windowMs - (now - (await getWindowStart(key, now, windowMs))),\r\n };\r\n }\r\n\r\n return {\r\n allowed: true,\r\n remaining: maxRequests - currentCount - 1,\r\n resetAt,\r\n };\r\n } catch (error) {\r\n // On Redis error, fail open (allow request)\r\n console.error(\"[RateLimiter] Error checking rate limit:\", error);\r\n return {\r\n allowed: true,\r\n remaining: maxRequests,\r\n resetAt: new Date(now + windowMs),\r\n };\r\n }\r\n}\r\n\r\nasync function getWindowStart(\r\n key: string,\r\n now: number,\r\n windowMs: number\r\n): Promise<number> {\r\n const oldest = await redis.zrange(key, 0, 0, \"WITHSCORES\");\r\n if (oldest.length >= 2) {\r\n return parseInt(oldest[1], 10);\r\n }\r\n return now - windowMs;\r\n}\r\n\r\nexport async function getRateLimitStatus(\r\n identifier: string,\r\n endpoint: string\r\n): Promise<{ count: number; remaining: number; resetAt: Date }> {\r\n const config = DEFAULT_LIMITS[endpoint] || DEFAULT_LIMITS.default;\r\n const { windowMs, maxRequests } = config;\r\n\r\n const key = getKey(identifier, endpoint);\r\n const now = Date.now();\r\n\r\n // Clean old entries\r\n await redis.zremrangebyscore(key, 0, now - windowMs);\r\n\r\n // Get current count\r\n const count = await redis.zcard(key);\r\n\r\n return {\r\n count,\r\n remaining: Math.max(0, maxRequests - count),\r\n resetAt: new Date(now + windowMs),\r\n };\r\n}\r\n\r\nexport async function resetRateLimit(\r\n identifier: string,\r\n endpoint: string\r\n): Promise<void> {\r\n const key = getKey(identifier, endpoint);\r\n await redis.del(key);\r\n}\r\n\r\nexport async function resetAllRateLimits(identifier: string): Promise<void> {\r\n const pattern = `ratelimit:${identifier}:*`;\r\n const keys = await redis.keys(pattern);\r\n if (keys.length > 0) {\r\n await redis.del(...keys);\r\n }\r\n}\r\n\r\n// Get all rate limit configs\r\nexport function getRateLimitConfigs(): Record<string, RateLimitConfig> {\r\n return { ...DEFAULT_LIMITS };\r\n}\r\n\r\n// Update rate limit config (in-memory only, resets on restart)\r\nexport function setRateLimitConfig(\r\n endpoint: string,\r\n config: RateLimitConfig\r\n): void {\r\n DEFAULT_LIMITS[endpoint] = config;\r\n}\r\n\r\n// Middleware helper for Hono\r\nexport function createRateLimitMiddleware(endpoint: string) {\r\n return async (c: { req: { header: (name: string) => string | undefined }; json: (data: unknown, status: number) => Response }, next: () => Promise<void>) => {\r\n // Try to get identifier from various sources\r\n const apiKey = c.req.header(\"x-api-key\");\r\n const ip = c.req.header(\"x-forwarded-for\") || c.req.header(\"x-real-ip\") || \"unknown\";\r\n\r\n const identifier = apiKey || ip;\r\n const result = await checkRateLimit(identifier, endpoint);\r\n\r\n if (!result.allowed) {\r\n return c.json(\r\n {\r\n error: \"Rate limit exceeded\",\r\n retryAfter: result.retryAfterMs,\r\n resetAt: result.resetAt.toISOString(),\r\n },\r\n 429\r\n );\r\n }\r\n\r\n await next();\r\n };\r\n}\r\n\r\n// Cleanup on shutdown\r\nexport async function closeRateLimiter(): Promise<void> {\r\n await redis.quit();\r\n}\r\n\r\nexport { redis as rateLimitRedis };\r\n","/**\r\n * Brain API Routes — Dashboard telemetry endpoints\r\n *\r\n * Exposes pipeline status, activity feed, scores, agent data,\r\n * cost forecasting, and memory-graph data for the Brain dashboard.\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\nimport { brainTelemetry } from \"../../../core/observability/brain-telemetry\";\r\nimport { costTracker } from \"../../../core/observability/cost-tracker\";\r\nimport { searchMemories } from \"../../../core/memory\";\r\n\r\nconst brainRouter = new Hono();\r\n\r\n// GET /api/brain/status — Current brain state (polled every 3s)\r\nbrainRouter.get(\"/status\", (c) => {\r\n return c.json(brainTelemetry.getStatus());\r\n});\r\n\r\n// GET /api/brain/activity?limit=100 — Activity feed entries\r\nbrainRouter.get(\"/activity\", (c) => {\r\n const limit = parseInt(c.req.query(\"limit\") || \"100\");\r\n return c.json(brainTelemetry.getActivity(Math.min(limit, 500)));\r\n});\r\n\r\n// GET /api/brain/scores — Pipeline metrics + cost summary\r\nbrainRouter.get(\"/scores\", async (c) => {\r\n // Ensure cost history is loaded from DB (idempotent)\r\n await costTracker.loadFromDb();\r\n return c.json(brainTelemetry.getScores());\r\n});\r\n\r\n// GET /api/brain/agents?userId=... — Active and recent agents\r\nbrainRouter.get(\"/agents\", async (c) => {\r\n const userId = c.req.query(\"userId\");\r\n try {\r\n const { getUserAgents, getAllAgents } = await import(\"../../../core/agents/agent-manager\");\r\n const agents = userId\r\n ? await getUserAgents(userId, undefined, 20)\r\n : await getAllAgents(undefined, 50);\r\n return c.json(agents);\r\n } catch {\r\n return c.json([]);\r\n }\r\n});\r\n\r\n// GET /api/brain/cost/forecast?days=7 — Cost forecast with trend\r\nbrainRouter.get(\"/cost/forecast\", (c) => {\r\n const days = parseInt(c.req.query(\"days\") || \"7\");\r\n return c.json({\r\n forecast: costTracker.getForecast(days),\r\n trend: costTracker.getCostTrend(),\r\n estimatedMonthly: costTracker.getEstimatedMonthlyCost(),\r\n });\r\n});\r\n\r\n// GET /api/brain/memory-graph?entityId=...&limit=50\r\n// Returns memory nodes + optional entity connections for graph overlay\r\nbrainRouter.get(\"/memory-graph\", async (c) => {\r\n const entityId = c.req.query(\"entityId\");\r\n const limit = parseInt(c.req.query(\"limit\") || \"50\");\r\n\r\n try {\r\n // Get recent memories as graph nodes\r\n const memories = await searchMemories(\"\", undefined, limit);\r\n const nodes: Array<{\r\n id: string;\r\n name: string;\r\n type: string;\r\n importance: number;\r\n content: string;\r\n createdAt: string;\r\n }> = [];\r\n const edges: Array<{\r\n source: string;\r\n target: string;\r\n type: string;\r\n strength: number;\r\n }> = [];\r\n\r\n for (const mem of memories) {\r\n nodes.push({\r\n id: `mem-${mem.id}`,\r\n name: (mem.content || \"\").slice(0, 60) + ((mem.content || \"\").length > 60 ? \"...\" : \"\"),\r\n type: \"memory\",\r\n importance: (mem.importance ?? 5) * 10, // Scale 1-10 to 10-100\r\n content: mem.content || \"\",\r\n createdAt: mem.createdAt?.toISOString?.() || new Date().toISOString(),\r\n });\r\n }\r\n\r\n // If entityId provided, try to connect memories to entity\r\n if (entityId) {\r\n try {\r\n const { db } = await import(\"../../../db\");\r\n const { graphEntities } = await import(\"../../../db/schema\");\r\n const { eq } = await import(\"drizzle-orm\");\r\n\r\n const [entity] = await db\r\n .select()\r\n .from(graphEntities)\r\n .where(eq(graphEntities.id, entityId))\r\n .limit(1);\r\n\r\n if (entity) {\r\n // Add the entity as a node\r\n nodes.push({\r\n id: entity.id,\r\n name: entity.name,\r\n type: entity.type,\r\n importance: entity.importance ?? 50,\r\n content: entity.description || \"\",\r\n createdAt: entity.createdAt?.toISOString?.() || new Date().toISOString(),\r\n });\r\n\r\n // Connect memories to entity by keyword match\r\n for (const mem of memories) {\r\n const content = (mem.content || \"\").toLowerCase();\r\n if (\r\n content.includes(entity.name.toLowerCase()) ||\r\n (entity.aliases as string[] || []).some((a: string) =>\r\n content.includes(a.toLowerCase())\r\n )\r\n ) {\r\n edges.push({\r\n source: `mem-${mem.id}`,\r\n target: entity.id,\r\n type: \"relates_to\",\r\n strength: 60,\r\n });\r\n }\r\n }\r\n }\r\n } catch {\r\n // Entity lookup failed, return memories only\r\n }\r\n }\r\n\r\n // Add inter-memory edges for memories of the same type\r\n for (let i = 0; i < nodes.length; i++) {\r\n for (let j = i + 1; j < nodes.length; j++) {\r\n if (\r\n nodes[i].type === \"memory\" &&\r\n nodes[j].type === \"memory\" &&\r\n nodes[i].content &&\r\n nodes[j].content\r\n ) {\r\n // Simple keyword overlap check\r\n const words1 = new Set(nodes[i].content.toLowerCase().split(/\\s+/).filter(w => w.length > 4));\r\n const words2 = new Set(nodes[j].content.toLowerCase().split(/\\s+/).filter(w => w.length > 4));\r\n const overlap = [...words1].filter(w => words2.has(w)).length;\r\n if (overlap >= 3) {\r\n edges.push({\r\n source: nodes[i].id,\r\n target: nodes[j].id,\r\n type: \"related\",\r\n strength: Math.min(100, overlap * 15),\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return c.json({ nodes, edges });\r\n } catch (error) {\r\n return c.json({ nodes: [], edges: [], error: \"Failed to build memory graph\" }, 500);\r\n }\r\n});\r\n\r\n// GET /api/brain/agents/catalog — Available agent types and their capabilities\r\nbrainRouter.get(\"/agents/catalog\", async (c) => {\r\n try {\r\n const { AGENT_TOOL_PERMISSIONS } = await import(\"../../../core/agents/agent-types\");\r\n const configs = await Promise.all([\r\n import(\"../../../core/agents/specialized/research-agent\").then(m => m.RESEARCH_AGENT_CONFIG),\r\n import(\"../../../core/agents/specialized/coding-agent\").then(m => m.CODING_AGENT_CONFIG),\r\n import(\"../../../core/agents/specialized/writing-agent\").then(m => m.WRITING_AGENT_CONFIG),\r\n import(\"../../../core/agents/specialized/analysis-agent\").then(m => m.ANALYSIS_AGENT_CONFIG),\r\n import(\"../../../core/agents/specialized/osint-agent\").then(m => m.OSINT_AGENT_CONFIG),\r\n ]);\r\n const catalog = configs.map(cfg => ({\r\n type: cfg.type,\r\n name: cfg.name,\r\n description: cfg.description,\r\n tools: AGENT_TOOL_PERMISSIONS[cfg.type] || [],\r\n settings: cfg.settings || {},\r\n }));\r\n return c.json(catalog);\r\n } catch {\r\n return c.json([]);\r\n }\r\n});\r\n\r\n// POST /api/brain/agents/spawn — Spawn a new sub-agent\r\nbrainRouter.post(\"/agents/spawn\", async (c) => {\r\n try {\r\n const { type, objective } = await c.req.json<{ type: string; objective: string }>();\r\n if (!type || !objective) {\r\n return c.json({ error: \"type and objective are required\" }, 400);\r\n }\r\n // Ensure a system user exists for dashboard-spawned tasks\r\n const { db } = await import(\"../../../db\");\r\n const { users } = await import(\"../../../db/schema\");\r\n let systemUser = await db.select().from(users).limit(1);\r\n if (systemUser.length === 0) {\r\n systemUser = await db.insert(users).values({ name: \"Dashboard\" }).returning();\r\n }\r\n const { spawnAgent } = await import(\"../../../core/agents/agent-manager\");\r\n const agent = await spawnAgent({\r\n type: type as any,\r\n objective,\r\n userId: systemUser[0].id,\r\n });\r\n return c.json(agent, 201);\r\n } catch (error: any) {\r\n return c.json({ error: error?.message || \"Failed to spawn agent\" }, 500);\r\n }\r\n});\r\n\r\n// POST /api/brain/agents/seed — Seed realistic sample tasks for the dashboard\r\nbrainRouter.post(\"/agents/seed\", async (c) => {\r\n try {\r\n const { db } = await import(\"../../../db\");\r\n const { subAgents, agentProgress, users } = await import(\"../../../db/schema\");\r\n\r\n // Ensure a system user exists for seeded tasks\r\n let systemUser = await db.select().from(users).limit(1);\r\n if (systemUser.length === 0) {\r\n systemUser = await db.insert(users).values({\r\n name: \"System\",\r\n }).returning();\r\n }\r\n const userId = systemUser[0].id;\r\n\r\n const now = Date.now();\r\n const tasks = [\r\n {\r\n userId,\r\n type: \"research\" as const,\r\n name: \"Research Agent\",\r\n status: \"completed\" as const,\r\n objective: \"Research current best practices for PostgreSQL query optimization and indexing strategies\",\r\n tokenBudget: 50000,\r\n tokensUsed: 32450,\r\n createdAt: new Date(now - 3 * 3600_000),\r\n result: { success: true, summary: \"Compiled 12 optimization strategies including partial indexes, covering indexes, and query plan analysis. Key findings: BRIN indexes for time-series data, GIN for JSONB columns, and composite indexes for multi-column queries.\", durationMs: 45200 },\r\n },\r\n {\r\n userId,\r\n type: \"coding\" as const,\r\n name: \"Coding Agent\",\r\n status: \"completed\" as const,\r\n objective: \"Implement rate limiting middleware for the API with configurable windows and Redis backing\",\r\n tokenBudget: 80000,\r\n tokensUsed: 61200,\r\n createdAt: new Date(now - 6 * 3600_000),\r\n result: { success: true, summary: \"Implemented sliding window rate limiter using Redis ZSET. Supports per-user and per-IP limits with configurable windows (1s, 1m, 1h, 1d). Added X-RateLimit headers and 429 responses.\", durationMs: 128400 },\r\n },\r\n {\r\n userId,\r\n type: \"analysis\" as const,\r\n name: \"Analysis Agent\",\r\n status: \"completed\" as const,\r\n objective: \"Analyze token usage patterns over the last 30 days and identify cost optimization opportunities\",\r\n tokenBudget: 40000,\r\n tokensUsed: 28900,\r\n createdAt: new Date(now - 12 * 3600_000),\r\n result: { success: true, summary: \"Found 3 key optimization opportunities: 1) System prompts can be shortened by 40% with prompt caching, 2) Research queries could use haiku for initial filtering, 3) Redundant context in multi-turn conversations accounts for 22% of input tokens.\", durationMs: 67800 },\r\n },\r\n {\r\n userId,\r\n type: \"writing\" as const,\r\n name: \"Writing Agent\",\r\n status: \"completed\" as const,\r\n objective: \"Generate API documentation for the webhook and scheduler endpoints\",\r\n tokenBudget: 30000,\r\n tokensUsed: 18700,\r\n createdAt: new Date(now - 24 * 3600_000),\r\n result: { success: true, summary: \"Generated OpenAPI 3.1 documentation for 8 endpoints across scheduler and webhook routes. Includes request/response schemas, authentication requirements, and usage examples.\", durationMs: 34500 },\r\n },\r\n {\r\n userId,\r\n type: \"research\" as const,\r\n name: \"Research Agent\",\r\n status: \"completed\" as const,\r\n objective: \"Gather public information about recent AI security vulnerabilities and prompt injection techniques\",\r\n tokenBudget: 60000,\r\n tokensUsed: 45300,\r\n createdAt: new Date(now - 48 * 3600_000),\r\n result: { success: true, summary: \"Compiled report on 15 known prompt injection vectors including indirect injection via retrieved content, multi-modal attacks through images, and tool-use exploitation. Recommended 6 mitigation strategies.\", durationMs: 89200 },\r\n },\r\n {\r\n userId,\r\n type: \"research\" as const,\r\n name: \"Research Agent\",\r\n status: \"failed\" as const,\r\n objective: \"Research pgvector HNSW vs IVFFlat index performance for RAG memory retrieval\",\r\n tokenBudget: 50000,\r\n tokensUsed: 12800,\r\n createdAt: new Date(now - 2 * 3600_000),\r\n result: { success: false, error: \"Token budget exhausted during benchmark phase. Partial results: HNSW shows better recall at higher ef_search values but IVFFlat index build is 3x faster.\", durationMs: 22100 },\r\n },\r\n {\r\n userId,\r\n type: \"coding\" as const,\r\n name: \"Coding Agent\",\r\n status: \"running\" as const,\r\n objective: \"Build automated test suite for the MCP server integration layer\",\r\n tokenBudget: 100000,\r\n tokensUsed: 34200,\r\n createdAt: new Date(now - 1800_000),\r\n result: null,\r\n },\r\n {\r\n userId,\r\n type: \"analysis\" as const,\r\n name: \"Analysis Agent\",\r\n status: \"pending\" as const,\r\n objective: \"Analyze error patterns in the last 7 days and correlate with deployment events\",\r\n tokenBudget: 40000,\r\n tokensUsed: 0,\r\n createdAt: new Date(now - 300_000),\r\n result: null,\r\n },\r\n ];\r\n\r\n const inserted = [];\r\n for (const task of tasks) {\r\n const [row] = await db.insert(subAgents).values(task as any).returning();\r\n inserted.push(row);\r\n }\r\n\r\n // Add progress steps for the running coding task\r\n const runningTask = inserted.find(t => t.status === \"running\");\r\n if (runningTask) {\r\n await db.insert(agentProgress).values([\r\n { agentId: runningTask.id, step: 1, description: \"Analyzing existing MCP client code and interfaces\", status: \"completed\" as const },\r\n { agentId: runningTask.id, step: 2, description: \"Generating mock MCP server for testing\", status: \"completed\" as const },\r\n { agentId: runningTask.id, step: 3, description: \"Writing connection lifecycle tests\", status: \"running\" as const },\r\n { agentId: runningTask.id, step: 4, description: \"Writing tool discovery and execution tests\", status: \"pending\" as const },\r\n { agentId: runningTask.id, step: 5, description: \"Writing error handling and retry tests\", status: \"pending\" as const },\r\n ]);\r\n }\r\n\r\n // Add progress steps for the completed research task\r\n const researchTask = inserted.find(t => t.status === \"completed\" && t.type === \"research\");\r\n if (researchTask) {\r\n await db.insert(agentProgress).values([\r\n { agentId: researchTask.id, step: 1, description: \"Surveying PostgreSQL documentation and performance guides\", status: \"completed\" as const },\r\n { agentId: researchTask.id, step: 2, description: \"Analyzing index types: B-tree, Hash, GIN, GiST, BRIN\", status: \"completed\" as const },\r\n { agentId: researchTask.id, step: 3, description: \"Reviewing EXPLAIN ANALYZE best practices\", status: \"completed\" as const },\r\n { agentId: researchTask.id, step: 4, description: \"Compiling optimization recommendations\", status: \"completed\" as const },\r\n ]);\r\n }\r\n\r\n return c.json({ success: true, seeded: inserted.length });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to seed tasks\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/brain/agents/history — Clear completed/failed agent tasks\r\nbrainRouter.delete(\"/agents/history\", async (c) => {\r\n try {\r\n const { db } = await import(\"../../../db\");\r\n const { subAgents } = await import(\"../../../db/schema\");\r\n const { inArray } = await import(\"drizzle-orm\");\r\n await db.delete(subAgents).where(inArray(subAgents.status, [\"completed\", \"failed\", \"cancelled\"]));\r\n return c.json({ success: true });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to clear task history\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/brain/activity — Clear activity feed\r\nbrainRouter.delete(\"/activity\", (c) => {\r\n brainTelemetry.clearActivity?.();\r\n return c.json({ success: true });\r\n});\r\n\r\nexport default brainRouter;\r\n","/**\r\n * Scheduler API Routes — Cron job management for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\n\r\nconst schedulerRouter = new Hono();\r\n\r\n// GET /api/scheduler/jobs — List repeatable jobs from all queues\r\nschedulerRouter.get(\"/jobs\", async (c) => {\r\n try {\r\n const { taskQueue, maintenanceQueue } = await import(\"../../../core/scheduler\");\r\n const [taskJobs, maintenanceJobs] = await Promise.allSettled([\r\n taskQueue?.getRepeatableJobs?.() ?? Promise.resolve([]),\r\n maintenanceQueue?.getRepeatableJobs?.() ?? Promise.resolve([]),\r\n ]);\r\n const jobs = [\r\n ...(taskJobs.status === \"fulfilled\" ? taskJobs.value : []),\r\n ...(maintenanceJobs.status === \"fulfilled\" ? maintenanceJobs.value : []),\r\n ];\r\n return c.json(jobs);\r\n } catch (error) {\r\n return c.json([], 200);\r\n }\r\n});\r\n\r\n// GET /api/scheduler/stats — Queue statistics\r\nschedulerRouter.get(\"/stats\", async (c) => {\r\n try {\r\n const { getQueueStats } = await import(\"../../../core/scheduler\");\r\n const stats = await getQueueStats();\r\n return c.json(stats);\r\n } catch (error) {\r\n return c.json({ waiting: 0, active: 0, completed: 0, failed: 0, delayed: 0 });\r\n }\r\n});\r\n\r\n// POST /api/scheduler/jobs — Create recurring job\r\nschedulerRouter.post(\"/jobs\", async (c) => {\r\n try {\r\n const { name, pattern, task } = await c.req.json<{\r\n name: string;\r\n pattern: string;\r\n task?: Record<string, unknown>;\r\n }>();\r\n\r\n if (!name || !pattern) {\r\n return c.json({ error: \"name and pattern are required\" }, 400);\r\n }\r\n\r\n const { scheduleRecurring } = await import(\"../../../core/scheduler\");\r\n await scheduleRecurring(name, task || { type: \"custom\", name }, pattern);\r\n return c.json({ success: true }, 201);\r\n } catch (error) {\r\n return c.json({ error: \"Failed to create job\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/scheduler/jobs/:key — Remove repeatable job\r\nschedulerRouter.delete(\"/jobs/:key\", async (c) => {\r\n try {\r\n const key = decodeURIComponent(c.req.param(\"key\"));\r\n const { taskQueue } = await import(\"../../../core/scheduler\");\r\n await taskQueue.removeRepeatableByKey(key);\r\n return c.json({ success: true });\r\n } catch (error) {\r\n return c.json({ error: \"Failed to remove job\" }, 500);\r\n }\r\n});\r\n\r\n// PUT /api/scheduler/jobs/:key — Update a repeatable job (delete old + recreate)\r\nschedulerRouter.put(\"/jobs/:key\", async (c) => {\r\n try {\r\n const key = decodeURIComponent(c.req.param(\"key\"));\r\n const { name, pattern, task } = await c.req.json<{\r\n name?: string;\r\n pattern?: string;\r\n task?: Record<string, unknown>;\r\n }>();\r\n\r\n if (!pattern) {\r\n return c.json({ error: \"pattern is required\" }, 400);\r\n }\r\n\r\n const { taskQueue, scheduleRecurring } = await import(\"../../../core/scheduler\");\r\n // Remove the old job\r\n await taskQueue.removeRepeatableByKey(key);\r\n // Create the new one\r\n const jobName = name || key.split(\":::\")[0] || \"custom-job\";\r\n await scheduleRecurring(jobName, task || { type: \"custom\", name: jobName }, pattern);\r\n return c.json({ success: true });\r\n } catch (error) {\r\n return c.json({ error: \"Failed to update job\" }, 500);\r\n }\r\n});\r\n\r\nexport default schedulerRouter;\r\n","/**\r\n * Alerts API Routes — Alert management for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\n\r\nconst alertsRouter = new Hono();\r\n\r\n// GET /api/alerts — Active alerts + history\r\nalertsRouter.get(\"/\", async (c) => {\r\n try {\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n // Ensure DB history is loaded\r\n await alerting.loadAlertHistoryFromDb?.();\r\n const active = alerting.getActiveAlerts?.() ?? [];\r\n const history = alerting.getAlertHistory?.(50) ?? [];\r\n return c.json({ active, history });\r\n } catch {\r\n return c.json({ active: [], history: [] });\r\n }\r\n});\r\n\r\n// POST /api/alerts/:id/acknowledge\r\nalertsRouter.post(\"/:id/acknowledge\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const { by } = await c.req.json<{ by: string }>();\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n alerting.acknowledgeAlert?.(id, by || \"web-user\");\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to acknowledge alert\" }, 500);\r\n }\r\n});\r\n\r\n// POST /api/alerts/:id/resolve\r\nalertsRouter.post(\"/:id/resolve\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const { by } = await c.req.json<{ by: string }>();\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n alerting.resolveAlert?.(id, by || \"web-user\");\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to resolve alert\" }, 500);\r\n }\r\n});\r\n\r\n// GET /api/alerts/rules — List alert rules (initialize defaults if empty)\r\nalertsRouter.get(\"/rules\", async (c) => {\r\n try {\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n let rules = alerting.getAlertRules?.() ?? [];\r\n // Auto-initialize default rules if none exist\r\n if (rules.length === 0 && alerting.initializeDefaultRules) {\r\n alerting.initializeDefaultRules();\r\n rules = alerting.getAlertRules?.() ?? [];\r\n }\r\n return c.json(rules);\r\n } catch {\r\n return c.json([]);\r\n }\r\n});\r\n\r\n// DELETE /api/alerts/history — Clear alert history\r\nalertsRouter.delete(\"/history\", async (c) => {\r\n try {\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n alerting.clearAlertHistory?.();\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to clear alert history\" }, 500);\r\n }\r\n});\r\n\r\n// POST /api/alerts/rules — Create alert rule\r\nalertsRouter.post(\"/rules\", async (c) => {\r\n try {\r\n const rule = await c.req.json();\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n alerting.addAlertRule?.(rule);\r\n return c.json({ success: true }, 201);\r\n } catch {\r\n return c.json({ error: \"Failed to create rule\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/alerts/rules/:index — Remove a specific alert rule by ID\r\nalertsRouter.delete(\"/rules/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n const removed = alerting.removeAlertRule?.(id);\r\n if (!removed) {\r\n return c.json({ error: \"Rule not found\" }, 404);\r\n }\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to delete rule\" }, 500);\r\n }\r\n});\r\n\r\n// PUT /api/alerts/rules/:id — Update a rule's config\r\nalertsRouter.put(\"/rules/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const updates = await c.req.json();\r\n const alerting = await import(\"../../../core/observability/alerting\");\r\n const rules = alerting.getAlertRules?.() ?? [];\r\n const existing = rules.find((r: any) => r.id === id);\r\n if (!existing) {\r\n return c.json({ error: \"Rule not found\" }, 404);\r\n }\r\n // Merge updates and re-add\r\n const updated = { ...existing, ...updates, id };\r\n alerting.addAlertRule?.(updated);\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to update rule\" }, 500);\r\n }\r\n});\r\n\r\nexport default alertsRouter;\r\n","/**\r\n * Webhooks API Routes — Webhook/workflow trigger management for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\n\r\nconst webhooksRouter = new Hono();\r\n\r\n// GET /api/webhooks — List all workflow triggers (webhook, event, time)\r\nwebhooksRouter.get(\"/\", async (c) => {\r\n try {\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n const workflows = await store.getAllWorkflows();\r\n const results = workflows.map((w: any) => ({\r\n id: w.id,\r\n name: w.name,\r\n description: w.description || \"\",\r\n triggerType: Array.isArray(w.triggers) && w.triggers[0]?.type || \"webhook\",\r\n trigger: Array.isArray(w.triggers) && w.triggers[0] || {},\r\n actions: (Array.isArray(w.steps) ? w.steps : []).map((s: any) => ({\r\n type: s.action?.type || s.type || \"unknown\",\r\n name: s.action?.name || s.action?.type || s.type || \"action\",\r\n })),\r\n enabled: w.status === \"active\",\r\n createdAt: w.createdAt,\r\n updatedAt: w.updatedAt,\r\n lastTriggered: w.lastExecutedAt,\r\n executionCount: w.executionCount || 0,\r\n }));\r\n return c.json(results);\r\n } catch {\r\n return c.json([]);\r\n }\r\n});\r\n\r\n// POST /api/webhooks — Create workflow with trigger + actions\r\nwebhooksRouter.post(\"/\", async (c) => {\r\n try {\r\n const body = await c.req.json<{\r\n name: string;\r\n description?: string;\r\n triggerType: string;\r\n trigger: Record<string, unknown>;\r\n actions: Array<{ type: string; config?: Record<string, unknown> }>;\r\n }>();\r\n\r\n if (!body.name) {\r\n return c.json({ error: \"name is required\" }, 400);\r\n }\r\n\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n const now = new Date();\r\n const workflow = await store.createWorkflow({\r\n id: uuidv4(),\r\n name: body.name,\r\n description: body.description,\r\n status: \"active\",\r\n triggers: [{ type: body.triggerType || \"webhook\", config: body.trigger || {} } as any],\r\n steps: (body.actions || []).map((a, i) => ({\r\n id: uuidv4(),\r\n type: \"action\" as const,\r\n action: { type: a.type, config: a.config || {} } as any,\r\n })),\r\n executionCount: 0,\r\n createdAt: now,\r\n updatedAt: now,\r\n });\r\n return c.json({ id: workflow.id, success: true }, 201);\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to create webhook\" }, 500);\r\n }\r\n});\r\n\r\n// PUT /api/webhooks/:id/toggle — Enable/disable a workflow\r\nwebhooksRouter.put(\"/:id/toggle\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n const workflow = await store.getWorkflow(id);\r\n if (!workflow) return c.json({ error: \"Workflow not found\" }, 404);\r\n const newStatus = workflow.status === \"active\" ? \"disabled\" : \"active\";\r\n await store.updateWorkflow(id, { status: newStatus });\r\n return c.json({ success: true, enabled: newStatus === \"active\" });\r\n } catch {\r\n return c.json({ error: \"Failed to toggle webhook\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/webhooks/:id — Delete workflow\r\nwebhooksRouter.delete(\"/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n await store.deleteWorkflow(id);\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to delete webhook\" }, 500);\r\n }\r\n});\r\n\r\n// PUT /api/webhooks/:id — Update webhook name, description, trigger config\r\nwebhooksRouter.put(\"/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const body = await c.req.json<{\r\n name?: string;\r\n description?: string;\r\n triggerType?: string;\r\n trigger?: Record<string, unknown>;\r\n actions?: Array<{ type: string; config?: Record<string, unknown> }>;\r\n }>();\r\n\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n const workflow = await store.getWorkflow(id);\r\n if (!workflow) return c.json({ error: \"Workflow not found\" }, 404);\r\n\r\n const updates: Record<string, unknown> = {};\r\n if (body.name !== undefined) updates.name = body.name;\r\n if (body.description !== undefined) updates.description = body.description;\r\n if (body.triggerType !== undefined || body.trigger !== undefined) {\r\n updates.triggers = [{ type: body.triggerType || \"webhook\", config: body.trigger || {} }];\r\n }\r\n if (body.actions !== undefined) {\r\n const { v4: uuidv4Gen } = await import(\"uuid\");\r\n updates.steps = body.actions.map((a) => ({\r\n id: uuidv4Gen(),\r\n type: \"action\" as const,\r\n action: { type: a.type, config: a.config || {} },\r\n }));\r\n }\r\n\r\n await store.updateWorkflow(id, updates as any);\r\n return c.json({ success: true });\r\n } catch {\r\n return c.json({ error: \"Failed to update webhook\" }, 500);\r\n }\r\n});\r\n\r\n// POST /api/webhooks/seed — Create default useful webhooks\r\nwebhooksRouter.post(\"/seed\", async (c) => {\r\n try {\r\n const { WorkflowStore } = await import(\"../../../core/workflows/workflow-store\");\r\n const store = new WorkflowStore();\r\n\r\n const now = new Date();\r\n const defaults = [\r\n {\r\n name: \"GitHub Push Notifications\",\r\n description: \"Alert on pushes to main branch via GitHub webhook\",\r\n triggers: [{\r\n type: \"webhook\",\r\n config: {\r\n path: \"/webhooks/github\",\r\n methods: [\"POST\"],\r\n secret: \"\",\r\n filter: { type: \"key_match\", expression: \"ref\", expectedValue: \"refs/heads/main\" },\r\n },\r\n }],\r\n steps: [\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"send_message\", config: { channel: \"web\", message: \"New push to main: {{trigger.data.head_commit.message}}\" } } },\r\n ],\r\n },\r\n {\r\n name: \"Email-to-Chat Forward\",\r\n description: \"Forward important emails to web chat\",\r\n triggers: [{\r\n type: \"event\",\r\n config: { source: \"email\", eventName: \"email_received\" },\r\n }],\r\n steps: [\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"send_message\", config: { channel: \"web\", message: \"New email from {{trigger.data.from}}: {{trigger.data.subject}}\" } } },\r\n ],\r\n },\r\n {\r\n name: \"Alert on High Error Rate\",\r\n description: \"Send notification when error rate spikes\",\r\n triggers: [{\r\n type: \"event\",\r\n config: { source: \"alerting\", eventName: \"alert_fired\", filter: { severity: \"error\" } },\r\n }],\r\n steps: [\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"send_message\", config: { channel: \"web\", message: \"ALERT: {{trigger.data.message}} (severity: {{trigger.data.severity}})\" } } },\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"log\", config: { level: \"error\", message: \"Alert fired: {{trigger.data.message}}\" } } },\r\n ],\r\n },\r\n {\r\n name: \"Daily Summary Report\",\r\n description: \"Generate and send a daily activity summary at 9 AM\",\r\n triggers: [{\r\n type: \"time\",\r\n config: { pattern: \"0 9 * * *\", timezone: \"America/New_York\" },\r\n }],\r\n steps: [\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"run_tool\", config: { tool: \"get_time\", input: {} } } },\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"send_message\", config: { channel: \"web\", message: \"Good morning! Here's your daily summary for {{date}}.\" } } },\r\n ],\r\n },\r\n {\r\n name: \"External API Health Check\",\r\n description: \"Monitor external API endpoint every 10 minutes\",\r\n triggers: [{\r\n type: \"time\",\r\n config: { pattern: \"*/10 * * * *\" },\r\n }],\r\n steps: [\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"http_request\", config: { method: \"GET\", url: \"https://api.github.com/rate_limit\", headers: {} } } },\r\n { id: uuidv4(), type: \"action\" as const, action: { type: \"log\", config: { level: \"info\", message: \"Health check completed\" } } },\r\n ],\r\n },\r\n ];\r\n\r\n let created = 0;\r\n const existing = await store.getAllWorkflows();\r\n const existingNames = new Set(existing.map((w: any) => w.name));\r\n\r\n for (const wf of defaults) {\r\n if (!existingNames.has(wf.name)) {\r\n await store.createWorkflow({\r\n id: uuidv4(),\r\n ...wf,\r\n status: \"active\",\r\n executionCount: 0,\r\n createdAt: now,\r\n updatedAt: now,\r\n } as any);\r\n created++;\r\n }\r\n }\r\n\r\n return c.json({ success: true, created, total: existing.length + created });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to seed webhooks\" }, 500);\r\n }\r\n});\r\n\r\nexport default webhooksRouter;\r\n","/**\r\n * GitHub API Routes — GitHub integration dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\n\r\nconst githubRouter = new Hono();\r\n\r\n// GET /api/github/repos — List repositories\r\ngithubRouter.get(\"/repos\", async (c) => {\r\n try {\r\n const { env } = await import(\"../../../config/env\");\r\n if (!env.GITHUB_TOKEN) {\r\n return c.json({ error: \"GITHUB_TOKEN not configured\" }, 400);\r\n }\r\n const github = await import(\"../../../integrations/github\");\r\n const repos = await github.listRepositories();\r\n return c.json(repos);\r\n } catch (error) {\r\n return c.json([], 200);\r\n }\r\n});\r\n\r\n// GET /api/github/issues — List issues (across repos or for a specific repo)\r\ngithubRouter.get(\"/issues\", async (c) => {\r\n try {\r\n const { env } = await import(\"../../../config/env\");\r\n if (!env.GITHUB_TOKEN) {\r\n return c.json({ error: \"GITHUB_TOKEN not configured\" }, 400);\r\n }\r\n const repo = c.req.query(\"repo\");\r\n const state = c.req.query(\"state\") || \"open\";\r\n const github = await import(\"../../../integrations/github\");\r\n if (repo) {\r\n const [owner, name] = repo.split(\"/\");\r\n const issues = await github.listIssues(owner, name, { state: state as any });\r\n return c.json(issues);\r\n }\r\n // List issues for authenticated user\r\n const issues = await github.listIssues(\"\", \"\", { state: state as any });\r\n return c.json(issues);\r\n } catch {\r\n return c.json([], 200);\r\n }\r\n});\r\n\r\n// GET /api/github/prs — List pull requests\r\ngithubRouter.get(\"/prs\", async (c) => {\r\n try {\r\n const { env } = await import(\"../../../config/env\");\r\n if (!env.GITHUB_TOKEN) {\r\n return c.json({ error: \"GITHUB_TOKEN not configured\" }, 400);\r\n }\r\n const repo = c.req.query(\"repo\");\r\n const state = c.req.query(\"state\") || \"open\";\r\n const github = await import(\"../../../integrations/github\");\r\n if (repo) {\r\n const [owner, name] = repo.split(\"/\");\r\n const prs = await github.listPullRequests(owner, name, { state: state as any });\r\n return c.json(prs);\r\n }\r\n const prs = await github.listPullRequests(\"\", \"\", { state: state as any });\r\n return c.json(prs);\r\n } catch {\r\n return c.json([], 200);\r\n }\r\n});\r\n\r\nexport default githubRouter;\r\n","import { Hono } from \"hono\";\r\nimport {\r\n recordMetric,\r\n getMetricAggregates,\r\n getMetricTimeSeries,\r\n flushMetrics,\r\n type MetricName,\r\n} from \"../../../core/observability/metrics\";\r\nimport {\r\n getRecentErrors,\r\n getErrorStats,\r\n} from \"../../../core/observability/error-tracker\";\r\nimport { checkRateLimit } from \"../../../core/security/rate-limiter\";\r\n\r\nconst metricsRouter = new Hono();\r\n\r\n// Middleware for API key authentication\r\nasync function requireApiKey(c: any, next: () => Promise<void>) {\r\n const apiKey = c.req.header(\"x-api-key\");\r\n if (!apiKey) {\r\n return c.json({ error: \"API key required\" }, 401);\r\n }\r\n\r\n // Rate limit check\r\n const rateLimitResult = await checkRateLimit(apiKey, \"api/metrics\");\r\n if (!rateLimitResult.allowed) {\r\n return c.json(\r\n {\r\n error: \"Rate limit exceeded\",\r\n retryAfter: rateLimitResult.retryAfterMs,\r\n },\r\n 429\r\n );\r\n }\r\n\r\n await next();\r\n}\r\n\r\nmetricsRouter.use(\"*\", requireApiKey);\r\n\r\n// Get metrics aggregation\r\nmetricsRouter.get(\"/aggregation\", async (c) => {\r\n const metricType = c.req.query(\"type\");\r\n const startDate = c.req.query(\"start\");\r\n const endDate = c.req.query(\"end\");\r\n const groupBy = c.req.query(\"groupBy\") as \"hour\" | \"day\" | \"week\" | undefined;\r\n\r\n if (!metricType) {\r\n return c.json({ error: \"Metric type required\" }, 400);\r\n }\r\n\r\n const start = startDate ? new Date(startDate) : new Date(Date.now() - 24 * 60 * 60 * 1000);\r\n const end = endDate ? new Date(endDate) : new Date();\r\n\r\n const aggregation = await getMetricAggregates(metricType as MetricName, start, end);\r\n\r\n return c.json({\r\n type: metricType,\r\n period: { start: start.toISOString(), end: end.toISOString() },\r\n aggregation,\r\n });\r\n});\r\n\r\n// Get metrics time series\r\nmetricsRouter.get(\"/timeseries\", async (c) => {\r\n const metricType = c.req.query(\"type\");\r\n const startDate = c.req.query(\"start\");\r\n const endDate = c.req.query(\"end\");\r\n const interval = c.req.query(\"interval\") as \"hour\" | \"day\" | undefined;\r\n\r\n if (!metricType) {\r\n return c.json({ error: \"Metric type required\" }, 400);\r\n }\r\n\r\n const start = startDate ? new Date(startDate) : new Date(Date.now() - 24 * 60 * 60 * 1000);\r\n const end = endDate ? new Date(endDate) : new Date();\r\n\r\n const timeSeries = await getMetricTimeSeries(metricType as MetricName, start, end);\r\n\r\n return c.json({\r\n type: metricType,\r\n period: { start: start.toISOString(), end: end.toISOString() },\r\n interval: interval || \"hour\",\r\n data: timeSeries,\r\n });\r\n});\r\n\r\n// Record a metric (for external systems)\r\nmetricsRouter.post(\"/record\", async (c) => {\r\n const body = await c.req.json();\r\n const { type, value, metadata, userId } = body;\r\n\r\n if (!type || value === undefined) {\r\n return c.json({ error: \"Type and value required\" }, 400);\r\n }\r\n\r\n await recordMetric({\r\n name: type as MetricName,\r\n value,\r\n tags: metadata,\r\n });\r\n\r\n return c.json({ success: true });\r\n});\r\n\r\n// Flush metrics buffer\r\nmetricsRouter.post(\"/flush\", async (c) => {\r\n await flushMetrics();\r\n return c.json({ success: true, message: \"Metrics flushed\" });\r\n});\r\n\r\n// Get error stats\r\nmetricsRouter.get(\"/errors/stats\", async (c) => {\r\n const days = parseInt(c.req.query(\"days\") || \"7\");\r\n const now = new Date();\r\n const since = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);\r\n const stats = await getErrorStats(since, now);\r\n\r\n return c.json({\r\n period: `Last ${days} days`,\r\n stats,\r\n });\r\n});\r\n\r\n// Get recent errors\r\nmetricsRouter.get(\"/errors/recent\", async (c) => {\r\n const limit = parseInt(c.req.query(\"limit\") || \"20\");\r\n const category = c.req.query(\"category\");\r\n const resolved = c.req.query(\"resolved\");\r\n\r\n const errors = await getRecentErrors(\r\n limit,\r\n category as any\r\n );\r\n\r\n return c.json({\r\n count: errors.length,\r\n errors,\r\n });\r\n});\r\n\r\n// Health check endpoint\r\nmetricsRouter.get(\"/health\", async (c) => {\r\n const now = new Date();\r\n\r\n // Get recent metrics to check system health\r\n const recentLatency = await getMetricAggregates(\r\n \"response_latency\" as MetricName,\r\n new Date(now.getTime() - 5 * 60 * 1000),\r\n now\r\n );\r\n\r\n const recentErrors = await getRecentErrors(10);\r\n\r\n const status = {\r\n healthy: true,\r\n timestamp: now.toISOString(),\r\n metrics: {\r\n avgLatencyMs: recentLatency.avg || 0,\r\n recentErrorCount: recentErrors.length,\r\n },\r\n };\r\n\r\n // Mark unhealthy if too many recent errors\r\n if (recentErrors.length > 5) {\r\n status.healthy = false;\r\n }\r\n\r\n return c.json(status, status.healthy ? 200 : 503);\r\n});\r\n\r\n// System metrics overview\r\nmetricsRouter.get(\"/overview\", async (c) => {\r\n const now = new Date();\r\n const dayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);\r\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\r\n\r\n const [\r\n latencyDay,\r\n tokensDay,\r\n errorsDay,\r\n latencyWeek,\r\n tokensWeek,\r\n errorsWeek,\r\n ] = await Promise.all([\r\n getMetricAggregates(\"response_latency\" as MetricName, dayAgo, now),\r\n getMetricAggregates(\"token_usage_input\" as MetricName, dayAgo, now),\r\n getErrorStats(dayAgo, now),\r\n getMetricAggregates(\"response_latency\" as MetricName, weekAgo, now),\r\n getMetricAggregates(\"token_usage_input\" as MetricName, weekAgo, now),\r\n getErrorStats(weekAgo, now),\r\n ]);\r\n\r\n return c.json({\r\n timestamp: now.toISOString(),\r\n last24Hours: {\r\n avgLatencyMs: latencyDay.avg || 0,\r\n totalTokens: tokensDay.sum || 0,\r\n requestCount: latencyDay.count || 0,\r\n errorCount: errorsDay.total || 0,\r\n },\r\n last7Days: {\r\n avgLatencyMs: latencyWeek.avg || 0,\r\n totalTokens: tokensWeek.sum || 0,\r\n requestCount: latencyWeek.count || 0,\r\n errorCount: errorsWeek.total || 0,\r\n },\r\n });\r\n});\r\n\r\nexport default metricsRouter;\r\n","/**\r\n * MCP API Routes — Model Context Protocol server status for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\n\r\nconst mcpRouter = new Hono();\r\n\r\n// GET /api/mcp/servers — List all MCP servers with status and tools\r\nmcpRouter.get(\"/servers\", async (c) => {\r\n try {\r\n const { getMCPRegistry } = await import(\"../../../tools\");\r\n const registry = getMCPRegistry();\r\n if (!registry) {\r\n return c.json({ enabled: false, servers: [], connectedCount: 0, totalToolCount: 0 });\r\n }\r\n\r\n const states = registry.getServerStates();\r\n const servers = states.map((s: any) => ({\r\n id: s.config?.id || \"unknown\",\r\n name: s.config?.name || s.serverInfo?.name || s.config?.id || \"Unknown\",\r\n transport: s.config?.transport || \"stdio\",\r\n enabled: s.config?.enabled ?? true,\r\n status: s.status || \"disconnected\",\r\n serverVersion: s.serverInfo?.version || null,\r\n toolCount: Array.isArray(s.tools) ? s.tools.length : 0,\r\n tools: Array.isArray(s.tools) ? s.tools.map((t: any) => ({\r\n name: t.name,\r\n description: t.description || \"\",\r\n })) : [],\r\n lastError: s.lastError || null,\r\n lastActivity: s.lastActivity || null,\r\n command: s.config?.command || null,\r\n args: s.config?.args || [],\r\n }));\r\n\r\n return c.json({\r\n enabled: true,\r\n connectedCount: registry.connectedCount,\r\n totalToolCount: registry.totalToolCount,\r\n servers,\r\n });\r\n } catch {\r\n return c.json({ enabled: false, servers: [], connectedCount: 0, totalToolCount: 0 });\r\n }\r\n});\r\n\r\n// POST /api/mcp/servers/:id/refresh — Refresh tools for a server\r\nmcpRouter.post(\"/servers/:id/refresh\", async (c) => {\r\n try {\r\n const { getMCPRegistry } = await import(\"../../../tools\");\r\n const registry = getMCPRegistry();\r\n if (!registry) return c.json({ error: \"MCP not initialized\" }, 500);\r\n await registry.refreshAllTools();\r\n return c.json({ success: true });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to refresh\" }, 500);\r\n }\r\n});\r\n\r\nexport default mcpRouter;\r\n","/**\r\n * Bots API Routes — Bot integration status + configuration for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\nimport { readFileSync, writeFileSync, existsSync } from \"fs\";\r\nimport { resolve } from \"path\";\r\n\r\nconst botsRouter = new Hono();\r\n\r\n// Bot field definitions for each platform\r\nconst BOT_FIELDS: Record<string, Array<{\r\n key: string;\r\n envVar: string;\r\n label: string;\r\n type: \"text\" | \"password\" | \"boolean\" | \"number\" | \"select\";\r\n placeholder?: string;\r\n options?: string[];\r\n help?: string;\r\n required?: boolean;\r\n}>> = {\r\n telegram: [\r\n { key: \"botToken\", envVar: \"TELEGRAM_BOT_TOKEN\", label: \"Bot Token\", type: \"password\", placeholder: \"123456:ABC-DEF1234...\", help: \"Get from @BotFather on Telegram\", required: true },\r\n { key: \"chatId\", envVar: \"TELEGRAM_CHAT_ID\", label: \"Chat ID\", type: \"text\", placeholder: \"-1001234567890\", help: \"Your chat/group ID for notifications\" },\r\n ],\r\n discord: [\r\n { key: \"botToken\", envVar: \"DISCORD_BOT_TOKEN\", label: \"Bot Token\", type: \"password\", placeholder: \"MTIz...\", help: \"From Discord Developer Portal > Bot\", required: true },\r\n { key: \"clientId\", envVar: \"DISCORD_CLIENT_ID\", label: \"Client ID\", type: \"text\", placeholder: \"123456789012345678\", help: \"Application ID from Discord Developer Portal\" },\r\n { key: \"guildId\", envVar: \"DISCORD_GUILD_ID\", label: \"Guild (Server) ID\", type: \"text\", placeholder: \"123456789012345678\", help: \"Right-click server > Copy Server ID\" },\r\n { key: \"allowedUserIds\", envVar: \"DISCORD_ALLOWED_USER_IDS\", label: \"Allowed User IDs\", type: \"text\", placeholder: \"id1,id2,id3\", help: \"Comma-separated Discord user IDs\" },\r\n { key: \"allowedRoleIds\", envVar: \"DISCORD_ALLOWED_ROLE_IDS\", label: \"Allowed Role IDs\", type: \"text\", placeholder: \"id1,id2\", help: \"Comma-separated Discord role IDs\" },\r\n ],\r\n slack: [\r\n { key: \"botToken\", envVar: \"SLACK_BOT_TOKEN\", label: \"Bot Token\", type: \"password\", placeholder: \"xoxb-...\", help: \"From Slack App > OAuth & Permissions\", required: true },\r\n { key: \"signingSecret\", envVar: \"SLACK_SIGNING_SECRET\", label: \"Signing Secret\", type: \"password\", placeholder: \"abc123...\", help: \"From Slack App > Basic Information\", required: true },\r\n { key: \"appToken\", envVar: \"SLACK_APP_TOKEN\", label: \"App Token\", type: \"password\", placeholder: \"xapp-...\", help: \"For Socket Mode — from Slack App > Basic Information\" },\r\n { key: \"socketMode\", envVar: \"SLACK_SOCKET_MODE\", label: \"Socket Mode\", type: \"boolean\", help: \"Use WebSocket instead of HTTP events\" },\r\n { key: \"port\", envVar: \"SLACK_PORT\", label: \"Port\", type: \"number\", placeholder: \"3000\", help: \"HTTP listener port (if not using Socket Mode)\" },\r\n { key: \"allowedUserIds\", envVar: \"SLACK_ALLOWED_USER_IDS\", label: \"Allowed User IDs\", type: \"text\", placeholder: \"U01ABC,U02DEF\", help: \"Comma-separated Slack user IDs\" },\r\n { key: \"allowedChannelIds\", envVar: \"SLACK_ALLOWED_CHANNEL_IDS\", label: \"Allowed Channel IDs\", type: \"text\", placeholder: \"C01ABC,C02DEF\", help: \"Comma-separated Slack channel IDs\" },\r\n ],\r\n whatsapp: [\r\n { key: \"enabled\", envVar: \"WHATSAPP_ENABLED\", label: \"Enabled\", type: \"boolean\", help: \"Enable WhatsApp bot\", required: true },\r\n { key: \"authDir\", envVar: \"WHATSAPP_AUTH_DIR\", label: \"Auth Directory\", type: \"text\", placeholder: \"./whatsapp-auth\", help: \"Directory for session storage\" },\r\n { key: \"allowedNumbers\", envVar: \"WHATSAPP_ALLOWED_NUMBERS\", label: \"Allowed Numbers\", type: \"text\", placeholder: \"+1234567890,+0987654321\", help: \"Comma-separated phone numbers\" },\r\n ],\r\n signal: [\r\n { key: \"enabled\", envVar: \"SIGNAL_ENABLED\", label: \"Enabled\", type: \"boolean\", help: \"Enable Signal bot\", required: true },\r\n { key: \"phoneNumber\", envVar: \"SIGNAL_PHONE_NUMBER\", label: \"Phone Number\", type: \"text\", placeholder: \"+1234567890\", help: \"Registered Signal phone number\", required: true },\r\n { key: \"cliPath\", envVar: \"SIGNAL_CLI_PATH\", label: \"CLI Path\", type: \"text\", placeholder: \"signal-cli\", help: \"Path to signal-cli binary\" },\r\n { key: \"allowedNumbers\", envVar: \"SIGNAL_ALLOWED_NUMBERS\", label: \"Allowed Numbers\", type: \"text\", placeholder: \"+1234567890,+0987654321\", help: \"Comma-separated phone numbers\" },\r\n ],\r\n imessage: [\r\n { key: \"enabled\", envVar: \"IMESSAGE_ENABLED\", label: \"Enabled\", type: \"boolean\", help: \"Enable iMessage bot (macOS only)\", required: true },\r\n { key: \"mode\", envVar: \"IMESSAGE_MODE\", label: \"Mode\", type: \"select\", options: [\"applescript\", \"bluebubbles\"], help: \"AppleScript (local) or BlueBubbles (remote)\" },\r\n { key: \"blueBubblesUrl\", envVar: \"IMESSAGE_BLUEBUBBLES_URL\", label: \"BlueBubbles URL\", type: \"text\", placeholder: \"http://localhost:1234\", help: \"BlueBubbles server URL\" },\r\n { key: \"blueBubblesPassword\", envVar: \"IMESSAGE_BLUEBUBBLES_PASSWORD\", label: \"BlueBubbles Password\", type: \"password\", help: \"BlueBubbles server password\" },\r\n { key: \"allowedNumbers\", envVar: \"IMESSAGE_ALLOWED_NUMBERS\", label: \"Allowed Numbers\", type: \"text\", placeholder: \"+1234567890,+0987654321\", help: \"Comma-separated phone numbers\" },\r\n ],\r\n matrix: [\r\n { key: \"enabled\", envVar: \"MATRIX_ENABLED\", label: \"Enabled\", type: \"boolean\", help: \"Enable Matrix bot\", required: true },\r\n { key: \"homeserverUrl\", envVar: \"MATRIX_HOMESERVER_URL\", label: \"Homeserver URL\", type: \"text\", placeholder: \"https://matrix.org\", help: \"Matrix homeserver URL\", required: true },\r\n { key: \"accessToken\", envVar: \"MATRIX_ACCESS_TOKEN\", label: \"Access Token\", type: \"password\", help: \"Matrix access token\", required: true },\r\n { key: \"userId\", envVar: \"MATRIX_USER_ID\", label: \"User ID\", type: \"text\", placeholder: \"@bot:matrix.org\", help: \"Bot's Matrix user ID\" },\r\n { key: \"autoJoin\", envVar: \"MATRIX_AUTO_JOIN\", label: \"Auto Join Rooms\", type: \"boolean\", help: \"Automatically join rooms when invited\" },\r\n { key: \"e2eEnabled\", envVar: \"MATRIX_E2E_ENABLED\", label: \"E2E Encryption\", type: \"boolean\", help: \"Enable end-to-end encryption\" },\r\n { key: \"allowedRoomIds\", envVar: \"MATRIX_ALLOWED_ROOM_IDS\", label: \"Allowed Room IDs\", type: \"text\", placeholder: \"!roomid:matrix.org\", help: \"Comma-separated room IDs\" },\r\n ],\r\n};\r\n\r\nfunction getEnvFilePath(): string {\r\n return resolve(process.cwd(), \".env\");\r\n}\r\n\r\nfunction parseEnvFile(): Map<string, string> {\r\n const envPath = getEnvFilePath();\r\n const vars = new Map<string, string>();\r\n if (!existsSync(envPath)) return vars;\r\n const content = readFileSync(envPath, \"utf-8\");\r\n for (const line of content.split(\"\\n\")) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\r\n const eqIdx = trimmed.indexOf(\"=\");\r\n if (eqIdx === -1) continue;\r\n const key = trimmed.slice(0, eqIdx).trim();\r\n let val = trimmed.slice(eqIdx + 1).trim();\r\n // Strip surrounding quotes\r\n if ((val.startsWith('\"') && val.endsWith('\"')) || (val.startsWith(\"'\") && val.endsWith(\"'\"))) {\r\n val = val.slice(1, -1);\r\n }\r\n vars.set(key, val);\r\n }\r\n return vars;\r\n}\r\n\r\nfunction updateEnvFile(updates: Record<string, string>): void {\r\n const envPath = getEnvFilePath();\r\n let content = existsSync(envPath) ? readFileSync(envPath, \"utf-8\") : \"\";\r\n const lines = content.split(\"\\n\");\r\n\r\n for (const [key, value] of Object.entries(updates)) {\r\n const lineIdx = lines.findIndex(l => {\r\n const trimmed = l.trim();\r\n return !trimmed.startsWith(\"#\") && trimmed.startsWith(key + \"=\");\r\n });\r\n const newLine = `${key}=${value}`;\r\n if (lineIdx >= 0) {\r\n lines[lineIdx] = newLine;\r\n } else {\r\n lines.push(newLine);\r\n }\r\n }\r\n\r\n writeFileSync(envPath, lines.join(\"\\n\"), \"utf-8\");\r\n}\r\n\r\n// GET /api/bots/status — Status of all bot integrations\r\nbotsRouter.get(\"/status\", async (c) => {\r\n try {\r\n const { env } = await import(\"../../../config/env\");\r\n\r\n const bots = [\r\n {\r\n id: \"telegram\",\r\n name: \"Telegram\",\r\n icon: \"telegram\",\r\n enabled: !!env.TELEGRAM_BOT_TOKEN,\r\n config: {\r\n chatId: env.TELEGRAM_CHAT_ID ? true : false,\r\n },\r\n description: \"Telegram bot via grammY framework\",\r\n },\r\n {\r\n id: \"discord\",\r\n name: \"Discord\",\r\n icon: \"discord\",\r\n enabled: !!env.DISCORD_BOT_TOKEN,\r\n config: {\r\n guildId: env.DISCORD_GUILD_ID || null,\r\n clientId: env.DISCORD_CLIENT_ID ? true : false,\r\n allowedUsers: env.DISCORD_ALLOWED_USER_IDS\r\n ? env.DISCORD_ALLOWED_USER_IDS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"Discord bot via discord.js with slash commands and voice\",\r\n },\r\n {\r\n id: \"slack\",\r\n name: \"Slack\",\r\n icon: \"slack\",\r\n enabled: !!env.SLACK_BOT_TOKEN && !!env.SLACK_SIGNING_SECRET,\r\n config: {\r\n socketMode: env.SLACK_SOCKET_MODE || false,\r\n port: env.SLACK_PORT || 3000,\r\n allowedUsers: env.SLACK_ALLOWED_USER_IDS\r\n ? env.SLACK_ALLOWED_USER_IDS.split(\",\").length\r\n : 0,\r\n allowedChannels: env.SLACK_ALLOWED_CHANNEL_IDS\r\n ? env.SLACK_ALLOWED_CHANNEL_IDS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"Slack bot via @slack/bolt with Socket Mode support\",\r\n },\r\n {\r\n id: \"whatsapp\",\r\n name: \"WhatsApp\",\r\n icon: \"whatsapp\",\r\n enabled: !!env.WHATSAPP_ENABLED,\r\n config: {\r\n allowedNumbers: env.WHATSAPP_ALLOWED_NUMBERS\r\n ? env.WHATSAPP_ALLOWED_NUMBERS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"WhatsApp bot via Baileys with QR code authentication\",\r\n },\r\n {\r\n id: \"signal\",\r\n name: \"Signal\",\r\n icon: \"signal\",\r\n enabled: !!env.SIGNAL_ENABLED && !!env.SIGNAL_PHONE_NUMBER,\r\n config: {\r\n hasPhoneNumber: !!env.SIGNAL_PHONE_NUMBER,\r\n allowedNumbers: env.SIGNAL_ALLOWED_NUMBERS\r\n ? env.SIGNAL_ALLOWED_NUMBERS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"Signal bot via signal-cli with end-to-end encryption\",\r\n },\r\n {\r\n id: \"imessage\",\r\n name: \"iMessage\",\r\n icon: \"imessage\",\r\n enabled: !!env.IMESSAGE_ENABLED,\r\n config: {\r\n mode: env.IMESSAGE_MODE || \"applescript\",\r\n allowedNumbers: env.IMESSAGE_ALLOWED_NUMBERS\r\n ? env.IMESSAGE_ALLOWED_NUMBERS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"iMessage bot via AppleScript or BlueBubbles API\",\r\n },\r\n {\r\n id: \"matrix\",\r\n name: \"Matrix\",\r\n icon: \"matrix\",\r\n enabled: !!env.MATRIX_ENABLED && !!env.MATRIX_HOMESERVER_URL && !!env.MATRIX_ACCESS_TOKEN,\r\n config: {\r\n homeserver: env.MATRIX_HOMESERVER_URL || null,\r\n userId: env.MATRIX_USER_ID || null,\r\n autoJoin: env.MATRIX_AUTO_JOIN ?? true,\r\n e2eEnabled: env.MATRIX_E2E_ENABLED || false,\r\n allowedRooms: env.MATRIX_ALLOWED_ROOM_IDS\r\n ? env.MATRIX_ALLOWED_ROOM_IDS.split(\",\").length\r\n : 0,\r\n },\r\n description: \"Matrix bot with optional end-to-end encryption\",\r\n },\r\n ];\r\n\r\n const enabledCount = bots.filter(b => b.enabled).length;\r\n\r\n return c.json({ bots, enabledCount, totalCount: bots.length });\r\n } catch {\r\n return c.json({ bots: [], enabledCount: 0, totalCount: 0 });\r\n }\r\n});\r\n\r\n// GET /api/bots/fields — Field definitions for each bot\r\nbotsRouter.get(\"/fields\", (c) => {\r\n return c.json(BOT_FIELDS);\r\n});\r\n\r\n// GET /api/bots/:id/config — Current config values (secrets masked)\r\nbotsRouter.get(\"/:id/config\", async (c) => {\r\n const botId = c.req.param(\"id\");\r\n const fields = BOT_FIELDS[botId];\r\n if (!fields) return c.json({ error: \"Unknown bot\" }, 404);\r\n\r\n const envVars = parseEnvFile();\r\n const values: Record<string, string> = {};\r\n\r\n for (const field of fields) {\r\n const raw = envVars.get(field.envVar) || \"\";\r\n if (field.type === \"password\" && raw) {\r\n // Mask secrets: show first 4 and last 4 chars\r\n values[field.key] = raw.length > 10\r\n ? raw.slice(0, 4) + \"...\" + raw.slice(-4)\r\n : \"****\";\r\n } else {\r\n values[field.key] = raw;\r\n }\r\n }\r\n\r\n return c.json({ botId, values, fields });\r\n});\r\n\r\n// PUT /api/bots/:id/config — Update bot configuration in .env\r\nbotsRouter.put(\"/:id/config\", async (c) => {\r\n const botId = c.req.param(\"id\");\r\n const fields = BOT_FIELDS[botId];\r\n if (!fields) return c.json({ error: \"Unknown bot\" }, 404);\r\n\r\n try {\r\n const body = await c.req.json<Record<string, string>>();\r\n const updates: Record<string, string> = {};\r\n\r\n for (const field of fields) {\r\n if (field.key in body) {\r\n let val = body[field.key];\r\n // Skip masked password values (user didn't change them)\r\n if (field.type === \"password\" && (val.includes(\"...\") || val === \"****\")) continue;\r\n updates[field.envVar] = val;\r\n }\r\n }\r\n\r\n if (Object.keys(updates).length > 0) {\r\n updateEnvFile(updates);\r\n }\r\n\r\n return c.json({ success: true, updated: Object.keys(updates).length, note: \"Restart required for changes to take effect\" });\r\n } catch (err: any) {\r\n return c.json({ error: err?.message || \"Failed to update config\" }, 500);\r\n }\r\n});\r\n\r\nexport default botsRouter;\r\n","/**\r\n * Users API Routes — User management for the dashboard\r\n */\r\n\r\nimport { Hono } from \"hono\";\r\n\r\nconst usersRouter = new Hono();\r\n\r\n// GET /api/users — List users\r\nusersRouter.get(\"/\", async (c) => {\r\n try {\r\n const { searchUsers } = await import(\"../../../core/enterprise/multi-user\");\r\n const users = await searchUsers({});\r\n return c.json(users);\r\n } catch {\r\n return c.json([]);\r\n }\r\n});\r\n\r\n// POST /api/users — Create user\r\nusersRouter.post(\"/\", async (c) => {\r\n try {\r\n const { email, name, role } = await c.req.json<{\r\n email: string;\r\n name?: string;\r\n role?: string;\r\n }>();\r\n\r\n if (!email) {\r\n return c.json({ error: \"email is required\" }, 400);\r\n }\r\n\r\n const { createUser } = await import(\"../../../core/enterprise/multi-user\");\r\n const user = await createUser({\r\n email,\r\n name: name || \"\",\r\n role: role || \"user\",\r\n });\r\n return c.json(user, 201);\r\n } catch (error) {\r\n return c.json({ error: \"Failed to create user\" }, 500);\r\n }\r\n});\r\n\r\n// PUT /api/users/:id — Update user\r\nusersRouter.put(\"/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const updates = await c.req.json();\r\n\r\n if (updates.status === \"suspended\") {\r\n const { suspendUser } = await import(\"../../../core/enterprise/multi-user\");\r\n await suspendUser(id, \"Suspended via dashboard\");\r\n return c.json({ success: true });\r\n }\r\n\r\n if (updates.status === \"active\") {\r\n const { reactivateUser } = await import(\"../../../core/enterprise/multi-user\");\r\n await reactivateUser(id);\r\n return c.json({ success: true });\r\n }\r\n\r\n const { updateUser } = await import(\"../../../core/enterprise/multi-user\");\r\n await updateUser(id, updates);\r\n return c.json({ success: true });\r\n } catch (error) {\r\n return c.json({ error: \"Failed to update user\" }, 500);\r\n }\r\n});\r\n\r\n// DELETE /api/users/:id — Delete user\r\nusersRouter.delete(\"/:id\", async (c) => {\r\n try {\r\n const id = c.req.param(\"id\");\r\n const { deleteUser } = await import(\"../../../core/enterprise/multi-user\");\r\n await deleteUser(id);\r\n return c.json({ success: true });\r\n } catch (error) {\r\n return c.json({ error: \"Failed to delete user\" }, 500);\r\n }\r\n});\r\n\r\nexport default usersRouter;\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,QAAAA,cAAY;AACrB,SAAS,YAAY;AACrB,SAAS,cAAc;AAcvB,SAAS,QAAAC,OAAM,MAAAC,WAAU;;;ACdzB,SAAS,IAAI,KAAK,cAAc;AAChC,SAAS,aAAa,kBAAkB;AAExC,IAAM,aAAa;AAqEnB,SAAS,WAAW,KAAqB;AACvC,SAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AACtD;AA+DA,eAAsB,eACpB,QACmE;AACnE,MAAI,CAAC,OAAO,WAAW,UAAU,GAAG;AAClC,WAAO,EAAE,OAAO,MAAM;AAAA,EACxB;AAEA,QAAM,UAAU,WAAW,MAAM;AACjC,QAAM,MAAM,oBAAI,KAAK;AAErB,QAAM,CAAC,GAAG,IAAI,MAAM,GACjB,OAAO,EACP,KAAK,OAAO,EACZ;AAAA,IACC;AAAA,MACE,GAAG,QAAQ,SAAS,OAAO;AAAA,MAC3B,OAAO,QAAQ,SAAS;AAAA,IAC1B;AAAA,EACF,EACC,MAAM,CAAC;AAEV,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,OAAO,MAAM;AAAA,EACxB;AAGA,MAAI,IAAI,aAAa,IAAI,YAAY,KAAK;AACxC,WAAO,EAAE,OAAO,MAAM;AAAA,EACxB;AAGA,QAAM,GACH,OAAO,OAAO,EACd,IAAI,EAAE,YAAY,IAAI,CAAC,EACvB,MAAM,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAE/B,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,MACN,IAAI,IAAI;AAAA,MACR,MAAM,IAAI;AAAA,MACV,QAAQ,IAAI;AAAA,MACZ,aAAc,IAAI,eAAgC,CAAC;AAAA,MACnD,WAAW,IAAI;AAAA,MACf,YAAY;AAAA,MACZ,WAAW,IAAI;AAAA,MACf,WAAW;AAAA,IACb;AAAA,IACA,QAAQ,IAAI;AAAA,EACd;AACF;AAEO,SAAS,cACd,mBACA,oBACS;AAET,MAAI,kBAAkB,SAAS,GAAG,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,SAAO,kBAAkB,SAAS,kBAAkB;AACtD;;;ACvMA,SAAS,MAAAC,KAAI,OAAAC,MAAK,IAAI,UAAU;AAChC,SAAS,eAAAC,cAAa,cAAAC,mBAAkB;AAExC,IAAM,sBAAsB,IAAI,KAAK,KAAK,KAAK;AA6B/C,SAAS,UAAU,OAAuB;AACxC,SAAOC,YAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAiCA,eAAsB,gBAAgB,OAA4C;AAChF,QAAM,YAAY,UAAU,KAAK;AACjC,QAAM,MAAM,oBAAI,KAAK;AAErB,QAAM,CAAC,OAAO,IAAI,MAAM,GACrB,OAAO,EACP,KAAK,QAAQ,EACb,MAAMC,KAAIC,IAAG,SAAS,OAAO,SAAS,GAAG,GAAG,SAAS,WAAW,GAAG,CAAC,CAAC,EACrE,MAAM,CAAC;AAEV,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAGA,QAAM,GACH,OAAO,QAAQ,EACf,IAAI,EAAE,cAAc,IAAI,CAAC,EACzB,MAAMA,IAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;AAEpC,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,EACtB;AACF;;;AClFO,SAAS,kBAAsC;AACpD,QAAM,QAAQ,IAAI;AAClB,SAAO,SAAS;AAClB;AAMO,SAAS,gBAAgB,GAAW,GAAoB;AAC7D,MAAI,EAAE,WAAW,EAAE,QAAQ;AAEzB,QAAIC,UAAS;AACb,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,MAAAA,WAAU,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,KAAK,EAAE,UAAU,EAAE,KAAK;AAAA,IACpE;AACA,WAAO;AAAA,EACT;AACA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,cAAU,EAAE,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC;AAAA,EAC5C;AACA,SAAO,WAAW;AACpB;;;ACrBA,IAAM,gBAAgB,CAAC,WAAW,sBAAsB,aAAa,mBAAmB;AAGxF,IAAM,aAAa;AAEZ,SAAS,iBAAoC;AAClD,SAAO,OAAO,GAAY,SAAe;AACvC,UAAM,OAAO,EAAE,IAAI;AAGnB,QAAI,cAAc,SAAS,IAAI,GAAG;AAChC,aAAO,KAAK;AAAA,IACd;AAGA,QAAI,KAAK,WAAW,UAAU,KAAK,SAAS,qBAAqB;AAC/D,aAAO,KAAK;AAAA,IACd;AAGA,UAAM,eAAe,gBAAgB;AACrC,QAAI,CAAC,cAAc;AACjB,QAAE,IAAI,UAAU,OAAO;AACvB,QAAE,IAAI,eAAe,CAAC,GAAG,CAAC;AAC1B,QAAE,IAAI,cAAc,MAAM;AAC1B,aAAO,KAAK;AAAA,IACd;AAGA,UAAM,aAAa,EAAE,IAAI,OAAO,eAAe;AAE/C,QAAI,CAAC,cAAc,CAAC,WAAW,WAAW,SAAS,GAAG;AACpD,aAAO,EAAE,KAAK,EAAE,OAAO,0CAA0C,GAAG,GAAG;AAAA,IACzE;AAEA,UAAM,QAAQ,WAAW,MAAM,CAAC;AAGhC,QAAI,gBAAgB,OAAO,YAAY,GAAG;AACxC,QAAE,IAAI,UAAU,SAAS;AACzB,QAAE,IAAI,eAAe,CAAC,GAAG,CAAC;AAC1B,QAAE,IAAI,cAAc,SAAS;AAE7B,eAAS;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS,EAAE,QAAQ,iBAAiB,KAAK;AAAA,MAC3C,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAEjB,aAAO,KAAK;AAAA,IACd;AAGA,UAAM,cAAc,MAAM,gBAAgB,KAAK;AAC/C,QAAI,aAAa;AACf,QAAE,IAAI,UAAU,YAAY,MAAM;AAClC,QAAE,IAAI,eAAe,CAAC,GAAG,CAAC;AAC1B,QAAE,IAAI,cAAc,SAAS;AAE7B,eAAS;AAAA,QACP,QAAQ,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS,EAAE,QAAQ,WAAW,KAAK;AAAA,MACrC,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAEjB,aAAO,KAAK;AAAA,IACd;AAGA,UAAM,eAAe,MAAM,eAAe,KAAK;AAC/C,QAAI,aAAa,SAAS,aAAa,UAAU,aAAa,QAAQ;AACpE,QAAE,IAAI,UAAU,aAAa,MAAM;AACnC,QAAE,IAAI,eAAe,aAAa,OAAO,WAAW;AACpD,QAAE,IAAI,cAAc,SAAS;AAE7B,eAAS;AAAA,QACP,QAAQ,aAAa;AAAA,QACrB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS,EAAE,QAAQ,WAAW,OAAO,aAAa,OAAO,IAAI,KAAK;AAAA,MACpE,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAEjB,aAAO,KAAK;AAAA,IACd;AAEA,WAAO,EAAE,KAAK,EAAE,OAAO,iCAAiC,GAAG,GAAG;AAAA,EAChE;AACF;AAEO,SAAS,qBACX,qBACgB;AACnB,SAAO,OAAO,GAAY,SAAe;AACvC,UAAM,cAAc,EAAE,IAAI,aAAa;AAEvC,QAAI,CAAC,aAAa;AAChB,aAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,IACnD;AAGA,QAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,aAAO,KAAK;AAAA,IACd;AAEA,eAAW,YAAY,qBAAqB;AAC1C,UAAI,CAAC,cAAc,aAAa,QAAQ,GAAG;AACzC,eAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG;AAAA,MAC1D;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,cAAc,GAAgC;AAC5D,SAAO,EAAE,IAAI,QAAQ;AACvB;;;AC7HA,SAAS,YAAY;AAGrB,SAAS,MAAAC,KAAI,KAAK,MAAM,OAAO,OAAAC,YAAW;AAW1C,IAAI,iBAAgE;AACpE,SAAS,mBAAmB;AAC1B,MAAI,CAAC,eAAgB,kBAAiB,oBAAoB;AAC1D,SAAO;AACT;AAEA,IAAM,QAAQ,IAAI,KAAK;AAMvB,MAAM,IAAI,KAAK,OAAO,GAAG,SAAS;AAChC,MAAI,CAAC,IAAI,eAAe;AACtB,WAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,EAC7D;AACA,QAAM,KAAK;AACb,CAAC;AAMD,MAAM,IAAI,UAAU,OAAO,MAAM;AAC/B,MAAI;AACF,UAAM,aAAa,KAAK,IAAI;AAC5B,UAAM,SAAS,EAAE,IAAI,MAAM,QAAQ,KAAK;AACxC,UAAM,QAAQ,KAAK,IAAI,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,OAAO,EAAE,GAAG,GAAI;AACxE,UAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AACjC,UAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AAEjC,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAc,WAAW;AAAA,MAC/B,WAAW,eAAe,UAAU;AAAA,MACpC,MAAM,EAAE,UAAU,oBAAoB,OAAO,OAAO,MAAM;AAAA,IAC5D,CAAC;AAGD,UAAM,aAAa,CAAC;AACpB,QAAI,OAAO;AACT,iBAAW,KAAK,MAAM,cAAc,SAAS,OAAO,IAAI,KAAK,KAAK,CAAC,EAAE;AAAA,IACvE;AACA,QAAI,OAAO;AACT,iBAAW,KAAK,MAAM,cAAc,SAAS,OAAO,IAAI,KAAK,KAAK,CAAC,EAAE;AAAA,IACvE;AAGA,UAAM,QAAQ,GACX,OAAO;AAAA,MACN,IAAI,cAAc;AAAA,MAClB,MAAM,cAAc;AAAA,MACpB,MAAM,cAAc;AAAA,MACpB,YAAY,cAAc;AAAA,MAC1B,aAAa,cAAc;AAAA,MAC3B,YAAY,cAAc;AAAA,MAC1B,SAAS,cAAc;AAAA,MACvB,WAAW,cAAc;AAAA,IAC3B,CAAC,EACA,KAAK,aAAa;AAErB,UAAM,WAAW,WAAW,SAAS,IACjC,MAAM,MAAM,MAAMC,KAAI,GAAG,UAAU,CAAC,EAAE,QAAQ,KAAK,cAAc,UAAU,CAAC,EAAE,MAAM,KAAK,IACzF,MAAM,MAAM,QAAQ,KAAK,cAAc,UAAU,CAAC,EAAE,MAAM,KAAK;AAEnE,UAAM,YAAY,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE;AAE1C,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,IACxC;AAGA,UAAM,gBAAgB,MAAM,GACzB,OAAO;AAAA,MACN,IAAI,mBAAmB;AAAA,MACvB,QAAQ,mBAAmB;AAAA,MAC3B,QAAQ,mBAAmB;AAAA,MAC3B,MAAM,mBAAmB;AAAA,MACzB,UAAU,mBAAmB;AAAA,IAC/B,CAAC,EACA,KAAK,kBAAkB,EACvB;AAAA,MACCA;AAAA,QACE,MAAM,mBAAmB,cAAc,UAAU,YAAY,IAAI,KAAK,UAAU,IAAI,QAAM,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,QAC1H,MAAM,mBAAmB,cAAc,UAAU,YAAY,IAAI,KAAK,UAAU,IAAI,QAAM,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,MAC5H;AAAA,IACF;AAEF,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAiB,WAAW,KAAK,IAAI;AAAA,MAC3C,WAAW,eAAe,UAAU;AAAA,MACpC,MAAM,EAAE,UAAU,oBAAoB,SAAS,MAAM,WAAW,KAAK,IAAI,IAAI,YAAY,WAAW,SAAS,QAAQ,WAAW,cAAc,OAAO;AAAA,IACvJ,CAAC;AAED,WAAO,EAAE,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,QACL,eAAe,SAAS;AAAA,QACxB,oBAAoB,cAAc;AAAA,QAClC,cAAc,IAAI;AAAA,UAChB,SAAS,QAAQ,CAAC,MAAM;AACtB,kBAAM,OAAQ,EAAE,YAAoB;AACpC,mBAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,MAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,UAC5E,CAAC;AAAA,QACH,EAAE;AAAA,MACJ;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,EAC5D;AACF,CAAC;AAMD,MAAM,IAAI,eAAe,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAE3B,UAAM,UAAU,MAAM,GACnB,OAAO,EACP,KAAK,aAAa,EAClB,MAAMC,IAAG,cAAc,IAAI,EAAE,CAAC,EAC9B,MAAM,CAAC;AAEV,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,UAAM,SAAS,QAAQ,CAAC;AAGxB,UAAM,WAAW,MAAM,GACpB,OAAO;AAAA,MACN,IAAI,mBAAmB;AAAA,MACvB,gBAAgB,mBAAmB;AAAA,MACnC,gBAAgB,mBAAmB;AAAA,MACnC,MAAM,mBAAmB;AAAA,MACzB,UAAU,mBAAmB;AAAA,MAC7B,SAAS,mBAAmB;AAAA,MAC5B,YAAY,mBAAmB;AAAA,MAC/B,YAAY,cAAc;AAAA,IAC5B,CAAC,EACA,KAAK,kBAAkB,EACvB,UAAU,eAAeA,IAAG,mBAAmB,gBAAgB,cAAc,EAAE,CAAC,EAChF,MAAMA,IAAG,mBAAmB,gBAAgB,EAAE,CAAC;AAGlD,UAAM,WAAW,MAAM,GACpB,OAAO;AAAA,MACN,IAAI,mBAAmB;AAAA,MACvB,gBAAgB,mBAAmB;AAAA,MACnC,gBAAgB,mBAAmB;AAAA,MACnC,MAAM,mBAAmB;AAAA,MACzB,UAAU,mBAAmB;AAAA,MAC7B,SAAS,mBAAmB;AAAA,MAC5B,YAAY,mBAAmB;AAAA,MAC/B,YAAY,cAAc;AAAA,IAC5B,CAAC,EACA,KAAK,kBAAkB,EACvB,UAAU,eAAeA,IAAG,mBAAmB,gBAAgB,cAAc,EAAE,CAAC,EAChF,MAAMA,IAAG,mBAAmB,gBAAgB,EAAE,CAAC;AAElD,WAAO,EAAE,KAAK;AAAA,MACZ;AAAA,MACA,eAAe;AAAA,QACb;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,KAAK;AACrD,WAAO,EAAE,KAAK,EAAE,OAAO,yBAAyB,GAAG,GAAG;AAAA,EACxD;AACF,CAAC;AASD,SAAS,iBAAiB,KAAqB;AAC7C,MAAI,CAAC,IAAI,SAAS,GAAG,EAAG,QAAO,YAAY,GAAG;AAC9C,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAC1D,QAAM,QAAQ,KAAK,KAAK,GAAG,EAAE,KAAK;AAClC,MAAI,CAAC,MAAO,QAAO,YAAY,IAAI;AACnC,SAAO,YAAY,GAAG,KAAK,IAAI,IAAI,EAAE;AACvC;AAEA,SAAS,YAAY,GAAmB;AACtC,SAAO,EACJ,YAAY,EACZ,QAAQ,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;AAC5C;AAMA,eAAe,mBAAmB,OAAkC;AAClE,QAAM,KAAK,iBAAiB;AAC5B,QAAM,eAAyB,CAAC;AAIhC,QAAM,CAAC,eAAe,eAAe,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpE,GAAG,IACA,iBAAiB,KAAK,EACtB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAC1B,MAAM,CAAC,QAAQ;AACd,cAAQ,KAAK,6CAA6C,IAAI,OAAO;AACrE,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,IACH,GAAG,IACA,iBAAiB,KAAK,EACtB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAC1B,MAAM,CAAC,QAAQ;AACd,cAAQ,KAAK,6CAA6C,IAAI,OAAO;AACrE,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,IACH,GAAG,eACA,gBAAgB,OAAO,IAAI,EAC3B,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAC1B,MAAM,CAAC,QAAQ;AACd,cAAQ,KAAK,6CAA6C,IAAI,OAAO;AACrE,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACL,CAAC;AAGD,QAAM,aAAgC,CAAC;AAEvC,aAAW,KAAK,eAAe;AAC7B,eAAW,KAAK;AAAA,MACd,MAAM,iBAAiB,EAAE,IAAI;AAAA,MAC7B,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa,EAAE,OAAO,EAAE,YAAY;AAAA,MACpC,YAAY;AAAA,QACV,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAEA,aAAW,KAAK,eAAe;AAC7B,eAAW,KAAK;AAAA,MACd,MAAM,YAAY,EAAE,IAAI;AAAA,MACxB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa,EAAE,OAAO,EAAE,YAAY;AAAA,MACpC,YAAY;AAAA,QACV,aAAa,EAAE;AAAA,QACf,eAAe,EAAE;AAAA,QACjB,OAAO,EAAE;AAAA,QACT,OAAO,EAAE;AAAA,QACT,eAAe,EAAE;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,aAAW,KAAK,aAAa;AAC3B,eAAW,KAAK;AAAA,MACd,MAAM,EAAE;AAAA,MACR,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,QACV,eAAe,EAAE;AAAA,QACjB,cAAc,EAAE;AAAA,QAChB,QAAQ,EAAE;AAAA,QACV,aAAa,EAAE;AAAA,QACf,mBAAmB,EAAE;AAAA,QACrB,mBAAmB,EAAE;AAAA,QACrB,mBAAmB,EAAE;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAIA,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,YAAM,WAAW,MAAM,cAAc,SAAS;AAC9C,mBAAa,KAAK,SAAS,QAAQ;AAAA,IACrC,SAAS,KAAU;AACjB,cAAQ,KAAK,6CAA6C,UAAU,IAAI,MAAM,IAAI,OAAO;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC;AAClC;AAMA,MAAM,IAAI,WAAW,OAAO,MAAM;AAChC,MAAI;AACF,UAAM,IAAI,EAAE,IAAI,MAAM,GAAG;AACzB,UAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAC/B,UAAM,QAAQ,KAAK,IAAI,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,GAAG,GAAG;AAEtE,QAAI,CAAC,GAAG;AACN,aAAO,EAAE,KAAK,EAAE,OAAO,kCAAkC,GAAG,GAAG;AAAA,IACjE;AAEA,UAAM,cAAc,KAAK,IAAI;AAC7B,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAc,WAAW;AAAA,MAC/B,WAAW,gBAAgB,WAAW;AAAA,MACtC,MAAM,EAAE,UAAU,gBAAgB,OAAO,GAAG,YAAY,KAAK;AAAA,IAC/D,CAAC;AAGD,QAAI,QAAQ,GACT,OAAO,EACP,KAAK,aAAa,EAClB;AAAA,MACC,OACID,KAAI,MAAM,cAAc,MAAM,IAAI,CAAC,GAAG,GAAGC,IAAG,cAAc,MAAM,IAAW,CAAC,IAC5E,MAAM,cAAc,MAAM,IAAI,CAAC,GAAG;AAAA,IACxC,EACC,QAAQ,KAAK,cAAc,UAAU,CAAC,EACtC,MAAM,KAAK;AAEd,QAAI,UAAU,MAAM;AACpB,QAAI,mBAAmB;AAGvB,QAAI,QAAQ,SAAS,KAAK,EAAE,UAAU,GAAG;AACvC,UAAI;AACF,gBAAQ,IAAI,8BAA8B,QAAQ,MAAM,cAAc,CAAC,8BAA8B;AACrG,cAAM,cAAc,MAAM,mBAAmB,CAAC;AAC9C,2BAAmB;AAEnB,YAAI,YAAY,SAAS,GAAG;AAI1B,gBAAM,gBAAgB,OAClBD,KAAI,MAAM,cAAc,MAAM,IAAI,CAAC,GAAG,GAAGC,IAAG,cAAc,MAAM,IAAW,CAAC,IAC5E,MAAM,cAAc,MAAM,IAAI,CAAC,GAAG;AAEtC,gBAAM,cAAc,MAAM,cAAc,EAAE,UAAU,YAAY,IAAI,KAAK,YAAY,IAAI,CAAC,OAAe,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW;AAEzI,oBAAU,MAAM,GACb,OAAO,EACP,KAAK,aAAa,EAClB,MAAM,OAAO,aAAa,SAAS,WAAW,GAAG,EACjD,QAAQ,KAAK,cAAc,UAAU,CAAC,EACtC,MAAM,KAAK;AAAA,QAChB;AAAA,MACF,SAAS,QAAa;AACpB,gBAAQ,KAAK,kDAAkD,OAAO,OAAO;AAAA,MAC/E;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,IAAI,CAAC,MAAW,EAAE,EAAE;AAC9C,QAAI,QAAe,CAAC;AACpB,QAAI,UAAU,SAAS,GAAG;AACxB,cAAQ,MAAM,GACX,OAAO;AAAA,QACN,IAAI,mBAAmB;AAAA,QACvB,QAAQ,mBAAmB;AAAA,QAC3B,QAAQ,mBAAmB;AAAA,QAC3B,MAAM,mBAAmB;AAAA,QACzB,UAAU,mBAAmB;AAAA,MAC/B,CAAC,EACA,KAAK,kBAAkB,EACvB;AAAA,QACCD;AAAA,UACE,MAAM,mBAAmB,cAAc,UAAU,YAAY,IAAI,KAAK,UAAU,IAAI,CAAC,OAAe,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,UACpI,MAAM,mBAAmB,cAAc,UAAU,YAAY,IAAI,KAAK,UAAU,IAAI,CAAC,OAAe,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,QACtI;AAAA,MACF;AAAA,IACJ;AAEA,UAAM,gBAAgB,KAAK,IAAI,IAAI;AACnC,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAiB,WAAW,KAAK,IAAI;AAAA,MAC3C,WAAW,gBAAgB,WAAW;AAAA,MACtC,MAAM,EAAE,UAAU,gBAAgB,SAAS,MAAM,WAAW,eAAe,aAAa,QAAQ,QAAQ,iBAAiB;AAAA,IAC3H,CAAC;AAGD,UAAM,QAAQ,iBAAiB,gBAAgB,EAAE,OAAO,GAAG,YAAY,MAAM,aAAa,QAAQ,QAAQ,kBAAkB,WAAW,cAAc,GAAG,IAAI,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAE5K,WAAO,EAAE,KAAK,EAAE,SAAS,OAAO,OAAO,QAAQ,QAAQ,iBAAiB,CAAC;AAAA,EAC3E,SAAS,OAAY;AACnB,YAAQ,MAAM,8BAA8B,KAAK;AACjD,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAiB,WAAW,KAAK,IAAI;AAAA,MAC3C,WAAW,gBAAgB,KAAK,IAAI,CAAC;AAAA,MACrC,MAAM,EAAE,UAAU,gBAAgB,SAAS,MAAM;AAAA,IACnD,CAAC;AACD,UAAM,QAAQ,iBAAiB,gBAAgB,EAAE,OAAO,EAAE,IAAI,MAAM,GAAG,GAAG,OAAO,OAAO,QAAQ,GAAG,KAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACxH,WAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AAAA,EAC/C;AACF,CAAC;AAMD,MAAM,KAAK,WAAW,OAAO,MAAM;AACjC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,QAAI,CAAC,KAAK,UAAU;AAClB,aAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,IACtD;AAGA,UAAM,SAAS,MAAM,GAClB,OAAO,EACP,KAAK,aAAa,EAClB,MAAMC,IAAG,cAAc,IAAI,KAAK,QAAQ,CAAC,EACzC,MAAM,CAAC;AAEV,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,UAAM,cAAc,KAAK,IAAI;AAC7B,UAAM,aAAc,OAAO,CAAC,EAAU,QAAQ,KAAK;AACnD,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAc,WAAW;AAAA,MAC/B,WAAW,gBAAgB,WAAW;AAAA,MACtC,MAAM,EAAE,UAAU,gBAAgB,UAAU,KAAK,UAAU,YAAY,SAAS,KAAK,SAAS,OAAO,KAAK,SAAS,EAAE;AAAA,IACvH,CAAC;AAGD,UAAM,EAAE,aAAa,IAAI,MAAM,OAC7B,mCACF;AAEA,UAAM,SAAS,MAAM,aAAa,KAAK,UAAU,KAAK,SAAS,KAAK,SAAS,CAAC;AAE9E,UAAM,gBAAgB,KAAK,IAAI,IAAI;AACnC,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAiB,WAAW,KAAK,IAAI;AAAA,MAC3C,WAAW,gBAAgB,WAAW;AAAA,MACtC,MAAM,EAAE,UAAU,gBAAgB,SAAS,MAAM,WAAW,eAAe,YAAY,aAAa,QAAQ,oBAAoB,kBAAkB,QAAQ,wBAAwB;AAAA,IACpL,CAAC;AAGD,UAAM,QAAQ,iBAAiB,gBAAgB,EAAE,UAAU,KAAK,UAAU,YAAY,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,aAAa,QAAQ,oBAAoB,kBAAkB,QAAQ,yBAAyB,WAAW,cAAc,GAAG,IAAI,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAE5Q,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC;AAAA,EACzC,SAAS,OAAY;AAEnB,QAAI,OAAO,SAAS,sBAAsB,OAAO,SAAS,SAAS,oBAAoB,GAAG;AACxF,aAAO,EAAE,KAAK,EAAE,OAAO,uCAAuC,GAAG,GAAG;AAAA,IACtE;AACA,YAAQ,MAAM,8BAA8B,KAAK;AACjD,mBAAe,UAAU;AAAA,MACvB,MAAM;AAAA,MAAiB,WAAW,KAAK,IAAI;AAAA,MAC3C,WAAW,gBAAgB,KAAK,IAAI,CAAC;AAAA,MACrC,MAAM,EAAE,UAAU,gBAAgB,SAAS,OAAO,OAAO,OAAO,QAAQ;AAAA,IAC1E,CAAC;AACD,UAAM,QAAQ,iBAAiB,gBAAgB,EAAE,OAAO,OAAO,QAAQ,GAAG,KAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAC/F,WAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,EACnD;AACF,CAAC;AAMD,IAAM,sBAAsB,CAAC,cAAc,UAAU,oBAAoB,YAAY,MAAM;AAE3F,MAAM,IAAI,mBAAmB,OAAO,MAAM;AACxC,MAAI;AACF,UAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AAEvC,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,KAAK,EAAE,OAAO,yCAAyC,GAAG,GAAG;AAAA,IACxE;AAGA,UAAM,aAAa,MAAM,GACtB,OAAO,EAAE,IAAI,cAAc,IAAI,MAAM,cAAc,KAAK,CAAC,EACzD,KAAK,aAAa,EAClB,MAAMA,IAAG,cAAc,IAAI,QAAQ,CAAC,EACpC,MAAM,CAAC;AAEV,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAGA,UAAM,WAAW,MAAM,GACpB,OAAO;AAAA,MACN,IAAI,mBAAmB;AAAA,MACvB,gBAAgB,mBAAmB;AAAA,MACnC,gBAAgB,mBAAmB;AAAA,MACnC,MAAM,mBAAmB;AAAA,MACzB,UAAU,mBAAmB;AAAA,MAC7B,YAAY,mBAAmB;AAAA,IACjC,CAAC,EACA,KAAK,kBAAkB,EACvB;AAAA,MACCD;AAAA,QACEC,IAAG,mBAAmB,gBAAgB,QAAQ;AAAA,QAC9C,MAAM,mBAAmB,IAAI,UAAU,YAAY,IAAI,KAAK,oBAAoB,IAAI,OAAK,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,MAC1H;AAAA,IACF;AAEF,UAAM,WAAW,MAAM,GACpB,OAAO;AAAA,MACN,IAAI,mBAAmB;AAAA,MACvB,gBAAgB,mBAAmB;AAAA,MACnC,gBAAgB,mBAAmB;AAAA,MACnC,MAAM,mBAAmB;AAAA,MACzB,UAAU,mBAAmB;AAAA,MAC7B,YAAY,mBAAmB;AAAA,IACjC,CAAC,EACA,KAAK,kBAAkB,EACvB;AAAA,MACCD;AAAA,QACEC,IAAG,mBAAmB,gBAAgB,QAAQ;AAAA,QAC9C,MAAM,mBAAmB,IAAI,UAAU,YAAY,IAAI,KAAK,oBAAoB,IAAI,OAAK,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW;AAAA,MAC1H;AAAA,IACF;AAEF,UAAM,UAAU,CAAC,GAAG,UAAU,GAAG,QAAQ;AAGzC,UAAM,aAAa,oBAAI,IAAY;AACnC,eAAW,IAAI,QAAQ;AACvB,eAAW,OAAO,SAAS;AACzB,iBAAW,IAAI,IAAI,cAAc;AACjC,iBAAW,IAAI,IAAI,cAAc;AAAA,IACnC;AAGA,UAAM,kBAAkB,MAAM,GAC3B,OAAO;AAAA,MACN,IAAI,cAAc;AAAA,MAClB,MAAM,cAAc;AAAA,MACpB,MAAM,cAAc;AAAA,IACtB,CAAC,EACA,KAAK,aAAa,EAClB,MAAM,MAAM,cAAc,EAAE,UAAU,YAAY,IAAI,KAAK,CAAC,GAAG,UAAU,EAAE,IAAI,QAAM,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,WAAW,GAAG;AAG3H,UAAM,YAAY,IAAI,IAAI,gBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAG/D,UAAM,aAAa,oBAAI,IAAoB;AAC3C,eAAW,OAAO,SAAS;AACzB,YAAM,QAAS,IAAI,cAA0C,CAAC;AAC9D,YAAM,SAAU,MAAM,UAAqB,IAAI,YAAY;AAC3D,iBAAW,IAAI,IAAI,iBAAiB,WAAW,IAAI,IAAI,cAAc,KAAK,KAAK,MAAM;AACrF,iBAAW,IAAI,IAAI,iBAAiB,WAAW,IAAI,IAAI,cAAc,KAAK,KAAK,MAAM;AAAA,IACvF;AAEA,UAAM,QAAQ,gBAAgB,IAAI,CAAC,OAAO;AAAA,MACxC,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,MACR,OAAO,WAAW,IAAI,EAAE,EAAE,KAAK;AAAA,IACjC,EAAE;AAGF,UAAM,QAAQ,QACX,OAAO,CAAC,QAAQ,UAAU,IAAI,IAAI,cAAc,KAAK,UAAU,IAAI,IAAI,cAAc,CAAC,EACtF,IAAI,CAAC,QAAQ;AACZ,YAAM,QAAS,IAAI,cAA0C,CAAC;AAC9D,aAAO;AAAA,QACL,QAAQ,IAAI;AAAA,QACZ,QAAQ,IAAI;AAAA,QACZ,OAAQ,MAAM,UAAqB,IAAI,YAAY;AAAA,QACnD,aAAa,GAAG,IAAI,KAAK,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM,SAAS,KAAK,MAAM,MAAM,MAAM,EAAE;AAAA,MACxF;AAAA,IACF,CAAC;AAEH,WAAO,EAAE,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAChC,SAAS,OAAO;AACd,YAAQ,MAAM,sCAAsC,KAAK;AACzD,WAAO,EAAE,KAAK,EAAE,OAAO,sCAAsC,GAAG,GAAG;AAAA,EACrE;AACF,CAAC;AAMD,MAAM,IAAI,eAAe,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,YAAY,WAAW,EAAE,IAAI,MAAM,WAAW,KAAK,MAAM;AAE/D,UAAM,EAAE,eAAe,IAAI,MAAM,OAC/B,iCACF;AAEA,UAAM,aAAa,MAAM,eAAe,SAAS;AAEjD,WAAO,EAAE,KAAK,EAAE,YAAY,OAAO,WAAW,OAAO,CAAC;AAAA,EACxD,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,KAAK;AACrD,WAAO,EAAE,KAAK,EAAE,OAAO,4BAA4B,GAAG,GAAG;AAAA,EAC3D;AACF,CAAC;AAMD,MAAM,IAAI,UAAU,OAAO,MAAM;AAC/B,MAAI;AAEF,UAAM,sBAAsB,MAAM,GAC/B,OAAO,EAAE,OAAO,mBAA2B,CAAC,EAC5C,KAAK,aAAa;AACrB,UAAM,gBAAgB,oBAAoB,CAAC,GAAG,SAAS;AAGvD,UAAM,kBAAkB,MAAM,GAC3B,OAAO,EAAE,OAAO,mBAA2B,CAAC,EAC5C,KAAK,kBAAkB;AAC1B,UAAM,qBAAqB,gBAAgB,CAAC,GAAG,SAAS;AAGxD,UAAM,iBAAiB,MAAM,GAC1B,OAAO;AAAA,MACN,MAAM,cAAc;AAAA,MACpB,OAAO;AAAA,IACT,CAAC,EACA,KAAK,aAAa,EAClB,QAAQ,cAAc,IAAI,EAC1B,QAAQ,KAAK,aAAa,CAAC;AAG9B,UAAM,cAAc,MAAM,GACvB,OAAO;AAAA,MACN,IAAI,cAAc;AAAA,MAClB,MAAM,cAAc;AAAA,MACpB,MAAM,cAAc;AAAA,MACpB,cAAc,cAAc;AAAA,MAC5B,YAAY,cAAc;AAAA,IAC5B,CAAC,EACA,KAAK,aAAa,EAClB,QAAQ,KAAK,cAAc,YAAY,CAAC,EACxC,MAAM,EAAE;AAEX,WAAO,EAAE,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,EAC5D;AACF,CAAC;;;AC3qBD,SAAS,QAAAC,aAAY;AAErB;AAKA;AAEA,IAAM,QAAQ,IAAIC,MAAK;AAQvB,eAAe,8BAA8B,cAA2C;AACtF,MAAI,IAAI,qBAAqB,IAAI,uBAAuB;AACtD,UAAM,WAAW,GAAG,YAAY,IAAI,IAAI,iBAAiB;AAGzD,UAAM,cAAc,IAAI,WAAW;AAAA,MACjC,MAAM,IAAI,yBAAyB;AAAA,MACnC,MAAM,IAAI,yBAAyB;AAAA,MACnC,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU,IAAI;AAAA,MACd,KAAK,EAAE,oBAAoB,MAAM;AAAA,IACnC,CAAC;AAED,QAAI;AACF,YAAM,YAAY,QAAQ;AAC1B,aAAO;AAAA,IACT,SAAS,UAAe;AAEtB,YAAM,aAAa,IAAI;AACvB,YAAM,aAAa,IAAI,mBAAmB;AAE1C,UAAI,CAAC,WAAY,OAAM;AAEvB,cAAQ;AAAA,QACN,uCAAuC,SAAS,QAAQ,SAAS,OAAO,sBAAsB,UAAU,IAAI,UAAU;AAAA,MACxH;AAEA,YAAM,eAAe,IAAI,WAAW;AAAA,QAClC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU,IAAI;AAAA,QACd,KAAK,EAAE,oBAAoB,MAAM;AAAA,MACnC,CAAC;AAED,YAAM,aAAa,QAAQ;AAC3B,aAAO;AAAA,IACT;AAAA,EACF,WAAW,IAAI,cAAc,IAAI,gBAAgB;AAC/C,UAAM,SAAS,IAAI,WAAW;AAAA,MAC5B,MAAM,IAAI,mBAAmB;AAAA,MAC7B,MAAM,IAAI,mBAAmB;AAAA,MAC7B,QAAQ,IAAI,sBAAsB;AAAA,MAClC,MAAM,IAAI;AAAA,MACV,UAAU,IAAI;AAAA,IAChB,CAAC;AACD,UAAM,OAAO,QAAQ;AACrB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,sBAAsB;AACxC;AAEA,SAAS,iBAAiB,aAAiC;AACzD,MAAI,IAAI,mBAAmB;AACzB,WAAO,IAAI;AAAA,MACT;AAAA,QACE,MAAM,IAAI,yBAAyB;AAAA,QACnC,MAAM,IAAI,yBAAyB;AAAA,QACnC,QAAQ;AAAA,QACR,MAAM,EAAE,MAAM,IAAI,MAAM,GAAG;AAAA,QAC3B,KAAK,EAAE,oBAAoB,MAAM;AAAA,MACnC;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,IAAI,cAAc,IAAI,gBAAgB;AAC/C,WAAO,IAAI;AAAA,MACT;AAAA,QACE,MAAM,IAAI,mBAAmB;AAAA,QAC7B,MAAM,IAAI,mBAAmB;AAAA,QAC7B,QAAQ,IAAI,sBAAsB;AAAA,QAClC,MAAM,EAAE,MAAM,IAAI,YAAY,MAAM,IAAI,eAAe;AAAA,MACzD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,MAAM,sBAAsB;AACxC;AAEA,SAAS,eAAeC,QAAqB,aAA+C;AAC1F,QAAM,aAAsC;AAAA,IAC1C,IAAIA,OAAM;AAAA,IACV,KAAKA,OAAM;AAAA,IACX,WAAWA,OAAM;AAAA,IACjB,SAASA,OAAM;AAAA,IACf,MAAMA,OAAM;AAAA,IACZ,IAAIA,OAAM;AAAA,IACV,IAAIA,OAAM;AAAA,IACV,KAAKA,OAAM;AAAA,IACX,MAAMA,OAAM,KAAK,YAAY;AAAA,IAC7B,MAAM,cAAcA,OAAM,OAAOA,OAAM;AAAA,IACvC,MAAM,cAAcA,OAAM,OAAO;AAAA,IACjC,SAASA,OAAM;AAAA,IACf,aAAaA,OAAM,YAAY,IAAI,CAAC,OAAO;AAAA,MACzC,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,MACf,MAAM,EAAE;AAAA,MACR,WAAW,EAAE;AAAA,MACb,YAAY,CAAC,CAAC,EAAE;AAAA,IAClB,EAAE;AAAA,IACF,OAAOA,OAAM;AAAA,IACb,QAAQA,OAAM;AAAA,IACd,UAAUA,OAAM;AAAA,IAChB,WAAWA,OAAM;AAAA,IACjB,YAAYA,OAAM;AAAA,IAClB,SAAS,OAAO,YAAYA,OAAM,OAAO;AAAA,EAC3C;AAEA,SAAO;AACT;AAMA,MAAM,IAAI,KAAK,OAAO,GAAG,SAAS;AAChC,MAAI,CAAC,IAAI,qBAAqB,CAAC,IAAI,YAAY;AAC7C,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,oEAAoE;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AACA,QAAM,KAAK;AACb,CAAC;AAMD,MAAM,IAAI,YAAY,OAAO,MAAM;AACjC,QAAM,eAAe,EAAE,IAAI,MAAM,eAAe;AAChD,MAAI,CAAC,cAAc;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,8CAA8C,GAAG,GAAG;AAAA,EAC7E;AAEA,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,YAAY;AACvD,UAAM,UAAU,MAAM,KAAK,YAAY;AACvC,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA+B,KAAK;AAClD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,yBAAyB;AAAA,MAC3E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,IAAI,UAAU,OAAO,MAAM;AAC/B,QAAM,eAAe,EAAE,IAAI,MAAM,eAAe;AAChD,MAAI,CAAC,cAAc;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,8CAA8C,GAAG,GAAG;AAAA,EAC7E;AAEA,QAAM,SAAS,EAAE,IAAI,MAAM,QAAQ,KAAK;AACxC,QAAM,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AACtC,QAAM,SAAS,EAAE,IAAI,MAAM,QAAQ,KAAK;AACxC,QAAM,aAAa,EAAE,IAAI,MAAM,aAAa,MAAM;AAElD,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,YAAY;AAEvD,QAAI;AACJ,QAAI,YAAY;AACd,eAAS,MAAM,KAAK,aAAa;AAAA,QAC/B;AAAA,QACA,MAAM;AAAA,QACN,OAAO,SAAS,KAAK;AAAA,MACvB,CAAC;AAAA,IACH,OAAO;AACL,eAAS,MAAM,KAAK,YAAY,QAAQ;AAAA,QACtC,OAAO,SAAS,KAAK;AAAA,QACrB,QAAQ,SAAS,MAAM;AAAA,MACzB,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,KAAK;AAAA,MACZ,QAAQ,OAAO,IAAI,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,yBAAyB;AAAA,MAC3E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,IAAI,iBAAiB,OAAO,MAAM;AACtC,QAAM,eAAe,EAAE,IAAI,MAAM,eAAe;AAChD,MAAI,CAAC,cAAc;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,8CAA8C,GAAG,GAAG;AAAA,EAC7E;AAEA,QAAM,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK,CAAC;AACvC,QAAM,SAAS,EAAE,IAAI,MAAM,QAAQ,KAAK;AAExC,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,YAAY;AAEvD,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,MAAM;AAClD,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,GAAG;AAAA,IACjD;AAEA,UAAM,KAAK,WAAW,KAAK,MAAM;AAEjC,WAAO,EAAE,KAAK,eAAe,UAAU,IAAI,CAAC;AAAA,EAC9C,SAAS,OAAO;AACd,YAAQ,MAAM,oCAAoC,KAAK;AACvD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,wBAAwB;AAAA,MAC1E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,IAAI,2BAA2B,OAAO,MAAM;AAChD,QAAM,eAAe,EAAE,IAAI,MAAM,eAAe;AAChD,MAAI,CAAC,cAAc;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,8CAA8C,GAAG,GAAG;AAAA,EAC7E;AAEA,QAAM,MAAM,SAAS,EAAE,IAAI,MAAM,KAAK,CAAC;AACvC,QAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,CAAC;AAC3C,QAAM,SAAS,EAAE,IAAI,MAAM,QAAQ,KAAK;AAExC,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,YAAY;AAEvD,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,MAAM;AAClD,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,GAAG;AAAA,IACjD;AAEA,UAAM,aAAa,SAAS,YAAY,KAAK;AAC7C,QAAI,CAAC,YAAY;AACf,aAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,IACtD;AAEA,QAAI,CAAC,WAAW,SAAS;AACvB,aAAO,EAAE,KAAK,EAAE,OAAO,mCAAmC,GAAG,GAAG;AAAA,IAClE;AAEA,WAAO,IAAI,SAAS,IAAI,WAAW,WAAW,OAAO,GAAU;AAAA,MAC7D,SAAS;AAAA,QACP,gBAAgB,WAAW,eAAe;AAAA,QAC1C,uBAAuB,yBAAyB,WAAW,QAAQ;AAAA,QACnE,kBAAkB,OAAO,WAAW,QAAQ,WAAW,QAAQ,MAAM;AAAA,MACvE;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,8CAA8C,KAAK;AACjE,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,6BAA6B;AAAA,MAC/E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,KAAK,SAAS,OAAO,MAAM;AAC/B,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAStB;AAEH,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM,CAAC,KAAK,SAAS;AAC3C,aAAO,EAAE,KAAK,EAAE,OAAO,kDAAkD,GAAG,GAAG;AAAA,IACjF;AAEA,UAAM,OAAO,iBAAiB,KAAK,IAAI;AAEvC,UAAM,uBAAuB,KAAK,aAAa,IAAI,CAAC,OAAO;AAAA,MACzD,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,MACf,MAAM,OAAO,KAAK,EAAE,SAAS,QAAQ,EAAE;AAAA,MACvC,SAAS,OAAO,KAAK,EAAE,SAAS,QAAQ;AAAA,IAC1C,EAAE;AAEF,UAAM,SAAS,MAAM,KAAK,KAAK;AAAA,MAC7B,IAAI,KAAK;AAAA,MACT,IAAI,KAAK;AAAA,MACT,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AAED,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,uBAAuB;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAMD,MAAM,KAAK,UAAU,OAAO,MAAM;AAChC,QAAM,OAAO,MAAM,EAAE,IAAI,KAQtB;AAEH,MAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,aAAa,CAAC,KAAK,MAAM;AACxD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,+DAA+D;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,KAAK,aAAa;AAE7D,UAAM,gBAAgB,MAAM,KAAK,WAAW,KAAK,WAAW,MAAM;AAClE,QAAI,CAAC,eAAe;AAClB,aAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG;AAAA,IAC1D;AAEA,UAAM,OAAO,iBAAiB,KAAK,aAAa;AAEhD,UAAM,uBAAuB,KAAK,aAAa,IAAI,CAAC,OAAO;AAAA,MACzD,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,MACf,MAAM,OAAO,KAAK,EAAE,SAAS,QAAQ,EAAE;AAAA,MACvC,SAAS,OAAO,KAAK,EAAE,SAAS,QAAQ;AAAA,IAC1C,EAAE;AAEF,QAAI;AACJ,QAAI,KAAK,WAAW;AAClB,eAAS,MAAM,KAAK;AAAA,QAClB;AAAA,QACA,EAAE,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,aAAa,qBAAqB;AAAA,QACtE,KAAK;AAAA,MACP;AAAA,IACF,OAAO;AACL,eAAS,MAAM,KAAK,MAAM,eAAe;AAAA,QACvC,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,uBAAuB;AAAA,MACzE;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,KAAK,WAAW,OAAO,MAAM;AACjC,QAAM,OAAO,MAAM,EAAE,IAAI,KAWtB;AAEH,MAAI,CAAC,KAAK,eAAe;AACvB,WAAO,EAAE,KAAK,EAAE,OAAO,oCAAoC,GAAG,GAAG;AAAA,EACnE;AAEA,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,KAAK,aAAa;AAE7D,UAAM,gBAAgB;AAAA,MACpB,QAAQ,KAAK,UAAU;AAAA,MACvB,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,OAAO,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAK,IAAI;AAAA,MAC3C,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,IAAI;AAAA,MAC9C,MAAM,KAAK,cAAc,QAAQ;AAAA,MACjC,OAAO,KAAK;AAAA,IACd;AAEA,UAAM,SAAS,MAAM,KAAK,aAAa,aAAa;AAEpD,WAAO,EAAE,KAAK;AAAA,MACZ,QAAQ,OAAO,IAAI,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAAA,IACpD,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,8BAA8B,KAAK;AACjD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AAAA,MAClE;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;AAMD,MAAM,KAAK,SAAS,OAAO,MAAM;AAC/B,QAAM,OAAO,MAAM,EAAE,IAAI,KAKtB;AAEH,MAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ;AACpD,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,2DAA2D;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI,OAA0B;AAC9B,MAAI;AACF,WAAO,MAAM,8BAA8B,KAAK,aAAa;AAE7D,YAAQ,KAAK,QAAQ;AAAA,MACnB,KAAK;AACH,cAAM,KAAK,WAAW,KAAK,KAAK,MAAM;AACtC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,aAAa,KAAK,KAAK,MAAM;AACxC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,UAAU,KAAK,KAAK,MAAM;AACrC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,YAAY,KAAK,KAAK,MAAM;AACvC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,YAAY,KAAK,KAAK,MAAM;AACvC;AAAA,MACF;AACE,eAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,KAAK,MAAM,GAAG,GAAG,GAAG;AAAA,IAClE;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,WAAO,EAAE;AAAA,MACP,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,2BAA2B;AAAA,MAC7E;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI,MAAM;AACR,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACxC;AAAA,EACF;AACF,CAAC;;;ACxiBD,SAAS,QAAAC,aAAY;AAwBrB,IAAM,iBAAiB,oBAAI,IAA2B;AAGtD,SAAS,iBAAyB;AAChC,QAAM,QAAQ;AACd,QAAM,WAAW,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE;AAChC,SAAO,SAAS,SACb,IAAI,CAAC,QAAQ,MAAM,KAAK,EAAE,QAAQ,IAAI,GAAG,MAAM,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EACxG,KAAK,GAAG;AACb;AAGA,eAAe,QAAQ,GAAQ,MAAW;AACxC,QAAM,aAAa,EAAE,IAAI,OAAO,eAAe;AAC/C,MAAI,CAAC,YAAY,WAAW,aAAa,GAAG;AAC1C,WAAO,EAAE,KAAK,EAAE,OAAO,iEAAiE,GAAG,GAAG;AAAA,EAChG;AAEA,QAAM,SAAS,WAAW,MAAM,CAAC;AACjC,QAAMC,OAAM,MAAM,KAAK,eAAe,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAE/E,MAAI,CAACA,MAAK;AACR,WAAO,EAAE,KAAK,EAAE,OAAO,sDAAsD,GAAG,GAAG;AAAA,EACrF;AAEA,EAAAA,KAAI,WAAW,oBAAI,KAAK;AACxB,IAAE,IAAI,UAAUA,IAAG;AACnB,QAAM,KAAK;AACb;AAEA,IAAM,YAAY,IAAIC,MAAa;AAGnC,UAAU,KAAK,aAAa,OAAO,MAAM;AACvC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM;AAC5B,aAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,IAC5D;AAGA,UAAM,WAAW,MAAM,KAAK,eAAe,OAAO,CAAC,EAAE;AAAA,MACnD,CAAC,MAAM,EAAE,SAAS,KAAK,QAAQ,EAAE,SAAS,KAAK;AAAA,IACjD;AACA,QAAI,UAAU;AACZ,aAAO,EAAE,KAAK;AAAA,QACZ,IAAI,SAAS;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,KAAK,OAAO,WAAW;AAC7B,UAAM,SAAS,eAAe;AAC9B,UAAMD,OAAqB;AAAA,MACzB;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,cAAc,oBAAI,KAAK;AAAA,MACvB,UAAU,oBAAI,KAAK;AAAA,IACrB;AAEA,mBAAe,IAAI,IAAIA,IAAG;AAE1B,WAAO,EAAE,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,WAAW;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,EACrD;AACF,CAAC;AAGD,UAAU,IAAI,MAAM,OAAO;AAG3B,UAAU,KAAK,SAAS,OAAO,MAAM;AACnC,MAAI;AACF,UAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,UAAM,OAAO,MAAM,EAAE,IAAI,KAKtB;AAEH,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,IACrD;AAEA,UAAME,YAAsB,CAAC;AAC7B,QAAI,KAAK,SAAS;AAChB,MAAAA,UAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,iBAAiBF,KAAI,IAAI,KAAKA,KAAI,IAAI,OAAO,KAAK,OAAO;AAAA,MACpE,CAAC;AACD,MAAAE,UAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,IAAAA,UAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,KAAK,QAAQ,CAAC;AAErD,UAAM,YAAsB,CAAC;AAC7B,UAAM,WAAW,KAAK,aAAa,QAC/B,MAAM,cAAcA,WAAU,OAAOF,KAAI,EAAE,IAAI,CAAC,SAAS,UAAU,KAAK,IAAI,GAAG,EAAE,SAASA,KAAI,KAAK,CAAC,IACpG,OAAO,MAAM,OAAO,qBAAqB,GAAG,KAAKE,WAAU,KAAK,YAAY;AAGhF,UAAM,YAAY;AAAA,MAChB,SAAS,IAAIF,KAAI,IAAI,iBAAiB,KAAK,QAAQ,MAAM,GAAG,GAAG,CAAC;AAAA,MAChE,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,QAAQ,OAAOA,KAAI,EAAE;AAAA,MACrB,QAAQ,OAAOA,KAAI,IAAI;AAAA,MACvB,YAAY,OAAOA,KAAI,IAAI;AAAA,IAC7B,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAEjB,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,MACzB;AAAA,MACA,KAAKA,KAAI;AAAA,IACX,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,mBAAmB,KAAK;AACtC,WAAO,EAAE,KAAK,EAAE,OAAO,cAAc,GAAG,GAAG;AAAA,EAC7C;AACF,CAAC;AAGD,UAAU,KAAK,WAAW,OAAO,MAAM;AACrC,MAAI;AACF,UAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,UAAM,OAAO,MAAM,EAAE,IAAI,KAKtB;AAEH,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,SAAS;AAClC,aAAO,EAAE,KAAK,EAAE,OAAO,mCAAmC,GAAG,GAAG;AAAA,IAClE;AAEA,UAAM,OAAiB,CAAC;AACxB,UAAM,SAAS,IAAIA,KAAI,IAAI;AAC3B,UAAM,cAAc,SAAS,KAAK;AAElC,UAAM,WAAW,KAAK,YAAY,QAC9B,CAAC,YAAY,WAAW,OAAO,IAC/B,CAAC,KAAK,OAAO;AAEjB,eAAW,MAAM,UAAU;AACzB,UAAI;AACF,gBAAQ,IAAI;AAAA,UACV,KAAK,YAAY;AACf,kBAAM,EAAE,IAAI,IAAI,MAAM,OAAO,QAAQ;AACrC,kBAAM,MAAM,IAAI,IAAI,IAAI,kBAAkB;AAC1C,kBAAM,IAAI,IAAI,YAAY,IAAI,kBAAkB,WAAW;AAC3D,iBAAK,KAAK,UAAU;AACpB;AAAA,UACF;AAAA,UACA,KAAK,WAAW;AACd,kBAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,uBAAe;AACzD,kBAAM,UAAU,iBAAiB;AAAA,cAC/B,OAAO,IAAI,qBAAqB;AAAA,cAChC,UAAU,IAAI,qBAAqB;AAAA,YACrC,CAAC;AACD,gBAAI,KAAK,WAAW;AAClB,oBAAM,QAAQ,YAAY,KAAK,WAAW,WAAW;AAAA,YACvD;AACA,iBAAK,KAAK,SAAS;AACnB;AAAA,UACF;AAAA,UACA,KAAK,SAAS;AACZ,kBAAM,EAAE,eAAe,IAAI,MAAM,OAAO,qBAAa;AACrD,kBAAM,QAAQ,eAAe;AAAA,cAC3B,OAAO,IAAI,mBAAmB;AAAA,cAC9B,eAAe,IAAI,wBAAwB;AAAA,YAC7C,CAAC;AACD,gBAAI,KAAK,WAAW;AAClB,oBAAM,MAAM,YAAY,KAAK,WAAW,WAAW;AAAA,YACrD;AACA,iBAAK,KAAK,OAAO;AACjB;AAAA,UACF;AAAA,UACA,KAAK,SAAS;AACZ,kBAAM,EAAE,YAAAG,YAAW,IAAI,MAAM,OAAO,qBAA6B;AACjE,kBAAM,OAAO,IAAIA,YAAW;AAAA,cAC1B,MAAM,IAAI,mBAAmB;AAAA,cAC7B,MAAM,IAAI,mBAAmB;AAAA,cAC7B,QAAQ,IAAI,qBAAqB;AAAA,cACjC,MAAM,EAAE,MAAM,IAAI,cAAc,IAAI,MAAM,IAAI,kBAAkB,GAAG;AAAA,YACrE,CAAC;AACD,kBAAM,KAAK,KAAK;AAAA,cACd,IAAI,KAAK,aAAa;AAAA,cACtB,SAAS,GAAGH,KAAI,IAAI;AAAA,cACpB,MAAM,KAAK;AAAA,YACb,CAAC;AACD,iBAAK,KAAK,OAAO;AACjB;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AAAA,MAEd;AAAA,IACF;AAEA,WAAO,EAAE,KAAK,EAAE,MAAM,SAAS,0BAA0B,KAAK,KAAK,IAAI,KAAK,+BAA+B,GAAG,CAAC;AAAA,EACjH,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,EACrD;AACF,CAAC;AAGD,UAAU,KAAK,WAAW,OAAO,MAAM;AACrC,MAAI;AACF,UAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,UAAM,OAAO,MAAM,EAAE,IAAI,KAKtB;AAEH,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,IACrD;AAEA,UAAM,SAAS,MAAM,YAAY;AAAA,MAC/B,SAAS,KAAK;AAAA,MACd,MAAM,KAAK,QAAQ;AAAA,MACnB,YAAY,KAAK,cAAc;AAAA,MAC/B,QAAQ,OAAOA,KAAI,EAAE;AAAA,MACrB,QAAQ,OAAOA,KAAI,IAAI;AAAA,MACvB,YAAY,OAAOA,KAAI,IAAI;AAAA,IAC7B,CAAC;AAED,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,EACrD;AACF,CAAC;AAGD,UAAU,KAAK,kBAAkB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,QAAI,CAAC,KAAK,OAAO;AACf,aAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,IACnD;AAGA,UAAM,SAAS,KAAK,WAAW,SAAY,OAAOA,KAAI,EAAE;AACxD,UAAM,UAAU,MAAM,eAAe,KAAK,OAAO,QAAQ,KAAK,SAAS,CAAC;AAExE,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAGD,UAAU,IAAI,UAAU,CAAC,MAAM;AAC7B,QAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,QAAM,UAAU,gBAAgB,OAAgBA,KAAI,IAAI;AACxD,QAAM,UAAU,cAAcA,KAAI,IAAI;AACtC,QAAM,cAAc,IAAI,IAAI,QAAQ,aAAa;AAEjD,QAAM,WAAW,QAAQ,IAAI,CAAC,OAAY;AAAA,IACxC,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,UAAU,YAAY,IAAI,EAAE,IAAI;AAAA,EAClC,EAAE;AACF,SAAO,EAAE,KAAK,EAAE,OAAO,UAAU,OAAO,SAAS,QAAQ,SAASA,KAAI,KAAK,CAAC;AAC9E,CAAC;AAGD,UAAU,KAAK,kBAAkB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAGtB;AAEH,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,OAAO;AAC7B,aAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,IAC7D;AAEA,UAAM,SAAS,MAAM,YAAY,KAAK,MAAM,KAAK,KAAK;AACtD,WAAO,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC;AAAA,EAC3C,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,UAAU,KAAK,gBAAgB,OAAO,MAAM;AAC1C,MAAI;AACF,UAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM;AAC5B,aAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,IAC5D;AAGA,UAAM,cAAc,QAAQ,KAAK,IAAI,cAAcA,KAAI,IAAI,yBAAyB,KAAK,IAAI,GAAG,KAAK,UAAU;AAAA;AAAA,WAAgB,KAAK,OAAO,KAAK,EAAE;AAElJ,UAAME,YAAsB,CAAC,EAAE,MAAM,QAAQ,SAAS,YAAY,CAAC;AACnE,UAAM,YAAsB,CAAC;AAC7B,UAAM,WAAW,MAAM,cAAcA,WAAU,OAAOF,KAAI,EAAE,UAAU,KAAK,IAAI,IAAI,CAAC,SAAS,UAAU,KAAK,IAAI,GAAG,EAAE,SAASA,KAAI,KAAK,CAAC;AAExI,WAAO,EAAE,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AAAA,EACpD;AACF,CAAC;AAGD,UAAU,IAAI,WAAW,CAAC,MAAM;AAC9B,QAAMA,OAAM,EAAE,IAAI,QAAQ;AAC1B,QAAM,UAAU,MAAM,KAAK,eAAe,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO;AAAA,IAC9D,IAAI,EAAE;AAAA,IACN,MAAM,EAAE;AAAA,IACR,MAAM,EAAE;AAAA,IACR,cAAc,EAAE;AAAA,IAChB,UAAU,EAAE;AAAA,EACd,EAAE;AAEF,SAAO,EAAE,KAAK;AAAA,IACZ,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ,QAAQ,OAAO;AAAA,IACzB;AAAA,IACA,YAAY;AAAA,MACV,IAAIA,KAAI;AAAA,MACR,MAAMA,KAAI;AAAA,MACV,MAAMA,KAAI;AAAA,IACZ;AAAA,IACA,gBAAgB;AAAA,IAChB,OAAQ,MAAgB;AAAA,EAC1B,CAAC;AACH,CAAC;;;ACxZD,SAAS,QAAAI,aAAY;;;ACArB,OAAO,WAAW;AAIlB,IAAM,QAAQ,IAAI,MAAM,IAAI,WAAW;AAAA,EACrC,sBAAsB;AACxB,CAAQ;AAeR,IAAM,iBAAkD;AAAA,EACtD,YAAY,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EAC/C,kBAAkB,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EACrD,WAAW,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EAC9C,cAAc,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EACjD,gBAAgB,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EACnD,mBAAmB,EAAE,UAAU,KAAO,aAAa,GAAG;AAAA,EACtD,eAAe,EAAE,UAAU,MAAS,aAAa,EAAE;AAAA;AAAA,EACnD,SAAS,EAAE,UAAU,KAAO,aAAa,GAAG;AAC9C;AAEA,SAAS,OAAO,YAAoB,UAA0B;AAC5D,SAAO,aAAa,UAAU,IAAI,QAAQ;AAC5C;AAEA,eAAsB,eACpB,YACA,UACA,cAC0B;AAC1B,QAAM,SAAS,gBAAgB,eAAe,QAAQ,KAAK,eAAe;AAC1E,QAAM,EAAE,UAAU,YAAY,IAAI;AAElC,QAAM,MAAM,OAAO,YAAY,QAAQ;AACvC,QAAM,MAAM,KAAK,IAAI;AAErB,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM;AAG1B,UAAM,iBAAiB,KAAK,GAAG,MAAM,QAAQ;AAG7C,UAAM,MAAM,GAAG;AAGf,UAAM,KAAK,KAAK,IAAI,SAAS,GAAG,GAAG,GAAG,IAAI,KAAK,OAAO,CAAC,EAAE;AAGzD,UAAM,QAAQ,KAAK,QAAQ;AAE3B,UAAM,UAAU,MAAM,MAAM,KAAK;AAEjC,QAAI,CAAC,SAAS;AAEZ,cAAQ,KAAK,0DAA0D;AACvE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX,SAAS,IAAI,KAAK,MAAM,QAAQ;AAAA,MAClC;AAAA,IACF;AAEA,UAAM,eAAgB,QAAQ,CAAC,IAAI,CAAC,KAAgB;AACpD,UAAM,UAAU,IAAI,KAAK,MAAM,QAAQ;AAEvC,QAAI,gBAAgB,aAAa;AAE/B,YAAM,MAAM,KAAK,KAAK,GAAG,GAAG,IAAI,KAAK,OAAO,CAAC,EAAE;AAE/C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX;AAAA,QACA,cAAc,YAAY,MAAO,MAAM,eAAe,KAAK,KAAK,QAAQ;AAAA,MAC1E;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW,cAAc,eAAe;AAAA,MACxC;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,MAAM,4CAA4C,KAAK;AAC/D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS,IAAI,KAAK,MAAM,QAAQ;AAAA,IAClC;AAAA,EACF;AACF;AAEA,eAAe,eACb,KACA,KACA,UACiB;AACjB,QAAM,SAAS,MAAM,MAAM,OAAO,KAAK,GAAG,GAAG,YAAY;AACzD,MAAI,OAAO,UAAU,GAAG;AACtB,WAAO,SAAS,OAAO,CAAC,GAAG,EAAE;AAAA,EAC/B;AACA,SAAO,MAAM;AACf;;;ADzGA,IAAM,cAAc,IAAIC,MAAK;AAG7B,eAAe,iBAAiB,GAAQ,MAA2B;AAEjE,QAAM,eAAe,gBAAgB;AACrC,MAAI,CAAC,cAAc;AACjB,WAAO,KAAK;AAAA,EACd;AAGA,QAAM,SAAS,EAAE,IAAI,OAAO,WAAW;AACvC,MAAI,QAAQ;AACV,UAAM,kBAAkB,MAAM,eAAe,QAAQ,WAAW;AAChE,QAAI,CAAC,gBAAgB,SAAS;AAC5B,aAAO,EAAE;AAAA,QACP,EAAE,OAAO,uBAAuB,YAAY,gBAAgB,aAAa;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAGA,QAAM,aAAa,EAAE,IAAI,OAAO,eAAe;AAC/C,MAAI,YAAY,WAAW,SAAS,GAAG;AACrC,UAAM,QAAQ,WAAW,MAAM,CAAC;AAChC,QAAI,gBAAgB,OAAO,YAAY,GAAG;AACxC,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAClD;AAEA,YAAY,IAAI,KAAK,gBAAgB;AAGrC,YAAY,IAAI,eAAe,OAAO,MAAM;AAC1C,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,EAAE,IAAI,GAAG;AAC7B,UAAM,UAA6B,CAAC;AAEpC,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAI,OAAQ,SAAQ,SAAS;AAE7B,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAI,OAAQ,SAAQ,SAAS;AAE7B,UAAM,WAAW,IAAI,aAAa,IAAI,UAAU;AAChD,QAAI,SAAU,SAAQ,WAAW;AAEjC,UAAM,YAAY,IAAI,aAAa,IAAI,WAAW;AAClD,QAAI,UAAW,SAAQ,YAAY,IAAI,KAAK,SAAS;AAErD,UAAM,UAAU,IAAI,aAAa,IAAI,SAAS;AAC9C,QAAI,QAAS,SAAQ,UAAU,IAAI,KAAK,OAAO;AAE/C,UAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,YAAQ,QAAQ,QAAQ,KAAK,IAAI,SAAS,OAAO,EAAE,GAAG,GAAG,IAAI;AAE7D,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,YAAQ,SAAS,SAAS,SAAS,QAAQ,EAAE,IAAI;AAEjD,UAAM,OAAO,MAAM,eAAe,OAAO;AAEzC,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS;AAAA,MACT;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,IAAI,WAAW,6BAA6B,GAAG,GAAG;AAAA,EAC3E;AACF,CAAC;AAGD,YAAY,IAAI,yBAAyB,OAAO,MAAM;AACpD,MAAI;AACF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,GAAG,UAAU,CAAC;AAAA,EAC/C,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,IAAI,WAAW,4BAA4B,GAAG,GAAG;AAAA,EAC1E;AACF,CAAC;AAGD,YAAY,IAAI,cAAc,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,EAAE,IAAI,GAAG;AAC7B,UAAM,QAAQ,KAAK,IAAI,SAAS,IAAI,aAAa,IAAI,OAAO,KAAK,MAAM,EAAE,GAAG,GAAG;AAG/E,UAAM,YAAY,MAAM,eAAe;AAAA,MACrC,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS;AAAA,MACT;AAAA,MACA,OAAO,UAAU;AAAA,IACnB,CAAC;AAAA,EACH,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,IAAI,WAAW,4BAA4B,GAAG,GAAG;AAAA,EAC1E;AACF,CAAC;AAED,IAAO,gBAAQ;;;AElHf,SAAS,QAAAC,aAAY;AAKrB,IAAM,cAAc,IAAIC,MAAK;AAG7B,YAAY,IAAI,WAAW,CAAC,MAAM;AAChC,SAAO,EAAE,KAAK,eAAe,UAAU,CAAC;AAC1C,CAAC;AAGD,YAAY,IAAI,aAAa,CAAC,MAAM;AAClC,QAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,KAAK;AACpD,SAAO,EAAE,KAAK,eAAe,YAAY,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC;AAChE,CAAC;AAGD,YAAY,IAAI,WAAW,OAAO,MAAM;AAEtC,QAAM,YAAY,WAAW;AAC7B,SAAO,EAAE,KAAK,eAAe,UAAU,CAAC;AAC1C,CAAC;AAGD,YAAY,IAAI,WAAW,OAAO,MAAM;AACtC,QAAM,SAAS,EAAE,IAAI,MAAM,QAAQ;AACnC,MAAI;AACF,UAAM,EAAE,eAAe,aAAa,IAAI,MAAM,OAAO,6BAAoC;AACzF,UAAM,SAAS,SACX,MAAM,cAAc,QAAQ,QAAW,EAAE,IACzC,MAAM,aAAa,QAAW,EAAE;AACpC,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,CAAC;AAAA,EAClB;AACF,CAAC;AAGD,YAAY,IAAI,kBAAkB,CAAC,MAAM;AACvC,QAAM,OAAO,SAAS,EAAE,IAAI,MAAM,MAAM,KAAK,GAAG;AAChD,SAAO,EAAE,KAAK;AAAA,IACZ,UAAU,YAAY,YAAY,IAAI;AAAA,IACtC,OAAO,YAAY,aAAa;AAAA,IAChC,kBAAkB,YAAY,wBAAwB;AAAA,EACxD,CAAC;AACH,CAAC;AAID,YAAY,IAAI,iBAAiB,OAAO,MAAM;AAC5C,QAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AACvC,QAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AAEnD,MAAI;AAEF,UAAMC,YAAW,MAAM,eAAe,IAAI,QAAW,KAAK;AAC1D,UAAM,QAOD,CAAC;AACN,UAAM,QAKD,CAAC;AAEN,eAAW,OAAOA,WAAU;AAC1B,YAAM,KAAK;AAAA,QACT,IAAI,OAAO,IAAI,EAAE;AAAA,QACjB,OAAO,IAAI,WAAW,IAAI,MAAM,GAAG,EAAE,MAAM,IAAI,WAAW,IAAI,SAAS,KAAK,QAAQ;AAAA,QACpF,MAAM;AAAA,QACN,aAAa,IAAI,cAAc,KAAK;AAAA;AAAA,QACpC,SAAS,IAAI,WAAW;AAAA,QACxB,WAAW,IAAI,WAAW,cAAc,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,MACtE,CAAC;AAAA,IACH;AAGA,QAAI,UAAU;AACZ,UAAI;AACF,cAAM,EAAE,IAAAC,IAAG,IAAI,MAAM,OAAO,kBAAa;AACzC,cAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,sBAAoB;AAC3D,cAAM,EAAE,IAAAC,IAAG,IAAI,MAAM,OAAO,aAAa;AAEzC,cAAM,CAAC,MAAM,IAAI,MAAMF,IACpB,OAAO,EACP,KAAKC,cAAa,EAClB,MAAMC,IAAGD,eAAc,IAAI,QAAQ,CAAC,EACpC,MAAM,CAAC;AAEV,YAAI,QAAQ;AAEV,gBAAM,KAAK;AAAA,YACT,IAAI,OAAO;AAAA,YACX,MAAM,OAAO;AAAA,YACb,MAAM,OAAO;AAAA,YACb,YAAY,OAAO,cAAc;AAAA,YACjC,SAAS,OAAO,eAAe;AAAA,YAC/B,WAAW,OAAO,WAAW,cAAc,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,UACzE,CAAC;AAGD,qBAAW,OAAOF,WAAU;AAC1B,kBAAM,WAAW,IAAI,WAAW,IAAI,YAAY;AAChD,gBACE,QAAQ,SAAS,OAAO,KAAK,YAAY,CAAC,MACzC,OAAO,WAAuB,CAAC,GAAG;AAAA,cAAK,CAAC,MACvC,QAAQ,SAAS,EAAE,YAAY,CAAC;AAAA,YAClC,GACA;AACA,oBAAM,KAAK;AAAA,gBACT,QAAQ,OAAO,IAAI,EAAE;AAAA,gBACrB,QAAQ,OAAO;AAAA,gBACf,MAAM;AAAA,gBACN,UAAU;AAAA,cACZ,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,eAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,YACE,MAAM,CAAC,EAAE,SAAS,YAClB,MAAM,CAAC,EAAE,SAAS,YAClB,MAAM,CAAC,EAAE,WACT,MAAM,CAAC,EAAE,SACT;AAEA,gBAAM,SAAS,IAAI,IAAI,MAAM,CAAC,EAAE,QAAQ,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,CAAC;AAC5F,gBAAM,SAAS,IAAI,IAAI,MAAM,CAAC,EAAE,QAAQ,YAAY,EAAE,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,CAAC;AAC5F,gBAAM,UAAU,CAAC,GAAG,MAAM,EAAE,OAAO,OAAK,OAAO,IAAI,CAAC,CAAC,EAAE;AACvD,cAAI,WAAW,GAAG;AAChB,kBAAM,KAAK;AAAA,cACT,QAAQ,MAAM,CAAC,EAAE;AAAA,cACjB,QAAQ,MAAM,CAAC,EAAE;AAAA,cACjB,MAAM;AAAA,cACN,UAAU,KAAK,IAAI,KAAK,UAAU,EAAE;AAAA,YACtC,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EAChC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,+BAA+B,GAAG,GAAG;AAAA,EACpF;AACF,CAAC;AAGD,YAAY,IAAI,mBAAmB,OAAO,MAAM;AAC9C,MAAI;AACF,UAAM,EAAE,uBAAuB,IAAI,MAAM,OAAO,2BAAkC;AAClF,UAAM,UAAU,MAAM,QAAQ,IAAI;AAAA,MAChC,OAAO,8BAAiD,EAAE,KAAK,OAAK,EAAE,qBAAqB;AAAA,MAC3F,OAAO,4BAA+C,EAAE,KAAK,OAAK,EAAE,mBAAmB;AAAA,MACvF,OAAO,6BAAgD,EAAE,KAAK,OAAK,EAAE,oBAAoB;AAAA,MACzF,OAAO,8BAAiD,EAAE,KAAK,OAAK,EAAE,qBAAqB;AAAA,MAC3F,OAAO,2BAA8C,EAAE,KAAK,OAAK,EAAE,kBAAkB;AAAA,IACvF,CAAC;AACD,UAAM,UAAU,QAAQ,IAAI,UAAQ;AAAA,MAClC,MAAM,IAAI;AAAA,MACV,MAAM,IAAI;AAAA,MACV,aAAa,IAAI;AAAA,MACjB,OAAO,uBAAuB,IAAI,IAAI,KAAK,CAAC;AAAA,MAC5C,UAAU,IAAI,YAAY,CAAC;AAAA,IAC7B,EAAE;AACF,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,CAAC;AAAA,EAClB;AACF,CAAC;AAGD,YAAY,KAAK,iBAAiB,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,EAAE,MAAM,UAAU,IAAI,MAAM,EAAE,IAAI,KAA0C;AAClF,QAAI,CAAC,QAAQ,CAAC,WAAW;AACvB,aAAO,EAAE,KAAK,EAAE,OAAO,kCAAkC,GAAG,GAAG;AAAA,IACjE;AAEA,UAAM,EAAE,IAAAC,IAAG,IAAI,MAAM,OAAO,kBAAa;AACzC,UAAM,EAAE,OAAAG,OAAM,IAAI,MAAM,OAAO,sBAAoB;AACnD,QAAI,aAAa,MAAMH,IAAG,OAAO,EAAE,KAAKG,MAAK,EAAE,MAAM,CAAC;AACtD,QAAI,WAAW,WAAW,GAAG;AAC3B,mBAAa,MAAMH,IAAG,OAAOG,MAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC,EAAE,UAAU;AAAA,IAC9E;AACA,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,6BAAoC;AACxE,UAAM,QAAQ,MAAM,WAAW;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,QAAQ,WAAW,CAAC,EAAE;AAAA,IACxB,CAAC;AACD,WAAO,EAAE,KAAK,OAAO,GAAG;AAAA,EAC1B,SAAS,OAAY;AACnB,WAAO,EAAE,KAAK,EAAE,OAAO,OAAO,WAAW,wBAAwB,GAAG,GAAG;AAAA,EACzE;AACF,CAAC;AAGD,YAAY,KAAK,gBAAgB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAM,EAAE,IAAAH,IAAG,IAAI,MAAM,OAAO,kBAAa;AACzC,UAAM,EAAE,WAAW,eAAe,OAAAG,OAAM,IAAI,MAAM,OAAO,sBAAoB;AAG7E,QAAI,aAAa,MAAMH,IAAG,OAAO,EAAE,KAAKG,MAAK,EAAE,MAAM,CAAC;AACtD,QAAI,WAAW,WAAW,GAAG;AAC3B,mBAAa,MAAMH,IAAG,OAAOG,MAAK,EAAE,OAAO;AAAA,QACzC,MAAM;AAAA,MACR,CAAC,EAAE,UAAU;AAAA,IACf;AACA,UAAM,SAAS,WAAW,CAAC,EAAE;AAE7B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAQ;AAAA,MACZ;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,IAAI,IAAQ;AAAA,QACtC,QAAQ,EAAE,SAAS,MAAM,SAAS,qOAAqO,YAAY,MAAM;AAAA,MAC3R;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,IAAI,IAAQ;AAAA,QACtC,QAAQ,EAAE,SAAS,MAAM,SAAS,0LAA0L,YAAY,OAAO;AAAA,MACjP;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,KAAK,IAAQ;AAAA,QACvC,QAAQ,EAAE,SAAS,MAAM,SAAS,wPAAwP,YAAY,MAAM;AAAA,MAC9S;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,KAAK,IAAQ;AAAA,QACvC,QAAQ,EAAE,SAAS,MAAM,SAAS,gLAAgL,YAAY,MAAM;AAAA,MACtO;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,KAAK,IAAQ;AAAA,QACvC,QAAQ,EAAE,SAAS,MAAM,SAAS,gNAAgN,YAAY,MAAM;AAAA,MACtQ;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,IAAI,IAAQ;AAAA,QACtC,QAAQ,EAAE,SAAS,OAAO,OAAO,6JAA6J,YAAY,MAAM;AAAA,MAClN;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,IAAQ;AAAA,QAClC,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,IAAI,KAAK,MAAM,GAAO;AAAA,QACjC,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,UAAM,WAAW,CAAC;AAClB,eAAW,QAAQ,OAAO;AACxB,YAAM,CAAC,GAAG,IAAI,MAAMH,IAAG,OAAO,SAAS,EAAE,OAAO,IAAW,EAAE,UAAU;AACvE,eAAS,KAAK,GAAG;AAAA,IACnB;AAGA,UAAM,cAAc,SAAS,KAAK,OAAK,EAAE,WAAW,SAAS;AAC7D,QAAI,aAAa;AACf,YAAMA,IAAG,OAAO,aAAa,EAAE,OAAO;AAAA,QACpC,EAAE,SAAS,YAAY,IAAI,MAAM,GAAG,aAAa,qDAAqD,QAAQ,YAAqB;AAAA,QACnI,EAAE,SAAS,YAAY,IAAI,MAAM,GAAG,aAAa,0CAA0C,QAAQ,YAAqB;AAAA,QACxH,EAAE,SAAS,YAAY,IAAI,MAAM,GAAG,aAAa,sCAAsC,QAAQ,UAAmB;AAAA,QAClH,EAAE,SAAS,YAAY,IAAI,MAAM,GAAG,aAAa,8CAA8C,QAAQ,UAAmB;AAAA,QAC1H,EAAE,SAAS,YAAY,IAAI,MAAM,GAAG,aAAa,0CAA0C,QAAQ,UAAmB;AAAA,MACxH,CAAC;AAAA,IACH;AAGA,UAAM,eAAe,SAAS,KAAK,OAAK,EAAE,WAAW,eAAe,EAAE,SAAS,UAAU;AACzF,QAAI,cAAc;AAChB,YAAMA,IAAG,OAAO,aAAa,EAAE,OAAO;AAAA,QACpC,EAAE,SAAS,aAAa,IAAI,MAAM,GAAG,aAAa,6DAA6D,QAAQ,YAAqB;AAAA,QAC5I,EAAE,SAAS,aAAa,IAAI,MAAM,GAAG,aAAa,wDAAwD,QAAQ,YAAqB;AAAA,QACvI,EAAE,SAAS,aAAa,IAAI,MAAM,GAAG,aAAa,4CAA4C,QAAQ,YAAqB;AAAA,QAC3H,EAAE,SAAS,aAAa,IAAI,MAAM,GAAG,aAAa,0CAA0C,QAAQ,YAAqB;AAAA,MAC3H,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,QAAQ,SAAS,OAAO,CAAC;AAAA,EAC1D,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,uBAAuB,GAAG,GAAG;AAAA,EACtE;AACF,CAAC;AAGD,YAAY,OAAO,mBAAmB,OAAO,MAAM;AACjD,MAAI;AACF,UAAM,EAAE,IAAAA,IAAG,IAAI,MAAM,OAAO,kBAAa;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAoB;AACvD,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,aAAa;AAC9C,UAAMA,IAAG,OAAO,SAAS,EAAE,MAAM,QAAQ,UAAU,QAAQ,CAAC,aAAa,UAAU,WAAW,CAAC,CAAC;AAChG,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,+BAA+B,GAAG,GAAG;AAAA,EAC9E;AACF,CAAC;AAGD,YAAY,OAAO,aAAa,CAAC,MAAM;AACrC,iBAAe,gBAAgB;AAC/B,SAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AACjC,CAAC;AAED,IAAO,gBAAQ;;;ACxXf,SAAS,QAAAI,aAAY;AAErB,IAAM,kBAAkB,IAAIA,MAAK;AAGjC,gBAAgB,IAAI,SAAS,OAAO,MAAM;AACxC,MAAI;AACF,UAAM,EAAE,WAAW,iBAAiB,IAAI,MAAM,OAAO,yBAAyB;AAC9E,UAAM,CAAC,UAAU,eAAe,IAAI,MAAM,QAAQ,WAAW;AAAA,MAC3D,WAAW,oBAAoB,KAAK,QAAQ,QAAQ,CAAC,CAAC;AAAA,MACtD,kBAAkB,oBAAoB,KAAK,QAAQ,QAAQ,CAAC,CAAC;AAAA,IAC/D,CAAC;AACD,UAAM,OAAO;AAAA,MACX,GAAI,SAAS,WAAW,cAAc,SAAS,QAAQ,CAAC;AAAA,MACxD,GAAI,gBAAgB,WAAW,cAAc,gBAAgB,QAAQ,CAAC;AAAA,IACxE;AACA,WAAO,EAAE,KAAK,IAAI;AAAA,EACpB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,CAAC,GAAG,GAAG;AAAA,EACvB;AACF,CAAC;AAGD,gBAAgB,IAAI,UAAU,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,yBAAyB;AAChE,UAAM,QAAQ,MAAM,cAAc;AAClC,WAAO,EAAE,KAAK,KAAK;AAAA,EACrB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,EAAE,CAAC;AAAA,EAC9E;AACF,CAAC;AAGD,gBAAgB,KAAK,SAAS,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,EAAE,MAAM,SAAS,KAAK,IAAI,MAAM,EAAE,IAAI,KAIzC;AAEH,QAAI,CAAC,QAAQ,CAAC,SAAS;AACrB,aAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,IAC/D;AAEA,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,yBAAyB;AACpE,UAAM,kBAAkB,MAAM,QAAQ,EAAE,MAAM,UAAU,KAAK,GAAG,OAAO;AACvE,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,GAAG,GAAG;AAAA,EACtC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAGD,gBAAgB,OAAO,cAAc,OAAO,MAAM;AAChD,MAAI;AACF,UAAM,MAAM,mBAAmB,EAAE,IAAI,MAAM,KAAK,CAAC;AACjD,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,yBAAyB;AAC5D,UAAM,UAAU,sBAAsB,GAAG;AACzC,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAGD,gBAAgB,IAAI,cAAc,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,MAAM,mBAAmB,EAAE,IAAI,MAAM,KAAK,CAAC;AACjD,UAAM,EAAE,MAAM,SAAS,KAAK,IAAI,MAAM,EAAE,IAAI,KAIzC;AAEH,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,IACrD;AAEA,UAAM,EAAE,WAAW,kBAAkB,IAAI,MAAM,OAAO,yBAAyB;AAE/E,UAAM,UAAU,sBAAsB,GAAG;AAEzC,UAAM,UAAU,QAAQ,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK;AAC/C,UAAM,kBAAkB,SAAS,QAAQ,EAAE,MAAM,UAAU,MAAM,QAAQ,GAAG,OAAO;AACnF,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAED,IAAO,oBAAQ;;;AC5Ff,SAAS,QAAAC,aAAY;AAErB,IAAM,eAAe,IAAIA,MAAK;AAG9B,aAAa,IAAI,KAAK,OAAO,MAAM;AACjC,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,wBAAsC;AAEpE,UAAM,SAAS,yBAAyB;AACxC,UAAM,SAAS,SAAS,kBAAkB,KAAK,CAAC;AAChD,UAAM,UAAU,SAAS,kBAAkB,EAAE,KAAK,CAAC;AACnD,WAAO,EAAE,KAAK,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACnC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;AAAA,EAC3C;AACF,CAAC;AAGD,aAAa,KAAK,oBAAoB,OAAO,MAAM;AACjD,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,EAAE,GAAG,IAAI,MAAM,EAAE,IAAI,KAAqB;AAChD,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,aAAS,mBAAmB,IAAI,MAAM,UAAU;AAChD,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,EAC7D;AACF,CAAC;AAGD,aAAa,KAAK,gBAAgB,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,EAAE,GAAG,IAAI,MAAM,EAAE,IAAI,KAAqB;AAChD,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,aAAS,eAAe,IAAI,MAAM,UAAU;AAC5C,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,GAAG,GAAG;AAAA,EACzD;AACF,CAAC;AAGD,aAAa,IAAI,UAAU,OAAO,MAAM;AACtC,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,QAAI,QAAQ,SAAS,gBAAgB,KAAK,CAAC;AAE3C,QAAI,MAAM,WAAW,KAAK,SAAS,wBAAwB;AACzD,eAAS,uBAAuB;AAChC,cAAQ,SAAS,gBAAgB,KAAK,CAAC;AAAA,IACzC;AACA,WAAO,EAAE,KAAK,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,CAAC;AAAA,EAClB;AACF,CAAC;AAGD,aAAa,OAAO,YAAY,OAAO,MAAM;AAC3C,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,aAAS,oBAAoB;AAC7B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC/D;AACF,CAAC;AAGD,aAAa,KAAK,UAAU,OAAO,MAAM;AACvC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAAK;AAC9B,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,aAAS,eAAe,IAAI;AAC5B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,GAAG,GAAG;AAAA,EACtC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,aAAa,OAAO,cAAc,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,UAAM,UAAU,SAAS,kBAAkB,EAAE;AAC7C,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAAA,IAChD;AACA,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,aAAa,IAAI,cAAc,OAAO,MAAM;AAC1C,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,UAAU,MAAM,EAAE,IAAI,KAAK;AACjC,UAAM,WAAW,MAAM,OAAO,wBAAsC;AACpE,UAAM,QAAQ,SAAS,gBAAgB,KAAK,CAAC;AAC7C,UAAM,WAAW,MAAM,KAAK,CAAC,MAAW,EAAE,OAAO,EAAE;AACnD,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAAA,IAChD;AAEA,UAAM,UAAU,EAAE,GAAG,UAAU,GAAG,SAAS,GAAG;AAC9C,aAAS,eAAe,OAAO;AAC/B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAO,iBAAQ;;;ACtHf,SAAS,QAAAC,aAAY;AACrB,SAAS,MAAM,cAAc;AAE7B,IAAM,iBAAiB,IAAIA,MAAK;AAGhC,eAAe,IAAI,KAAK,OAAO,MAAM;AACnC,MAAI;AACF,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAChC,UAAM,YAAY,MAAM,MAAM,gBAAgB;AAC9C,UAAM,UAAU,UAAU,IAAI,CAAC,OAAY;AAAA,MACzC,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,aAAa,EAAE,eAAe;AAAA,MAC9B,aAAa,MAAM,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,CAAC,GAAG,QAAQ;AAAA,MACjE,SAAS,MAAM,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC;AAAA,MACxD,UAAU,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAY;AAAA,QAChE,MAAM,EAAE,QAAQ,QAAQ,EAAE,QAAQ;AAAA,QAClC,MAAM,EAAE,QAAQ,QAAQ,EAAE,QAAQ,QAAQ,EAAE,QAAQ;AAAA,MACtD,EAAE;AAAA,MACF,SAAS,EAAE,WAAW;AAAA,MACtB,WAAW,EAAE;AAAA,MACb,WAAW,EAAE;AAAA,MACb,eAAe,EAAE;AAAA,MACjB,gBAAgB,EAAE,kBAAkB;AAAA,IACtC,EAAE;AACF,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,CAAC;AAAA,EAClB;AACF,CAAC;AAGD,eAAe,KAAK,KAAK,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAMtB;AAEH,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAChC,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,WAAW,MAAM,MAAM,eAAe;AAAA,MAC1C,IAAI,OAAO;AAAA,MACX,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,QAAQ;AAAA,MACR,UAAU,CAAC,EAAE,MAAM,KAAK,eAAe,WAAW,QAAQ,KAAK,WAAW,CAAC,EAAE,CAAQ;AAAA,MACrF,QAAQ,KAAK,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,OAAO;AAAA,QACzC,IAAI,OAAO;AAAA,QACX,MAAM;AAAA,QACN,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,UAAU,CAAC,EAAE;AAAA,MACjD,EAAE;AAAA,MACF,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,WAAO,EAAE,KAAK,EAAE,IAAI,SAAS,IAAI,SAAS,KAAK,GAAG,GAAG;AAAA,EACvD,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,2BAA2B,GAAG,GAAG;AAAA,EAC1E;AACF,CAAC;AAGD,eAAe,IAAI,eAAe,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAChC,UAAM,WAAW,MAAM,MAAM,YAAY,EAAE;AAC3C,QAAI,CAAC,SAAU,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AACjE,UAAM,YAAY,SAAS,WAAW,WAAW,aAAa;AAC9D,UAAM,MAAM,eAAe,IAAI,EAAE,QAAQ,UAAU,CAAC;AACpD,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,SAAS,cAAc,SAAS,CAAC;AAAA,EAClE,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG;AAAA,EAC1D;AACF,CAAC;AAGD,eAAe,OAAO,QAAQ,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAChC,UAAM,MAAM,eAAe,EAAE;AAC7B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG;AAAA,EAC1D;AACF,CAAC;AAGD,eAAe,IAAI,QAAQ,OAAO,MAAM;AACtC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,OAAO,MAAM,EAAE,IAAI,KAMtB;AAEH,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAChC,UAAM,WAAW,MAAM,MAAM,YAAY,EAAE;AAC3C,QAAI,CAAC,SAAU,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AAEjE,UAAM,UAAmC,CAAC;AAC1C,QAAI,KAAK,SAAS,OAAW,SAAQ,OAAO,KAAK;AACjD,QAAI,KAAK,gBAAgB,OAAW,SAAQ,cAAc,KAAK;AAC/D,QAAI,KAAK,gBAAgB,UAAa,KAAK,YAAY,QAAW;AAChE,cAAQ,WAAW,CAAC,EAAE,MAAM,KAAK,eAAe,WAAW,QAAQ,KAAK,WAAW,CAAC,EAAE,CAAC;AAAA,IACzF;AACA,QAAI,KAAK,YAAY,QAAW;AAC9B,YAAM,EAAE,IAAI,UAAU,IAAI,MAAM,OAAO,MAAM;AAC7C,cAAQ,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO;AAAA,QACvC,IAAI,UAAU;AAAA,QACd,MAAM;AAAA,QACN,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,UAAU,CAAC,EAAE;AAAA,MACjD,EAAE;AAAA,IACJ;AAEA,UAAM,MAAM,eAAe,IAAI,OAAc;AAC7C,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG;AAAA,EAC1D;AACF,CAAC;AAGD,eAAe,KAAK,SAAS,OAAO,MAAM;AACxC,MAAI;AACF,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,8BAAwC;AAC/E,UAAM,QAAQ,IAAI,cAAc;AAEhC,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,WAAW;AAAA,MACf;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,UACT,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,SAAS,CAAC,MAAM;AAAA,YAChB,QAAQ;AAAA,YACR,QAAQ,EAAE,MAAM,aAAa,YAAY,OAAO,eAAe,kBAAkB;AAAA,UACnF;AAAA,QACF,CAAC;AAAA,QACD,OAAO;AAAA,UACL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,gBAAgB,QAAQ,EAAE,SAAS,OAAO,SAAS,yDAAyD,EAAE,EAAE;AAAA,QAC3K;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,UACT,MAAM;AAAA,UACN,QAAQ,EAAE,QAAQ,SAAS,WAAW,iBAAiB;AAAA,QACzD,CAAC;AAAA,QACD,OAAO;AAAA,UACL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,gBAAgB,QAAQ,EAAE,SAAS,OAAO,SAAS,iEAAiE,EAAE,EAAE;AAAA,QACnL;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,UACT,MAAM;AAAA,UACN,QAAQ,EAAE,QAAQ,YAAY,WAAW,eAAe,QAAQ,EAAE,UAAU,QAAQ,EAAE;AAAA,QACxF,CAAC;AAAA,QACD,OAAO;AAAA,UACL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,gBAAgB,QAAQ,EAAE,SAAS,OAAO,SAAS,wEAAwE,EAAE,EAAE;AAAA,UACxL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,OAAO,QAAQ,EAAE,OAAO,SAAS,SAAS,wCAAwC,EAAE,EAAE;AAAA,QACjJ;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,UACT,MAAM;AAAA,UACN,QAAQ,EAAE,SAAS,aAAa,UAAU,mBAAmB;AAAA,QAC/D,CAAC;AAAA,QACD,OAAO;AAAA,UACL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,YAAY,QAAQ,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,EAAE,EAAE;AAAA,UAC/G,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,gBAAgB,QAAQ,EAAE,SAAS,OAAO,SAAS,wDAAwD,EAAE,EAAE;AAAA,QAC1K;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,UACT,MAAM;AAAA,UACN,QAAQ,EAAE,SAAS,eAAe;AAAA,QACpC,CAAC;AAAA,QACD,OAAO;AAAA,UACL,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,gBAAgB,QAAQ,EAAE,QAAQ,OAAO,KAAK,qCAAqC,SAAS,CAAC,EAAE,EAAE,EAAE;AAAA,UAC5J,EAAE,IAAI,OAAO,GAAG,MAAM,UAAmB,QAAQ,EAAE,MAAM,OAAO,QAAQ,EAAE,OAAO,QAAQ,SAAS,yBAAyB,EAAE,EAAE;AAAA,QACjI;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU;AACd,UAAM,WAAW,MAAM,MAAM,gBAAgB;AAC7C,UAAM,gBAAgB,IAAI,IAAI,SAAS,IAAI,CAAC,MAAW,EAAE,IAAI,CAAC;AAE9D,eAAW,MAAM,UAAU;AACzB,UAAI,CAAC,cAAc,IAAI,GAAG,IAAI,GAAG;AAC/B,cAAM,MAAM,eAAe;AAAA,UACzB,IAAI,OAAO;AAAA,UACX,GAAG;AAAA,UACH,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,WAAW;AAAA,UACX,WAAW;AAAA,QACb,CAAQ;AACR;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,SAAS,OAAO,SAAS,SAAS,QAAQ,CAAC;AAAA,EAC5E,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,0BAA0B,GAAG,GAAG;AAAA,EACzE;AACF,CAAC;AAED,IAAO,mBAAQ;;;AC7Of,SAAS,QAAAC,aAAY;AAErB,IAAM,eAAe,IAAIA,MAAK;AAG9B,aAAa,IAAI,UAAU,OAAO,MAAM;AACtC,MAAI;AACF,UAAM,EAAE,KAAAC,KAAI,IAAI,MAAM,OAAO,mBAAqB;AAClD,QAAI,CAACA,KAAI,cAAc;AACrB,aAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,IAC7D;AACA,UAAM,SAAS,MAAM,OAAO,sBAA8B;AAC1D,UAAM,QAAQ,MAAM,OAAO,iBAAiB;AAC5C,WAAO,EAAE,KAAK,KAAK;AAAA,EACrB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,CAAC,GAAG,GAAG;AAAA,EACvB;AACF,CAAC;AAGD,aAAa,IAAI,WAAW,OAAO,MAAM;AACvC,MAAI;AACF,UAAM,EAAE,KAAAA,KAAI,IAAI,MAAM,OAAO,mBAAqB;AAClD,QAAI,CAACA,KAAI,cAAc;AACrB,aAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,IAC7D;AACA,UAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAC/B,UAAM,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AACtC,UAAM,SAAS,MAAM,OAAO,sBAA8B;AAC1D,QAAI,MAAM;AACR,YAAM,CAAC,OAAO,IAAI,IAAI,KAAK,MAAM,GAAG;AACpC,YAAMC,UAAS,MAAM,OAAO,WAAW,OAAO,MAAM,EAAE,MAAoB,CAAC;AAC3E,aAAO,EAAE,KAAKA,OAAM;AAAA,IACtB;AAEA,UAAM,SAAS,MAAM,OAAO,WAAW,IAAI,IAAI,EAAE,MAAoB,CAAC;AACtE,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,GAAG,GAAG;AAAA,EACvB;AACF,CAAC;AAGD,aAAa,IAAI,QAAQ,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,EAAE,KAAAD,KAAI,IAAI,MAAM,OAAO,mBAAqB;AAClD,QAAI,CAACA,KAAI,cAAc;AACrB,aAAO,EAAE,KAAK,EAAE,OAAO,8BAA8B,GAAG,GAAG;AAAA,IAC7D;AACA,UAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAC/B,UAAM,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AACtC,UAAM,SAAS,MAAM,OAAO,sBAA8B;AAC1D,QAAI,MAAM;AACR,YAAM,CAAC,OAAO,IAAI,IAAI,KAAK,MAAM,GAAG;AACpC,YAAME,OAAM,MAAM,OAAO,iBAAiB,OAAO,MAAM,EAAE,MAAoB,CAAC;AAC9E,aAAO,EAAE,KAAKA,IAAG;AAAA,IACnB;AACA,UAAM,MAAM,MAAM,OAAO,iBAAiB,IAAI,IAAI,EAAE,MAAoB,CAAC;AACzE,WAAO,EAAE,KAAK,GAAG;AAAA,EACnB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,GAAG,GAAG;AAAA,EACvB;AACF,CAAC;AAED,IAAO,iBAAQ;;;ACpEf,SAAS,QAAAC,cAAY;AAcrB,IAAM,gBAAgB,IAAIC,OAAK;AAG/B,eAAe,cAAc,GAAQ,MAA2B;AAC9D,QAAM,SAAS,EAAE,IAAI,OAAO,WAAW;AACvC,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,EAClD;AAGA,QAAM,kBAAkB,MAAM,eAAe,QAAQ,aAAa;AAClE,MAAI,CAAC,gBAAgB,SAAS;AAC5B,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,YAAY,gBAAgB;AAAA,MAC9B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,KAAK;AACb;AAEA,cAAc,IAAI,KAAK,aAAa;AAGpC,cAAc,IAAI,gBAAgB,OAAO,MAAM;AAC7C,QAAM,aAAa,EAAE,IAAI,MAAM,MAAM;AACrC,QAAM,YAAY,EAAE,IAAI,MAAM,OAAO;AACrC,QAAM,UAAU,EAAE,IAAI,MAAM,KAAK;AACjC,QAAM,UAAU,EAAE,IAAI,MAAM,SAAS;AAErC,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AAEA,QAAM,QAAQ,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI;AACzF,QAAM,MAAM,UAAU,IAAI,KAAK,OAAO,IAAI,oBAAI,KAAK;AAEnD,QAAM,cAAc,MAAM,oBAAoB,YAA0B,OAAO,GAAG;AAElF,SAAO,EAAE,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ,EAAE,OAAO,MAAM,YAAY,GAAG,KAAK,IAAI,YAAY,EAAE;AAAA,IAC7D;AAAA,EACF,CAAC;AACH,CAAC;AAGD,cAAc,IAAI,eAAe,OAAO,MAAM;AAC5C,QAAM,aAAa,EAAE,IAAI,MAAM,MAAM;AACrC,QAAM,YAAY,EAAE,IAAI,MAAM,OAAO;AACrC,QAAM,UAAU,EAAE,IAAI,MAAM,KAAK;AACjC,QAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AAEvC,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AAEA,QAAM,QAAQ,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI;AACzF,QAAM,MAAM,UAAU,IAAI,KAAK,OAAO,IAAI,oBAAI,KAAK;AAEnD,QAAM,aAAa,MAAM,oBAAoB,YAA0B,OAAO,GAAG;AAEjF,SAAO,EAAE,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ,EAAE,OAAO,MAAM,YAAY,GAAG,KAAK,IAAI,YAAY,EAAE;AAAA,IAC7D,UAAU,YAAY;AAAA,IACtB,MAAM;AAAA,EACR,CAAC;AACH,CAAC;AAGD,cAAc,KAAK,WAAW,OAAO,MAAM;AACzC,QAAM,OAAO,MAAM,EAAE,IAAI,KAAK;AAC9B,QAAM,EAAE,MAAM,OAAO,UAAU,OAAO,IAAI;AAE1C,MAAI,CAAC,QAAQ,UAAU,QAAW;AAChC,WAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,GAAG,GAAG;AAAA,EACzD;AAEA,QAAM,aAAa;AAAA,IACjB,MAAM;AAAA,IACN;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AAED,SAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AACjC,CAAC;AAGD,cAAc,KAAK,UAAU,OAAO,MAAM;AACxC,QAAM,aAAa;AACnB,SAAO,EAAE,KAAK,EAAE,SAAS,MAAM,SAAS,kBAAkB,CAAC;AAC7D,CAAC;AAGD,cAAc,IAAI,iBAAiB,OAAO,MAAM;AAC9C,QAAM,OAAO,SAAS,EAAE,IAAI,MAAM,MAAM,KAAK,GAAG;AAChD,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,OAAO,KAAK,KAAK,KAAK,GAAI;AACjE,QAAM,QAAQ,MAAM,cAAc,OAAO,GAAG;AAE5C,SAAO,EAAE,KAAK;AAAA,IACZ,QAAQ,QAAQ,IAAI;AAAA,IACpB;AAAA,EACF,CAAC;AACH,CAAC;AAGD,cAAc,IAAI,kBAAkB,OAAO,MAAM;AAC/C,QAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AACnD,QAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AACvC,QAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AAEvC,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,KAAK;AAAA,IACZ,OAAO,OAAO;AAAA,IACd;AAAA,EACF,CAAC;AACH,CAAC;AAGD,cAAc,IAAI,WAAW,OAAO,MAAM;AACxC,QAAM,MAAM,oBAAI,KAAK;AAGrB,QAAM,gBAAgB,MAAM;AAAA,IAC1B;AAAA,IACA,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAK,GAAI;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,eAAe,MAAM,gBAAgB,EAAE;AAE7C,QAAM,SAAS;AAAA,IACb,SAAS;AAAA,IACT,WAAW,IAAI,YAAY;AAAA,IAC3B,SAAS;AAAA,MACP,cAAc,cAAc,OAAO;AAAA,MACnC,kBAAkB,aAAa;AAAA,IACjC;AAAA,EACF;AAGA,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,UAAU;AAAA,EACnB;AAEA,SAAO,EAAE,KAAK,QAAQ,OAAO,UAAU,MAAM,GAAG;AAClD,CAAC;AAGD,cAAc,IAAI,aAAa,OAAO,MAAM;AAC1C,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,SAAS,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,KAAK,KAAK,GAAI;AAC3D,QAAM,UAAU,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI;AAEhE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpB,oBAAoB,oBAAkC,QAAQ,GAAG;AAAA,IACjE,oBAAoB,qBAAmC,QAAQ,GAAG;AAAA,IAClE,cAAc,QAAQ,GAAG;AAAA,IACzB,oBAAoB,oBAAkC,SAAS,GAAG;AAAA,IAClE,oBAAoB,qBAAmC,SAAS,GAAG;AAAA,IACnE,cAAc,SAAS,GAAG;AAAA,EAC5B,CAAC;AAED,SAAO,EAAE,KAAK;AAAA,IACZ,WAAW,IAAI,YAAY;AAAA,IAC3B,aAAa;AAAA,MACX,cAAc,WAAW,OAAO;AAAA,MAChC,aAAa,UAAU,OAAO;AAAA,MAC9B,cAAc,WAAW,SAAS;AAAA,MAClC,YAAY,UAAU,SAAS;AAAA,IACjC;AAAA,IACA,WAAW;AAAA,MACT,cAAc,YAAY,OAAO;AAAA,MACjC,aAAa,WAAW,OAAO;AAAA,MAC/B,cAAc,YAAY,SAAS;AAAA,MACnC,YAAY,WAAW,SAAS;AAAA,IAClC;AAAA,EACF,CAAC;AACH,CAAC;AAED,IAAO,kBAAQ;;;AC9Mf,SAAS,QAAAC,cAAY;AAErB,IAAM,YAAY,IAAIA,OAAK;AAG3B,UAAU,IAAI,YAAY,OAAO,MAAM;AACrC,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,qBAAgB;AACxD,UAAM,WAAW,eAAe;AAChC,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,KAAK,EAAE,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;AAAA,IACrF;AAEA,UAAM,SAAS,SAAS,gBAAgB;AACxC,UAAM,UAAU,OAAO,IAAI,CAAC,OAAY;AAAA,MACtC,IAAI,EAAE,QAAQ,MAAM;AAAA,MACpB,MAAM,EAAE,QAAQ,QAAQ,EAAE,YAAY,QAAQ,EAAE,QAAQ,MAAM;AAAA,MAC9D,WAAW,EAAE,QAAQ,aAAa;AAAA,MAClC,SAAS,EAAE,QAAQ,WAAW;AAAA,MAC9B,QAAQ,EAAE,UAAU;AAAA,MACpB,eAAe,EAAE,YAAY,WAAW;AAAA,MACxC,WAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS;AAAA,MACrD,OAAO,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,MAAM,IAAI,CAAC,OAAY;AAAA,QACvD,MAAM,EAAE;AAAA,QACR,aAAa,EAAE,eAAe;AAAA,MAChC,EAAE,IAAI,CAAC;AAAA,MACP,WAAW,EAAE,aAAa;AAAA,MAC1B,cAAc,EAAE,gBAAgB;AAAA,MAChC,SAAS,EAAE,QAAQ,WAAW;AAAA,MAC9B,MAAM,EAAE,QAAQ,QAAQ,CAAC;AAAA,IAC3B,EAAE;AAEF,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS;AAAA,MACT,gBAAgB,SAAS;AAAA,MACzB,gBAAgB,SAAS;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;AAAA,EACrF;AACF,CAAC;AAGD,UAAU,KAAK,wBAAwB,OAAO,MAAM;AAClD,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,qBAAgB;AACxD,UAAM,WAAW,eAAe;AAChC,QAAI,CAAC,SAAU,QAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAClE,UAAM,SAAS,gBAAgB;AAC/B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,oBAAoB,GAAG,GAAG;AAAA,EACnE;AACF,CAAC;AAED,IAAO,cAAQ;;;ACxDf,SAAS,QAAAC,cAAY;AACrB,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,eAAe;AAExB,IAAM,aAAa,IAAIA,OAAK;AAG5B,IAAM,aASA;AAAA,EACJ,UAAU;AAAA,IACR,EAAE,KAAK,YAAY,QAAQ,sBAAsB,OAAO,aAAa,MAAM,YAAY,aAAa,yBAAyB,MAAM,mCAAmC,UAAU,KAAK;AAAA,IACrL,EAAE,KAAK,UAAU,QAAQ,oBAAoB,OAAO,WAAW,MAAM,QAAQ,aAAa,kBAAkB,MAAM,uCAAuC;AAAA,EAC3J;AAAA,EACA,SAAS;AAAA,IACP,EAAE,KAAK,YAAY,QAAQ,qBAAqB,OAAO,aAAa,MAAM,YAAY,aAAa,WAAW,MAAM,uCAAuC,UAAU,KAAK;AAAA,IAC1K,EAAE,KAAK,YAAY,QAAQ,qBAAqB,OAAO,aAAa,MAAM,QAAQ,aAAa,sBAAsB,MAAM,+CAA+C;AAAA,IAC1K,EAAE,KAAK,WAAW,QAAQ,oBAAoB,OAAO,qBAAqB,MAAM,QAAQ,aAAa,sBAAsB,MAAM,sCAAsC;AAAA,IACvK,EAAE,KAAK,kBAAkB,QAAQ,4BAA4B,OAAO,oBAAoB,MAAM,QAAQ,aAAa,eAAe,MAAM,mCAAmC;AAAA,IAC3K,EAAE,KAAK,kBAAkB,QAAQ,4BAA4B,OAAO,oBAAoB,MAAM,QAAQ,aAAa,WAAW,MAAM,mCAAmC;AAAA,EACzK;AAAA,EACA,OAAO;AAAA,IACL,EAAE,KAAK,YAAY,QAAQ,mBAAmB,OAAO,aAAa,MAAM,YAAY,aAAa,YAAY,MAAM,wCAAwC,UAAU,KAAK;AAAA,IAC1K,EAAE,KAAK,iBAAiB,QAAQ,wBAAwB,OAAO,kBAAkB,MAAM,YAAY,aAAa,aAAa,MAAM,sCAAsC,UAAU,KAAK;AAAA,IACxL,EAAE,KAAK,YAAY,QAAQ,mBAAmB,OAAO,aAAa,MAAM,YAAY,aAAa,YAAY,MAAM,4DAAuD;AAAA,IAC1K,EAAE,KAAK,cAAc,QAAQ,qBAAqB,OAAO,eAAe,MAAM,WAAW,MAAM,uCAAuC;AAAA,IACtI,EAAE,KAAK,QAAQ,QAAQ,cAAc,OAAO,QAAQ,MAAM,UAAU,aAAa,QAAQ,MAAM,gDAAgD;AAAA,IAC/I,EAAE,KAAK,kBAAkB,QAAQ,0BAA0B,OAAO,oBAAoB,MAAM,QAAQ,aAAa,iBAAiB,MAAM,iCAAiC;AAAA,IACzK,EAAE,KAAK,qBAAqB,QAAQ,6BAA6B,OAAO,uBAAuB,MAAM,QAAQ,aAAa,iBAAiB,MAAM,oCAAoC;AAAA,EACvL;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,WAAW,QAAQ,oBAAoB,OAAO,WAAW,MAAM,WAAW,MAAM,uBAAuB,UAAU,KAAK;AAAA,IAC7H,EAAE,KAAK,WAAW,QAAQ,qBAAqB,OAAO,kBAAkB,MAAM,QAAQ,aAAa,mBAAmB,MAAM,gCAAgC;AAAA,IAC5J,EAAE,KAAK,kBAAkB,QAAQ,4BAA4B,OAAO,mBAAmB,MAAM,QAAQ,aAAa,2BAA2B,MAAM,gCAAgC;AAAA,EACrL;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,KAAK,WAAW,QAAQ,kBAAkB,OAAO,WAAW,MAAM,WAAW,MAAM,qBAAqB,UAAU,KAAK;AAAA,IACzH,EAAE,KAAK,eAAe,QAAQ,uBAAuB,OAAO,gBAAgB,MAAM,QAAQ,aAAa,eAAe,MAAM,kCAAkC,UAAU,KAAK;AAAA,IAC7K,EAAE,KAAK,WAAW,QAAQ,mBAAmB,OAAO,YAAY,MAAM,QAAQ,aAAa,cAAc,MAAM,4BAA4B;AAAA,IAC3I,EAAE,KAAK,kBAAkB,QAAQ,0BAA0B,OAAO,mBAAmB,MAAM,QAAQ,aAAa,2BAA2B,MAAM,gCAAgC;AAAA,EACnL;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,WAAW,QAAQ,oBAAoB,OAAO,WAAW,MAAM,WAAW,MAAM,oCAAoC,UAAU,KAAK;AAAA,IAC1I,EAAE,KAAK,QAAQ,QAAQ,iBAAiB,OAAO,QAAQ,MAAM,UAAU,SAAS,CAAC,eAAe,aAAa,GAAG,MAAM,8CAA8C;AAAA,IACpK,EAAE,KAAK,kBAAkB,QAAQ,4BAA4B,OAAO,mBAAmB,MAAM,QAAQ,aAAa,yBAAyB,MAAM,yBAAyB;AAAA,IAC1K,EAAE,KAAK,uBAAuB,QAAQ,iCAAiC,OAAO,wBAAwB,MAAM,YAAY,MAAM,8BAA8B;AAAA,IAC5J,EAAE,KAAK,kBAAkB,QAAQ,4BAA4B,OAAO,mBAAmB,MAAM,QAAQ,aAAa,2BAA2B,MAAM,gCAAgC;AAAA,EACrL;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,KAAK,WAAW,QAAQ,kBAAkB,OAAO,WAAW,MAAM,WAAW,MAAM,qBAAqB,UAAU,KAAK;AAAA,IACzH,EAAE,KAAK,iBAAiB,QAAQ,yBAAyB,OAAO,kBAAkB,MAAM,QAAQ,aAAa,sBAAsB,MAAM,yBAAyB,UAAU,KAAK;AAAA,IACjL,EAAE,KAAK,eAAe,QAAQ,uBAAuB,OAAO,gBAAgB,MAAM,YAAY,MAAM,uBAAuB,UAAU,KAAK;AAAA,IAC1I,EAAE,KAAK,UAAU,QAAQ,kBAAkB,OAAO,WAAW,MAAM,QAAQ,aAAa,mBAAmB,MAAM,uBAAuB;AAAA,IACxI,EAAE,KAAK,YAAY,QAAQ,oBAAoB,OAAO,mBAAmB,MAAM,WAAW,MAAM,wCAAwC;AAAA,IACxI,EAAE,KAAK,cAAc,QAAQ,sBAAsB,OAAO,kBAAkB,MAAM,WAAW,MAAM,+BAA+B;AAAA,IAClI,EAAE,KAAK,kBAAkB,QAAQ,2BAA2B,OAAO,oBAAoB,MAAM,QAAQ,aAAa,sBAAsB,MAAM,2BAA2B;AAAA,EAC3K;AACF;AAEA,SAAS,iBAAyB;AAChC,SAAO,QAAQ,QAAQ,IAAI,GAAG,MAAM;AACtC;AAEA,SAAS,eAAoC;AAC3C,QAAM,UAAU,eAAe;AAC/B,QAAM,OAAO,oBAAI,IAAoB;AACrC,MAAI,CAAC,WAAW,OAAO,EAAG,QAAO;AACjC,QAAM,UAAU,aAAa,SAAS,OAAO;AAC7C,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,UAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,QAAI,UAAU,GAAI;AAClB,UAAM,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE,KAAK;AACzC,QAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAE,KAAK;AAExC,QAAK,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,KAAO,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAI;AAC5F,YAAM,IAAI,MAAM,GAAG,EAAE;AAAA,IACvB;AACA,SAAK,IAAI,KAAK,GAAG;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,cAAc,SAAuC;AAC5D,QAAM,UAAU,eAAe;AAC/B,MAAI,UAAU,WAAW,OAAO,IAAI,aAAa,SAAS,OAAO,IAAI;AACrE,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAM,UAAU,MAAM,UAAU,OAAK;AACnC,YAAM,UAAU,EAAE,KAAK;AACvB,aAAO,CAAC,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,MAAM,GAAG;AAAA,IACjE,CAAC;AACD,UAAM,UAAU,GAAG,GAAG,IAAI,KAAK;AAC/B,QAAI,WAAW,GAAG;AAChB,YAAM,OAAO,IAAI;AAAA,IACnB,OAAO;AACL,YAAM,KAAK,OAAO;AAAA,IACpB;AAAA,EACF;AAEA,gBAAc,SAAS,MAAM,KAAK,IAAI,GAAG,OAAO;AAClD;AAGA,WAAW,IAAI,WAAW,OAAO,MAAM;AACrC,MAAI;AACF,UAAM,EAAE,KAAAC,KAAI,IAAI,MAAM,OAAO,mBAAqB;AAElD,UAAM,OAAO;AAAA,MACX;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI;AAAA,QACf,QAAQ;AAAA,UACN,QAAQA,KAAI,mBAAmB,OAAO;AAAA,QACxC;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI;AAAA,QACf,QAAQ;AAAA,UACN,SAASA,KAAI,oBAAoB;AAAA,UACjC,UAAUA,KAAI,oBAAoB,OAAO;AAAA,UACzC,cAAcA,KAAI,2BACdA,KAAI,yBAAyB,MAAM,GAAG,EAAE,SACxC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI,mBAAmB,CAAC,CAACA,KAAI;AAAA,QACxC,QAAQ;AAAA,UACN,YAAYA,KAAI,qBAAqB;AAAA,UACrC,MAAMA,KAAI,cAAc;AAAA,UACxB,cAAcA,KAAI,yBACdA,KAAI,uBAAuB,MAAM,GAAG,EAAE,SACtC;AAAA,UACJ,iBAAiBA,KAAI,4BACjBA,KAAI,0BAA0B,MAAM,GAAG,EAAE,SACzC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI;AAAA,QACf,QAAQ;AAAA,UACN,gBAAgBA,KAAI,2BAChBA,KAAI,yBAAyB,MAAM,GAAG,EAAE,SACxC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI,kBAAkB,CAAC,CAACA,KAAI;AAAA,QACvC,QAAQ;AAAA,UACN,gBAAgB,CAAC,CAACA,KAAI;AAAA,UACtB,gBAAgBA,KAAI,yBAChBA,KAAI,uBAAuB,MAAM,GAAG,EAAE,SACtC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI;AAAA,QACf,QAAQ;AAAA,UACN,MAAMA,KAAI,iBAAiB;AAAA,UAC3B,gBAAgBA,KAAI,2BAChBA,KAAI,yBAAyB,MAAM,GAAG,EAAE,SACxC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,CAAC,CAACA,KAAI,kBAAkB,CAAC,CAACA,KAAI,yBAAyB,CAAC,CAACA,KAAI;AAAA,QACtE,QAAQ;AAAA,UACN,YAAYA,KAAI,yBAAyB;AAAA,UACzC,QAAQA,KAAI,kBAAkB;AAAA,UAC9B,UAAUA,KAAI,oBAAoB;AAAA,UAClC,YAAYA,KAAI,sBAAsB;AAAA,UACtC,cAAcA,KAAI,0BACdA,KAAI,wBAAwB,MAAM,GAAG,EAAE,SACvC;AAAA,QACN;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,OAAO,OAAK,EAAE,OAAO,EAAE;AAEjD,WAAO,EAAE,KAAK,EAAE,MAAM,cAAc,YAAY,KAAK,OAAO,CAAC;AAAA,EAC/D,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,cAAc,GAAG,YAAY,EAAE,CAAC;AAAA,EAC5D;AACF,CAAC;AAGD,WAAW,IAAI,WAAW,CAAC,MAAM;AAC/B,SAAO,EAAE,KAAK,UAAU;AAC1B,CAAC;AAGD,WAAW,IAAI,eAAe,OAAO,MAAM;AACzC,QAAM,QAAQ,EAAE,IAAI,MAAM,IAAI;AAC9B,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,CAAC,OAAQ,QAAO,EAAE,KAAK,EAAE,OAAO,cAAc,GAAG,GAAG;AAExD,QAAM,UAAU,aAAa;AAC7B,QAAM,SAAiC,CAAC;AAExC,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,QAAQ,IAAI,MAAM,MAAM,KAAK;AACzC,QAAI,MAAM,SAAS,cAAc,KAAK;AAEpC,aAAO,MAAM,GAAG,IAAI,IAAI,SAAS,KAC7B,IAAI,MAAM,GAAG,CAAC,IAAI,QAAQ,IAAI,MAAM,EAAE,IACtC;AAAA,IACN,OAAO;AACL,aAAO,MAAM,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,EAAE,OAAO,QAAQ,OAAO,CAAC;AACzC,CAAC;AAGD,WAAW,IAAI,eAAe,OAAO,MAAM;AACzC,QAAM,QAAQ,EAAE,IAAI,MAAM,IAAI;AAC9B,QAAM,SAAS,WAAW,KAAK;AAC/B,MAAI,CAAC,OAAQ,QAAO,EAAE,KAAK,EAAE,OAAO,cAAc,GAAG,GAAG;AAExD,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAA6B;AACtD,UAAM,UAAkC,CAAC;AAEzC,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,OAAO,MAAM;AACrB,YAAI,MAAM,KAAK,MAAM,GAAG;AAExB,YAAI,MAAM,SAAS,eAAe,IAAI,SAAS,KAAK,KAAK,QAAQ,QAAS;AAC1E,gBAAQ,MAAM,MAAM,IAAI;AAAA,MAC1B;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,oBAAc,OAAO;AAAA,IACvB;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,SAAS,OAAO,KAAK,OAAO,EAAE,QAAQ,MAAM,8CAA8C,CAAC;AAAA,EAC5H,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,0BAA0B,GAAG,GAAG;AAAA,EACzE;AACF,CAAC;AAED,IAAO,eAAQ;;;ACzRf,SAAS,QAAAC,cAAY;AAErB,IAAM,cAAc,IAAIA,OAAK;AAG7B,YAAY,IAAI,KAAK,OAAO,MAAM;AAChC,MAAI;AACF,UAAM,EAAE,YAAY,IAAI,MAAM,OAAO,0BAAqC;AAC1E,UAAMC,SAAQ,MAAM,YAAY,CAAC,CAAC;AAClC,WAAO,EAAE,KAAKA,MAAK;AAAA,EACrB,QAAQ;AACN,WAAO,EAAE,KAAK,CAAC,CAAC;AAAA,EAClB;AACF,CAAC;AAGD,YAAY,KAAK,KAAK,OAAO,MAAM;AACjC,MAAI;AACF,UAAM,EAAE,OAAAC,QAAO,MAAM,KAAK,IAAI,MAAM,EAAE,IAAI,KAIvC;AAEH,QAAI,CAACA,QAAO;AACV,aAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,IACnD;AAEA,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,0BAAqC;AACzE,UAAM,OAAO,MAAM,WAAW;AAAA,MAC5B,OAAAA;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,WAAO,EAAE,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,YAAY,IAAI,QAAQ,OAAO,MAAM;AACnC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,UAAU,MAAM,EAAE,IAAI,KAAK;AAEjC,QAAI,QAAQ,WAAW,aAAa;AAClC,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,0BAAqC;AAC1E,YAAM,YAAY,IAAI,yBAAyB;AAC/C,aAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,IACjC;AAEA,QAAI,QAAQ,WAAW,UAAU;AAC/B,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,0BAAqC;AAC7E,YAAM,eAAe,EAAE;AACvB,aAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,IACjC;AAEA,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,0BAAqC;AACzE,UAAM,WAAW,IAAI,OAAO;AAC5B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,YAAY,OAAO,QAAQ,OAAO,MAAM;AACtC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,EAAE,WAAW,IAAI,MAAM,OAAO,0BAAqC;AACzE,UAAM,WAAW,EAAE;AACnB,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAO,gBAAQ;;;AlByrBf,SAAS,cAAc;AACvB,SAAS,WAAAC,UAAS,YAAsB;AACxC,SAAS,eAAAC,oBAAmB;AAzwB5B,IAAI;AACJ,IAAI;AAEF,gBAAc,UAAQ,UAAU,EAAE;AACpC,QAAQ;AAEN,gBAAc,MAAM,OAAO,IAAS,SAAc,KAAK;AACzD;AAUA,IAAM,MAAM,IAAIC,OAAK;AAGrB,IAAI,IAAI,KAAK,OAAO,CAAC;AACrB,IAAI,IAAI,UAAU,KAAK,CAAC;AACxB,IAAI,IAAI,UAAU,eAAe,CAAC;AAGlC,IAAI,IAAI,WAAW,CAAC,MAAM;AACxB,SAAO,EAAE,KAAK,EAAE,QAAQ,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AACrE,CAAC;AAKD,IAAI,KAAK,aAAa,OAAO,MAAM;AACjC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAGtB;AAEH,QAAI,CAAC,KAAK,YAAY,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG;AACnD,aAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,IAC5D;AAEA,UAAM,WAAW,MAAM,KAAK,KAAK,UAAU,KAAK,YAAY;AAE5D,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,mBAAmB,KAAK;AACtC,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,IAAI,KAAK,mBAAmB,kBAAkB,YAAmB,GAAG,OAAO,MAAM;AAC/E,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAGtB;AAEH,QAAI,CAAC,KAAK,YAAY,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG;AACnD,aAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,IAC5D;AAEA,UAAM,YAAsB,CAAC;AAC7B,UAAM,WAAW,MAAM,cAAc,KAAK,UAAU,KAAK,QAAQ,CAAC,SAAS;AACzE,gBAAU,KAAK,IAAI;AAAA,IACrB,CAAC;AAED,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,8BAA8B,KAAK;AACjD,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,IAAI,KAAK,YAAY,OAAO,MAAM;AAChC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,IACrD;AAEA,UAAMC,YAAsB,CAAC,EAAE,MAAM,QAAQ,SAAS,KAAK,QAAQ,CAAC;AAEpE,UAAM,WAAW,KAAK,WAClB,MAAM,cAAcA,SAAQ,IAC5B,MAAM,KAAKA,WAAU,KAAK,YAAY;AAE1C,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB,cAAc,SAAS;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAID,IAAI,IAAI,sBAAsB,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,SAAS,MAAM,GAClB,OAAO,EACP,KAAK,aAAa,EAClB,QAAQC,MAAK,cAAc,SAAS,CAAC,EACrC,MAAM,EAAE;AAEX,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAI,IAAI,0BAA0B,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,QAAQ,MAAM,GACjB,OAAO,EACP,KAAK,aAAa,EAClB,MAAMC,IAAG,cAAc,IAAI,EAAE,CAAC,EAC9B,MAAM,CAAC;AAEV,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,EAAE,KAAK,EAAE,OAAO,yBAAyB,GAAG,GAAG;AAAA,IACxD;AAEA,UAAM,OAAO,MAAM,GAChB,OAAO,EACP,KAAK,QAAQ,EACb,MAAMA,IAAG,SAAS,gBAAgB,EAAE,CAAC,EACrC,QAAQ,SAAS,SAAS;AAG7B,UAAM,gBAAgB,KAAK,IAAI,CAAC,MAAM;AACpC,UAAK,EAAU,aAAa,EAAE,SAAS;AACrC,YAAI;AACF,iBAAO,EAAE,GAAG,GAAG,SAAS,aAAa,EAAE,OAAO,KAAK,EAAE,QAAQ;AAAA,QAC/D,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAED,WAAO,EAAE,KAAK,EAAE,cAAc,MAAM,CAAC,GAAG,UAAU,cAAc,CAAC;AAAA,EACnE,SAAS,OAAO;AACd,YAAQ,MAAM,gCAAgC,KAAK;AACnD,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAID,IAAI,IAAI,iBAAiB,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,SAAS,EAAE,IAAI,MAAM,QAAQ;AACnC,UAAM,QAAQ,SAAS,EAAE,IAAI,MAAM,OAAO,KAAK,IAAI;AAEnD,QAAI,QAAQ,GAAG,OAAO,EAAE,KAAK,QAAQ,EAAE,QAAQD,MAAK,SAAS,SAAS,CAAC,EAAE,MAAM,KAAK;AAEpF,UAAM,OAAO,MAAM;AACnB,WAAO,EAAE,KAAK,IAAI;AAAA,EACpB,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAI,KAAK,wBAAwB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAAyD;AAElF,QAAI,CAAC,KAAK,OAAO;AACf,aAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,IACnD;AAEA,UAAM,UAAU,MAAM,eAAe,KAAK,OAAO,KAAK,QAAQ,KAAK,SAAS,CAAC;AAC7E,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAI,KAAK,iBAAiB,OAAO,MAAM;AACrC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAKtB;AAEH,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAAA,IACrD;AAEA,UAAM,SAAS,MAAM,YAAY;AAAA,MAC/B,SAAS,KAAK;AAAA,MACd,MAAM,KAAK,QAAQ;AAAA,MACnB,YAAY,KAAK,cAAc;AAAA,MAC/B,QAAQ,KAAK;AAAA,MACb,QAAQ;AAAA,MACR,YAAY;AAAA,IACd,CAAC;AAED,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,yBAAyB,KAAK;AAC5C,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,IAAI,IAAI,wBAAwB,OAAO,MAAM;AAC3C,MAAI;AACF,UAAM,SAAS,EAAE,IAAI,MAAM,QAAQ;AACnC,UAAM,SAAU,EAAE,IAAI,MAAM,QAAQ,KAAK;AAEzC,UAAM,WAAW,MAAM,eAAe,UAAU,QAAW,MAAM;AAEjE,QAAI,WAAW,QAAQ;AACrB,aAAO,EAAE,KAAK,KAAK,MAAM,QAAQ,CAAC;AAAA,IACpC;AAEA,WAAO,EAAE,KAAK,QAAQ;AAAA,EACxB,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAED,IAAI,IAAI,qBAAqB,OAAO,MAAM;AACxC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,SAAS,MAAM,cAAc,EAAE;AAErC,QAAI,CAAC,QAAQ;AACX,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,YAAQ,MAAM,0BAA0B,KAAK;AAC7C,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,IAAI,IAAI,qBAAqB,OAAO,MAAM;AACxC,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,OAAO,MAAM,EAAE,IAAI,KAItB;AAEH,UAAM,UAAU,MAAM,aAAa,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,KAAK,EAAE,OAAO,iCAAiC,GAAG,GAAG;AAAA,IAChE;AAEA,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,SAAS,OAAO;AACd,YAAQ,MAAM,0BAA0B,KAAK;AAC7C,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAGD,IAAI,OAAO,qBAAqB,kBAAkB,iBAAwB,GAAG,OAAO,MAAM;AACxF,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,UAAU,MAAM,aAAa,EAAE;AAErC,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,GAAG,CAAC;AAAA,EACrC,SAAS,OAAO;AACd,YAAQ,MAAM,0BAA0B,KAAK;AAC7C,WAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,EACvD;AACF,CAAC;AAID,IAAI,IAAI,iBAAiB,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,wBAA8B;AACvE,UAAM,SAAS,EAAE,IAAI,MAAM,QAAQ;AACnC,WAAO,EAAE,KAAK;AAAA,MACZ,OAAO,SAAS,gBAAgB,SAAS,MAAM,IAAI,gBAAgB,gBAAgB;AAAA,MACnF,OAAO,gBAAgB,SAAS;AAAA,IAClC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC/D;AACF,CAAC;AAED,IAAI,IAAI,iBAAiB,OAAO,MAAM;AACpC,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,wBAA8B;AACvE,UAAM,OAAO,MAAM,EAAE,IAAI,KAAyC;AAClE,UAAM,QAAQ,KAAK;AAEnB,QAAI,CAAC,CAAC,YAAY,cAAc,YAAY,EAAE,SAAS,KAAK,GAAG;AAC7D,aAAO,EAAE,KAAK,EAAE,OAAO,8DAA8D,GAAG,GAAG;AAAA,IAC7F;AAEA,QAAI,KAAK,QAAQ;AACf,sBAAgB,SAAS,KAAK,QAAQ,KAAK;AAAA,IAC7C,OAAO;AACL,sBAAgB,gBAAgB,KAAK;AAAA,IACvC;AAEA,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,EACxC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC/D;AACF,CAAC;AAID,IAAI,IAAI,YAAY,OAAO,MAAM;AAC/B,MAAI;AACF,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,0BAAqC;AACjF,UAAM,OAAO,mBAAmB,aAAa;AAC7C,WAAO,EAAE,KAAK,MAAM,KAAK,EAAE,gBAAgB,2CAA2C,CAAC;AAAA,EACzF,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,wCAAwC,GAAG;AAAA,EAC3D;AACF,CAAC;AAED,IAAI,IAAI,2BAA2B,OAAO,MAAM;AAC9C,MAAI;AACF,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,0BAAqC;AACjF,UAAM,OAAO,mBAAmB,aAAa;AAC7C,WAAO,EAAE,KAAK,MAAM,KAAK,EAAE,gBAAgB,2CAA2C,CAAC;AAAA,EACzF,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,wCAAwC,GAAG;AAAA,EAC3D;AACF,CAAC;AAID,IAAI,KAAK,aAAa,OAAO,MAAM;AACjC,MAAI;AACF,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,uBAA6B;AACrE,UAAM,OAAO,MAAM,EAAE,IAAI,KAA4C;AAErE,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,UAAM,SAAS,eAAe,KAAK,KAAK,MAAM,KAAK,cAAc,gBAAgB;AAEjF,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE,KAAK,EAAE,OAAO,OAAO,MAAM,GAAG,GAAG;AAAA,IAC5C;AAEA,WAAO,EAAE,KAAK,EAAE,OAAO,OAAO,MAAM,CAAC;AAAA,EACvC,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG;AAAA,EAC9D;AACF,CAAC;AAID,IAAI,IAAI,kBAAkB,OAAO,MAAM;AACrC,MAAI;AACF,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,yBAAsB;AAChE,WAAO,EAAE,KAAK;AAAA,MACZ,WAAW,iBAAiB,cAAc;AAAA,MAC1C,SAAS,iBAAiB,aAAa;AAAA,IACzC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC/D;AACF,CAAC;AAID,IAAI,MAAM,cAAc,KAAW;AAGnC,IAAI,MAAM,cAAc,KAAW;AAInC,IAAI,MAAM,YAAY,SAAS;AAI/B,IAAI,MAAM,cAAc,aAAW;AAGnC,IAAI,IAAI,mBAAmB,OAAO,MAAM;AACtC,MAAI;AACF,UAAM,EAAE,gBAAAE,gBAAe,IAAI,MAAM,OAAO,4BAAkC;AAC1E,UAAM,MAAM,IAAI,IAAI,EAAE,IAAI,GAAG;AAC7B,UAAM,UAAmC,CAAC;AAC1C,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAI,OAAQ,SAAQ,SAAS;AAC7B,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAI,OAAQ,SAAQ,SAAS;AAC7B,UAAM,WAAW,IAAI,aAAa,IAAI,UAAU;AAChD,QAAI,SAAU,SAAQ,WAAW;AACjC,UAAM,YAAY,IAAI,aAAa,IAAI,WAAW;AAClD,QAAI,UAAW,SAAQ,YAAY,IAAI,KAAK,SAAS;AACrD,UAAM,UAAU,IAAI,aAAa,IAAI,SAAS;AAC9C,QAAI,QAAS,SAAQ,UAAU,IAAI,KAAK,OAAO;AAC/C,UAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,QAAI,MAAO,SAAQ,QAAQ,SAAS,KAAK;AACzC,UAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;AAC5C,QAAI,OAAQ,SAAQ,SAAS,SAAS,MAAM;AAC5C,UAAM,OAAO,MAAMA,gBAAe,OAAc;AAChD,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,KAAK,CAAC;AAAA,EACvC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,SAAS,OAAO,OAAO,KAAK,WAAW,8BAA8B,MAAM,CAAC,EAAE,CAAC;AAAA,EACjG;AACF,CAAC;AAED,IAAI,IAAI,6BAA6B,OAAO,MAAM;AAChD,MAAI;AACF,UAAM,EAAE,wBAAAC,wBAAuB,IAAI,MAAM,OAAO,4BAAkC;AAClF,UAAM,YAAY,MAAMA,wBAAuB;AAC/C,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,GAAG,UAAU,CAAC;AAAA,EAC/C,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,SAAS,OAAO,OAAO,KAAK,SAAS,YAAY,OAAO,cAAc,GAAG,cAAc,EAAE,CAAC;AAAA,EAC5G;AACF,CAAC;AAKD,IAAI,OAAO,mBAAmB,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAiB;AACpD,UAAM,GAAG,OAAO,SAAS;AACzB,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,6BAA6B,GAAG,GAAG;AAAA,EAC5E;AACF,CAAC;AAGD,IAAI,OAAO,sBAAsB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAM,GAAG,OAAO,QAAQ;AACxB,UAAM,GAAG,OAAO,aAAa;AAC7B,WAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EACjC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,2BAA2B,GAAG,GAAG;AAAA,EAC1E;AACF,CAAC;AAGD,IAAI,OAAO,0BAA0B,OAAO,MAAM;AAChD,MAAI;AACF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,QAAQ,MAAM,GACjB,OAAO,EACP,KAAK,aAAa,EAClB,MAAMF,IAAG,cAAc,IAAI,EAAE,CAAC,EAC9B,MAAM,CAAC;AAEV,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,EAAE,KAAK,EAAE,OAAO,yBAAyB,GAAG,GAAG;AAAA,IACxD;AAEA,UAAM,GAAG,OAAO,QAAQ,EAAE,MAAMA,IAAG,SAAS,gBAAgB,EAAE,CAAC;AAC/D,UAAM,GAAG,OAAO,aAAa,EAAE,MAAMA,IAAG,cAAc,IAAI,EAAE,CAAC;AAC7D,WAAO,EAAE,KAAK,EAAE,SAAS,MAAM,GAAG,CAAC;AAAA,EACrC,SAAS,KAAU;AACjB,WAAO,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,gCAAgC,GAAG,GAAG;AAAA,EAC/E;AACF,CAAC;AAID,IAAI,MAAM,cAAc,aAAW;AAInC,IAAI,MAAM,kBAAkB,iBAAe;AAI3C,IAAI,MAAM,eAAe,cAAY;AAIrC,IAAI,MAAM,iBAAiB,gBAAc;AAIzC,IAAI,MAAM,eAAe,cAAY;AAIrC,IAAI,MAAM,gBAAgB,eAAa;AAGvC,IAAI,IAAI,yBAAyB,OAAO,MAAM;AAC5C,MAAI;AACF,UAAM,EAAE,qBAAAG,qBAAoB,IAAI,MAAM,OAAO,uBAAkC;AAC/E,UAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,6BAAwC;AAC/E,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,SAAS,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,KAAK,KAAK,GAAI;AAC3D,UAAM,UAAU,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI;AAEhE,UAAM,CAAC,YAAY,UAAU,WAAW,WAAW,WAAW,UAAU,IAAI,MAAM,QAAQ,WAAW;AAAA,MACnGD,qBAAoB,oBAA2B,QAAQ,GAAG;AAAA,MAC1DA,qBAAoB,qBAA4B,QAAQ,GAAG;AAAA,MAC3DA,qBAAoB,sBAA6B,QAAQ,GAAG;AAAA,MAC5DC,eAAc,QAAQ,GAAG;AAAA,MACzBD,qBAAoB,qBAA4B,SAAS,GAAG;AAAA,MAC5DA,qBAAoB,sBAA6B,SAAS,GAAG;AAAA,IAC/D,CAAC;AAED,UAAM,MAAM,CAAC,GAA8B,QACzC,EAAE,WAAW,cAAe,EAAE,QAAQ,GAAG,KAAK,IAAK;AAErD,WAAO,EAAE,KAAK;AAAA,MACZ,SAAS;AAAA,QACP,aAAa,IAAI,UAAU,KAAK;AAAA,QAChC,cAAc,IAAI,WAAW,KAAK;AAAA,QAClC,UAAU,IAAI,YAAY,OAAO;AAAA,QACjC,cAAc,IAAI,YAAY,KAAK;AAAA,QACnC,QAAQ,UAAU,WAAW,cAAe,UAAU,OAAO,SAAS,IAAK;AAAA,MAC7E;AAAA,MACA,QAAQ;AAAA,QACN,aAAa,IAAI,WAAW,KAAK;AAAA,QACjC,cAAc,IAAI,YAAY,KAAK;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;AAAA,EAC3C;AACF,CAAC;AAID,IAAI,MAAM,YAAY,WAAS;AAI/B,IAAI,MAAM,aAAa,YAAU;AAIjC,IAAI,MAAM,cAAc,aAAW;AAInC,IAAI,IAAI,kBAAkB,kBAAkB,gBAAuB,GAAG,OAAO,MAAM;AACjF,MAAI;AACF,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,iCAAuC;AACjF,UAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AACvC,UAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAC/B,UAAM,YAAY,MAAM,iBAAiB,EAAE,UAAU,MAAM,OAAO,GAAG,CAAC;AACtE,WAAO,EAAE,KAAK,SAAS;AAAA,EACzB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC/D;AACF,CAAC;AAED,IAAI,IAAI,sBAAsB,kBAAkB,gBAAuB,GAAG,OAAO,MAAM;AACrF,MAAI;AACF,UAAM,EAAE,uBAAuB,IAAI,MAAM,OAAO,iCAAuC;AACvF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,SAAS,MAAM,uBAAuB,EAAE;AAC9C,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AAAA,EACpD;AACF,CAAC;AAED,IAAI,KAAK,6BAA6B,kBAAkB,gBAAuB,GAAG,OAAO,MAAM;AAC7F,MAAI;AACF,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,iCAAuC;AACrF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,OAAO,MAAM,EAAE,IAAI,KAAyC;AAClE,UAAM,SAAS,cAAc,CAAC;AAC9B,UAAM,UAAU,MAAM,qBAAqB,IAAI,KAAK,QAAe,QAAQ,KAAK,KAAK;AACrF,WAAO,EAAE,KAAK,OAAO;AAAA,EACvB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,4BAA4B,GAAG,GAAG;AAAA,EAC3D;AACF,CAAC;AAED,IAAI,KAAK,8BAA8B,kBAAkB,gBAAuB,GAAG,OAAO,MAAM;AAC9F,MAAI;AACF,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,iCAAuC;AAChF,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI;AAC3B,UAAM,OAAO,MAAM,EAAE,IAAI,KAAwB;AACjD,UAAM,SAAS,cAAc,CAAC;AAC9B,UAAM,WAAW,MAAM,gBAAgB,IAAI,KAAK,OAAO,MAAM;AAC7D,WAAO,EAAE,KAAK,QAAQ;AAAA,EACxB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,EAC5D;AACF,CAAC;AAID,IAAI,IAAI,wBAAwB,kBAAkB,gBAAuB,GAAG,OAAO,MAAM;AACvF,MAAI;AACF,UAAM,EAAE,wBAAAD,wBAAuB,IAAI,MAAM,OAAO,4BAAkC;AAClF,UAAM,YAAY,MAAMA,wBAAuB;AAC/C,WAAO,EAAE,KAAK,SAAS;AAAA,EACzB,SAAS,OAAO;AACd,WAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,EAC5D;AACF,CAAC;AAID,IAAI,KAAK,mBAAmB,OAAO,MAAM;AACvC,MAAI;AACF,UAAM,WAAW,MAAM,EAAE,IAAI,SAAS;AACtC,UAAM,YAAY,SAAS,IAAI,OAAO;AAEtC,QAAI,CAAC,aAAa,EAAE,qBAAqB,OAAO;AAC9C,aAAO,EAAE,KAAK,EAAE,OAAO,yBAAyB,GAAG,GAAG;AAAA,IACxD;AAEA,UAAM,SAAS,OAAO,KAAK,MAAM,UAAU,YAAY,CAAC;AACxD,UAAM,OAAO,MAAM,gBAAgB,MAAM;AAEzC,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAAA,IAC5D;AAEA,WAAO,EAAE,KAAK,EAAE,KAAK,CAAC;AAAA,EACxB,SAAS,OAAO;AACd,YAAQ,MAAM,yBAAyB,KAAK;AAC5C,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAED,IAAI,KAAK,YAAY,OAAO,MAAM;AAChC,MAAI;AACF,UAAM,OAAO,MAAM,EAAE,IAAI,KAAuB;AAEhD,QAAI,CAAC,KAAK,MAAM;AACd,aAAO,EAAE,KAAK,EAAE,OAAO,mBAAmB,GAAG,GAAG;AAAA,IAClD;AAEA,UAAM,cAAc,MAAM,aAAa,KAAK,IAAI;AAEhD,QAAI,CAAC,aAAa;AAChB,aAAO,EAAE,KAAK,EAAE,OAAO,wBAAwB,GAAG,GAAG;AAAA,IACvD;AAEA,WAAO,IAAI,SAAS,IAAI,WAAW,WAAW,GAAG;AAAA,MAC/C,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,kBAAkB,OAAO,YAAY,MAAM;AAAA,MAC7C;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,WAAO,EAAE,KAAK,EAAE,OAAO,aAAa,GAAG,GAAG;AAAA,EAC5C;AACF,CAAC;AAID,IAAI,IAAI,sBAAsB,OAAO,MAAM;AACzC,SAAO,EAAE,KAAK;AAAA,IACZ,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ,QAAQ,OAAO;AAAA,IACvB,QAAQ,QAAQ,YAAY;AAAA,EAC9B,CAAC;AACH,CAAC;AAID,IAAI,IAAI,0BAA0B,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAC/B,UAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AAEjC,QAAI,OAAO;AACT,aAAO,EAAE,KAAK,kDAAkD,KAAK,mCAAmC;AAAA,IAC1G;AAEA,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,KAAK,0EAA0E;AAAA,IAC1F;AAEA,UAAM,EAAE,KAAK,OAAO,IAAI,MAAM,OAAO,mBAAkB;AACvD,QAAI,CAAC,OAAO,qBAAqB,CAAC,OAAO,uBAAuB;AAC9D,aAAO,EAAE,KAAK,+FAA+F;AAAA,IAC/G;AAEA,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,oBAAiC;AAC5E,UAAM,OAAO,kBAAkB;AAAA,MAC7B,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO,wBAAwB,oBAAoB,OAAO,IAAI;AAAA,IAC7E,CAAC;AAED,UAAM,SAAS,MAAM,KAAK,aAAa,IAAI;AAE3C,WAAO,EAAE,KAAK;AAAA;AAAA;AAAA;AAAA,mJAIiI,OAAO,YAAY;AAAA;AAAA;AAAA,KAGjK;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,MAAM,2BAA2B,GAAG;AAC5C,WAAO,EAAE,KAAK,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,MAAM;AAAA,EACvG;AACF,CAAC;AAED,IAAI,IAAI,0BAA0B,OAAO,MAAM;AAC7C,MAAI;AACF,UAAM,EAAE,KAAK,OAAO,IAAI,MAAM,OAAO,mBAAkB;AACvD,QAAI,CAAC,OAAO,qBAAqB,CAAC,OAAO,uBAAuB;AAC9D,aAAO,EAAE,KAAK,EAAE,OAAO,kFAAkF,GAAG,GAAG;AAAA,IACjH;AAEA,UAAM,EAAE,mBAAmB,eAAe,IAAI,MAAM,OAAO,oBAAiC;AAC5F,UAAM,OAAO,kBAAkB;AAAA,MAC7B,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,MACrB,aAAa,OAAO,wBAAwB,oBAAoB,OAAO,IAAI;AAAA,IAC7E,CAAC;AAED,UAAM,MAAM,KAAK,oBAAoB,gBAAgB,QAAW,IAAI;AACpE,WAAO,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,EACvB,SAAS,KAAK;AACZ,WAAO,EAAE,KAAK,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,GAAG,GAAG;AAAA,EAChF;AACF,CAAC;AAUD,IAAI,IAAI,8BAA8B,OAAO,MAAM;AACjD,QAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AACjC,QAAM,QAAQ,iBAAiB,KAAK;AACpC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,KAAK,EAAE,OAAO,mCAAmC,GAAG,GAAG;AAAA,EAClE;AAEA,QAAM,MAAMP,SAAQ,OAAO,CAAC;AAC5B,MAAI,CAAC,MAAM,SAAS,WAAW,GAAG,GAAG;AACnC,WAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AAAA,EAC/C;AACA,MAAI;AACF,UAAM,OAAO,IAAI,KAAK,MAAM,QAAQ;AACpC,QAAI,CAAE,MAAM,KAAK,OAAO,GAAI;AAC1B,aAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAAA,IAChD;AACA,WAAO,IAAI,SAAS,MAAM;AAAA,MACxB,SAAS;AAAA,QACP,gBAAgB,MAAM;AAAA,QACtB,uBAAuB,yBAAyB,MAAM,QAAQ;AAAA,MAChE;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,EACtD;AACF,CAAC;AAGD,IAAI,KAAK,qBAAqB,OAAO,MAAM;AACzC,MAAI;AACF,UAAM,WAAW,MAAM,EAAE,IAAI,SAAS;AACtC,UAAM,OAAO,SAAS,IAAI,MAAM;AAChC,QAAI,CAAC,QAAQ,EAAE,gBAAgB,OAAO;AACpC,aAAO,EAAE,KAAK,EAAE,OAAO,yBAAyB,GAAG,GAAG;AAAA,IACxD;AACA,QAAI,KAAK,OAAO,KAAK,OAAO,MAAM;AAChC,aAAO,EAAE,KAAK,EAAE,OAAO,4BAA4B,GAAG,GAAG;AAAA,IAC3D;AACA,UAAM,MAAM,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK;AAC1C,UAAM,KAAKC,aAAY,CAAC,EAAE,SAAS,KAAK;AACxC,UAAM,WAAW,mBAAmB,EAAE,IAAI,GAAG;AAC7C,UAAM,WAAW,KAAK,OAAO,GAAG,QAAQ;AACxC,UAAM,SAAS,OAAO,KAAK,MAAM,KAAK,YAAY,CAAC;AACnD,UAAM,IAAI,MAAM,UAAU,MAAM;AAChC,WAAO,EAAE,KAAK,EAAE,UAAU,cAAc,KAAK,KAAK,CAAC;AAAA,EACrD,QAAQ;AACN,WAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AAAA,EAC/C;AACF,CAAC;AAGD,IAAI,IAAI,MAAM,YAAY,EAAE,MAAM,iBAAiB,CAAC,CAAC;AAGrD,IAAI,IAAI,MAAM,YAAY,EAAE,MAAM,4BAA4B,CAAC,CAAC;","names":["Hono","desc","eq","eq","and","randomBytes","createHash","createHash","and","eq","result","eq","and","and","eq","Hono","Hono","email","Hono","app","Hono","messages","SmtpClient","Hono","Hono","Hono","Hono","memories","db","graphEntities","eq","users","Hono","Hono","Hono","Hono","env","issues","prs","Hono","Hono","Hono","Hono","env","Hono","users","email","resolve","randomBytes","Hono","messages","desc","eq","queryAuditLogs","getAuditChainIntegrity","getMetricAggregates","getErrorStats"]}