@hotmeshio/long-tail 0.1.21 → 0.2.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 (269) hide show
  1. package/build/api/agent-subscriptions.d.ts +15 -0
  2. package/build/api/agent-subscriptions.js +82 -0
  3. package/build/api/agents.d.ts +21 -0
  4. package/build/api/agents.js +100 -0
  5. package/build/api/capabilities.d.ts +2 -0
  6. package/build/api/capabilities.js +76 -0
  7. package/build/index.d.ts +2 -2
  8. package/build/index.js +5 -2
  9. package/build/lib/db/schemas/003_agents.sql +46 -0
  10. package/build/lib/db/schemas/004_agent_subscriptions.sql +38 -0
  11. package/build/lib/db/schemas/005_server_category.sql +6 -0
  12. package/build/lib/db/schemas/006_agent_sub_unique.sql +9 -0
  13. package/build/lib/events/callback.d.ts +4 -18
  14. package/build/lib/events/callback.js +8 -45
  15. package/build/lib/events/matching.d.ts +13 -0
  16. package/build/lib/events/matching.js +31 -0
  17. package/build/lib/events/publish.d.ts +20 -0
  18. package/build/lib/events/publish.js +33 -0
  19. package/build/routes/agents.d.ts +2 -0
  20. package/build/routes/agents.js +130 -0
  21. package/build/routes/capabilities.d.ts +2 -0
  22. package/build/routes/capabilities.js +47 -0
  23. package/build/routes/index.js +4 -0
  24. package/build/sdk/index.d.ts +13 -0
  25. package/build/sdk/index.js +14 -0
  26. package/build/services/agent/index.d.ts +32 -0
  27. package/build/services/agent/index.js +195 -0
  28. package/build/services/agent/input-mapper.d.ts +18 -0
  29. package/build/services/agent/input-mapper.js +51 -0
  30. package/build/services/agent/sql.d.ts +10 -0
  31. package/build/services/agent/sql.js +70 -0
  32. package/build/services/agent/subscription-sql.d.ts +7 -0
  33. package/build/services/agent/subscription-sql.js +49 -0
  34. package/build/services/agent/subscriptions.d.ts +30 -0
  35. package/build/services/agent/subscriptions.js +82 -0
  36. package/build/services/agent/trigger-registry.d.ts +45 -0
  37. package/build/services/agent/trigger-registry.js +232 -0
  38. package/build/services/cron/index.d.ts +17 -1
  39. package/build/services/cron/index.js +152 -4
  40. package/build/services/insight/index.js +11 -6
  41. package/build/services/mcp/db.d.ts +1 -0
  42. package/build/services/mcp/db.js +1 -0
  43. package/build/services/mcp/sql.d.ts +1 -1
  44. package/build/services/mcp/sql.js +2 -2
  45. package/build/start/workers.js +67 -0
  46. package/build/system/activities/knowledge.js +9 -2
  47. package/build/system/index.d.ts +2 -1
  48. package/build/system/index.js +93 -1
  49. package/build/system/mcp-servers/events.d.ts +5 -0
  50. package/build/system/mcp-servers/events.js +104 -0
  51. package/build/system/mcp-servers/playwright/schemas.d.ts +6 -6
  52. package/build/system/seed/tool-manifests-events.d.ts +37 -0
  53. package/build/system/seed/tool-manifests-events.js +30 -0
  54. package/build/tsconfig.tsbuildinfo +1 -1
  55. package/build/types/agent.d.ts +72 -0
  56. package/build/types/agent.js +6 -0
  57. package/build/types/events.d.ts +7 -1
  58. package/build/types/index.d.ts +2 -1
  59. package/build/types/mcp.d.ts +2 -0
  60. package/build/types/startup.d.ts +37 -0
  61. package/dashboard/dist/assets/{AdminDashboard-CsTOErp1.js → AdminDashboard-DThDjhN5.js} +2 -2
  62. package/dashboard/dist/assets/{AdminDashboard-CsTOErp1.js.map → AdminDashboard-DThDjhN5.js.map} +1 -1
  63. package/dashboard/dist/assets/AgentConfigPage-NgxblxBW.js +13 -0
  64. package/dashboard/dist/assets/AgentConfigPage-NgxblxBW.js.map +1 -0
  65. package/dashboard/dist/assets/AgentDetailPage-DMS46nYY.js +4 -0
  66. package/dashboard/dist/assets/AgentDetailPage-DMS46nYY.js.map +1 -0
  67. package/dashboard/dist/assets/AgentsPage-pKfjHe4u.js +2 -0
  68. package/dashboard/dist/assets/AgentsPage-pKfjHe4u.js.map +1 -0
  69. package/dashboard/dist/assets/{AvailableEscalationsPage-BqQA3IJp.js → AvailableEscalationsPage-BFzHVnPh.js} +2 -2
  70. package/dashboard/dist/assets/{AvailableEscalationsPage-BqQA3IJp.js.map → AvailableEscalationsPage-BFzHVnPh.js.map} +1 -1
  71. package/dashboard/dist/assets/BotPicker-Zxf7Npew.js +2 -0
  72. package/dashboard/dist/assets/BotPicker-Zxf7Npew.js.map +1 -0
  73. package/dashboard/dist/assets/CapabilitiesPage-6zOJ12cB.js +2 -0
  74. package/dashboard/dist/assets/CapabilitiesPage-6zOJ12cB.js.map +1 -0
  75. package/dashboard/dist/assets/{CollapsibleSection-CRtHQsAv.js → CollapsibleSection-DvBx4tmw.js} +2 -2
  76. package/dashboard/dist/assets/{CollapsibleSection-CRtHQsAv.js.map → CollapsibleSection-DvBx4tmw.js.map} +1 -1
  77. package/dashboard/dist/assets/{CredentialsPage-C7XT1bnO.js → CredentialsPage-C5f-Bg-o.js} +2 -2
  78. package/dashboard/dist/assets/{CredentialsPage-C7XT1bnO.js.map → CredentialsPage-C5f-Bg-o.js.map} +1 -1
  79. package/dashboard/dist/assets/CronLabel-CAVTt5AG.js +2 -0
  80. package/dashboard/dist/assets/CronLabel-CAVTt5AG.js.map +1 -0
  81. package/dashboard/dist/assets/{CustomDurationPicker-BABUv1V2.js → CustomDurationPicker-Bk7D38y7.js} +2 -2
  82. package/dashboard/dist/assets/{CustomDurationPicker-BABUv1V2.js.map → CustomDurationPicker-Bk7D38y7.js.map} +1 -1
  83. package/dashboard/dist/assets/{DataTable-D3-wSEf0.js → DataTable-D9yuBv0w.js} +2 -2
  84. package/dashboard/dist/assets/{DataTable-D3-wSEf0.js.map → DataTable-D9yuBv0w.js.map} +1 -1
  85. package/dashboard/dist/assets/{DropZone-DHKmMqRA.js → DropZone-2mGyDo1P.js} +2 -2
  86. package/dashboard/dist/assets/{DropZone-DHKmMqRA.js.map → DropZone-2mGyDo1P.js.map} +1 -1
  87. package/dashboard/dist/assets/{ElapsedCell-DrJif03B.js → ElapsedCell-BpJjG1s-.js} +2 -2
  88. package/dashboard/dist/assets/{ElapsedCell-DrJif03B.js.map → ElapsedCell-BpJjG1s-.js.map} +1 -1
  89. package/dashboard/dist/assets/{EscalationsOverview-H6CwfeR-.js → EscalationsOverview-DPNd1vjF.js} +2 -2
  90. package/dashboard/dist/assets/{EscalationsOverview-H6CwfeR-.js.map → EscalationsOverview-DPNd1vjF.js.map} +1 -1
  91. package/dashboard/dist/assets/{EventTable-Dh3_9DAY.js → EventTable-BoP8KC3M.js} +2 -2
  92. package/dashboard/dist/assets/{EventTable-Dh3_9DAY.js.map → EventTable-BoP8KC3M.js.map} +1 -1
  93. package/dashboard/dist/assets/EventTopicPill-BUxxvpNg.js +2 -0
  94. package/dashboard/dist/assets/EventTopicPill-BUxxvpNg.js.map +1 -0
  95. package/dashboard/dist/assets/HomePage-h8I5ZolJ.js +2 -0
  96. package/dashboard/dist/assets/HomePage-h8I5ZolJ.js.map +1 -0
  97. package/dashboard/dist/assets/ListToolbar-BaYIIsAt.js +2 -0
  98. package/dashboard/dist/assets/ListToolbar-BaYIIsAt.js.map +1 -0
  99. package/dashboard/dist/assets/{McpOverview-ChLa6Gl7.js → McpOverview-BhZ3lSO6.js} +2 -2
  100. package/dashboard/dist/assets/{McpOverview-ChLa6Gl7.js.map → McpOverview-BhZ3lSO6.js.map} +1 -1
  101. package/dashboard/dist/assets/McpQueryDetailPage-DVgcKa61.js +5 -0
  102. package/dashboard/dist/assets/McpQueryDetailPage-DVgcKa61.js.map +1 -0
  103. package/dashboard/dist/assets/{McpQueryPage-D2DmDFPu.js → McpQueryPage-CTWOBqKT.js} +2 -2
  104. package/dashboard/dist/assets/{McpQueryPage-D2DmDFPu.js.map → McpQueryPage-CTWOBqKT.js.map} +1 -1
  105. package/dashboard/dist/assets/{McpRunDetailPage-ERVuNEEK.js → McpRunDetailPage-CIpZJWRB.js} +2 -2
  106. package/dashboard/dist/assets/{McpRunDetailPage-ERVuNEEK.js.map → McpRunDetailPage-CIpZJWRB.js.map} +1 -1
  107. package/dashboard/dist/assets/McpRunsPage-B3zpzPBf.js +2 -0
  108. package/dashboard/dist/assets/McpRunsPage-B3zpzPBf.js.map +1 -0
  109. package/dashboard/dist/assets/{OperatorDashboard-CJm_BTPU.js → OperatorDashboard-l2hVlIF3.js} +2 -2
  110. package/dashboard/dist/assets/{OperatorDashboard-CJm_BTPU.js.map → OperatorDashboard-l2hVlIF3.js.map} +1 -1
  111. package/dashboard/dist/assets/{PageHeader-B-SN5GZ2.js → PageHeader-DLjHNYHX.js} +2 -2
  112. package/dashboard/dist/assets/{PageHeader-B-SN5GZ2.js.map → PageHeader-DLjHNYHX.js.map} +1 -1
  113. package/dashboard/dist/assets/{PageHeaderWithStats-BZ3AGT5s.js → PageHeaderWithStats-Oljg3n4j.js} +2 -2
  114. package/dashboard/dist/assets/{PageHeaderWithStats-BZ3AGT5s.js.map → PageHeaderWithStats-Oljg3n4j.js.map} +1 -1
  115. package/dashboard/dist/assets/{ProcessDetailPage-vfnCDyQK.js → ProcessDetailPage-BJ1rhK9_.js} +2 -2
  116. package/dashboard/dist/assets/{ProcessDetailPage-vfnCDyQK.js.map → ProcessDetailPage-BJ1rhK9_.js.map} +1 -1
  117. package/dashboard/dist/assets/{ProcessesListPage-DcAN6AJK.js → ProcessesListPage-IQKk_qkn.js} +2 -2
  118. package/dashboard/dist/assets/{ProcessesListPage-DcAN6AJK.js.map → ProcessesListPage-IQKk_qkn.js.map} +1 -1
  119. package/dashboard/dist/assets/RolePill-Bp10-WfX.js +2 -0
  120. package/dashboard/dist/assets/RolePill-Bp10-WfX.js.map +1 -0
  121. package/dashboard/dist/assets/{RolesPage-DYSt2aAr.js → RolesPage-Dwcirtze.js} +2 -2
  122. package/dashboard/dist/assets/{RolesPage-DYSt2aAr.js.map → RolesPage-Dwcirtze.js.map} +1 -1
  123. package/dashboard/dist/assets/RunAsSelector-D4Fu8LVG.js +2 -0
  124. package/dashboard/dist/assets/RunAsSelector-D4Fu8LVG.js.map +1 -0
  125. package/dashboard/dist/assets/ServerName-C9lUCFYb.js +2 -0
  126. package/dashboard/dist/assets/ServerName-C9lUCFYb.js.map +1 -0
  127. package/dashboard/dist/assets/SwimlaneTimeline-DQqgvwmC.js +2 -0
  128. package/dashboard/dist/assets/SwimlaneTimeline-DQqgvwmC.js.map +1 -0
  129. package/dashboard/dist/assets/{TagInput-DftaRHDV.js → TagInput-Dkljw_WI.js} +2 -2
  130. package/dashboard/dist/assets/{TagInput-DftaRHDV.js.map → TagInput-Dkljw_WI.js.map} +1 -1
  131. package/dashboard/dist/assets/{TaskDetailPage-BoA-cfwW.js → TaskDetailPage-AHBMSHAA.js} +2 -2
  132. package/dashboard/dist/assets/{TaskDetailPage-BoA-cfwW.js.map → TaskDetailPage-AHBMSHAA.js.map} +1 -1
  133. package/dashboard/dist/assets/{TaskQueuePill-Ce8KlXtR.js → TaskQueuePill-DPwm25Cc.js} +2 -2
  134. package/dashboard/dist/assets/{TaskQueuePill-Ce8KlXtR.js.map → TaskQueuePill-DPwm25Cc.js.map} +1 -1
  135. package/dashboard/dist/assets/{TasksListPage-g6XIbhju.js → TasksListPage-CnJdTsoX.js} +2 -2
  136. package/dashboard/dist/assets/{TasksListPage-g6XIbhju.js.map → TasksListPage-CnJdTsoX.js.map} +1 -1
  137. package/dashboard/dist/assets/{TimeAgo-BihIwEbB.js → TimeAgo-C3A1r1Cv.js} +2 -2
  138. package/dashboard/dist/assets/{TimeAgo-BihIwEbB.js.map → TimeAgo-C3A1r1Cv.js.map} +1 -1
  139. package/dashboard/dist/assets/{TimestampCell-GOFcvE-i.js → TimestampCell-DPfLR6bZ.js} +2 -2
  140. package/dashboard/dist/assets/{TimestampCell-GOFcvE-i.js.map → TimestampCell-DPfLR6bZ.js.map} +1 -1
  141. package/dashboard/dist/assets/ToolPill-D_DIWFJ5.js +2 -0
  142. package/dashboard/dist/assets/ToolPill-D_DIWFJ5.js.map +1 -0
  143. package/dashboard/dist/assets/ToolTestPanel-CwZ9zkD-.js +2 -0
  144. package/dashboard/dist/assets/ToolTestPanel-CwZ9zkD-.js.map +1 -0
  145. package/dashboard/dist/assets/{UserName-CmMVt4vS.js → UserName-ClO0a6Ar.js} +2 -2
  146. package/dashboard/dist/assets/{UserName-CmMVt4vS.js.map → UserName-ClO0a6Ar.js.map} +1 -1
  147. package/dashboard/dist/assets/{WorkflowExecutionPage-soRFz_30.js → WorkflowExecutionPage-B-2aHAHK.js} +2 -2
  148. package/dashboard/dist/assets/{WorkflowExecutionPage-soRFz_30.js.map → WorkflowExecutionPage-B-2aHAHK.js.map} +1 -1
  149. package/dashboard/dist/assets/{WorkflowPill-DUDDyBsj.js → WorkflowPill-BbgVTGgI.js} +2 -2
  150. package/dashboard/dist/assets/WorkflowPill-BbgVTGgI.js.map +1 -0
  151. package/dashboard/dist/assets/WorkflowsDashboard-NtiQKl_i.js +2 -0
  152. package/dashboard/dist/assets/WorkflowsDashboard-NtiQKl_i.js.map +1 -0
  153. package/dashboard/dist/assets/{WorkflowsOverview-z3Ztiz1y.js → WorkflowsOverview-BQip_pvL.js} +2 -2
  154. package/dashboard/dist/assets/{WorkflowsOverview-z3Ztiz1y.js.map → WorkflowsOverview-BQip_pvL.js.map} +1 -1
  155. package/dashboard/dist/assets/YamlWorkflowsPage-BWFCVQ8b.js +2 -0
  156. package/dashboard/dist/assets/YamlWorkflowsPage-BWFCVQ8b.js.map +1 -0
  157. package/dashboard/dist/assets/agents-5APoyRH8.js +2 -0
  158. package/dashboard/dist/assets/agents-5APoyRH8.js.map +1 -0
  159. package/dashboard/dist/assets/{bots-BZPXDh_y.js → bots-BoDH-pS7.js} +2 -2
  160. package/dashboard/dist/assets/{bots-BZPXDh_y.js.map → bots-BoDH-pS7.js.map} +1 -1
  161. package/dashboard/dist/assets/controlplane-D4NhQux3.js +2 -0
  162. package/dashboard/dist/assets/controlplane-D4NhQux3.js.map +1 -0
  163. package/dashboard/dist/assets/{escalation-DBUIq1Z4.js → escalation-BD2wtAt2.js} +2 -2
  164. package/dashboard/dist/assets/{escalation-DBUIq1Z4.js.map → escalation-BD2wtAt2.js.map} +1 -1
  165. package/dashboard/dist/assets/escalation-columns-DjHcNgjo.js +2 -0
  166. package/dashboard/dist/assets/{escalation-columns-DL4zsR8Y.js.map → escalation-columns-DjHcNgjo.js.map} +1 -1
  167. package/dashboard/dist/assets/{helpers-D50KFFkI.js → helpers-D1ZPA4kI.js} +2 -2
  168. package/dashboard/dist/assets/{helpers-D50KFFkI.js.map → helpers-D1ZPA4kI.js.map} +1 -1
  169. package/dashboard/dist/assets/index-B-Z9TisY.js +2 -0
  170. package/dashboard/dist/assets/index-B-Z9TisY.js.map +1 -0
  171. package/dashboard/dist/assets/index-B6vQeWwf.js +6 -0
  172. package/dashboard/dist/assets/index-B6vQeWwf.js.map +1 -0
  173. package/dashboard/dist/assets/{index-D9_hZmsW.js → index-BD2vW8MG.js} +3 -3
  174. package/dashboard/dist/assets/{index-D9_hZmsW.js.map → index-BD2vW8MG.js.map} +1 -1
  175. package/dashboard/dist/assets/index-BciXgS35.css +1 -0
  176. package/dashboard/dist/assets/index-BgJR7kwH.js +2 -0
  177. package/dashboard/dist/assets/index-BgJR7kwH.js.map +1 -0
  178. package/dashboard/dist/assets/index-D9qswqDQ.js +2 -0
  179. package/dashboard/dist/assets/{index-BpoHVMV7.js.map → index-D9qswqDQ.js.map} +1 -1
  180. package/dashboard/dist/assets/index-DC7f6rWu.js +2 -0
  181. package/dashboard/dist/assets/{index-CEnDYJOO.js.map → index-DC7f6rWu.js.map} +1 -1
  182. package/dashboard/dist/assets/{index-B-jzKfuv.js → index-Zn5XforP.js} +2 -2
  183. package/dashboard/dist/assets/{index-B-jzKfuv.js.map → index-Zn5XforP.js.map} +1 -1
  184. package/dashboard/dist/assets/index-_5qNyf9o.js +2 -0
  185. package/dashboard/dist/assets/index-_5qNyf9o.js.map +1 -0
  186. package/dashboard/dist/assets/index-_dKxJhey.js +2 -0
  187. package/dashboard/dist/assets/{index-DzICLMI7.js.map → index-_dKxJhey.js.map} +1 -1
  188. package/dashboard/dist/assets/index-jp94-YlF.js +2 -0
  189. package/dashboard/dist/assets/index-jp94-YlF.js.map +1 -0
  190. package/dashboard/dist/assets/{index-BUjxYyxc.js → index-oGYUhkFa.js} +27 -27
  191. package/dashboard/dist/assets/index-oGYUhkFa.js.map +1 -0
  192. package/dashboard/dist/assets/index-qdYsS9h2.js +15 -0
  193. package/dashboard/dist/assets/index-qdYsS9h2.js.map +1 -0
  194. package/dashboard/dist/assets/knowledge-DsAU_TGL.js +2 -0
  195. package/dashboard/dist/assets/knowledge-DsAU_TGL.js.map +1 -0
  196. package/dashboard/dist/assets/{mcp-D0GrHRFe.js → mcp-CA3OeIyH.js} +2 -2
  197. package/dashboard/dist/assets/{mcp-D0GrHRFe.js.map → mcp-CA3OeIyH.js.map} +1 -1
  198. package/dashboard/dist/assets/{mcp-query-DC5woQn5.js → mcp-query-BgmTDc7h.js} +2 -2
  199. package/dashboard/dist/assets/{mcp-query-DC5woQn5.js.map → mcp-query-BgmTDc7h.js.map} +1 -1
  200. package/dashboard/dist/assets/{mcp-runs-CsoVQoPB.js → mcp-runs-C-FK2SyD.js} +2 -2
  201. package/dashboard/dist/assets/{mcp-runs-CsoVQoPB.js.map → mcp-runs-C-FK2SyD.js.map} +1 -1
  202. package/dashboard/dist/assets/{namespaces-unpIb4gX.js → namespaces-B8KNk0Jb.js} +2 -2
  203. package/dashboard/dist/assets/{namespaces-unpIb4gX.js.map → namespaces-B8KNk0Jb.js.map} +1 -1
  204. package/dashboard/dist/assets/{roles--kBaFljg.js → roles-BAPy1LU_.js} +2 -2
  205. package/dashboard/dist/assets/{roles--kBaFljg.js.map → roles-BAPy1LU_.js.map} +1 -1
  206. package/dashboard/dist/assets/{settings-B96YkawY.js → settings-Da0QSQDH.js} +2 -2
  207. package/dashboard/dist/assets/{settings-B96YkawY.js.map → settings-Da0QSQDH.js.map} +1 -1
  208. package/dashboard/dist/assets/{tasks-D_1NCfOZ.js → tasks-BHlTusW0.js} +2 -2
  209. package/dashboard/dist/assets/{tasks-D_1NCfOZ.js.map → tasks-BHlTusW0.js.map} +1 -1
  210. package/dashboard/dist/assets/useEventHooks-DBMdj9vw.js +2 -0
  211. package/dashboard/dist/assets/useEventHooks-DBMdj9vw.js.map +1 -0
  212. package/dashboard/dist/assets/{useYamlActivityEvents-D3RQjfzo.js → useYamlActivityEvents-BH_ynR_L.js} +2 -2
  213. package/dashboard/dist/assets/{useYamlActivityEvents-D3RQjfzo.js.map → useYamlActivityEvents-BH_ynR_L.js.map} +1 -1
  214. package/dashboard/dist/assets/{users-e2oatvoj.js → users-C9K2cMyb.js} +2 -2
  215. package/dashboard/dist/assets/{users-e2oatvoj.js.map → users-C9K2cMyb.js.map} +1 -1
  216. package/dashboard/dist/assets/{vendor-icons-BkK55L-1.js → vendor-icons-E6836lXZ.js} +140 -95
  217. package/dashboard/dist/assets/vendor-icons-E6836lXZ.js.map +1 -0
  218. package/dashboard/dist/assets/workflows-B2rsLjoh.js +2 -0
  219. package/dashboard/dist/assets/workflows-B2rsLjoh.js.map +1 -0
  220. package/dashboard/dist/assets/{yaml-workflows-CAKU7LUu.js → yaml-workflows-BLiTvQM2.js} +2 -2
  221. package/dashboard/dist/assets/{yaml-workflows-CAKU7LUu.js.map → yaml-workflows-BLiTvQM2.js.map} +1 -1
  222. package/dashboard/dist/index.html +3 -3
  223. package/docs/agents.md +160 -0
  224. package/docs/api/http/agents.md +201 -0
  225. package/docs/api/sdk/agents.md +138 -0
  226. package/docs/story.md +101 -78
  227. package/package.json +3 -3
  228. package/dashboard/dist/assets/BotPicker-C2xR1xay.js +0 -2
  229. package/dashboard/dist/assets/BotPicker-C2xR1xay.js.map +0 -1
  230. package/dashboard/dist/assets/ListToolbar-CyEkulVR.js +0 -2
  231. package/dashboard/dist/assets/ListToolbar-CyEkulVR.js.map +0 -1
  232. package/dashboard/dist/assets/McpQueryDetailPage-5Dsj6PlL.js +0 -5
  233. package/dashboard/dist/assets/McpQueryDetailPage-5Dsj6PlL.js.map +0 -1
  234. package/dashboard/dist/assets/McpRunsPage-BKba-3Wl.js +0 -2
  235. package/dashboard/dist/assets/McpRunsPage-BKba-3Wl.js.map +0 -1
  236. package/dashboard/dist/assets/RolePill-BhVC0cc3.js +0 -2
  237. package/dashboard/dist/assets/RolePill-BhVC0cc3.js.map +0 -1
  238. package/dashboard/dist/assets/RunAsSelector-CD7_Dmb0.js +0 -2
  239. package/dashboard/dist/assets/RunAsSelector-CD7_Dmb0.js.map +0 -1
  240. package/dashboard/dist/assets/SwimlaneTimeline-CUl5RdXU.js +0 -2
  241. package/dashboard/dist/assets/SwimlaneTimeline-CUl5RdXU.js.map +0 -1
  242. package/dashboard/dist/assets/WorkflowPill-DUDDyBsj.js.map +0 -1
  243. package/dashboard/dist/assets/WorkflowsDashboard-Be1A1zAT.js +0 -2
  244. package/dashboard/dist/assets/WorkflowsDashboard-Be1A1zAT.js.map +0 -1
  245. package/dashboard/dist/assets/YamlWorkflowsPage-C6qzcQcJ.js +0 -2
  246. package/dashboard/dist/assets/YamlWorkflowsPage-C6qzcQcJ.js.map +0 -1
  247. package/dashboard/dist/assets/escalation-columns-DL4zsR8Y.js +0 -2
  248. package/dashboard/dist/assets/index-B-ioA6yv.js +0 -2
  249. package/dashboard/dist/assets/index-B-ioA6yv.js.map +0 -1
  250. package/dashboard/dist/assets/index-BMpoMc4A.js +0 -2
  251. package/dashboard/dist/assets/index-BMpoMc4A.js.map +0 -1
  252. package/dashboard/dist/assets/index-BU04qgJt.js +0 -15
  253. package/dashboard/dist/assets/index-BU04qgJt.js.map +0 -1
  254. package/dashboard/dist/assets/index-BUjxYyxc.js.map +0 -1
  255. package/dashboard/dist/assets/index-BpoHVMV7.js +0 -2
  256. package/dashboard/dist/assets/index-CEnDYJOO.js +0 -2
  257. package/dashboard/dist/assets/index-CbuH92vk.js +0 -6
  258. package/dashboard/dist/assets/index-CbuH92vk.js.map +0 -1
  259. package/dashboard/dist/assets/index-DrouIN-M.js +0 -2
  260. package/dashboard/dist/assets/index-DrouIN-M.js.map +0 -1
  261. package/dashboard/dist/assets/index-DzICLMI7.js +0 -2
  262. package/dashboard/dist/assets/index-efS5gKpv.css +0 -1
  263. package/dashboard/dist/assets/index-qT78AZDq.js +0 -2
  264. package/dashboard/dist/assets/index-qT78AZDq.js.map +0 -1
  265. package/dashboard/dist/assets/useEventHooks-BPjEkCpD.js +0 -2
  266. package/dashboard/dist/assets/useEventHooks-BPjEkCpD.js.map +0 -1
  267. package/dashboard/dist/assets/vendor-icons-BkK55L-1.js.map +0 -1
  268. package/dashboard/dist/assets/workflows-D6diL54s.js +0 -2
  269. package/dashboard/dist/assets/workflows-D6diL54s.js.map +0 -1
@@ -1,2 +0,0 @@
1
- import{a as h,j as e}from"./vendor-query-B2UbickB.js";import{a as z,u as J,b as D,c as F,d as O}from"./mcp-D0GrHRFe.js";import{E as I}from"./EmptyState-BcsfPq9T.js";import{C as _}from"./ConfirmDeleteModal-dOxidrSR.js";import{P as R}from"./PageHeader-B-SN5GZ2.js";import{F as $,a as q,b as T}from"./FilterBar-Ck4K4rzu.js";import{S as A}from"./StickyPagination-F9FZsRy9.js";import{u as W}from"./useFilterParams-DZCAaBC7.js";import{u as B}from"./useExpandedRows-CkcEntB-.js";import{J as U}from"./index-BUjxYyxc.js";import{b as G,R as H}from"./RunAsSelector-CD7_Dmb0.js";import{X as V,a6 as K,P as E,_ as M,a2 as X,k as Q,ab as Y,ac as Z,z as ee,l as te,W as se}from"./vendor-icons-BkK55L-1.js";import{L,c as re}from"./vendor-react-CX88sFS5.js";import{R as ae,a as w}from"./RowActions-Dg-Fsm5O.js";import{S as ne}from"./StatusBadge-XQlNFwmH.js";import"./Modal-DEODGeqx.js";import"./BotPicker-C2xR1xay.js";import"./bots-BZPXDh_y.js";function oe({error:s}){const t=s instanceof Error?s.message:"";return t.startsWith("No credential found for provider")?e.jsxs("div",{className:"bg-status-warning/10 border border-status-warning/30 rounded-md px-3 py-2 flex items-start gap-2",children:[e.jsx(X,{size:14,className:"text-status-warning mt-0.5 shrink-0"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] font-medium text-text-primary mb-0.5",children:"Credential required"}),e.jsx("p",{className:"text-[11px] text-text-secondary mb-1",children:t}),e.jsxs(L,{to:"/credentials",className:"text-[11px] text-accent hover:underline inline-flex items-center gap-1",children:["Go to Credentials ",e.jsx(M,{size:10})]})]})]}):e.jsx("div",{className:"bg-status-error/10 border border-status-error/20 rounded-md px-3 py-2",children:e.jsx("p",{className:"text-[11px] text-status-error",children:t||"Tool call failed"})})}function ie({data:s}){const t=s==null?void 0:s.result,n=t==null?void 0:t.job_id,c=(t==null?void 0:t.namespace)||"longtail";return n?e.jsxs(L,{to:`/mcp/executions/${encodeURIComponent(n)}?namespace=${encodeURIComponent(c)}`,className:"inline-flex items-center gap-1.5 text-xs text-accent hover:underline",children:[e.jsx(M,{size:12}),"View Execution"]}):null}function le({serverId:s,serverName:t,tool:n,onClose:c}){const a=z(),[d,j]=h.useState(!1),[m,p]=h.useState({}),[i,f]=h.useState(""),[g,l]=h.useState(""),[x,N]=h.useState("");h.useEffect(()=>{const o=G(n.inputSchema);p(o),f(JSON.stringify(o,null,2)),j(!1),l(""),a.reset()},[n.name,s]);const y=!!a.data||!!a.error,v=()=>{if(!d)f(JSON.stringify(m,null,2));else try{p(JSON.parse(i))}catch{}j(!d)},C=()=>{l(""),a.reset();let o;if(d)try{o=JSON.parse(i)}catch{l("Invalid JSON");return}else o={...m};a.mutate({serverId:s,toolName:n.name,arguments:o,...x?{execute_as:x}:{}})};return e.jsxs("div",{className:"border-l border-surface-border bg-surface-raised flex flex-col h-full",children:[e.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-surface-border shrink-0",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-xs font-medium text-text-primary truncate",children:t}),e.jsx("code",{className:"text-[11px] font-mono text-accent truncate block",children:n.name})]}),e.jsx("button",{onClick:c,className:"p-1 text-text-tertiary hover:text-text-primary shrink-0 ml-2",children:e.jsx(V,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-3 space-y-4",children:[e.jsx(H,{selected:x,onChange:N}),n.description&&e.jsx("p",{className:"text-[11px] text-text-secondary leading-relaxed",children:n.description}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("label",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:"Request"}),e.jsx("button",{onClick:v,className:"text-[10px] text-accent hover:underline",children:d?"Form view":"JSON view"})]}),d?e.jsx("textarea",{value:i,onChange:o=>f(o.target.value),className:"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-2 font-mono text-[11px] text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary resize-y",rows:6,spellCheck:!1}):e.jsxs("div",{className:"space-y-3 max-h-[300px] overflow-y-auto",children:[Object.entries(m).map(([o,b])=>e.jsxs("div",{children:[e.jsx("label",{className:"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:o}),typeof b=="boolean"?e.jsxs("select",{value:String(b),onChange:r=>p({...m,[o]:r.target.value==="true"}),className:"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary",children:[e.jsx("option",{value:"true",children:"true"}),e.jsx("option",{value:"false",children:"false"})]}):typeof b=="object"?e.jsx("textarea",{value:JSON.stringify(b,null,2),onChange:r=>{try{p({...m,[o]:JSON.parse(r.target.value)})}catch{}},className:"w-full min-h-[60px] px-3 py-1.5 bg-surface-sunken border border-surface-border rounded-md font-mono text-xs text-text-primary resize-y focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary"}):e.jsx("input",{type:typeof b=="number"?"number":"text",value:String(b??""),onChange:r=>p({...m,[o]:typeof b=="number"?Number(r.target.value):r.target.value}),className:"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary"})]},o)),Object.keys(m).length===0&&e.jsx("p",{className:"text-[11px] text-text-tertiary italic",children:"No input fields defined"})]}),g&&e.jsx("p",{className:"text-[11px] text-status-error mt-1",children:g})]}),e.jsx("button",{onClick:C,disabled:a.isPending,className:"btn-primary text-xs disabled:opacity-50 inline-flex items-center gap-1.5",children:a.isPending?"Running...":y?e.jsxs(e.Fragment,{children:[e.jsx(K,{size:12})," Re-run"]}):e.jsxs(e.Fragment,{children:[e.jsx(E,{size:12})," Run"]})}),a.isPending&&e.jsxs("div",{className:"animate-pulse",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Response"}),e.jsx("div",{className:"h-20 bg-surface-sunken rounded-md"})]}),a.data?e.jsxs("div",{className:"space-y-2",children:[e.jsx(U,{data:a.data,label:"Response",defaultCollapsed:!0}),e.jsx(ie,{data:a.data})]}):null,a.error?e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Response"}),e.jsx(oe,{error:a.error})]}):null]})]})}function ce(s){var t,n;return!!((t=s.metadata)!=null&&t.builtin)||!!((n=s.transport_config)!=null&&n.builtin)}function de(s,t){var a;if(!t)return!0;const n=t.toLowerCase();return s.name.toLowerCase().includes(n)||(a=s.description)!=null&&a.toLowerCase().includes(n)||(s.tags??[]).some(d=>d.toLowerCase().includes(n))?!0:(s.tool_manifest??[]).some(d=>{var j;return d.name.toLowerCase().includes(n)||((j=d.description)==null?void 0:j.toLowerCase().includes(n))})}function xe(s,t){if(!t)return s;const n=t.toLowerCase();return s.filter(c=>{var a;return c.name.toLowerCase().includes(n)||((a=c.description)==null?void 0:a.toLowerCase().includes(n))})}function ue({server:s,expanded:t,onToggle:n,onEdit:c,onDelete:a,onTryTool:d,connect:j,disconnect:m,visibleTools:p}){const i=s.tool_manifest??[],f=ce(s),g=s.tags??[];return e.jsxs(e.Fragment,{children:[e.jsxs("tr",{onClick:i.length>0?n:void 0,className:`group/row border-b border-surface-border/50 transition-colors duration-100 ${i.length>0?"cursor-pointer row-hover":""}`,children:[e.jsx("td",{className:"px-6 py-2.5",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:`transition-transform duration-150 ${t?"rotate-90":""} ${i.length===0?"opacity-0":"text-text-tertiary"}`,children:e.jsx(Q,{size:14})}),e.jsxs("p",{className:"text-sm text-text-primary font-medium",children:[s.name,i.length>0&&e.jsx("sup",{className:"ml-1 text-[9px] font-normal text-accent/70",children:i.length})]}),g.length>0&&e.jsxs("div",{className:"flex gap-1 ml-auto shrink-0",children:[g.slice(0,3).map(l=>e.jsx("span",{className:"inline-block px-1.5 py-0 text-[9px] text-text-tertiary bg-surface-sunken rounded",children:l},l)),g.length>3&&e.jsx("span",{className:"text-[9px] text-text-quaternary",title:g.slice(3).join(", "),children:"…"})]})]})}),e.jsx("td",{className:"px-4 py-2.5 w-28 whitespace-nowrap",children:e.jsx(ne,{status:s.status})}),e.jsx("td",{className:"px-4 py-2.5 w-16",children:e.jsxs(ae,{children:[!f&&(s.status==="connected"?e.jsx(w,{icon:Y,title:"Disconnect server",onClick:()=>m.mutate(s.id)}):e.jsx(w,{icon:Z,title:"Connect server",onClick:()=>j.mutate(s.id),colorClass:"text-text-tertiary hover:text-status-success"})),e.jsx(w,{icon:ee,title:"Edit server",onClick:c}),!f&&e.jsx(w,{icon:te,title:"Delete server",onClick:a,colorClass:"text-text-tertiary hover:text-status-error"})]})})]}),t&&p.map(l=>e.jsxs("tr",{onClick:()=>d(l),className:"group/row cursor-pointer hover:bg-surface-hover/50 transition-colors border-b border-surface-border/15",children:[e.jsxs("td",{className:"pl-14 pr-6 py-2.5",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2.5 py-0.5 text-[13px] font-mono bg-accent/[0.06] text-text-secondary rounded-lg",children:[e.jsx(se,{className:"w-3 h-3 shrink-0 text-accent/75"}),l.name]}),l.description&&e.jsx("p",{className:"text-[11px] leading-snug text-text-quaternary mt-0.5",children:l.description})]}),e.jsx("td",{className:"px-4 py-2.5 w-28"}),e.jsx("td",{className:"px-4 py-2.5 w-16",children:e.jsx("div",{className:"flex items-center justify-end",children:e.jsx("button",{onClick:x=>{x.stopPropagation(),d(l)},className:"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-accent",title:"Try tool",children:e.jsx(E,{className:"w-3.5 h-3.5",strokeWidth:1.5})})})})]},l.name))]})}function Le(){const s=re(),{filters:t,setFilter:n,pagination:c}=W({filters:{status:"",search:"",tag:""}}),{data:a,isLoading:d}=J({status:t.status||void 0,search:t.search||void 0,tags:t.tag||void 0}),j=D(),m=F(),p=O(),[i,f]=h.useState(null),{expandedIds:g,toggle:l}=B("lt:expanded:mcp-servers"),[x,N]=h.useState(null),y=(a==null?void 0:a.servers)??[],v=(a==null?void 0:a.total)??0,C=h.useMemo(()=>{const r=new Set;for(const u of y)for(const S of u.tags??[])r.add(S);return[...r].sort().map(u=>({value:u,label:u}))},[y]),o=h.useMemo(()=>t.search?y.filter(r=>de(r,t.search)):y,[y,t.search]);h.useEffect(()=>{if(!t.search)return;const r=t.search.toLowerCase();for(const u of o)(u.tool_manifest??[]).some(k=>{var P;return k.name.toLowerCase().includes(r)||((P=k.description)==null?void 0:P.toLowerCase().includes(r))})&&!g.has(u.id)&&l(u.id)},[t.search,o]);const b=()=>{i&&p.mutate(i.id,{onSuccess:()=>f(null)})};return d?e.jsxs("div",{children:[e.jsx(R,{title:"MCP Server Tools"}),e.jsx("div",{className:"animate-pulse space-y-0",children:Array.from({length:5}).map((r,u)=>e.jsx("div",{className:"h-14 border-b last:border-b-0 px-6 flex items-center",children:e.jsx("div",{className:"h-3 bg-surface-sunken rounded w-full"})},u))})]}):e.jsxs("div",{children:[e.jsx(R,{title:"MCP Server Tools",docsHash:"#docs:dashboard.md:mcp-server-tools",actions:e.jsx("button",{onClick:()=>s("/mcp/servers/new"),className:"btn-primary text-xs",children:"Register Server"})}),e.jsx("p",{className:"text-sm text-text-secondary mb-6 max-w-2xl leading-relaxed",children:"Registered MCP servers and their available tools. Each server exposes tools that can be used by the MCP Tool Designer."}),e.jsxs($,{children:[e.jsx(q,{label:"Search",value:t.search,onChange:r=>n("search",r),placeholder:"Server or tool name..."}),e.jsx(T,{label:"Tag",value:t.tag,onChange:r=>n("tag",r),options:C}),e.jsx(T,{label:"Status",value:t.status,onChange:r=>n("status",r),options:[{value:"registered",label:"Registered"},{value:"connected",label:"Connected"},{value:"error",label:"Error"},{value:"disconnected",label:"Disconnected"}]})]}),e.jsxs("div",{className:"flex gap-0 ",children:[e.jsxs("div",{className:`${x?"flex-1 min-w-0":"w-full"} transition-all`,children:[o.length===0?e.jsx(I,{title:"No servers found"}):e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b",children:[e.jsx("th",{className:"sticky top-[2.75rem] z-10 bg-surface px-6 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:"Server / Tool"}),e.jsx("th",{className:"sticky top-[2.75rem] z-10 bg-surface px-4 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary w-28",children:"Status"}),e.jsx("th",{className:"sticky top-[2.75rem] z-10 bg-surface w-16"})]})}),e.jsx("tbody",{children:o.map(r=>e.jsx(ue,{server:r,expanded:g.has(r.id),onToggle:()=>l(r.id),onEdit:()=>s(`/mcp/servers/${r.id}`),onDelete:()=>f(r),onTryTool:u=>N({serverId:r.id,serverName:r.name,tool:u}),connect:j,disconnect:m,visibleTools:xe(r.tool_manifest??[],t.search)},r.id))})]}),e.jsx(A,{page:c.page,totalPages:c.totalPages(v),onPageChange:c.setPage,total:v,pageSize:c.pageSize,onPageSizeChange:c.setPageSize})]}),x&&e.jsx("div",{className:"w-[380px] shrink-0 sticky top-0 h-[calc(100vh-12rem)]",children:e.jsx(le,{serverId:x.serverId,serverName:x.serverName,tool:x.tool,onClose:()=>N(null)})})]}),e.jsx(_,{open:!!i,onClose:()=>f(null),onConfirm:b,title:"Delete MCP Server",description:e.jsxs(e.Fragment,{children:["Delete"," ",e.jsx("span",{className:"font-medium text-text-primary",children:i==null?void 0:i.name}),"? This will remove the server registration."]}),isPending:p.isPending,error:p.error})]})}export{Le as McpServersPage};
2
- //# sourceMappingURL=index-B-ioA6yv.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-B-ioA6yv.js","sources":["../../src/components/common/test/ToolTestPanel.tsx","../../src/pages/mcp/servers/helpers.ts","../../src/pages/mcp/servers/ServerRow.tsx","../../src/pages/mcp/servers/McpServersPage.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { Link } from 'react-router-dom';\nimport { X, RotateCcw, Play, ExternalLink, KeyRound } from 'lucide-react';\nimport { useCallMcpTool } from '../../../api/mcp';\nimport { JsonViewer } from '../data/JsonViewer';\nimport { RunAsSelector } from '../form/RunAsSelector';\nimport type { McpToolManifest } from '../../../api/types';\nimport { buildSkeleton } from '../../../pages/mcp/mcp-query-detail/helpers';\n\nfunction ToolErrorDisplay({ error }: { error: Error | null }) {\n const msg = error instanceof Error ? error.message : '';\n if (msg.startsWith('No credential found for provider')) {\n return (\n <div className=\"bg-status-warning/10 border border-status-warning/30 rounded-md px-3 py-2 flex items-start gap-2\">\n <KeyRound size={14} className=\"text-status-warning mt-0.5 shrink-0\" />\n <div>\n <p className=\"text-[11px] font-medium text-text-primary mb-0.5\">Credential required</p>\n <p className=\"text-[11px] text-text-secondary mb-1\">{msg}</p>\n <Link to=\"/credentials\" className=\"text-[11px] text-accent hover:underline inline-flex items-center gap-1\">\n Go to Credentials <ExternalLink size={10} />\n </Link>\n </div>\n </div>\n );\n }\n return (\n <div className=\"bg-status-error/10 border border-status-error/20 rounded-md px-3 py-2\">\n <p className=\"text-[11px] text-status-error\">{msg || 'Tool call failed'}</p>\n </div>\n );\n}\n\nfunction ExecutionLink({ data }: { data: unknown }) {\n const res = (data as any)?.result;\n const jobId = res?.job_id;\n const ns = res?.namespace || 'longtail';\n if (!jobId) return null;\n return (\n <Link\n to={`/mcp/executions/${encodeURIComponent(jobId)}?namespace=${encodeURIComponent(ns)}`}\n className=\"inline-flex items-center gap-1.5 text-xs text-accent hover:underline\"\n >\n <ExternalLink size={12} />\n View Execution\n </Link>\n );\n}\n\ninterface ToolTestPanelProps {\n serverId: string;\n serverName: string;\n tool: McpToolManifest;\n onClose: () => void;\n}\n\nexport function ToolTestPanel({ serverId, serverName, tool, onClose }: ToolTestPanelProps) {\n const callTool = useCallMcpTool();\n const [jsonMode, setJsonMode] = useState(false);\n const [fields, setFields] = useState<Record<string, any>>({});\n const [argsJson, setArgsJson] = useState('');\n const [jsonError, setJsonError] = useState('');\n const [executeAs, setExecuteAs] = useState('');\n\n useEffect(() => {\n const skeleton = buildSkeleton(tool.inputSchema);\n setFields(skeleton);\n setArgsJson(JSON.stringify(skeleton, null, 2));\n setJsonMode(false);\n setJsonError('');\n callTool.reset();\n }, [tool.name, serverId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const hasResult = !!callTool.data || !!callTool.error;\n\n const toggleMode = () => {\n if (!jsonMode) {\n setArgsJson(JSON.stringify(fields, null, 2));\n } else {\n try { setFields(JSON.parse(argsJson)); } catch { /* keep fields */ }\n }\n setJsonMode(!jsonMode);\n };\n\n const handleRun = () => {\n setJsonError('');\n callTool.reset();\n let parsed: Record<string, unknown>;\n if (jsonMode) {\n try { parsed = JSON.parse(argsJson); } catch { setJsonError('Invalid JSON'); return; }\n } else {\n parsed = { ...fields };\n }\n callTool.mutate({\n serverId,\n toolName: tool.name,\n arguments: parsed,\n ...(executeAs ? { execute_as: executeAs } : {}),\n });\n };\n\n return (\n <div className=\"border-l border-surface-border bg-surface-raised flex flex-col h-full\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-surface-border shrink-0\">\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-text-primary truncate\">{serverName}</p>\n <code className=\"text-[11px] font-mono text-accent truncate block\">{tool.name}</code>\n </div>\n <button onClick={onClose} className=\"p-1 text-text-tertiary hover:text-text-primary shrink-0 ml-2\">\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n\n {/* Scrollable body */}\n <div className=\"flex-1 overflow-y-auto px-4 py-3 space-y-4\">\n <RunAsSelector selected={executeAs} onChange={setExecuteAs} />\n\n {tool.description && (\n <p className=\"text-[11px] text-text-secondary leading-relaxed\">{tool.description}</p>\n )}\n\n {/* Form / JSON toggle input */}\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <label className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">Request</label>\n <button onClick={toggleMode} className=\"text-[10px] text-accent hover:underline\">\n {jsonMode ? 'Form view' : 'JSON view'}\n </button>\n </div>\n\n {jsonMode ? (\n <textarea\n value={argsJson}\n onChange={(e) => setArgsJson(e.target.value)}\n className=\"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-2 font-mono text-[11px] text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary resize-y\"\n rows={6}\n spellCheck={false}\n />\n ) : (\n <div className=\"space-y-3 max-h-[300px] overflow-y-auto\">\n {Object.entries(fields).map(([key, value]) => (\n <div key={key}>\n <label className=\"block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">{key}</label>\n {typeof value === 'boolean' ? (\n <select\n value={String(value)}\n onChange={(e) => setFields({ ...fields, [key]: e.target.value === 'true' })}\n className=\"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary\"\n >\n <option value=\"true\">true</option>\n <option value=\"false\">false</option>\n </select>\n ) : typeof value === 'object' ? (\n <textarea\n value={JSON.stringify(value, null, 2)}\n onChange={(e) => { try { setFields({ ...fields, [key]: JSON.parse(e.target.value) }); } catch { /* invalid */ } }}\n className=\"w-full min-h-[60px] px-3 py-1.5 bg-surface-sunken border border-surface-border rounded-md font-mono text-xs text-text-primary resize-y focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary\"\n />\n ) : (\n <input\n type={typeof value === 'number' ? 'number' : 'text'}\n value={String(value ?? '')}\n onChange={(e) => setFields({ ...fields, [key]: typeof value === 'number' ? Number(e.target.value) : e.target.value })}\n className=\"w-full bg-surface-sunken border border-surface-border rounded-md px-3 py-1.5 text-xs text-text-primary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-accent-primary\"\n />\n )}\n </div>\n ))}\n {Object.keys(fields).length === 0 && (\n <p className=\"text-[11px] text-text-tertiary italic\">No input fields defined</p>\n )}\n </div>\n )}\n {jsonError && <p className=\"text-[11px] text-status-error mt-1\">{jsonError}</p>}\n </div>\n\n {/* Run button */}\n <button\n onClick={handleRun}\n disabled={callTool.isPending}\n className=\"btn-primary text-xs disabled:opacity-50 inline-flex items-center gap-1.5\"\n >\n {callTool.isPending ? (\n 'Running...'\n ) : hasResult ? (\n <><RotateCcw size={12} /> Re-run</>\n ) : (\n <><Play size={12} /> Run</>\n )}\n </button>\n\n {/* Response */}\n {callTool.isPending && (\n <div className=\"animate-pulse\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">Response</p>\n <div className=\"h-20 bg-surface-sunken rounded-md\" />\n </div>\n )}\n {callTool.data ? (\n <div className=\"space-y-2\">\n <JsonViewer data={callTool.data as Record<string, unknown>} label=\"Response\" defaultCollapsed />\n <ExecutionLink data={callTool.data} />\n </div>\n ) : null}\n {callTool.error ? (\n <div>\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">Response</p>\n <ToolErrorDisplay error={callTool.error as Error | null} />\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n","import type { McpServerRecord, McpToolManifest } from '../../../api/types';\n\nexport function isBuiltIn(row: McpServerRecord): boolean {\n return !!(row.metadata as Record<string, unknown> | null)?.builtin\n || !!(row.transport_config as Record<string, unknown> | null)?.builtin;\n}\n\n/** Check if a server or any of its tools match the search term */\nexport function matchesSearch(server: McpServerRecord, search: string): boolean {\n if (!search) return true;\n const q = search.toLowerCase();\n if (server.name.toLowerCase().includes(q)) return true;\n if (server.description?.toLowerCase().includes(q)) return true;\n if ((server.tags ?? []).some((t) => t.toLowerCase().includes(q))) return true;\n const tools = (server.tool_manifest ?? []) as McpToolManifest[];\n return tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n\n/** Filter tools within a server that match the search term */\nexport function filterTools(tools: McpToolManifest[], search: string): McpToolManifest[] {\n if (!search) return tools;\n const q = search.toLowerCase();\n return tools.filter(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n}\n","import { ChevronRight, Pencil, Trash2, Plug, Unplug, Play, Wrench } from 'lucide-react';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport {\n useConnectMcpServer,\n useDisconnectMcpServer,\n} from '../../../api/mcp';\nimport { StatusBadge } from '../../../components/common/display/StatusBadge';\n\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { isBuiltIn } from './helpers';\n\nexport function ServerRow({\n server,\n expanded,\n onToggle,\n onEdit,\n onDelete,\n onTryTool,\n connect,\n disconnect,\n visibleTools,\n}: {\n server: McpServerRecord;\n expanded: boolean;\n onToggle: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onTryTool: (tool: McpToolManifest) => void;\n connect: ReturnType<typeof useConnectMcpServer>;\n disconnect: ReturnType<typeof useDisconnectMcpServer>;\n visibleTools: McpToolManifest[];\n}) {\n const allTools = (server.tool_manifest ?? []) as McpToolManifest[];\n const builtin = isBuiltIn(server);\n const tags = server.tags ?? [];\n\n return (\n <>\n {/* Server header row */}\n <tr\n onClick={allTools.length > 0 ? onToggle : undefined}\n className={`group/row border-b border-surface-border/50 transition-colors duration-100 ${\n allTools.length > 0 ? 'cursor-pointer row-hover' : ''\n }`}\n >\n {/* Name + tags */}\n <td className=\"px-6 py-2.5\">\n <div className=\"flex items-center gap-3\">\n <span className={`transition-transform duration-150 ${expanded ? 'rotate-90' : ''} ${allTools.length === 0 ? 'opacity-0' : 'text-text-tertiary'}`}>\n <ChevronRight size={14} />\n </span>\n <p className=\"text-sm text-text-primary font-medium\">\n {server.name}\n {allTools.length > 0 && (\n <sup className=\"ml-1 text-[9px] font-normal text-accent/70\">{allTools.length}</sup>\n )}\n </p>\n {tags.length > 0 && (\n <div className=\"flex gap-1 ml-auto shrink-0\">\n {tags.slice(0, 3).map((tag) => (\n <span key={tag} className=\"inline-block px-1.5 py-0 text-[9px] text-text-tertiary bg-surface-sunken rounded\">\n {tag}\n </span>\n ))}\n {tags.length > 3 && (\n <span className=\"text-[9px] text-text-quaternary\" title={tags.slice(3).join(', ')}>&hellip;</span>\n )}\n </div>\n )}\n </div>\n </td>\n\n {/* Status */}\n <td className=\"px-4 py-2.5 w-28 whitespace-nowrap\">\n <StatusBadge status={server.status} />\n </td>\n\n {/* Actions */}\n <td className=\"px-4 py-2.5 w-16\">\n <RowActionGroup>\n {!builtin && (\n server.status === 'connected' ? (\n <RowAction\n icon={Unplug}\n title=\"Disconnect server\"\n onClick={() => disconnect.mutate(server.id)}\n />\n ) : (\n <RowAction\n icon={Plug}\n title=\"Connect server\"\n onClick={() => connect.mutate(server.id)}\n colorClass=\"text-text-tertiary hover:text-status-success\"\n />\n )\n )}\n <RowAction\n icon={Pencil}\n title=\"Edit server\"\n onClick={onEdit}\n />\n {!builtin && (\n <RowAction\n icon={Trash2}\n title=\"Delete server\"\n onClick={onDelete}\n colorClass=\"text-text-tertiary hover:text-status-error\"\n />\n )}\n </RowActionGroup>\n </td>\n </tr>\n\n {/* Expanded tool rows — real table rows for column alignment */}\n {expanded && visibleTools.map((tool) => (\n <tr\n key={tool.name}\n onClick={() => onTryTool(tool)}\n className=\"group/row cursor-pointer hover:bg-surface-hover/50 transition-colors border-b border-surface-border/15\"\n >\n {/* Tool name + description */}\n <td className=\"pl-14 pr-6 py-2.5\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-0.5 text-[13px] font-mono bg-accent/[0.06] text-text-secondary rounded-lg\">\n <Wrench className=\"w-3 h-3 shrink-0 text-accent/75\" />\n {tool.name}\n </span>\n {tool.description && (\n <p className=\"text-[11px] leading-snug text-text-quaternary mt-0.5\">{tool.description}</p>\n )}\n </td>\n\n {/* Status — empty for tools */}\n <td className=\"px-4 py-2.5 w-28\" />\n\n {/* Actions — play on hover */}\n <td className=\"px-4 py-2.5 w-16\">\n <div className=\"flex items-center justify-end\">\n <button\n onClick={(e) => { e.stopPropagation(); onTryTool(tool); }}\n className=\"opacity-0 group-hover/row:opacity-100 transition-opacity text-text-tertiary hover:text-accent\"\n title=\"Try tool\"\n >\n <Play className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n </button>\n </div>\n </td>\n </tr>\n ))}\n </>\n );\n}\n","import { useState, useMemo, useEffect } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n useMcpServers,\n useConnectMcpServer,\n useDisconnectMcpServer,\n useDeleteMcpServer,\n} from '../../../api/mcp';\nimport { EmptyState } from '../../../components/common/display/EmptyState';\nimport { ConfirmDeleteModal } from '../../../components/common/modal/ConfirmDeleteModal';\nimport type { McpServerRecord, McpToolManifest } from '../../../api/types';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { FilterBar, FilterSelect, FilterInput } from '../../../components/common/data/FilterBar';\nimport { StickyPagination } from '../../../components/common/data/StickyPagination';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport { useExpandedRows } from '../../../hooks/useExpandedRows';\nimport { ToolTestPanel } from '../../../components/common/test/ToolTestPanel';\nimport { matchesSearch, filterTools } from './helpers';\nimport { ServerRow } from './ServerRow';\n\nexport function McpServersPage() {\n const navigate = useNavigate();\n const { filters, setFilter, pagination } = useFilterParams({\n filters: { status: '', search: '', tag: '' },\n });\n\n const { data, isLoading } = useMcpServers({\n status: filters.status || undefined,\n search: filters.search || undefined,\n tags: filters.tag || undefined,\n });\n const connect = useConnectMcpServer();\n const disconnect = useDisconnectMcpServer();\n const deleteServer = useDeleteMcpServer();\n\n const [confirmDelete, setConfirmDelete] = useState<McpServerRecord | null>(null);\n const { expandedIds, toggle: toggleExpand } = useExpandedRows('lt:expanded:mcp-servers');\n const [tryTool, setTryTool] = useState<{\n serverId: string;\n serverName: string;\n tool: McpToolManifest;\n } | null>(null);\n\n const servers = data?.servers ?? [];\n const total = data?.total ?? 0;\n\n // Derive unique tags from current result set for the filter dropdown\n const tagOptions = useMemo(() => {\n const allTags = new Set<string>();\n for (const s of servers) {\n for (const t of s.tags ?? []) allTags.add(t);\n }\n return [...allTags].sort().map((t) => ({ value: t, label: t }));\n }, [servers]);\n\n // Client-side search filtering for tool-level matches within expanded rows\n const filteredServers = useMemo(() => {\n if (!filters.search) return servers;\n return servers.filter((s) => matchesSearch(s, filters.search));\n }, [servers, filters.search]);\n\n // Auto-expand servers whose tools match the search (so results are visible)\n useEffect(() => {\n if (!filters.search) return;\n const q = filters.search.toLowerCase();\n for (const s of filteredServers) {\n const tools = (s.tool_manifest ?? []) as McpToolManifest[];\n const hasToolMatch = tools.some(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n if (hasToolMatch && !expandedIds.has(s.id)) {\n toggleExpand(s.id);\n }\n }\n }, [filters.search, filteredServers]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleDelete = () => {\n if (!confirmDelete) return;\n deleteServer.mutate(confirmDelete.id, {\n onSuccess: () => setConfirmDelete(null),\n });\n };\n\n if (isLoading) {\n return (\n <div>\n <PageHeader title=\"MCP Server Tools\" />\n <div className=\"animate-pulse space-y-0\">\n {Array.from({ length: 5 }).map((_, i) => (\n <div key={i} className=\"h-14 border-b last:border-b-0 px-6 flex items-center\">\n <div className=\"h-3 bg-surface-sunken rounded w-full\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div>\n <PageHeader\n title=\"MCP Server Tools\"\n docsHash=\"#docs:dashboard.md:mcp-server-tools\"\n actions={\n <button\n onClick={() => navigate('/mcp/servers/new')}\n className=\"btn-primary text-xs\"\n >\n Register Server\n </button>\n }\n />\n\n <p className=\"text-sm text-text-secondary mb-6 max-w-2xl leading-relaxed\">\n Registered MCP servers and their available tools. Each server exposes tools that can be used by the MCP Tool Designer.\n </p>\n\n <FilterBar>\n <FilterInput\n label=\"Search\"\n value={filters.search}\n onChange={(v) => setFilter('search', v)}\n placeholder=\"Server or tool name...\"\n />\n <FilterSelect\n label=\"Tag\"\n value={filters.tag}\n onChange={(v) => setFilter('tag', v)}\n options={tagOptions}\n />\n <FilterSelect\n label=\"Status\"\n value={filters.status}\n onChange={(v) => setFilter('status', v)}\n options={[\n { value: 'registered', label: 'Registered' },\n { value: 'connected', label: 'Connected' },\n { value: 'error', label: 'Error' },\n { value: 'disconnected', label: 'Disconnected' },\n ]}\n />\n </FilterBar>\n\n <div className={`flex gap-0 ${tryTool ? '' : ''}`}>\n {/* Server list */}\n <div className={`${tryTool ? 'flex-1 min-w-0' : 'w-full'} transition-all`}>\n {filteredServers.length === 0 ? (\n <EmptyState title=\"No servers found\" />\n ) : (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-6 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">\n Server / Tool\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface px-4 py-3 text-left text-[10px] font-semibold uppercase tracking-widest text-text-tertiary w-28\">\n Status\n </th>\n <th className=\"sticky top-[2.75rem] z-10 bg-surface w-16\" />\n </tr>\n </thead>\n <tbody>\n {filteredServers.map((server) => (\n <ServerRow\n key={server.id}\n server={server}\n expanded={expandedIds.has(server.id)}\n onToggle={() => toggleExpand(server.id)}\n onEdit={() => navigate(`/mcp/servers/${server.id}`)}\n onDelete={() => setConfirmDelete(server)}\n onTryTool={(tool) =>\n setTryTool({\n serverId: server.id,\n serverName: server.name,\n tool,\n })\n }\n connect={connect}\n disconnect={disconnect}\n visibleTools={filterTools(\n (server.tool_manifest ?? []) as McpToolManifest[],\n filters.search,\n )}\n />\n ))}\n </tbody>\n </table>\n )}\n\n <StickyPagination\n page={pagination.page}\n totalPages={pagination.totalPages(total)}\n onPageChange={pagination.setPage}\n total={total}\n pageSize={pagination.pageSize}\n onPageSizeChange={pagination.setPageSize}\n />\n </div>\n\n {/* Test panel — slides in from right */}\n {tryTool && (\n <div className=\"w-[380px] shrink-0 sticky top-0 h-[calc(100vh-12rem)]\">\n <ToolTestPanel\n serverId={tryTool.serverId}\n serverName={tryTool.serverName}\n tool={tryTool.tool}\n onClose={() => setTryTool(null)}\n />\n </div>\n )}\n </div>\n\n {/* Delete confirmation modal */}\n <ConfirmDeleteModal\n open={!!confirmDelete}\n onClose={() => setConfirmDelete(null)}\n onConfirm={handleDelete}\n title=\"Delete MCP Server\"\n description={\n <>\n Delete{' '}\n <span className=\"font-medium text-text-primary\">{confirmDelete?.name}</span>?\n This will remove the server registration.\n </>\n }\n isPending={deleteServer.isPending}\n error={deleteServer.error as Error | null}\n />\n </div>\n );\n}\n"],"names":["ToolErrorDisplay","error","msg","jsxs","jsx","KeyRound","Link","ExternalLink","ExecutionLink","data","res","jobId","ns","ToolTestPanel","serverId","serverName","tool","onClose","callTool","useCallMcpTool","jsonMode","setJsonMode","useState","fields","setFields","argsJson","setArgsJson","jsonError","setJsonError","executeAs","setExecuteAs","useEffect","skeleton","buildSkeleton","hasResult","toggleMode","handleRun","parsed","X","RunAsSelector","e","key","value","Fragment","RotateCcw","Play","JsonViewer","isBuiltIn","row","_a","_b","matchesSearch","server","search","q","t","filterTools","tools","ServerRow","expanded","onToggle","onEdit","onDelete","onTryTool","connect","disconnect","visibleTools","allTools","builtin","tags","ChevronRight","tag","StatusBadge","RowActionGroup","RowAction","Unplug","Plug","Pencil","Trash2","Wrench","McpServersPage","navigate","useNavigate","filters","setFilter","pagination","useFilterParams","isLoading","useMcpServers","useConnectMcpServer","useDisconnectMcpServer","deleteServer","useDeleteMcpServer","confirmDelete","setConfirmDelete","expandedIds","toggleExpand","useExpandedRows","tryTool","setTryTool","servers","total","tagOptions","useMemo","allTags","s","filteredServers","handleDelete","PageHeader","_","i","FilterBar","FilterInput","v","FilterSelect","EmptyState","StickyPagination","ConfirmDeleteModal"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{u as z,c as re,b as we,j as e,a as l}from"./vendor-query-B2UbickB.js";import{P as ve}from"./PageHeaderWithStats-BZ3AGT5s.js";import{F as Se,b as Te}from"./FilterBar-Ck4K4rzu.js";import{u as Re}from"./useFilterParams-DZCAaBC7.js";import{b as I,C as W,u as _e,J as Ee}from"./index-BUjxYyxc.js";import{R as ae,a as J}from"./RowActions-Dg-Fsm5O.js";import{ah as L,ai as G,aj as Me,P as $e,k as Pe,A as Fe,$ as Ae,R as Qe,S as Oe,ak as Ie,E as Be,al as We}from"./vendor-icons-BkK55L-1.js";import{M as Je}from"./Modal-DEODGeqx.js";import{D as oe}from"./DataTable-D3-wSEf0.js";import{C as V}from"./CollapsibleSection-CRtHQsAv.js";import{T as Le}from"./TaskQueuePill-Ce8KlXtR.js";import"./vendor-react-CX88sFS5.js";import"./EmptyState-BcsfPq9T.js";function qe(){return I("/controlplane/apps")}function Ke(t){return I(`/controlplane/rollcall?app_id=${encodeURIComponent(t)}`)}function Ue(t){return I("/controlplane/throttle",{method:"POST",body:JSON.stringify(t)})}function Ve(t){return I("/controlplane/subscribe",{method:"POST",body:JSON.stringify(t)})}function Ge(t,s,n){let r=`/controlplane/streams?app_id=${encodeURIComponent(t)}&duration=${encodeURIComponent(s)}`;return I(r)}function le(){return z({queryKey:["controlplane","apps"],queryFn:qe,staleTime:6e4})}function ze(t,s){return z({queryKey:["controlplane","rollcall",t],queryFn:()=>Ke(t),enabled:!!t,refetchInterval:s})}function ie(){const t=we();return re({mutationFn:Ue,onSuccess:()=>{setTimeout(()=>{t.invalidateQueries({queryKey:["controlplane","rollcall"]})},1500)}})}function He(t,s,n,r){return z({queryKey:["controlplane","streams",t,s,""],queryFn:()=>Ge(t,s),enabled:!!t,staleTime:15e3,refetchInterval:r})}function De(){return re({mutationFn:Ve})}const Ye=[{label:"15m",value:"15m"},{label:"30m",value:"30m"},{label:"1h",value:"1h"},{label:"1d",value:"1d"},{label:"7d",value:"7d"}],Xe={pong:"text-status-success",ping:"text-accent",throttle:"text-status-warning",job:"text-purple-400",work:"text-text-secondary",activate:"text-status-error",cron:"text-text-tertiary",user:"text-text-secondary"},Ze=250;function Q(t){return!!t.worker_topic}function O(t){return typeof t.throttle=="number"&&t.throttle!==0}function H(t){return t===void 0||t===0?"Normal":t===-1?"Paused":t>=864e5?`${(t/864e5).toFixed(0)}d`:t>=36e5?`${(t/36e5).toFixed(1)}h`:t>=6e4?`${(t/6e4).toFixed(1)}m`:t>=1e3?`${(t/1e3).toFixed(1)}s`:`${t}ms`}function ce(t,s){if(!t||!s)return"—";const n=parseFloat(t),r=parseFloat(s);return isNaN(n)||isNaN(r)?"—":`${(n-r).toFixed(1)} / ${n.toFixed(1)} GB`}function ue(t){return t.replace(/^hmsh:[^:]+:x:/,"")||"(engine)"}const xe=[{key:"pong",label:"Pong",description:"Roll call responses"},{key:"ping",label:"Ping",description:"Roll call broadcasts"},{key:"throttle",label:"Throttle",description:"Throttle commands"},{key:"job",label:"Job",description:"Job lifecycle events"},{key:"work",label:"Work",description:"Worker dispatch events"},{key:"activate",label:"Activate",description:"Worker activation"},{key:"cron",label:"Cron",description:"Cron schedule triggers"},{key:"user",label:"User",description:"User-defined messages"}];function T(t){return`${t.engine_id}-${t.worker_topic||"engine"}`}function et(t){const s=new Map;for(const n of t){if(!n.worker_topic)continue;const r=n.worker_topic;s.has(r)||s.set(r,[]),s.get(r).push(n)}return s}function tt(t){let s=0,n=0,r=0;for(const o of t)if(o.counts)for(const[a,m]of Object.entries(o.counts))s+=m,a==="200"?n+=m:a==="500"&&(r+=m);return{total:s,success:n,errors:r}}function st(){return{key:"throttle",label:"Throttle",render:t=>{const s=t.throttle;return s===-1?e.jsx("span",{className:"text-xs text-status-error font-medium",children:"Paused"}):s&&s>0?e.jsx("span",{className:"text-xs text-status-warning font-medium",children:H(s)}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"0"})},className:"w-24"}}function nt(){return{key:"memory",label:"Memory",render:t=>{var s,n;return e.jsx("span",{className:"text-xs font-mono text-text-tertiary",children:ce((s=t.system)==null?void 0:s.TotalMemoryGB,(n=t.system)==null?void 0:n.FreeMemoryGB)})},className:"w-36"}}function rt(t,s){return{key:"actions",label:"",render:n=>e.jsxs(ae,{children:[O(n)&&e.jsx(J,{icon:G,title:"Resume (remove throttle)",onClick:()=>s(n),colorClass:"text-text-tertiary hover:text-status-success"}),e.jsx(J,{icon:L,title:"Adjust throttle",onClick:()=>t(n)})]}),className:"w-16"}}function at(t){const s=t.profiles.some(n=>t.selectedIds.has(T(n)));return[{key:"select",label:e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",checked:t.profiles.length>0&&t.profiles.every(n=>t.selectedIds.has(T(n))),onChange:t.toggleAll,className:"rounded"}),s&&t.onBulkThrottle&&e.jsx(L,{className:"w-[14px] h-[14px] text-text-tertiary hover:text-accent cursor-pointer",strokeWidth:1.5,onClick:n=>{n.stopPropagation(),t.onBulkThrottle()}})]}),render:n=>e.jsx("input",{type:"checkbox",checked:t.selectedIds.has(T(n)),onChange:r=>{r.stopPropagation(),t.toggleCheckbox(n)},onClick:r=>r.stopPropagation(),className:"rounded"}),className:"w-16"},{key:"engine_id",label:"Engine ID",render:n=>e.jsx("span",{className:"text-xs font-mono text-text-tertiary",children:n.engine_id}),className:"w-48"},st(),{key:"processed",label:"Processed",render:n=>{const r=tt([n]);return e.jsx("span",{className:"text-xs font-mono text-text-tertiary",children:r.total.toLocaleString()})},className:"w-24"},nt(),rt(t.onRowThrottle,t.onResumeThrottle)]}function ot({activeAppId:t,allProfiles:s,profiles:n}){const r=ie(),[o,a]=l.useState(new Set),[m,i]=l.useState(!1),[f,c]=l.useState([]);l.useEffect(()=>{a(new Set)},[t]);const v=l.useCallback(p=>{a(R=>{const w=new Set(R),_=T(p);return w.has(_)?w.delete(_):w.add(_),w})},[]),j=l.useCallback(()=>{o.size===n.length?a(new Set):a(new Set(n.map(T)))},[n,o.size]),x=l.useMemo(()=>{const p=n.filter(k=>o.has(T(k)));if(p.length===0)return[];if(p.length===s.length)return[{label:"Entire Mesh"}];const R=p.filter(k=>!Q(k)),w=p.filter(Q),_=[];for(const k of R)_.push({label:`Engine ${k.engine_id}`,guid:k.engine_id});const M=new Map;for(const k of w){const E=k.worker_topic;M.has(E)||M.set(E,[]),M.get(E).push(k)}for(const[k,E]of M){const q=s.filter(P=>P.worker_topic===k);if(E.length===q.length)_.push({label:k,topic:k});else for(const P of E)_.push({label:`${k} ${P.engine_id}`,guid:P.engine_id})}return _},[n,s,o]);return{selectedIds:o,setSelectedIds:a,toggleCheckbox:v,toggleAll:j,throttleModalOpen:m,throttleTargets:f,selectedThrottleTargets:x,throttleMutation:r,handleBulkThrottle:p=>{const R=f.length>0?f:x;for(const w of R)r.mutate({appId:t,throttle:p,...w.topic?{topic:w.topic}:{},...w.guid?{guid:w.guid}:{}});i(!1),c([])},handleRowClick:p=>{const R=Q(p)?`${p.worker_topic} ${p.engine_id}`:`Engine ${p.engine_id}`;c([{label:R,guid:p.engine_id}]),i(!0)},handleBulkThrottleOpen:()=>{c(x),i(!0)},handleResumeThrottle:p=>{r.mutate({appId:t,throttle:0,guid:p.engine_id})},handleResumeQueue:p=>{r.mutate({appId:t,throttle:0,topic:p})},handleQueueThrottle:p=>{c([{label:p,topic:p}]),i(!0)},closeThrottleModal:()=>{i(!1),c([])}}}const lt=[{label:"Resume",ms:0},{label:"0.5s",ms:500},{label:"1s",ms:1e3},{label:"5s",ms:5e3},{label:"30s",ms:3e4},{label:"Pause",ms:-1}];function it({target:t}){const s=t.label==="Entire Mesh",n=t.label==="All Engines"||t.label.startsWith("Engine "),r=s?"bg-status-error/10 text-status-error":n?"bg-blue-500/10 text-blue-500":"bg-accent/[0.06] text-text-secondary",o=t.guid?"guid":t.topic?"topic":"mesh";return e.jsxs("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 text-[10px] font-medium rounded-lg ${r}`,children:[t.label,e.jsx("span",{className:"text-[8px] opacity-50",children:o})]})}function ct({open:t,onClose:s,targets:n,onApply:r,isPending:o}){const[a,m]=l.useState("0");return e.jsx(Je,{open:t,onClose:s,title:"Adjust Throttle",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2",children:"Targets"}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:n.map((i,f)=>e.jsx(it,{target:i},i.guid||i.topic||f))})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2",children:"Presets"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:lt.map(i=>e.jsx("button",{onClick:()=>{m(i.ms===-1?"-1":String(i.ms/1e3)),r(i.ms)},disabled:o,className:`px-3 py-1.5 text-xs rounded transition-colors ${i.ms===-1?"bg-status-error/10 text-status-error hover:bg-status-error/20":i.ms===0?"bg-status-success/10 text-status-success hover:bg-status-success/20":"bg-surface-sunken text-text-secondary hover:bg-surface-hover"} disabled:opacity-50`,children:i.label},i.label))})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2",children:"Custom (seconds between messages)"}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("input",{type:"number",step:"0.1",min:"-1",value:a,onChange:i=>m(i.target.value),className:"input text-xs py-1.5 px-3 w-28"}),e.jsx("button",{onClick:()=>{const i=parseFloat(a);isNaN(i)||r(i===-1?-1:Math.round(i*1e3))},disabled:o,className:"btn-primary text-xs py-1.5 px-4 disabled:opacity-50",children:"Apply"})]}),e.jsx("p",{className:"text-[10px] text-text-tertiary mt-1",children:"0 = resume, -1 = pause indefinitely"})]})]})})}function ut(){const{data:t}=le(),s=ie(),[n,r]=l.useState(!1),o=(t==null?void 0:t.apps)??[],a=m=>{for(const i of o)s.mutate({appId:i.appId,throttle:m});r(!1)};return n?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-status-error",children:"Pause all queues?"}),e.jsx("button",{onClick:()=>a(-1),className:"px-2.5 py-1 text-xs rounded-md bg-status-error text-white hover:bg-status-error/90 transition-colors",children:"Confirm"}),e.jsx("button",{onClick:()=>r(!1),className:"px-2.5 py-1 text-xs text-text-tertiary hover:text-text-primary transition-colors",children:"Cancel"})]}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{onClick:()=>r(!0),className:"flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-md text-status-error/80 hover:text-status-error hover:bg-status-error/10 transition-colors",title:"Pause all queues",children:[e.jsx(Me,{className:"w-3.5 h-3.5"}),"Pause All"]}),e.jsxs("button",{onClick:()=>a(0),className:"flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-md text-status-success/80 hover:text-status-success hover:bg-status-success/10 transition-colors",title:"Resume all queues",children:[e.jsx($e,{className:"w-3.5 h-3.5"}),"Resume All"]})]})}function xt({byStream:t,onNodeFilter:s}){const[n,r]=l.useState(!1);if(l.useEffect(()=>{r(!1);const c=requestAnimationFrame(()=>r(!0));return()=>cancelAnimationFrame(c)},[t]),t.length===0)return e.jsx("p",{className:"text-xs text-text-tertiary py-4 text-center",children:"No activity in this period"});const o=t.filter(c=>c.stream_type==="engine"),a=t.filter(c=>c.stream_type==="worker"),m=Math.max(...t.map(c=>c.count)),i=c=>{const v=m>0?c.count/m*100:0,j=c.stream_type==="engine",x=j?"(all engines)":ue(c.stream_name),h=j?"bg-blue-500/70":"bg-accent/60",S=j?"text-blue-500":"text-text-tertiary";return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:`text-[9px] font-mono ${S} w-36 truncate text-right shrink-0`,title:c.stream_name,children:x}),e.jsx("div",{className:"flex-1 h-4 bg-surface-sunken rounded overflow-hidden",children:e.jsx("div",{className:`h-full ${h} rounded transition-all duration-500 ease-out`,style:{width:n?`${v}%`:"0%"}})}),e.jsx("span",{className:"text-[10px] font-mono tabular-nums text-text-secondary w-12 text-right shrink-0",children:c.count.toLocaleString()})]},`${c.stream_type}-${c.stream_name}`)},f="text-[9px] uppercase tracking-widest font-semibold mb-1 cursor-pointer hover:underline";return e.jsxs("div",{className:"space-y-1.5",children:[o.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:`${f} text-blue-500/70 hover:text-blue-500`,onClick:()=>s==null?void 0:s("engines"),children:"Engine Message Volume"}),o.map(i),a.length>0&&e.jsx("div",{className:"h-2"})]}),a.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:`${f} text-accent/70 hover:text-accent`,onClick:()=>s==null?void 0:s("workers"),children:"Worker Message Volume"}),a.map(i)]})]})}function dt({queue:t,workers:s,expanded:n,onToggle:r,onWorkerClick:o,onResumeThrottle:a,onQueueThrottle:m,onResumeQueue:i,byStream:f,activeDuration:c}){const v=l.useMemo(()=>{const x=f.find(h=>h.stream_type==="worker"&&ue(h.stream_name)===t);return(x==null?void 0:x.count)??0},[f,t]),j=l.useMemo(()=>[{key:"engine_id",label:"Worker ID",render:x=>e.jsx("span",{className:"text-xs font-mono text-text-tertiary",children:x.engine_id}),className:"w-48"},{key:"throttle",label:"Throttle",render:x=>{const h=x.throttle;return h===-1?e.jsx("span",{className:"text-xs text-status-error font-medium",children:"Paused"}):h&&h>0?e.jsx("span",{className:"text-xs text-status-warning font-medium",children:H(h)}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"0"})},className:"w-24"},{key:"memory",label:"Memory",render:x=>{var h,S;return e.jsx("span",{className:"text-xs font-mono text-text-tertiary",children:ce((h=x.system)==null?void 0:h.TotalMemoryGB,(S=x.system)==null?void 0:S.FreeMemoryGB)})},className:"w-36"},{key:"actions",label:"",render:x=>e.jsxs(ae,{children:[O(x)&&e.jsx(J,{icon:G,title:"Resume (remove throttle)",onClick:()=>a(x),colorClass:"text-text-tertiary hover:text-status-success"}),e.jsx(J,{icon:L,title:"Adjust throttle",onClick:()=>o(x)})]}),className:"w-16"}],[o,a]);return e.jsxs("div",{children:[e.jsxs("button",{onClick:()=>r(t),className:"group/row relative flex items-center gap-3 w-full py-2 hover:bg-surface-hover transition-colors text-left rounded",children:[e.jsx(Pe,{className:`w-3.5 h-3.5 text-text-tertiary/50 transition-transform duration-200 ${n?"rotate-90":""}`,strokeWidth:2}),e.jsx(Le,{queue:t,size:"sm"}),e.jsx("span",{className:"flex-1"}),e.jsxs("span",{className:`flex items-center gap-1 text-xs w-24 ${s.some(O)?"text-status-warning":"text-text-tertiary"}`,children:[e.jsx(Fe,{className:"w-3 h-3 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"font-mono tabular-nums",children:s.length}),e.jsx("span",{children:"workers"})]}),e.jsx("span",{className:"flex items-center gap-1 text-xs font-mono text-text-tertiary w-28 justify-end mr-16",children:v>0?e.jsxs(e.Fragment,{children:[e.jsx(Ae,{className:"w-3 h-3 shrink-0",strokeWidth:1.5}),v.toLocaleString()," in ",c]}):e.jsx("span",{className:"text-text-tertiary/40",children:"—"})}),e.jsxs("span",{className:"absolute right-3 top-1/2 -translate-y-1/2 opacity-0 group-hover/row:opacity-100 transition-opacity flex items-center gap-2",children:[s.some(O)&&e.jsx(G,{className:"w-4 h-4 text-text-tertiary hover:text-status-success",strokeWidth:1.5,onClick:x=>{x.stopPropagation(),i(t)}}),e.jsx(L,{className:"w-4 h-4 text-text-tertiary hover:text-accent",strokeWidth:1.5,onClick:x=>{x.stopPropagation(),m(t)}})]})]}),e.jsx(W,{open:n,children:e.jsx("div",{className:"ml-6",children:e.jsx(oe,{columns:j,data:s,keyFn:T,onRowClick:o,emptyMessage:"No workers",inline:!0})})})]})}let mt=0;function pt({event:t}){var r,o,a;const[s,n]=l.useState(!1);return e.jsxs("div",{className:"border-b border-surface-border/50 last:border-b-0",children:[e.jsxs("button",{onClick:()=>n(!s),className:"flex items-center gap-2 py-1.5 w-full text-left hover:bg-surface-hover/50 transition-colors",children:[e.jsx("span",{className:"text-[9px] font-mono text-text-tertiary whitespace-nowrap tabular-nums shrink-0",children:new Date(t.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}),e.jsx("span",{className:`text-[9px] font-medium px-1 py-0.5 rounded ${Xe[t.type]||"text-text-tertiary"} bg-surface-sunken whitespace-nowrap shrink-0`,children:t.type}),e.jsxs("span",{className:"text-[9px] text-text-tertiary font-mono flex-1 min-w-0 break-all",children:[(r=t.data)!=null&&r.guid?String(t.data.guid):"",(o=t.data)!=null&&o.topic?` ${String(t.data.topic)}`:"",t.type==="throttle"?` → ${H((a=t.data)==null?void 0:a.throttle)}`:""]}),e.jsx("svg",{className:`w-2.5 h-2.5 text-text-tertiary shrink-0 transition-transform duration-150 ${s?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"})})]}),e.jsx(W,{open:s,children:e.jsx("div",{className:"pb-2",children:e.jsx(Ee,{data:t.data})})})]})}function ht({channels:t,onToggle:s,customFilter:n,onCustomFilterChange:r}){return e.jsxs("div",{className:"space-y-3 pb-3 border-b border-surface-border mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary",children:"Channels"}),e.jsx("p",{className:"text-[9px] text-text-tertiary",children:"Unchecked channels are dropped before buffering"})]}),e.jsx("div",{className:"grid grid-cols-2 gap-1",children:xe.map(o=>e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer py-0.5",children:[e.jsx("input",{type:"checkbox",checked:t.has(o.key),onChange:()=>s(o.key),className:"w-3 h-3 rounded border-border accent-accent"}),e.jsx("span",{className:"text-[10px] text-text-secondary",title:o.description,children:o.label})]},o.key))}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",children:"Text Filter"}),e.jsx("input",{type:"text",value:n,onChange:o=>r(o.target.value),placeholder:"pong",className:"input text-[10px] font-mono py-1 px-2 w-full"}),e.jsxs("p",{className:"text-[9px] text-text-tertiary mt-1",children:["Filter by event type, e.g. ",e.jsx("span",{className:"font-mono",children:"pong"}),", ",e.jsx("span",{className:"font-mono",children:"throttle"}),", or any text in the event data."]})]})]})}function gt({bridgeActive:t}){const[s,n]=l.useState(!1),[r,o]=l.useState(!1),[a,m]=l.useState([]),[i,f]=l.useState(()=>new Set(xe.map(u=>u.key))),[c,v]=l.useState(""),j=l.useRef(i);l.useEffect(()=>{j.current=i},[i]);const x=l.useRef(c);l.useEffect(()=>{x.current=c},[c]);const h=u=>{f(g=>{const y=new Set(g);return y.has(u)?y.delete(u):y.add(u),y})};_e("lt.events.mesh.>",l.useCallback(u=>{var C;const g=((C=u.type)==null?void 0:C.replace("mesh.",""))||"unknown";if(!j.current.has(g))return;const y=x.current;y&&!`${g} ${JSON.stringify(u.data||u)}`.toLowerCase().includes(y.toLowerCase())||m($=>[{id:++mt,type:g,timestamp:u.timestamp||new Date().toISOString(),data:u.data||u},...$].slice(0,Ze))},[]));const S=()=>m([]);return e.jsxs("div",{className:"border-l border-surface-border pl-6 pt-4 min-h-[300px] sticky top-14 self-start max-h-[calc(100vh-8rem)] flex flex-col",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary",children:"Event Stream"}),e.jsx(Qe,{className:`w-3 h-3 ${t?"text-status-success animate-pulse":"text-text-tertiary"}`}),e.jsx("span",{className:"text-[9px] text-text-tertiary",children:t?"Live":"..."}),e.jsxs("span",{className:"ml-auto flex items-center gap-1",children:[e.jsx("button",{onClick:()=>{n(u=>!u),o(!1)},className:`p-1 rounded transition-colors ${s?"text-accent bg-accent/10":"text-text-tertiary hover:text-text-primary"}`,title:"Configure channels",children:e.jsx(Oe,{className:"w-3.5 h-3.5"})}),e.jsx("button",{onClick:()=>{o(u=>!u),n(!1)},className:`p-1 rounded transition-colors ${r?"text-accent bg-accent/10":"text-text-tertiary hover:text-text-primary"}`,title:"View raw JSON",children:e.jsx(Ie,{className:"w-3.5 h-3.5"})}),a.length>0&&e.jsx("button",{onClick:S,className:"p-1 rounded text-text-tertiary hover:text-text-primary transition-colors",title:"Clear events",children:e.jsx(Be,{className:"w-3.5 h-3.5"})})]})]}),e.jsx(W,{open:s,children:e.jsx(ht,{channels:i,onToggle:h,customFilter:c,onCustomFilterChange:v})}),e.jsx(W,{open:r,children:e.jsx("div",{className:"pb-3 border-b border-surface-border mb-3",children:e.jsx("pre",{className:"text-[9px] font-mono text-text-tertiary bg-surface-sunken rounded-lg p-3 max-h-[50vh] overflow-auto whitespace-pre-wrap",children:JSON.stringify(a.slice(0,50),null,2)})})}),a.length>0&&e.jsxs("p",{className:"text-[9px] text-text-tertiary mb-2",children:[a.length," events"]}),e.jsx("div",{className:"flex-1 overflow-y-auto",children:a.length===0?e.jsx("p",{className:"text-xs text-text-tertiary py-6 text-center",children:t?"Waiting for events...":"Subscribing..."}):a.map(u=>e.jsx(pt,{event:u},u.id))})]})}function ft({collapsed:t,toggleSection:s,activeDuration:n,streamStats:r,isLoading:o,queueMap:a,expandedQueues:m,toggleQueue:i,allQueuesExpanded:f,toggleAllQueues:c,handleRowClick:v,handleResumeThrottle:j,handleQueueThrottle:x,handleResumeQueue:h,engineColumns:S,engines:u,bridgeActive:g}){return e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[1fr_340px] gap-6",children:[e.jsxs("div",{className:"flex flex-col gap-12 mt-10",children:[e.jsx(V,{title:`Stream Volume (${n})`,sectionKey:"volume",isCollapsed:!!t.volume,onToggle:s,contentClassName:"mt-4 ml-7",children:e.jsx(xt,{byStream:(r==null?void 0:r.byStream)??[],onNodeFilter:()=>{},onQueueFilter:()=>{}})}),e.jsx(V,{title:"Worker Queues",sectionKey:"queues",isCollapsed:!!t.queues,onToggle:s,contentClassName:"mt-4 ml-7 flex flex-col gap-0",children:o?e.jsx("p",{className:"text-xs text-text-tertiary",children:"Discovering mesh nodes..."}):a.size===0?e.jsx("p",{className:"text-xs text-text-tertiary",children:'No worker queues found. Click "Roll Call" to discover.'}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex justify-end mb-2",children:e.jsx("button",{onClick:c,className:"text-[10px] text-accent hover:underline",children:f?"Collapse all":"Expand all"})}),[...a.entries()].sort(([y],[C])=>y.localeCompare(C)).map(([y,C])=>e.jsx(dt,{queue:y,workers:C,expanded:m.has(y),onToggle:i,onWorkerClick:v,onResumeThrottle:j,onQueueThrottle:x,onResumeQueue:h,byStream:(r==null?void 0:r.byStream)??[],activeDuration:n},y))]})}),e.jsx(V,{title:"Engines",sectionKey:"engines",isCollapsed:!!t.engines,onToggle:s,contentClassName:"mt-4 ml-7",children:e.jsx(oe,{columns:S,data:u,keyFn:T,onRowClick:v,isLoading:o,emptyMessage:o?"Discovering engines...":"No engines found.",inline:!0})})]}),e.jsx(gt,{bridgeActive:g})]})}function Mt(){var ne;const{data:t}=le(),s=(t==null?void 0:t.apps)??[],{filters:n,setFilter:r}=Re({filters:{app_id:"",duration:"1h"}}),o=((ne=s[0])==null?void 0:ne.appId)??"durable",a=n.app_id||o,m=n.duration||"1h",i=De(),f=6e4,{data:c,isLoading:v,error:j,refetch:x,isFetching:h}=ze(a,f),{data:S}=He(a,m,void 0,f),u=l.useMemo(()=>[...(c==null?void 0:c.profiles)??[]].sort((b,N)=>{const A=b.worker_topic||b.stream||"",B=N.worker_topic||N.stream||"";return!b.worker_topic&&N.worker_topic?-1:b.worker_topic&&!N.worker_topic?1:A.localeCompare(B)}),[c==null?void 0:c.profiles]),g=l.useMemo(()=>u.filter(d=>!Q(d)),[u]),y=l.useMemo(()=>u.filter(Q),[u]),C=l.useMemo(()=>et(u),[u]),$=u.filter(O).length,p=l.useMemo(()=>{const d=new Set(s.map(b=>b.appId));return a&&d.add(a),[...d].sort().map(b=>({value:b,label:b}))},[s,a]),[R,w]=l.useState(new Set),_=l.useCallback(d=>{w(b=>{const N=new Set(b);return N.has(d)?N.delete(d):N.add(d),N})},[]),M=C.size>0&&[...C.keys()].every(d=>R.has(d)),k=l.useCallback(()=>{w(M?new Set:new Set(C.keys()))},[M,C]),E="lt:controlplane:collapsed",[q,P]=l.useState(()=>{try{return JSON.parse(localStorage.getItem(E)||"{}")}catch{return{}}}),de=l.useCallback(d=>{P(b=>{const N={...b,[d]:!b[d]};return localStorage.setItem(E,JSON.stringify(N)),N})},[]),{selectedIds:F,setSelectedIds:D,toggleCheckbox:Y,throttleModalOpen:me,throttleTargets:X,selectedThrottleTargets:pe,throttleMutation:he,handleBulkThrottle:ge,handleRowClick:K,handleBulkThrottleOpen:Z,handleResumeThrottle:U,handleResumeQueue:fe,handleQueueThrottle:be,closeThrottleModal:ye}=ot({activeAppId:a,allProfiles:u,profiles:u}),ee=l.useCallback(()=>{const d=new Set(g.map(T)),b=g.length>0&&g.every(N=>F.has(T(N)));D(N=>{const A=new Set(N);for(const B of d)b?A.delete(B):A.add(B);return A})},[g,F,D]),te=l.useCallback(()=>{g.filter(b=>F.has(T(b))).length!==0&&Z()},[g,F,Z]),je=l.useMemo(()=>at({profiles:g,selectedIds:F,toggleAll:ee,toggleCheckbox:Y,onRowThrottle:K,onResumeThrottle:U,onBulkThrottle:te}),[g,F,ee,Y,K,U,te]),ke=l.useMemo(()=>{const d=[{label:"Engines",value:g.length,dotClass:"bg-blue-500"},{label:"Workers",value:y.length,dotClass:"bg-text-secondary"},{label:"Queues",value:C.size}];return $>0&&d.push({label:"Throttled",value:$,dotClass:"bg-status-warning"}),d},[g.length,y.length,C.size,$]),[se,Ne]=l.useState(!1),Ce=l.useCallback(()=>{i.mutate({appId:a},{onSuccess:()=>Ne(!0)})},[a,i]);return l.useEffect(()=>{!se&&a&&Ce()},[a]),e.jsxs("div",{children:[e.jsx(ve,{title:"Task Queues",docsHash:"#docs:dashboard.md:task-queues",stats:ke,actions:e.jsx(ut,{})}),e.jsxs(Se,{actions:e.jsx("div",{className:"flex items-center gap-1",children:Ye.map(d=>e.jsx("button",{onClick:()=>r("duration",d.value),className:`px-3 py-1 text-xs rounded-full transition-colors ${m===d.value?"bg-accent text-text-inverse":"text-text-tertiary hover:text-text-primary hover:bg-surface-hover"}`,children:d.label},d.value))}),children:[e.jsx(Te,{label:"Application",value:n.app_id,onChange:d=>r("app_id",d),options:p}),e.jsxs("button",{onClick:()=>x(),disabled:h,className:"flex items-center gap-1.5 px-3 py-1.5 text-xs text-text-tertiary hover:text-text-primary transition-colors disabled:opacity-50",children:[e.jsx(We,{className:`w-3.5 h-3.5 ${h?"animate-spin":""}`}),"Roll Call"]})]}),j&&e.jsx("div",{className:"mb-6 px-4 py-3 rounded bg-status-error/10 border border-status-error/20",children:e.jsx("p",{className:"text-xs text-status-error font-medium",children:j.message==="Session expired"?"Session expired — please log in again.":`Failed to load mesh data: ${j.message}`})}),e.jsx(ft,{collapsed:q,toggleSection:de,activeDuration:m,streamStats:S,isLoading:v,queueMap:C,expandedQueues:R,toggleQueue:_,allQueuesExpanded:M,toggleAllQueues:k,handleRowClick:K,handleResumeThrottle:U,handleQueueThrottle:be,handleResumeQueue:fe,engineColumns:je,engines:g,bridgeActive:se}),e.jsx(ct,{open:me,onClose:ye,targets:X.length>0?X:pe,onApply:ge,isPending:he.isPending})]})}export{Mt as ControlPlanePage};
2
- //# sourceMappingURL=index-BMpoMc4A.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BMpoMc4A.js","sources":["../../src/api/controlplane.ts","../../src/pages/admin/controlplane/helpers.ts","../../src/pages/admin/controlplane/columns.tsx","../../src/pages/admin/controlplane/useMeshSelection.ts","../../src/pages/admin/controlplane/ThrottleModal.tsx","../../src/pages/admin/controlplane/EmergencyControls.tsx","../../src/pages/admin/controlplane/StreamVolumeChart.tsx","../../src/pages/admin/controlplane/QueueCard.tsx","../../src/pages/admin/controlplane/QuorumFeed.tsx","../../src/pages/admin/controlplane/ControlPlaneContent.tsx","../../src/pages/admin/controlplane/ControlPlanePage.tsx"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface ControlPlaneApp {\n appId: string;\n version: string;\n}\n\nexport interface QuorumProfile {\n namespace: string;\n app_id: string;\n engine_id: string;\n entity?: string;\n worker_topic?: string;\n stream?: string;\n stream_depth?: number;\n counts?: Record<string, number>;\n inited?: string;\n timestamp?: string;\n throttle?: number;\n reclaimDelay?: number;\n reclaimCount?: number;\n system?: {\n TotalMemoryGB: string;\n FreeMemoryGB: string;\n UsedMemoryGB: string;\n CPULoad: Array<Record<string, string>>;\n NetworkStats: Array<Record<string, unknown>>;\n };\n signature?: string;\n}\n\n// ── API functions ───────────────────────────────────────────────────────────\n\nfunction fetchApps() {\n return apiFetch<{ apps: ControlPlaneApp[] }>('/controlplane/apps');\n}\n\nfunction fetchRollCall(appId: string) {\n return apiFetch<{ profiles: QuorumProfile[] }>(`/controlplane/rollcall?app_id=${encodeURIComponent(appId)}`);\n}\n\nfunction postThrottle(body: { appId: string; throttle: number; topic?: string; guid?: string }) {\n return apiFetch<{ success: boolean }>('/controlplane/throttle', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n}\n\nfunction postSubscribe(body: { appId: string }) {\n return apiFetch<{ subscribed: boolean; appId: string }>('/controlplane/subscribe', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n}\n\nexport interface StreamStats {\n pending: number;\n processed: number;\n byStream: Array<{ stream_type: 'engine' | 'worker'; stream_name: string; count: number }>;\n}\n\nfunction fetchStreamStats(appId: string, duration: string, stream?: string) {\n let url = `/controlplane/streams?app_id=${encodeURIComponent(appId)}&duration=${encodeURIComponent(duration)}`;\n if (stream) url += `&stream=${encodeURIComponent(stream)}`;\n return apiFetch<StreamStats>(url);\n}\n\n// ── Hooks ───────────────────────────────────────────────────────────────────\n\nexport function useControlPlaneApps() {\n return useQuery({\n queryKey: ['controlplane', 'apps'],\n queryFn: fetchApps,\n staleTime: 60_000,\n });\n}\n\nexport function useRollCall(appId: string, refetchInterval?: number | false) {\n return useQuery({\n queryKey: ['controlplane', 'rollcall', appId],\n queryFn: () => fetchRollCall(appId),\n enabled: !!appId,\n refetchInterval: refetchInterval ?? false,\n });\n}\n\nexport function useThrottle() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: postThrottle,\n onSuccess: () => {\n // Delay refetch so mesh members have time to process the throttle message\n setTimeout(() => {\n qc.invalidateQueries({ queryKey: ['controlplane', 'rollcall'] });\n }, 1500);\n },\n });\n}\n\nexport function useStreamStats(appId: string, duration: string, stream?: string, refetchInterval?: number | false) {\n return useQuery({\n queryKey: ['controlplane', 'streams', appId, duration, stream ?? ''],\n queryFn: () => fetchStreamStats(appId, duration, stream),\n enabled: !!appId,\n staleTime: 15_000,\n refetchInterval: refetchInterval ?? false,\n });\n}\n\nexport function useSubscribeMesh() {\n return useMutation({\n mutationFn: postSubscribe,\n });\n}\n","import type { QuorumProfile } from '../../../api/controlplane';\n\nexport const DURATIONS = [\n { label: '15m', value: '15m' },\n { label: '30m', value: '30m' },\n { label: '1h', value: '1h' },\n { label: '1d', value: '1d' },\n { label: '7d', value: '7d' },\n] as const;\n\nexport type Duration = (typeof DURATIONS)[number]['value'];\n\nexport interface QuorumEvent {\n id: number;\n type: string;\n timestamp: string;\n data: Record<string, unknown>;\n}\n\nexport const EVENT_TYPE_COLORS: Record<string, string> = {\n pong: 'text-status-success',\n ping: 'text-accent',\n throttle: 'text-status-warning',\n job: 'text-purple-400',\n work: 'text-text-secondary',\n activate: 'text-status-error',\n cron: 'text-text-tertiary',\n user: 'text-text-secondary',\n};\n\nexport const MAX_EVENTS = 250;\n\nexport function isWorker(p: QuorumProfile): boolean {\n return !!p.worker_topic;\n}\n\nexport function isThrottled(p: QuorumProfile): boolean {\n return typeof p.throttle === 'number' && p.throttle !== 0;\n}\n\nexport function formatThrottleHuman(ms?: number): string {\n if (ms === undefined || ms === 0) return 'Normal';\n if (ms === -1) return 'Paused';\n if (ms >= 86_400_000) return `${(ms / 86_400_000).toFixed(0)}d`;\n if (ms >= 3_600_000) return `${(ms / 3_600_000).toFixed(1)}h`;\n if (ms >= 60_000) return `${(ms / 60_000).toFixed(1)}m`;\n if (ms >= 1000) return `${(ms / 1000).toFixed(1)}s`;\n return `${ms}ms`;\n}\n\nexport function formatMemory(total?: string, free?: string): string {\n if (!total || !free) return '—';\n const t = parseFloat(total);\n const f = parseFloat(free);\n if (isNaN(t) || isNaN(f)) return '—';\n return `${(t - f).toFixed(1)} / ${t.toFixed(1)} GB`;\n}\n\nexport function stripStreamPrefix(name: string): string {\n return name.replace(/^hmsh:[^:]+:x:/, '') || '(engine)';\n}\n\n/** Engine streams have no suffix after hmsh:{app}:x: */\nexport function isEngineStream(streamName: string): boolean {\n return stripStreamPrefix(streamName) === '(engine)';\n}\n\nexport type NodeFilter = 'all' | 'workers' | 'engines';\n\n/** Known quorum message types published via the bridge. */\nexport const QUORUM_CHANNELS = [\n { key: 'pong', label: 'Pong', description: 'Roll call responses' },\n { key: 'ping', label: 'Ping', description: 'Roll call broadcasts' },\n { key: 'throttle', label: 'Throttle', description: 'Throttle commands' },\n { key: 'job', label: 'Job', description: 'Job lifecycle events' },\n { key: 'work', label: 'Work', description: 'Worker dispatch events' },\n { key: 'activate', label: 'Activate', description: 'Worker activation' },\n { key: 'cron', label: 'Cron', description: 'Cron schedule triggers' },\n { key: 'user', label: 'User', description: 'User-defined messages' },\n] as const;\n\n/** Typed throttle target with display label and API params. */\nexport interface ThrottleTarget {\n label: string;\n /** API param: topic-based throttle (queues, all engines) */\n topic?: string;\n /** API param: guid-based throttle (single engine/worker) */\n guid?: string;\n}\n\nexport const NODE_FILTER_OPTIONS = [\n { value: 'all', label: 'All Nodes' },\n { value: 'workers', label: 'Workers' },\n { value: 'engines', label: 'Engines' },\n] as const;\n\nexport function rowKey(p: QuorumProfile): string {\n return `${p.engine_id}-${p.worker_topic || 'engine'}`;\n}\n\n// ── Queue-level helpers ────────────────────────────────────────────────\n\n/** Group worker profiles by `worker_topic` (engines excluded). */\nexport function groupByQueue(profiles: QuorumProfile[]): Map<string, QuorumProfile[]> {\n const map = new Map<string, QuorumProfile[]>();\n for (const p of profiles) {\n if (!p.worker_topic) continue;\n const q = p.worker_topic;\n if (!map.has(q)) map.set(q, []);\n map.get(q)!.push(p);\n }\n return map;\n}\n\n/** Aggregate `counts` across profiles: 200 = success, 500 = error, all = total. */\nexport function sumCounts(profiles: QuorumProfile[]): { total: number; success: number; errors: number } {\n let total = 0;\n let success = 0;\n let errors = 0;\n for (const p of profiles) {\n if (!p.counts) continue;\n for (const [code, n] of Object.entries(p.counts)) {\n total += n;\n if (code === '200') success += n;\n else if (code === '500') errors += n;\n }\n }\n return { total, success, errors };\n}\n\n/** Sum `stream_depth` across profiles. */\nexport function totalPending(profiles: QuorumProfile[]): number {\n let sum = 0;\n for (const p of profiles) {\n if (typeof p.stream_depth === 'number') sum += p.stream_depth;\n }\n return sum;\n}\n\n/** Derive queue health from member profiles. */\nexport function queueHealth(profiles: QuorumProfile[]): 'healthy' | 'degraded' | 'paused' {\n if (profiles.length === 0) return 'healthy';\n const allPaused = profiles.every((p) => p.throttle === -1);\n if (allPaused) return 'paused';\n const { errors } = sumCounts(profiles);\n if (errors > 0 || profiles.some(isThrottled)) return 'degraded';\n return 'healthy';\n}\n","import { Gauge, CirclePlay } from 'lucide-react';\nimport type { Column } from '../../../components/common/data/DataTable';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport type { QuorumProfile } from '../../../api/controlplane';\nimport { isThrottled, formatThrottleHuman, formatMemory, rowKey, sumCounts } from './helpers';\n\ninterface ColumnOptions {\n profiles: QuorumProfile[];\n selectedIds: Set<string>;\n toggleAll: () => void;\n toggleCheckbox: (profile: QuorumProfile) => void;\n onRowThrottle: (profile: QuorumProfile) => void;\n onResumeThrottle: (profile: QuorumProfile) => void;\n onBulkThrottle?: () => void;\n}\n\nfunction throttleColumn(): Column<QuorumProfile> {\n return {\n key: 'throttle',\n label: 'Throttle',\n render: (row) => {\n const t = row.throttle;\n if (t === -1) return <span className=\"text-xs text-status-error font-medium\">Paused</span>;\n if (t && t > 0) return <span className=\"text-xs text-status-warning font-medium\">{formatThrottleHuman(t)}</span>;\n return <span className=\"text-xs text-text-tertiary\">0</span>;\n },\n className: 'w-24',\n };\n}\n\nfunction memoryColumn(): Column<QuorumProfile> {\n return {\n key: 'memory',\n label: 'Memory',\n render: (row) => (\n <span className=\"text-xs font-mono text-text-tertiary\">\n {formatMemory(row.system?.TotalMemoryGB, row.system?.FreeMemoryGB)}\n </span>\n ),\n className: 'w-36',\n };\n}\n\nfunction actionColumn(\n onRowThrottle: (p: QuorumProfile) => void,\n onResumeThrottle: (p: QuorumProfile) => void,\n): Column<QuorumProfile> {\n return {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n {isThrottled(row) && (\n <RowAction\n icon={CirclePlay}\n title=\"Resume (remove throttle)\"\n onClick={() => onResumeThrottle(row)}\n colorClass=\"text-text-tertiary hover:text-status-success\"\n />\n )}\n <RowAction icon={Gauge} title=\"Adjust throttle\" onClick={() => onRowThrottle(row)} />\n </RowActionGroup>\n ),\n className: 'w-16',\n };\n}\n\n/** Columns for the Engines section DataTable. */\nexport function getEngineColumns(opts: ColumnOptions): Column<QuorumProfile>[] {\n const hasSelection = opts.profiles.some((p) => opts.selectedIds.has(rowKey(p)));\n return [\n {\n key: 'select',\n label: (\n <span className=\"inline-flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={opts.profiles.length > 0 && opts.profiles.every((p) => opts.selectedIds.has(rowKey(p)))}\n onChange={opts.toggleAll}\n className=\"rounded\"\n />\n {hasSelection && opts.onBulkThrottle && (\n <Gauge\n className=\"w-[14px] h-[14px] text-text-tertiary hover:text-accent cursor-pointer\"\n strokeWidth={1.5}\n onClick={(e) => { e.stopPropagation(); opts.onBulkThrottle!(); }}\n />\n )}\n </span>\n ) as any,\n render: (row) => (\n <input\n type=\"checkbox\"\n checked={opts.selectedIds.has(rowKey(row))}\n onChange={(e) => { e.stopPropagation(); opts.toggleCheckbox(row); }}\n onClick={(e) => e.stopPropagation()}\n className=\"rounded\"\n />\n ),\n className: 'w-16',\n },\n {\n key: 'engine_id',\n label: 'Engine ID',\n render: (row) => (\n <span className=\"text-xs font-mono text-text-tertiary\">{row.engine_id}</span>\n ),\n className: 'w-48',\n },\n throttleColumn(),\n {\n key: 'processed',\n label: 'Processed',\n render: (row) => {\n const c = sumCounts([row]);\n return <span className=\"text-xs font-mono text-text-tertiary\">{c.total.toLocaleString()}</span>;\n },\n className: 'w-24',\n },\n memoryColumn(),\n actionColumn(opts.onRowThrottle, opts.onResumeThrottle),\n ];\n}\n","import { useState, useCallback, useEffect, useMemo } from 'react';\n\nimport type { QuorumProfile } from '../../../api/controlplane';\nimport { useThrottle } from '../../../api/controlplane';\nimport { isWorker, rowKey, type ThrottleTarget } from './helpers';\n\ninterface UseMeshSelectionOptions {\n activeAppId: string;\n allProfiles: QuorumProfile[];\n profiles: QuorumProfile[];\n}\n\nexport function useMeshSelection({\n activeAppId,\n allProfiles,\n profiles,\n}: UseMeshSelectionOptions) {\n const throttleMutation = useThrottle();\n\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());\n const [throttleModalOpen, setThrottleModalOpen] = useState(false);\n const [throttleTargets, setThrottleTargets] = useState<ThrottleTarget[]>([]);\n\n useEffect(() => { setSelectedIds(new Set()); }, [activeAppId]);\n\n const toggleCheckbox = useCallback((profile: QuorumProfile) => {\n setSelectedIds((prev) => {\n const next = new Set(prev);\n const key = rowKey(profile);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n }, []);\n\n const toggleAll = useCallback(() => {\n if (selectedIds.size === profiles.length) {\n setSelectedIds(new Set());\n } else {\n setSelectedIds(new Set(profiles.map(rowKey)));\n }\n }, [profiles, selectedIds.size]);\n\n /**\n * Build throttle targets from checkbox selection.\n *\n * Smart grouping:\n * - All nodes selected -> no topic/guid (entire mesh)\n * - All engines selected -> topic = engine stream (all engines)\n * - All workers on a queue selected -> topic = queue (all workers on queue)\n * - Subset of a group -> individual guid targets\n */\n const selectedThrottleTargets = useMemo((): ThrottleTarget[] => {\n const selected = profiles.filter((p) => selectedIds.has(rowKey(p)));\n if (selected.length === 0) return [];\n\n // All nodes -> entire mesh\n if (selected.length === allProfiles.length) {\n return [{ label: 'Entire Mesh' }];\n }\n\n const engines = selected.filter((p) => !isWorker(p));\n const workers = selected.filter(isWorker);\n const targets: ThrottleTarget[] = [];\n\n // Engines — always guid-per-engine (each engine subscribes to its own guid channel)\n for (const e of engines) {\n targets.push({ label: `Engine ${e.engine_id}`, guid: e.engine_id });\n }\n\n // Workers — topic targets the queue; guid targets a single instance\n const queues = new Map<string, QuorumProfile[]>();\n for (const w of workers) {\n const q = w.worker_topic!;\n if (!queues.has(q)) queues.set(q, []);\n queues.get(q)!.push(w);\n }\n for (const [queue, members] of queues) {\n const allOnQueue = allProfiles.filter((p) => p.worker_topic === queue);\n if (members.length === allOnQueue.length) {\n targets.push({ label: queue, topic: queue });\n } else {\n for (const w of members) {\n targets.push({ label: `${queue} ${w.engine_id}`, guid: w.engine_id });\n }\n }\n }\n\n return targets;\n }, [profiles, allProfiles, selectedIds]);\n\n // ── Throttle handlers ─────────────────────────────────────────\n const handleBulkThrottle = (ms: number) => {\n const targets = throttleTargets.length > 0 ? throttleTargets : selectedThrottleTargets;\n for (const t of targets) {\n throttleMutation.mutate({\n appId: activeAppId,\n throttle: ms,\n ...(t.topic ? { topic: t.topic } : {}),\n ...(t.guid ? { guid: t.guid } : {}),\n });\n }\n setThrottleModalOpen(false);\n setThrottleTargets([]);\n };\n\n const handleRowClick = (profile: QuorumProfile) => {\n const label = isWorker(profile)\n ? `${profile.worker_topic} ${profile.engine_id}`\n : `Engine ${profile.engine_id}`;\n // guid-only: workers and engines both subscribe to their own guid channel\n setThrottleTargets([{ label, guid: profile.engine_id }]);\n setThrottleModalOpen(true);\n };\n\n const handleBulkThrottleOpen = () => {\n setThrottleTargets(selectedThrottleTargets);\n setThrottleModalOpen(true);\n };\n\n const handleResumeThrottle = (profile: QuorumProfile) => {\n // guid-only: both engines and workers subscribe to their own guid channel\n throttleMutation.mutate({ appId: activeAppId, throttle: 0, guid: profile.engine_id });\n };\n\n const handleResumeQueue = (queueName: string) => {\n throttleMutation.mutate({ appId: activeAppId, throttle: 0, topic: queueName });\n };\n\n const handleQueueThrottle = (queueName: string) => {\n setThrottleTargets([{ label: queueName, topic: queueName }]);\n setThrottleModalOpen(true);\n };\n\n const closeThrottleModal = () => {\n setThrottleModalOpen(false);\n setThrottleTargets([]);\n };\n\n return {\n selectedIds,\n setSelectedIds,\n toggleCheckbox,\n toggleAll,\n throttleModalOpen,\n throttleTargets,\n selectedThrottleTargets,\n throttleMutation,\n handleBulkThrottle,\n handleRowClick,\n handleBulkThrottleOpen,\n handleResumeThrottle,\n handleResumeQueue,\n handleQueueThrottle,\n closeThrottleModal,\n };\n}\n","import { useState } from 'react';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport type { ThrottleTarget } from './helpers';\n\ninterface ThrottleModalProps {\n open: boolean;\n onClose: () => void;\n targets: ThrottleTarget[];\n onApply: (ms: number) => void;\n isPending: boolean;\n}\n\nconst PRESETS = [\n { label: 'Resume', ms: 0 },\n { label: '0.5s', ms: 500 },\n { label: '1s', ms: 1000 },\n { label: '5s', ms: 5000 },\n { label: '30s', ms: 30000 },\n { label: 'Pause', ms: -1 },\n];\n\nfunction TargetPill({ target }: { target: ThrottleTarget }) {\n const isMesh = target.label === 'Entire Mesh';\n const isEngine = target.label === 'All Engines' || target.label.startsWith('Engine ');\n const color = isMesh\n ? 'bg-status-error/10 text-status-error'\n : isEngine\n ? 'bg-blue-500/10 text-blue-500'\n : 'bg-accent/[0.06] text-text-secondary';\n const scope = target.guid ? 'guid' : target.topic ? 'topic' : 'mesh';\n\n return (\n <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 text-[10px] font-medium rounded-lg ${color}`}>\n {target.label}\n <span className=\"text-[8px] opacity-50\">{scope}</span>\n </span>\n );\n}\n\nexport function ThrottleModal({ open, onClose, targets, onApply, isPending }: ThrottleModalProps) {\n const [seconds, setSeconds] = useState('0');\n\n return (\n <Modal open={open} onClose={onClose} title=\"Adjust Throttle\">\n <div className=\"space-y-4\">\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2\">Targets</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {targets.map((t, i) => (\n <TargetPill key={t.guid || t.topic || i} target={t} />\n ))}\n </div>\n </div>\n\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2\">Presets</p>\n <div className=\"flex flex-wrap gap-2\">\n {PRESETS.map((p) => (\n <button\n key={p.label}\n onClick={() => { setSeconds(p.ms === -1 ? '-1' : String(p.ms / 1000)); onApply(p.ms); }}\n disabled={isPending}\n className={`px-3 py-1.5 text-xs rounded transition-colors ${\n p.ms === -1\n ? 'bg-status-error/10 text-status-error hover:bg-status-error/20'\n : p.ms === 0\n ? 'bg-status-success/10 text-status-success hover:bg-status-success/20'\n : 'bg-surface-sunken text-text-secondary hover:bg-surface-hover'\n } disabled:opacity-50`}\n >\n {p.label}\n </button>\n ))}\n </div>\n </div>\n\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-2\">\n Custom (seconds between messages)\n </p>\n <div className=\"flex items-center gap-3\">\n <input\n type=\"number\"\n step=\"0.1\"\n min=\"-1\"\n value={seconds}\n onChange={(e) => setSeconds(e.target.value)}\n className=\"input text-xs py-1.5 px-3 w-28\"\n />\n <button\n onClick={() => {\n const s = parseFloat(seconds);\n if (isNaN(s)) return;\n onApply(s === -1 ? -1 : Math.round(s * 1000));\n }}\n disabled={isPending}\n className=\"btn-primary text-xs py-1.5 px-4 disabled:opacity-50\"\n >\n Apply\n </button>\n </div>\n <p className=\"text-[10px] text-text-tertiary mt-1\">\n 0 = resume, -1 = pause indefinitely\n </p>\n </div>\n </div>\n </Modal>\n );\n}\n","import { useState } from 'react';\nimport { CirclePause, Play } from 'lucide-react';\nimport { useControlPlaneApps, useThrottle } from '../../../api/controlplane';\n\nexport function EmergencyControls() {\n const { data: appsData } = useControlPlaneApps();\n const throttle = useThrottle();\n const [confirming, setConfirming] = useState(false);\n\n const apps = appsData?.apps ?? [];\n\n const applyAll = (ms: number) => {\n for (const app of apps) {\n throttle.mutate({ appId: app.appId, throttle: ms });\n }\n setConfirming(false);\n };\n\n if (confirming) {\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-status-error\">Pause all queues?</span>\n <button\n onClick={() => applyAll(-1)}\n className=\"px-2.5 py-1 text-xs rounded-md bg-status-error text-white hover:bg-status-error/90 transition-colors\"\n >\n Confirm\n </button>\n <button\n onClick={() => setConfirming(false)}\n className=\"px-2.5 py-1 text-xs text-text-tertiary hover:text-text-primary transition-colors\"\n >\n Cancel\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setConfirming(true)}\n className=\"flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-md text-status-error/80 hover:text-status-error hover:bg-status-error/10 transition-colors\"\n title=\"Pause all queues\"\n >\n <CirclePause className=\"w-3.5 h-3.5\" />\n Pause All\n </button>\n <button\n onClick={() => applyAll(0)}\n className=\"flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-md text-status-success/80 hover:text-status-success hover:bg-status-success/10 transition-colors\"\n title=\"Resume all queues\"\n >\n <Play className=\"w-3.5 h-3.5\" />\n Resume All\n </button>\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { stripStreamPrefix, type NodeFilter } from './helpers';\n\ninterface StreamEntry {\n stream_type: 'engine' | 'worker';\n stream_name: string;\n count: number;\n}\n\ninterface StreamVolumeChartProps {\n byStream: StreamEntry[];\n onNodeFilter?: (filter: NodeFilter) => void;\n onQueueFilter?: (queue: string) => void;\n}\n\nexport function StreamVolumeChart({ byStream, onNodeFilter }: StreamVolumeChartProps) {\n const [animated, setAnimated] = useState(false);\n\n useEffect(() => {\n setAnimated(false);\n const raf = requestAnimationFrame(() => setAnimated(true));\n return () => cancelAnimationFrame(raf);\n }, [byStream]);\n\n if (byStream.length === 0) {\n return <p className=\"text-xs text-text-tertiary py-4 text-center\">No activity in this period</p>;\n }\n\n const engineStreams = byStream.filter((s) => s.stream_type === 'engine');\n const workerStreams = byStream.filter((s) => s.stream_type === 'worker');\n const maxCount = Math.max(...byStream.map((s) => s.count));\n\n const renderBar = (s: StreamEntry) => {\n const pct = maxCount > 0 ? (s.count / maxCount) * 100 : 0;\n const isEngine = s.stream_type === 'engine';\n const label = isEngine ? '(all engines)' : stripStreamPrefix(s.stream_name);\n const barColor = isEngine ? 'bg-blue-500/70' : 'bg-accent/60';\n const labelColor = isEngine ? 'text-blue-500' : 'text-text-tertiary';\n return (\n <div key={`${s.stream_type}-${s.stream_name}`} className=\"flex items-center gap-3\">\n <span\n className={`text-[9px] font-mono ${labelColor} w-36 truncate text-right shrink-0`}\n title={s.stream_name}\n >\n {label}\n </span>\n <div className=\"flex-1 h-4 bg-surface-sunken rounded overflow-hidden\">\n <div\n className={`h-full ${barColor} rounded transition-all duration-500 ease-out`}\n style={{ width: animated ? `${pct}%` : '0%' }}\n />\n </div>\n <span className=\"text-[10px] font-mono tabular-nums text-text-secondary w-12 text-right shrink-0\">\n {s.count.toLocaleString()}\n </span>\n </div>\n );\n };\n\n const labelCls = 'text-[9px] uppercase tracking-widest font-semibold mb-1 cursor-pointer hover:underline';\n\n return (\n <div className=\"space-y-1.5\">\n {engineStreams.length > 0 && (\n <>\n <p\n className={`${labelCls} text-blue-500/70 hover:text-blue-500`}\n onClick={() => onNodeFilter?.('engines')}\n >\n Engine Message Volume\n </p>\n {engineStreams.map(renderBar)}\n {workerStreams.length > 0 && <div className=\"h-2\" />}\n </>\n )}\n {workerStreams.length > 0 && (\n <>\n <p\n className={`${labelCls} text-accent/70 hover:text-accent`}\n onClick={() => onNodeFilter?.('workers')}\n >\n Worker Message Volume\n </p>\n {workerStreams.map(renderBar)}\n </>\n )}\n </div>\n );\n}\n","import { useMemo } from 'react';\nimport { ChevronRight, Gauge, CirclePlay, Activity, Clock } from 'lucide-react';\nimport { TaskQueuePill } from '../../../components/common/display/TaskQueuePill';\nimport { DataTable } from '../../../components/common/data/DataTable';\nimport { Collapsible } from '../../../components/common/layout/Collapsible';\nimport { RowAction, RowActionGroup } from '../../../components/common/layout/RowActions';\nimport type { QuorumProfile } from '../../../api/controlplane';\nimport { isThrottled, formatThrottleHuman, formatMemory, rowKey, stripStreamPrefix } from './helpers';\nimport type { Column } from '../../../components/common/data/DataTable';\nimport type { Duration } from './helpers';\n\ninterface StreamEntry {\n stream_type: 'engine' | 'worker';\n stream_name: string;\n count: number;\n}\n\ninterface QueueCardProps {\n queue: string;\n workers: QuorumProfile[];\n expanded: boolean;\n onToggle: (queue: string) => void;\n onWorkerClick: (p: QuorumProfile) => void;\n onResumeThrottle: (p: QuorumProfile) => void;\n onQueueThrottle: (queue: string) => void;\n onResumeQueue: (queue: string) => void;\n byStream: StreamEntry[];\n activeDuration: Duration;\n}\n\nexport function QueueCard({\n queue,\n workers,\n expanded,\n onToggle,\n onWorkerClick,\n onResumeThrottle,\n onQueueThrottle,\n onResumeQueue,\n byStream,\n activeDuration,\n}: QueueCardProps) {\n const streamCount = useMemo(() => {\n const match = byStream.find(\n (s) => s.stream_type === 'worker' && stripStreamPrefix(s.stream_name) === queue,\n );\n return match?.count ?? 0;\n }, [byStream, queue]);\n\n const columns = useMemo((): Column<QuorumProfile>[] => [\n {\n key: 'engine_id',\n label: 'Worker ID',\n render: (row) => (\n <span className=\"text-xs font-mono text-text-tertiary\">\n {row.engine_id}\n </span>\n ),\n className: 'w-48',\n },\n {\n key: 'throttle',\n label: 'Throttle',\n render: (row) => {\n const t = row.throttle;\n if (t === -1) return <span className=\"text-xs text-status-error font-medium\">Paused</span>;\n if (t && t > 0) return <span className=\"text-xs text-status-warning font-medium\">{formatThrottleHuman(t)}</span>;\n return <span className=\"text-xs text-text-tertiary\">0</span>;\n },\n className: 'w-24',\n },\n {\n key: 'memory',\n label: 'Memory',\n render: (row) => (\n <span className=\"text-xs font-mono text-text-tertiary\">\n {formatMemory(row.system?.TotalMemoryGB, row.system?.FreeMemoryGB)}\n </span>\n ),\n className: 'w-36',\n },\n {\n key: 'actions',\n label: '',\n render: (row) => (\n <RowActionGroup>\n {isThrottled(row) && (\n <RowAction\n icon={CirclePlay}\n title=\"Resume (remove throttle)\"\n onClick={() => onResumeThrottle(row)}\n colorClass=\"text-text-tertiary hover:text-status-success\"\n />\n )}\n <RowAction\n icon={Gauge}\n title=\"Adjust throttle\"\n onClick={() => onWorkerClick(row)}\n />\n </RowActionGroup>\n ),\n className: 'w-16',\n },\n ], [onWorkerClick, onResumeThrottle]);\n\n return (\n <div>\n <button\n onClick={() => onToggle(queue)}\n className=\"group/row relative flex items-center gap-3 w-full py-2 hover:bg-surface-hover transition-colors text-left rounded\"\n >\n <ChevronRight\n className={`w-3.5 h-3.5 text-text-tertiary/50 transition-transform duration-200 ${expanded ? 'rotate-90' : ''}`}\n strokeWidth={2}\n />\n <TaskQueuePill queue={queue} size=\"sm\" />\n\n <span className=\"flex-1\" />\n\n <span className={`flex items-center gap-1 text-xs w-24 ${workers.some(isThrottled) ? 'text-status-warning' : 'text-text-tertiary'}`}>\n <Activity className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n <span className=\"font-mono tabular-nums\">{workers.length}</span>\n <span>workers</span>\n </span>\n\n <span className=\"flex items-center gap-1 text-xs font-mono text-text-tertiary w-28 justify-end mr-16\">\n {streamCount > 0 ? (\n <>\n <Clock className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n {streamCount.toLocaleString()} in {activeDuration}\n </>\n ) : (\n <span className=\"text-text-tertiary/40\">—</span>\n )}\n </span>\n\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 opacity-0 group-hover/row:opacity-100 transition-opacity flex items-center gap-2\">\n {workers.some(isThrottled) && (\n <CirclePlay\n className=\"w-4 h-4 text-text-tertiary hover:text-status-success\"\n strokeWidth={1.5}\n onClick={(e) => {\n e.stopPropagation();\n onResumeQueue(queue);\n }}\n />\n )}\n <Gauge\n className=\"w-4 h-4 text-text-tertiary hover:text-accent\"\n strokeWidth={1.5}\n onClick={(e) => {\n e.stopPropagation();\n onQueueThrottle(queue);\n }}\n />\n </span>\n </button>\n\n <Collapsible open={expanded}>\n <div className=\"ml-6\">\n <DataTable\n columns={columns}\n data={workers}\n keyFn={rowKey}\n onRowClick={onWorkerClick}\n emptyMessage=\"No workers\"\n inline\n />\n </div>\n </Collapsible>\n </div>\n );\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { Radio, Settings, Eraser, Code } from 'lucide-react';\nimport { JsonViewer } from '../../../components/common/data/JsonViewer';\nimport { Collapsible } from '../../../components/common/layout/Collapsible';\nimport { useEventSubscription } from '../../../hooks/useEventContext';\nimport {\n EVENT_TYPE_COLORS,\n QUORUM_CHANNELS,\n MAX_EVENTS,\n formatThrottleHuman,\n type QuorumEvent,\n} from './helpers';\n\nlet eventCounter = 0;\n\n// ── Event row ───────────────────────────────────────────────────────────────\n\nfunction QuorumEventRow({ event }: { event: QuorumEvent }) {\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div className=\"border-b border-surface-border/50 last:border-b-0\">\n <button\n onClick={() => setExpanded(!expanded)}\n className=\"flex items-center gap-2 py-1.5 w-full text-left hover:bg-surface-hover/50 transition-colors\"\n >\n <span className=\"text-[9px] font-mono text-text-tertiary whitespace-nowrap tabular-nums shrink-0\">\n {new Date(event.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}\n </span>\n <span className={`text-[9px] font-medium px-1 py-0.5 rounded ${EVENT_TYPE_COLORS[event.type] || 'text-text-tertiary'} bg-surface-sunken whitespace-nowrap shrink-0`}>\n {event.type}\n </span>\n <span className=\"text-[9px] text-text-tertiary font-mono flex-1 min-w-0 break-all\">\n {event.data?.guid ? String(event.data.guid) : ''}\n {event.data?.topic ? ` ${String(event.data.topic)}` : ''}\n {event.type === 'throttle' ? ` → ${formatThrottleHuman(event.data?.throttle as number)}` : ''}\n </span>\n <svg\n className={`w-2.5 h-2.5 text-text-tertiary shrink-0 transition-transform duration-150 ${expanded ? 'rotate-180' : ''}`}\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n <Collapsible open={expanded}>\n <div className=\"pb-2\">\n <JsonViewer data={event.data} />\n </div>\n </Collapsible>\n </div>\n );\n}\n\n// ── Config panel ────────────────────────────────────────────────────────────\n\ninterface ConfigPanelProps {\n channels: Set<string>;\n onToggle: (key: string) => void;\n customFilter: string;\n onCustomFilterChange: (v: string) => void;\n}\n\nfunction ConfigPanel({ channels, onToggle, customFilter, onCustomFilterChange }: ConfigPanelProps) {\n return (\n <div className=\"space-y-3 pb-3 border-b border-surface-border mb-3\">\n <div className=\"flex items-center gap-2 mb-1\">\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary\">\n Channels\n </p>\n <p className=\"text-[9px] text-text-tertiary\">\n Unchecked channels are dropped before buffering\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-1\">\n {QUORUM_CHANNELS.map((ch) => (\n <label key={ch.key} className=\"flex items-center gap-2 cursor-pointer py-0.5\">\n <input\n type=\"checkbox\"\n checked={channels.has(ch.key)}\n onChange={() => onToggle(ch.key)}\n className=\"w-3 h-3 rounded border-border accent-accent\"\n />\n <span className=\"text-[10px] text-text-secondary\" title={ch.description}>\n {ch.label}\n </span>\n </label>\n ))}\n </div>\n <div>\n <p className=\"text-[9px] font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n Text Filter\n </p>\n <input\n type=\"text\"\n value={customFilter}\n onChange={(e) => onCustomFilterChange(e.target.value)}\n placeholder=\"pong\"\n className=\"input text-[10px] font-mono py-1 px-2 w-full\"\n />\n <p className=\"text-[9px] text-text-tertiary mt-1\">\n Filter by event type, e.g. <span className=\"font-mono\">pong</span>, <span className=\"font-mono\">throttle</span>, or any text in the event data.\n </p>\n </div>\n </div>\n );\n}\n\n// ── Feed panel ──────────────────────────────────────────────────────────────\n\ninterface QuorumFeedProps {\n bridgeActive: boolean;\n}\n\nexport function QuorumFeed({ bridgeActive }: QuorumFeedProps) {\n const [showConfig, setShowConfig] = useState(false);\n const [showRaw, setShowRaw] = useState(false);\n const [events, setEvents] = useState<QuorumEvent[]>([]);\n const [channels, setChannels] = useState<Set<string>>(\n () => new Set(QUORUM_CHANNELS.map((c) => c.key)),\n );\n const [customFilter, setCustomFilter] = useState('');\n\n // Keep a ref to channels so the event callback reads the latest without re-subscribing\n const channelsRef = useRef(channels);\n useEffect(() => { channelsRef.current = channels; }, [channels]);\n const customFilterRef = useRef(customFilter);\n useEffect(() => { customFilterRef.current = customFilter; }, [customFilter]);\n\n const toggleChannel = (key: string) => {\n setChannels((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n };\n\n // Subscribe to NATS and filter on intake (before buffer)\n useEventSubscription('lt.events.mesh.>', useCallback((raw: any) => {\n const type = raw.type?.replace('mesh.', '') || 'unknown';\n\n // Channel filter: drop events for unchecked channels at intake\n if (!channelsRef.current.has(type)) return;\n\n // Text filter: if set, match against type or stringified data\n const cf = customFilterRef.current;\n if (cf) {\n const haystack = `${type} ${JSON.stringify(raw.data || raw)}`.toLowerCase();\n if (!haystack.includes(cf.toLowerCase())) return;\n }\n\n setEvents((prev) => {\n const next = [{\n id: ++eventCounter,\n type,\n timestamp: raw.timestamp || new Date().toISOString(),\n data: raw.data || raw,\n }, ...prev];\n return next.slice(0, MAX_EVENTS);\n });\n }, []));\n\n const handleClear = () => setEvents([]);\n\n return (\n <div className=\"border-l border-surface-border pl-6 pt-4 min-h-[300px] sticky top-14 self-start max-h-[calc(100vh-8rem)] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center gap-2 mb-3\">\n <p className=\"text-[10px] font-semibold uppercase tracking-widest text-text-tertiary\">\n Event Stream\n </p>\n <Radio className={`w-3 h-3 ${bridgeActive ? 'text-status-success animate-pulse' : 'text-text-tertiary'}`} />\n <span className=\"text-[9px] text-text-tertiary\">\n {bridgeActive ? 'Live' : '...'}\n </span>\n\n <span className=\"ml-auto flex items-center gap-1\">\n <button\n onClick={() => { setShowConfig((v) => !v); setShowRaw(false); }}\n className={`p-1 rounded transition-colors ${showConfig ? 'text-accent bg-accent/10' : 'text-text-tertiary hover:text-text-primary'}`}\n title=\"Configure channels\"\n >\n <Settings className=\"w-3.5 h-3.5\" />\n </button>\n <button\n onClick={() => { setShowRaw((v) => !v); setShowConfig(false); }}\n className={`p-1 rounded transition-colors ${showRaw ? 'text-accent bg-accent/10' : 'text-text-tertiary hover:text-text-primary'}`}\n title=\"View raw JSON\"\n >\n <Code className=\"w-3.5 h-3.5\" />\n </button>\n {events.length > 0 && (\n <button\n onClick={handleClear}\n className=\"p-1 rounded text-text-tertiary hover:text-text-primary transition-colors\"\n title=\"Clear events\"\n >\n <Eraser className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </span>\n </div>\n\n {/* Config panel (animated) */}\n <Collapsible open={showConfig}>\n <ConfigPanel\n channels={channels}\n onToggle={toggleChannel}\n customFilter={customFilter}\n onCustomFilterChange={setCustomFilter}\n />\n </Collapsible>\n\n {/* Raw JSON view */}\n <Collapsible open={showRaw}>\n <div className=\"pb-3 border-b border-surface-border mb-3\">\n <pre className=\"text-[9px] font-mono text-text-tertiary bg-surface-sunken rounded-lg p-3 max-h-[50vh] overflow-auto whitespace-pre-wrap\">\n {JSON.stringify(events.slice(0, 50), null, 2)}\n </pre>\n </div>\n </Collapsible>\n\n {/* Event count */}\n {events.length > 0 && (\n <p className=\"text-[9px] text-text-tertiary mb-2\">\n {events.length} events\n </p>\n )}\n\n {/* Event list */}\n <div className=\"flex-1 overflow-y-auto\">\n {events.length === 0 ? (\n <p className=\"text-xs text-text-tertiary py-6 text-center\">\n {bridgeActive ? 'Waiting for events...' : 'Subscribing...'}\n </p>\n ) : (\n events.map((evt) => (\n <QuorumEventRow key={evt.id} event={evt} />\n ))\n )}\n </div>\n </div>\n );\n}\n","import { DataTable } from '../../../components/common/data/DataTable';\nimport { CollapsibleSection } from '../../../components/common/layout/CollapsibleSection';\nimport { StreamVolumeChart } from './StreamVolumeChart';\nimport { QueueCard } from './QueueCard';\nimport { QuorumFeed } from './QuorumFeed';\nimport { rowKey } from './helpers';\nimport type { Duration } from './helpers';\nimport type { Column } from '../../../components/common/data/DataTable';\n\ninterface ControlPlaneContentProps {\n collapsed: Record<string, boolean>;\n toggleSection: (key: string) => void;\n activeDuration: Duration;\n streamStats: { byStream: Array<any> } | undefined;\n isLoading: boolean;\n queueMap: Map<string, Array<any>>;\n expandedQueues: Set<string>;\n toggleQueue: (queue: string) => void;\n allQueuesExpanded: boolean;\n toggleAllQueues: () => void;\n handleRowClick: (profile: any) => void;\n handleResumeThrottle: (profile: any) => void;\n handleQueueThrottle: (queue: string) => void;\n handleResumeQueue: (queue: string) => void;\n engineColumns: Column<any>[];\n engines: Array<any>;\n bridgeActive: boolean;\n}\n\nexport function ControlPlaneContent({\n collapsed,\n toggleSection,\n activeDuration,\n streamStats,\n isLoading,\n queueMap,\n expandedQueues,\n toggleQueue,\n allQueuesExpanded,\n toggleAllQueues,\n handleRowClick,\n handleResumeThrottle,\n handleQueueThrottle,\n handleResumeQueue,\n engineColumns,\n engines,\n bridgeActive,\n}: ControlPlaneContentProps) {\n return (\n <div className=\"grid grid-cols-1 lg:grid-cols-[1fr_340px] gap-6\">\n <div className=\"flex flex-col gap-12 mt-10\">\n {/* Stream Volume section */}\n <CollapsibleSection\n title={`Stream Volume (${activeDuration})`}\n sectionKey=\"volume\"\n isCollapsed={!!collapsed.volume}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-7\"\n >\n <StreamVolumeChart\n byStream={streamStats?.byStream ?? []}\n onNodeFilter={() => {}}\n onQueueFilter={() => {}}\n />\n </CollapsibleSection>\n\n {/* Task Queues section */}\n <CollapsibleSection\n title=\"Worker Queues\"\n sectionKey=\"queues\"\n isCollapsed={!!collapsed.queues}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-7 flex flex-col gap-0\"\n >\n {isLoading ? (\n <p className=\"text-xs text-text-tertiary\">Discovering mesh nodes...</p>\n ) : queueMap.size === 0 ? (\n <p className=\"text-xs text-text-tertiary\">No worker queues found. Click \"Roll Call\" to discover.</p>\n ) : (\n <>\n <div className=\"flex justify-end mb-2\">\n <button onClick={toggleAllQueues} className=\"text-[10px] text-accent hover:underline\">\n {allQueuesExpanded ? 'Collapse all' : 'Expand all'}\n </button>\n </div>\n {[...queueMap.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([queue, qWorkers]) => (\n <QueueCard\n key={queue}\n queue={queue}\n workers={qWorkers}\n expanded={expandedQueues.has(queue)}\n onToggle={toggleQueue}\n onWorkerClick={handleRowClick}\n onResumeThrottle={handleResumeThrottle}\n onQueueThrottle={handleQueueThrottle}\n onResumeQueue={handleResumeQueue}\n byStream={streamStats?.byStream ?? []}\n activeDuration={activeDuration}\n />\n ))}\n </>\n )}\n </CollapsibleSection>\n\n {/* Engines section */}\n <CollapsibleSection\n title=\"Engines\"\n sectionKey=\"engines\"\n isCollapsed={!!collapsed.engines}\n onToggle={toggleSection}\n contentClassName=\"mt-4 ml-7\"\n >\n <DataTable\n columns={engineColumns}\n data={engines}\n keyFn={rowKey}\n onRowClick={handleRowClick}\n isLoading={isLoading}\n emptyMessage={isLoading ? 'Discovering engines...' : 'No engines found.'}\n inline\n />\n </CollapsibleSection>\n </div>\n\n <QuorumFeed bridgeActive={bridgeActive} />\n </div>\n );\n}\n","import { useMemo, useState, useCallback, useEffect } from 'react';\nimport { RefreshCw } from 'lucide-react';\nimport { PageHeaderWithStats, type InlineStat } from '../../../components/common/layout/PageHeaderWithStats';\nimport { FilterBar, FilterSelect } from '../../../components/common/data/FilterBar';\nimport { useFilterParams } from '../../../hooks/useFilterParams';\nimport {\n useControlPlaneApps,\n useRollCall,\n useStreamStats,\n useSubscribeMesh,\n} from '../../../api/controlplane';\nimport {\n DURATIONS,\n isWorker,\n isThrottled,\n rowKey,\n groupByQueue,\n type Duration,\n} from './helpers';\nimport { getEngineColumns } from './columns';\nimport { useMeshSelection } from './useMeshSelection';\nimport { ThrottleModal } from './ThrottleModal';\nimport { EmergencyControls } from './EmergencyControls';\nimport { ControlPlaneContent } from './ControlPlaneContent';\n\nexport function ControlPlanePage() {\n const { data: appsData } = useControlPlaneApps();\n const apps = appsData?.apps ?? [];\n\n const { filters, setFilter } = useFilterParams({\n filters: { app_id: '', duration: '1h' },\n });\n\n const firstAppId = apps[0]?.appId ?? 'durable';\n const activeAppId = filters.app_id || firstAppId;\n const activeDuration = (filters.duration || '1h') as Duration;\n\n const subscribeMesh = useSubscribeMesh();\n\n const REFRESH_INTERVAL = 60_000;\n\n const { data: rollCallData, isLoading, error: rollCallError, refetch, isFetching } = useRollCall(activeAppId, REFRESH_INTERVAL);\n const { data: streamStats } = useStreamStats(activeAppId, activeDuration, undefined, REFRESH_INTERVAL);\n\n // ── All profiles (sorted) ───────────────────────────────────\n const allProfiles = useMemo(() => {\n const raw = rollCallData?.profiles ?? [];\n return [...raw].sort((a, b) => {\n const ta = a.worker_topic || a.stream || '';\n const tb = b.worker_topic || b.stream || '';\n if (!a.worker_topic && b.worker_topic) return -1;\n if (a.worker_topic && !b.worker_topic) return 1;\n return ta.localeCompare(tb);\n });\n }, [rollCallData?.profiles]);\n\n // ── Derived data ──────────────────────────────────────────────\n const engines = useMemo(() => allProfiles.filter((p) => !isWorker(p)), [allProfiles]);\n const workers = useMemo(() => allProfiles.filter(isWorker), [allProfiles]);\n const queueMap = useMemo(() => groupByQueue(allProfiles), [allProfiles]);\n const throttledCount = allProfiles.filter(isThrottled).length;\n\n const appOptions = useMemo(() => {\n const ids = new Set(apps.map((a) => a.appId));\n if (activeAppId) ids.add(activeAppId);\n return [...ids].sort().map((id) => ({ value: id, label: id }));\n }, [apps, activeAppId]);\n\n // ── Queue card expand/collapse state ───────────────────────────\n const [expandedQueues, setExpandedQueues] = useState<Set<string>>(new Set());\n const toggleQueue = useCallback((queue: string) => {\n setExpandedQueues((prev) => {\n const next = new Set(prev);\n if (next.has(queue)) next.delete(queue);\n else next.add(queue);\n return next;\n });\n }, []);\n const allQueuesExpanded = queueMap.size > 0 && [...queueMap.keys()].every((q) => expandedQueues.has(q));\n const toggleAllQueues = useCallback(() => {\n if (allQueuesExpanded) setExpandedQueues(new Set());\n else setExpandedQueues(new Set(queueMap.keys()));\n }, [allQueuesExpanded, queueMap]);\n\n // ── Section collapse state (persisted) ─────────────────────────\n const STORAGE_KEY = 'lt:controlplane:collapsed';\n const [collapsed, setCollapsed] = useState<Record<string, boolean>>(() => {\n try {\n return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');\n } catch { return {}; }\n });\n const toggleSection = useCallback((key: string) => {\n setCollapsed((prev) => {\n const next = { ...prev, [key]: !prev[key] };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\n return next;\n });\n }, []);\n\n // ── Selection + throttle logic ─────────────────────────────\n const {\n selectedIds,\n setSelectedIds,\n toggleCheckbox,\n throttleModalOpen,\n throttleTargets,\n selectedThrottleTargets,\n throttleMutation,\n handleBulkThrottle,\n handleRowClick,\n handleBulkThrottleOpen,\n handleResumeThrottle,\n handleResumeQueue,\n handleQueueThrottle,\n closeThrottleModal,\n } = useMeshSelection({ activeAppId, allProfiles, profiles: allProfiles });\n\n // ── Engine-scoped toggle ───────────────────────────────────────\n const toggleAllEngines = useCallback(() => {\n const engineKeys = new Set(engines.map(rowKey));\n const allSelected = engines.length > 0 && engines.every((e) => selectedIds.has(rowKey(e)));\n setSelectedIds((prev) => {\n const next = new Set(prev);\n for (const k of engineKeys) {\n if (allSelected) next.delete(k);\n else next.add(k);\n }\n return next;\n });\n }, [engines, selectedIds, setSelectedIds]);\n\n // ── Engine bulk throttle (header icon) ─────────────────────────\n const handleEngineBulkThrottle = useCallback(() => {\n const selected = engines.filter((e) => selectedIds.has(rowKey(e)));\n if (selected.length === 0) return;\n handleBulkThrottleOpen();\n }, [engines, selectedIds, handleBulkThrottleOpen]);\n\n // ── Engine column definitions ─────────────────────────────────\n const engineColumns = useMemo(\n () => getEngineColumns({\n profiles: engines,\n selectedIds,\n toggleAll: toggleAllEngines,\n toggleCheckbox,\n onRowThrottle: handleRowClick,\n onResumeThrottle: handleResumeThrottle,\n onBulkThrottle: handleEngineBulkThrottle,\n }),\n [engines, selectedIds, toggleAllEngines, toggleCheckbox, handleRowClick, handleResumeThrottle, handleEngineBulkThrottle],\n );\n\n // ── Header stats ──────────────────────────────────────────────\n const headerStats = useMemo((): InlineStat[] => {\n const stats: InlineStat[] = [\n { label: 'Engines', value: engines.length, dotClass: 'bg-blue-500' },\n { label: 'Workers', value: workers.length, dotClass: 'bg-text-secondary' },\n { label: 'Queues', value: queueMap.size },\n ];\n if (throttledCount > 0) {\n stats.push({ label: 'Throttled', value: throttledCount, dotClass: 'bg-status-warning' });\n }\n return stats;\n }, [engines.length, workers.length, queueMap.size, throttledCount]);\n\n // ── Quorum bridge ────────────────────────────────────────────\n const [bridgeActive, setBridgeActive] = useState(false);\n\n const handleStartBridge = useCallback(() => {\n subscribeMesh.mutate({ appId: activeAppId }, {\n onSuccess: () => setBridgeActive(true),\n });\n }, [activeAppId, subscribeMesh]);\n\n useEffect(() => {\n if (!bridgeActive && activeAppId) {\n handleStartBridge();\n }\n }, [activeAppId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <div>\n <PageHeaderWithStats\n title=\"Task Queues\"\n docsHash=\"#docs:dashboard.md:task-queues\"\n stats={headerStats}\n actions={<EmergencyControls />}\n />\n\n <FilterBar\n actions={\n <div className=\"flex items-center gap-1\">\n {DURATIONS.map((d) => (\n <button\n key={d.value}\n onClick={() => setFilter('duration', d.value)}\n className={`px-3 py-1 text-xs rounded-full transition-colors ${\n activeDuration === d.value\n ? 'bg-accent text-text-inverse'\n : 'text-text-tertiary hover:text-text-primary hover:bg-surface-hover'\n }`}\n >\n {d.label}\n </button>\n ))}\n </div>\n }\n >\n <FilterSelect\n label=\"Application\"\n value={filters.app_id}\n onChange={(v) => setFilter('app_id', v)}\n options={appOptions}\n />\n <button\n onClick={() => refetch()}\n disabled={isFetching}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs text-text-tertiary hover:text-text-primary transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`w-3.5 h-3.5 ${isFetching ? 'animate-spin' : ''}`} />\n Roll Call\n </button>\n </FilterBar>\n\n {/* Error banner */}\n {rollCallError && (\n <div className=\"mb-6 px-4 py-3 rounded bg-status-error/10 border border-status-error/20\">\n <p className=\"text-xs text-status-error font-medium\">\n {rollCallError.message === 'Session expired'\n ? 'Session expired — please log in again.'\n : `Failed to load mesh data: ${rollCallError.message}`}\n </p>\n </div>\n )}\n\n <ControlPlaneContent\n collapsed={collapsed}\n toggleSection={toggleSection}\n activeDuration={activeDuration}\n streamStats={streamStats}\n isLoading={isLoading}\n queueMap={queueMap}\n expandedQueues={expandedQueues}\n toggleQueue={toggleQueue}\n allQueuesExpanded={allQueuesExpanded}\n toggleAllQueues={toggleAllQueues}\n handleRowClick={handleRowClick}\n handleResumeThrottle={handleResumeThrottle}\n handleQueueThrottle={handleQueueThrottle}\n handleResumeQueue={handleResumeQueue}\n engineColumns={engineColumns}\n engines={engines}\n bridgeActive={bridgeActive}\n />\n\n <ThrottleModal\n open={throttleModalOpen}\n onClose={closeThrottleModal}\n targets={throttleTargets.length > 0 ? throttleTargets : selectedThrottleTargets}\n onApply={handleBulkThrottle}\n isPending={throttleMutation.isPending}\n />\n </div>\n );\n}\n"],"names":["fetchApps","apiFetch","fetchRollCall","appId","postThrottle","body","postSubscribe","fetchStreamStats","duration","stream","url","useControlPlaneApps","useQuery","useRollCall","refetchInterval","useThrottle","qc","useQueryClient","useMutation","useStreamStats","useSubscribeMesh","DURATIONS","EVENT_TYPE_COLORS","MAX_EVENTS","isWorker","p","isThrottled","formatThrottleHuman","ms","formatMemory","total","free","t","f","stripStreamPrefix","name","QUORUM_CHANNELS","rowKey","groupByQueue","profiles","map","q","sumCounts","success","errors","code","n","throttleColumn","row","jsx","memoryColumn","_a","_b","actionColumn","onRowThrottle","onResumeThrottle","jsxs","RowActionGroup","RowAction","CirclePlay","Gauge","getEngineColumns","opts","hasSelection","e","c","useMeshSelection","activeAppId","allProfiles","throttleMutation","selectedIds","setSelectedIds","useState","throttleModalOpen","setThrottleModalOpen","throttleTargets","setThrottleTargets","useEffect","toggleCheckbox","useCallback","profile","prev","next","key","toggleAll","selectedThrottleTargets","useMemo","selected","engines","workers","targets","queues","w","queue","members","allOnQueue","label","queueName","PRESETS","TargetPill","target","isMesh","isEngine","color","scope","ThrottleModal","open","onClose","onApply","isPending","seconds","setSeconds","Modal","i","s","EmergencyControls","appsData","throttle","confirming","setConfirming","apps","applyAll","app","CirclePause","Play","StreamVolumeChart","byStream","onNodeFilter","animated","setAnimated","raf","engineStreams","workerStreams","maxCount","renderBar","pct","barColor","labelColor","labelCls","Fragment","QueueCard","expanded","onToggle","onWorkerClick","onQueueThrottle","onResumeQueue","activeDuration","streamCount","match","columns","ChevronRight","TaskQueuePill","Activity","Clock","Collapsible","DataTable","eventCounter","QuorumEventRow","event","setExpanded","_c","JsonViewer","ConfigPanel","channels","customFilter","onCustomFilterChange","ch","QuorumFeed","bridgeActive","showConfig","setShowConfig","showRaw","setShowRaw","events","setEvents","setChannels","setCustomFilter","channelsRef","useRef","customFilterRef","toggleChannel","useEventSubscription","raw","type","cf","handleClear","Radio","v","Settings","Code","Eraser","evt","ControlPlaneContent","collapsed","toggleSection","streamStats","isLoading","queueMap","expandedQueues","toggleQueue","allQueuesExpanded","toggleAllQueues","handleRowClick","handleResumeThrottle","handleQueueThrottle","handleResumeQueue","engineColumns","CollapsibleSection","a","b","qWorkers","ControlPlanePage","filters","setFilter","useFilterParams","firstAppId","subscribeMesh","REFRESH_INTERVAL","rollCallData","rollCallError","refetch","isFetching","ta","tb","throttledCount","appOptions","ids","id","setExpandedQueues","STORAGE_KEY","setCollapsed","handleBulkThrottle","handleBulkThrottleOpen","closeThrottleModal","toggleAllEngines","engineKeys","allSelected","k","handleEngineBulkThrottle","headerStats","stats","setBridgeActive","handleStartBridge","PageHeaderWithStats","FilterBar","FilterSelect","RefreshCw"],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- import{a as x,j as e}from"./vendor-query-B2UbickB.js";import{e as Z,i as ee,u as B,j as te,b as se}from"./workflows-D6diL54s.js";import{D as re}from"./DataTable-D3-wSEf0.js";import{C as ae}from"./ConfirmDeleteModal-dOxidrSR.js";import{F as ne,b as E}from"./FilterBar-Ck4K4rzu.js";import{R as oe,a as I}from"./RowActions-Dg-Fsm5O.js";import{u as le}from"./useFilterParams-DZCAaBC7.js";import{P as Q}from"./PageHeader-B-SN5GZ2.js";import{R as L}from"./RolePill-BhVC0cc3.js";import{T as ie}from"./TaskQueuePill-Ce8KlXtR.js";import{W as ce}from"./WorkflowPill-DUDDyBsj.js";import{a5 as O,S as ue,W as A,a8 as de,P as xe,a9 as me,aa as pe,U as F,X as z,g as H,D as V,d as $}from"./vendor-icons-BkK55L-1.js";import{c as Y,e as fe,f as he}from"./vendor-react-CX88sFS5.js";import{S as we}from"./StepIndicator-CuUIGxKk.js";import{u as ve}from"./roles--kBaFljg.js";import{B as je}from"./BotPicker-C2xR1xay.js";import"./index-BUjxYyxc.js";import"./EmptyState-BcsfPq9T.js";import"./Modal-DEODGeqx.js";import"./bots-BZPXDh_y.js";function ke(t,r){const l=r.toLowerCase();return t.workflow_type.toLowerCase().includes(l)||(t.description??"").toLowerCase().includes(l)}function Ve(){const t=Y(),{data:r,isLoading:l}=Z(),d=ee(),{filters:a,setFilter:i}=le({filters:{search:"",queue:"",role:"",tier:""}}),[u,y]=x.useState(a.search),[p,N]=x.useState(null);x.useEffect(()=>{if(u===a.search)return;const s=setTimeout(()=>i("search",u),300);return()=>clearTimeout(s)},[u,i,a.search]);const o=r??[],m=x.useMemo(()=>[...new Set(o.map(s=>s.task_queue).filter(Boolean))].sort(),[o]),c=x.useMemo(()=>[...new Set(o.flatMap(s=>s.roles??[]))].sort(),[o]),n=x.useMemo(()=>{let s=o;return a.search&&(s=s.filter(h=>ke(h,a.search))),a.queue&&(s=s.filter(h=>h.task_queue===a.queue)),a.role&&(s=s.filter(h=>(h.roles??[]).includes(a.role))),a.tier&&(s=s.filter(h=>h.tier===a.tier)),s},[o,a]),_=[{key:"workflow_type",label:"Workflow",className:"max-w-xs",render:s=>e.jsxs("div",{className:"min-w-0",children:[e.jsx(ce,{type:s.workflow_type,size:"md",variant:s.tier==="certified"?"certified":s.tier==="configured"?"configured":"durable"}),s.description&&e.jsx("p",{className:"text-[10px] leading-tight text-text-quaternary mt-0.5",children:s.description})]})},{key:"task_queue",label:"Queue",render:s=>s.task_queue?e.jsx(ie,{queue:s.task_queue}):e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}),className:"whitespace-nowrap"},{key:"tier",label:"Tier",render:s=>s.tier==="certified"?e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(O,{className:"w-3 h-3"}),"Certified"]}):s.tier==="configured"?e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(ue,{className:"w-3 h-3"}),"Configured"]}):e.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-medium text-text-secondary",children:[e.jsx(A,{className:"w-3 h-3"}),"Durable"]}),className:"whitespace-nowrap"},{key:"roles",label:"Access",render:s=>{if(!s.registered)return e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"});const h=s.roles??[],w=s.invocation_roles??[];return!h.length&&!w.length?e.jsx("span",{className:"text-xs text-text-tertiary",children:"—"}):e.jsxs("div",{className:"space-y-1.5",children:[h.length>0&&e.jsxs("div",{className:"flex items-start gap-1.5",children:[e.jsx("span",{title:"Escalation roles",className:"mt-0.5",children:e.jsx(O,{className:"w-3 h-3 text-text-quaternary"})}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:h.map(b=>e.jsx(L,{role:b},`e-${b}`))})]}),w.length>0&&e.jsxs("div",{className:"flex items-start gap-1.5",children:[e.jsx("span",{title:"Invocation roles",className:"mt-0.5",children:e.jsx(de,{className:"w-3 h-3 text-text-quaternary"})}),e.jsx("div",{className:"flex gap-1 flex-wrap",children:w.map(b=>e.jsx(L,{role:b},`i-${b}`))})]})]})}},{key:"actions",label:"",render:s=>e.jsxs(oe,{children:[s.invocable&&e.jsx(I,{icon:xe,title:"Invoke workflow",onClick:()=>t(`/workflows/start?type=${encodeURIComponent(s.workflow_type)}&mode=now`),colorClass:"text-text-tertiary hover:text-status-success"}),s.tier==="durable"&&e.jsx(I,{icon:A,title:"Configure workflow",onClick:()=>t(`/workflows/registry/new?workflow_type=${encodeURIComponent(s.workflow_type)}&task_queue=${encodeURIComponent(s.task_queue??"")}`),colorClass:"text-text-tertiary hover:text-status-info"}),s.tier==="configured"&&e.jsx(I,{icon:me,title:"Certify workflow",onClick:()=>t(`/workflows/registry/${encodeURIComponent(s.workflow_type)}`),colorClass:"text-text-tertiary hover:text-status-success"}),s.registered&&e.jsx(I,{icon:pe,title:"Remove configuration",onClick:()=>N(s.workflow_type),colorClass:"text-text-tertiary hover:text-status-warning"})]}),className:"w-16 text-right"}],R=()=>{p&&d.mutate(p,{onSuccess:()=>N(null)})},C=s=>{s.registered?t(`/workflows/registry/${encodeURIComponent(s.workflow_type)}`):t(`/workflows/registry/new?workflow_type=${encodeURIComponent(s.workflow_type)}&task_queue=${encodeURIComponent(s.task_queue??"")}`)};return e.jsxs("div",{children:[e.jsx(Q,{title:"Workflow Registry",docsHash:"#docs:dashboard.md:workflow-registry",actions:e.jsx("button",{onClick:()=>t("/workflows/registry/new"),className:"btn-primary text-xs",children:"Register Workflow"})}),e.jsxs(ne,{children:[e.jsx("input",{type:"text",placeholder:"Search workflow type...",value:u,onChange:s=>y(s.target.value),className:"input text-[11px] py-1 px-2 w-56"}),e.jsx(E,{label:"Queue",value:a.queue,onChange:s=>i("queue",s),options:m.map(s=>({value:s,label:s}))}),e.jsx(E,{label:"Tier",value:a.tier,onChange:s=>i("tier",s),options:[{value:"certified",label:"Certified"},{value:"configured",label:"Configured"},{value:"durable",label:"Durable"}]}),e.jsx(E,{label:"Role",value:a.role,onChange:s=>i("role",s),options:c.map(s=>({value:s,label:s}))})]}),e.jsx(re,{columns:_,data:n,keyFn:s=>s.workflow_type,onRowClick:C,isLoading:l,emptyMessage:"No workflows found"}),e.jsx(ae,{open:!!p,onClose:()=>N(null),onConfirm:R,title:"De-certify Workflow",description:e.jsxs(e.Fragment,{children:["Remove certification from ",e.jsx("span",{className:"font-mono font-medium text-text-primary",children:p}),"? This removes interceptor guarantees, escalation chains, and invocation role constraints. The workflow will continue running as a standard durable workflow."]}),isPending:d.isPending,error:d.error})]})}function S(t){return t.split(",").map(r=>r.trim()).filter(Boolean)}const T={workflow_type:"",description:"",task_queue:"",default_role:"reviewer",invocable:!1,roles:"",invocation_roles:"",consumes:"",envelope_schema:"",resolver_schema:"",cron_schedule:"",execute_as:"",certified:!1};function ge(t){const r=(t.roles??[]).join(", "),l=(t.consumes??[]).join(", ");return{workflow_type:t.workflow_type,description:t.description??"",task_queue:t.task_queue??"",default_role:t.default_role,invocable:t.invocable,roles:r,invocation_roles:(t.invocation_roles??[]).join(", "),consumes:l,envelope_schema:t.envelope_schema?JSON.stringify(t.envelope_schema,null,2):"",resolver_schema:t.resolver_schema?JSON.stringify(t.resolver_schema,null,2):"",cron_schedule:t.cron_schedule??"",execute_as:t.execute_as??"",certified:!!(r||l)}}const U=["Identity","Invocation","Advanced"];function P(t){if(!t.trim())return!0;try{return JSON.parse(t),!0}catch{return!1}}function J(t,r){return t===1?!!r.workflow_type.trim():t===2?P(r.envelope_schema):t===3?P(r.resolver_schema):!0}const g="block text-[10px] font-semibold uppercase tracking-widest text-text-tertiary mb-1",j="text-[10px] text-text-tertiary mt-2 leading-relaxed",G="input font-mono text-[11px] w-full leading-relaxed tabular-nums";function D({selected:t,onChange:r,single:l,placeholder:d}){const{data:a}=ve(),i=(a==null?void 0:a.roles)??[],[u,y]=x.useState(!1),p=x.useRef(null);x.useEffect(()=>{const c=n=>{p.current&&!p.current.contains(n.target)&&y(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[]);const N=c=>{l?(r(t.includes(c)?[]:[c]),y(!1)):r(t.includes(c)?t.filter(n=>n!==c):[...t,c])},o=c=>{r(t.filter(n=>n!==c))},m=d??(l?"Select role...":"Add roles...");return e.jsxs("div",{ref:p,className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>y(!u),className:"flex flex-wrap items-center gap-1.5 w-full min-h-[34px] px-2 py-1.5 bg-surface-sunken border border-surface-border rounded-md text-left cursor-pointer hover:border-accent/40 transition-colors focus:ring-1 focus:ring-accent focus:outline-none",children:[t.length===0&&e.jsx("span",{className:"text-xs text-text-tertiary",children:m}),t.map(c=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-lg bg-accent/[0.08] text-text-secondary text-[11px]",children:[e.jsx(F,{className:"w-2.5 h-2.5 shrink-0 text-accent/75"}),c,e.jsx("span",{role:"button",onClick:n=>{n.stopPropagation(),o(c)},className:"ml-0.5 hover:text-status-error transition-colors",children:e.jsx(z,{className:"w-2.5 h-2.5"})})]},c)),e.jsx(H,{className:`w-3.5 h-3.5 ml-auto shrink-0 text-text-tertiary transition-transform ${u?"rotate-180":""}`})]}),u&&e.jsx("div",{className:"absolute z-20 mt-1 w-full bg-white border border-surface-border rounded-md shadow-lg max-h-48 overflow-y-auto",children:i.length===0?e.jsx("p",{className:"px-3 py-2 text-xs text-text-tertiary",children:"No roles defined"}):i.map(c=>{const n=t.includes(c);return e.jsxs("button",{type:"button",onClick:()=>N(c),className:`flex items-center gap-2 w-full px-3 py-1.5 text-left text-xs transition-colors ${n?"bg-accent/[0.06] text-accent":"text-text-primary hover:bg-surface-sunken"}`,children:[e.jsx(F,{className:"w-3 h-3 shrink-0 text-accent/60"}),e.jsx("span",{className:"flex-1",children:c}),n&&e.jsx(V,{className:"w-3 h-3 shrink-0"})]},c)})})]})}function ye({options:t,selected:r,onChange:l,placeholder:d}){const[a,i]=x.useState(!1),u=x.useRef(null);x.useEffect(()=>{const o=m=>{u.current&&!u.current.contains(m.target)&&i(!1)};return document.addEventListener("mousedown",o),()=>document.removeEventListener("mousedown",o)},[]);const y=o=>{l(r.includes(o)?r.filter(m=>m!==o):[...r,o])},p=o=>{l(r.filter(m=>m!==o))},N=d??"Add workflows...";return e.jsxs("div",{ref:u,className:"relative",children:[e.jsxs("button",{type:"button",onClick:()=>i(!a),className:"flex flex-wrap items-center gap-1.5 w-full min-h-[34px] px-2 py-1.5 bg-surface-sunken border border-surface-border rounded-md text-left cursor-pointer hover:border-accent/40 transition-colors focus:ring-1 focus:ring-accent focus:outline-none",children:[r.length===0&&e.jsx("span",{className:"text-xs text-text-tertiary",children:N}),r.map(o=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-lg bg-accent/[0.08] text-text-secondary text-[11px] font-mono",children:[e.jsx($,{className:"w-2.5 h-2.5 shrink-0 text-accent/75"}),o,e.jsx("span",{role:"button",onClick:m=>{m.stopPropagation(),p(o)},className:"ml-0.5 hover:text-status-error transition-colors",children:e.jsx(z,{className:"w-2.5 h-2.5"})})]},o)),e.jsx(H,{className:`w-3.5 h-3.5 ml-auto shrink-0 text-text-tertiary transition-transform ${a?"rotate-180":""}`})]}),a&&e.jsx("div",{className:"absolute z-20 mt-1 w-full bg-white border border-surface-border rounded-md shadow-lg max-h-48 overflow-y-auto",children:t.length===0?e.jsx("p",{className:"px-3 py-2 text-xs text-text-tertiary",children:"No registered workflows"}):t.map(o=>{const m=r.includes(o);return e.jsxs("button",{type:"button",onClick:()=>y(o),className:`flex items-center gap-2 w-full px-3 py-1.5 text-left text-xs font-mono transition-colors ${m?"bg-accent/[0.06] text-accent":"text-text-primary hover:bg-surface-sunken"}`,children:[e.jsx($,{className:"w-3 h-3 shrink-0 text-accent/60"}),e.jsx("span",{className:"flex-1",children:o}),m&&e.jsx(V,{className:"w-3 h-3 shrink-0"})]},o)})})]})}function W(t){return S(t)}function M(t){return t.join(", ")}function Ne({form:t,set:r}){const{data:l}=B(),d=(l??[]).map(a=>a.workflow_type).filter(a=>a!==t.workflow_type);return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Resolver Schema"}),e.jsx("textarea",{value:t.resolver_schema,onChange:a=>r("resolver_schema",a.target.value),placeholder:`{
2
- "properties": {
3
- "approved": { "type": "boolean", "default": false, "description": "Approve?" },
4
- "notes": { "type": "string", "default": "", "description": "Reviewer notes" }
5
- }
6
- }`,className:G,rows:8,spellCheck:!1}),e.jsxs("p",{className:j,children:["Default form template for resolving escalations from this workflow. Use ",e.jsx("span",{className:"font-mono",children:"properties"})," with ",e.jsx("span",{className:"font-mono",children:"type"}),", ",e.jsx("span",{className:"font-mono",children:"default"}),", ",e.jsx("span",{className:"font-mono",children:"description"}),", ",e.jsx("span",{className:"font-mono",children:"enum"}),", and ",e.jsx("span",{className:"font-mono",children:"format"})," for typed form fields."]}),t.resolver_schema.trim()&&!P(t.resolver_schema)&&e.jsx("p",{className:"text-[10px] text-status-error mt-1",children:"Invalid JSON"})]}),e.jsx("div",{className:"flex gap-6 pt-1",children:e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.certified,onChange:a=>r("certified",a.target.checked),className:"w-4 h-4 rounded border-border accent-accent"}),e.jsx("span",{className:"text-xs text-text-primary font-medium",children:"Certify for HITL Escalation"})]})}),e.jsx("p",{className:j,children:"Certified workflows use the interceptor to wrap executions — failures escalate to human reviewers instead of throwing."}),t.certified?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Default Escalation Role"}),e.jsx(D,{selected:W(t.default_role),onChange:a=>r("default_role",a[0]??""),single:!0,placeholder:"Select escalation role..."}),e.jsx("p",{className:j,children:"When this workflow escalates, assign to users with this role"})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Escalation Roles"}),e.jsx(D,{selected:W(t.roles),onChange:a=>r("roles",M(a)),placeholder:"Select who can resolve escalations..."}),e.jsx("p",{className:j,children:"Users with any of these roles can claim and resolve escalations from this workflow."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Consumes"}),e.jsx(ye,{options:d,selected:W(t.consumes),onChange:a=>r("consumes",M(a)),placeholder:"Select workflow dependencies..."}),e.jsx("p",{className:j,children:"Output from these upstream workflows will be injected into the input envelope for this workflow."})]})]}):e.jsx("div",{className:"py-4 px-4 bg-surface-sunken/50 rounded-md text-center",children:e.jsxs("p",{className:"text-xs text-text-tertiary",children:["This workflow will run as standard durable without the interceptor. Enable"," ",e.jsx("span",{className:"font-medium text-text-secondary",children:"Certify for HITL Escalation"})," ","to add automatic escalation routing and role-based resolution."]})})]})}function be(t){return S(t)}function _e(t){return t.join(", ")}function Ce({form:t,set:r,editing:l,durableTypes:d=[]}){const a=!l&&d.length>0;return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Workflow Type"}),a&&!t.workflow_type?e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs text-text-secondary",children:"Select a durable workflow to register:"}),e.jsx("div",{className:"grid gap-1",children:d.map(i=>e.jsx("button",{onClick:()=>r("workflow_type",i),className:"flex items-center gap-2 px-3 py-2 text-left text-xs font-mono rounded-md border border-surface-border hover:border-accent/50 hover:bg-accent/[0.04] transition-colors",children:i},i))}),e.jsxs("div",{className:"flex items-center gap-2 pt-1",children:[e.jsx("span",{className:"text-[10px] text-text-tertiary",children:"or"}),e.jsx("input",{type:"text",onChange:i=>r("workflow_type",i.target.value),placeholder:"Enter a workflow type manually",className:"input font-mono text-xs flex-1"})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("input",{type:"text",value:t.workflow_type,onChange:i=>r("workflow_type",i.target.value),disabled:l,placeholder:"reviewContent",className:"input font-mono text-xs w-full"}),!l&&t.workflow_type&&d.length>0&&e.jsx("button",{onClick:()=>r("workflow_type",""),className:"text-[10px] text-accent hover:underline mt-1",children:"Choose from durable workflows"})]}),e.jsx("p",{className:j,children:"Register a workflow to configure invocation schemas and dashboard visibility. Certification for HITL escalation is optional (step 3)."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Description"}),e.jsx("input",{type:"text",value:t.description,onChange:i=>r("description",i.target.value),placeholder:"AI-powered content moderation with human escalation",className:"input text-xs w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Task Queue"}),e.jsx("input",{type:"text",value:t.task_queue,onChange:i=>r("task_queue",i.target.value),placeholder:"lt-review",className:"input font-mono text-xs w-full"}),e.jsx("p",{className:j,children:"Durable task queue this workflow listens on"})]})]})}function Se({form:t,set:r}){return e.jsxs("div",{className:"space-y-5",children:[e.jsx("div",{className:"flex gap-6 pt-1",children:e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.invocable,onChange:l=>r("invocable",l.target.checked),className:"w-4 h-4 rounded border-border accent-accent"}),e.jsx("span",{className:"text-xs text-text-primary font-medium",children:"Invocable"})]})}),e.jsx("p",{className:j,children:"Allow this workflow to be started from the dashboard or API."}),t.invocable&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Run As"}),e.jsx(je,{selected:t.execute_as,onChange:l=>r("execute_as",l)}),e.jsx("p",{className:j,children:"Choose a bot to execute this workflow under its identity and credentials. Default runs as the invoking user."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Invocation Roles"}),e.jsx(D,{selected:be(t.invocation_roles),onChange:l=>r("invocation_roles",_e(l)),placeholder:"Select who can start this workflow..."}),e.jsx("p",{className:j,children:"Only users with these roles can start this workflow. Leave empty to allow all authenticated users."})]}),e.jsxs("div",{children:[e.jsx("label",{className:g,children:"Envelope Schema"}),e.jsx("textarea",{value:t.envelope_schema,onChange:l=>r("envelope_schema",l.target.value),placeholder:`{
7
- "data": {
8
- "contentId": "example-123",
9
- "content": "Text to review"
10
- },
11
- "metadata": {
12
- "source": "dashboard"
13
- }
14
- }`,className:G,rows:8,spellCheck:!1}),e.jsxs("p",{className:j,children:["Pre-fills the JSON editor when invoking this workflow. Should include ",e.jsx("span",{className:"font-mono",children:"data"})," (workflow input) and optional ",e.jsx("span",{className:"font-mono",children:"metadata"})," (context)."]}),t.envelope_schema.trim()&&!P(t.envelope_schema)&&e.jsx("p",{className:"text-[10px] text-status-error mt-1",children:"Invalid JSON"})]})]}),!t.invocable&&e.jsx("div",{className:"py-4 px-4 bg-surface-sunken/50 rounded-md text-center",children:e.jsxs("p",{className:"text-xs text-text-tertiary",children:["Enable ",e.jsx("span",{className:"font-medium text-text-secondary",children:"Invocable"})," above to configure who can start this workflow and set an input template."]})})]})}function Ye(){const{workflowType:t}=fe(),r=!t,l=Y(),{data:d,isLoading:a}=B(),i=te(),u=(d==null?void 0:d.find(f=>f.workflow_type===t))??null,y=new Set(["mcpQuery","mcpDeterministic","mcpQueryRouter","mcpTriage","mcpTriageRouter","mcpTriageDeterministic","insightQuery"]),{data:p}=se({limit:500}),N=x.useMemo(()=>{const f=new Set((d??[]).map(v=>v.workflow_type));return[...new Set(((p==null?void 0:p.jobs)??[]).map(v=>v.entity))].filter(v=>!f.has(v)&&!y.has(v)).sort()},[d,p]),[o,m]=he(),c=x.useMemo(()=>{if(!r)return T;const f=o.get("workflow_type")??"",k=o.get("task_queue")??"";return!f&&!k?T:{...T,workflow_type:f,task_queue:k}},[r,o]),[n,_]=x.useState(c),[R,C]=x.useState(""),[s,h]=x.useState(!1),w=parseInt(o.get("step")||"1",10),b=x.useCallback(f=>{m(k=>{const v=new URLSearchParams(k);return v.set("step",String(f)),v},{replace:!1})},[m]);x.useEffect(()=>{if(!s){if(r){_(c),h(!0);return}u&&(_(ge(u)),h(!0))}},[u,r,s,c]);const q=(f,k)=>_(v=>({...v,[f]:k})),K=()=>{if(!n.workflow_type.trim())return;C("");let f=null,k=null;try{n.envelope_schema.trim()&&(f=JSON.parse(n.envelope_schema))}catch{C("Invalid JSON in Envelope Schema");return}try{n.resolver_schema.trim()&&(k=JSON.parse(n.resolver_schema))}catch{C("Invalid JSON in Resolver Schema");return}i.mutate({workflow_type:n.workflow_type.trim(),description:n.description.trim()||null,task_queue:n.task_queue.trim()||null,default_role:n.default_role.trim()||"reviewer",invocable:n.invocable,roles:S(n.roles),invocation_roles:S(n.invocation_roles),consumes:S(n.consumes),envelope_schema:f,resolver_schema:k,cron_schedule:n.cron_schedule.trim()||null,execute_as:n.execute_as.trim()||null},{onSuccess:()=>{l("/workflows/registry")}})};if(a)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-48"}),e.jsx("div",{className:"h-60 bg-surface-sunken rounded"})]});if(!r&&!u)return e.jsx("p",{className:"text-sm text-text-secondary",children:"Config not found."});const X=w===U.length;return e.jsxs("div",{children:[e.jsx(Q,{title:r?"Register Workflow":(u==null?void 0:u.workflow_type)??""}),e.jsxs("div",{className:"max-w-3xl",children:[e.jsx(we,{steps:U,currentStep:w-1,onStepClick:f=>b(f+1)}),e.jsxs("div",{className:"min-h-[360px] py-2",children:[w===1&&e.jsx(Ce,{form:n,set:q,editing:!!u,durableTypes:N}),w===2&&e.jsx(Se,{form:n,set:q}),w===3&&e.jsx(Ne,{form:n,set:q})]}),(R||i.error)&&e.jsx("p",{className:"text-xs text-status-error mt-4",children:R||i.error.message}),e.jsxs("div",{className:"flex justify-between items-center pt-4 border-t border-surface-border mt-4",children:[e.jsx("div",{children:w>1&&e.jsx("button",{onClick:()=>b(w-1),className:"btn-secondary text-xs",children:"Back"})}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx("button",{onClick:()=>l("/workflows/registry"),className:"btn-ghost text-xs",children:"Cancel"}),X?e.jsx("button",{onClick:K,disabled:!J(w,n)||i.isPending,className:"btn-primary text-xs",children:i.isPending?"Saving...":u?"Save":"Create"}):e.jsx("button",{onClick:()=>b(w+1),disabled:!J(w,n),className:"btn-primary text-xs",children:"Next"})]})]})]})]})}export{Ye as WorkflowConfigDetailPage,Ve as WorkflowConfigsPage};
15
- //# sourceMappingURL=index-BU04qgJt.js.map