@hotmeshio/long-tail 0.4.18 → 0.4.20

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 (354) hide show
  1. package/README.md +0 -2
  2. package/build/api/auth-sso.d.ts +12 -0
  3. package/build/api/auth-sso.js +54 -0
  4. package/build/api/escalations/bulk.js +2 -2
  5. package/build/api/escalations/claim.js +3 -13
  6. package/build/api/escalations/create.js +3 -2
  7. package/build/api/escalations/helpers.d.ts +1 -0
  8. package/build/api/escalations/helpers.js +12 -9
  9. package/build/api/escalations/list.d.ts +1 -0
  10. package/build/api/escalations/list.js +1 -0
  11. package/build/api/escalations/metadata.d.ts +7 -24
  12. package/build/api/escalations/metadata.js +31 -65
  13. package/build/api/escalations/single.js +3 -2
  14. package/build/api/settings.js +5 -0
  15. package/build/api/topics.d.ts +9 -0
  16. package/build/api/topics.js +31 -2
  17. package/build/lib/events/index.d.ts +1 -0
  18. package/build/lib/events/index.js +4 -0
  19. package/build/lib/events/publish.d.ts +12 -9
  20. package/build/lib/events/publish.js +27 -17
  21. package/build/modules/auth.d.ts +7 -0
  22. package/build/modules/auth.js +104 -2
  23. package/build/modules/sso.d.ts +6 -0
  24. package/build/modules/sso.js +20 -0
  25. package/build/routes/auth-sso.d.ts +2 -0
  26. package/build/routes/auth-sso.js +51 -0
  27. package/build/routes/bot-accounts.js +1 -1
  28. package/build/routes/controlplane.js +6 -6
  29. package/build/routes/escalations/list.js +1 -0
  30. package/build/routes/index.js +2 -0
  31. package/build/routes/mcp-endpoint.d.ts +17 -0
  32. package/build/routes/mcp-endpoint.js +70 -0
  33. package/build/routes/roles.js +5 -5
  34. package/build/routes/topics.js +2 -0
  35. package/build/routes/users.js +31 -5
  36. package/build/sdk/index.d.ts +1 -0
  37. package/build/services/agent/input-mapper.js +17 -1
  38. package/build/services/escalation/crud.d.ts +17 -1
  39. package/build/services/escalation/crud.js +62 -13
  40. package/build/services/escalation/queries.d.ts +1 -0
  41. package/build/services/escalation/queries.js +7 -0
  42. package/build/services/escalation/sql.d.ts +14 -5
  43. package/build/services/escalation/sql.js +53 -16
  44. package/build/services/mcp/exposure.d.ts +15 -0
  45. package/build/services/mcp/exposure.js +18 -0
  46. package/build/services/mcp/external-server.d.ts +15 -0
  47. package/build/services/mcp/external-server.js +125 -0
  48. package/build/services/mcp/seed-service-account.d.ts +11 -0
  49. package/build/services/mcp/seed-service-account.js +77 -0
  50. package/build/services/role/index.d.ts +1 -1
  51. package/build/services/role/index.js +2 -2
  52. package/build/services/topics/system-topics.js +29 -25
  53. package/build/services/user/index.d.ts +1 -1
  54. package/build/services/user/index.js +3 -1
  55. package/build/services/user/rbac.d.ts +16 -0
  56. package/build/services/user/rbac.js +31 -0
  57. package/build/services/user/sso-provision.d.ts +19 -0
  58. package/build/services/user/sso-provision.js +62 -0
  59. package/build/services/workflow-invocation.js +5 -3
  60. package/build/start/config.js +6 -0
  61. package/build/start/server.js +2 -0
  62. package/build/start/workers.js +15 -0
  63. package/build/system/index.js +53 -35
  64. package/build/system/mcp-servers/admin/agent-subscriptions.d.ts +5 -0
  65. package/build/system/mcp-servers/admin/agent-subscriptions.js +78 -0
  66. package/build/system/mcp-servers/admin/agents.d.ts +5 -0
  67. package/build/system/mcp-servers/admin/agents.js +103 -0
  68. package/build/system/mcp-servers/admin/bot-accounts.d.ts +5 -0
  69. package/build/system/mcp-servers/admin/bot-accounts.js +126 -0
  70. package/build/system/mcp-servers/admin/controlplane.d.ts +5 -0
  71. package/build/system/mcp-servers/admin/controlplane.js +107 -0
  72. package/build/system/mcp-servers/admin/escalations.js +88 -0
  73. package/build/system/mcp-servers/admin/exports.d.ts +5 -0
  74. package/build/system/mcp-servers/admin/exports.js +101 -0
  75. package/build/system/mcp-servers/admin/index.d.ts +16 -8
  76. package/build/system/mcp-servers/admin/index.js +36 -21
  77. package/build/system/mcp-servers/admin/pipelines.d.ts +5 -0
  78. package/build/system/mcp-servers/admin/pipelines.js +96 -0
  79. package/build/system/mcp-servers/admin/schemas.d.ts +614 -6
  80. package/build/system/mcp-servers/admin/schemas.js +239 -1
  81. package/build/system/mcp-servers/admin/settings.d.ts +5 -0
  82. package/build/system/mcp-servers/admin/settings.js +53 -0
  83. package/build/system/mcp-servers/admin/topics.d.ts +5 -0
  84. package/build/system/mcp-servers/admin/topics.js +101 -0
  85. package/build/system/seed/tool-manifests-admin.d.ts +5077 -188
  86. package/build/system/seed/tool-manifests-admin.js +79 -30
  87. package/build/system/seed/tool-manifests-data.d.ts +20 -0
  88. package/build/system/seed/tool-manifests-data.js +24 -6
  89. package/build/system/seed/tool-manifests-escalation.d.ts +5 -0
  90. package/build/system/seed/tool-manifests-escalation.js +5 -0
  91. package/build/system/seed/tool-manifests-events.d.ts +4 -0
  92. package/build/system/seed/tool-manifests-events.js +4 -0
  93. package/build/system/seed/tool-manifests-knowledge.d.ts +6 -0
  94. package/build/system/seed/tool-manifests-knowledge.js +7 -0
  95. package/build/system/seed/tool-manifests-workflows.d.ts +8 -0
  96. package/build/system/seed/tool-manifests-workflows.js +8 -0
  97. package/build/tsconfig.tsbuildinfo +1 -1
  98. package/build/types/auth.d.ts +71 -0
  99. package/build/types/events.d.ts +17 -6
  100. package/build/types/index.d.ts +1 -1
  101. package/build/types/startup.d.ts +22 -1
  102. package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js → AdminDashboard-BwUGcCxQ.js} +2 -2
  103. package/dashboard/dist/assets/{AdminDashboard-Cfo0mwL2.js.map → AdminDashboard-BwUGcCxQ.js.map} +1 -1
  104. package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js +16 -0
  105. package/dashboard/dist/assets/AgentConfigPage-DgrYzLwq.js.map +1 -0
  106. package/dashboard/dist/assets/{AgentDetailPage-3mZA7SOb.js → AgentDetailPage-XJpl7wfJ.js} +4 -4
  107. package/dashboard/dist/assets/AgentDetailPage-XJpl7wfJ.js.map +1 -0
  108. package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js → AgentsPage-CGpVG6r8.js} +2 -2
  109. package/dashboard/dist/assets/{AgentsPage-CTVocfBb.js.map → AgentsPage-CGpVG6r8.js.map} +1 -1
  110. package/dashboard/dist/assets/AvailableEscalationsPage-DR1e0TQZ.js +2 -0
  111. package/dashboard/dist/assets/{AvailableEscalationsPage-CA9x9o5s.js.map → AvailableEscalationsPage-DR1e0TQZ.js.map} +1 -1
  112. package/dashboard/dist/assets/BotPicker-BKtjl6IL.js +2 -0
  113. package/dashboard/dist/assets/{BotPicker-BQp_Vs73.js.map → BotPicker-BKtjl6IL.js.map} +1 -1
  114. package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js → CapabilitiesPage-kCB8fyOj.js} +2 -2
  115. package/dashboard/dist/assets/{CapabilitiesPage-wpVtkGeU.js.map → CapabilitiesPage-kCB8fyOj.js.map} +1 -1
  116. package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js → CollapsibleSection-C3tU61hB.js} +2 -2
  117. package/dashboard/dist/assets/{CollapsibleSection-2eZMMZiG.js.map → CollapsibleSection-C3tU61hB.js.map} +1 -1
  118. package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js → CredentialsPage-Dt4nJs_B.js} +2 -2
  119. package/dashboard/dist/assets/{CredentialsPage-DJGLssm0.js.map → CredentialsPage-Dt4nJs_B.js.map} +1 -1
  120. package/dashboard/dist/assets/CronLabel-BdE6mHyA.js +2 -0
  121. package/dashboard/dist/assets/CronLabel-BdE6mHyA.js.map +1 -0
  122. package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js → CustomDurationPicker-B_Yxfb-u.js} +2 -2
  123. package/dashboard/dist/assets/{CustomDurationPicker-DbyqfK35.js.map → CustomDurationPicker-B_Yxfb-u.js.map} +1 -1
  124. package/dashboard/dist/assets/{DropZone-BkfRoUcm.js → DropZone-CptiQ0wc.js} +2 -2
  125. package/dashboard/dist/assets/{DropZone-BkfRoUcm.js.map → DropZone-CptiQ0wc.js.map} +1 -1
  126. package/dashboard/dist/assets/ElapsedCell-tcGx5PFI.js +2 -0
  127. package/dashboard/dist/assets/{ElapsedCell-BPYm8RA7.js.map → ElapsedCell-tcGx5PFI.js.map} +1 -1
  128. package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js → EscalationsOverview-1KO5dXzk.js} +2 -2
  129. package/dashboard/dist/assets/{EscalationsOverview-kYGHfnLf.js.map → EscalationsOverview-1KO5dXzk.js.map} +1 -1
  130. package/dashboard/dist/assets/{EventTable-DSDzJMer.js → EventTable-DnpsQ6Ew.js} +2 -2
  131. package/dashboard/dist/assets/{EventTable-DSDzJMer.js.map → EventTable-DnpsQ6Ew.js.map} +1 -1
  132. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +2 -0
  133. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +1 -0
  134. package/dashboard/dist/assets/ListToolbar-jrVba7QN.js +2 -0
  135. package/dashboard/dist/assets/{ListToolbar-DEef1_-T.js.map → ListToolbar-jrVba7QN.js.map} +1 -1
  136. package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js → McpOverview-BzyxJyc9.js} +2 -2
  137. package/dashboard/dist/assets/{McpOverview-CZFW5qMb.js.map → McpOverview-BzyxJyc9.js.map} +1 -1
  138. package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js → McpQueryDetailPage-DXNseeKl.js} +2 -2
  139. package/dashboard/dist/assets/{McpQueryDetailPage-q9xH-QRo.js.map → McpQueryDetailPage-DXNseeKl.js.map} +1 -1
  140. package/dashboard/dist/assets/{McpQueryPage-D14466yi.js → McpQueryPage-WZfTY43_.js} +2 -2
  141. package/dashboard/dist/assets/{McpQueryPage-D14466yi.js.map → McpQueryPage-WZfTY43_.js.map} +1 -1
  142. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +2 -0
  143. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +1 -0
  144. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +2 -0
  145. package/dashboard/dist/assets/{McpRunsPage-aZg057y3.js.map → McpRunsPage-SXyiwc0d.js.map} +1 -1
  146. package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js +2 -0
  147. package/dashboard/dist/assets/OperatorDashboard-Cy7ySMXj.js.map +1 -0
  148. package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js → PageHeader-BuJpMxyu.js} +2 -2
  149. package/dashboard/dist/assets/{PageHeader-CR6TpJG_.js.map → PageHeader-BuJpMxyu.js.map} +1 -1
  150. package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js → PageHeaderWithStats-yD_PTbOl.js} +2 -2
  151. package/dashboard/dist/assets/{PageHeaderWithStats-CRcQEAO1.js.map → PageHeaderWithStats-yD_PTbOl.js.map} +1 -1
  152. package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js → ProcessDetailPage-DYIfvWyc.js} +2 -2
  153. package/dashboard/dist/assets/{ProcessDetailPage-DyzNjwu8.js.map → ProcessDetailPage-DYIfvWyc.js.map} +1 -1
  154. package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js → ProcessesListPage-DR1RGaMl.js} +2 -2
  155. package/dashboard/dist/assets/{ProcessesListPage-CT_3b5Wt.js.map → ProcessesListPage-DR1RGaMl.js.map} +1 -1
  156. package/dashboard/dist/assets/{RolePill-BC54Vn-U.js → RolePill-SasQKc_B.js} +2 -2
  157. package/dashboard/dist/assets/{RolePill-BC54Vn-U.js.map → RolePill-SasQKc_B.js.map} +1 -1
  158. package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js → RolesPage-pMERxj15.js} +2 -2
  159. package/dashboard/dist/assets/{RolesPage-CpRJq-sg.js.map → RolesPage-pMERxj15.js.map} +1 -1
  160. package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js → RunAsSelector-B-ksMoEj.js} +2 -2
  161. package/dashboard/dist/assets/{RunAsSelector-C20rdNsC.js.map → RunAsSelector-B-ksMoEj.js.map} +1 -1
  162. package/dashboard/dist/assets/ServerName-CHspudaC.js +2 -0
  163. package/dashboard/dist/assets/{ServerName-Q6okiv4f.js.map → ServerName-CHspudaC.js.map} +1 -1
  164. package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js → SwimlaneTimeline-Cr_K5qpu.js} +2 -2
  165. package/dashboard/dist/assets/{SwimlaneTimeline-CbFaU4bq.js.map → SwimlaneTimeline-Cr_K5qpu.js.map} +1 -1
  166. package/dashboard/dist/assets/{TagInput-D6l1SPWd.js → TagInput-DvF3j8MA.js} +2 -2
  167. package/dashboard/dist/assets/{TagInput-D6l1SPWd.js.map → TagInput-DvF3j8MA.js.map} +1 -1
  168. package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js → TaskDetailPage-BO5p7AEe.js} +2 -2
  169. package/dashboard/dist/assets/{TaskDetailPage-22cJsFmM.js.map → TaskDetailPage-BO5p7AEe.js.map} +1 -1
  170. package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js → TaskQueuePill-BCQrS2oK.js} +2 -2
  171. package/dashboard/dist/assets/{TaskQueuePill-iDBVCEQQ.js.map → TaskQueuePill-BCQrS2oK.js.map} +1 -1
  172. package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js → TasksListPage-BRg-uFtF.js} +2 -2
  173. package/dashboard/dist/assets/{TasksListPage-BDmaUIKu.js.map → TasksListPage-BRg-uFtF.js.map} +1 -1
  174. package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js → TimeAgo-BSzN6rAH.js} +2 -2
  175. package/dashboard/dist/assets/{TimeAgo-7wqEp87-.js.map → TimeAgo-BSzN6rAH.js.map} +1 -1
  176. package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js → TimestampCell-DL6zMNEQ.js} +2 -2
  177. package/dashboard/dist/assets/{TimestampCell-BBCf8zsN.js.map → TimestampCell-DL6zMNEQ.js.map} +1 -1
  178. package/dashboard/dist/assets/{ToolPill-HcRTggHo.js → ToolPill-1aTqYtzp.js} +2 -2
  179. package/dashboard/dist/assets/{ToolPill-HcRTggHo.js.map → ToolPill-1aTqYtzp.js.map} +1 -1
  180. package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js → ToolTestPanel-fLzNp79U.js} +2 -2
  181. package/dashboard/dist/assets/{ToolTestPanel-Dosq1cqG.js.map → ToolTestPanel-fLzNp79U.js.map} +1 -1
  182. package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js +9 -0
  183. package/dashboard/dist/assets/TopicDetailPage-D7gCsPKB.js.map +1 -0
  184. package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js → TopicsPage-B3Aa8Haz.js} +2 -2
  185. package/dashboard/dist/assets/{TopicsPage-tVPdz-k0.js.map → TopicsPage-B3Aa8Haz.js.map} +1 -1
  186. package/dashboard/dist/assets/{UserName-DX7IBjFn.js → UserName-BjHIJWgh.js} +2 -2
  187. package/dashboard/dist/assets/{UserName-DX7IBjFn.js.map → UserName-BjHIJWgh.js.map} +1 -1
  188. package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js → WorkflowExecutionPage-BQ7AYlQA.js} +2 -2
  189. package/dashboard/dist/assets/{WorkflowExecutionPage-BjC0j9_L.js.map → WorkflowExecutionPage-BQ7AYlQA.js.map} +1 -1
  190. package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js → WorkflowPill-Z-zHRKOK.js} +2 -2
  191. package/dashboard/dist/assets/{WorkflowPill-54px0YiY.js.map → WorkflowPill-Z-zHRKOK.js.map} +1 -1
  192. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +2 -0
  193. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +1 -0
  194. package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js → WorkflowsOverview-B4DUcVxs.js} +2 -2
  195. package/dashboard/dist/assets/{WorkflowsOverview-DaJRDkNy.js.map → WorkflowsOverview-B4DUcVxs.js.map} +1 -1
  196. package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js → YamlWorkflowsPage-CnTNOku0.js} +2 -2
  197. package/dashboard/dist/assets/{YamlWorkflowsPage-CkpQaUmz.js.map → YamlWorkflowsPage-CnTNOku0.js.map} +1 -1
  198. package/dashboard/dist/assets/{agents-B-P5MlEx.js → agents-CkvQDr9b.js} +2 -2
  199. package/dashboard/dist/assets/{agents-B-P5MlEx.js.map → agents-CkvQDr9b.js.map} +1 -1
  200. package/dashboard/dist/assets/{bots-CZz9iVys.js → bots-CzuMCVgU.js} +2 -2
  201. package/dashboard/dist/assets/{bots-CZz9iVys.js.map → bots-CzuMCVgU.js.map} +1 -1
  202. package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js → capabilities-CbGmS0ty.js} +2 -2
  203. package/dashboard/dist/assets/{capabilities-DrZ8Vw_v.js.map → capabilities-CbGmS0ty.js.map} +1 -1
  204. package/dashboard/dist/assets/{controlplane-cj-1c-1C.js → controlplane-DGvwkuYx.js} +2 -2
  205. package/dashboard/dist/assets/{controlplane-cj-1c-1C.js.map → controlplane-DGvwkuYx.js.map} +1 -1
  206. package/dashboard/dist/assets/{escalation-BEVFyQnE.js → escalation-B7ysVToF.js} +2 -2
  207. package/dashboard/dist/assets/{escalation-BEVFyQnE.js.map → escalation-B7ysVToF.js.map} +1 -1
  208. package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js → escalation-columns-CHQEJU1j.js} +2 -2
  209. package/dashboard/dist/assets/{escalation-columns-Beox3TXH.js.map → escalation-columns-CHQEJU1j.js.map} +1 -1
  210. package/dashboard/dist/assets/{helpers-B4gzNq9h.js → helpers-BFOjXa4r.js} +2 -2
  211. package/dashboard/dist/assets/{helpers-B4gzNq9h.js.map → helpers-BFOjXa4r.js.map} +1 -1
  212. package/dashboard/dist/assets/index-B9_1AZaG.js +2 -0
  213. package/dashboard/dist/assets/{index-3n5VREXN.js.map → index-B9_1AZaG.js.map} +1 -1
  214. package/dashboard/dist/assets/{index-BCQ65lNu.js → index-BFaDxPxA.js} +2 -2
  215. package/dashboard/dist/assets/{index-BCQ65lNu.js.map → index-BFaDxPxA.js.map} +1 -1
  216. package/dashboard/dist/assets/index-BduDiGcw.js +15 -0
  217. package/dashboard/dist/assets/{index-UtAfnStw.js.map → index-BduDiGcw.js.map} +1 -1
  218. package/dashboard/dist/assets/{index-Bh-PnP17.js → index-BeLphL59.js} +2 -2
  219. package/dashboard/dist/assets/{index-Bh-PnP17.js.map → index-BeLphL59.js.map} +1 -1
  220. package/dashboard/dist/assets/index-C--SEsU7.css +1 -0
  221. package/dashboard/dist/assets/{index-_DfbFHXk.js → index-CRiBkHPb.js} +2 -2
  222. package/dashboard/dist/assets/{index-_DfbFHXk.js.map → index-CRiBkHPb.js.map} +1 -1
  223. package/dashboard/dist/assets/{index-DdKbIZNE.js → index-CbrMW-gM.js} +2 -2
  224. package/dashboard/dist/assets/{index-DdKbIZNE.js.map → index-CbrMW-gM.js.map} +1 -1
  225. package/dashboard/dist/assets/{index-aJRDh4zW.js → index-CvOGgvzP.js} +2 -2
  226. package/dashboard/dist/assets/{index-aJRDh4zW.js.map → index-CvOGgvzP.js.map} +1 -1
  227. package/dashboard/dist/assets/{index-D1MywQ2z.js → index-DDlrQeTj.js} +2 -2
  228. package/dashboard/dist/assets/{index-D1MywQ2z.js.map → index-DDlrQeTj.js.map} +1 -1
  229. package/dashboard/dist/assets/{index-BYXiz05a.js → index-DQHmfTPo.js} +2 -2
  230. package/dashboard/dist/assets/{index-BYXiz05a.js.map → index-DQHmfTPo.js.map} +1 -1
  231. package/dashboard/dist/assets/{index-BpN31nuC.js → index-_BRA9uFL.js} +25 -25
  232. package/dashboard/dist/assets/index-_BRA9uFL.js.map +1 -0
  233. package/dashboard/dist/assets/index-a98qWLB-.js +2 -0
  234. package/dashboard/dist/assets/index-a98qWLB-.js.map +1 -0
  235. package/dashboard/dist/assets/index-l_8R6U4r.js +6 -0
  236. package/dashboard/dist/assets/index-l_8R6U4r.js.map +1 -0
  237. package/dashboard/dist/assets/{index-D4KGadbW.js → index-v0OQpgXS.js} +2 -2
  238. package/dashboard/dist/assets/{index-D4KGadbW.js.map → index-v0OQpgXS.js.map} +1 -1
  239. package/dashboard/dist/assets/{knowledge-DhtKWMON.js → knowledge-BlF8UMrk.js} +2 -2
  240. package/dashboard/dist/assets/{knowledge-DhtKWMON.js.map → knowledge-BlF8UMrk.js.map} +1 -1
  241. package/dashboard/dist/assets/{mcp-BXN7-wGF.js → mcp-MtXuky8q.js} +2 -2
  242. package/dashboard/dist/assets/{mcp-BXN7-wGF.js.map → mcp-MtXuky8q.js.map} +1 -1
  243. package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js → mcp-query-DQ-J1Q0K.js} +2 -2
  244. package/dashboard/dist/assets/{mcp-query-BIJP4mQJ.js.map → mcp-query-DQ-J1Q0K.js.map} +1 -1
  245. package/dashboard/dist/assets/{namespaces-ne_yDQZX.js → namespaces-DtsT_GoV.js} +2 -2
  246. package/dashboard/dist/assets/{namespaces-ne_yDQZX.js.map → namespaces-DtsT_GoV.js.map} +1 -1
  247. package/dashboard/dist/assets/{pipelines-Bcz62DoS.js → pipelines-BjlCm9VH.js} +2 -2
  248. package/dashboard/dist/assets/{pipelines-Bcz62DoS.js.map → pipelines-BjlCm9VH.js.map} +1 -1
  249. package/dashboard/dist/assets/{roles-De2CzGCy.js → roles-D-LhJ82d.js} +2 -2
  250. package/dashboard/dist/assets/{roles-De2CzGCy.js.map → roles-D-LhJ82d.js.map} +1 -1
  251. package/dashboard/dist/assets/{tasks-4yL5EfxI.js → tasks-BrP_8uEN.js} +2 -2
  252. package/dashboard/dist/assets/{tasks-4yL5EfxI.js.map → tasks-BrP_8uEN.js.map} +1 -1
  253. package/dashboard/dist/assets/topics-DUk-zX5D.js +2 -0
  254. package/dashboard/dist/assets/{topics-DDKHpRwP.js.map → topics-DUk-zX5D.js.map} +1 -1
  255. package/dashboard/dist/assets/useEventHooks-XNNzwADV.js +2 -0
  256. package/dashboard/dist/assets/useEventHooks-XNNzwADV.js.map +1 -0
  257. package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js → useYamlActivityEvents-DANQ5jIY.js} +2 -2
  258. package/dashboard/dist/assets/{useYamlActivityEvents-Dv6GhDkh.js.map → useYamlActivityEvents-DANQ5jIY.js.map} +1 -1
  259. package/dashboard/dist/assets/{users-pSMWP58G.js → users-vj0JgOkA.js} +2 -2
  260. package/dashboard/dist/assets/{users-pSMWP58G.js.map → users-vj0JgOkA.js.map} +1 -1
  261. package/dashboard/dist/assets/{vendor-icons-CrrAvF2g.js → vendor-icons-Doy0g69_.js} +116 -111
  262. package/dashboard/dist/assets/vendor-icons-Doy0g69_.js.map +1 -0
  263. package/dashboard/dist/assets/{workflows-COYPOe2I.js → workflows-CmqgGPzI.js} +2 -2
  264. package/dashboard/dist/assets/{workflows-COYPOe2I.js.map → workflows-CmqgGPzI.js.map} +1 -1
  265. package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js → yaml-workflows-DNFyjBXH.js} +2 -2
  266. package/dashboard/dist/assets/{yaml-workflows-1dF3ig6u.js.map → yaml-workflows-DNFyjBXH.js.map} +1 -1
  267. package/dashboard/dist/index.html +3 -3
  268. package/docs/api/http/controlplane.md +1 -1
  269. package/docs/api/http/mcp-endpoint.md +133 -0
  270. package/docs/api/http/roles.md +46 -0
  271. package/docs/api/http/service-accounts.md +15 -0
  272. package/docs/api/http/settings.md +6 -0
  273. package/docs/api/mcp/admin.md +1187 -0
  274. package/docs/api/mcp/claude-code.md +47 -0
  275. package/docs/api/mcp/docs.md +54 -0
  276. package/docs/api/mcp/events.md +80 -0
  277. package/docs/api/mcp/file-storage.md +76 -0
  278. package/docs/api/mcp/http-fetch.md +64 -0
  279. package/docs/api/mcp/human-queue.md +101 -0
  280. package/docs/api/mcp/index.md +52 -0
  281. package/docs/api/mcp/knowledge.md +125 -0
  282. package/docs/api/mcp/oauth.md +62 -0
  283. package/docs/api/mcp/schema-exchange.md +56 -0
  284. package/docs/api/mcp/translation.md +28 -0
  285. package/docs/api/mcp/vision.md +46 -0
  286. package/docs/api/sdk/settings.md +3 -1
  287. package/docs/auth.md +109 -0
  288. package/docs/dashboard.md +1 -1
  289. package/package.json +1 -1
  290. package/build/system/mcp-servers/playwright/browser-lifecycle.d.ts +0 -26
  291. package/build/system/mcp-servers/playwright/browser-lifecycle.js +0 -125
  292. package/build/system/mcp-servers/playwright/index.d.ts +0 -25
  293. package/build/system/mcp-servers/playwright/index.js +0 -42
  294. package/build/system/mcp-servers/playwright/schemas.d.ts +0 -394
  295. package/build/system/mcp-servers/playwright/schemas.js +0 -90
  296. package/build/system/mcp-servers/playwright/tools-atomic.d.ts +0 -2
  297. package/build/system/mcp-servers/playwright/tools-atomic.js +0 -9
  298. package/build/system/mcp-servers/playwright/tools-navigation.d.ts +0 -2
  299. package/build/system/mcp-servers/playwright/tools-navigation.js +0 -153
  300. package/build/system/mcp-servers/playwright/tools-page-interaction.d.ts +0 -2
  301. package/build/system/mcp-servers/playwright/tools-page-interaction.js +0 -162
  302. package/build/system/mcp-servers/playwright/tools-run-script.d.ts +0 -2
  303. package/build/system/mcp-servers/playwright/tools-run-script.js +0 -207
  304. package/build/system/mcp-servers/playwright/types.d.ts +0 -8
  305. package/build/system/mcp-servers/playwright/types.js +0 -30
  306. package/build/system/mcp-servers/playwright/vision-helper.d.ts +0 -12
  307. package/build/system/mcp-servers/playwright/vision-helper.js +0 -81
  308. package/build/system/mcp-servers/playwright-cli/helpers.d.ts +0 -11
  309. package/build/system/mcp-servers/playwright-cli/helpers.js +0 -20
  310. package/build/system/mcp-servers/playwright-cli/index.d.ts +0 -4
  311. package/build/system/mcp-servers/playwright-cli/index.js +0 -15
  312. package/build/system/mcp-servers/playwright-cli/schemas.d.ts +0 -219
  313. package/build/system/mcp-servers/playwright-cli/schemas.js +0 -75
  314. package/build/system/mcp-servers/playwright-cli/tools-auth.d.ts +0 -2
  315. package/build/system/mcp-servers/playwright-cli/tools-auth.js +0 -183
  316. package/build/system/mcp-servers/playwright-cli/tools-capture.d.ts +0 -2
  317. package/build/system/mcp-servers/playwright-cli/tools-capture.js +0 -273
  318. package/build/system/seed/tool-manifests-browser.d.ts +0 -577
  319. package/build/system/seed/tool-manifests-browser.js +0 -158
  320. package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js +0 -16
  321. package/dashboard/dist/assets/AgentConfigPage-DBtvb2x5.js.map +0 -1
  322. package/dashboard/dist/assets/AgentDetailPage-3mZA7SOb.js.map +0 -1
  323. package/dashboard/dist/assets/AvailableEscalationsPage-CA9x9o5s.js +0 -2
  324. package/dashboard/dist/assets/BotPicker-BQp_Vs73.js +0 -2
  325. package/dashboard/dist/assets/CronLabel-DY8VdTS9.js +0 -2
  326. package/dashboard/dist/assets/CronLabel-DY8VdTS9.js.map +0 -1
  327. package/dashboard/dist/assets/ElapsedCell-BPYm8RA7.js +0 -2
  328. package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js +0 -2
  329. package/dashboard/dist/assets/EventTopicPill-CCWCs07y.js.map +0 -1
  330. package/dashboard/dist/assets/HomePage-CwRebzmO.js +0 -2
  331. package/dashboard/dist/assets/HomePage-CwRebzmO.js.map +0 -1
  332. package/dashboard/dist/assets/ListToolbar-DEef1_-T.js +0 -2
  333. package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js +0 -2
  334. package/dashboard/dist/assets/McpRunDetailPage-X0sfRFTk.js.map +0 -1
  335. package/dashboard/dist/assets/McpRunsPage-aZg057y3.js +0 -2
  336. package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js +0 -2
  337. package/dashboard/dist/assets/OperatorDashboard-iZEHnndU.js.map +0 -1
  338. package/dashboard/dist/assets/ServerName-Q6okiv4f.js +0 -2
  339. package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js +0 -9
  340. package/dashboard/dist/assets/TopicDetailPage-DW97-YHQ.js.map +0 -1
  341. package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js +0 -2
  342. package/dashboard/dist/assets/WorkflowsDashboard-eCH4gpAk.js.map +0 -1
  343. package/dashboard/dist/assets/index-3n5VREXN.js +0 -2
  344. package/dashboard/dist/assets/index-BAXzN-QB.js +0 -6
  345. package/dashboard/dist/assets/index-BAXzN-QB.js.map +0 -1
  346. package/dashboard/dist/assets/index-BpN31nuC.js.map +0 -1
  347. package/dashboard/dist/assets/index-C37LMzJa.css +0 -1
  348. package/dashboard/dist/assets/index-C5dHozmW.js +0 -2
  349. package/dashboard/dist/assets/index-C5dHozmW.js.map +0 -1
  350. package/dashboard/dist/assets/index-UtAfnStw.js +0 -15
  351. package/dashboard/dist/assets/topics-DDKHpRwP.js +0 -2
  352. package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js +0 -2
  353. package/dashboard/dist/assets/useEventHooks-NzIyvoGY.js.map +0 -1
  354. package/dashboard/dist/assets/vendor-icons-CrrAvF2g.js.map +0 -1
@@ -40,7 +40,23 @@ function applyInputMapping(mapping, event) {
40
40
  if (typeof value === 'string') {
41
41
  result[key] = resolveTemplate(value, event);
42
42
  }
43
- else if (value && typeof value === 'object' && !Array.isArray(value)) {
43
+ else if (Array.isArray(value)) {
44
+ result[key] = value.map((item) => {
45
+ if (typeof item === 'string') {
46
+ const resolved = resolveTemplate(item, event);
47
+ // Coerce scalars to strings when the template was a string in an array context.
48
+ // Objects/arrays pass through (e.g., "{event.data}" resolves to the full object).
49
+ if (resolved !== null && resolved !== undefined && typeof resolved !== 'object') {
50
+ return String(resolved);
51
+ }
52
+ return resolved;
53
+ }
54
+ if (item && typeof item === 'object')
55
+ return applyInputMapping(item, event);
56
+ return item;
57
+ });
58
+ }
59
+ else if (value && typeof value === 'object') {
44
60
  result[key] = applyInputMapping(value, event);
45
61
  }
46
62
  else {
@@ -49,4 +49,20 @@ export declare function findByMetadata(key: string, value: string, status?: stri
49
49
  escalations: LTEscalationRecord[];
50
50
  total: number;
51
51
  }>;
52
- export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>): Promise<ClaimResult | null>;
52
+ /**
53
+ * Atomic claim by metadata with inline RBAC.
54
+ * The SQL WHERE clause enforces role membership — if the caller
55
+ * doesn't have an allowed role, zero rows match and the claim
56
+ * never happens. No pre-flight find, no TOCTOU.
57
+ *
58
+ * @param allowedRoles — roles the caller can claim (null = no filter / global access)
59
+ * @returns `{ escalation, isExtension, candidatesExist }` or null
60
+ */
61
+ export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>, allowedRoles?: string[] | null): Promise<(ClaimResult & {
62
+ candidatesExist: number;
63
+ }) | null>;
64
+ /**
65
+ * Atomic resolve by metadata: find + claim + resolve in one CTE.
66
+ * RBAC is enforced in the SQL WHERE clause via allowedRoles.
67
+ */
68
+ export declare function resolveByMetadataAtomic(key: string, value: string, userId: string, resolverPayload: Record<string, any>, metadata?: Record<string, any>, allowedRoles?: string[] | null): Promise<LTEscalationRecord | null>;
@@ -16,6 +16,7 @@ exports.enrichEscalationRouting = enrichEscalationRouting;
16
16
  exports.getEscalationsByOriginId = getEscalationsByOriginId;
17
17
  exports.findByMetadata = findByMetadata;
18
18
  exports.claimByMetadata = claimByMetadata;
19
+ exports.resolveByMetadataAtomic = resolveByMetadataAtomic;
19
20
  const db_1 = require("../../lib/db");
20
21
  const publish_1 = require("../../lib/events/publish");
21
22
  const logger_1 = require("../../lib/logger");
@@ -135,7 +136,20 @@ async function getEscalationRoles(ids) {
135
136
  async function releaseEscalation(id, userId) {
136
137
  const pool = (0, db_1.getPool)();
137
138
  const { rows } = await pool.query(sql_1.RELEASE_ESCALATION, [id, userId]);
138
- return rows[0] || null;
139
+ const released = rows[0];
140
+ if (released) {
141
+ (0, publish_1.publishEscalationEvent)({
142
+ type: 'escalation.released',
143
+ source: 'service',
144
+ workflowId: released.workflow_id || '',
145
+ workflowName: released.workflow_type || '',
146
+ taskQueue: released.task_queue || '',
147
+ escalationId: released.id,
148
+ status: 'released',
149
+ data: { released_by: userId },
150
+ });
151
+ }
152
+ return released || null;
139
153
  }
140
154
  async function releaseExpiredClaims() {
141
155
  const pool = (0, db_1.getPool)();
@@ -192,24 +206,32 @@ async function getEscalationsByOriginId(originId) {
192
206
  async function findByMetadata(key, value, status, limit = 50, offset = 0) {
193
207
  const pool = (0, db_1.getPool)();
194
208
  const filter = JSON.stringify({ [key]: value });
195
- const [countResult, dataResult] = await Promise.all([
196
- pool.query(sql_1.COUNT_BY_METADATA, [filter, status || null]),
197
- pool.query(sql_1.FIND_BY_METADATA, [filter, status || null, limit, offset]),
198
- ]);
199
- return {
200
- escalations: dataResult.rows,
201
- total: parseInt(countResult.rows[0].count, 10),
202
- };
209
+ const { rows } = await pool.query(sql_1.FIND_BY_METADATA, [filter, status || null, limit, offset]);
210
+ const total = rows.length > 0 ? parseInt(rows[0]._total, 10) : 0;
211
+ // Strip the window function column from results
212
+ const escalations = rows.map(({ _total, ...rest }) => rest);
213
+ return { escalations, total };
203
214
  }
204
- async function claimByMetadata(key, value, userId, durationMinutes = 30, metadata) {
215
+ /**
216
+ * Atomic claim by metadata with inline RBAC.
217
+ * The SQL WHERE clause enforces role membership — if the caller
218
+ * doesn't have an allowed role, zero rows match and the claim
219
+ * never happens. No pre-flight find, no TOCTOU.
220
+ *
221
+ * @param allowedRoles — roles the caller can claim (null = no filter / global access)
222
+ * @returns `{ escalation, isExtension, candidatesExist }` or null
223
+ */
224
+ async function claimByMetadata(key, value, userId, durationMinutes = 30, metadata, allowedRoles) {
205
225
  const pool = (0, db_1.getPool)();
206
226
  const filter = JSON.stringify({ [key]: value });
207
227
  const metaPatch = metadata ? JSON.stringify(metadata) : null;
208
- const { rows } = await pool.query(sql_1.CLAIM_BY_METADATA, [filter, userId, durationMinutes, metaPatch]);
228
+ const roles = allowedRoles ?? null;
229
+ const { rows } = await pool.query(sql_1.CLAIM_BY_METADATA_GUARDED, [filter, userId, durationMinutes, metaPatch, roles]);
209
230
  if (rows.length === 0)
210
231
  return null;
211
232
  const row = rows[0];
212
- const escalation = row;
233
+ const { candidates_exist, prev_assigned_to, _total, ...rest } = row;
234
+ const escalation = rest;
213
235
  (0, publish_1.publishEscalationEvent)({
214
236
  type: 'escalation.claimed',
215
237
  source: 'service',
@@ -222,6 +244,33 @@ async function claimByMetadata(key, value, userId, durationMinutes = 30, metadat
222
244
  });
223
245
  return {
224
246
  escalation,
225
- isExtension: row.prev_assigned_to === userId,
247
+ isExtension: prev_assigned_to === userId,
248
+ candidatesExist: parseInt(candidates_exist, 10),
226
249
  };
227
250
  }
251
+ /**
252
+ * Atomic resolve by metadata: find + claim + resolve in one CTE.
253
+ * RBAC is enforced in the SQL WHERE clause via allowedRoles.
254
+ */
255
+ async function resolveByMetadataAtomic(key, value, userId, resolverPayload, metadata, allowedRoles) {
256
+ const pool = (0, db_1.getPool)();
257
+ const filter = JSON.stringify({ [key]: value });
258
+ const payloadJson = JSON.stringify(resolverPayload);
259
+ const metaPatch = metadata ? JSON.stringify(metadata) : null;
260
+ const roles = allowedRoles ?? null;
261
+ const { rows } = await pool.query(sql_1.RESOLVE_BY_METADATA_ATOMIC, [filter, userId, payloadJson, metaPatch, roles]);
262
+ if (rows.length === 0)
263
+ return null;
264
+ const escalation = rows[0];
265
+ (0, publish_1.publishEscalationEvent)({
266
+ type: 'escalation.resolved',
267
+ source: 'service',
268
+ workflowId: escalation.workflow_id || '',
269
+ workflowName: escalation.workflow_type || '',
270
+ taskQueue: escalation.task_queue || '',
271
+ escalationId: escalation.id,
272
+ status: 'resolved',
273
+ data: { resolved_by: userId },
274
+ });
275
+ return escalation;
276
+ }
@@ -8,6 +8,7 @@ export declare function listEscalations(filters: {
8
8
  type?: string;
9
9
  subtype?: string;
10
10
  assigned_to?: string;
11
+ claimed?: boolean;
11
12
  priority?: number;
12
13
  limit?: number;
13
14
  offset?: number;
@@ -96,6 +96,13 @@ async function listEscalations(filters) {
96
96
  if (filters.assigned_to) {
97
97
  conditions.push(`assigned_to = $${idx++}`);
98
98
  values.push(filters.assigned_to);
99
+ // Only return active claims — expired claims are back in the available pool
100
+ conditions.push('assigned_until > NOW()');
101
+ }
102
+ if (filters.claimed) {
103
+ // All actively claimed escalations (by anyone)
104
+ conditions.push('assigned_to IS NOT NULL');
105
+ conditions.push('assigned_until > NOW()');
99
106
  }
100
107
  if (filters.priority) {
101
108
  conditions.push(`priority = $${idx++}`);
@@ -19,8 +19,17 @@ export declare const BULK_RESOLVE_FOR_TRIAGE = "UPDATE lt_escalations\nSET statu
19
19
  export declare const UPDATE_ESCALATION_METADATA = "UPDATE lt_escalations\nSET metadata = COALESCE(metadata, '{}'::jsonb) || $2::jsonb,\n updated_at = NOW()\nWHERE id = $1\nRETURNING *";
20
20
  export declare const ENRICH_ESCALATION_ROUTING = "UPDATE lt_escalations\nSET metadata = COALESCE(metadata, '{}'::jsonb) || $2::jsonb,\n workflow_type = COALESCE(workflow_type, $3),\n workflow_id = COALESCE(workflow_id, $4),\n task_queue = COALESCE(task_queue, $5),\n task_id = COALESCE(task_id, $6),\n updated_at = NOW()\nWHERE id = $1\nRETURNING *";
21
21
  export declare const LIST_DISTINCT_TYPES = "SELECT DISTINCT type FROM lt_escalations ORDER BY type";
22
- /** Find escalations by a single metadata key-value pair. */
23
- export declare const FIND_BY_METADATA = "SELECT * FROM lt_escalations\nWHERE metadata @> $1::jsonb\n AND ($2::text IS NULL OR status = $2)\nORDER BY priority ASC, created_at ASC\nLIMIT $3 OFFSET $4";
24
- export declare const COUNT_BY_METADATA = "SELECT COUNT(*) FROM lt_escalations\nWHERE metadata @> $1::jsonb\n AND ($2::text IS NULL OR status = $2)";
25
- /** Atomic claim by metadata: find one available escalation, claim it, and optionally merge metadata. */
26
- export declare const CLAIM_BY_METADATA = "WITH target AS (\n SELECT id, assigned_to\n FROM lt_escalations\n WHERE metadata @> $1::jsonb\n AND status = 'pending'\n AND (\n assigned_to IS NULL\n OR assigned_until <= NOW()\n OR assigned_to = $2\n )\n ORDER BY priority ASC, created_at ASC\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n),\nupdated AS (\n UPDATE lt_escalations e\n SET assigned_to = $2,\n claimed_at = NOW(),\n assigned_until = NOW() + INTERVAL '1 minute' * $3,\n metadata = CASE WHEN $4::jsonb IS NOT NULL\n THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb\n ELSE e.metadata END\n FROM target t\n WHERE e.id = t.id\n RETURNING e.*, t.assigned_to AS prev_assigned_to\n)\nSELECT * FROM updated";
22
+ /** Find escalations by a single metadata key-value pair. Window function for total count. */
23
+ export declare const FIND_BY_METADATA = "SELECT *, COUNT(*) OVER() AS _total\nFROM lt_escalations\nWHERE metadata @> $1::jsonb\n AND ($2::text IS NULL OR status = $2)\nORDER BY priority ASC, created_at ASC\nLIMIT $3 OFFSET $4";
24
+ /**
25
+ * Atomic claim by metadata with inline RBAC.
26
+ * $1 = metadata filter (jsonb), $2 = userId, $3 = durationMinutes,
27
+ * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
28
+ */
29
+ export declare const CLAIM_BY_METADATA_GUARDED = "WITH target AS (\n SELECT id, assigned_to\n FROM lt_escalations\n WHERE metadata @> $1::jsonb\n AND status = 'pending'\n AND (assigned_to IS NULL OR assigned_until <= NOW() OR assigned_to = $2)\n AND ($5::text[] IS NULL OR role = ANY($5))\n ORDER BY priority ASC, created_at ASC\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n),\nupdated AS (\n UPDATE lt_escalations e\n SET assigned_to = $2,\n claimed_at = NOW(),\n assigned_until = NOW() + INTERVAL '1 minute' * $3,\n metadata = CASE WHEN $4::jsonb IS NOT NULL\n THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb\n ELSE e.metadata END,\n updated_at = NOW()\n FROM target t\n WHERE e.id = t.id\n RETURNING e.*, t.assigned_to AS prev_assigned_to\n)\nSELECT *,\n (SELECT COUNT(*) FROM lt_escalations WHERE metadata @> $1::jsonb AND status = 'pending') AS candidates_exist\nFROM updated";
30
+ /**
31
+ * Atomic resolve by metadata: find + claim + resolve in one CTE.
32
+ * $1 = metadata filter (jsonb), $2 = userId, $3 = resolver_payload (jsonb),
33
+ * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
34
+ */
35
+ export declare const RESOLVE_BY_METADATA_ATOMIC = "WITH target AS (\n SELECT id\n FROM lt_escalations\n WHERE metadata @> $1::jsonb\n AND status = 'pending'\n AND ($5::text[] IS NULL OR role = ANY($5))\n ORDER BY priority ASC, created_at ASC\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n),\nclaimed AS (\n UPDATE lt_escalations e\n SET assigned_to = $2,\n claimed_at = NOW(),\n assigned_until = NOW() + INTERVAL '5 minutes',\n metadata = CASE WHEN $4::jsonb IS NOT NULL\n THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb\n ELSE e.metadata END\n FROM target\n WHERE e.id = target.id\n RETURNING e.*\n)\nUPDATE lt_escalations e\nSET status = 'resolved',\n resolved_at = NOW(),\n resolver_payload = $3,\n updated_at = NOW()\nFROM claimed\nWHERE e.id = claimed.id\nRETURNING e.*";
@@ -3,7 +3,7 @@
3
3
  // Escalation SQL – externalized from crud.ts, bulk.ts, queries.ts
4
4
  // ---------------------------------------------------------------------------
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.CLAIM_BY_METADATA = exports.COUNT_BY_METADATA = exports.FIND_BY_METADATA = exports.LIST_DISTINCT_TYPES = exports.ENRICH_ESCALATION_ROUTING = exports.UPDATE_ESCALATION_METADATA = exports.BULK_RESOLVE_FOR_TRIAGE = exports.BULK_ESCALATE_TO_ROLE = exports.BULK_ASSIGN = exports.BULK_CLAIM = exports.GET_ESCALATIONS_BY_ORIGIN_ID = exports.GET_ESCALATIONS_BY_WORKFLOW_ID = exports.GET_ESCALATIONS_BY_TASK_ID = exports.GET_ESCALATION = exports.ESCALATE_TO_ROLE = exports.RELEASE_EXPIRED_CLAIMS = exports.RELEASE_ESCALATION = exports.GET_ESCALATION_ROLES = exports.UPDATE_ESCALATIONS_PRIORITY = exports.RESOLVE_ESCALATION = exports.CLAIM_ESCALATION = exports.CREATE_ESCALATION = exports.ENSURE_ROLE_EXISTS = void 0;
6
+ exports.RESOLVE_BY_METADATA_ATOMIC = exports.CLAIM_BY_METADATA_GUARDED = exports.FIND_BY_METADATA = exports.LIST_DISTINCT_TYPES = exports.ENRICH_ESCALATION_ROUTING = exports.UPDATE_ESCALATION_METADATA = exports.BULK_RESOLVE_FOR_TRIAGE = exports.BULK_ESCALATE_TO_ROLE = exports.BULK_ASSIGN = exports.BULK_CLAIM = exports.GET_ESCALATIONS_BY_ORIGIN_ID = exports.GET_ESCALATIONS_BY_WORKFLOW_ID = exports.GET_ESCALATIONS_BY_TASK_ID = exports.GET_ESCALATION = exports.ESCALATE_TO_ROLE = exports.RELEASE_EXPIRED_CLAIMS = exports.RELEASE_ESCALATION = exports.GET_ESCALATION_ROLES = exports.UPDATE_ESCALATIONS_PRIORITY = exports.RESOLVE_ESCALATION = exports.CLAIM_ESCALATION = exports.CREATE_ESCALATION = exports.ENSURE_ROLE_EXISTS = void 0;
7
7
  // --- Role management -------------------------------------------------------
8
8
  exports.ENSURE_ROLE_EXISTS = 'INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING';
9
9
  // --- Single-record CRUD ---------------------------------------------------
@@ -134,29 +134,27 @@ WHERE id = $1
134
134
  RETURNING *`;
135
135
  exports.LIST_DISTINCT_TYPES = 'SELECT DISTINCT type FROM lt_escalations ORDER BY type';
136
136
  // --- Metadata candidate key lookups -----------------------------------------
137
- /** Find escalations by a single metadata key-value pair. */
137
+ /** Find escalations by a single metadata key-value pair. Window function for total count. */
138
138
  exports.FIND_BY_METADATA = `\
139
- SELECT * FROM lt_escalations
139
+ SELECT *, COUNT(*) OVER() AS _total
140
+ FROM lt_escalations
140
141
  WHERE metadata @> $1::jsonb
141
142
  AND ($2::text IS NULL OR status = $2)
142
143
  ORDER BY priority ASC, created_at ASC
143
144
  LIMIT $3 OFFSET $4`;
144
- exports.COUNT_BY_METADATA = `\
145
- SELECT COUNT(*) FROM lt_escalations
146
- WHERE metadata @> $1::jsonb
147
- AND ($2::text IS NULL OR status = $2)`;
148
- /** Atomic claim by metadata: find one available escalation, claim it, and optionally merge metadata. */
149
- exports.CLAIM_BY_METADATA = `\
145
+ /**
146
+ * Atomic claim by metadata with inline RBAC.
147
+ * $1 = metadata filter (jsonb), $2 = userId, $3 = durationMinutes,
148
+ * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
149
+ */
150
+ exports.CLAIM_BY_METADATA_GUARDED = `\
150
151
  WITH target AS (
151
152
  SELECT id, assigned_to
152
153
  FROM lt_escalations
153
154
  WHERE metadata @> $1::jsonb
154
155
  AND status = 'pending'
155
- AND (
156
- assigned_to IS NULL
157
- OR assigned_until <= NOW()
158
- OR assigned_to = $2
159
- )
156
+ AND (assigned_to IS NULL OR assigned_until <= NOW() OR assigned_to = $2)
157
+ AND ($5::text[] IS NULL OR role = ANY($5))
160
158
  ORDER BY priority ASC, created_at ASC
161
159
  LIMIT 1
162
160
  FOR UPDATE SKIP LOCKED
@@ -168,9 +166,48 @@ updated AS (
168
166
  assigned_until = NOW() + INTERVAL '1 minute' * $3,
169
167
  metadata = CASE WHEN $4::jsonb IS NOT NULL
170
168
  THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb
171
- ELSE e.metadata END
169
+ ELSE e.metadata END,
170
+ updated_at = NOW()
172
171
  FROM target t
173
172
  WHERE e.id = t.id
174
173
  RETURNING e.*, t.assigned_to AS prev_assigned_to
175
174
  )
176
- SELECT * FROM updated`;
175
+ SELECT *,
176
+ (SELECT COUNT(*) FROM lt_escalations WHERE metadata @> $1::jsonb AND status = 'pending') AS candidates_exist
177
+ FROM updated`;
178
+ /**
179
+ * Atomic resolve by metadata: find + claim + resolve in one CTE.
180
+ * $1 = metadata filter (jsonb), $2 = userId, $3 = resolver_payload (jsonb),
181
+ * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
182
+ */
183
+ exports.RESOLVE_BY_METADATA_ATOMIC = `\
184
+ WITH target AS (
185
+ SELECT id
186
+ FROM lt_escalations
187
+ WHERE metadata @> $1::jsonb
188
+ AND status = 'pending'
189
+ AND ($5::text[] IS NULL OR role = ANY($5))
190
+ ORDER BY priority ASC, created_at ASC
191
+ LIMIT 1
192
+ FOR UPDATE SKIP LOCKED
193
+ ),
194
+ claimed AS (
195
+ UPDATE lt_escalations e
196
+ SET assigned_to = $2,
197
+ claimed_at = NOW(),
198
+ assigned_until = NOW() + INTERVAL '5 minutes',
199
+ metadata = CASE WHEN $4::jsonb IS NOT NULL
200
+ THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb
201
+ ELSE e.metadata END
202
+ FROM target
203
+ WHERE e.id = target.id
204
+ RETURNING e.*
205
+ )
206
+ UPDATE lt_escalations e
207
+ SET status = 'resolved',
208
+ resolved_at = NOW(),
209
+ resolver_payload = $3,
210
+ updated_at = NOW()
211
+ FROM claimed
212
+ WHERE e.id = claimed.id
213
+ RETURNING e.*`;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * MCP exposure configuration — controls which tools are visible
3
+ * when long-tail acts as an MCP server for external clients.
4
+ *
5
+ * Set once at startup from startConfig.mcp.exposure.
6
+ * Read by the /mcp endpoint handler on each request.
7
+ */
8
+ export interface ExposureConfig {
9
+ readOnly?: boolean;
10
+ hideAiWhenUnavailable?: boolean;
11
+ allowServers?: string[];
12
+ denyServers?: string[];
13
+ }
14
+ export declare function setExposureConfig(config?: ExposureConfig): void;
15
+ export declare function getExposureConfig(): ExposureConfig | undefined;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /**
3
+ * MCP exposure configuration — controls which tools are visible
4
+ * when long-tail acts as an MCP server for external clients.
5
+ *
6
+ * Set once at startup from startConfig.mcp.exposure.
7
+ * Read by the /mcp endpoint handler on each request.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.setExposureConfig = setExposureConfig;
11
+ exports.getExposureConfig = getExposureConfig;
12
+ let _exposure;
13
+ function setExposureConfig(config) {
14
+ _exposure = config;
15
+ }
16
+ function getExposureConfig() {
17
+ return _exposure;
18
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Unified MCP server for external clients.
3
+ *
4
+ * Aggregates tools from all shipped built-in servers into a single
5
+ * McpServer instance that can be connected to a StreamableHTTPServerTransport.
6
+ * Created per-request in stateless mode (pure in-memory, no IO).
7
+ */
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import type { ExposureConfig } from './exposure';
10
+ /**
11
+ * Create a unified McpServer with tools from all qualifying shipped servers.
12
+ * Called per-request in stateless mode. Server instances are cached; only
13
+ * the McpServer wrapper and tool registrations are fresh (pure in-memory).
14
+ */
15
+ export declare function createUnifiedMcpServer(exposure?: ExposureConfig, callerScopes?: string[]): Promise<McpServer>;
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /**
3
+ * Unified MCP server for external clients.
4
+ *
5
+ * Aggregates tools from all shipped built-in servers into a single
6
+ * McpServer instance that can be connected to a StreamableHTTPServerTransport.
7
+ * Created per-request in stateless mode (pure in-memory, no IO).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createUnifiedMcpServer = createUnifiedMcpServer;
11
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
12
+ const logger_1 = require("../../lib/logger");
13
+ const system_1 = require("../../system");
14
+ // ── Shipped server allowlist ─────────────────────────────────────────────────
15
+ // Only these servers are exposed via the /mcp endpoint.
16
+ // Example servers (playwright, gmail, image-tools) are excluded.
17
+ const SHIPPED_SERVERS = new Set([
18
+ 'long-tail-admin',
19
+ 'long-tail-human-queue',
20
+ 'long-tail-file-storage',
21
+ 'long-tail-http-fetch',
22
+ 'long-tail-schema-exchange',
23
+ 'long-tail-oauth',
24
+ 'long-tail-knowledge',
25
+ 'long-tail-docs',
26
+ 'long-tail-events',
27
+ 'long-tail-vision',
28
+ 'long-tail-translation',
29
+ 'long-tail-claude-code',
30
+ ]);
31
+ // ── Server instance cache ────────────────────────────────────────────────────
32
+ // Built-in servers are lazily created once and reused across requests.
33
+ // Tool handlers are stateless — safe to share.
34
+ const serverCache = new Map();
35
+ async function getOrCreateServer(name) {
36
+ if (serverCache.has(name))
37
+ return serverCache.get(name);
38
+ const entry = system_1.builtinMcpServerFactories[name];
39
+ if (!entry)
40
+ return null;
41
+ const server = await entry.factory();
42
+ serverCache.set(name, server);
43
+ return server;
44
+ }
45
+ // ── Exposure filtering ───────────────────────────────────────────────────────
46
+ function isServerAllowed(name, exposure) {
47
+ if (!SHIPPED_SERVERS.has(name))
48
+ return false;
49
+ if (exposure?.allowServers?.length) {
50
+ if (!exposure.allowServers.includes(name))
51
+ return false;
52
+ }
53
+ if (exposure?.denyServers?.length) {
54
+ if (exposure.denyServers.includes(name))
55
+ return false;
56
+ }
57
+ if (exposure?.hideAiWhenUnavailable !== false) {
58
+ const config = system_1.builtinMcpServerFactories[name]?.config;
59
+ if (config?.aiRequired) {
60
+ const hasKey = !!(process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY);
61
+ if (!hasKey)
62
+ return false;
63
+ }
64
+ }
65
+ return true;
66
+ }
67
+ function isToolAllowed(toolName, serverName, exposure, callerScopes) {
68
+ // Per-caller scope filtering: mcp:read callers only see read_safe tools
69
+ const isReadOnly = exposure?.readOnly
70
+ || (callerScopes?.length && callerScopes.includes('mcp:read') && !callerScopes.includes('mcp:full'));
71
+ if (!isReadOnly)
72
+ return true;
73
+ // Check read_safe in the tool manifest
74
+ const config = system_1.builtinMcpServerFactories[serverName]?.config;
75
+ const manifest = config?.toolManifest;
76
+ if (!manifest)
77
+ return true; // no manifest = allow (conservative)
78
+ const entry = manifest.find((t) => t.name === toolName);
79
+ return entry?.read_safe !== false; // allow if read_safe is true or absent
80
+ }
81
+ // ── Unified server creation ──────────────────────────────────────────────────
82
+ /**
83
+ * Create a unified McpServer with tools from all qualifying shipped servers.
84
+ * Called per-request in stateless mode. Server instances are cached; only
85
+ * the McpServer wrapper and tool registrations are fresh (pure in-memory).
86
+ */
87
+ async function createUnifiedMcpServer(exposure, callerScopes) {
88
+ const unified = new mcp_js_1.McpServer({ name: 'long-tail', version: '1.0.0' });
89
+ const registered = new Set();
90
+ for (const [name, entry] of Object.entries(system_1.builtinMcpServerFactories)) {
91
+ if (!isServerAllowed(name, exposure))
92
+ continue;
93
+ const server = await getOrCreateServer(name);
94
+ if (!server)
95
+ continue;
96
+ const tools = server._registeredTools;
97
+ if (!tools)
98
+ continue;
99
+ for (const [toolName, tool] of Object.entries(tools)) {
100
+ if (!tool?.handler || !tool.enabled)
101
+ continue;
102
+ if (!isToolAllowed(toolName, name, exposure, callerScopes))
103
+ continue;
104
+ // Deduplicate: prefix with server short name on collision
105
+ let finalName = toolName;
106
+ if (registered.has(toolName)) {
107
+ const prefix = name.replace('long-tail-', '').replace(/-/g, '_');
108
+ finalName = `${prefix}_${toolName}`;
109
+ if (registered.has(finalName))
110
+ continue; // still a collision — skip
111
+ }
112
+ registered.add(finalName);
113
+ // Re-register the tool handler on the unified server.
114
+ // Use the low-level `tool()` API since we already have the parsed handler.
115
+ unified.registerTool(finalName, {
116
+ title: tool.title,
117
+ description: tool.description,
118
+ inputSchema: tool.inputSchema,
119
+ annotations: tool.annotations,
120
+ }, tool.handler);
121
+ }
122
+ }
123
+ logger_1.loggerRegistry.info(`[lt-mcp:endpoint] unified server ready (${registered.size} tools)`);
124
+ return unified;
125
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Seed the MCP service account at startup.
3
+ *
4
+ * Creates a single `mcp-service` bot account with two API keys:
5
+ * - `mcp:read` — read-safe tools only (discovery, monitoring)
6
+ * - `mcp:full` — all tools (automation, orchestration)
7
+ *
8
+ * Idempotent — skips creation if the account already exists.
9
+ * Keys are generated once and logged; they cannot be retrieved again.
10
+ */
11
+ export declare function seedMcpServiceAccount(): Promise<void>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * Seed the MCP service account at startup.
4
+ *
5
+ * Creates a single `mcp-service` bot account with two API keys:
6
+ * - `mcp:read` — read-safe tools only (discovery, monitoring)
7
+ * - `mcp:full` — all tools (automation, orchestration)
8
+ *
9
+ * Idempotent — skips creation if the account already exists.
10
+ * Keys are generated once and logged; they cannot be retrieved again.
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.seedMcpServiceAccount = seedMcpServiceAccount;
47
+ const logger_1 = require("../../lib/logger");
48
+ const crud_1 = require("../user/crud");
49
+ const iam = __importStar(require("../iam"));
50
+ const SERVICE_ACCOUNT_NAME = 'mcp-service';
51
+ async function seedMcpServiceAccount() {
52
+ try {
53
+ // Check if account already exists (bot external_id = name)
54
+ const existing = await (0, crud_1.getUserByExternalId)(SERVICE_ACCOUNT_NAME);
55
+ if (existing) {
56
+ logger_1.loggerRegistry.info(`[seed-mcp] ${SERVICE_ACCOUNT_NAME} already exists, skipping`);
57
+ return;
58
+ }
59
+ // Create the service account
60
+ const bot = await iam.createBot({
61
+ name: SERVICE_ACCOUNT_NAME,
62
+ description: 'MCP service account for external tool access. Use the read key to explore, full key to automate.',
63
+ display_name: 'MCP Service',
64
+ roles: [{ role: 'system', type: 'member' }],
65
+ });
66
+ // Generate read key (scoped to mcp:read)
67
+ const readKey = await iam.createBotKey(bot.id, 'read', ['mcp:read']);
68
+ logger_1.loggerRegistry.info(`[seed-mcp] read key: ${readKey.rawKey}`);
69
+ // Generate full key (scoped to mcp:full)
70
+ const fullKey = await iam.createBotKey(bot.id, 'full', ['mcp:read', 'mcp:full']);
71
+ logger_1.loggerRegistry.info(`[seed-mcp] full key: ${fullKey.rawKey}`);
72
+ logger_1.loggerRegistry.info(`[seed-mcp] ${SERVICE_ACCOUNT_NAME} created with read + full API keys`);
73
+ }
74
+ catch (err) {
75
+ logger_1.loggerRegistry.warn(`[seed-mcp] failed to seed: ${err.message}`);
76
+ }
77
+ }
@@ -21,7 +21,7 @@ export declare function removeEscalationChain(sourceRole: string, targetRole: st
21
21
  export declare function replaceEscalationTargets(sourceRole: string, targets: string[]): Promise<void>;
22
22
  /**
23
23
  * Check whether a user can escalate from sourceRole to targetRole.
24
- * Superadmins can escalate to any role.
24
+ * Superadmins and admin/admin can escalate to any role.
25
25
  * Others must hold the sourceRole AND the chain must exist.
26
26
  */
27
27
  export declare function canEscalateTo(userId: string, sourceRole: string, targetRole: string): Promise<boolean>;
@@ -74,11 +74,11 @@ async function replaceEscalationTargets(sourceRole, targets) {
74
74
  }
75
75
  /**
76
76
  * Check whether a user can escalate from sourceRole to targetRole.
77
- * Superadmins can escalate to any role.
77
+ * Superadmins and admin/admin can escalate to any role.
78
78
  * Others must hold the sourceRole AND the chain must exist.
79
79
  */
80
80
  async function canEscalateTo(userId, sourceRole, targetRole) {
81
- if (await (0, user_1.isSuperAdmin)(userId))
81
+ if (await (0, user_1.hasGlobalEscalationAccess)(userId))
82
82
  return true;
83
83
  if (!(await (0, user_1.hasRole)(userId, sourceRole)))
84
84
  return false;