@hotmeshio/long-tail 0.4.14 → 0.4.16

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 (186) hide show
  1. package/build/adapters/express.js +14 -0
  2. package/build/api/escalations/claim.js +1 -10
  3. package/build/api/escalations/create.js +1 -11
  4. package/build/api/escalations/metadata.d.ts +2 -0
  5. package/build/api/escalations/metadata.js +6 -12
  6. package/build/api/escalations/resolve.js +4 -23
  7. package/build/api/settings.js +5 -6
  8. package/build/bin/ltc.js +2 -0
  9. package/build/index.js +2 -2
  10. package/build/lib/cli/commands/escalations.d.ts +2 -0
  11. package/build/lib/cli/commands/escalations.js +4 -0
  12. package/build/lib/events/nats-ws-proxy.d.ts +19 -0
  13. package/build/lib/events/nats-ws-proxy.js +68 -0
  14. package/build/lib/events/nats.d.ts +16 -0
  15. package/build/lib/events/nats.js +23 -1
  16. package/build/lib/events/publish.js +2 -0
  17. package/build/modules/config.d.ts +3 -0
  18. package/build/modules/config.js +3 -0
  19. package/build/routes/escalations/metadata.js +4 -2
  20. package/build/routes/nats-credentials.js +4 -4
  21. package/build/sdk/index.d.ts +2 -0
  22. package/build/services/escalation/crud.d.ts +1 -1
  23. package/build/services/escalation/crud.js +56 -6
  24. package/build/services/escalation/sql.d.ts +2 -2
  25. package/build/services/escalation/sql.js +5 -2
  26. package/build/services/interceptor/activities/escalation.js +1 -11
  27. package/build/services/interceptor/activities/task.js +2 -23
  28. package/build/services/interceptor/completion.js +2 -22
  29. package/build/services/interceptor/escalation.js +5 -44
  30. package/build/services/interceptor/index.js +26 -2
  31. package/build/services/interceptor/lifecycle.d.ts +1 -1
  32. package/build/services/interceptor/lifecycle.js +18 -32
  33. package/build/services/task/crud.js +36 -2
  34. package/build/start/index.js +14 -0
  35. package/build/tsconfig.tsbuildinfo +1 -1
  36. package/build/types/startup.d.ts +3 -0
  37. package/dashboard/dist/assets/{AdminDashboard-BuqyRY2r.js → AdminDashboard-Cfo0mwL2.js} +2 -2
  38. package/dashboard/dist/assets/{AdminDashboard-BuqyRY2r.js.map → AdminDashboard-Cfo0mwL2.js.map} +1 -1
  39. package/dashboard/dist/assets/{AgentConfigPage-Bum1dUIi.js → AgentConfigPage-DBtvb2x5.js} +2 -2
  40. package/dashboard/dist/assets/{AgentConfigPage-Bum1dUIi.js.map → AgentConfigPage-DBtvb2x5.js.map} +1 -1
  41. package/dashboard/dist/assets/{AgentDetailPage-0Kq-tBF2.js → AgentDetailPage-3mZA7SOb.js} +2 -2
  42. package/dashboard/dist/assets/{AgentDetailPage-0Kq-tBF2.js.map → AgentDetailPage-3mZA7SOb.js.map} +1 -1
  43. package/dashboard/dist/assets/{AgentsPage-B5gYDSOX.js → AgentsPage-CTVocfBb.js} +2 -2
  44. package/dashboard/dist/assets/{AgentsPage-B5gYDSOX.js.map → AgentsPage-CTVocfBb.js.map} +1 -1
  45. package/dashboard/dist/assets/{AvailableEscalationsPage-BWHThQDC.js → AvailableEscalationsPage-CA9x9o5s.js} +2 -2
  46. package/dashboard/dist/assets/{AvailableEscalationsPage-BWHThQDC.js.map → AvailableEscalationsPage-CA9x9o5s.js.map} +1 -1
  47. package/dashboard/dist/assets/{BotPicker-BQ336piW.js → BotPicker-BQp_Vs73.js} +2 -2
  48. package/dashboard/dist/assets/{BotPicker-BQ336piW.js.map → BotPicker-BQp_Vs73.js.map} +1 -1
  49. package/dashboard/dist/assets/{CapabilitiesPage-CkiJROX-.js → CapabilitiesPage-wpVtkGeU.js} +2 -2
  50. package/dashboard/dist/assets/{CapabilitiesPage-CkiJROX-.js.map → CapabilitiesPage-wpVtkGeU.js.map} +1 -1
  51. package/dashboard/dist/assets/{CollapsibleSection-SM8_UjNe.js → CollapsibleSection-2eZMMZiG.js} +2 -2
  52. package/dashboard/dist/assets/{CollapsibleSection-SM8_UjNe.js.map → CollapsibleSection-2eZMMZiG.js.map} +1 -1
  53. package/dashboard/dist/assets/{CredentialsPage-f6niro9_.js → CredentialsPage-DJGLssm0.js} +2 -2
  54. package/dashboard/dist/assets/{CredentialsPage-f6niro9_.js.map → CredentialsPage-DJGLssm0.js.map} +1 -1
  55. package/dashboard/dist/assets/{CronLabel-DINmdqoe.js → CronLabel-DY8VdTS9.js} +2 -2
  56. package/dashboard/dist/assets/{CronLabel-DINmdqoe.js.map → CronLabel-DY8VdTS9.js.map} +1 -1
  57. package/dashboard/dist/assets/{CustomDurationPicker-BCUcYxfB.js → CustomDurationPicker-DbyqfK35.js} +2 -2
  58. package/dashboard/dist/assets/{CustomDurationPicker-BCUcYxfB.js.map → CustomDurationPicker-DbyqfK35.js.map} +1 -1
  59. package/dashboard/dist/assets/{ElapsedCell-DPYZnXsX.js → ElapsedCell-BPYm8RA7.js} +2 -2
  60. package/dashboard/dist/assets/{ElapsedCell-DPYZnXsX.js.map → ElapsedCell-BPYm8RA7.js.map} +1 -1
  61. package/dashboard/dist/assets/{EscalationsOverview-CTB8AEBd.js → EscalationsOverview-kYGHfnLf.js} +2 -2
  62. package/dashboard/dist/assets/{EscalationsOverview-CTB8AEBd.js.map → EscalationsOverview-kYGHfnLf.js.map} +1 -1
  63. package/dashboard/dist/assets/{EventTable-8_r3Tg09.js → EventTable-DSDzJMer.js} +2 -2
  64. package/dashboard/dist/assets/{EventTable-8_r3Tg09.js.map → EventTable-DSDzJMer.js.map} +1 -1
  65. package/dashboard/dist/assets/{HomePage-Bjxnjv6p.js → HomePage-CwRebzmO.js} +2 -2
  66. package/dashboard/dist/assets/{HomePage-Bjxnjv6p.js.map → HomePage-CwRebzmO.js.map} +1 -1
  67. package/dashboard/dist/assets/{ListToolbar-B60JrvJ9.js → ListToolbar-DEef1_-T.js} +2 -2
  68. package/dashboard/dist/assets/{ListToolbar-B60JrvJ9.js.map → ListToolbar-DEef1_-T.js.map} +1 -1
  69. package/dashboard/dist/assets/{McpOverview-whVRP_Nj.js → McpOverview-CZFW5qMb.js} +2 -2
  70. package/dashboard/dist/assets/{McpOverview-whVRP_Nj.js.map → McpOverview-CZFW5qMb.js.map} +1 -1
  71. package/dashboard/dist/assets/{McpQueryDetailPage-DPuujJkH.js → McpQueryDetailPage-q9xH-QRo.js} +2 -2
  72. package/dashboard/dist/assets/{McpQueryDetailPage-DPuujJkH.js.map → McpQueryDetailPage-q9xH-QRo.js.map} +1 -1
  73. package/dashboard/dist/assets/{McpQueryPage-DciK6r7r.js → McpQueryPage-D14466yi.js} +2 -2
  74. package/dashboard/dist/assets/{McpQueryPage-DciK6r7r.js.map → McpQueryPage-D14466yi.js.map} +1 -1
  75. package/dashboard/dist/assets/{McpRunDetailPage-QEz8BCTu.js → McpRunDetailPage-X0sfRFTk.js} +2 -2
  76. package/dashboard/dist/assets/{McpRunDetailPage-QEz8BCTu.js.map → McpRunDetailPage-X0sfRFTk.js.map} +1 -1
  77. package/dashboard/dist/assets/{McpRunsPage-BA6AVpi_.js → McpRunsPage-aZg057y3.js} +2 -2
  78. package/dashboard/dist/assets/{McpRunsPage-BA6AVpi_.js.map → McpRunsPage-aZg057y3.js.map} +1 -1
  79. package/dashboard/dist/assets/{OperatorDashboard-DrUMzwnl.js → OperatorDashboard-iZEHnndU.js} +2 -2
  80. package/dashboard/dist/assets/{OperatorDashboard-DrUMzwnl.js.map → OperatorDashboard-iZEHnndU.js.map} +1 -1
  81. package/dashboard/dist/assets/{ProcessDetailPage-Dc5ASJpQ.js → ProcessDetailPage-DyzNjwu8.js} +2 -2
  82. package/dashboard/dist/assets/{ProcessDetailPage-Dc5ASJpQ.js.map → ProcessDetailPage-DyzNjwu8.js.map} +1 -1
  83. package/dashboard/dist/assets/{ProcessesListPage-Sa-bjC-g.js → ProcessesListPage-CT_3b5Wt.js} +2 -2
  84. package/dashboard/dist/assets/{ProcessesListPage-Sa-bjC-g.js.map → ProcessesListPage-CT_3b5Wt.js.map} +1 -1
  85. package/dashboard/dist/assets/{RolesPage-DmO8Jlbw.js → RolesPage-CpRJq-sg.js} +2 -2
  86. package/dashboard/dist/assets/{RolesPage-DmO8Jlbw.js.map → RolesPage-CpRJq-sg.js.map} +1 -1
  87. package/dashboard/dist/assets/{RunAsSelector-yWEwIZRe.js → RunAsSelector-C20rdNsC.js} +2 -2
  88. package/dashboard/dist/assets/{RunAsSelector-yWEwIZRe.js.map → RunAsSelector-C20rdNsC.js.map} +1 -1
  89. package/dashboard/dist/assets/{SwimlaneTimeline-CmzfFQ09.js → SwimlaneTimeline-CbFaU4bq.js} +2 -2
  90. package/dashboard/dist/assets/{SwimlaneTimeline-CmzfFQ09.js.map → SwimlaneTimeline-CbFaU4bq.js.map} +1 -1
  91. package/dashboard/dist/assets/{TaskDetailPage-CI4JTC62.js → TaskDetailPage-22cJsFmM.js} +2 -2
  92. package/dashboard/dist/assets/{TaskDetailPage-CI4JTC62.js.map → TaskDetailPage-22cJsFmM.js.map} +1 -1
  93. package/dashboard/dist/assets/{TasksListPage-xdNmQsNE.js → TasksListPage-BDmaUIKu.js} +2 -2
  94. package/dashboard/dist/assets/{TasksListPage-xdNmQsNE.js.map → TasksListPage-BDmaUIKu.js.map} +1 -1
  95. package/dashboard/dist/assets/{TimeAgo-B_um9BWR.js → TimeAgo-7wqEp87-.js} +2 -2
  96. package/dashboard/dist/assets/{TimeAgo-B_um9BWR.js.map → TimeAgo-7wqEp87-.js.map} +1 -1
  97. package/dashboard/dist/assets/{TimestampCell-BJ6trAqW.js → TimestampCell-BBCf8zsN.js} +2 -2
  98. package/dashboard/dist/assets/{TimestampCell-BJ6trAqW.js.map → TimestampCell-BBCf8zsN.js.map} +1 -1
  99. package/dashboard/dist/assets/{ToolTestPanel-DMQhLDES.js → ToolTestPanel-Dosq1cqG.js} +2 -2
  100. package/dashboard/dist/assets/{ToolTestPanel-DMQhLDES.js.map → ToolTestPanel-Dosq1cqG.js.map} +1 -1
  101. package/dashboard/dist/assets/{TopicDetailPage-YeGQA0vD.js → TopicDetailPage-DW97-YHQ.js} +2 -2
  102. package/dashboard/dist/assets/{TopicDetailPage-YeGQA0vD.js.map → TopicDetailPage-DW97-YHQ.js.map} +1 -1
  103. package/dashboard/dist/assets/{TopicsPage-B3QZNlWz.js → TopicsPage-tVPdz-k0.js} +2 -2
  104. package/dashboard/dist/assets/{TopicsPage-B3QZNlWz.js.map → TopicsPage-tVPdz-k0.js.map} +1 -1
  105. package/dashboard/dist/assets/{UserName-MpSZ2_EH.js → UserName-DX7IBjFn.js} +2 -2
  106. package/dashboard/dist/assets/{UserName-MpSZ2_EH.js.map → UserName-DX7IBjFn.js.map} +1 -1
  107. package/dashboard/dist/assets/{WorkflowExecutionPage-DqMqDb1h.js → WorkflowExecutionPage-BjC0j9_L.js} +2 -2
  108. package/dashboard/dist/assets/{WorkflowExecutionPage-DqMqDb1h.js.map → WorkflowExecutionPage-BjC0j9_L.js.map} +1 -1
  109. package/dashboard/dist/assets/{WorkflowsDashboard-BF7FpMmk.js → WorkflowsDashboard-eCH4gpAk.js} +2 -2
  110. package/dashboard/dist/assets/{WorkflowsDashboard-BF7FpMmk.js.map → WorkflowsDashboard-eCH4gpAk.js.map} +1 -1
  111. package/dashboard/dist/assets/{WorkflowsOverview-YFc_KBMS.js → WorkflowsOverview-DaJRDkNy.js} +2 -2
  112. package/dashboard/dist/assets/{WorkflowsOverview-YFc_KBMS.js.map → WorkflowsOverview-DaJRDkNy.js.map} +1 -1
  113. package/dashboard/dist/assets/{YamlWorkflowsPage-BOLs5KTB.js → YamlWorkflowsPage-CkpQaUmz.js} +2 -2
  114. package/dashboard/dist/assets/{YamlWorkflowsPage-BOLs5KTB.js.map → YamlWorkflowsPage-CkpQaUmz.js.map} +1 -1
  115. package/dashboard/dist/assets/{agents-CPYVSCQ3.js → agents-B-P5MlEx.js} +2 -2
  116. package/dashboard/dist/assets/{agents-CPYVSCQ3.js.map → agents-B-P5MlEx.js.map} +1 -1
  117. package/dashboard/dist/assets/{bots-DCXjHjID.js → bots-CZz9iVys.js} +2 -2
  118. package/dashboard/dist/assets/{bots-DCXjHjID.js.map → bots-CZz9iVys.js.map} +1 -1
  119. package/dashboard/dist/assets/{capabilities-CreogBYU.js → capabilities-DrZ8Vw_v.js} +2 -2
  120. package/dashboard/dist/assets/{capabilities-CreogBYU.js.map → capabilities-DrZ8Vw_v.js.map} +1 -1
  121. package/dashboard/dist/assets/{controlplane-Cm_-Gb1x.js → controlplane-cj-1c-1C.js} +2 -2
  122. package/dashboard/dist/assets/{controlplane-Cm_-Gb1x.js.map → controlplane-cj-1c-1C.js.map} +1 -1
  123. package/dashboard/dist/assets/{escalation-ulsBFHVb.js → escalation-BEVFyQnE.js} +2 -2
  124. package/dashboard/dist/assets/{escalation-ulsBFHVb.js.map → escalation-BEVFyQnE.js.map} +1 -1
  125. package/dashboard/dist/assets/{escalation-columns-CLqe28Ba.js → escalation-columns-Beox3TXH.js} +2 -2
  126. package/dashboard/dist/assets/{escalation-columns-CLqe28Ba.js.map → escalation-columns-Beox3TXH.js.map} +1 -1
  127. package/dashboard/dist/assets/{helpers-etjHeZEI.js → helpers-B4gzNq9h.js} +2 -2
  128. package/dashboard/dist/assets/{helpers-etjHeZEI.js.map → helpers-B4gzNq9h.js.map} +1 -1
  129. package/dashboard/dist/assets/{index-BkOv2dQA.js → index-3n5VREXN.js} +2 -2
  130. package/dashboard/dist/assets/{index-BkOv2dQA.js.map → index-3n5VREXN.js.map} +1 -1
  131. package/dashboard/dist/assets/{index-CKDOaej4.js → index-BAXzN-QB.js} +2 -2
  132. package/dashboard/dist/assets/{index-CKDOaej4.js.map → index-BAXzN-QB.js.map} +1 -1
  133. package/dashboard/dist/assets/{index-DVqtJBno.js → index-BCQ65lNu.js} +2 -2
  134. package/dashboard/dist/assets/{index-DVqtJBno.js.map → index-BCQ65lNu.js.map} +1 -1
  135. package/dashboard/dist/assets/{index-BkCkBW_D.js → index-BYXiz05a.js} +2 -2
  136. package/dashboard/dist/assets/{index-BkCkBW_D.js.map → index-BYXiz05a.js.map} +1 -1
  137. package/dashboard/dist/assets/{index-CcvHiZW-.js → index-Bh-PnP17.js} +2 -2
  138. package/dashboard/dist/assets/{index-CcvHiZW-.js.map → index-Bh-PnP17.js.map} +1 -1
  139. package/dashboard/dist/assets/{index-DYmrNJ_H.js → index-BpN31nuC.js} +17 -17
  140. package/dashboard/dist/assets/index-BpN31nuC.js.map +1 -0
  141. package/dashboard/dist/assets/{index-DT68ewTC.js → index-C5dHozmW.js} +2 -2
  142. package/dashboard/dist/assets/{index-DT68ewTC.js.map → index-C5dHozmW.js.map} +1 -1
  143. package/dashboard/dist/assets/{index-7Fbktqcl.js → index-D1MywQ2z.js} +2 -2
  144. package/dashboard/dist/assets/{index-7Fbktqcl.js.map → index-D1MywQ2z.js.map} +1 -1
  145. package/dashboard/dist/assets/{index-Cnpo94XG.js → index-D4KGadbW.js} +2 -2
  146. package/dashboard/dist/assets/{index-Cnpo94XG.js.map → index-D4KGadbW.js.map} +1 -1
  147. package/dashboard/dist/assets/{index-DT0JeuiL.js → index-DdKbIZNE.js} +2 -2
  148. package/dashboard/dist/assets/{index-DT0JeuiL.js.map → index-DdKbIZNE.js.map} +1 -1
  149. package/dashboard/dist/assets/{index-DFuHrLll.js → index-UtAfnStw.js} +2 -2
  150. package/dashboard/dist/assets/{index-DFuHrLll.js.map → index-UtAfnStw.js.map} +1 -1
  151. package/dashboard/dist/assets/{index-DGpIF_Td.js → index-_DfbFHXk.js} +2 -2
  152. package/dashboard/dist/assets/{index-DGpIF_Td.js.map → index-_DfbFHXk.js.map} +1 -1
  153. package/dashboard/dist/assets/{index-CihScSLF.js → index-aJRDh4zW.js} +2 -2
  154. package/dashboard/dist/assets/{index-CihScSLF.js.map → index-aJRDh4zW.js.map} +1 -1
  155. package/dashboard/dist/assets/{knowledge-CXA2DJwY.js → knowledge-DhtKWMON.js} +2 -2
  156. package/dashboard/dist/assets/{knowledge-CXA2DJwY.js.map → knowledge-DhtKWMON.js.map} +1 -1
  157. package/dashboard/dist/assets/{mcp-DeC-PpeL.js → mcp-BXN7-wGF.js} +2 -2
  158. package/dashboard/dist/assets/{mcp-DeC-PpeL.js.map → mcp-BXN7-wGF.js.map} +1 -1
  159. package/dashboard/dist/assets/{mcp-query-DldD_RPZ.js → mcp-query-BIJP4mQJ.js} +2 -2
  160. package/dashboard/dist/assets/{mcp-query-DldD_RPZ.js.map → mcp-query-BIJP4mQJ.js.map} +1 -1
  161. package/dashboard/dist/assets/{namespaces-BIGZ6exX.js → namespaces-ne_yDQZX.js} +2 -2
  162. package/dashboard/dist/assets/{namespaces-BIGZ6exX.js.map → namespaces-ne_yDQZX.js.map} +1 -1
  163. package/dashboard/dist/assets/{pipelines-BtihifKT.js → pipelines-Bcz62DoS.js} +2 -2
  164. package/dashboard/dist/assets/{pipelines-BtihifKT.js.map → pipelines-Bcz62DoS.js.map} +1 -1
  165. package/dashboard/dist/assets/{roles-4DocbpKy.js → roles-De2CzGCy.js} +2 -2
  166. package/dashboard/dist/assets/{roles-4DocbpKy.js.map → roles-De2CzGCy.js.map} +1 -1
  167. package/dashboard/dist/assets/{tasks-B9P_7SR_.js → tasks-4yL5EfxI.js} +2 -2
  168. package/dashboard/dist/assets/{tasks-B9P_7SR_.js.map → tasks-4yL5EfxI.js.map} +1 -1
  169. package/dashboard/dist/assets/{topics-CcLT-IrY.js → topics-DDKHpRwP.js} +2 -2
  170. package/dashboard/dist/assets/{topics-CcLT-IrY.js.map → topics-DDKHpRwP.js.map} +1 -1
  171. package/dashboard/dist/assets/{useEventHooks-B9UOxef_.js → useEventHooks-NzIyvoGY.js} +2 -2
  172. package/dashboard/dist/assets/{useEventHooks-B9UOxef_.js.map → useEventHooks-NzIyvoGY.js.map} +1 -1
  173. package/dashboard/dist/assets/{useYamlActivityEvents-V_MENSI5.js → useYamlActivityEvents-Dv6GhDkh.js} +2 -2
  174. package/dashboard/dist/assets/{useYamlActivityEvents-V_MENSI5.js.map → useYamlActivityEvents-Dv6GhDkh.js.map} +1 -1
  175. package/dashboard/dist/assets/{users-BHF3YOU1.js → users-pSMWP58G.js} +2 -2
  176. package/dashboard/dist/assets/{users-BHF3YOU1.js.map → users-pSMWP58G.js.map} +1 -1
  177. package/dashboard/dist/assets/{workflows-DorgmYSk.js → workflows-COYPOe2I.js} +2 -2
  178. package/dashboard/dist/assets/{workflows-DorgmYSk.js.map → workflows-COYPOe2I.js.map} +1 -1
  179. package/dashboard/dist/assets/{yaml-workflows-DTGpqnEG.js → yaml-workflows-1dF3ig6u.js} +2 -2
  180. package/dashboard/dist/assets/{yaml-workflows-DTGpqnEG.js.map → yaml-workflows-1dF3ig6u.js.map} +1 -1
  181. package/dashboard/dist/index.html +1 -1
  182. package/docs/api/http/escalations.md +6 -4
  183. package/docs/api/http/settings.md +1 -1
  184. package/docs/api/sdk/escalations.md +6 -4
  185. package/package.json +3 -2
  186. package/dashboard/dist/assets/index-DYmrNJ_H.js.map +0 -1
@@ -43,6 +43,8 @@ const express_1 = __importStar(require("express"));
43
43
  const routes_1 = __importDefault(require("../routes"));
44
44
  const events_1 = require("../lib/events");
45
45
  const socketio_1 = require("../lib/events/socketio");
46
+ const nats_1 = require("../lib/events/nats");
47
+ const nats_ws_proxy_1 = require("../lib/events/nats-ws-proxy");
46
48
  /**
47
49
  * Express adapter for mounting the Long Tail dashboard at an arbitrary subpath
48
50
  * inside an existing Express-based application (NestJS, Fastify-Express, etc.).
@@ -112,6 +114,18 @@ class LTExpressAdapter {
112
114
  socketAdapter.attachServer(server);
113
115
  await socketAdapter.connect();
114
116
  }
117
+ // Attach NATS WebSocket proxy (if configured)
118
+ const natsAdapter = events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
119
+ if (natsAdapter?.wsProxyTarget) {
120
+ (0, nats_ws_proxy_1.attachNatsWsProxy)(server, natsAdapter.wsProxyTarget, {
121
+ basePath: this.basePath,
122
+ onWsUrlDerived: (url) => {
123
+ if (!natsAdapter.wsUrl) {
124
+ natsAdapter.setWsUrl(url);
125
+ }
126
+ },
127
+ });
128
+ }
115
129
  }
116
130
  /**
117
131
  * Return a self-contained Express Router that serves:
@@ -71,16 +71,7 @@ async function claimEscalation(input, auth) {
71
71
  if (!result) {
72
72
  return { status: 409, error: 'Escalation not available for claim' };
73
73
  }
74
- (0, publish_1.publishEscalationEvent)({
75
- type: 'escalation.claimed',
76
- source: 'api',
77
- workflowId: escalation.workflow_id || '',
78
- workflowName: escalation.workflow_type || '',
79
- taskQueue: escalation.task_queue || '',
80
- escalationId: id,
81
- status: 'claimed',
82
- data: { assigned_to: auth.userId },
83
- });
74
+ // Event published by service layer (services/escalation/crud.ts)
84
75
  return { status: 200, data: result };
85
76
  }
86
77
  catch (err) {
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.createEscalation = createEscalation;
37
37
  const escalationService = __importStar(require("../../services/escalation"));
38
38
  const userService = __importStar(require("../../services/user"));
39
- const publish_1 = require("../../lib/events/publish");
40
39
  // ── Create ────────────────────────────────────────────────────────────────
41
40
  /**
42
41
  * Create a standalone escalation (not tied to a workflow).
@@ -83,16 +82,7 @@ async function createEscalation(input, auth) {
83
82
  metadata: input.metadata,
84
83
  escalation_payload: input.escalation_payload,
85
84
  });
86
- (0, publish_1.publishEscalationEvent)({
87
- type: 'escalation.created',
88
- source: 'api',
89
- workflowId: '',
90
- workflowName: '',
91
- taskQueue: '',
92
- escalationId: escalation.id,
93
- status: 'pending',
94
- data: { type: input.type, role },
95
- });
85
+ // Event published by service layer (services/escalation/crud.ts)
96
86
  return { status: 201, data: escalation };
97
87
  }
98
88
  catch (err) {
@@ -35,6 +35,7 @@ export declare function claimByMetadata(input: {
35
35
  value: string;
36
36
  durationMinutes?: number;
37
37
  assignee?: string;
38
+ metadata?: Record<string, any>;
38
39
  }, auth: LTApiAuth): Promise<LTApiResult>;
39
40
  /**
40
41
  * Resolve an escalation by metadata key-value pair.
@@ -53,4 +54,5 @@ export declare function resolveByMetadata(input: {
53
54
  value: string;
54
55
  resolverPayload: Record<string, any>;
55
56
  assignee?: string;
57
+ metadata?: Record<string, any>;
56
58
  }, auth: LTApiAuth): Promise<LTApiResult>;
@@ -38,7 +38,6 @@ exports.claimByMetadata = claimByMetadata;
38
38
  exports.resolveByMetadata = resolveByMetadata;
39
39
  const escalationService = __importStar(require("../../services/escalation"));
40
40
  const userService = __importStar(require("../../services/user"));
41
- const publish_1 = require("../../lib/events/publish");
42
41
  const helpers_1 = require("./helpers");
43
42
  /**
44
43
  * Find escalations by a metadata key-value pair.
@@ -105,20 +104,11 @@ async function claimByMetadata(input, auth) {
105
104
  return { status: 403, error: `User must have the "${candidate.role}" role to claim this escalation` };
106
105
  }
107
106
  }
108
- const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes);
107
+ const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes, input.metadata);
109
108
  if (!result) {
110
109
  return { status: 409, error: 'Escalation not available for claim' };
111
110
  }
112
- (0, publish_1.publishEscalationEvent)({
113
- type: 'escalation.claimed',
114
- source: 'api',
115
- workflowId: result.escalation.workflow_id || '',
116
- workflowName: result.escalation.workflow_type || '',
117
- taskQueue: result.escalation.task_queue || '',
118
- escalationId: result.escalation.id,
119
- status: 'claimed',
120
- data: { assigned_to: claimUserId },
121
- });
111
+ // Event published by service layer (services/escalation/crud.ts)
122
112
  return { status: 200, data: result };
123
113
  }
124
114
  catch (err) {
@@ -161,6 +151,10 @@ async function resolveByMetadata(input, auth) {
161
151
  return { status: 403, error: `User must have the "${escalation.role}" role` };
162
152
  }
163
153
  }
154
+ // Merge additional metadata if provided
155
+ if (input.metadata && Object.keys(input.metadata).length > 0) {
156
+ await escalationService.updateEscalationMetadata(escalation.id, input.metadata);
157
+ }
164
158
  // Auto-claim if unclaimed or expired
165
159
  const isClaimed = escalation.assigned_to &&
166
160
  escalation.assigned_until &&
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.resolveEscalation = resolveEscalation;
37
37
  const escalationService = __importStar(require("../../services/escalation"));
38
38
  const taskService = __importStar(require("../../services/task"));
39
- const publish_1 = require("../../lib/events/publish");
40
39
  const escalation_strategy_1 = require("../../services/escalation-strategy");
41
40
  const ephemeral_1 = require("../../services/iam/ephemeral");
42
41
  const deployer_1 = require("../../services/yaml-workflow/deployer");
@@ -105,7 +104,7 @@ async function resolveViaConditionSignal(escalation, resolverPayload) {
105
104
  const client = (0, workers_1.createClient)();
106
105
  const handle = await client.workflow.getHandle(escalation.task_queue, escalation.workflow_type, escalation.workflow_id);
107
106
  await handle.signal(signalId, { ...resolverPayload, $escalation_id: escalation.id });
108
- publishResolvedEvent(escalation);
107
+ // Event published by service layer (services/escalation/crud.ts)
109
108
  return signaledResult(escalation, escalation.workflow_id);
110
109
  }
111
110
  /** Path B: waitFor signal escalation — signal via YAML engine or Durable handle. */
@@ -129,12 +128,7 @@ async function resolveViaSignalRouting(escalation, resolverPayload) {
129
128
  if (signalRouting.engine !== 'yaml') {
130
129
  await escalationService.resolveEscalation(escalation.id, resolverPayload);
131
130
  }
132
- publishResolvedEvent(escalation, {
133
- workflowId: escalation.workflow_id || signalRouting.workflowId,
134
- workflowName: escalation.workflow_type || signalRouting.workflowType,
135
- taskQueue: escalation.task_queue || signalRouting.taskQueue || signalRouting.appId,
136
- status: signalRouting.engine === 'yaml' ? 'signaled' : 'resolved',
137
- });
131
+ // Event published by service layer (services/escalation/crud.ts)
138
132
  return signaledResult(escalation, signalRouting.workflowId || signalRouting.appId);
139
133
  }
140
134
  /** Path C: escalation strategy directed triage — start a triage workflow. */
@@ -165,7 +159,7 @@ async function resolveViaTriage(escalation, resolverPayload, triageEnvelope) {
165
159
  ...resolverPayload,
166
160
  _lt: { ...resolverPayload._lt, triaged: true, triageWorkflowId },
167
161
  });
168
- publishResolvedEvent(escalation);
162
+ // Event published by service layer (services/escalation/crud.ts)
169
163
  return {
170
164
  status: 200,
171
165
  data: { started: true, escalationId: escalation.id, workflowId: triageWorkflowId, triage: true },
@@ -184,26 +178,13 @@ async function resolveViaRerun(escalation, envelope, resolverPayload) {
184
178
  workflowId: newWorkflowId,
185
179
  expire: 180,
186
180
  });
187
- publishResolvedEvent(escalation);
181
+ // Event published by service layer (services/escalation/crud.ts)
188
182
  return {
189
183
  status: 200,
190
184
  data: { started: true, escalationId: escalation.id, workflowId: newWorkflowId },
191
185
  };
192
186
  }
193
187
  // ── Shared helpers ───────────────────────────────────────────────────────
194
- function publishResolvedEvent(escalation, overrides) {
195
- (0, publish_1.publishEscalationEvent)({
196
- type: 'escalation.resolved',
197
- source: 'api',
198
- workflowId: overrides?.workflowId || escalation.workflow_id || '',
199
- workflowName: overrides?.workflowName || escalation.workflow_type || '',
200
- taskQueue: overrides?.taskQueue || escalation.task_queue || '',
201
- taskId: escalation.task_id,
202
- escalationId: escalation.id,
203
- originId: escalation.origin_id ?? undefined,
204
- status: overrides?.status || 'resolved',
205
- });
206
- }
207
188
  function signaledResult(escalation, workflowId) {
208
189
  return {
209
190
  status: 200,
@@ -5,6 +5,7 @@ const telemetry_1 = require("../lib/telemetry");
5
5
  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
+ const config_1 = require("../modules/config");
8
9
  const defaults_1 = require("../modules/defaults");
9
10
  const llm_1 = require("../services/llm");
10
11
  /**
@@ -18,13 +19,13 @@ const llm_1 = require("../services/llm");
18
19
  async function getSettings() {
19
20
  try {
20
21
  const hasSocketIO = !!events_1.eventRegistry.getAdapter(socketio_1.SocketIOEventAdapter);
21
- const hasNats = !!events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
22
+ const natsAdapter = events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
22
23
  // Dashboard transport: Socket.IO is the default (works in-process, zero config).
23
24
  // NATS is only reported when explicitly opted in via EVENT_TRANSPORT=nats,
24
25
  // which a multi-container deployment sets when it wants the dashboard to
25
26
  // connect via NATS instead of Socket.IO.
26
- const forceNats = process.env.EVENT_TRANSPORT === 'nats';
27
- const transport = forceNats && hasNats ? 'nats' : hasSocketIO ? 'socketio' : hasNats ? 'nats' : 'none';
27
+ const forceNats = config_1.config.EVENT_TRANSPORT === 'nats';
28
+ const transport = forceNats && natsAdapter ? 'nats' : hasSocketIO ? 'socketio' : natsAdapter ? 'nats' : 'none';
28
29
  return {
29
30
  status: 200,
30
31
  data: {
@@ -36,9 +37,7 @@ async function getSettings() {
36
37
  },
37
38
  events: {
38
39
  transport,
39
- natsWsUrl: hasNats
40
- ? (process.env.VITE_NATS_WS_URL || process.env.NATS_WS_URL || null)
41
- : null,
40
+ natsWsUrl: natsAdapter?.wsUrl ?? null,
42
41
  },
43
42
  ai: {
44
43
  enabled: (0, llm_1.hasLLMApiKey)(),
package/build/bin/ltc.js CHANGED
@@ -145,11 +145,13 @@ escCmd.command('claim-by-meta <key> <value>')
145
145
  .description('Claim an escalation by metadata key-value pair')
146
146
  .option('--duration <minutes>', 'Claim duration in minutes')
147
147
  .option('--assignee <external_id>', 'Claim on behalf of user (external_id)')
148
+ .option('--meta <json>', 'Merge metadata (JSON object, e.g. \'{"claimedBy":"jimbo"}\')')
148
149
  .action(wrap(esc.claimByMetadata));
149
150
  escCmd.command('resolve-by-meta <key> <value>')
150
151
  .description('Resolve an escalation by metadata key-value pair')
151
152
  .option('--data <json>', 'Resolver payload (JSON string)')
152
153
  .option('--assignee <external_id>', 'Resolve on behalf of user (external_id)')
154
+ .option('--meta <json>', 'Merge metadata (JSON object)')
153
155
  .action(wrap(esc.resolveByMetadata));
154
156
  // ── Workflows ────────────────────────────────────────────────────────────
155
157
  const wfCmd = commander_1.program.command('workflows').alias('wf').description('Manage durable workflows');
package/build/index.js CHANGED
@@ -171,8 +171,8 @@ async function main() {
171
171
  strategy: 'mcp',
172
172
  },
173
173
  telemetry: honeycombKey ? { honeycomb: { apiKey: honeycombKey } } : undefined,
174
- events: process.env.NATS_URL
175
- ? { nats: { url: config_1.config.NATS_URL, token: process.env.NATS_TOKEN || 'dev_api_secret' } }
174
+ events: config_1.config.EVENT_TRANSPORT === 'nats'
175
+ ? { nats: { url: config_1.config.NATS_URL, wsUrl: config_1.config.NATS_WS_URL || undefined, token: config_1.config.NATS_TOKEN || undefined } }
176
176
  : undefined,
177
177
  });
178
178
  }
@@ -20,9 +20,11 @@ export declare function findByMetadata(key: string, value: string, opts: ListOpt
20
20
  export declare function claimByMetadata(key: string, value: string, opts: {
21
21
  duration?: string;
22
22
  assignee?: string;
23
+ meta?: string;
23
24
  }): Promise<void>;
24
25
  export declare function resolveByMetadata(key: string, value: string, opts: {
25
26
  data?: string;
26
27
  assignee?: string;
28
+ meta?: string;
27
29
  }): Promise<void>;
28
30
  export {};
@@ -86,6 +86,8 @@ async function claimByMetadata(key, value, opts) {
86
86
  body.durationMinutes = parseInt(opts.duration, 10);
87
87
  if (opts.assignee)
88
88
  body.assignee = opts.assignee;
89
+ if (opts.meta)
90
+ body.metadata = JSON.parse(opts.meta);
89
91
  const data = await (0, client_1.apiFetch)('/escalations/claim-by-metadata', {
90
92
  method: 'POST',
91
93
  body: JSON.stringify(body),
@@ -97,6 +99,8 @@ async function resolveByMetadata(key, value, opts) {
97
99
  const body = { key, value, resolverPayload };
98
100
  if (opts.assignee)
99
101
  body.assignee = opts.assignee;
102
+ if (opts.meta)
103
+ body.metadata = JSON.parse(opts.meta);
100
104
  await (0, client_1.apiFetch)('/escalations/resolve-by-metadata', {
101
105
  method: 'POST',
102
106
  body: JSON.stringify(body),
@@ -0,0 +1,19 @@
1
+ import type { Server as HttpServer } from 'http';
2
+ /** Default path for the NATS WebSocket proxy endpoint. */
3
+ export declare const NATS_WS_PROXY_PATH = "/nats-ws";
4
+ /**
5
+ * Attach a WebSocket proxy to an HTTP server that bridges browser
6
+ * connections to an internal NATS WebSocket endpoint.
7
+ *
8
+ * The browser connects to `wss://domain.com{basePath}/nats-ws` (port 443,
9
+ * through an ALB or reverse proxy). This handler upgrades the connection
10
+ * and bridges bidirectionally to the internal NATS WS target.
11
+ *
12
+ * The proxy auto-derives the public `wsUrl` from the first incoming
13
+ * request's headers, respecting `X-Forwarded-Proto` and `X-Forwarded-Host`
14
+ * so the correct `wss://` scheme is used behind TLS-terminating load balancers.
15
+ */
16
+ export declare function attachNatsWsProxy(server: HttpServer, target: string, options?: {
17
+ basePath?: string;
18
+ onWsUrlDerived?: (url: string) => void;
19
+ }): void;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NATS_WS_PROXY_PATH = void 0;
4
+ exports.attachNatsWsProxy = attachNatsWsProxy;
5
+ const ws_1 = require("ws");
6
+ const logger_1 = require("../logger");
7
+ /** Default path for the NATS WebSocket proxy endpoint. */
8
+ exports.NATS_WS_PROXY_PATH = '/nats-ws';
9
+ /**
10
+ * Attach a WebSocket proxy to an HTTP server that bridges browser
11
+ * connections to an internal NATS WebSocket endpoint.
12
+ *
13
+ * The browser connects to `wss://domain.com{basePath}/nats-ws` (port 443,
14
+ * through an ALB or reverse proxy). This handler upgrades the connection
15
+ * and bridges bidirectionally to the internal NATS WS target.
16
+ *
17
+ * The proxy auto-derives the public `wsUrl` from the first incoming
18
+ * request's headers, respecting `X-Forwarded-Proto` and `X-Forwarded-Host`
19
+ * so the correct `wss://` scheme is used behind TLS-terminating load balancers.
20
+ */
21
+ function attachNatsWsProxy(server, target, options = {}) {
22
+ const basePath = options.basePath || '';
23
+ const proxyPath = `${basePath}${exports.NATS_WS_PROXY_PATH}`;
24
+ const wss = new ws_1.WebSocketServer({ noServer: true });
25
+ let derived = false;
26
+ server.on('upgrade', (req, socket, head) => {
27
+ if (req.url !== proxyPath)
28
+ return;
29
+ // Derive the public wsUrl from the first request's headers
30
+ if (!derived && options.onWsUrlDerived) {
31
+ const proto = req.headers['x-forwarded-proto'] || 'ws';
32
+ const scheme = proto === 'https' ? 'wss' : 'ws';
33
+ const host = req.headers['x-forwarded-host'] || req.headers.host || 'localhost';
34
+ options.onWsUrlDerived(`${scheme}://${host}${proxyPath}`);
35
+ derived = true;
36
+ }
37
+ wss.handleUpgrade(req, socket, head, (clientWs) => {
38
+ const upstream = new ws_1.WebSocket(target);
39
+ upstream.on('open', () => {
40
+ clientWs.on('message', (data) => {
41
+ if (upstream.readyState === ws_1.WebSocket.OPEN)
42
+ upstream.send(data);
43
+ });
44
+ upstream.on('message', (data) => {
45
+ if (clientWs.readyState === ws_1.WebSocket.OPEN)
46
+ clientWs.send(data);
47
+ });
48
+ });
49
+ const close = () => {
50
+ if (clientWs.readyState === ws_1.WebSocket.OPEN)
51
+ clientWs.close();
52
+ if (upstream.readyState === ws_1.WebSocket.OPEN)
53
+ upstream.close();
54
+ };
55
+ clientWs.on('close', close);
56
+ upstream.on('close', close);
57
+ upstream.on('error', (err) => {
58
+ logger_1.loggerRegistry.error(`[lt-nats-ws-proxy] upstream error: ${err.message}`);
59
+ close();
60
+ });
61
+ clientWs.on('error', (err) => {
62
+ logger_1.loggerRegistry.error(`[lt-nats-ws-proxy] client error: ${err.message}`);
63
+ close();
64
+ });
65
+ });
66
+ });
67
+ logger_1.loggerRegistry.info(`[lt-nats-ws-proxy] active: ${proxyPath} -> ${target}`);
68
+ }
@@ -23,15 +23,31 @@ export declare class NatsEventAdapter implements LTEventAdapter {
23
23
  private nc;
24
24
  private sub;
25
25
  private url;
26
+ private _wsUrl;
27
+ private _wsProxyTarget;
26
28
  private subjectPrefix;
27
29
  private token?;
28
30
  private originId;
29
31
  private callbackAdapter;
30
32
  constructor(options?: {
31
33
  url?: string;
34
+ wsUrl?: string;
35
+ wsProxy?: string;
32
36
  subjectPrefix?: string;
33
37
  token?: string;
34
38
  });
39
+ /**
40
+ * Public NATS WebSocket URL for browser connections.
41
+ * When a wsProxy is configured, this can be set dynamically
42
+ * via `setWsUrl()` once the server's public address is known.
43
+ */
44
+ get wsUrl(): string | null;
45
+ /** Set the browser-facing WebSocket URL (called by proxy setup). */
46
+ setWsUrl(url: string): void;
47
+ /** Internal NATS WS target for the proxy to bridge to (e.g. ws://nats:9222). */
48
+ get wsProxyTarget(): string | null;
49
+ /** NATS auth token for browser connections. */
50
+ get authToken(): string | null;
35
51
  /**
36
52
  * Bridge NATS → local callback adapter for cross-container dispatch.
37
53
  * Part of the LTEventAdapter contract. Call before `connect()`.
@@ -33,8 +33,30 @@ class NatsEventAdapter {
33
33
  this.originId = (0, crypto_1.randomUUID)();
34
34
  this.callbackAdapter = null;
35
35
  this.url = options?.url || config_1.config.NATS_URL;
36
+ this._wsUrl = options?.wsUrl || config_1.config.NATS_WS_URL || null;
37
+ this._wsProxyTarget = options?.wsProxy || null;
36
38
  this.subjectPrefix = options?.subjectPrefix || 'lt.events';
37
- this.token = options?.token || process.env.NATS_TOKEN || 'dev_api_secret';
39
+ this.token = options?.token || config_1.config.NATS_TOKEN || undefined;
40
+ }
41
+ /**
42
+ * Public NATS WebSocket URL for browser connections.
43
+ * When a wsProxy is configured, this can be set dynamically
44
+ * via `setWsUrl()` once the server's public address is known.
45
+ */
46
+ get wsUrl() {
47
+ return this._wsUrl;
48
+ }
49
+ /** Set the browser-facing WebSocket URL (called by proxy setup). */
50
+ setWsUrl(url) {
51
+ this._wsUrl = url;
52
+ }
53
+ /** Internal NATS WS target for the proxy to bridge to (e.g. ws://nats:9222). */
54
+ get wsProxyTarget() {
55
+ return this._wsProxyTarget;
56
+ }
57
+ /** NATS auth token for browser connections. */
58
+ get authToken() {
59
+ return this.token || null;
38
60
  }
39
61
  /**
40
62
  * Bridge NATS → local callback adapter for cross-container dispatch.
@@ -9,12 +9,14 @@ exports.publishFileEvent = publishFileEvent;
9
9
  exports.publishAgentEvent = publishAgentEvent;
10
10
  exports.publishWorkflowEvent = publishWorkflowEvent;
11
11
  const index_1 = require("./index");
12
+ const logger_1 = require("../logger");
12
13
  /**
13
14
  * Fire-and-forget publish helper. Swallows errors (best-effort).
14
15
  */
15
16
  function fireAndForget(event) {
16
17
  if (!index_1.eventRegistry.hasAdapters)
17
18
  return Promise.resolve();
19
+ logger_1.loggerRegistry.info(`[lt-pub] ${event.type} ${event.workflowId || ''} ${event.escalationId || event.taskId || ''}`);
18
20
  return index_1.eventRegistry.publish(event).catch(() => { });
19
21
  }
20
22
  /**
@@ -4,7 +4,10 @@ export declare const config: {
4
4
  POSTGRES_USER: string;
5
5
  POSTGRES_PASSWORD: string;
6
6
  POSTGRES_DB: string;
7
+ EVENT_TRANSPORT: string;
7
8
  NATS_URL: string;
9
+ NATS_WS_URL: string;
10
+ NATS_TOKEN: string;
8
11
  PORT: number;
9
12
  NODE_ENV: string;
10
13
  JWT_SECRET: string;
@@ -11,7 +11,10 @@ exports.config = {
11
11
  POSTGRES_DB: process.env.NODE_ENV === 'test'
12
12
  ? 'longtail_test'
13
13
  : (process.env.POSTGRES_DB || 'longtail'),
14
+ EVENT_TRANSPORT: process.env.EVENT_TRANSPORT || '',
14
15
  NATS_URL: process.env.NATS_URL || 'nats://localhost:4222',
16
+ NATS_WS_URL: process.env.NATS_WS_URL || '',
17
+ NATS_TOKEN: process.env.NATS_TOKEN || '',
15
18
  PORT: parseInt(process.env.PORT || '3000', 10),
16
19
  NODE_ENV: process.env.NODE_ENV || 'development',
17
20
  JWT_SECRET: process.env.JWT_SECRET || '',
@@ -58,7 +58,7 @@ function registerMetadataRoutes(router) {
58
58
  /**
59
59
  * POST /api/escalations/claim-by-metadata
60
60
  * Find and claim an escalation by metadata key-value pair.
61
- * Body: { key, value, durationMinutes?, assignee? }
61
+ * Body: { key, value, durationMinutes?, assignee?, metadata? }
62
62
  */
63
63
  router.post('/claim-by-metadata', async (req, res) => {
64
64
  const result = await api.claimByMetadata({
@@ -66,13 +66,14 @@ function registerMetadataRoutes(router) {
66
66
  value: req.body?.value,
67
67
  durationMinutes: req.body?.durationMinutes,
68
68
  assignee: req.body?.assignee,
69
+ metadata: req.body?.metadata,
69
70
  }, req.auth);
70
71
  res.status(result.status).json(result.data ?? { error: result.error });
71
72
  });
72
73
  /**
73
74
  * POST /api/escalations/resolve-by-metadata
74
75
  * Find and resolve an escalation by metadata key-value pair.
75
- * Body: { key, value, resolverPayload, assignee? }
76
+ * Body: { key, value, resolverPayload, assignee?, metadata? }
76
77
  */
77
78
  router.post('/resolve-by-metadata', async (req, res) => {
78
79
  const result = await api.resolveByMetadata({
@@ -80,6 +81,7 @@ function registerMetadataRoutes(router) {
80
81
  value: req.body?.value,
81
82
  resolverPayload: req.body?.resolverPayload,
82
83
  assignee: req.body?.assignee,
84
+ metadata: req.body?.metadata,
83
85
  }, req.auth);
84
86
  res.status(result.status).json(result.data ?? { error: result.error });
85
87
  });
@@ -10,13 +10,13 @@ const router = (0, express_1.Router)();
10
10
  * Mounted behind requireAuth — only authenticated users receive the token.
11
11
  */
12
12
  router.get('/', async (_req, res) => {
13
- const hasNats = !!events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
14
- if (!hasNats) {
13
+ const natsAdapter = events_1.eventRegistry.getAdapter(nats_1.NatsEventAdapter);
14
+ if (!natsAdapter) {
15
15
  return res.json({ natsWsUrl: null, natsToken: null });
16
16
  }
17
17
  res.json({
18
- natsWsUrl: process.env.VITE_NATS_WS_URL || process.env.NATS_WS_URL || null,
19
- natsToken: process.env.NATS_TOKEN || null,
18
+ natsWsUrl: natsAdapter.wsUrl,
19
+ natsToken: natsAdapter.authToken,
20
20
  });
21
21
  });
22
22
  exports.default = router;
@@ -162,12 +162,14 @@ export declare function createClient(options?: LTClientOptions): {
162
162
  value: string;
163
163
  durationMinutes?: number;
164
164
  assignee?: string;
165
+ metadata?: Record<string, any>;
165
166
  }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
166
167
  resolveByMetadata: (input: {
167
168
  key: string;
168
169
  value: string;
169
170
  resolverPayload: Record<string, any>;
170
171
  assignee?: string;
172
+ metadata?: Record<string, any>;
171
173
  }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
172
174
  };
173
175
  workflows: {
@@ -49,4 +49,4 @@ export declare function findByMetadata(key: string, value: string, status?: stri
49
49
  escalations: LTEscalationRecord[];
50
50
  total: number;
51
51
  }>;
52
- export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number): Promise<ClaimResult | null>;
52
+ export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>): Promise<ClaimResult | null>;