@hotmeshio/long-tail 0.4.21 → 0.4.23

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 (231) hide show
  1. package/build/api/dba.d.ts +2 -1
  2. package/build/api/dba.js +3 -2
  3. package/build/api/escalations/claim.d.ts +2 -0
  4. package/build/api/escalations/claim.js +10 -6
  5. package/build/api/escalations/helpers.d.ts +24 -1
  6. package/build/api/escalations/helpers.js +48 -3
  7. package/build/api/escalations/metadata.d.ts +10 -2
  8. package/build/api/escalations/metadata.js +29 -6
  9. package/build/api/exports.d.ts +1 -0
  10. package/build/api/exports.js +1 -1
  11. package/build/api/maintenance.d.ts +1 -0
  12. package/build/api/maintenance.js +3 -3
  13. package/build/api/workflows/discovery.js +5 -2
  14. package/build/modules/auth.d.ts +1 -1
  15. package/build/modules/auth.js +3 -3
  16. package/build/modules/maintenance.js +1 -0
  17. package/build/routes/controlplane.js +40 -29
  18. package/build/routes/dba.js +13 -2
  19. package/build/routes/escalations/metadata.js +2 -1
  20. package/build/routes/escalations/single.js +1 -1
  21. package/build/routes/exports.js +6 -0
  22. package/build/routes/maintenance.js +1 -0
  23. package/build/sdk/index.d.ts +2 -0
  24. package/build/services/auth/bot-api-key.js +6 -24
  25. package/build/services/auth/service-token.js +6 -18
  26. package/build/services/auth/sql.d.ts +11 -0
  27. package/build/services/auth/sql.js +37 -0
  28. package/build/services/controlplane/index.js +7 -5
  29. package/build/services/dba.d.ts +3 -1
  30. package/build/services/dba.js +5 -4
  31. package/build/services/escalation/crud.d.ts +19 -3
  32. package/build/services/escalation/crud.js +32 -15
  33. package/build/services/escalation/sql.d.ts +9 -2
  34. package/build/services/escalation/sql.js +36 -14
  35. package/build/services/export/index.d.ts +2 -2
  36. package/build/services/export/index.js +16 -10
  37. package/build/services/maintenance/index.js +7 -4
  38. package/build/services/pipelines/queries.js +5 -2
  39. package/build/services/pipelines/sql.d.ts +0 -1
  40. package/build/services/pipelines/sql.js +1 -3
  41. package/build/system/mcp-servers/admin/controlplane.js +1 -1
  42. package/build/system/mcp-servers/admin/maintenance.js +1 -0
  43. package/build/system/mcp-servers/admin/pipelines.js +4 -4
  44. package/build/system/mcp-servers/admin/schemas.d.ts +31 -25
  45. package/build/system/mcp-servers/admin/schemas.js +9 -7
  46. package/build/system/seed/tool-manifests-admin.d.ts +59 -0
  47. package/build/system/seed/tool-manifests-admin.js +2 -2
  48. package/build/tsconfig.tsbuildinfo +1 -1
  49. package/build/types/maintenance.d.ts +2 -0
  50. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js → AdminDashboard-CgJC8ZZF.js} +2 -2
  51. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js.map → AdminDashboard-CgJC8ZZF.js.map} +1 -1
  52. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js → AgentConfigPage-Bjl2Lsvo.js} +2 -2
  53. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js.map → AgentConfigPage-Bjl2Lsvo.js.map} +1 -1
  54. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js → AgentDetailPage-D5dHrfaM.js} +2 -2
  55. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js.map → AgentDetailPage-D5dHrfaM.js.map} +1 -1
  56. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js → AgentsPage-Mom3N1Av.js} +2 -2
  57. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js.map → AgentsPage-Mom3N1Av.js.map} +1 -1
  58. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js → AvailableEscalationsPage-B2ZAb41C.js} +2 -2
  59. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js.map → AvailableEscalationsPage-B2ZAb41C.js.map} +1 -1
  60. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js → BotPicker-dCvnjynP.js} +2 -2
  61. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js.map → BotPicker-dCvnjynP.js.map} +1 -1
  62. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js → CapabilitiesPage-CK2fJ9Sy.js} +2 -2
  63. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js.map → CapabilitiesPage-CK2fJ9Sy.js.map} +1 -1
  64. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js → CollapsibleSection-bW0UZN9b.js} +2 -2
  65. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js.map → CollapsibleSection-bW0UZN9b.js.map} +1 -1
  66. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js → CredentialsPage-DVOK3aaR.js} +2 -2
  67. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js.map → CredentialsPage-DVOK3aaR.js.map} +1 -1
  68. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js → CronLabel-Cv5em7OP.js} +2 -2
  69. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js.map → CronLabel-Cv5em7OP.js.map} +1 -1
  70. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js → CustomDurationPicker-Dy4NBqhZ.js} +2 -2
  71. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js.map → CustomDurationPicker-Dy4NBqhZ.js.map} +1 -1
  72. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js → ElapsedCell-TQqWaVRq.js} +2 -2
  73. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js.map → ElapsedCell-TQqWaVRq.js.map} +1 -1
  74. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js → EscalationsOverview-Cv5UvuHI.js} +2 -2
  75. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js.map → EscalationsOverview-Cv5UvuHI.js.map} +1 -1
  76. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js → EventTable-Doky6fCO.js} +2 -2
  77. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js.map → EventTable-Doky6fCO.js.map} +1 -1
  78. package/dashboard/dist/assets/HomePage-CzvVyTq4.js +2 -0
  79. package/dashboard/dist/assets/HomePage-CzvVyTq4.js.map +1 -0
  80. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js → ListToolbar-Cfec9gz_.js} +2 -2
  81. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js.map → ListToolbar-Cfec9gz_.js.map} +1 -1
  82. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js +2 -0
  83. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js.map +1 -0
  84. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +5 -0
  85. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +1 -0
  86. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js → McpQueryPage-BK5L2PqJ.js} +2 -2
  87. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js.map → McpQueryPage-BK5L2PqJ.js.map} +1 -1
  88. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +2 -0
  89. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +1 -0
  90. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js +2 -0
  91. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js.map +1 -0
  92. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js → OperatorDashboard-CZQSINho.js} +2 -2
  93. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js.map → OperatorDashboard-CZQSINho.js.map} +1 -1
  94. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js → ProcessDetailPage-DUCOOvOK.js} +2 -2
  95. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js.map → ProcessDetailPage-DUCOOvOK.js.map} +1 -1
  96. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js → ProcessesListPage-CXvSLTIM.js} +2 -2
  97. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js.map → ProcessesListPage-CXvSLTIM.js.map} +1 -1
  98. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js +2 -0
  99. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js.map +1 -0
  100. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js → RunAsSelector-DP-jxsv6.js} +2 -2
  101. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js.map → RunAsSelector-DP-jxsv6.js.map} +1 -1
  102. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js → SwimlaneTimeline-BmASA0nN.js} +2 -2
  103. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js.map → SwimlaneTimeline-BmASA0nN.js.map} +1 -1
  104. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js → TaskDetailPage-CRowpkeZ.js} +2 -2
  105. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js.map → TaskDetailPage-CRowpkeZ.js.map} +1 -1
  106. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js → TasksListPage-uJ6z37J-.js} +2 -2
  107. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js.map → TasksListPage-uJ6z37J-.js.map} +1 -1
  108. package/dashboard/dist/assets/TimeAgo-BxwngK1D.js +2 -0
  109. package/dashboard/dist/assets/{TimeAgo-BSzN6rAH.js.map → TimeAgo-BxwngK1D.js.map} +1 -1
  110. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js → TimestampCell-CDmichOM.js} +2 -2
  111. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js.map → TimestampCell-CDmichOM.js.map} +1 -1
  112. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +2 -0
  113. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +1 -0
  114. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js → TopicDetailPage-Dm0hDlS8.js} +2 -2
  115. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js.map → TopicDetailPage-Dm0hDlS8.js.map} +1 -1
  116. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js → TopicsPage-letISGGD.js} +2 -2
  117. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js.map → TopicsPage-letISGGD.js.map} +1 -1
  118. package/dashboard/dist/assets/{UserName-BjHIJWgh.js → UserName-W6_Iz2Qb.js} +2 -2
  119. package/dashboard/dist/assets/{UserName-BjHIJWgh.js.map → UserName-W6_Iz2Qb.js.map} +1 -1
  120. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js → WorkflowExecutionPage-Cfx-xlRT.js} +2 -2
  121. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js.map → WorkflowExecutionPage-Cfx-xlRT.js.map} +1 -1
  122. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js +2 -0
  123. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js.map +1 -0
  124. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js → WorkflowsOverview-GefO_yn0.js} +2 -2
  125. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js.map → WorkflowsOverview-GefO_yn0.js.map} +1 -1
  126. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +2 -0
  127. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +1 -0
  128. package/dashboard/dist/assets/{agents-CkvQDr9b.js → agents-BI5OeN84.js} +2 -2
  129. package/dashboard/dist/assets/{agents-CkvQDr9b.js.map → agents-BI5OeN84.js.map} +1 -1
  130. package/dashboard/dist/assets/{bots-CzuMCVgU.js → bots-1UzUCsrR.js} +2 -2
  131. package/dashboard/dist/assets/{bots-CzuMCVgU.js.map → bots-1UzUCsrR.js.map} +1 -1
  132. package/dashboard/dist/assets/capabilities-BUbl-ojp.js +2 -0
  133. package/dashboard/dist/assets/{capabilities-CbGmS0ty.js.map → capabilities-BUbl-ojp.js.map} +1 -1
  134. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js → controlplane-DTFrH_vN.js} +2 -2
  135. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js.map → controlplane-DTFrH_vN.js.map} +1 -1
  136. package/dashboard/dist/assets/{escalation-B7ysVToF.js → escalation-BQhCt4W0.js} +2 -2
  137. package/dashboard/dist/assets/{escalation-B7ysVToF.js.map → escalation-BQhCt4W0.js.map} +1 -1
  138. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js → escalation-columns-J20k5CcY.js} +2 -2
  139. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js.map → escalation-columns-J20k5CcY.js.map} +1 -1
  140. package/dashboard/dist/assets/{helpers-BFOjXa4r.js → helpers-ge6Eu90Y.js} +2 -2
  141. package/dashboard/dist/assets/{helpers-BFOjXa4r.js.map → helpers-ge6Eu90Y.js.map} +1 -1
  142. package/dashboard/dist/assets/index-C-mbURj-.js +2 -0
  143. package/dashboard/dist/assets/index-C-mbURj-.js.map +1 -0
  144. package/dashboard/dist/assets/{index-BduDiGcw.js → index-C45DvtAZ.js} +2 -2
  145. package/dashboard/dist/assets/{index-BduDiGcw.js.map → index-C45DvtAZ.js.map} +1 -1
  146. package/dashboard/dist/assets/{index-B9_1AZaG.js → index-C9ClHiiW.js} +2 -2
  147. package/dashboard/dist/assets/{index-B9_1AZaG.js.map → index-C9ClHiiW.js.map} +1 -1
  148. package/dashboard/dist/assets/index-CLUYzdwz.js +2 -0
  149. package/dashboard/dist/assets/{index-DQHmfTPo.js.map → index-CLUYzdwz.js.map} +1 -1
  150. package/dashboard/dist/assets/{index-l_8R6U4r.js → index-CVGgSoda.js} +2 -2
  151. package/dashboard/dist/assets/{index-l_8R6U4r.js.map → index-CVGgSoda.js.map} +1 -1
  152. package/dashboard/dist/assets/{index-_BRA9uFL.js → index-CWEOhAiK.js} +3 -3
  153. package/dashboard/dist/assets/{index-_BRA9uFL.js.map → index-CWEOhAiK.js.map} +1 -1
  154. package/dashboard/dist/assets/{index-BFaDxPxA.js → index-CWlP6vHG.js} +2 -2
  155. package/dashboard/dist/assets/{index-BFaDxPxA.js.map → index-CWlP6vHG.js.map} +1 -1
  156. package/dashboard/dist/assets/index-DasoTRjT.js +2 -0
  157. package/dashboard/dist/assets/{index-BeLphL59.js.map → index-DasoTRjT.js.map} +1 -1
  158. package/dashboard/dist/assets/{index-CvOGgvzP.js → index-FhasoOjO.js} +2 -2
  159. package/dashboard/dist/assets/{index-CvOGgvzP.js.map → index-FhasoOjO.js.map} +1 -1
  160. package/dashboard/dist/assets/{index-a98qWLB-.js → index-WQQJ_cp7.js} +2 -2
  161. package/dashboard/dist/assets/{index-a98qWLB-.js.map → index-WQQJ_cp7.js.map} +1 -1
  162. package/dashboard/dist/assets/{index-CbrMW-gM.js → index-hAZiac0C.js} +2 -2
  163. package/dashboard/dist/assets/{index-CbrMW-gM.js.map → index-hAZiac0C.js.map} +1 -1
  164. package/dashboard/dist/assets/{index-v0OQpgXS.js → index-si70YcIP.js} +2 -2
  165. package/dashboard/dist/assets/{index-v0OQpgXS.js.map → index-si70YcIP.js.map} +1 -1
  166. package/dashboard/dist/assets/{index-CRiBkHPb.js → index-vgxjge70.js} +2 -2
  167. package/dashboard/dist/assets/{index-CRiBkHPb.js.map → index-vgxjge70.js.map} +1 -1
  168. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js → knowledge-D9Tuh-o-.js} +2 -2
  169. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js.map → knowledge-D9Tuh-o-.js.map} +1 -1
  170. package/dashboard/dist/assets/{mcp-MtXuky8q.js → mcp-BO8QnWyk.js} +2 -2
  171. package/dashboard/dist/assets/{mcp-MtXuky8q.js.map → mcp-BO8QnWyk.js.map} +1 -1
  172. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js → mcp-query-WLtQtr51.js} +2 -2
  173. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js.map → mcp-query-WLtQtr51.js.map} +1 -1
  174. package/dashboard/dist/assets/pipelines-BAVf9xud.js +2 -0
  175. package/dashboard/dist/assets/pipelines-BAVf9xud.js.map +1 -0
  176. package/dashboard/dist/assets/{roles-D-LhJ82d.js → roles-mGO2-2hA.js} +2 -2
  177. package/dashboard/dist/assets/{roles-D-LhJ82d.js.map → roles-mGO2-2hA.js.map} +1 -1
  178. package/dashboard/dist/assets/{tasks-BrP_8uEN.js → tasks-JVRVCx0f.js} +2 -2
  179. package/dashboard/dist/assets/{tasks-BrP_8uEN.js.map → tasks-JVRVCx0f.js.map} +1 -1
  180. package/dashboard/dist/assets/{topics-DUk-zX5D.js → topics-BLVnahd7.js} +2 -2
  181. package/dashboard/dist/assets/{topics-DUk-zX5D.js.map → topics-BLVnahd7.js.map} +1 -1
  182. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js → useEventHooks-BwjAi0Qq.js} +2 -2
  183. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js.map → useEventHooks-BwjAi0Qq.js.map} +1 -1
  184. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js +2 -0
  185. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js.map +1 -0
  186. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js → useYamlActivityEvents-CsaR5dWj.js} +2 -2
  187. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js.map → useYamlActivityEvents-CsaR5dWj.js.map} +1 -1
  188. package/dashboard/dist/assets/{users-vj0JgOkA.js → users-BvizpAkV.js} +2 -2
  189. package/dashboard/dist/assets/{users-vj0JgOkA.js.map → users-BvizpAkV.js.map} +1 -1
  190. package/dashboard/dist/assets/{workflows-CmqgGPzI.js → workflows-CyEYa01a.js} +2 -2
  191. package/dashboard/dist/assets/{workflows-CmqgGPzI.js.map → workflows-CyEYa01a.js.map} +1 -1
  192. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js → yaml-workflows-i3GzrEme.js} +2 -2
  193. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js.map → yaml-workflows-i3GzrEme.js.map} +1 -1
  194. package/dashboard/dist/index.html +1 -1
  195. package/docs/api/http/controlplane.md +6 -4
  196. package/docs/api/http/dba.md +1 -0
  197. package/docs/api/http/escalations.md +38 -2
  198. package/docs/api/http/exports.md +26 -0
  199. package/docs/api/http/maintenance.md +1 -0
  200. package/docs/api/mcp/admin.md +7 -7
  201. package/docs/api/sdk/controlplane.md +4 -4
  202. package/docs/api/sdk/escalations.md +25 -5
  203. package/package.json +1 -1
  204. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +0 -2
  205. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +0 -1
  206. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js +0 -2
  207. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js.map +0 -1
  208. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js +0 -5
  209. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js.map +0 -1
  210. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +0 -2
  211. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +0 -1
  212. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +0 -2
  213. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js.map +0 -1
  214. package/dashboard/dist/assets/RolesPage-pMERxj15.js +0 -2
  215. package/dashboard/dist/assets/RolesPage-pMERxj15.js.map +0 -1
  216. package/dashboard/dist/assets/TimeAgo-BSzN6rAH.js +0 -2
  217. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js +0 -2
  218. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js.map +0 -1
  219. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +0 -2
  220. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +0 -1
  221. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js +0 -2
  222. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js.map +0 -1
  223. package/dashboard/dist/assets/capabilities-CbGmS0ty.js +0 -2
  224. package/dashboard/dist/assets/index-BeLphL59.js +0 -2
  225. package/dashboard/dist/assets/index-DDlrQeTj.js +0 -2
  226. package/dashboard/dist/assets/index-DDlrQeTj.js.map +0 -1
  227. package/dashboard/dist/assets/index-DQHmfTPo.js +0 -2
  228. package/dashboard/dist/assets/namespaces-DtsT_GoV.js +0 -2
  229. package/dashboard/dist/assets/namespaces-DtsT_GoV.js.map +0 -1
  230. package/dashboard/dist/assets/pipelines-BjlCm9VH.js +0 -2
  231. package/dashboard/dist/assets/pipelines-BjlCm9VH.js.map +0 -1
@@ -43,26 +43,8 @@ exports.listBotApiKeys = listBotApiKeys;
43
43
  const crypto = __importStar(require("crypto"));
44
44
  const bcryptjs_1 = __importDefault(require("bcryptjs"));
45
45
  const db_1 = require("../../lib/db");
46
+ const sql_1 = require("./sql");
46
47
  const TOKEN_PREFIX = 'lt_bot_';
47
- const INSERT_KEY = `
48
- INSERT INTO lt_bot_api_keys (name, user_id, key_hash, scopes, expires_at)
49
- VALUES ($1, $2, $3, $4, $5) RETURNING id`;
50
- const GET_KEYS_BY_USER = `
51
- SELECT id, name, user_id, key_hash, scopes
52
- FROM lt_bot_api_keys
53
- WHERE user_id = $1
54
- AND (expires_at IS NULL OR expires_at > NOW())`;
55
- const GET_ALL_ACTIVE_KEYS = `
56
- SELECT id, name, user_id, key_hash, scopes
57
- FROM lt_bot_api_keys
58
- WHERE (expires_at IS NULL OR expires_at > NOW())`;
59
- const UPDATE_LAST_USED = `
60
- UPDATE lt_bot_api_keys SET last_used_at = NOW() WHERE id = $1`;
61
- const DELETE_KEY = `
62
- DELETE FROM lt_bot_api_keys WHERE id = $1`;
63
- const LIST_BY_USER = `
64
- SELECT id, name, user_id, scopes, expires_at, last_used_at, created_at, updated_at
65
- FROM lt_bot_api_keys WHERE user_id = $1 ORDER BY created_at`;
66
48
  /**
67
49
  * Generate a new API key for a bot account.
68
50
  * Returns the raw key once — it is never stored in plaintext.
@@ -71,7 +53,7 @@ async function generateBotApiKey(name, userId, scopes = [], expiresAt) {
71
53
  const rawKey = `${TOKEN_PREFIX}${crypto.randomBytes(32).toString('hex')}`;
72
54
  const keyHash = await bcryptjs_1.default.hash(rawKey, 10);
73
55
  const pool = await (0, db_1.getPool)();
74
- const { rows } = await pool.query(INSERT_KEY, [
56
+ const { rows } = await pool.query(sql_1.INSERT_BOT_KEY, [
75
57
  name, userId, keyHash, scopes, expiresAt || null,
76
58
  ]);
77
59
  return { id: rows[0].id, rawKey };
@@ -84,10 +66,10 @@ async function validateBotApiKey(rawKey) {
84
66
  if (!rawKey.startsWith(TOKEN_PREFIX))
85
67
  return null;
86
68
  const pool = await (0, db_1.getPool)();
87
- const { rows } = await pool.query(GET_ALL_ACTIVE_KEYS);
69
+ const { rows } = await pool.query(sql_1.GET_ALL_ACTIVE_BOT_KEYS);
88
70
  for (const row of rows) {
89
71
  if (await bcryptjs_1.default.compare(rawKey, row.key_hash)) {
90
- await pool.query(UPDATE_LAST_USED, [row.id]);
72
+ await pool.query(sql_1.UPDATE_BOT_KEY_LAST_USED, [row.id]);
91
73
  const { key_hash, ...record } = row;
92
74
  return record;
93
75
  }
@@ -99,7 +81,7 @@ async function validateBotApiKey(rawKey) {
99
81
  */
100
82
  async function revokeBotApiKey(id) {
101
83
  const pool = await (0, db_1.getPool)();
102
- const result = await pool.query(DELETE_KEY, [id]);
84
+ const result = await pool.query(sql_1.DELETE_BOT_KEY, [id]);
103
85
  return (result.rowCount ?? 0) > 0;
104
86
  }
105
87
  /**
@@ -107,6 +89,6 @@ async function revokeBotApiKey(id) {
107
89
  */
108
90
  async function listBotApiKeys(userId) {
109
91
  const pool = await (0, db_1.getPool)();
110
- const { rows } = await pool.query(LIST_BY_USER, [userId]);
92
+ const { rows } = await pool.query(sql_1.LIST_BOT_KEYS_BY_USER, [userId]);
111
93
  return rows;
112
94
  }
@@ -43,20 +43,8 @@ exports.listServiceTokens = listServiceTokens;
43
43
  const crypto = __importStar(require("crypto"));
44
44
  const bcryptjs_1 = __importDefault(require("bcryptjs"));
45
45
  const db_1 = require("../../lib/db");
46
+ const sql_1 = require("./sql");
46
47
  const TOKEN_PREFIX = 'lt_svc_';
47
- const INSERT_TOKEN = `
48
- INSERT INTO lt_service_tokens (name, token_hash, server_id, scopes, expires_at)
49
- VALUES ($1, $2, $3, $4, $5) RETURNING id`;
50
- const GET_ALL_TOKENS = `
51
- SELECT id, name, token_hash FROM lt_service_tokens
52
- WHERE (expires_at IS NULL OR expires_at > NOW())`;
53
- const UPDATE_LAST_USED = `
54
- UPDATE lt_service_tokens SET last_used_at = NOW() WHERE id = $1`;
55
- const DELETE_TOKEN = `
56
- DELETE FROM lt_service_tokens WHERE id = $1`;
57
- const LIST_BY_SERVER = `
58
- SELECT id, name, server_id, scopes, expires_at, last_used_at, created_at, updated_at
59
- FROM lt_service_tokens WHERE server_id = $1 ORDER BY created_at`;
60
48
  /**
61
49
  * Generate a new service token for an external MCP server.
62
50
  * Returns the raw token once — it is never stored in plaintext.
@@ -65,7 +53,7 @@ async function generateServiceToken(name, serverId, scopes, expiresAt) {
65
53
  const rawToken = `${TOKEN_PREFIX}${crypto.randomBytes(32).toString('hex')}`;
66
54
  const tokenHash = await bcryptjs_1.default.hash(rawToken, 10);
67
55
  const pool = await (0, db_1.getPool)();
68
- const { rows } = await pool.query(INSERT_TOKEN, [
56
+ const { rows } = await pool.query(sql_1.INSERT_SERVICE_TOKEN, [
69
57
  name, tokenHash, serverId, scopes, expiresAt || null,
70
58
  ]);
71
59
  return { id: rows[0].id, rawToken };
@@ -77,10 +65,10 @@ async function validateServiceToken(rawToken) {
77
65
  if (!rawToken.startsWith(TOKEN_PREFIX))
78
66
  return null;
79
67
  const pool = await (0, db_1.getPool)();
80
- const { rows } = await pool.query(GET_ALL_TOKENS);
68
+ const { rows } = await pool.query(sql_1.GET_ALL_ACTIVE_SERVICE_TOKENS);
81
69
  for (const row of rows) {
82
70
  if (await bcryptjs_1.default.compare(rawToken, row.token_hash)) {
83
- await pool.query(UPDATE_LAST_USED, [row.id]);
71
+ await pool.query(sql_1.UPDATE_SERVICE_TOKEN_LAST_USED, [row.id]);
84
72
  const { token_hash, ...record } = row;
85
73
  return record;
86
74
  }
@@ -92,7 +80,7 @@ async function validateServiceToken(rawToken) {
92
80
  */
93
81
  async function revokeServiceToken(id) {
94
82
  const pool = await (0, db_1.getPool)();
95
- const result = await pool.query(DELETE_TOKEN, [id]);
83
+ const result = await pool.query(sql_1.DELETE_SERVICE_TOKEN, [id]);
96
84
  return (result.rowCount ?? 0) > 0;
97
85
  }
98
86
  /**
@@ -100,6 +88,6 @@ async function revokeServiceToken(id) {
100
88
  */
101
89
  async function listServiceTokens(serverId) {
102
90
  const pool = await (0, db_1.getPool)();
103
- const { rows } = await pool.query(LIST_BY_SERVER, [serverId]);
91
+ const { rows } = await pool.query(sql_1.LIST_SERVICE_TOKENS_BY_SERVER, [serverId]);
104
92
  return rows;
105
93
  }
@@ -0,0 +1,11 @@
1
+ export declare const INSERT_BOT_KEY = "\n INSERT INTO lt_bot_api_keys (name, user_id, key_hash, scopes, expires_at)\n VALUES ($1, $2, $3, $4, $5) RETURNING id";
2
+ export declare const GET_BOT_KEYS_BY_USER = "\n SELECT id, name, user_id, key_hash, scopes\n FROM lt_bot_api_keys\n WHERE user_id = $1\n AND (expires_at IS NULL OR expires_at > NOW())";
3
+ export declare const GET_ALL_ACTIVE_BOT_KEYS = "\n SELECT id, name, user_id, key_hash, scopes\n FROM lt_bot_api_keys\n WHERE (expires_at IS NULL OR expires_at > NOW())";
4
+ export declare const UPDATE_BOT_KEY_LAST_USED = "\n UPDATE lt_bot_api_keys SET last_used_at = NOW() WHERE id = $1";
5
+ export declare const DELETE_BOT_KEY = "\n DELETE FROM lt_bot_api_keys WHERE id = $1";
6
+ export declare const LIST_BOT_KEYS_BY_USER = "\n SELECT id, name, user_id, scopes, expires_at, last_used_at, created_at, updated_at\n FROM lt_bot_api_keys WHERE user_id = $1 ORDER BY created_at";
7
+ export declare const INSERT_SERVICE_TOKEN = "\n INSERT INTO lt_service_tokens (name, token_hash, server_id, scopes, expires_at)\n VALUES ($1, $2, $3, $4, $5) RETURNING id";
8
+ export declare const GET_ALL_ACTIVE_SERVICE_TOKENS = "\n SELECT id, name, token_hash FROM lt_service_tokens\n WHERE (expires_at IS NULL OR expires_at > NOW())";
9
+ export declare const UPDATE_SERVICE_TOKEN_LAST_USED = "\n UPDATE lt_service_tokens SET last_used_at = NOW() WHERE id = $1";
10
+ export declare const DELETE_SERVICE_TOKEN = "\n DELETE FROM lt_service_tokens WHERE id = $1";
11
+ export declare const LIST_SERVICE_TOKENS_BY_SERVER = "\n SELECT id, name, server_id, scopes, expires_at, last_used_at, created_at, updated_at\n FROM lt_service_tokens WHERE server_id = $1 ORDER BY created_at";
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // ── Bot API key queries ─────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.LIST_SERVICE_TOKENS_BY_SERVER = exports.DELETE_SERVICE_TOKEN = exports.UPDATE_SERVICE_TOKEN_LAST_USED = exports.GET_ALL_ACTIVE_SERVICE_TOKENS = exports.INSERT_SERVICE_TOKEN = exports.LIST_BOT_KEYS_BY_USER = exports.DELETE_BOT_KEY = exports.UPDATE_BOT_KEY_LAST_USED = exports.GET_ALL_ACTIVE_BOT_KEYS = exports.GET_BOT_KEYS_BY_USER = exports.INSERT_BOT_KEY = void 0;
5
+ exports.INSERT_BOT_KEY = `
6
+ INSERT INTO lt_bot_api_keys (name, user_id, key_hash, scopes, expires_at)
7
+ VALUES ($1, $2, $3, $4, $5) RETURNING id`;
8
+ exports.GET_BOT_KEYS_BY_USER = `
9
+ SELECT id, name, user_id, key_hash, scopes
10
+ FROM lt_bot_api_keys
11
+ WHERE user_id = $1
12
+ AND (expires_at IS NULL OR expires_at > NOW())`;
13
+ exports.GET_ALL_ACTIVE_BOT_KEYS = `
14
+ SELECT id, name, user_id, key_hash, scopes
15
+ FROM lt_bot_api_keys
16
+ WHERE (expires_at IS NULL OR expires_at > NOW())`;
17
+ exports.UPDATE_BOT_KEY_LAST_USED = `
18
+ UPDATE lt_bot_api_keys SET last_used_at = NOW() WHERE id = $1`;
19
+ exports.DELETE_BOT_KEY = `
20
+ DELETE FROM lt_bot_api_keys WHERE id = $1`;
21
+ exports.LIST_BOT_KEYS_BY_USER = `
22
+ SELECT id, name, user_id, scopes, expires_at, last_used_at, created_at, updated_at
23
+ FROM lt_bot_api_keys WHERE user_id = $1 ORDER BY created_at`;
24
+ // ── Service token queries ───────────────────────────────────────────────────
25
+ exports.INSERT_SERVICE_TOKEN = `
26
+ INSERT INTO lt_service_tokens (name, token_hash, server_id, scopes, expires_at)
27
+ VALUES ($1, $2, $3, $4, $5) RETURNING id`;
28
+ exports.GET_ALL_ACTIVE_SERVICE_TOKENS = `
29
+ SELECT id, name, token_hash FROM lt_service_tokens
30
+ WHERE (expires_at IS NULL OR expires_at > NOW())`;
31
+ exports.UPDATE_SERVICE_TOKEN_LAST_USED = `
32
+ UPDATE lt_service_tokens SET last_used_at = NOW() WHERE id = $1`;
33
+ exports.DELETE_SERVICE_TOKEN = `
34
+ DELETE FROM lt_service_tokens WHERE id = $1`;
35
+ exports.LIST_SERVICE_TOKENS_BY_SERVER = `
36
+ SELECT id, name, server_id, scopes, expires_at, last_used_at, created_at, updated_at
37
+ FROM lt_service_tokens WHERE server_id = $1 ORDER BY created_at`;
@@ -91,10 +91,12 @@ async function getStreamStats(schema, duration = '1h', streamName) {
91
91
  throw new Error(`Invalid duration: ${duration}`);
92
92
  const pool = (0, db_1.getPool)();
93
93
  const stream = streamName || null;
94
+ // Graceful degradation: HotMesh schema may not exist if no engine has started.
95
+ const emptyCount = { rows: [{ count: 0 }] };
94
96
  const [pendingRes, processedRes, byStreamRes] = await Promise.all([
95
- pool.query((0, sql_1.COUNT_PENDING)(schema), [stream]),
96
- pool.query((0, sql_1.COUNT_PROCESSED_SINCE)(schema), [interval, stream]),
97
- pool.query((0, sql_1.VOLUME_BY_STREAM)(schema), [interval, stream]),
97
+ pool.query((0, sql_1.COUNT_PENDING)(schema), [stream]).catch(() => emptyCount),
98
+ pool.query((0, sql_1.COUNT_PROCESSED_SINCE)(schema), [interval, stream]).catch(() => emptyCount),
99
+ pool.query((0, sql_1.VOLUME_BY_STREAM)(schema), [interval, stream]).catch(() => ({ rows: [] })),
98
100
  ]);
99
101
  return {
100
102
  pending: pendingRes.rows[0]?.count ?? 0,
@@ -131,8 +133,8 @@ async function getStreamMessages(schema, params) {
131
133
  const queryParams = [streamName, status, msgType, topic, workflowName, jid, aid, limit, offset];
132
134
  const countParams = [streamName, status, msgType, topic, workflowName, jid, aid];
133
135
  const [messagesRes, countRes] = await Promise.all([
134
- pool.query((0, stream_messages_sql_1.LIST_STREAM_MESSAGES)(schema, sortColumn, sortOrder, source), queryParams),
135
- pool.query((0, stream_messages_sql_1.COUNT_STREAM_MESSAGES)(schema, source), countParams),
136
+ pool.query((0, stream_messages_sql_1.LIST_STREAM_MESSAGES)(schema, sortColumn, sortOrder, source), queryParams).catch(() => ({ rows: [] })),
137
+ pool.query((0, stream_messages_sql_1.COUNT_STREAM_MESSAGES)(schema, source), countParams).catch(() => ({ rows: [{ count: 0 }] })),
136
138
  ]);
137
139
  return {
138
140
  messages: messagesRes.rows,
@@ -4,10 +4,11 @@ import type { PruneOptions, PruneResult } from '@hotmeshio/hotmesh/build/types/d
4
4
  * any schema migrations (e.g. adding the `pruned_at` column).
5
5
  * Idempotent — safe to call on every startup.
6
6
  */
7
- export declare function deploy(): Promise<void>;
7
+ export declare function deploy(appId: string): Promise<void>;
8
8
  /**
9
9
  * Prune expired jobs, streams, and/or execution artifacts.
10
10
  *
11
+ * - `appId` — HotMesh application namespace (required)
11
12
  * - `jobs` — hard-delete expired job rows older than `expire`
12
13
  * - `streams` — hard-delete expired stream messages (engine + worker) older than `expire`
13
14
  * - `attributes` — strip execution artifacts from completed jobs
@@ -17,6 +18,7 @@ export declare function deploy(): Promise<void>;
17
18
  * - `keepHmark` — preserve hmark rows during stripping
18
19
  */
19
20
  export declare function prune(options: {
21
+ appId: string;
20
22
  expire?: string;
21
23
  jobs?: boolean;
22
24
  streams?: boolean;
@@ -4,18 +4,18 @@ exports.deploy = deploy;
4
4
  exports.prune = prune;
5
5
  const hotmesh_1 = require("@hotmeshio/hotmesh");
6
6
  const db_1 = require("../lib/db");
7
- const APP_ID = 'durable';
8
7
  /**
9
8
  * Deploy the server-side prune() Postgres function and run
10
9
  * any schema migrations (e.g. adding the `pruned_at` column).
11
10
  * Idempotent — safe to call on every startup.
12
11
  */
13
- async function deploy() {
14
- await hotmesh_1.DBA.deploy((0, db_1.getConnection)(), APP_ID);
12
+ async function deploy(appId) {
13
+ await hotmesh_1.DBA.deploy((0, db_1.getConnection)(), appId);
15
14
  }
16
15
  /**
17
16
  * Prune expired jobs, streams, and/or execution artifacts.
18
17
  *
18
+ * - `appId` — HotMesh application namespace (required)
19
19
  * - `jobs` — hard-delete expired job rows older than `expire`
20
20
  * - `streams` — hard-delete expired stream messages (engine + worker) older than `expire`
21
21
  * - `attributes` — strip execution artifacts from completed jobs
@@ -25,5 +25,6 @@ async function deploy() {
25
25
  * - `keepHmark` — preserve hmark rows during stripping
26
26
  */
27
27
  async function prune(options) {
28
- return hotmesh_1.DBA.prune({ appId: APP_ID, connection: (0, db_1.getConnection)(), ...options });
28
+ const { appId, ...rest } = options;
29
+ return hotmesh_1.DBA.prune({ appId, connection: (0, db_1.getConnection)(), ...rest });
29
30
  }
@@ -61,8 +61,24 @@ export declare function findByMetadata(key: string, value: string, status?: stri
61
61
  export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>, allowedRoles?: string[] | null): Promise<(ClaimResult & {
62
62
  candidatesExist: number;
63
63
  }) | null>;
64
+ export interface ResolveByMetadataResult {
65
+ /** 'resolved' = done atomically. 'signal_required' = signal_id present, caller must signal. */
66
+ outcome: 'resolved' | 'signal_required' | 'not_found';
67
+ /** The resolved escalation (when outcome = 'resolved') */
68
+ escalation?: LTEscalationRecord;
69
+ /** Signal info (when outcome = 'signal_required') */
70
+ signalId?: string;
71
+ escalationId?: string;
72
+ workflowId?: string;
73
+ workflowType?: string;
74
+ taskQueue?: string;
75
+ }
64
76
  /**
65
- * Atomic resolve by metadata: find + claim + resolve in one CTE.
66
- * RBAC is enforced in the SQL WHERE clause via allowedRoles.
77
+ * Atomic resolve by metadata with signal guard.
78
+ *
79
+ * Single query, two outcomes:
80
+ * 1. No signal_id → claim + resolve atomically. Returns { outcome: 'resolved', escalation }.
81
+ * 2. signal_id present → resolve skipped. Returns { outcome: 'signal_required', signalId, escalationId, ... }
82
+ * so the caller can signal the workflow. conditionLT handles the rest.
67
83
  */
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>;
84
+ export declare function resolveByMetadataAtomic(key: string, value: string, userId: string, resolverPayload: Record<string, any>, metadata?: Record<string, any>, allowedRoles?: string[] | null): Promise<ResolveByMetadataResult>;
@@ -249,8 +249,12 @@ async function claimByMetadata(key, value, userId, durationMinutes = 30, metadat
249
249
  };
250
250
  }
251
251
  /**
252
- * Atomic resolve by metadata: find + claim + resolve in one CTE.
253
- * RBAC is enforced in the SQL WHERE clause via allowedRoles.
252
+ * Atomic resolve by metadata with signal guard.
253
+ *
254
+ * Single query, two outcomes:
255
+ * 1. No signal_id → claim + resolve atomically. Returns { outcome: 'resolved', escalation }.
256
+ * 2. signal_id present → resolve skipped. Returns { outcome: 'signal_required', signalId, escalationId, ... }
257
+ * so the caller can signal the workflow. conditionLT handles the rest.
254
258
  */
255
259
  async function resolveByMetadataAtomic(key, value, userId, resolverPayload, metadata, allowedRoles) {
256
260
  const pool = (0, db_1.getPool)();
@@ -260,17 +264,30 @@ async function resolveByMetadataAtomic(key, value, userId, resolverPayload, meta
260
264
  const roles = allowedRoles ?? null;
261
265
  const { rows } = await pool.query(sql_1.RESOLVE_BY_METADATA_ATOMIC, [filter, userId, payloadJson, metaPatch, roles]);
262
266
  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;
267
+ return { outcome: 'not_found' };
268
+ const row = rows[0];
269
+ if (row.outcome === 'resolved') {
270
+ const { target_id, signal_id, target_workflow_id, target_workflow_type, target_task_queue, outcome, ...rest } = row;
271
+ const escalation = rest;
272
+ (0, publish_1.publishEscalationEvent)({
273
+ type: 'escalation.resolved',
274
+ source: 'service',
275
+ workflowId: escalation.workflow_id || '',
276
+ workflowName: escalation.workflow_type || '',
277
+ taskQueue: escalation.task_queue || '',
278
+ escalationId: escalation.id,
279
+ status: 'resolved',
280
+ data: { resolved_by: userId },
281
+ });
282
+ return { outcome: 'resolved', escalation };
283
+ }
284
+ // Signal-backed escalation — return the signal info for the caller
285
+ return {
286
+ outcome: 'signal_required',
287
+ signalId: row.signal_id,
288
+ escalationId: row.target_id,
289
+ workflowId: row.target_workflow_id,
290
+ workflowType: row.target_workflow_type,
291
+ taskQueue: row.target_task_queue,
292
+ };
276
293
  }
@@ -28,8 +28,15 @@ export declare const FIND_BY_METADATA = "SELECT *, COUNT(*) OVER() AS _total\nFR
28
28
  */
29
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
30
  /**
31
- * Atomic resolve by metadata: find + claim + resolve in one CTE.
31
+ * Atomic resolve by metadata with signal guard.
32
+ *
33
+ * Single query, two outcomes:
34
+ * 1. No signal_id → claim + resolve atomically. `resolved` is populated.
35
+ * 2. signal_id present → resolve CTE skips (guard in WHERE). `resolved` is null,
36
+ * but `target_id`, `signal_id`, `workflow_id`, `task_queue`, `workflow_type`
37
+ * are returned so the caller can signal the workflow directly.
38
+ *
32
39
  * $1 = metadata filter (jsonb), $2 = userId, $3 = resolver_payload (jsonb),
33
40
  * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
34
41
  */
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.*";
42
+ export declare const RESOLVE_BY_METADATA_ATOMIC = "WITH target AS (\n SELECT *\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\n),\nclaimed AS (\n UPDATE lt_escalations e\n SET assigned_to = COALESCE(e.assigned_to, $2),\n claimed_at = COALESCE(e.claimed_at, NOW()),\n assigned_until = CASE\n WHEN e.assigned_to IS NOT NULL AND e.assigned_until > NOW() THEN e.assigned_until\n ELSE NOW() + INTERVAL '5 minutes' END,\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 AND (target.metadata->>'signal_id') IS NULL\n RETURNING e.*\n),\nresolved AS (\n UPDATE lt_escalations e\n SET status = 'resolved',\n resolved_at = NOW(),\n resolver_payload = $3,\n updated_at = NOW()\n FROM claimed\n WHERE e.id = claimed.id\n RETURNING e.*\n)\nSELECT\n resolved.*,\n target.id AS target_id,\n target.metadata->>'signal_id' AS signal_id,\n target.workflow_id AS target_workflow_id,\n target.workflow_type AS target_workflow_type,\n target.task_queue AS target_task_queue,\n CASE WHEN resolved.id IS NOT NULL THEN 'resolved' ELSE 'signal_required' END AS outcome\nFROM target\nLEFT JOIN resolved ON resolved.id = target.id";
@@ -176,38 +176,60 @@ SELECT *,
176
176
  (SELECT COUNT(*) FROM lt_escalations WHERE metadata @> $1::jsonb AND status = 'pending') AS candidates_exist
177
177
  FROM updated`;
178
178
  /**
179
- * Atomic resolve by metadata: find + claim + resolve in one CTE.
179
+ * Atomic resolve by metadata with signal guard.
180
+ *
181
+ * Single query, two outcomes:
182
+ * 1. No signal_id → claim + resolve atomically. `resolved` is populated.
183
+ * 2. signal_id present → resolve CTE skips (guard in WHERE). `resolved` is null,
184
+ * but `target_id`, `signal_id`, `workflow_id`, `task_queue`, `workflow_type`
185
+ * are returned so the caller can signal the workflow directly.
186
+ *
180
187
  * $1 = metadata filter (jsonb), $2 = userId, $3 = resolver_payload (jsonb),
181
188
  * $4 = metadata patch (jsonb, nullable), $5 = allowed roles (text[], null = no filter)
182
189
  */
183
190
  exports.RESOLVE_BY_METADATA_ATOMIC = `\
184
191
  WITH target AS (
185
- SELECT id
192
+ SELECT *
186
193
  FROM lt_escalations
187
194
  WHERE metadata @> $1::jsonb
188
195
  AND status = 'pending'
189
196
  AND ($5::text[] IS NULL OR role = ANY($5))
190
197
  ORDER BY priority ASC, created_at ASC
191
198
  LIMIT 1
192
- FOR UPDATE SKIP LOCKED
199
+ FOR UPDATE
193
200
  ),
194
201
  claimed AS (
195
202
  UPDATE lt_escalations e
196
- SET assigned_to = $2,
197
- claimed_at = NOW(),
198
- assigned_until = NOW() + INTERVAL '5 minutes',
203
+ SET assigned_to = COALESCE(e.assigned_to, $2),
204
+ claimed_at = COALESCE(e.claimed_at, NOW()),
205
+ assigned_until = CASE
206
+ WHEN e.assigned_to IS NOT NULL AND e.assigned_until > NOW() THEN e.assigned_until
207
+ ELSE NOW() + INTERVAL '5 minutes' END,
199
208
  metadata = CASE WHEN $4::jsonb IS NOT NULL
200
209
  THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb
201
210
  ELSE e.metadata END
202
211
  FROM target
203
212
  WHERE e.id = target.id
213
+ AND (target.metadata->>'signal_id') IS NULL
214
+ RETURNING e.*
215
+ ),
216
+ resolved AS (
217
+ UPDATE lt_escalations e
218
+ SET status = 'resolved',
219
+ resolved_at = NOW(),
220
+ resolver_payload = $3,
221
+ updated_at = NOW()
222
+ FROM claimed
223
+ WHERE e.id = claimed.id
204
224
  RETURNING e.*
205
225
  )
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.*`;
226
+ SELECT
227
+ resolved.*,
228
+ target.id AS target_id,
229
+ target.metadata->>'signal_id' AS signal_id,
230
+ target.workflow_id AS target_workflow_id,
231
+ target.workflow_type AS target_workflow_type,
232
+ target.task_queue AS target_task_queue,
233
+ CASE WHEN resolved.id IS NOT NULL THEN 'resolved' ELSE 'signal_required' END AS outcome
234
+ FROM target
235
+ LEFT JOIN resolved ON resolved.id = target.id`;
@@ -33,7 +33,7 @@ export declare function getWorkflowState(workflowId: string, taskQueue: string,
33
33
  state: Record<string, any>;
34
34
  }>;
35
35
  /**
36
- * List workflow jobs from durable.jobs where entity IS NOT NULL.
36
+ * List workflow jobs from {schema}.jobs where entity IS NOT NULL.
37
37
  * Returns paginated results sorted by active first, then created_at DESC.
38
38
  */
39
- export declare function listJobs(params: JobListParams): Promise<JobListResult>;
39
+ export declare function listJobs(app_id: string, params: JobListParams): Promise<JobListResult>;
@@ -6,6 +6,7 @@ exports.exportWorkflowExecution = exportWorkflowExecution;
6
6
  exports.getWorkflowState = getWorkflowState;
7
7
  exports.listJobs = listJobs;
8
8
  const db_1 = require("../../lib/db");
9
+ const hotmesh_utils_1 = require("../hotmesh-utils");
9
10
  const client_1 = require("./client");
10
11
  const post_process_1 = require("./post-process");
11
12
  /** Error thrown when a workflow job is not found (expired or never existed). */
@@ -131,10 +132,13 @@ function buildJobOrderBy(sortBy, order) {
131
132
  return `j.${sortBy} ${dir}`;
132
133
  }
133
134
  /**
134
- * List workflow jobs from durable.jobs where entity IS NOT NULL.
135
+ * List workflow jobs from {schema}.jobs where entity IS NOT NULL.
135
136
  * Returns paginated results sorted by active first, then created_at DESC.
136
137
  */
137
- async function listJobs(params) {
138
+ async function listJobs(app_id, params) {
139
+ const appId = (0, hotmesh_utils_1.sanitizeAppId)(app_id);
140
+ const schema = (0, hotmesh_utils_1.quoteSchema)(appId);
141
+ const keyPrefix = `hmsh:${appId}:j:`;
138
142
  const limit = Math.min(params.limit ?? 20, 100);
139
143
  const offset = params.offset ?? 0;
140
144
  const pool = (0, db_1.getPool)();
@@ -172,11 +176,13 @@ async function listJobs(params) {
172
176
  conditions.push('j.status < 0');
173
177
  }
174
178
  const where = conditions.join(' AND ');
179
+ // Graceful degradation: schema may not exist if no engine has started.
180
+ const emptyCount = { rows: [{ count: '0' }] };
175
181
  const [countResult, dataResult] = await Promise.all([
176
- pool.query(`SELECT COUNT(*) FROM durable.jobs j WHERE ${where}`, values),
182
+ pool.query(`SELECT COUNT(*) FROM ${schema}.jobs j WHERE ${where}`, values).catch(() => emptyCount),
177
183
  pool.query(`WITH ju_symbols AS (
178
- SELECT value FROM durable.symbols
179
- WHERE key LIKE 'hmsh:durable:sym:keys:%' AND field = 'metadata/ju'
184
+ SELECT value FROM ${schema}.symbols
185
+ WHERE key LIKE 'hmsh:${appId}:sym:keys:%' AND field = 'metadata/ju'
180
186
  )
181
187
  SELECT j.key, j.entity, j.status, j.is_live, j.created_at,
182
188
  CASE WHEN j.updated_at != j.created_at THEN j.updated_at
@@ -184,20 +190,20 @@ async function listJobs(params) {
184
190
  ELSE j.updated_at
185
191
  END as updated_at,
186
192
  ws.id as set_id
187
- FROM durable.jobs j
188
- LEFT JOIN durable.jobs_attributes ju
193
+ FROM ${schema}.jobs j
194
+ LEFT JOIN ${schema}.jobs_attributes ju
189
195
  ON ju.job_id = j.id
190
196
  AND ju.symbol IN (SELECT value FROM ju_symbols)
191
197
  AND (ju.dimension IS NULL OR ju.dimension = '')
192
198
  LEFT JOIN lt_workflow_sets ws
193
- ON ws.source_workflow_id = REPLACE(j.key, 'hmsh:durable:j:', '')
199
+ ON ws.source_workflow_id = REPLACE(j.key, '${keyPrefix}', '')
194
200
  AND j.entity = 'mcpWorkflowPlanner'
195
201
  WHERE ${where}
196
202
  ORDER BY ${buildJobOrderBy(params.sort_by, params.order)}
197
- LIMIT $${idx++} OFFSET $${idx++}`, [...values, limit, offset]),
203
+ LIMIT $${idx++} OFFSET $${idx++}`, [...values, limit, offset]).catch(() => ({ rows: [] })),
198
204
  ]);
199
205
  const jobs = dataResult.rows.map((row) => ({
200
- workflow_id: row.key.replace('hmsh:durable:j:', ''),
206
+ workflow_id: row.key.replace(keyPrefix, ''),
201
207
  entity: row.entity,
202
208
  status: (row.status > 0 ? 'running' : row.status === 0 ? 'completed' : 'failed'),
203
209
  is_live: row.is_live,
@@ -43,11 +43,12 @@ const CRON_ID = 'lt-maintenance-nightly';
43
43
  /**
44
44
  * Translate a single maintenance rule into the appropriate dbaService.prune() call.
45
45
  */
46
- async function executeRule(rule) {
46
+ async function executeRule(appId, rule) {
47
47
  switch (true) {
48
48
  // Delete stream messages
49
49
  case rule.target === 'streams' && rule.action === 'delete':
50
50
  await dbaService.prune({
51
+ appId,
51
52
  expire: rule.olderThan,
52
53
  streams: true,
53
54
  jobs: false,
@@ -56,6 +57,7 @@ async function executeRule(rule) {
56
57
  // Delete transient jobs (entity IS NULL)
57
58
  case rule.target === 'jobs' && rule.action === 'delete' && rule.hasEntity === false:
58
59
  await dbaService.prune({
60
+ appId,
59
61
  expire: rule.olderThan,
60
62
  jobs: false,
61
63
  streams: false,
@@ -65,6 +67,7 @@ async function executeRule(rule) {
65
67
  // Strip execution artifacts from entity jobs (keep jdata/udata/jmark/hmark)
66
68
  case rule.target === 'jobs' && rule.action === 'prune' && rule.hasEntity === true:
67
69
  await dbaService.prune({
70
+ appId,
68
71
  expire: rule.olderThan,
69
72
  jobs: false,
70
73
  streams: false,
@@ -75,6 +78,7 @@ async function executeRule(rule) {
75
78
  // Hard-delete old pruned jobs
76
79
  case rule.target === 'jobs' && rule.action === 'delete' && rule.pruned === true:
77
80
  await dbaService.prune({
81
+ appId,
78
82
  expire: rule.olderThan,
79
83
  jobs: true,
80
84
  streams: false,
@@ -112,8 +116,7 @@ class LTMaintenanceRegistry {
112
116
  async connect() {
113
117
  if (this.connected || !this._config)
114
118
  return;
115
- const rules = this._config.rules;
116
- const schedule = this._config.schedule;
119
+ const { appId, rules, schedule } = this._config;
117
120
  const connection = (0, db_1.getConnection)();
118
121
  await hotmesh_1.Virtual.cron({
119
122
  topic: CRON_TOPIC,
@@ -122,7 +125,7 @@ class LTMaintenanceRegistry {
122
125
  logger_1.loggerRegistry.info('[lt-maintenance] starting maintenance cycle...');
123
126
  for (const rule of rules) {
124
127
  try {
125
- await executeRule(rule);
128
+ await executeRule(appId, rule);
126
129
  }
127
130
  catch (err) {
128
131
  logger_1.loggerRegistry.error(`[lt-maintenance] rule failed: ${JSON.stringify(rule)} ${err?.message}`);
@@ -65,9 +65,12 @@ async function listJobs(params) {
65
65
  const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
66
66
  const keyPrefix = `hmsh:${appId}:j:`;
67
67
  const orderBy = buildOrderBy(params.sort_by, params.order);
68
+ // Graceful degradation: HotMesh schema may not exist yet if no
69
+ // engine/worker has initialized. Return empty results, not 500.
70
+ const empty = { rows: [{ count: '0' }] };
68
71
  const [countResult, dataResult] = await Promise.all([
69
- pool.query((0, sql_1.COUNT_JOBS)(schema, where), values),
70
- pool.query((0, sql_1.LIST_JOBS)(schema, appId, where, idx++, idx++, orderBy), [...values, limit, offset]),
72
+ pool.query((0, sql_1.COUNT_JOBS)(schema, where), values).catch(() => empty),
73
+ pool.query((0, sql_1.LIST_JOBS)(schema, appId, where, idx++, idx++, orderBy), [...values, limit, offset]).catch(() => ({ rows: [] })),
71
74
  ]);
72
75
  const jobs = dataResult.rows.map((row) => ({
73
76
  workflow_id: row.key.startsWith(keyPrefix) ? row.key.slice(keyPrefix.length) : row.key,
@@ -1,4 +1,3 @@
1
- export declare const DISTINCT_ENTITIES_DURABLE = "\n SELECT DISTINCT entity FROM durable.jobs WHERE entity IS NOT NULL AND entity != '' ORDER BY entity";
2
1
  export declare const DISTINCT_ENTITIES: (schema: string) => string;
3
2
  export declare const ACTIVE_GRAPH_TOPICS = "SELECT DISTINCT graph_topic FROM lt_yaml_workflows WHERE app_id = $1 AND status IN ('active', 'deployed')";
4
3
  export declare const COUNT_JOBS: (schema: string, where: string) => string;
@@ -3,9 +3,7 @@
3
3
  // Schema placeholders (${schema}) are interpolated at call time
4
4
  // because Postgres does not support parameterized schema names.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.LIST_JOBS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB = exports.COUNT_JOBS = exports.ACTIVE_GRAPH_TOPICS = exports.DISTINCT_ENTITIES = exports.DISTINCT_ENTITIES_DURABLE = void 0;
7
- exports.DISTINCT_ENTITIES_DURABLE = `
8
- SELECT DISTINCT entity FROM durable.jobs WHERE entity IS NOT NULL AND entity != '' ORDER BY entity`;
6
+ exports.LIST_JOBS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB = exports.COUNT_JOBS = exports.ACTIVE_GRAPH_TOPICS = exports.DISTINCT_ENTITIES = void 0;
9
7
  const DISTINCT_ENTITIES = (schema) => `SELECT DISTINCT entity FROM ${schema}.jobs WHERE entity IS NOT NULL AND entity != '' ORDER BY entity`;
10
8
  exports.DISTINCT_ENTITIES = DISTINCT_ENTITIES;
11
9
  exports.ACTIVE_GRAPH_TOPICS = `SELECT DISTINCT graph_topic FROM lt_yaml_workflows WHERE app_id = $1 AND status IN ('active', 'deployed')`;
@@ -57,7 +57,7 @@ function registerControlPlaneTools(server) {
57
57
  inputSchema: schemas_1.rollCallSchema,
58
58
  }, async (args) => {
59
59
  const result = await api.rollCall({
60
- appId: args.app_id || 'durable',
60
+ appId: args.app_id,
61
61
  delay: args.delay,
62
62
  });
63
63
  if (result.error) {
@@ -45,6 +45,7 @@ function registerMaintenanceTools(server) {
45
45
  inputSchema: schemas_1.pruneSchema,
46
46
  }, async (args) => {
47
47
  const result = await dbaService.prune({
48
+ appId: args.app_id,
48
49
  expire: args.expire,
49
50
  jobs: args.jobs,
50
51
  streams: args.streams,