@hotmeshio/long-tail 0.4.3 → 0.4.4

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 (244) hide show
  1. package/build/api/settings.js +4 -0
  2. package/build/lib/db/index.d.ts +1 -7
  3. package/build/lib/db/schemas/008_capability_reaction.sql +12 -0
  4. package/build/lib/db/schemas/009_file_topic_category.sql +10 -0
  5. package/build/lib/events/index.d.ts +9 -0
  6. package/build/lib/events/index.js +15 -0
  7. package/build/lib/events/nats.d.ts +15 -1
  8. package/build/lib/events/nats.js +44 -2
  9. package/build/lib/events/publish.d.ts +10 -0
  10. package/build/lib/events/publish.js +28 -0
  11. package/build/modules/config.d.ts +1 -7
  12. package/build/services/agent/subscription-sql.d.ts +3 -3
  13. package/build/services/agent/subscription-sql.js +7 -5
  14. package/build/services/agent/subscriptions.d.ts +3 -1
  15. package/build/services/agent/subscriptions.js +6 -0
  16. package/build/services/agent/trigger-registry.js +18 -0
  17. package/build/services/topics/system-topics.js +29 -0
  18. package/build/services/yaml-workflow/deployer.d.ts +1 -1
  19. package/build/services/yaml-workflow/deployer.js +2 -2
  20. package/build/services/yaml-workflow/invoke.d.ts +2 -0
  21. package/build/services/yaml-workflow/invoke.js +5 -1
  22. package/build/start/adapters.js +11 -9
  23. package/build/start/config.js +4 -0
  24. package/build/start/workers.js +12 -3
  25. package/build/system/index.js +16 -0
  26. package/build/system/mcp-servers/file-storage.js +18 -0
  27. package/build/system/workflows/capability-invoke/activities.d.ts +12 -0
  28. package/build/system/workflows/capability-invoke/activities.js +14 -0
  29. package/build/system/workflows/capability-invoke/index.d.ts +14 -0
  30. package/build/system/workflows/capability-invoke/index.js +74 -0
  31. package/build/tsconfig.tsbuildinfo +1 -1
  32. package/build/types/events.d.ts +13 -1
  33. package/build/types/startup.d.ts +7 -0
  34. package/dashboard/dist/assets/{AdminDashboard-Dr5wTIZT.js → AdminDashboard-DISq0Tz8.js} +2 -2
  35. package/dashboard/dist/assets/{AdminDashboard-Dr5wTIZT.js.map → AdminDashboard-DISq0Tz8.js.map} +1 -1
  36. package/dashboard/dist/assets/AgentConfigPage-DqaJpB3K.js +16 -0
  37. package/dashboard/dist/assets/AgentConfigPage-DqaJpB3K.js.map +1 -0
  38. package/dashboard/dist/assets/AgentDetailPage-BPzPk2GC.js +4 -0
  39. package/dashboard/dist/assets/AgentDetailPage-BPzPk2GC.js.map +1 -0
  40. package/dashboard/dist/assets/AgentsPage-CLcxJWjC.js +2 -0
  41. package/dashboard/dist/assets/AgentsPage-CLcxJWjC.js.map +1 -0
  42. package/dashboard/dist/assets/AvailableEscalationsPage-hOcjAAIj.js +2 -0
  43. package/dashboard/dist/assets/{AvailableEscalationsPage-UzjXcO3W.js.map → AvailableEscalationsPage-hOcjAAIj.js.map} +1 -1
  44. package/dashboard/dist/assets/{BotPicker-CM-_u73k.js → BotPicker-DuAZgHbJ.js} +2 -2
  45. package/dashboard/dist/assets/{BotPicker-CM-_u73k.js.map → BotPicker-DuAZgHbJ.js.map} +1 -1
  46. package/dashboard/dist/assets/CapabilitiesPage-PRel6TXd.js +2 -0
  47. package/dashboard/dist/assets/CapabilitiesPage-PRel6TXd.js.map +1 -0
  48. package/dashboard/dist/assets/{CollapsibleSection-CnPKa7df.js → CollapsibleSection-DnoUFQVf.js} +2 -2
  49. package/dashboard/dist/assets/{CollapsibleSection-CnPKa7df.js.map → CollapsibleSection-DnoUFQVf.js.map} +1 -1
  50. package/dashboard/dist/assets/CopyableId-D0SQ39nR.js +2 -0
  51. package/dashboard/dist/assets/CopyableId-D0SQ39nR.js.map +1 -0
  52. package/dashboard/dist/assets/{CredentialsPage-CImIzra4.js → CredentialsPage-CqedUU7b.js} +2 -2
  53. package/dashboard/dist/assets/{CredentialsPage-CImIzra4.js.map → CredentialsPage-CqedUU7b.js.map} +1 -1
  54. package/dashboard/dist/assets/{CronLabel-5HPAmciI.js → CronLabel-CPEjE-mH.js} +2 -2
  55. package/dashboard/dist/assets/CronLabel-CPEjE-mH.js.map +1 -0
  56. package/dashboard/dist/assets/CustomDurationPicker-BIQWzbv0.js +2 -0
  57. package/dashboard/dist/assets/{CustomDurationPicker-5JzEgS7I.js.map → CustomDurationPicker-BIQWzbv0.js.map} +1 -1
  58. package/dashboard/dist/assets/{DropZone-BEW3jBzf.js → DropZone-e5EOL5gC.js} +2 -2
  59. package/dashboard/dist/assets/{DropZone-BEW3jBzf.js.map → DropZone-e5EOL5gC.js.map} +1 -1
  60. package/dashboard/dist/assets/ElapsedCell-CzVjr74Y.js +2 -0
  61. package/dashboard/dist/assets/{ElapsedCell-B79BF5Mj.js.map → ElapsedCell-CzVjr74Y.js.map} +1 -1
  62. package/dashboard/dist/assets/{EscalationsOverview-QvWvbpx3.js → EscalationsOverview-Bcrb44xJ.js} +2 -2
  63. package/dashboard/dist/assets/{EscalationsOverview-QvWvbpx3.js.map → EscalationsOverview-Bcrb44xJ.js.map} +1 -1
  64. package/dashboard/dist/assets/{EventTable-DAclQwfr.js → EventTable-CGfJU7e1.js} +2 -2
  65. package/dashboard/dist/assets/{EventTable-DAclQwfr.js.map → EventTable-CGfJU7e1.js.map} +1 -1
  66. package/dashboard/dist/assets/{EventTopicPill-By-6sXDp.js → EventTopicPill-xJJnxvlP.js} +2 -2
  67. package/dashboard/dist/assets/{EventTopicPill-By-6sXDp.js.map → EventTopicPill-xJJnxvlP.js.map} +1 -1
  68. package/dashboard/dist/assets/{HomePage-DVOi7rR1.js → HomePage-BIzUcGW9.js} +2 -2
  69. package/dashboard/dist/assets/{HomePage-DVOi7rR1.js.map → HomePage-BIzUcGW9.js.map} +1 -1
  70. package/dashboard/dist/assets/{ListToolbar-Bntl2hex.js → ListToolbar-DNAGFe14.js} +2 -2
  71. package/dashboard/dist/assets/{ListToolbar-Bntl2hex.js.map → ListToolbar-DNAGFe14.js.map} +1 -1
  72. package/dashboard/dist/assets/{McpOverview-B-xSYPJj.js → McpOverview-BpYk21es.js} +2 -2
  73. package/dashboard/dist/assets/{McpOverview-B-xSYPJj.js.map → McpOverview-BpYk21es.js.map} +1 -1
  74. package/dashboard/dist/assets/{McpQueryDetailPage-Cq71BzjB.js → McpQueryDetailPage-DlrZiSuL.js} +2 -2
  75. package/dashboard/dist/assets/{McpQueryDetailPage-Cq71BzjB.js.map → McpQueryDetailPage-DlrZiSuL.js.map} +1 -1
  76. package/dashboard/dist/assets/{McpQueryPage-Dfz87aZF.js → McpQueryPage-COfPssO7.js} +2 -2
  77. package/dashboard/dist/assets/{McpQueryPage-Dfz87aZF.js.map → McpQueryPage-COfPssO7.js.map} +1 -1
  78. package/dashboard/dist/assets/McpRunDetailPage-Cra0nQSw.js +2 -0
  79. package/dashboard/dist/assets/McpRunDetailPage-Cra0nQSw.js.map +1 -0
  80. package/dashboard/dist/assets/{McpRunsPage-MUYvUYqz.js → McpRunsPage-BlgcGN3k.js} +2 -2
  81. package/dashboard/dist/assets/{McpRunsPage-MUYvUYqz.js.map → McpRunsPage-BlgcGN3k.js.map} +1 -1
  82. package/dashboard/dist/assets/{OperatorDashboard-Rih1SZrn.js → OperatorDashboard-BbO6cWzb.js} +2 -2
  83. package/dashboard/dist/assets/{OperatorDashboard-Rih1SZrn.js.map → OperatorDashboard-BbO6cWzb.js.map} +1 -1
  84. package/dashboard/dist/assets/{PageHeader-Bo0SpcCK.js → PageHeader-B_gV_jKk.js} +2 -2
  85. package/dashboard/dist/assets/{PageHeader-Bo0SpcCK.js.map → PageHeader-B_gV_jKk.js.map} +1 -1
  86. package/dashboard/dist/assets/{PageHeaderWithStats-7K5BdhOj.js → PageHeaderWithStats-D0I0nrnx.js} +2 -2
  87. package/dashboard/dist/assets/{PageHeaderWithStats-7K5BdhOj.js.map → PageHeaderWithStats-D0I0nrnx.js.map} +1 -1
  88. package/dashboard/dist/assets/ProcessDetailPage-s_iV8ICg.js +2 -0
  89. package/dashboard/dist/assets/{ProcessDetailPage-BMkWCjqD.js.map → ProcessDetailPage-s_iV8ICg.js.map} +1 -1
  90. package/dashboard/dist/assets/{ProcessesListPage-vZjUSc7S.js → ProcessesListPage-MnLMnxAa.js} +2 -2
  91. package/dashboard/dist/assets/{ProcessesListPage-vZjUSc7S.js.map → ProcessesListPage-MnLMnxAa.js.map} +1 -1
  92. package/dashboard/dist/assets/{RolePill-BDzPFQUv.js → RolePill-BOBytzrP.js} +2 -2
  93. package/dashboard/dist/assets/{RolePill-BDzPFQUv.js.map → RolePill-BOBytzrP.js.map} +1 -1
  94. package/dashboard/dist/assets/{RolesPage-kjeAsj3_.js → RolesPage-BH7KASM7.js} +2 -2
  95. package/dashboard/dist/assets/{RolesPage-kjeAsj3_.js.map → RolesPage-BH7KASM7.js.map} +1 -1
  96. package/dashboard/dist/assets/{RunAsSelector-DC4SLtTq.js → RunAsSelector-_QbJKhlo.js} +2 -2
  97. package/dashboard/dist/assets/{RunAsSelector-DC4SLtTq.js.map → RunAsSelector-_QbJKhlo.js.map} +1 -1
  98. package/dashboard/dist/assets/{ServerName-CEOFF7UG.js → ServerName-uqa4eBqm.js} +2 -2
  99. package/dashboard/dist/assets/{ServerName-CEOFF7UG.js.map → ServerName-uqa4eBqm.js.map} +1 -1
  100. package/dashboard/dist/assets/SwimlaneTimeline-og79Llvs.js +2 -0
  101. package/dashboard/dist/assets/SwimlaneTimeline-og79Llvs.js.map +1 -0
  102. package/dashboard/dist/assets/{TagInput-VBY0xIwb.js → TagInput-D3f11sbM.js} +2 -2
  103. package/dashboard/dist/assets/{TagInput-VBY0xIwb.js.map → TagInput-D3f11sbM.js.map} +1 -1
  104. package/dashboard/dist/assets/{TaskDetailPage-C0AlG_2t.js → TaskDetailPage-DPV4ySd9.js} +2 -2
  105. package/dashboard/dist/assets/{TaskDetailPage-C0AlG_2t.js.map → TaskDetailPage-DPV4ySd9.js.map} +1 -1
  106. package/dashboard/dist/assets/{TaskQueuePill-DZykFijh.js → TaskQueuePill-Bc45J7X1.js} +2 -2
  107. package/dashboard/dist/assets/{TaskQueuePill-DZykFijh.js.map → TaskQueuePill-Bc45J7X1.js.map} +1 -1
  108. package/dashboard/dist/assets/{TasksListPage-69ZWCaCP.js → TasksListPage-BYj3OqUi.js} +2 -2
  109. package/dashboard/dist/assets/{TasksListPage-69ZWCaCP.js.map → TasksListPage-BYj3OqUi.js.map} +1 -1
  110. package/dashboard/dist/assets/TimeAgo-W7TdJpV-.js +2 -0
  111. package/dashboard/dist/assets/{TimeAgo-CttiZG0k.js.map → TimeAgo-W7TdJpV-.js.map} +1 -1
  112. package/dashboard/dist/assets/{TimestampCell-CYFbEhqc.js → TimestampCell-Bi2nc9Q_.js} +2 -2
  113. package/dashboard/dist/assets/{TimestampCell-CYFbEhqc.js.map → TimestampCell-Bi2nc9Q_.js.map} +1 -1
  114. package/dashboard/dist/assets/{ToolPill-RP2Tvlrx.js → ToolPill-CuoXcmhv.js} +2 -2
  115. package/dashboard/dist/assets/{ToolPill-RP2Tvlrx.js.map → ToolPill-CuoXcmhv.js.map} +1 -1
  116. package/dashboard/dist/assets/ToolTestPanel-Dl3C53zb.js +2 -0
  117. package/dashboard/dist/assets/ToolTestPanel-Dl3C53zb.js.map +1 -0
  118. package/dashboard/dist/assets/{TopicDetailPage-Aq4-6GLl.js → TopicDetailPage-CjaZn4WP.js} +2 -2
  119. package/dashboard/dist/assets/{TopicDetailPage-Aq4-6GLl.js.map → TopicDetailPage-CjaZn4WP.js.map} +1 -1
  120. package/dashboard/dist/assets/{TopicsPage-BYFKjRY_.js → TopicsPage-BfsJEC1p.js} +2 -2
  121. package/dashboard/dist/assets/{TopicsPage-BYFKjRY_.js.map → TopicsPage-BfsJEC1p.js.map} +1 -1
  122. package/dashboard/dist/assets/{UserName-C4_T5-rI.js → UserName-b4baWHM_.js} +2 -2
  123. package/dashboard/dist/assets/{UserName-C4_T5-rI.js.map → UserName-b4baWHM_.js.map} +1 -1
  124. package/dashboard/dist/assets/WorkflowExecutionPage-BGmJnXnk.js +2 -0
  125. package/dashboard/dist/assets/WorkflowExecutionPage-BGmJnXnk.js.map +1 -0
  126. package/dashboard/dist/assets/WorkflowPill-Bg2-0Hkg.js +2 -0
  127. package/dashboard/dist/assets/WorkflowPill-Bg2-0Hkg.js.map +1 -0
  128. package/dashboard/dist/assets/{WorkflowsDashboard-_LMWc-OC.js → WorkflowsDashboard-BzH7jMRu.js} +2 -2
  129. package/dashboard/dist/assets/{WorkflowsDashboard-_LMWc-OC.js.map → WorkflowsDashboard-BzH7jMRu.js.map} +1 -1
  130. package/dashboard/dist/assets/{WorkflowsOverview-DFrfw554.js → WorkflowsOverview-BcUgBvjD.js} +2 -2
  131. package/dashboard/dist/assets/{WorkflowsOverview-DFrfw554.js.map → WorkflowsOverview-BcUgBvjD.js.map} +1 -1
  132. package/dashboard/dist/assets/{YamlWorkflowsPage-CZzGwfol.js → YamlWorkflowsPage-OhpCQJ0l.js} +2 -2
  133. package/dashboard/dist/assets/{YamlWorkflowsPage-CZzGwfol.js.map → YamlWorkflowsPage-OhpCQJ0l.js.map} +1 -1
  134. package/dashboard/dist/assets/{agents-CsKILVSU.js → agents-Ce3HmPz4.js} +2 -2
  135. package/dashboard/dist/assets/{agents-CsKILVSU.js.map → agents-Ce3HmPz4.js.map} +1 -1
  136. package/dashboard/dist/assets/{bots-BzEs6Q9L.js → bots-B0BomNnf.js} +2 -2
  137. package/dashboard/dist/assets/{bots-BzEs6Q9L.js.map → bots-B0BomNnf.js.map} +1 -1
  138. package/dashboard/dist/assets/capabilities-t-w5N9K9.js +2 -0
  139. package/dashboard/dist/assets/capabilities-t-w5N9K9.js.map +1 -0
  140. package/dashboard/dist/assets/{controlplane-COYEIIAz.js → controlplane-BrtAZnJM.js} +2 -2
  141. package/dashboard/dist/assets/{controlplane-COYEIIAz.js.map → controlplane-BrtAZnJM.js.map} +1 -1
  142. package/dashboard/dist/assets/{escalation-BZjS2202.js → escalation-DilnDxw2.js} +2 -2
  143. package/dashboard/dist/assets/{escalation-BZjS2202.js.map → escalation-DilnDxw2.js.map} +1 -1
  144. package/dashboard/dist/assets/{escalation-columns-DtRVmPSB.js → escalation-columns-C0slywOY.js} +2 -2
  145. package/dashboard/dist/assets/{escalation-columns-DtRVmPSB.js.map → escalation-columns-C0slywOY.js.map} +1 -1
  146. package/dashboard/dist/assets/{helpers-BngVEys5.js → helpers-BMvPqQr8.js} +2 -2
  147. package/dashboard/dist/assets/{helpers-BngVEys5.js.map → helpers-BMvPqQr8.js.map} +1 -1
  148. package/dashboard/dist/assets/{index-DxMNiFPS.js → index-30-pN97P.js} +2 -2
  149. package/dashboard/dist/assets/{index-DxMNiFPS.js.map → index-30-pN97P.js.map} +1 -1
  150. package/dashboard/dist/assets/index-BPxglOYm.css +1 -0
  151. package/dashboard/dist/assets/{index-R61-yG56.js → index-Bl9wzQ8Q.js} +2 -2
  152. package/dashboard/dist/assets/{index-R61-yG56.js.map → index-Bl9wzQ8Q.js.map} +1 -1
  153. package/dashboard/dist/assets/{index-ABsZZf_U.js → index-BxOuF0hm.js} +2 -2
  154. package/dashboard/dist/assets/{index-ABsZZf_U.js.map → index-BxOuF0hm.js.map} +1 -1
  155. package/dashboard/dist/assets/{index-BCsShN2l.js → index-Ck2QdJXT.js} +2 -2
  156. package/dashboard/dist/assets/{index-BCsShN2l.js.map → index-Ck2QdJXT.js.map} +1 -1
  157. package/dashboard/dist/assets/{index-xgl431mG.js → index-DNmlrCAp.js} +2 -2
  158. package/dashboard/dist/assets/{index-xgl431mG.js.map → index-DNmlrCAp.js.map} +1 -1
  159. package/dashboard/dist/assets/index-DPW_i3fH.js +6 -0
  160. package/dashboard/dist/assets/index-DPW_i3fH.js.map +1 -0
  161. package/dashboard/dist/assets/{index-DcpCR9c_.js → index-DZX-E_3q.js} +24 -24
  162. package/dashboard/dist/assets/index-DZX-E_3q.js.map +1 -0
  163. package/dashboard/dist/assets/{index-DykjJxzr.js → index-D_wqdvG_.js} +2 -2
  164. package/dashboard/dist/assets/{index-DykjJxzr.js.map → index-D_wqdvG_.js.map} +1 -1
  165. package/dashboard/dist/assets/{index-Bq5MSkCL.js → index-DnsVYMMg.js} +2 -2
  166. package/dashboard/dist/assets/{index-Bq5MSkCL.js.map → index-DnsVYMMg.js.map} +1 -1
  167. package/dashboard/dist/assets/{index-BwivT39P.js → index-H5TlloTk.js} +2 -2
  168. package/dashboard/dist/assets/{index-BwivT39P.js.map → index-H5TlloTk.js.map} +1 -1
  169. package/dashboard/dist/assets/{index-ByxH4qQ-.js → index-f-0Duls3.js} +2 -2
  170. package/dashboard/dist/assets/{index-ByxH4qQ-.js.map → index-f-0Duls3.js.map} +1 -1
  171. package/dashboard/dist/assets/{index-COgyD_H2.js → index-pIMl0mYp.js} +2 -2
  172. package/dashboard/dist/assets/{index-COgyD_H2.js.map → index-pIMl0mYp.js.map} +1 -1
  173. package/dashboard/dist/assets/{index-Byp8BDPs.js → index-qNuxC8kX.js} +2 -2
  174. package/dashboard/dist/assets/{index-Byp8BDPs.js.map → index-qNuxC8kX.js.map} +1 -1
  175. package/dashboard/dist/assets/{knowledge-DhCbDgy4.js → knowledge-D01NdF5h.js} +2 -2
  176. package/dashboard/dist/assets/{knowledge-DhCbDgy4.js.map → knowledge-D01NdF5h.js.map} +1 -1
  177. package/dashboard/dist/assets/{mcp-xh7T0I-f.js → mcp-CjXjDZI0.js} +2 -2
  178. package/dashboard/dist/assets/{mcp-xh7T0I-f.js.map → mcp-CjXjDZI0.js.map} +1 -1
  179. package/dashboard/dist/assets/{mcp-query-il3CfU3U.js → mcp-query-LlKQcWLJ.js} +2 -2
  180. package/dashboard/dist/assets/{mcp-query-il3CfU3U.js.map → mcp-query-LlKQcWLJ.js.map} +1 -1
  181. package/dashboard/dist/assets/{mcp-runs-4fyRpegc.js → mcp-runs-C0C54hU6.js} +2 -2
  182. package/dashboard/dist/assets/{mcp-runs-4fyRpegc.js.map → mcp-runs-C0C54hU6.js.map} +1 -1
  183. package/dashboard/dist/assets/{namespaces-BBTvHnRF.js → namespaces-6qWDXXJV.js} +2 -2
  184. package/dashboard/dist/assets/{namespaces-BBTvHnRF.js.map → namespaces-6qWDXXJV.js.map} +1 -1
  185. package/dashboard/dist/assets/{roles-D7bx5FAM.js → roles-Dtj0uabn.js} +2 -2
  186. package/dashboard/dist/assets/{roles-D7bx5FAM.js.map → roles-Dtj0uabn.js.map} +1 -1
  187. package/dashboard/dist/assets/{tasks-BgxRbhVM.js → tasks-BevFBjZq.js} +2 -2
  188. package/dashboard/dist/assets/{tasks-BgxRbhVM.js.map → tasks-BevFBjZq.js.map} +1 -1
  189. package/dashboard/dist/assets/{topics-CTtCboHe.js → topics-BMG5tx2g.js} +2 -2
  190. package/dashboard/dist/assets/{topics-CTtCboHe.js.map → topics-BMG5tx2g.js.map} +1 -1
  191. package/dashboard/dist/assets/useEventHooks-CPyvFlVR.js +2 -0
  192. package/dashboard/dist/assets/useEventHooks-CPyvFlVR.js.map +1 -0
  193. package/dashboard/dist/assets/{useYamlActivityEvents-CSMX9He5.js → useYamlActivityEvents-Bll8NPNQ.js} +2 -2
  194. package/dashboard/dist/assets/{useYamlActivityEvents-CSMX9He5.js.map → useYamlActivityEvents-Bll8NPNQ.js.map} +1 -1
  195. package/dashboard/dist/assets/{users-CyF-5WLI.js → users-XZ349b0r.js} +2 -2
  196. package/dashboard/dist/assets/{users-CyF-5WLI.js.map → users-XZ349b0r.js.map} +1 -1
  197. package/dashboard/dist/assets/{vendor-icons-BNtvBbnj.js → vendor-icons-B_Yla7iD.js} +2 -2
  198. package/dashboard/dist/assets/{vendor-icons-BNtvBbnj.js.map → vendor-icons-B_Yla7iD.js.map} +1 -1
  199. package/dashboard/dist/assets/{workflows-Bf4_w24H.js → workflows-Do-Eiv8f.js} +2 -2
  200. package/dashboard/dist/assets/{workflows-Bf4_w24H.js.map → workflows-Do-Eiv8f.js.map} +1 -1
  201. package/dashboard/dist/assets/{yaml-workflows-Cp1N0NMK.js → yaml-workflows-DolGRQ5f.js} +2 -2
  202. package/dashboard/dist/assets/{yaml-workflows-Cp1N0NMK.js.map → yaml-workflows-DolGRQ5f.js.map} +1 -1
  203. package/dashboard/dist/index.html +3 -3
  204. package/docs/agents.md +9 -9
  205. package/docs/api/http/agents.md +12 -10
  206. package/docs/api/http/settings.md +4 -0
  207. package/docs/api/sdk/agents.md +4 -2
  208. package/docs/api/sdk/settings.md +2 -1
  209. package/docs/dashboard.md +1 -1
  210. package/package.json +2 -2
  211. package/dashboard/dist/assets/AgentConfigPage-D52KyJY-.js +0 -13
  212. package/dashboard/dist/assets/AgentConfigPage-D52KyJY-.js.map +0 -1
  213. package/dashboard/dist/assets/AgentDetailPage-Cbo_qrYF.js +0 -4
  214. package/dashboard/dist/assets/AgentDetailPage-Cbo_qrYF.js.map +0 -1
  215. package/dashboard/dist/assets/AgentsPage-CvuF8--H.js +0 -2
  216. package/dashboard/dist/assets/AgentsPage-CvuF8--H.js.map +0 -1
  217. package/dashboard/dist/assets/AvailableEscalationsPage-UzjXcO3W.js +0 -2
  218. package/dashboard/dist/assets/CapabilitiesPage-D1QEHMKw.js +0 -2
  219. package/dashboard/dist/assets/CapabilitiesPage-D1QEHMKw.js.map +0 -1
  220. package/dashboard/dist/assets/CopyableId-DmLF-RqZ.js +0 -2
  221. package/dashboard/dist/assets/CopyableId-DmLF-RqZ.js.map +0 -1
  222. package/dashboard/dist/assets/CronLabel-5HPAmciI.js.map +0 -1
  223. package/dashboard/dist/assets/CustomDurationPicker-5JzEgS7I.js +0 -2
  224. package/dashboard/dist/assets/ElapsedCell-B79BF5Mj.js +0 -2
  225. package/dashboard/dist/assets/McpRunDetailPage-CXXRgMmJ.js +0 -2
  226. package/dashboard/dist/assets/McpRunDetailPage-CXXRgMmJ.js.map +0 -1
  227. package/dashboard/dist/assets/ProcessDetailPage-BMkWCjqD.js +0 -2
  228. package/dashboard/dist/assets/SwimlaneTimeline-MUUXgT3o.js +0 -2
  229. package/dashboard/dist/assets/SwimlaneTimeline-MUUXgT3o.js.map +0 -1
  230. package/dashboard/dist/assets/TimeAgo-CttiZG0k.js +0 -2
  231. package/dashboard/dist/assets/ToolTestPanel-CY_PLZSe.js +0 -2
  232. package/dashboard/dist/assets/ToolTestPanel-CY_PLZSe.js.map +0 -1
  233. package/dashboard/dist/assets/WorkflowExecutionPage-DUSTBasv.js +0 -2
  234. package/dashboard/dist/assets/WorkflowExecutionPage-DUSTBasv.js.map +0 -1
  235. package/dashboard/dist/assets/WorkflowPill-pPuGH8v9.js +0 -2
  236. package/dashboard/dist/assets/WorkflowPill-pPuGH8v9.js.map +0 -1
  237. package/dashboard/dist/assets/index-DXEYynKO.css +0 -1
  238. package/dashboard/dist/assets/index-DcpCR9c_.js.map +0 -1
  239. package/dashboard/dist/assets/index-DuPY59Yu.js +0 -5
  240. package/dashboard/dist/assets/index-DuPY59Yu.js.map +0 -1
  241. package/dashboard/dist/assets/settings-nt6qyR1S.js +0 -2
  242. package/dashboard/dist/assets/settings-nt6qyR1S.js.map +0 -1
  243. package/dashboard/dist/assets/useEventHooks-CkJOmbF-.js +0 -2
  244. package/dashboard/dist/assets/useEventHooks-CkJOmbF-.js.map +0 -1
@@ -6,6 +6,7 @@ const events_1 = require("../lib/events");
6
6
  const nats_1 = require("../lib/events/nats");
7
7
  const socketio_1 = require("../lib/events/socketio");
8
8
  const defaults_1 = require("../modules/defaults");
9
+ const llm_1 = require("../services/llm");
9
10
  /**
10
11
  * Return platform settings for the current deployment.
11
12
  *
@@ -39,6 +40,9 @@ async function getSettings() {
39
40
  ? (process.env.VITE_NATS_WS_URL || process.env.NATS_WS_URL || null)
40
41
  : null,
41
42
  },
43
+ ai: {
44
+ enabled: (0, llm_1.hasLLMApiKey)(),
45
+ },
42
46
  },
43
47
  };
44
48
  }
@@ -8,11 +8,5 @@ export declare function closePool(): Promise<void>;
8
8
  */
9
9
  export declare function getConnection(): {
10
10
  class: typeof Client;
11
- options: {
12
- host: string;
13
- port: number;
14
- user: string;
15
- password: string;
16
- database: string;
17
- };
11
+ options: Record<string, unknown>;
18
12
  };
@@ -0,0 +1,12 @@
1
+ -- Add 'capability' reaction type and server_id/tool_name columns
2
+ -- for late-binding MCP tool invocation via agent subscriptions.
3
+
4
+ ALTER TABLE lt_agent_subscriptions
5
+ DROP CONSTRAINT IF EXISTS lt_agent_subscriptions_reaction_type_check;
6
+
7
+ ALTER TABLE lt_agent_subscriptions
8
+ ADD CONSTRAINT lt_agent_subscriptions_reaction_type_check
9
+ CHECK (reaction_type IN ('durable', 'pipeline', 'mcp_query', 'capability'));
10
+
11
+ ALTER TABLE lt_agent_subscriptions ADD COLUMN IF NOT EXISTS server_id TEXT;
12
+ ALTER TABLE lt_agent_subscriptions ADD COLUMN IF NOT EXISTS tool_name TEXT;
@@ -0,0 +1,10 @@
1
+ -- Add 'file' to the topic catalog category check constraint.
2
+
3
+ ALTER TABLE lt_topic_catalog
4
+ DROP CONSTRAINT IF EXISTS lt_topic_catalog_category_check;
5
+
6
+ ALTER TABLE lt_topic_catalog
7
+ ADD CONSTRAINT lt_topic_catalog_category_check
8
+ CHECK (category IN (
9
+ 'task','workflow','escalation','activity','knowledge','file','agent','app','milestone'
10
+ ));
@@ -31,6 +31,15 @@ declare class LTEventRegistry {
31
31
  * Return the first registered adapter that matches the given type.
32
32
  */
33
33
  getAdapter<T extends LTEventAdapter>(ctor: new (...args: any[]) => T): T | undefined;
34
+ /**
35
+ * Bridge cross-container events to the in-process callback adapter.
36
+ *
37
+ * Iterates all registered adapters and calls `setCallbackBridge()` on
38
+ * any that implement it. This is the generic contract — any transport
39
+ * adapter (NATS, SNS, GCP Pub/Sub, Kafka) that supports cross-process
40
+ * delivery implements `setCallbackBridge` on the LTEventAdapter interface.
41
+ */
42
+ bridgeCallbackAdapter(callbackAdapter: LTEventAdapter): void;
34
43
  }
35
44
  /** Singleton event registry */
36
45
  export declare const eventRegistry: LTEventRegistry;
@@ -59,6 +59,21 @@ class LTEventRegistry {
59
59
  getAdapter(ctor) {
60
60
  return this.adapters.find((a) => a instanceof ctor);
61
61
  }
62
+ /**
63
+ * Bridge cross-container events to the in-process callback adapter.
64
+ *
65
+ * Iterates all registered adapters and calls `setCallbackBridge()` on
66
+ * any that implement it. This is the generic contract — any transport
67
+ * adapter (NATS, SNS, GCP Pub/Sub, Kafka) that supports cross-process
68
+ * delivery implements `setCallbackBridge` on the LTEventAdapter interface.
69
+ */
70
+ bridgeCallbackAdapter(callbackAdapter) {
71
+ for (const adapter of this.adapters) {
72
+ if (adapter !== callbackAdapter && typeof adapter.setCallbackBridge === 'function') {
73
+ adapter.setCallbackBridge(callbackAdapter);
74
+ }
75
+ }
76
+ }
62
77
  }
63
78
  /** Singleton event registry */
64
79
  exports.eventRegistry = new LTEventRegistry();
@@ -1,10 +1,16 @@
1
1
  import type { LTEvent, LTEventAdapter } from '../../types';
2
2
  /**
3
- * NATS event adapter — reference implementation.
3
+ * NATS event adapter — publish AND subscribe.
4
4
  *
5
5
  * Publishes LTEvent payloads as JSON to NATS subjects
6
6
  * following the pattern: `{subjectPrefix}.{event.type}`
7
7
  *
8
+ * When a CallbackEventAdapter is bridged via `setCallbackBridge()`,
9
+ * this adapter also subscribes to `{subjectPrefix}.>` and forwards
10
+ * events from other containers to the local callback adapter.
11
+ * An `_originId` field prevents the publishing container from
12
+ * re-dispatching its own events.
13
+ *
8
14
  * Usage:
9
15
  * ```typescript
10
16
  * import { eventRegistry, NatsEventAdapter } from '@hotmeshio/long-tail';
@@ -15,14 +21,22 @@ import type { LTEvent, LTEventAdapter } from '../../types';
15
21
  */
16
22
  export declare class NatsEventAdapter implements LTEventAdapter {
17
23
  private nc;
24
+ private sub;
18
25
  private url;
19
26
  private subjectPrefix;
20
27
  private token?;
28
+ private originId;
29
+ private callbackAdapter;
21
30
  constructor(options?: {
22
31
  url?: string;
23
32
  subjectPrefix?: string;
24
33
  token?: string;
25
34
  });
35
+ /**
36
+ * Bridge NATS → local callback adapter for cross-container dispatch.
37
+ * Part of the LTEventAdapter contract. Call before `connect()`.
38
+ */
39
+ setCallbackBridge(adapter: LTEventAdapter): void;
26
40
  connect(): Promise<void>;
27
41
  publish(event: LTEvent): Promise<void>;
28
42
  disconnect(): Promise<void>;
@@ -1,16 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NatsEventAdapter = void 0;
4
+ const crypto_1 = require("crypto");
4
5
  const nats_1 = require("nats");
5
6
  const config_1 = require("../../modules/config");
6
7
  const logger_1 = require("../logger");
7
8
  const sc = (0, nats_1.StringCodec)();
8
9
  /**
9
- * NATS event adapter — reference implementation.
10
+ * NATS event adapter — publish AND subscribe.
10
11
  *
11
12
  * Publishes LTEvent payloads as JSON to NATS subjects
12
13
  * following the pattern: `{subjectPrefix}.{event.type}`
13
14
  *
15
+ * When a CallbackEventAdapter is bridged via `setCallbackBridge()`,
16
+ * this adapter also subscribes to `{subjectPrefix}.>` and forwards
17
+ * events from other containers to the local callback adapter.
18
+ * An `_originId` field prevents the publishing container from
19
+ * re-dispatching its own events.
20
+ *
14
21
  * Usage:
15
22
  * ```typescript
16
23
  * import { eventRegistry, NatsEventAdapter } from '@hotmeshio/long-tail';
@@ -22,24 +29,59 @@ const sc = (0, nats_1.StringCodec)();
22
29
  class NatsEventAdapter {
23
30
  constructor(options) {
24
31
  this.nc = null;
32
+ this.sub = null;
33
+ this.originId = (0, crypto_1.randomUUID)();
34
+ this.callbackAdapter = null;
25
35
  this.url = options?.url || config_1.config.NATS_URL;
26
36
  this.subjectPrefix = options?.subjectPrefix || 'lt.events';
27
37
  this.token = options?.token || process.env.NATS_TOKEN || 'dev_api_secret';
28
38
  }
39
+ /**
40
+ * Bridge NATS → local callback adapter for cross-container dispatch.
41
+ * Part of the LTEventAdapter contract. Call before `connect()`.
42
+ */
43
+ setCallbackBridge(adapter) {
44
+ this.callbackAdapter = adapter;
45
+ }
29
46
  async connect() {
30
47
  this.nc = await (0, nats_1.connect)({
31
48
  servers: this.url,
32
49
  token: this.token,
33
50
  });
34
51
  logger_1.loggerRegistry.info(`[lt-events:nats] connected to ${this.url}`);
52
+ // Subscribe to all events for cross-container bridging
53
+ if (this.callbackAdapter) {
54
+ const adapter = this.callbackAdapter;
55
+ this.sub = this.nc.subscribe(`${this.subjectPrefix}.>`);
56
+ logger_1.loggerRegistry.info(`[lt-events:nats] subscribed to ${this.subjectPrefix}.> for cross-container bridge`);
57
+ (async () => {
58
+ for await (const msg of this.sub) {
59
+ try {
60
+ const event = JSON.parse(sc.decode(msg.data));
61
+ // Skip events that originated from this container
62
+ if (event._originId === this.originId)
63
+ continue;
64
+ adapter.publish(event);
65
+ }
66
+ catch {
67
+ // Malformed message — skip
68
+ }
69
+ }
70
+ })();
71
+ }
35
72
  }
36
73
  async publish(event) {
37
74
  if (!this.nc)
38
75
  return;
39
76
  const subject = `${this.subjectPrefix}.${event.type}`;
40
- this.nc.publish(subject, sc.encode(JSON.stringify(event)));
77
+ const enriched = { ...event, _originId: this.originId };
78
+ this.nc.publish(subject, sc.encode(JSON.stringify(enriched)));
41
79
  }
42
80
  async disconnect() {
81
+ if (this.sub) {
82
+ this.sub.unsubscribe();
83
+ this.sub = null;
84
+ }
43
85
  if (this.nc) {
44
86
  await this.nc.drain();
45
87
  this.nc = null;
@@ -66,6 +66,16 @@ export declare function publishKnowledgeEvent(params: {
66
66
  domain: string;
67
67
  key: string;
68
68
  }): Promise<void>;
69
+ /**
70
+ * Publish a file storage event (stored, deleted).
71
+ * Includes rich metadata: path, name, extension, mime type, size.
72
+ */
73
+ export declare function publishFileEvent(params: {
74
+ type: 'file.stored' | 'file.deleted';
75
+ path: string;
76
+ size?: number;
77
+ mime?: string;
78
+ }): Promise<void>;
69
79
  /**
70
80
  * Publish an agent lifecycle event.
71
81
  */
@@ -5,6 +5,7 @@ exports.publishTaskEvent = publishTaskEvent;
5
5
  exports.publishEscalationEvent = publishEscalationEvent;
6
6
  exports.publishActivityEvent = publishActivityEvent;
7
7
  exports.publishKnowledgeEvent = publishKnowledgeEvent;
8
+ exports.publishFileEvent = publishFileEvent;
8
9
  exports.publishAgentEvent = publishAgentEvent;
9
10
  exports.publishWorkflowEvent = publishWorkflowEvent;
10
11
  const index_1 = require("./index");
@@ -105,6 +106,33 @@ function publishKnowledgeEvent(params) {
105
106
  timestamp: new Date().toISOString(),
106
107
  });
107
108
  }
109
+ /**
110
+ * Publish a file storage event (stored, deleted).
111
+ * Includes rich metadata: path, name, extension, mime type, size.
112
+ */
113
+ function publishFileEvent(params) {
114
+ const parsed = params.path.split('/');
115
+ const filename = parsed[parsed.length - 1] || '';
116
+ const dotIdx = filename.lastIndexOf('.');
117
+ const name = dotIdx > 0 ? filename.slice(0, dotIdx) : filename;
118
+ const extension = dotIdx > 0 ? filename.slice(dotIdx + 1) : '';
119
+ return fireAndForget({
120
+ type: params.type,
121
+ source: 'file-storage',
122
+ workflowId: '',
123
+ workflowName: '',
124
+ taskQueue: '',
125
+ data: {
126
+ path: params.path,
127
+ name,
128
+ extension,
129
+ filename,
130
+ mime: params.mime,
131
+ size: params.size,
132
+ },
133
+ timestamp: new Date().toISOString(),
134
+ });
135
+ }
108
136
  /**
109
137
  * Publish an agent lifecycle event.
110
138
  */
@@ -10,10 +10,4 @@ export declare const config: {
10
10
  JWT_SECRET: string;
11
11
  HONEYCOMB_API_KEY: string;
12
12
  };
13
- export declare const postgres_options: {
14
- host: string;
15
- port: number;
16
- user: string;
17
- password: string;
18
- database: string;
19
- };
13
+ export declare const postgres_options: Record<string, unknown>;
@@ -1,7 +1,7 @@
1
1
  export declare const LIST_SUBSCRIPTIONS = "\n SELECT * FROM lt_agent_subscriptions\n WHERE agent_id = $1\n ORDER BY created_at\n";
2
2
  export declare const GET_SUBSCRIPTION = "\n SELECT * FROM lt_agent_subscriptions WHERE id = $1\n";
3
- export declare const INSERT_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)\n RETURNING *\n";
4
- export declare const UPDATE_SUBSCRIPTION = "\n UPDATE lt_agent_subscriptions SET\n topic = COALESCE($2, topic),\n filter = COALESCE($3, filter),\n reaction_type = COALESCE($4, reaction_type),\n workflow_type = COALESCE($5, workflow_type),\n pipeline_id = COALESCE($6, pipeline_id),\n mcp_prompt = COALESCE($7, mcp_prompt),\n input_mapping = COALESCE($8, input_mapping),\n execute_as = COALESCE($9, execute_as),\n enabled = COALESCE($10, enabled)\n WHERE id = $1\n RETURNING *\n";
3
+ export declare const INSERT_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled, server_id, tool_name)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\n RETURNING *\n";
4
+ export declare const UPDATE_SUBSCRIPTION = "\n UPDATE lt_agent_subscriptions SET\n topic = COALESCE($2, topic),\n filter = COALESCE($3, filter),\n reaction_type = COALESCE($4, reaction_type),\n workflow_type = COALESCE($5, workflow_type),\n pipeline_id = COALESCE($6, pipeline_id),\n mcp_prompt = COALESCE($7, mcp_prompt),\n input_mapping = COALESCE($8, input_mapping),\n execute_as = COALESCE($9, execute_as),\n enabled = COALESCE($10, enabled),\n server_id = COALESCE($11, server_id),\n tool_name = COALESCE($12, tool_name)\n WHERE id = $1\n RETURNING *\n";
5
5
  export declare const DELETE_SUBSCRIPTION = "\n DELETE FROM lt_agent_subscriptions WHERE id = $1\n";
6
- export declare const SEED_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true)\n ON CONFLICT (agent_id, topic) DO NOTHING\n";
6
+ export declare const SEED_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled, server_id, tool_name)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)\n ON CONFLICT (agent_id, topic) DO NOTHING\n";
7
7
  export declare const LIST_ACTIVE_SUBSCRIPTIONS = "\n SELECT s.*, a.id AS agent_name, a.user_id AS agent_user_id\n FROM lt_agent_subscriptions s\n JOIN lt_agents a ON s.agent_id = a.id\n WHERE s.enabled = true AND a.status = 'active'\n ORDER BY s.created_at\n";
@@ -12,8 +12,8 @@ exports.GET_SUBSCRIPTION = `
12
12
  exports.INSERT_SUBSCRIPTION = `
13
13
  INSERT INTO lt_agent_subscriptions
14
14
  (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,
15
- input_mapping, execute_as, enabled)
16
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
15
+ input_mapping, execute_as, enabled, server_id, tool_name)
16
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
17
17
  RETURNING *
18
18
  `;
19
19
  exports.UPDATE_SUBSCRIPTION = `
@@ -26,7 +26,9 @@ exports.UPDATE_SUBSCRIPTION = `
26
26
  mcp_prompt = COALESCE($7, mcp_prompt),
27
27
  input_mapping = COALESCE($8, input_mapping),
28
28
  execute_as = COALESCE($9, execute_as),
29
- enabled = COALESCE($10, enabled)
29
+ enabled = COALESCE($10, enabled),
30
+ server_id = COALESCE($11, server_id),
31
+ tool_name = COALESCE($12, tool_name)
30
32
  WHERE id = $1
31
33
  RETURNING *
32
34
  `;
@@ -36,8 +38,8 @@ exports.DELETE_SUBSCRIPTION = `
36
38
  exports.SEED_SUBSCRIPTION = `
37
39
  INSERT INTO lt_agent_subscriptions
38
40
  (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,
39
- input_mapping, execute_as, enabled)
40
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true)
41
+ input_mapping, execute_as, enabled, server_id, tool_name)
42
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)
41
43
  ON CONFLICT (agent_id, topic) DO NOTHING
42
44
  `;
43
45
  exports.LIST_ACTIVE_SUBSCRIPTIONS = `
@@ -3,10 +3,12 @@ export interface AgentSubscription {
3
3
  agent_id: string;
4
4
  topic: string;
5
5
  filter?: Record<string, any>;
6
- reaction_type: 'durable' | 'pipeline' | 'mcp_query';
6
+ reaction_type: 'durable' | 'pipeline' | 'mcp_query' | 'capability';
7
7
  workflow_type?: string;
8
8
  pipeline_id?: string;
9
9
  mcp_prompt?: string;
10
+ server_id?: string;
11
+ tool_name?: string;
10
12
  input_mapping: Record<string, any>;
11
13
  execute_as?: string;
12
14
  enabled: boolean;
@@ -32,6 +32,8 @@ async function createSubscription(agentId, data) {
32
32
  JSON.stringify(data.input_mapping ?? {}),
33
33
  data.execute_as ?? null,
34
34
  data.enabled !== false,
35
+ data.server_id ?? null,
36
+ data.tool_name ?? null,
35
37
  ]);
36
38
  return rows[0];
37
39
  }
@@ -48,6 +50,8 @@ async function updateSubscription(id, data) {
48
50
  data.input_mapping ? JSON.stringify(data.input_mapping) : null,
49
51
  data.execute_as ?? null,
50
52
  data.enabled ?? null,
53
+ data.server_id ?? null,
54
+ data.tool_name ?? null,
51
55
  ]);
52
56
  return rows[0] ?? null;
53
57
  }
@@ -77,6 +81,8 @@ async function seedSubscription(agentId, data) {
77
81
  data.mcp_prompt ?? null,
78
82
  JSON.stringify(data.input_mapping ?? {}),
79
83
  data.execute_as ?? null,
84
+ data.server_id ?? null,
85
+ data.tool_name ?? null,
80
86
  ]);
81
87
  return (rowCount ?? 0) > 0;
82
88
  }
@@ -214,6 +214,7 @@ class AgentTriggerRegistry {
214
214
  data: mapped.data ?? mapped,
215
215
  execute_as: sub.execute_as ?? sub.agent_user_id ?? undefined,
216
216
  source: 'agent',
217
+ jobId: deterministicId,
217
218
  });
218
219
  break;
219
220
  }
@@ -226,6 +227,23 @@ class AgentTriggerRegistry {
226
227
  });
227
228
  break;
228
229
  }
230
+ case 'capability': {
231
+ logger_1.loggerRegistry.info(`[long-tail] agent capability: ${sub.agent_name} → ${sub.tool_name} on ${sub.server_id} (id=${deterministicId})`);
232
+ const { invokeWorkflow } = await Promise.resolve().then(() => __importStar(require('../workflow-invocation')));
233
+ await invokeWorkflow({
234
+ workflowType: 'capabilityInvoke',
235
+ data: {
236
+ serverId: sub.server_id,
237
+ toolName: sub.tool_name,
238
+ arguments: mapped,
239
+ },
240
+ metadata: { source: 'agent' },
241
+ executeAs: sub.execute_as ?? sub.agent_user_id ?? undefined,
242
+ options: { workflowId: deterministicId },
243
+ auth: { userId: sub.agent_user_id || 'lt-system', role: 'admin' },
244
+ });
245
+ break;
246
+ }
229
247
  }
230
248
  }
231
249
  }
@@ -158,6 +158,35 @@ const SYSTEM_TOPICS = [
158
158
  example_payload: { domain: 'orders', key: 'order-12345' },
159
159
  tags: ['lifecycle', 'knowledge'],
160
160
  },
161
+ // File storage
162
+ {
163
+ topic: 'file.stored',
164
+ description: 'A file has been written to storage.',
165
+ category: 'file',
166
+ payload_schema: objectSchema({
167
+ path: { type: 'string', description: 'File path in storage' },
168
+ name: { type: 'string', description: 'File name without extension' },
169
+ extension: { type: 'string', description: 'File extension (without dot)' },
170
+ filename: { type: 'string', description: 'Full filename with extension' },
171
+ mime: { type: 'string', description: 'MIME type' },
172
+ size: { type: 'number', description: 'File size in bytes' },
173
+ }),
174
+ example_payload: { path: '/images/photo.jpg', name: 'photo', extension: 'jpg', filename: 'photo.jpg', mime: 'image/jpeg', size: 245760 },
175
+ tags: ['lifecycle', 'file', 'storage'],
176
+ },
177
+ {
178
+ topic: 'file.deleted',
179
+ description: 'A file has been removed from storage.',
180
+ category: 'file',
181
+ payload_schema: objectSchema({
182
+ path: { type: 'string', description: 'File path in storage' },
183
+ name: { type: 'string', description: 'File name without extension' },
184
+ extension: { type: 'string', description: 'File extension (without dot)' },
185
+ filename: { type: 'string', description: 'Full filename with extension' },
186
+ }),
187
+ example_payload: { path: '/images/photo.jpg', name: 'photo', extension: 'jpg', filename: 'photo.jpg' },
188
+ tags: ['lifecycle', 'file', 'storage'],
189
+ },
161
190
  // Agent lifecycle
162
191
  {
163
192
  topic: 'agent.started',
@@ -30,7 +30,7 @@ export declare function activateYamlWorkflow(appId: string, version: string): Pr
30
30
  /**
31
31
  * Invoke a YAML workflow (fire-and-forget). Returns the job ID.
32
32
  */
33
- export declare function invokeYamlWorkflow(appId: string, topic: string, data: Record<string, unknown>, entity?: string): Promise<string>;
33
+ export declare function invokeYamlWorkflow(appId: string, topic: string, data: Record<string, unknown>, entity?: string, context?: Record<string, any>): Promise<string>;
34
34
  /**
35
35
  * Invoke a YAML workflow and wait for the result.
36
36
  *
@@ -136,9 +136,9 @@ async function activateYamlWorkflow(appId, version) {
136
136
  /**
137
137
  * Invoke a YAML workflow (fire-and-forget). Returns the job ID.
138
138
  */
139
- async function invokeYamlWorkflow(appId, topic, data, entity) {
139
+ async function invokeYamlWorkflow(appId, topic, data, entity, context) {
140
140
  const engine = await getEngine(appId);
141
- return engine.pub(topic, data, undefined, entity ? { entity } : undefined);
141
+ return engine.pub(topic, data, context, entity ? { entity } : undefined);
142
142
  }
143
143
  /**
144
144
  * Invoke a YAML workflow and wait for the result.
@@ -7,6 +7,8 @@ interface InvokeOptions {
7
7
  userId?: string;
8
8
  /** Source identifier for metadata injection (e.g., 'cron') */
9
9
  source?: string;
10
+ /** Deterministic job ID for idempotent execution (agent subscriptions) */
11
+ jobId?: string;
10
12
  }
11
13
  /**
12
14
  * Invoke a YAML workflow with scope injection.
@@ -71,10 +71,14 @@ async function invokeYamlWorkflow(wf, options = {}) {
71
71
  data._metadata = {};
72
72
  data._metadata.source = options.source;
73
73
  }
74
+ // Build context with deterministic job ID when provided (agent subscriptions)
75
+ const context = options.jobId
76
+ ? { metadata: { jid: options.jobId } }
77
+ : undefined;
74
78
  if (options.sync) {
75
79
  const { job_id, result } = await yamlDeployer.invokeYamlWorkflowSync(wf.app_id, wf.graph_topic, data, options.timeout, wf.graph_topic);
76
80
  return { job_id, result };
77
81
  }
78
- const jobId = await yamlDeployer.invokeYamlWorkflow(wf.app_id, wf.graph_topic, data, wf.graph_topic);
82
+ const jobId = await yamlDeployer.invokeYamlWorkflow(wf.app_id, wf.graph_topic, data, wf.graph_topic, context);
79
83
  return { job_id: jobId };
80
84
  }
@@ -8,7 +8,6 @@ const honeycomb_1 = require("../lib/telemetry/honeycomb");
8
8
  const events_1 = require("../lib/events");
9
9
  const nats_1 = require("../lib/events/nats");
10
10
  const socketio_1 = require("../lib/events/socketio");
11
- const callback_1 = require("../lib/events/callback");
12
11
  const maintenance_1 = require("../services/maintenance");
13
12
  const maintenance_2 = require("../modules/maintenance");
14
13
  const mcp_1 = require("../services/mcp");
@@ -36,24 +35,27 @@ function registerAdapters(startConfig) {
36
35
  else if (startConfig.telemetry?.honeycomb) {
37
36
  telemetry_1.telemetryRegistry.register(new honeycomb_1.HoneycombTelemetryAdapter(startConfig.telemetry.honeycomb));
38
37
  }
39
- // Events — always register socket.io (zero-cost until HTTP server attaches).
40
- // NATS is additive: when configured, events publish to both transports.
38
+ // Events — register the configured transport.
39
+ // Socket.IO is the default for single-container ("nothing but Postgres").
40
+ // When NATS or custom adapters are configured, Socket.IO is NOT registered —
41
+ // the dashboard auto-detects the transport via GET /api/settings and connects
42
+ // directly (e.g., NATS WebSocket). Socket.IO never interferes in production.
41
43
  if (startConfig.events?.adapters) {
42
44
  for (const adapter of startConfig.events.adapters) {
43
45
  events_1.eventRegistry.register(adapter);
44
46
  }
45
47
  }
48
+ else if (startConfig.events?.nats) {
49
+ events_1.eventRegistry.register(new nats_1.NatsEventAdapter(startConfig.events.nats));
50
+ }
46
51
  else {
47
- if (startConfig.events?.nats) {
48
- events_1.eventRegistry.register(new nats_1.NatsEventAdapter(startConfig.events.nats));
49
- }
50
52
  events_1.eventRegistry.register(new socketio_1.SocketIOEventAdapter({
51
53
  authenticate: (0, socket_auth_1.createSocketIOAuthenticator)(startConfig),
52
54
  }));
53
55
  }
54
- // Always register the callback adapter for SDK event subscriptions.
55
- // Zero-cost when no listeners are registered.
56
- events_1.eventRegistry.register(new callback_1.CallbackEventAdapter());
56
+ // CallbackEventAdapter is registered later in start/workers.ts
57
+ // so it can be wired to the NATS bridge before connect().
58
+ // Do NOT register a duplicate here.
57
59
  // Maintenance
58
60
  if (startConfig.maintenance === false) {
59
61
  // Disabled
@@ -61,6 +61,10 @@ function applyDatabaseConfig(db) {
61
61
  database: db.database ?? config_1.postgres_options.database,
62
62
  });
63
63
  }
64
+ // SSL passthrough — applies to both connectionString and individual-field modes
65
+ if (db.ssl !== undefined) {
66
+ config_1.postgres_options.ssl = db.ssl;
67
+ }
64
68
  }
65
69
  /**
66
70
  * Apply server port and auth settings from the startup config.
@@ -278,11 +278,20 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
278
278
  }
279
279
  }
280
280
  }
281
- // Register the in-process callback adapter for agent event triggers
281
+ // Register the in-process callback adapter for agent event triggers.
282
+ // Reuse existing instance if already registered (e.g., from SDK createClient).
282
283
  const { CallbackEventAdapter } = await Promise.resolve().then(() => __importStar(require('../lib/events/callback')));
283
284
  const { agentTriggerRegistry } = await Promise.resolve().then(() => __importStar(require('../services/agent/trigger-registry')));
284
- const callbackAdapter = new CallbackEventAdapter();
285
- events_1.eventRegistry.register(callbackAdapter);
285
+ let callbackAdapter = events_1.eventRegistry.getAdapter(CallbackEventAdapter);
286
+ if (!callbackAdapter) {
287
+ callbackAdapter = new CallbackEventAdapter();
288
+ events_1.eventRegistry.register(callbackAdapter);
289
+ }
290
+ // Bridge cross-container events to the local callback adapter.
291
+ // Any transport adapter (NATS, SNS, GCP Pub/Sub, etc.) that implements
292
+ // setCallbackBridge() will subscribe to the bus and forward events
293
+ // from other containers so agent triggers fire locally.
294
+ events_1.eventRegistry.bridgeCallbackAdapter(callbackAdapter);
286
295
  // Connect event adapters (outside workers guard so API-only containers
287
296
  // still connect to NATS and can publish/receive events)
288
297
  if (events_1.eventRegistry.hasAdapters) {
@@ -71,6 +71,12 @@ const SYSTEM_WORKFLOW_BASE = {
71
71
  invocable: false,
72
72
  };
73
73
  const systemWorkflowConfigs = {
74
+ capabilityInvoke: {
75
+ defaultRole: ENGINEER,
76
+ roles: [],
77
+ invocable: true,
78
+ description: 'Late-binding MCP tool invocation — calls a single capability with idempotent execution',
79
+ },
74
80
  mcpTriageRouter: {
75
81
  ...SYSTEM_WORKFLOW_BASE,
76
82
  description: 'Triage router — discovers compiled workflows for remediation, routes to deterministic or dynamic triage',
@@ -110,6 +116,16 @@ const systemWorkflowConfigs = {
110
116
  };
111
117
  function getSystemWorkers() {
112
118
  const workers = [];
119
+ // Capability invoke — always available (no LLM required)
120
+ try {
121
+ const { capabilityInvoke } = require('./workflows/capability-invoke');
122
+ workers.push({
123
+ taskQueue: 'long-tail-system',
124
+ workflow: capabilityInvoke,
125
+ config: systemWorkflowConfigs.capabilityInvoke,
126
+ });
127
+ }
128
+ catch { /* module not available */ }
113
129
  const hasLLM = process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY;
114
130
  if (hasLLM) {
115
131
  const pairs = [