@hotmeshio/long-tail 0.4.22 → 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 (207) hide show
  1. package/build/api/dba.d.ts +2 -1
  2. package/build/api/dba.js +3 -2
  3. package/build/api/exports.d.ts +1 -0
  4. package/build/api/exports.js +1 -1
  5. package/build/api/maintenance.d.ts +1 -0
  6. package/build/api/maintenance.js +3 -3
  7. package/build/api/workflows/discovery.js +5 -2
  8. package/build/modules/maintenance.js +1 -0
  9. package/build/routes/controlplane.js +40 -29
  10. package/build/routes/dba.js +13 -2
  11. package/build/routes/exports.js +6 -0
  12. package/build/routes/maintenance.js +1 -0
  13. package/build/services/controlplane/index.js +7 -5
  14. package/build/services/dba.d.ts +3 -1
  15. package/build/services/dba.js +5 -4
  16. package/build/services/export/index.d.ts +2 -2
  17. package/build/services/export/index.js +16 -10
  18. package/build/services/maintenance/index.js +7 -4
  19. package/build/services/pipelines/queries.js +5 -2
  20. package/build/services/pipelines/sql.d.ts +0 -1
  21. package/build/services/pipelines/sql.js +1 -3
  22. package/build/system/mcp-servers/admin/controlplane.js +1 -1
  23. package/build/system/mcp-servers/admin/maintenance.js +1 -0
  24. package/build/system/mcp-servers/admin/pipelines.js +4 -4
  25. package/build/system/mcp-servers/admin/schemas.d.ts +31 -25
  26. package/build/system/mcp-servers/admin/schemas.js +9 -7
  27. package/build/types/maintenance.d.ts +2 -0
  28. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js → AdminDashboard-CgJC8ZZF.js} +2 -2
  29. package/dashboard/dist/assets/{AdminDashboard-BwUGcCxQ.js.map → AdminDashboard-CgJC8ZZF.js.map} +1 -1
  30. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js → AgentConfigPage-Bjl2Lsvo.js} +2 -2
  31. package/dashboard/dist/assets/{AgentConfigPage-DgrYzLwq.js.map → AgentConfigPage-Bjl2Lsvo.js.map} +1 -1
  32. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js → AgentDetailPage-D5dHrfaM.js} +2 -2
  33. package/dashboard/dist/assets/{AgentDetailPage-XJpl7wfJ.js.map → AgentDetailPage-D5dHrfaM.js.map} +1 -1
  34. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js → AgentsPage-Mom3N1Av.js} +2 -2
  35. package/dashboard/dist/assets/{AgentsPage-CGpVG6r8.js.map → AgentsPage-Mom3N1Av.js.map} +1 -1
  36. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js → AvailableEscalationsPage-B2ZAb41C.js} +2 -2
  37. package/dashboard/dist/assets/{AvailableEscalationsPage-DR1e0TQZ.js.map → AvailableEscalationsPage-B2ZAb41C.js.map} +1 -1
  38. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js → BotPicker-dCvnjynP.js} +2 -2
  39. package/dashboard/dist/assets/{BotPicker-BKtjl6IL.js.map → BotPicker-dCvnjynP.js.map} +1 -1
  40. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js → CapabilitiesPage-CK2fJ9Sy.js} +2 -2
  41. package/dashboard/dist/assets/{CapabilitiesPage-kCB8fyOj.js.map → CapabilitiesPage-CK2fJ9Sy.js.map} +1 -1
  42. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js → CollapsibleSection-bW0UZN9b.js} +2 -2
  43. package/dashboard/dist/assets/{CollapsibleSection-C3tU61hB.js.map → CollapsibleSection-bW0UZN9b.js.map} +1 -1
  44. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js → CredentialsPage-DVOK3aaR.js} +2 -2
  45. package/dashboard/dist/assets/{CredentialsPage-Dt4nJs_B.js.map → CredentialsPage-DVOK3aaR.js.map} +1 -1
  46. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js → CronLabel-Cv5em7OP.js} +2 -2
  47. package/dashboard/dist/assets/{CronLabel-BdE6mHyA.js.map → CronLabel-Cv5em7OP.js.map} +1 -1
  48. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js → CustomDurationPicker-Dy4NBqhZ.js} +2 -2
  49. package/dashboard/dist/assets/{CustomDurationPicker-B_Yxfb-u.js.map → CustomDurationPicker-Dy4NBqhZ.js.map} +1 -1
  50. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js → ElapsedCell-TQqWaVRq.js} +2 -2
  51. package/dashboard/dist/assets/{ElapsedCell-tcGx5PFI.js.map → ElapsedCell-TQqWaVRq.js.map} +1 -1
  52. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js → EscalationsOverview-Cv5UvuHI.js} +2 -2
  53. package/dashboard/dist/assets/{EscalationsOverview-1KO5dXzk.js.map → EscalationsOverview-Cv5UvuHI.js.map} +1 -1
  54. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js → EventTable-Doky6fCO.js} +2 -2
  55. package/dashboard/dist/assets/{EventTable-DnpsQ6Ew.js.map → EventTable-Doky6fCO.js.map} +1 -1
  56. package/dashboard/dist/assets/HomePage-CzvVyTq4.js +2 -0
  57. package/dashboard/dist/assets/HomePage-CzvVyTq4.js.map +1 -0
  58. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js → ListToolbar-Cfec9gz_.js} +2 -2
  59. package/dashboard/dist/assets/{ListToolbar-jrVba7QN.js.map → ListToolbar-Cfec9gz_.js.map} +1 -1
  60. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js +2 -0
  61. package/dashboard/dist/assets/McpOverview-BN4GsBGI.js.map +1 -0
  62. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +5 -0
  63. package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +1 -0
  64. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js → McpQueryPage-BK5L2PqJ.js} +2 -2
  65. package/dashboard/dist/assets/{McpQueryPage-WZfTY43_.js.map → McpQueryPage-BK5L2PqJ.js.map} +1 -1
  66. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +2 -0
  67. package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +1 -0
  68. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js +2 -0
  69. package/dashboard/dist/assets/McpRunsPage-QsXid9Xe.js.map +1 -0
  70. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js → OperatorDashboard-CZQSINho.js} +2 -2
  71. package/dashboard/dist/assets/{OperatorDashboard-Cy7ySMXj.js.map → OperatorDashboard-CZQSINho.js.map} +1 -1
  72. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js → ProcessDetailPage-DUCOOvOK.js} +2 -2
  73. package/dashboard/dist/assets/{ProcessDetailPage-DYIfvWyc.js.map → ProcessDetailPage-DUCOOvOK.js.map} +1 -1
  74. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js → ProcessesListPage-CXvSLTIM.js} +2 -2
  75. package/dashboard/dist/assets/{ProcessesListPage-DR1RGaMl.js.map → ProcessesListPage-CXvSLTIM.js.map} +1 -1
  76. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js +2 -0
  77. package/dashboard/dist/assets/RolesPage-DlQR0Iz_.js.map +1 -0
  78. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js → RunAsSelector-DP-jxsv6.js} +2 -2
  79. package/dashboard/dist/assets/{RunAsSelector-B-ksMoEj.js.map → RunAsSelector-DP-jxsv6.js.map} +1 -1
  80. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js → SwimlaneTimeline-BmASA0nN.js} +2 -2
  81. package/dashboard/dist/assets/{SwimlaneTimeline-Cr_K5qpu.js.map → SwimlaneTimeline-BmASA0nN.js.map} +1 -1
  82. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js → TaskDetailPage-CRowpkeZ.js} +2 -2
  83. package/dashboard/dist/assets/{TaskDetailPage-BO5p7AEe.js.map → TaskDetailPage-CRowpkeZ.js.map} +1 -1
  84. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js → TasksListPage-uJ6z37J-.js} +2 -2
  85. package/dashboard/dist/assets/{TasksListPage-BRg-uFtF.js.map → TasksListPage-uJ6z37J-.js.map} +1 -1
  86. package/dashboard/dist/assets/TimeAgo-BxwngK1D.js +2 -0
  87. package/dashboard/dist/assets/{TimeAgo-BSzN6rAH.js.map → TimeAgo-BxwngK1D.js.map} +1 -1
  88. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js → TimestampCell-CDmichOM.js} +2 -2
  89. package/dashboard/dist/assets/{TimestampCell-DL6zMNEQ.js.map → TimestampCell-CDmichOM.js.map} +1 -1
  90. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +2 -0
  91. package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +1 -0
  92. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js → TopicDetailPage-Dm0hDlS8.js} +2 -2
  93. package/dashboard/dist/assets/{TopicDetailPage-D7gCsPKB.js.map → TopicDetailPage-Dm0hDlS8.js.map} +1 -1
  94. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js → TopicsPage-letISGGD.js} +2 -2
  95. package/dashboard/dist/assets/{TopicsPage-B3Aa8Haz.js.map → TopicsPage-letISGGD.js.map} +1 -1
  96. package/dashboard/dist/assets/{UserName-BjHIJWgh.js → UserName-W6_Iz2Qb.js} +2 -2
  97. package/dashboard/dist/assets/{UserName-BjHIJWgh.js.map → UserName-W6_Iz2Qb.js.map} +1 -1
  98. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js → WorkflowExecutionPage-Cfx-xlRT.js} +2 -2
  99. package/dashboard/dist/assets/{WorkflowExecutionPage-BQ7AYlQA.js.map → WorkflowExecutionPage-Cfx-xlRT.js.map} +1 -1
  100. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js +2 -0
  101. package/dashboard/dist/assets/WorkflowsDashboard-DC4XHMWt.js.map +1 -0
  102. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js → WorkflowsOverview-GefO_yn0.js} +2 -2
  103. package/dashboard/dist/assets/{WorkflowsOverview-B4DUcVxs.js.map → WorkflowsOverview-GefO_yn0.js.map} +1 -1
  104. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +2 -0
  105. package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +1 -0
  106. package/dashboard/dist/assets/{agents-CkvQDr9b.js → agents-BI5OeN84.js} +2 -2
  107. package/dashboard/dist/assets/{agents-CkvQDr9b.js.map → agents-BI5OeN84.js.map} +1 -1
  108. package/dashboard/dist/assets/{bots-CzuMCVgU.js → bots-1UzUCsrR.js} +2 -2
  109. package/dashboard/dist/assets/{bots-CzuMCVgU.js.map → bots-1UzUCsrR.js.map} +1 -1
  110. package/dashboard/dist/assets/capabilities-BUbl-ojp.js +2 -0
  111. package/dashboard/dist/assets/{capabilities-CbGmS0ty.js.map → capabilities-BUbl-ojp.js.map} +1 -1
  112. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js → controlplane-DTFrH_vN.js} +2 -2
  113. package/dashboard/dist/assets/{controlplane-DGvwkuYx.js.map → controlplane-DTFrH_vN.js.map} +1 -1
  114. package/dashboard/dist/assets/{escalation-B7ysVToF.js → escalation-BQhCt4W0.js} +2 -2
  115. package/dashboard/dist/assets/{escalation-B7ysVToF.js.map → escalation-BQhCt4W0.js.map} +1 -1
  116. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js → escalation-columns-J20k5CcY.js} +2 -2
  117. package/dashboard/dist/assets/{escalation-columns-CHQEJU1j.js.map → escalation-columns-J20k5CcY.js.map} +1 -1
  118. package/dashboard/dist/assets/{helpers-BFOjXa4r.js → helpers-ge6Eu90Y.js} +2 -2
  119. package/dashboard/dist/assets/{helpers-BFOjXa4r.js.map → helpers-ge6Eu90Y.js.map} +1 -1
  120. package/dashboard/dist/assets/index-C-mbURj-.js +2 -0
  121. package/dashboard/dist/assets/index-C-mbURj-.js.map +1 -0
  122. package/dashboard/dist/assets/{index-BduDiGcw.js → index-C45DvtAZ.js} +2 -2
  123. package/dashboard/dist/assets/{index-BduDiGcw.js.map → index-C45DvtAZ.js.map} +1 -1
  124. package/dashboard/dist/assets/{index-B9_1AZaG.js → index-C9ClHiiW.js} +2 -2
  125. package/dashboard/dist/assets/{index-B9_1AZaG.js.map → index-C9ClHiiW.js.map} +1 -1
  126. package/dashboard/dist/assets/index-CLUYzdwz.js +2 -0
  127. package/dashboard/dist/assets/{index-DQHmfTPo.js.map → index-CLUYzdwz.js.map} +1 -1
  128. package/dashboard/dist/assets/{index-l_8R6U4r.js → index-CVGgSoda.js} +2 -2
  129. package/dashboard/dist/assets/{index-l_8R6U4r.js.map → index-CVGgSoda.js.map} +1 -1
  130. package/dashboard/dist/assets/{index-_BRA9uFL.js → index-CWEOhAiK.js} +3 -3
  131. package/dashboard/dist/assets/{index-_BRA9uFL.js.map → index-CWEOhAiK.js.map} +1 -1
  132. package/dashboard/dist/assets/{index-BFaDxPxA.js → index-CWlP6vHG.js} +2 -2
  133. package/dashboard/dist/assets/{index-BFaDxPxA.js.map → index-CWlP6vHG.js.map} +1 -1
  134. package/dashboard/dist/assets/index-DasoTRjT.js +2 -0
  135. package/dashboard/dist/assets/{index-BeLphL59.js.map → index-DasoTRjT.js.map} +1 -1
  136. package/dashboard/dist/assets/{index-CvOGgvzP.js → index-FhasoOjO.js} +2 -2
  137. package/dashboard/dist/assets/{index-CvOGgvzP.js.map → index-FhasoOjO.js.map} +1 -1
  138. package/dashboard/dist/assets/{index-a98qWLB-.js → index-WQQJ_cp7.js} +2 -2
  139. package/dashboard/dist/assets/{index-a98qWLB-.js.map → index-WQQJ_cp7.js.map} +1 -1
  140. package/dashboard/dist/assets/{index-CbrMW-gM.js → index-hAZiac0C.js} +2 -2
  141. package/dashboard/dist/assets/{index-CbrMW-gM.js.map → index-hAZiac0C.js.map} +1 -1
  142. package/dashboard/dist/assets/{index-v0OQpgXS.js → index-si70YcIP.js} +2 -2
  143. package/dashboard/dist/assets/{index-v0OQpgXS.js.map → index-si70YcIP.js.map} +1 -1
  144. package/dashboard/dist/assets/{index-CRiBkHPb.js → index-vgxjge70.js} +2 -2
  145. package/dashboard/dist/assets/{index-CRiBkHPb.js.map → index-vgxjge70.js.map} +1 -1
  146. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js → knowledge-D9Tuh-o-.js} +2 -2
  147. package/dashboard/dist/assets/{knowledge-BlF8UMrk.js.map → knowledge-D9Tuh-o-.js.map} +1 -1
  148. package/dashboard/dist/assets/{mcp-MtXuky8q.js → mcp-BO8QnWyk.js} +2 -2
  149. package/dashboard/dist/assets/{mcp-MtXuky8q.js.map → mcp-BO8QnWyk.js.map} +1 -1
  150. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js → mcp-query-WLtQtr51.js} +2 -2
  151. package/dashboard/dist/assets/{mcp-query-DQ-J1Q0K.js.map → mcp-query-WLtQtr51.js.map} +1 -1
  152. package/dashboard/dist/assets/pipelines-BAVf9xud.js +2 -0
  153. package/dashboard/dist/assets/pipelines-BAVf9xud.js.map +1 -0
  154. package/dashboard/dist/assets/{roles-D-LhJ82d.js → roles-mGO2-2hA.js} +2 -2
  155. package/dashboard/dist/assets/{roles-D-LhJ82d.js.map → roles-mGO2-2hA.js.map} +1 -1
  156. package/dashboard/dist/assets/{tasks-BrP_8uEN.js → tasks-JVRVCx0f.js} +2 -2
  157. package/dashboard/dist/assets/{tasks-BrP_8uEN.js.map → tasks-JVRVCx0f.js.map} +1 -1
  158. package/dashboard/dist/assets/{topics-DUk-zX5D.js → topics-BLVnahd7.js} +2 -2
  159. package/dashboard/dist/assets/{topics-DUk-zX5D.js.map → topics-BLVnahd7.js.map} +1 -1
  160. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js → useEventHooks-BwjAi0Qq.js} +2 -2
  161. package/dashboard/dist/assets/{useEventHooks-XNNzwADV.js.map → useEventHooks-BwjAi0Qq.js.map} +1 -1
  162. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js +2 -0
  163. package/dashboard/dist/assets/useNamespace-DkHmXddZ.js.map +1 -0
  164. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js → useYamlActivityEvents-CsaR5dWj.js} +2 -2
  165. package/dashboard/dist/assets/{useYamlActivityEvents-DANQ5jIY.js.map → useYamlActivityEvents-CsaR5dWj.js.map} +1 -1
  166. package/dashboard/dist/assets/{users-vj0JgOkA.js → users-BvizpAkV.js} +2 -2
  167. package/dashboard/dist/assets/{users-vj0JgOkA.js.map → users-BvizpAkV.js.map} +1 -1
  168. package/dashboard/dist/assets/{workflows-CmqgGPzI.js → workflows-CyEYa01a.js} +2 -2
  169. package/dashboard/dist/assets/{workflows-CmqgGPzI.js.map → workflows-CyEYa01a.js.map} +1 -1
  170. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js → yaml-workflows-i3GzrEme.js} +2 -2
  171. package/dashboard/dist/assets/{yaml-workflows-DNFyjBXH.js.map → yaml-workflows-i3GzrEme.js.map} +1 -1
  172. package/dashboard/dist/index.html +1 -1
  173. package/docs/api/http/controlplane.md +6 -4
  174. package/docs/api/http/dba.md +1 -0
  175. package/docs/api/http/exports.md +26 -0
  176. package/docs/api/http/maintenance.md +1 -0
  177. package/docs/api/mcp/admin.md +7 -7
  178. package/docs/api/sdk/controlplane.md +4 -4
  179. package/package.json +1 -1
  180. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js +0 -2
  181. package/dashboard/dist/assets/HomePage-B2Jgo1J1.js.map +0 -1
  182. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js +0 -2
  183. package/dashboard/dist/assets/McpOverview-BzyxJyc9.js.map +0 -1
  184. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js +0 -5
  185. package/dashboard/dist/assets/McpQueryDetailPage-DXNseeKl.js.map +0 -1
  186. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js +0 -2
  187. package/dashboard/dist/assets/McpRunDetailPage-DKZp-p7S.js.map +0 -1
  188. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js +0 -2
  189. package/dashboard/dist/assets/McpRunsPage-SXyiwc0d.js.map +0 -1
  190. package/dashboard/dist/assets/RolesPage-pMERxj15.js +0 -2
  191. package/dashboard/dist/assets/RolesPage-pMERxj15.js.map +0 -1
  192. package/dashboard/dist/assets/TimeAgo-BSzN6rAH.js +0 -2
  193. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js +0 -2
  194. package/dashboard/dist/assets/ToolTestPanel-fLzNp79U.js.map +0 -1
  195. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js +0 -2
  196. package/dashboard/dist/assets/WorkflowsDashboard-D-G8Xudz.js.map +0 -1
  197. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js +0 -2
  198. package/dashboard/dist/assets/YamlWorkflowsPage-CnTNOku0.js.map +0 -1
  199. package/dashboard/dist/assets/capabilities-CbGmS0ty.js +0 -2
  200. package/dashboard/dist/assets/index-BeLphL59.js +0 -2
  201. package/dashboard/dist/assets/index-DDlrQeTj.js +0 -2
  202. package/dashboard/dist/assets/index-DDlrQeTj.js.map +0 -1
  203. package/dashboard/dist/assets/index-DQHmfTPo.js +0 -2
  204. package/dashboard/dist/assets/namespaces-DtsT_GoV.js +0 -2
  205. package/dashboard/dist/assets/namespaces-DtsT_GoV.js.map +0 -1
  206. package/dashboard/dist/assets/pipelines-BjlCm9VH.js +0 -2
  207. package/dashboard/dist/assets/pipelines-BjlCm9VH.js.map +0 -1
@@ -19,6 +19,7 @@ import type { LTApiResult } from '../types/sdk';
19
19
  * @returns `{ status: 200, data: <prune result summary> }`
20
20
  */
21
21
  export declare function prune(input: {
22
+ appId: string;
22
23
  expire?: string;
23
24
  jobs?: boolean;
24
25
  streams?: boolean;
@@ -39,4 +40,4 @@ export declare function prune(input: {
39
40
  *
40
41
  * @returns `{ status: 200, data: { ok: true } }`
41
42
  */
42
- export declare function deploy(): Promise<LTApiResult>;
43
+ export declare function deploy(appId: string): Promise<LTApiResult>;
package/build/api/dba.js CHANGED
@@ -58,6 +58,7 @@ const dbaService = __importStar(require("../services/dba"));
58
58
  async function prune(input) {
59
59
  try {
60
60
  const result = await dbaService.prune({
61
+ appId: input.appId,
61
62
  expire: input.expire,
62
63
  jobs: input.jobs,
63
64
  streams: input.streams,
@@ -84,9 +85,9 @@ async function prune(input) {
84
85
  *
85
86
  * @returns `{ status: 200, data: { ok: true } }`
86
87
  */
87
- async function deploy() {
88
+ async function deploy(appId) {
88
89
  try {
89
- await dbaService.deploy();
90
+ await dbaService.deploy(appId);
90
91
  return { status: 200, data: { ok: true } };
91
92
  }
92
93
  catch (err) {
@@ -15,6 +15,7 @@ import type { ExportMode } from '@hotmeshio/hotmesh/build/types/exporter';
15
15
  * @returns `{ status: 200, data: { jobs, total, ... } }` on success
16
16
  */
17
17
  export declare function listJobs(input: {
18
+ app_id: string;
18
19
  limit?: number;
19
20
  offset?: number;
20
21
  entity?: string;
@@ -55,7 +55,7 @@ const resolve_1 = require("../services/task/resolve");
55
55
  */
56
56
  async function listJobs(input) {
57
57
  try {
58
- const result = await exportService.listJobs(input);
58
+ const result = await exportService.listJobs(input.app_id, input);
59
59
  return { status: 200, data: result };
60
60
  }
61
61
  catch (err) {
@@ -17,6 +17,7 @@ export declare function getMaintenanceConfig(): LTApiResult;
17
17
  * @returns `{ status: 200, data: { config, restarted: true } }`
18
18
  */
19
19
  export declare function updateMaintenanceConfig(input: {
20
+ appId: string;
20
21
  schedule: string;
21
22
  rules: LTMaintenanceConfig['rules'];
22
23
  }): Promise<LTApiResult>;
@@ -26,11 +26,11 @@ function getMaintenanceConfig() {
26
26
  */
27
27
  async function updateMaintenanceConfig(input) {
28
28
  try {
29
- if (!input.schedule || !Array.isArray(input.rules)) {
30
- return { status: 400, error: 'schedule (string) and rules (array) are required' };
29
+ if (!input.appId || !input.schedule || !Array.isArray(input.rules)) {
30
+ return { status: 400, error: 'appId (string), schedule (string), and rules (array) are required' };
31
31
  }
32
32
  await maintenance_1.maintenanceRegistry.disconnect();
33
- maintenance_1.maintenanceRegistry.register({ schedule: input.schedule, rules: input.rules });
33
+ maintenance_1.maintenanceRegistry.register({ appId: input.appId, schedule: input.schedule, rules: input.rules });
34
34
  await maintenance_1.maintenanceRegistry.connect();
35
35
  return {
36
36
  status: 200,
@@ -41,6 +41,7 @@ const cron_1 = require("../../services/cron");
41
41
  const db_1 = require("../../lib/db");
42
42
  const registry_1 = require("../../services/workers/registry");
43
43
  const sql_1 = require("../../services/pipelines/sql");
44
+ const hotmesh_utils_1 = require("../../services/hotmesh-utils");
44
45
  /**
45
46
  * List active workflow workers with their registration status.
46
47
  *
@@ -81,9 +82,11 @@ async function listDiscoveredWorkflows(input) {
81
82
  try {
82
83
  // 1. Active workers from in-memory registry
83
84
  const activeWorkers = (0, registry_1.getRegisteredWorkers)();
84
- // 2. Historical entities from durable.jobs
85
+ // 2. Historical entities from jobs table
85
86
  const pool = (0, db_1.getPool)();
86
- const { rows: entityRows } = await pool.query(sql_1.DISTINCT_ENTITIES_DURABLE);
87
+ // TODO: accept app_id parameter to avoid hardcoded schema
88
+ const schema = (0, hotmesh_utils_1.quoteSchema)((0, hotmesh_utils_1.sanitizeAppId)('durable'));
89
+ const { rows: entityRows } = await pool.query((0, sql_1.DISTINCT_ENTITIES)(schema));
87
90
  const historicalEntities = new Set(entityRows.map((r) => r.entity));
88
91
  // 3. Registered configs
89
92
  const configs = await configService.listWorkflowConfigs();
@@ -18,6 +18,7 @@ exports.defaultMaintenanceConfig = void 0;
18
18
  * inputs from the execution timeline.
19
19
  */
20
20
  exports.defaultMaintenanceConfig = {
21
+ appId: 'durable',
21
22
  schedule: '0 2 * * 0',
22
23
  rules: [
23
24
  {
@@ -39,8 +39,8 @@ const api = __importStar(require("../api/controlplane"));
39
39
  const router = (0, express_1.Router)();
40
40
  /**
41
41
  * GET /api/controlplane/apps
42
- * List available HotMesh application IDs.
43
- * Admin-only.
42
+ * List available HotMesh application namespaces.
43
+ * Builder-only.
44
44
  */
45
45
  router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
46
46
  const result = await api.listApps();
@@ -49,11 +49,16 @@ router.get('/apps', auth_1.requireBuilder, async (_req, res) => {
49
49
  /**
50
50
  * GET /api/controlplane/rollcall?app_id=durable&delay=1000
51
51
  * Execute a roll call — discovers all engines and workers.
52
- * Admin-only.
52
+ * Builder-only. app_id is required.
53
53
  */
54
54
  router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
55
+ const appId = req.query.app_id;
56
+ if (!appId) {
57
+ res.status(400).json({ error: 'app_id query parameter is required' });
58
+ return;
59
+ }
55
60
  const result = await api.rollCall({
56
- appId: req.query.app_id || 'durable',
61
+ appId,
57
62
  delay: req.query.delay ? parseInt(req.query.delay, 10) : undefined,
58
63
  });
59
64
  res.status(result.status).json(result.data ?? { error: result.error });
@@ -61,27 +66,32 @@ router.get('/rollcall', auth_1.requireBuilder, async (req, res) => {
61
66
  /**
62
67
  * POST /api/controlplane/throttle
63
68
  * Apply a throttle command to the mesh.
64
- * Admin-only.
69
+ * Builder-only. appId is required in body.
65
70
  *
66
71
  * Body: { appId: string, throttle: number, topic?: string, guid?: string }
67
- * throttle: ms delay (-1 = pause, 0 = resume, >0 = delay per msg)
68
72
  */
69
73
  router.post('/throttle', auth_1.requireBuilder, async (req, res) => {
70
- const { appId = 'durable', throttle, topic, guid, scope } = req.body;
74
+ const { appId, throttle, topic, guid, scope } = req.body;
75
+ if (!appId) {
76
+ res.status(400).json({ error: 'appId is required' });
77
+ return;
78
+ }
71
79
  const result = await api.applyThrottle({ appId, throttle, topic, guid, scope });
72
80
  res.status(result.status).json(result.data ?? { error: result.error });
73
81
  });
74
82
  /**
75
- * GET /api/controlplane/streams?app_id=durable&duration=1h&stream=hmsh:durable:x:
76
- * Stream processing statistics — pending count + processed volume by time range.
77
- * Admin-only.
78
- *
79
- * duration: 15m | 30m | 1h | 1d | 7d (default: 1h)
80
- * stream: optional stream_name filter (specific task queue topic)
83
+ * GET /api/controlplane/streams?app_id=durable&duration=1h
84
+ * Stream processing statistics.
85
+ * Builder-only. app_id is required.
81
86
  */
82
87
  router.get('/streams', auth_1.requireBuilder, async (req, res) => {
88
+ const app_id = req.query.app_id;
89
+ if (!app_id) {
90
+ res.status(400).json({ error: 'app_id query parameter is required' });
91
+ return;
92
+ }
83
93
  const result = await api.getStreamStats({
84
- app_id: req.query.app_id || 'durable',
94
+ app_id,
85
95
  duration: req.query.duration || '1h',
86
96
  stream: req.query.stream || undefined,
87
97
  });
@@ -89,18 +99,19 @@ router.get('/streams', auth_1.requireBuilder, async (req, res) => {
89
99
  });
90
100
  /**
91
101
  * GET /api/controlplane/stream-messages?namespace=durable&source=worker
92
- * &limit=25&offset=0&sort_by=created_at&order=desc
93
- * &status=pending&stream_name=hmsh:durable:w:&msg_type=WORKER
94
- *
95
102
  * Browse stream messages with pagination, filtering, and sorting.
96
- * Both namespace and source are required — engine and worker streams
97
- * are separate tables with different schemas.
98
- * Admin-only.
103
+ * Builder-only. namespace and source are required.
99
104
  */
100
105
  router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
106
+ const namespace = req.query.namespace;
107
+ const source = req.query.source;
108
+ if (!namespace || !source) {
109
+ res.status(400).json({ error: 'namespace and source query parameters are required' });
110
+ return;
111
+ }
101
112
  const result = await api.listStreamMessages({
102
- namespace: req.query.namespace,
103
- source: req.query.source,
113
+ namespace,
114
+ source,
104
115
  limit: req.query.limit ? parseInt(req.query.limit, 10) : undefined,
105
116
  offset: req.query.offset ? parseInt(req.query.offset, 10) : undefined,
106
117
  sort_by: req.query.sort_by || undefined,
@@ -117,15 +128,15 @@ router.get('/stream-messages', auth_1.requireBuilder, async (req, res) => {
117
128
  });
118
129
  /**
119
130
  * POST /api/controlplane/subscribe
120
- * Start the quorum→NATS bridge for an appId.
121
- * Subscribes to the HotMesh quorum channel and republishes
122
- * all control plane messages to NATS on `lt.mesh.*` topics.
123
- * Admin-only.
124
- *
125
- * Body: { appId: string }
131
+ * Start the quorum→NATS bridge for a namespace.
132
+ * Builder-only. appId is required in body.
126
133
  */
127
134
  router.post('/subscribe', auth_1.requireBuilder, async (req, res) => {
128
- const { appId = 'durable' } = req.body;
135
+ const { appId } = req.body;
136
+ if (!appId) {
137
+ res.status(400).json({ error: 'appId is required' });
138
+ return;
139
+ }
129
140
  const result = await api.subscribeMesh({ appId });
130
141
  res.status(result.status).json(result.data ?? { error: result.error });
131
142
  });
@@ -53,7 +53,13 @@ const router = (0, express_1.Router)();
53
53
  * Returns: { jobs, streams, attributes, transient, marked }
54
54
  */
55
55
  router.post('/prune', auth_1.requireAdmin, async (req, res) => {
56
+ const appId = req.body.app_id;
57
+ if (!appId) {
58
+ res.status(400).json({ error: 'app_id is required' });
59
+ return;
60
+ }
56
61
  const result = await api.prune({
62
+ appId,
57
63
  expire: req.body.expire,
58
64
  jobs: req.body.jobs,
59
65
  streams: req.body.streams,
@@ -73,8 +79,13 @@ router.post('/prune', auth_1.requireAdmin, async (req, res) => {
73
79
  * Deploy the server-side prune function and run migrations.
74
80
  * Idempotent — safe to call on startup or from CI/CD.
75
81
  */
76
- router.post('/deploy', auth_1.requireAdmin, async (_req, res) => {
77
- const result = await api.deploy();
82
+ router.post('/deploy', auth_1.requireAdmin, async (req, res) => {
83
+ const appId = req.body.app_id;
84
+ if (!appId) {
85
+ res.status(400).json({ error: 'app_id is required' });
86
+ return;
87
+ }
88
+ const result = await api.deploy(appId);
78
89
  res.status(result.status).json(result.data ?? { error: result.error });
79
90
  });
80
91
  exports.default = router;
@@ -41,7 +41,13 @@ const router = (0, express_1.Router)();
41
41
  * List workflow jobs with optional filtering and pagination.
42
42
  */
43
43
  router.get('/jobs', async (req, res) => {
44
+ const app_id = (req.query.app_id || req.query.namespace);
45
+ if (!app_id) {
46
+ res.status(400).json({ error: 'app_id (or namespace) query parameter is required' });
47
+ return;
48
+ }
44
49
  const result = await api.listJobs({
50
+ app_id,
45
51
  limit: parseInt(req.query.limit) || undefined,
46
52
  offset: parseInt(req.query.offset) || undefined,
47
53
  entity: req.query.entity || undefined,
@@ -54,6 +54,7 @@ router.get('/', (_req, res) => {
54
54
  */
55
55
  router.put('/', auth_1.requireAdmin, async (req, res) => {
56
56
  const result = await api.updateMaintenanceConfig({
57
+ appId: req.body?.appId ?? req.body?.app_id,
57
58
  schedule: req.body?.schedule,
58
59
  rules: req.body?.rules,
59
60
  });
@@ -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
  }
@@ -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,
@@ -44,7 +44,7 @@ function registerPipelineTools(server) {
44
44
  'with graph topics from compiled YAML workflows.',
45
45
  inputSchema: schemas_1.listPipelineEntitiesSchema,
46
46
  }, async (args) => {
47
- const result = await api.listEntities({ app_id: args.app_id || 'durable' });
47
+ const result = await api.listEntities({ app_id: args.app_id });
48
48
  if (result.error) {
49
49
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
50
50
  }
@@ -56,7 +56,7 @@ function registerPipelineTools(server) {
56
56
  description: 'List pipeline jobs with optional entity, search, and status filters.',
57
57
  inputSchema: schemas_1.listPipelineJobsSchema,
58
58
  }, async (args) => {
59
- const result = await api.listJobs({ ...args, app_id: args.app_id || 'durable' });
59
+ const result = await api.listJobs({ ...args, app_id: args.app_id });
60
60
  if (result.error) {
61
61
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
62
62
  }
@@ -70,7 +70,7 @@ function registerPipelineTools(server) {
70
70
  }, async (args) => {
71
71
  const result = await api.getJobExecution({
72
72
  jobId: args.job_id,
73
- app_id: args.app_id || 'durable',
73
+ app_id: args.app_id,
74
74
  });
75
75
  if (result.error) {
76
76
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
@@ -86,7 +86,7 @@ function registerPipelineTools(server) {
86
86
  const result = await api.interruptJob({
87
87
  jobId: args.job_id,
88
88
  topic: args.topic,
89
- app_id: args.app_id || 'durable',
89
+ app_id: args.app_id,
90
90
  });
91
91
  if (result.error) {
92
92
  return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };