@hotmeshio/long-tail 0.4.13 → 0.4.15

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 (195) hide show
  1. package/build/api/escalations/claim.js +1 -10
  2. package/build/api/escalations/create.js +1 -11
  3. package/build/api/escalations/helpers.d.ts +14 -0
  4. package/build/api/escalations/helpers.js +14 -0
  5. package/build/api/escalations/index.d.ts +1 -0
  6. package/build/api/escalations/index.js +5 -1
  7. package/build/api/escalations/metadata.d.ts +58 -0
  8. package/build/api/escalations/metadata.js +172 -0
  9. package/build/api/escalations/resolve.js +4 -23
  10. package/build/bin/ltc.js +19 -0
  11. package/build/lib/cli/commands/escalations.d.ts +11 -0
  12. package/build/lib/cli/commands/escalations.js +40 -0
  13. package/build/lib/db/schemas/010_metadata_gin.sql +5 -0
  14. package/build/lib/events/publish.js +2 -0
  15. package/build/routes/escalations/index.js +3 -0
  16. package/build/routes/escalations/metadata.d.ts +6 -0
  17. package/build/routes/escalations/metadata.js +88 -0
  18. package/build/sdk/index.d.ts +21 -0
  19. package/build/sdk/index.js +3 -0
  20. package/build/services/escalation/crud.d.ts +5 -0
  21. package/build/services/escalation/crud.js +80 -3
  22. package/build/services/escalation/sql.d.ts +5 -0
  23. package/build/services/escalation/sql.js +42 -1
  24. package/build/services/interceptor/activities/escalation.js +1 -0
  25. package/build/services/interceptor/activities/task.js +2 -23
  26. package/build/services/interceptor/completion.js +2 -22
  27. package/build/services/interceptor/escalation.js +5 -44
  28. package/build/services/interceptor/index.js +26 -2
  29. package/build/services/interceptor/lifecycle.d.ts +1 -1
  30. package/build/services/interceptor/lifecycle.js +18 -32
  31. package/build/services/task/crud.js +36 -2
  32. package/build/start/server.js +5 -4
  33. package/build/tsconfig.tsbuildinfo +1 -1
  34. package/dashboard/dist/assets/{AdminDashboard-Jwr3Fsaz.js → AdminDashboard-BuqyRY2r.js} +2 -2
  35. package/dashboard/dist/assets/{AdminDashboard-Jwr3Fsaz.js.map → AdminDashboard-BuqyRY2r.js.map} +1 -1
  36. package/dashboard/dist/assets/AgentConfigPage-Bum1dUIi.js +16 -0
  37. package/dashboard/dist/assets/AgentConfigPage-Bum1dUIi.js.map +1 -0
  38. package/dashboard/dist/assets/{AgentDetailPage-Cw7foCHd.js → AgentDetailPage-0Kq-tBF2.js} +2 -2
  39. package/dashboard/dist/assets/{AgentDetailPage-Cw7foCHd.js.map → AgentDetailPage-0Kq-tBF2.js.map} +1 -1
  40. package/dashboard/dist/assets/{AgentsPage-DzpWsTFO.js → AgentsPage-B5gYDSOX.js} +2 -2
  41. package/dashboard/dist/assets/{AgentsPage-DzpWsTFO.js.map → AgentsPage-B5gYDSOX.js.map} +1 -1
  42. package/dashboard/dist/assets/AvailableEscalationsPage-BWHThQDC.js +2 -0
  43. package/dashboard/dist/assets/AvailableEscalationsPage-BWHThQDC.js.map +1 -0
  44. package/dashboard/dist/assets/{BotPicker-Ddu4V0uf.js → BotPicker-BQ336piW.js} +2 -2
  45. package/dashboard/dist/assets/{BotPicker-Ddu4V0uf.js.map → BotPicker-BQ336piW.js.map} +1 -1
  46. package/dashboard/dist/assets/{CapabilitiesPage-BTd-uYTM.js → CapabilitiesPage-CkiJROX-.js} +2 -2
  47. package/dashboard/dist/assets/{CapabilitiesPage-BTd-uYTM.js.map → CapabilitiesPage-CkiJROX-.js.map} +1 -1
  48. package/dashboard/dist/assets/{CollapsibleSection-DM-75khr.js → CollapsibleSection-SM8_UjNe.js} +2 -2
  49. package/dashboard/dist/assets/{CollapsibleSection-DM-75khr.js.map → CollapsibleSection-SM8_UjNe.js.map} +1 -1
  50. package/dashboard/dist/assets/{CredentialsPage-BQNraRZu.js → CredentialsPage-f6niro9_.js} +2 -2
  51. package/dashboard/dist/assets/{CredentialsPage-BQNraRZu.js.map → CredentialsPage-f6niro9_.js.map} +1 -1
  52. package/dashboard/dist/assets/{CronLabel-CPuMNBua.js → CronLabel-DINmdqoe.js} +2 -2
  53. package/dashboard/dist/assets/{CronLabel-CPuMNBua.js.map → CronLabel-DINmdqoe.js.map} +1 -1
  54. package/dashboard/dist/assets/{CustomDurationPicker-CLq8B89Y.js → CustomDurationPicker-BCUcYxfB.js} +2 -2
  55. package/dashboard/dist/assets/{CustomDurationPicker-CLq8B89Y.js.map → CustomDurationPicker-BCUcYxfB.js.map} +1 -1
  56. package/dashboard/dist/assets/{ElapsedCell-8lk94nZt.js → ElapsedCell-DPYZnXsX.js} +2 -2
  57. package/dashboard/dist/assets/{ElapsedCell-8lk94nZt.js.map → ElapsedCell-DPYZnXsX.js.map} +1 -1
  58. package/dashboard/dist/assets/{EscalationsOverview-BfSrQ7A5.js → EscalationsOverview-CTB8AEBd.js} +2 -2
  59. package/dashboard/dist/assets/{EscalationsOverview-BfSrQ7A5.js.map → EscalationsOverview-CTB8AEBd.js.map} +1 -1
  60. package/dashboard/dist/assets/{EventTable-D3IOLoxv.js → EventTable-8_r3Tg09.js} +2 -2
  61. package/dashboard/dist/assets/{EventTable-D3IOLoxv.js.map → EventTable-8_r3Tg09.js.map} +1 -1
  62. package/dashboard/dist/assets/{HomePage-RO3qbF38.js → HomePage-Bjxnjv6p.js} +2 -2
  63. package/dashboard/dist/assets/{HomePage-RO3qbF38.js.map → HomePage-Bjxnjv6p.js.map} +1 -1
  64. package/dashboard/dist/assets/{ListToolbar-4lObXT3_.js → ListToolbar-B60JrvJ9.js} +2 -2
  65. package/dashboard/dist/assets/{ListToolbar-4lObXT3_.js.map → ListToolbar-B60JrvJ9.js.map} +1 -1
  66. package/dashboard/dist/assets/{McpOverview-BdLivZv8.js → McpOverview-whVRP_Nj.js} +2 -2
  67. package/dashboard/dist/assets/{McpOverview-BdLivZv8.js.map → McpOverview-whVRP_Nj.js.map} +1 -1
  68. package/dashboard/dist/assets/{McpQueryDetailPage-DKFkH1qa.js → McpQueryDetailPage-DPuujJkH.js} +2 -2
  69. package/dashboard/dist/assets/{McpQueryDetailPage-DKFkH1qa.js.map → McpQueryDetailPage-DPuujJkH.js.map} +1 -1
  70. package/dashboard/dist/assets/{McpQueryPage-AFV_QPwm.js → McpQueryPage-DciK6r7r.js} +2 -2
  71. package/dashboard/dist/assets/{McpQueryPage-AFV_QPwm.js.map → McpQueryPage-DciK6r7r.js.map} +1 -1
  72. package/dashboard/dist/assets/{McpRunDetailPage-DQJ41oKW.js → McpRunDetailPage-QEz8BCTu.js} +2 -2
  73. package/dashboard/dist/assets/{McpRunDetailPage-DQJ41oKW.js.map → McpRunDetailPage-QEz8BCTu.js.map} +1 -1
  74. package/dashboard/dist/assets/{McpRunsPage-CzVS7zcc.js → McpRunsPage-BA6AVpi_.js} +2 -2
  75. package/dashboard/dist/assets/{McpRunsPage-CzVS7zcc.js.map → McpRunsPage-BA6AVpi_.js.map} +1 -1
  76. package/dashboard/dist/assets/OperatorDashboard-DrUMzwnl.js +2 -0
  77. package/dashboard/dist/assets/OperatorDashboard-DrUMzwnl.js.map +1 -0
  78. package/dashboard/dist/assets/{ProcessDetailPage-qibro3Dm.js → ProcessDetailPage-Dc5ASJpQ.js} +2 -2
  79. package/dashboard/dist/assets/{ProcessDetailPage-qibro3Dm.js.map → ProcessDetailPage-Dc5ASJpQ.js.map} +1 -1
  80. package/dashboard/dist/assets/{ProcessesListPage-CPgiDbdS.js → ProcessesListPage-Sa-bjC-g.js} +2 -2
  81. package/dashboard/dist/assets/{ProcessesListPage-CPgiDbdS.js.map → ProcessesListPage-Sa-bjC-g.js.map} +1 -1
  82. package/dashboard/dist/assets/{RolesPage-BAj88I_Y.js → RolesPage-DmO8Jlbw.js} +2 -2
  83. package/dashboard/dist/assets/{RolesPage-BAj88I_Y.js.map → RolesPage-DmO8Jlbw.js.map} +1 -1
  84. package/dashboard/dist/assets/{RunAsSelector-IdZ-qOfl.js → RunAsSelector-yWEwIZRe.js} +2 -2
  85. package/dashboard/dist/assets/{RunAsSelector-IdZ-qOfl.js.map → RunAsSelector-yWEwIZRe.js.map} +1 -1
  86. package/dashboard/dist/assets/{SwimlaneTimeline-WQ6VMuqg.js → SwimlaneTimeline-CmzfFQ09.js} +2 -2
  87. package/dashboard/dist/assets/{SwimlaneTimeline-WQ6VMuqg.js.map → SwimlaneTimeline-CmzfFQ09.js.map} +1 -1
  88. package/dashboard/dist/assets/{TaskDetailPage-buNgjwiz.js → TaskDetailPage-CI4JTC62.js} +2 -2
  89. package/dashboard/dist/assets/{TaskDetailPage-buNgjwiz.js.map → TaskDetailPage-CI4JTC62.js.map} +1 -1
  90. package/dashboard/dist/assets/{TasksListPage-BQjjNjRC.js → TasksListPage-xdNmQsNE.js} +2 -2
  91. package/dashboard/dist/assets/{TasksListPage-BQjjNjRC.js.map → TasksListPage-xdNmQsNE.js.map} +1 -1
  92. package/dashboard/dist/assets/{TimeAgo-Dvkw4shy.js → TimeAgo-B_um9BWR.js} +2 -2
  93. package/dashboard/dist/assets/{TimeAgo-Dvkw4shy.js.map → TimeAgo-B_um9BWR.js.map} +1 -1
  94. package/dashboard/dist/assets/{TimestampCell-DGEGdbOW.js → TimestampCell-BJ6trAqW.js} +2 -2
  95. package/dashboard/dist/assets/{TimestampCell-DGEGdbOW.js.map → TimestampCell-BJ6trAqW.js.map} +1 -1
  96. package/dashboard/dist/assets/{ToolTestPanel-GY3n1V12.js → ToolTestPanel-DMQhLDES.js} +2 -2
  97. package/dashboard/dist/assets/{ToolTestPanel-GY3n1V12.js.map → ToolTestPanel-DMQhLDES.js.map} +1 -1
  98. package/dashboard/dist/assets/{TopicDetailPage-CGim5yi0.js → TopicDetailPage-YeGQA0vD.js} +2 -2
  99. package/dashboard/dist/assets/{TopicDetailPage-CGim5yi0.js.map → TopicDetailPage-YeGQA0vD.js.map} +1 -1
  100. package/dashboard/dist/assets/{TopicsPage-DLyRlo0A.js → TopicsPage-B3QZNlWz.js} +2 -2
  101. package/dashboard/dist/assets/{TopicsPage-DLyRlo0A.js.map → TopicsPage-B3QZNlWz.js.map} +1 -1
  102. package/dashboard/dist/assets/{UserName-B8dGlxj9.js → UserName-MpSZ2_EH.js} +2 -2
  103. package/dashboard/dist/assets/{UserName-B8dGlxj9.js.map → UserName-MpSZ2_EH.js.map} +1 -1
  104. package/dashboard/dist/assets/{WorkflowExecutionPage-BQbIIdIA.js → WorkflowExecutionPage-DqMqDb1h.js} +2 -2
  105. package/dashboard/dist/assets/{WorkflowExecutionPage-BQbIIdIA.js.map → WorkflowExecutionPage-DqMqDb1h.js.map} +1 -1
  106. package/dashboard/dist/assets/{WorkflowsDashboard-DL6oRbka.js → WorkflowsDashboard-BF7FpMmk.js} +2 -2
  107. package/dashboard/dist/assets/{WorkflowsDashboard-DL6oRbka.js.map → WorkflowsDashboard-BF7FpMmk.js.map} +1 -1
  108. package/dashboard/dist/assets/{WorkflowsOverview-Reab_xHT.js → WorkflowsOverview-YFc_KBMS.js} +2 -2
  109. package/dashboard/dist/assets/{WorkflowsOverview-Reab_xHT.js.map → WorkflowsOverview-YFc_KBMS.js.map} +1 -1
  110. package/dashboard/dist/assets/{YamlWorkflowsPage-BoFstOcp.js → YamlWorkflowsPage-BOLs5KTB.js} +2 -2
  111. package/dashboard/dist/assets/{YamlWorkflowsPage-BoFstOcp.js.map → YamlWorkflowsPage-BOLs5KTB.js.map} +1 -1
  112. package/dashboard/dist/assets/{agents-CQsJU21y.js → agents-CPYVSCQ3.js} +2 -2
  113. package/dashboard/dist/assets/{agents-CQsJU21y.js.map → agents-CPYVSCQ3.js.map} +1 -1
  114. package/dashboard/dist/assets/{bots-t1FPESbm.js → bots-DCXjHjID.js} +2 -2
  115. package/dashboard/dist/assets/{bots-t1FPESbm.js.map → bots-DCXjHjID.js.map} +1 -1
  116. package/dashboard/dist/assets/{capabilities-D1Y3hVvf.js → capabilities-CreogBYU.js} +2 -2
  117. package/dashboard/dist/assets/{capabilities-D1Y3hVvf.js.map → capabilities-CreogBYU.js.map} +1 -1
  118. package/dashboard/dist/assets/{controlplane-CV-y8cfH.js → controlplane-Cm_-Gb1x.js} +2 -2
  119. package/dashboard/dist/assets/{controlplane-CV-y8cfH.js.map → controlplane-Cm_-Gb1x.js.map} +1 -1
  120. package/dashboard/dist/assets/escalation-columns-CLqe28Ba.js +2 -0
  121. package/dashboard/dist/assets/escalation-columns-CLqe28Ba.js.map +1 -0
  122. package/dashboard/dist/assets/{escalation-Bf_SO_75.js → escalation-ulsBFHVb.js} +2 -2
  123. package/dashboard/dist/assets/{escalation-Bf_SO_75.js.map → escalation-ulsBFHVb.js.map} +1 -1
  124. package/dashboard/dist/assets/{helpers-nWSTagzD.js → helpers-etjHeZEI.js} +2 -2
  125. package/dashboard/dist/assets/{helpers-nWSTagzD.js.map → helpers-etjHeZEI.js.map} +1 -1
  126. package/dashboard/dist/assets/{index-BRYCB_g0.js → index-7Fbktqcl.js} +2 -2
  127. package/dashboard/dist/assets/{index-BRYCB_g0.js.map → index-7Fbktqcl.js.map} +1 -1
  128. package/dashboard/dist/assets/{index-CHBiEYmf.js → index-BkCkBW_D.js} +2 -2
  129. package/dashboard/dist/assets/{index-CHBiEYmf.js.map → index-BkCkBW_D.js.map} +1 -1
  130. package/dashboard/dist/assets/{index-B77P0ssX.js → index-BkOv2dQA.js} +2 -2
  131. package/dashboard/dist/assets/{index-B77P0ssX.js.map → index-BkOv2dQA.js.map} +1 -1
  132. package/dashboard/dist/assets/index-C37LMzJa.css +1 -0
  133. package/dashboard/dist/assets/{index-DUaF8VYe.js → index-CKDOaej4.js} +6 -6
  134. package/dashboard/dist/assets/index-CKDOaej4.js.map +1 -0
  135. package/dashboard/dist/assets/{index-Dp8iH4i2.js → index-CcvHiZW-.js} +2 -2
  136. package/dashboard/dist/assets/{index-Dp8iH4i2.js.map → index-CcvHiZW-.js.map} +1 -1
  137. package/dashboard/dist/assets/{index-BVXXvXlF.js → index-CihScSLF.js} +2 -2
  138. package/dashboard/dist/assets/{index-BVXXvXlF.js.map → index-CihScSLF.js.map} +1 -1
  139. package/dashboard/dist/assets/{index-wlL3EZ14.js → index-Cnpo94XG.js} +2 -2
  140. package/dashboard/dist/assets/{index-wlL3EZ14.js.map → index-Cnpo94XG.js.map} +1 -1
  141. package/dashboard/dist/assets/{index-CdUj8mKq.js → index-DFuHrLll.js} +2 -2
  142. package/dashboard/dist/assets/{index-CdUj8mKq.js.map → index-DFuHrLll.js.map} +1 -1
  143. package/dashboard/dist/assets/{index-0i5oHs_4.js → index-DGpIF_Td.js} +2 -2
  144. package/dashboard/dist/assets/{index-0i5oHs_4.js.map → index-DGpIF_Td.js.map} +1 -1
  145. package/dashboard/dist/assets/{index-C42ACUTi.js → index-DT0JeuiL.js} +2 -2
  146. package/dashboard/dist/assets/{index-C42ACUTi.js.map → index-DT0JeuiL.js.map} +1 -1
  147. package/dashboard/dist/assets/{index-MO0YnTPi.js → index-DT68ewTC.js} +2 -2
  148. package/dashboard/dist/assets/{index-MO0YnTPi.js.map → index-DT68ewTC.js.map} +1 -1
  149. package/dashboard/dist/assets/{index-DAQvhgrL.js → index-DVqtJBno.js} +2 -2
  150. package/dashboard/dist/assets/{index-DAQvhgrL.js.map → index-DVqtJBno.js.map} +1 -1
  151. package/dashboard/dist/assets/{index-BZu5zewH.js → index-DYmrNJ_H.js} +4 -4
  152. package/dashboard/dist/assets/index-DYmrNJ_H.js.map +1 -0
  153. package/dashboard/dist/assets/{knowledge-DJhm5z0p.js → knowledge-CXA2DJwY.js} +2 -2
  154. package/dashboard/dist/assets/{knowledge-DJhm5z0p.js.map → knowledge-CXA2DJwY.js.map} +1 -1
  155. package/dashboard/dist/assets/{mcp-DMYXb9fv.js → mcp-DeC-PpeL.js} +2 -2
  156. package/dashboard/dist/assets/{mcp-DMYXb9fv.js.map → mcp-DeC-PpeL.js.map} +1 -1
  157. package/dashboard/dist/assets/{mcp-query-DE-oPOvi.js → mcp-query-DldD_RPZ.js} +2 -2
  158. package/dashboard/dist/assets/{mcp-query-DE-oPOvi.js.map → mcp-query-DldD_RPZ.js.map} +1 -1
  159. package/dashboard/dist/assets/{namespaces-Bjjm4EG1.js → namespaces-BIGZ6exX.js} +2 -2
  160. package/dashboard/dist/assets/{namespaces-Bjjm4EG1.js.map → namespaces-BIGZ6exX.js.map} +1 -1
  161. package/dashboard/dist/assets/{pipelines-C8aRprVr.js → pipelines-BtihifKT.js} +2 -2
  162. package/dashboard/dist/assets/{pipelines-C8aRprVr.js.map → pipelines-BtihifKT.js.map} +1 -1
  163. package/dashboard/dist/assets/{roles-CQsPYJXe.js → roles-4DocbpKy.js} +2 -2
  164. package/dashboard/dist/assets/{roles-CQsPYJXe.js.map → roles-4DocbpKy.js.map} +1 -1
  165. package/dashboard/dist/assets/{tasks-BQ1c7trT.js → tasks-B9P_7SR_.js} +2 -2
  166. package/dashboard/dist/assets/{tasks-BQ1c7trT.js.map → tasks-B9P_7SR_.js.map} +1 -1
  167. package/dashboard/dist/assets/{topics-DIziCjqg.js → topics-CcLT-IrY.js} +2 -2
  168. package/dashboard/dist/assets/{topics-DIziCjqg.js.map → topics-CcLT-IrY.js.map} +1 -1
  169. package/dashboard/dist/assets/{useEventHooks-CPxcH6zx.js → useEventHooks-B9UOxef_.js} +2 -2
  170. package/dashboard/dist/assets/{useEventHooks-CPxcH6zx.js.map → useEventHooks-B9UOxef_.js.map} +1 -1
  171. package/dashboard/dist/assets/{useYamlActivityEvents-DnPywDgy.js → useYamlActivityEvents-V_MENSI5.js} +2 -2
  172. package/dashboard/dist/assets/{useYamlActivityEvents-DnPywDgy.js.map → useYamlActivityEvents-V_MENSI5.js.map} +1 -1
  173. package/dashboard/dist/assets/{users-CMGaVe_B.js → users-BHF3YOU1.js} +2 -2
  174. package/dashboard/dist/assets/{users-CMGaVe_B.js.map → users-BHF3YOU1.js.map} +1 -1
  175. package/dashboard/dist/assets/{workflows-CD7-d5w8.js → workflows-DorgmYSk.js} +2 -2
  176. package/dashboard/dist/assets/{workflows-CD7-d5w8.js.map → workflows-DorgmYSk.js.map} +1 -1
  177. package/dashboard/dist/assets/{yaml-workflows-CIeymjZr.js → yaml-workflows-DTGpqnEG.js} +2 -2
  178. package/dashboard/dist/assets/{yaml-workflows-CIeymjZr.js.map → yaml-workflows-DTGpqnEG.js.map} +1 -1
  179. package/dashboard/dist/index.html +2 -2
  180. package/docs/api/http/escalations.md +98 -0
  181. package/docs/api/sdk/escalations.md +86 -0
  182. package/docs/cli.md +8 -0
  183. package/docs/sdk.md +1 -1
  184. package/package.json +1 -1
  185. package/dashboard/dist/assets/AgentConfigPage-DbqbFXEq.js +0 -16
  186. package/dashboard/dist/assets/AgentConfigPage-DbqbFXEq.js.map +0 -1
  187. package/dashboard/dist/assets/AvailableEscalationsPage-D2cxvpAK.js +0 -2
  188. package/dashboard/dist/assets/AvailableEscalationsPage-D2cxvpAK.js.map +0 -1
  189. package/dashboard/dist/assets/OperatorDashboard-B_QmNzLw.js +0 -2
  190. package/dashboard/dist/assets/OperatorDashboard-B_QmNzLw.js.map +0 -1
  191. package/dashboard/dist/assets/escalation-columns-DgY8c1hM.js +0 -2
  192. package/dashboard/dist/assets/escalation-columns-DgY8c1hM.js.map +0 -1
  193. package/dashboard/dist/assets/index-BZu5zewH.js.map +0 -1
  194. package/dashboard/dist/assets/index-DUaF8VYe.js.map +0 -1
  195. package/dashboard/dist/assets/index-ib-nDwd6.css +0 -1
@@ -150,6 +150,27 @@ export declare function createClient(options?: LTClientOptions): {
150
150
  ids: string[];
151
151
  hint?: string;
152
152
  }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
153
+ findByMetadata: (input: {
154
+ key: string;
155
+ value: string;
156
+ status?: string;
157
+ limit?: number;
158
+ offset?: number;
159
+ }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
160
+ claimByMetadata: (input: {
161
+ key: string;
162
+ value: string;
163
+ durationMinutes?: number;
164
+ assignee?: string;
165
+ metadata?: Record<string, any>;
166
+ }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
167
+ resolveByMetadata: (input: {
168
+ key: string;
169
+ value: string;
170
+ resolverPayload: Record<string, any>;
171
+ assignee?: string;
172
+ metadata?: Record<string, any>;
173
+ }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
153
174
  };
154
175
  workflows: {
155
176
  invoke: (input: {
@@ -130,6 +130,9 @@ function createClient(options = {}) {
130
130
  bulkAssign: bindAuth(escalationsApi.bulkAssign, auth),
131
131
  bulkEscalate: bindAuth(escalationsApi.bulkEscalate, auth),
132
132
  bulkTriage: bindAuth(escalationsApi.bulkTriage, auth),
133
+ findByMetadata: bindAuth(escalationsApi.findByMetadata, auth),
134
+ claimByMetadata: bindAuth(escalationsApi.claimByMetadata, auth),
135
+ resolveByMetadata: bindAuth(escalationsApi.resolveByMetadata, auth),
133
136
  },
134
137
  // ── Workflows ──────────────────────────────────────────────────────────
135
138
  workflows: {
@@ -45,3 +45,8 @@ export declare function enrichEscalationRouting(id: string, metadataPatch: Recor
45
45
  taskId?: string;
46
46
  }): Promise<LTEscalationRecord | null>;
47
47
  export declare function getEscalationsByOriginId(originId: string): Promise<LTEscalationRecord[]>;
48
+ export declare function findByMetadata(key: string, value: string, status?: string, limit?: number, offset?: number): Promise<{
49
+ escalations: LTEscalationRecord[];
50
+ total: number;
51
+ }>;
52
+ export declare function claimByMetadata(key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>): Promise<ClaimResult | null>;
@@ -14,9 +14,14 @@ exports.getEscalationsByWorkflowId = getEscalationsByWorkflowId;
14
14
  exports.updateEscalationMetadata = updateEscalationMetadata;
15
15
  exports.enrichEscalationRouting = enrichEscalationRouting;
16
16
  exports.getEscalationsByOriginId = getEscalationsByOriginId;
17
+ exports.findByMetadata = findByMetadata;
18
+ exports.claimByMetadata = claimByMetadata;
17
19
  const db_1 = require("../../lib/db");
20
+ const publish_1 = require("../../lib/events/publish");
21
+ const logger_1 = require("../../lib/logger");
18
22
  const sql_1 = require("./sql");
19
23
  async function createEscalation(input) {
24
+ logger_1.loggerRegistry.info(`[escalation-crud] createEscalation called for wf=${input.workflow_id} type=${input.type} caller=${new Error().stack?.split('\n')[2]?.trim()}`);
20
25
  const pool = (0, db_1.getPool)();
21
26
  // Ensure the role exists in lt_roles (FK constraint)
22
27
  await pool.query(sql_1.ENSURE_ROLE_EXISTS, [input.role]);
@@ -38,7 +43,18 @@ async function createEscalation(input) {
38
43
  input.trace_id || null,
39
44
  input.span_id || null,
40
45
  ]);
41
- return rows[0];
46
+ const escalation = rows[0];
47
+ (0, publish_1.publishEscalationEvent)({
48
+ type: 'escalation.created',
49
+ source: 'service',
50
+ workflowId: escalation.workflow_id || '',
51
+ workflowName: escalation.workflow_type || '',
52
+ taskQueue: escalation.task_queue || '',
53
+ escalationId: escalation.id,
54
+ status: 'pending',
55
+ data: { type: input.type, role: input.role },
56
+ });
57
+ return escalation;
42
58
  }
43
59
  /**
44
60
  * Atomic claim operation. Does NOT change status — "claimed" is implicit
@@ -56,15 +72,39 @@ async function claimEscalation(id, userId, durationMinutes = 30) {
56
72
  if (rows.length === 0)
57
73
  return null;
58
74
  const row = rows[0];
75
+ const escalation = row;
76
+ (0, publish_1.publishEscalationEvent)({
77
+ type: 'escalation.claimed',
78
+ source: 'service',
79
+ workflowId: escalation.workflow_id || '',
80
+ workflowName: escalation.workflow_type || '',
81
+ taskQueue: escalation.task_queue || '',
82
+ escalationId: escalation.id,
83
+ status: 'claimed',
84
+ data: { assigned_to: userId },
85
+ });
59
86
  return {
60
- escalation: row,
87
+ escalation,
61
88
  isExtension: row.prev_assigned_to === userId,
62
89
  };
63
90
  }
64
91
  async function resolveEscalation(id, resolverPayload) {
65
92
  const pool = (0, db_1.getPool)();
66
93
  const { rows } = await pool.query(sql_1.RESOLVE_ESCALATION, [id, JSON.stringify(resolverPayload)]);
67
- return rows[0] || null;
94
+ const escalation = rows[0] || null;
95
+ if (escalation) {
96
+ (0, publish_1.publishEscalationEvent)({
97
+ type: 'escalation.resolved',
98
+ source: 'service',
99
+ workflowId: escalation.workflow_id || '',
100
+ workflowName: escalation.workflow_type || '',
101
+ taskQueue: escalation.task_queue || '',
102
+ escalationId: escalation.id,
103
+ status: 'resolved',
104
+ data: {},
105
+ });
106
+ }
107
+ return escalation;
68
108
  }
69
109
  /**
70
110
  * Bulk update priority for a set of escalations.
@@ -148,3 +188,40 @@ async function getEscalationsByOriginId(originId) {
148
188
  const { rows } = await pool.query(sql_1.GET_ESCALATIONS_BY_ORIGIN_ID, [originId]);
149
189
  return rows;
150
190
  }
191
+ // --- Metadata candidate key lookups -----------------------------------------
192
+ async function findByMetadata(key, value, status, limit = 50, offset = 0) {
193
+ const pool = (0, db_1.getPool)();
194
+ const filter = JSON.stringify({ [key]: value });
195
+ const [countResult, dataResult] = await Promise.all([
196
+ pool.query(sql_1.COUNT_BY_METADATA, [filter, status || null]),
197
+ pool.query(sql_1.FIND_BY_METADATA, [filter, status || null, limit, offset]),
198
+ ]);
199
+ return {
200
+ escalations: dataResult.rows,
201
+ total: parseInt(countResult.rows[0].count, 10),
202
+ };
203
+ }
204
+ async function claimByMetadata(key, value, userId, durationMinutes = 30, metadata) {
205
+ const pool = (0, db_1.getPool)();
206
+ const filter = JSON.stringify({ [key]: value });
207
+ const metaPatch = metadata ? JSON.stringify(metadata) : null;
208
+ const { rows } = await pool.query(sql_1.CLAIM_BY_METADATA, [filter, userId, durationMinutes, metaPatch]);
209
+ if (rows.length === 0)
210
+ return null;
211
+ const row = rows[0];
212
+ const escalation = row;
213
+ (0, publish_1.publishEscalationEvent)({
214
+ type: 'escalation.claimed',
215
+ source: 'service',
216
+ workflowId: escalation.workflow_id || '',
217
+ workflowName: escalation.workflow_type || '',
218
+ taskQueue: escalation.task_queue || '',
219
+ escalationId: escalation.id,
220
+ status: 'claimed',
221
+ data: { assigned_to: userId },
222
+ });
223
+ return {
224
+ escalation,
225
+ isExtension: row.prev_assigned_to === userId,
226
+ };
227
+ }
@@ -19,3 +19,8 @@ export declare const BULK_RESOLVE_FOR_TRIAGE = "UPDATE lt_escalations\nSET statu
19
19
  export declare const UPDATE_ESCALATION_METADATA = "UPDATE lt_escalations\nSET metadata = COALESCE(metadata, '{}'::jsonb) || $2::jsonb,\n updated_at = NOW()\nWHERE id = $1\nRETURNING *";
20
20
  export declare const ENRICH_ESCALATION_ROUTING = "UPDATE lt_escalations\nSET metadata = COALESCE(metadata, '{}'::jsonb) || $2::jsonb,\n workflow_type = COALESCE(workflow_type, $3),\n workflow_id = COALESCE(workflow_id, $4),\n task_queue = COALESCE(task_queue, $5),\n task_id = COALESCE(task_id, $6),\n updated_at = NOW()\nWHERE id = $1\nRETURNING *";
21
21
  export declare const LIST_DISTINCT_TYPES = "SELECT DISTINCT type FROM lt_escalations ORDER BY type";
22
+ /** Find escalations by a single metadata key-value pair. */
23
+ export declare const FIND_BY_METADATA = "SELECT * FROM lt_escalations\nWHERE metadata @> $1::jsonb\n AND ($2::text IS NULL OR status = $2)\nORDER BY priority ASC, created_at ASC\nLIMIT $3 OFFSET $4";
24
+ export declare const COUNT_BY_METADATA = "SELECT COUNT(*) FROM lt_escalations\nWHERE metadata @> $1::jsonb\n AND ($2::text IS NULL OR status = $2)";
25
+ /** Atomic claim by metadata: find one available escalation, claim it, and optionally merge metadata. */
26
+ export declare const CLAIM_BY_METADATA = "WITH target AS (\n SELECT id, assigned_to\n FROM lt_escalations\n WHERE metadata @> $1::jsonb\n AND status = 'pending'\n AND (\n assigned_to IS NULL\n OR assigned_until <= NOW()\n OR assigned_to = $2\n )\n ORDER BY priority ASC, created_at ASC\n LIMIT 1\n FOR UPDATE SKIP LOCKED\n),\nupdated AS (\n UPDATE lt_escalations e\n SET assigned_to = $2,\n claimed_at = NOW(),\n assigned_until = NOW() + INTERVAL '1 minute' * $3,\n metadata = CASE WHEN $4::jsonb IS NOT NULL\n THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb\n ELSE e.metadata END\n FROM target t\n WHERE e.id = t.id\n RETURNING e.*, t.assigned_to AS prev_assigned_to\n)\nSELECT * FROM updated";
@@ -3,7 +3,7 @@
3
3
  // Escalation SQL – externalized from crud.ts, bulk.ts, queries.ts
4
4
  // ---------------------------------------------------------------------------
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.LIST_DISTINCT_TYPES = exports.ENRICH_ESCALATION_ROUTING = exports.UPDATE_ESCALATION_METADATA = exports.BULK_RESOLVE_FOR_TRIAGE = exports.BULK_ESCALATE_TO_ROLE = exports.BULK_ASSIGN = exports.BULK_CLAIM = exports.GET_ESCALATIONS_BY_ORIGIN_ID = exports.GET_ESCALATIONS_BY_WORKFLOW_ID = exports.GET_ESCALATIONS_BY_TASK_ID = exports.GET_ESCALATION = exports.ESCALATE_TO_ROLE = exports.RELEASE_EXPIRED_CLAIMS = exports.RELEASE_ESCALATION = exports.GET_ESCALATION_ROLES = exports.UPDATE_ESCALATIONS_PRIORITY = exports.RESOLVE_ESCALATION = exports.CLAIM_ESCALATION = exports.CREATE_ESCALATION = exports.ENSURE_ROLE_EXISTS = void 0;
6
+ exports.CLAIM_BY_METADATA = exports.COUNT_BY_METADATA = exports.FIND_BY_METADATA = exports.LIST_DISTINCT_TYPES = exports.ENRICH_ESCALATION_ROUTING = exports.UPDATE_ESCALATION_METADATA = exports.BULK_RESOLVE_FOR_TRIAGE = exports.BULK_ESCALATE_TO_ROLE = exports.BULK_ASSIGN = exports.BULK_CLAIM = exports.GET_ESCALATIONS_BY_ORIGIN_ID = exports.GET_ESCALATIONS_BY_WORKFLOW_ID = exports.GET_ESCALATIONS_BY_TASK_ID = exports.GET_ESCALATION = exports.ESCALATE_TO_ROLE = exports.RELEASE_EXPIRED_CLAIMS = exports.RELEASE_ESCALATION = exports.GET_ESCALATION_ROLES = exports.UPDATE_ESCALATIONS_PRIORITY = exports.RESOLVE_ESCALATION = exports.CLAIM_ESCALATION = exports.CREATE_ESCALATION = exports.ENSURE_ROLE_EXISTS = void 0;
7
7
  // --- Role management -------------------------------------------------------
8
8
  exports.ENSURE_ROLE_EXISTS = 'INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING';
9
9
  // --- Single-record CRUD ---------------------------------------------------
@@ -133,3 +133,44 @@ SET metadata = COALESCE(metadata, '{}'::jsonb) || $2::jsonb,
133
133
  WHERE id = $1
134
134
  RETURNING *`;
135
135
  exports.LIST_DISTINCT_TYPES = 'SELECT DISTINCT type FROM lt_escalations ORDER BY type';
136
+ // --- Metadata candidate key lookups -----------------------------------------
137
+ /** Find escalations by a single metadata key-value pair. */
138
+ exports.FIND_BY_METADATA = `\
139
+ SELECT * FROM lt_escalations
140
+ WHERE metadata @> $1::jsonb
141
+ AND ($2::text IS NULL OR status = $2)
142
+ ORDER BY priority ASC, created_at ASC
143
+ LIMIT $3 OFFSET $4`;
144
+ exports.COUNT_BY_METADATA = `\
145
+ SELECT COUNT(*) FROM lt_escalations
146
+ WHERE metadata @> $1::jsonb
147
+ AND ($2::text IS NULL OR status = $2)`;
148
+ /** Atomic claim by metadata: find one available escalation, claim it, and optionally merge metadata. */
149
+ exports.CLAIM_BY_METADATA = `\
150
+ WITH target AS (
151
+ SELECT id, assigned_to
152
+ FROM lt_escalations
153
+ WHERE metadata @> $1::jsonb
154
+ AND status = 'pending'
155
+ AND (
156
+ assigned_to IS NULL
157
+ OR assigned_until <= NOW()
158
+ OR assigned_to = $2
159
+ )
160
+ ORDER BY priority ASC, created_at ASC
161
+ LIMIT 1
162
+ FOR UPDATE SKIP LOCKED
163
+ ),
164
+ updated AS (
165
+ UPDATE lt_escalations e
166
+ SET assigned_to = $2,
167
+ claimed_at = NOW(),
168
+ assigned_until = NOW() + INTERVAL '1 minute' * $3,
169
+ metadata = CASE WHEN $4::jsonb IS NOT NULL
170
+ THEN COALESCE(e.metadata, '{}'::jsonb) || $4::jsonb
171
+ ELSE e.metadata END
172
+ FROM target t
173
+ WHERE e.id = t.id
174
+ RETURNING e.*, t.assigned_to AS prev_assigned_to
175
+ )
176
+ SELECT * FROM updated`;
@@ -106,5 +106,6 @@ async function ltCreateEscalation(input) {
106
106
  trace_id: input.traceId,
107
107
  span_id: input.spanId,
108
108
  });
109
+ // Event published by service layer (services/escalation/crud.ts)
109
110
  return escalation.id;
110
111
  }
@@ -81,16 +81,7 @@ async function ltCreateTask(input) {
81
81
  executing_as: input.executingAs,
82
82
  status: input.status,
83
83
  });
84
- (0, publish_1.publishTaskEvent)({
85
- type: 'task.created',
86
- source: 'interceptor',
87
- workflowId: input.workflowId,
88
- workflowName: input.workflowType,
89
- taskQueue: input.taskQueue || 'unknown',
90
- taskId: task.id,
91
- originId: input.originId,
92
- status: input.status || 'pending',
93
- });
84
+ // Event published by service layer (services/task/crud.ts)
94
85
  return task.id;
95
86
  }
96
87
  /**
@@ -109,19 +100,7 @@ async function ltCompleteTask(input) {
109
100
  data: input.data,
110
101
  milestones: input.milestones,
111
102
  });
112
- // Publish task.completed event
113
- if (input.workflowId) {
114
- (0, publish_1.publishTaskEvent)({
115
- type: 'task.completed',
116
- source: 'orchestrator',
117
- workflowId: input.workflowId,
118
- workflowName: input.workflowName || 'unknown',
119
- taskQueue: input.taskQueue || 'unknown',
120
- taskId: input.taskId,
121
- status: 'completed',
122
- milestones: input.milestones,
123
- });
124
- }
103
+ // task.completed event published by service layer (services/task/crud.ts)
125
104
  // Publish milestone event from orchestrator context
126
105
  if (input.milestones?.length && input.workflowId) {
127
106
  (0, publish_1.publishMilestoneEvent)({
@@ -115,28 +115,8 @@ async function createAdvisoryEscalation(state, result) {
115
115
  traceId: state.traceId,
116
116
  spanId: state.spanId,
117
117
  });
118
- (0, publish_1.publishEscalationEvent)({
119
- type: 'escalation.created',
120
- source: 'interceptor',
121
- workflowId: state.workflowId,
122
- workflowName: state.workflowName,
123
- taskQueue: state.taskQueue,
124
- taskId: state.taskId,
125
- escalationId,
126
- originId: state.envelope?.lt?.originId,
127
- status: 'pending',
128
- data: result.data,
129
- });
130
- (0, publish_1.publishTaskEvent)({
131
- type: 'task.escalated',
132
- source: 'interceptor',
133
- workflowId: state.workflowId,
134
- workflowName: state.workflowName,
135
- taskQueue: state.taskQueue,
136
- taskId: state.taskId,
137
- originId: state.envelope?.lt?.originId,
138
- status: 'needs_intervention',
139
- });
118
+ // escalation.created event published by service layer (services/escalation/crud.ts)
119
+ // task.escalated event published by service layer (services/task/crud.ts)
140
120
  // Auto-claim to submitting user if known
141
121
  const userId = state.envelope?.lt?.userId;
142
122
  if (userId) {
@@ -41,28 +41,8 @@ async function handleEscalation(state, result) {
41
41
  traceId: state.traceId,
42
42
  spanId: state.spanId,
43
43
  });
44
- (0, publish_1.publishEscalationEvent)({
45
- type: 'escalation.created',
46
- source: 'interceptor',
47
- workflowId: state.workflowId,
48
- workflowName: state.workflowName,
49
- taskQueue: state.taskQueue,
50
- taskId: state.taskId,
51
- escalationId,
52
- originId: state.envelope?.lt?.originId,
53
- status: 'pending',
54
- data: result.data,
55
- });
56
- (0, publish_1.publishTaskEvent)({
57
- type: 'task.escalated',
58
- source: 'interceptor',
59
- workflowId: state.workflowId,
60
- workflowName: state.workflowName,
61
- taskQueue: state.taskQueue,
62
- taskId: state.taskId,
63
- originId: state.envelope?.lt?.originId,
64
- status: 'needs_intervention',
65
- });
44
+ // escalation.created event published by service layer (services/escalation/crud.ts)
45
+ // task.escalated event published by service layer (services/task/crud.ts)
66
46
  return result;
67
47
  }
68
48
  /**
@@ -109,28 +89,9 @@ async function handleErrorEscalation(state, err) {
109
89
  traceId: state.traceId,
110
90
  spanId: state.spanId,
111
91
  });
112
- (0, publish_1.publishEscalationEvent)({
113
- type: 'escalation.created',
114
- source: 'interceptor',
115
- workflowId: state.workflowId,
116
- workflowName: state.workflowName,
117
- taskQueue: state.taskQueue,
118
- taskId: state.taskId,
119
- escalationId: errorEscalationId,
120
- originId: state.envelope?.lt?.originId,
121
- status: 'pending',
122
- data: { error: err.message },
123
- });
124
- (0, publish_1.publishTaskEvent)({
125
- type: 'task.escalated',
126
- source: 'interceptor',
127
- workflowId: state.workflowId,
128
- workflowName: state.workflowName,
129
- taskQueue: state.taskQueue,
130
- taskId: state.taskId,
131
- originId: state.envelope?.lt?.originId,
132
- status: 'needs_intervention',
133
- });
92
+ // escalation.created event published by service layer (services/escalation/crud.ts)
93
+ // task.escalated event published by service layer (services/task/crud.ts)
94
+ // Publish workflow.failed event (error path only runs once — no replay guard needed)
134
95
  (0, publish_1.publishWorkflowEvent)({
135
96
  type: 'workflow.failed',
136
97
  source: 'interceptor',
@@ -44,6 +44,7 @@ const escalation_1 = require("./escalation");
44
44
  const completion_1 = require("./completion");
45
45
  const lifecycle_1 = require("./lifecycle");
46
46
  const context_2 = require("../iam/context");
47
+ const publish_1 = require("../../lib/events/publish");
47
48
  const envelope_1 = require("../iam/envelope");
48
49
  const DEFAULT_ACTIVITY_QUEUE = 'lt-interceptor';
49
50
  /**
@@ -104,13 +105,36 @@ function createLTInterceptor(options) {
104
105
  // task creation, and escalation wiring.
105
106
  if (envelope?.metadata?.certified !== true) {
106
107
  const toolCtx = (0, envelope_1.buildToolContextFromEnvelope)(envelope, wf.workflowId, wf.workflowTrace, wf.workflowSpan);
107
- return toolCtx ? (0, context_2.runWithToolContext)(toolCtx, next) : next();
108
+ // Publish workflow events even for uncertified workflows
109
+ const taskQueue = (0, lifecycle_1.deriveTaskQueue)(wf);
110
+ (0, lifecycle_1.publishStartedEvents)(wf, taskQueue, undefined, wf.workflowId);
111
+ const result = toolCtx ? await (0, context_2.runWithToolContext)(toolCtx, next) : await next();
112
+ (0, publish_1.publishWorkflowEvent)({
113
+ type: 'workflow.completed',
114
+ source: 'interceptor',
115
+ workflowId: wf.workflowId,
116
+ workflowName: wf.workflowName,
117
+ taskQueue,
118
+ status: 'completed',
119
+ });
120
+ return result;
108
121
  }
109
122
  // 3. Load config — unregistered/uncertified workflows get ToolContext only
110
123
  const wfConfig = await activities.ltGetWorkflowConfig(wf.workflowName);
111
124
  if (!wfConfig) {
112
125
  const toolCtx = (0, envelope_1.buildToolContextFromEnvelope)(envelope, wf.workflowId, wf.workflowTrace, wf.workflowSpan);
113
- return toolCtx ? (0, context_2.runWithToolContext)(toolCtx, next) : next();
126
+ const taskQueue2 = (0, lifecycle_1.deriveTaskQueue)(wf);
127
+ (0, lifecycle_1.publishStartedEvents)(wf, taskQueue2, undefined, wf.workflowId);
128
+ const result2 = toolCtx ? await (0, context_2.runWithToolContext)(toolCtx, next) : await next();
129
+ (0, publish_1.publishWorkflowEvent)({
130
+ type: 'workflow.completed',
131
+ source: 'interceptor',
132
+ workflowId: wf.workflowId,
133
+ workflowName: wf.workflowName,
134
+ taskQueue: taskQueue2,
135
+ status: 'completed',
136
+ });
137
+ return result2;
114
138
  }
115
139
  const taskQueue = (0, lifecycle_1.deriveTaskQueue)(wf);
116
140
  // 3. Find existing task and handle re-run escalation resolution
@@ -37,7 +37,7 @@ export declare function resolveReRun(activities: ProxiedActivities, envelope: LT
37
37
  * Also injects originId back into the envelope for downstream consistency.
38
38
  */
39
39
  export declare function ensureTaskWithRouting(activities: ProxiedActivities, wf: WorkflowIdentity, envelope: LTEnvelope | undefined, existingTask: any | null, taskQueue: string, reRun: ReRunContext): Promise<TaskContext>;
40
- /** Publish workflow.started + task.started events. */
40
+ /** Publish workflow.started event (guarded against replay). */
41
41
  export declare function publishStartedEvents(wf: WorkflowIdentity, taskQueue: string, taskId: string | undefined, originId: string): void;
42
42
  /** Complete a task and signal parent for plain (non-LTReturn) results. */
43
43
  export declare function completePlainResult(activities: ProxiedActivities, wf: WorkflowIdentity, taskQueue: string, taskId: string | undefined, routing: Record<string, any> | null, result: any): Promise<void>;
@@ -13,6 +13,7 @@ exports.resolveReRun = resolveReRun;
13
13
  exports.ensureTaskWithRouting = ensureTaskWithRouting;
14
14
  exports.publishStartedEvents = publishStartedEvents;
15
15
  exports.completePlainResult = completePlainResult;
16
+ const hotmesh_1 = require("@hotmeshio/hotmesh");
16
17
  const publish_1 = require("../../lib/events/publish");
17
18
  // ── Helpers ──────────────────────────────────────────────────────────────────
18
19
  /** Extract workflow identity fields from the HotMesh context map. */
@@ -56,17 +57,7 @@ async function resolveReRun(activities, envelope, existingTask, wf, taskQueue) {
56
57
  escalationId: escalationId,
57
58
  resolverPayload: envelope.resolver,
58
59
  });
59
- (0, publish_1.publishEscalationEvent)({
60
- type: 'escalation.resolved',
61
- source: 'interceptor',
62
- workflowId: wf.workflowId,
63
- workflowName: wf.workflowName,
64
- taskQueue,
65
- taskId: task?.id || existingTask?.id,
66
- escalationId: escalationId,
67
- originId: envelope?.lt?.originId,
68
- status: 'resolved',
69
- });
60
+ // escalation.resolved event published by service layer (services/escalation/crud.ts)
70
61
  }
71
62
  return { isReRun, task, metadata };
72
63
  }
@@ -128,28 +119,23 @@ async function ensureTaskWithRouting(activities, wf, envelope, existingTask, tas
128
119
  }
129
120
  return { taskId, routing, originId };
130
121
  }
131
- /** Publish workflow.started + task.started events. */
122
+ /** Publish workflow.started event (guarded against replay). */
132
123
  function publishStartedEvents(wf, taskQueue, taskId, originId) {
133
- (0, publish_1.publishWorkflowEvent)({
134
- type: 'workflow.started',
135
- source: 'interceptor',
136
- workflowId: wf.workflowId,
137
- workflowName: wf.workflowName,
138
- taskQueue,
139
- taskId,
140
- originId,
141
- status: 'running',
142
- });
143
- (0, publish_1.publishTaskEvent)({
144
- type: 'task.started',
145
- source: 'interceptor',
146
- workflowId: wf.workflowId,
147
- workflowName: wf.workflowName,
148
- taskQueue,
149
- taskId: taskId,
150
- originId,
151
- status: 'in_progress',
152
- });
124
+ const { replay } = hotmesh_1.Durable.workflow.workflowInfo();
125
+ const isFirstExecution = Object.keys(replay).length === 0;
126
+ if (isFirstExecution) {
127
+ (0, publish_1.publishWorkflowEvent)({
128
+ type: 'workflow.started',
129
+ source: 'interceptor',
130
+ workflowId: wf.workflowId,
131
+ workflowName: wf.workflowName,
132
+ taskQueue,
133
+ taskId,
134
+ originId,
135
+ status: 'running',
136
+ });
137
+ }
138
+ // task.started event published by service layer (services/task/crud.ts)
153
139
  }
154
140
  /** Complete a task and signal parent for plain (non-LTReturn) results. */
155
141
  async function completePlainResult(activities, wf, taskQueue, taskId, routing, result) {
@@ -8,6 +8,7 @@ exports.getTaskBySignalId = getTaskBySignalId;
8
8
  exports.getTaskByWorkflowId = getTaskByWorkflowId;
9
9
  exports.listTasks = listTasks;
10
10
  const db_1 = require("../../lib/db");
11
+ const publish_1 = require("../../lib/events/publish");
11
12
  const sql_1 = require("./sql");
12
13
  async function createTask(input) {
13
14
  const pool = (0, db_1.getPool)();
@@ -30,7 +31,18 @@ async function createTask(input) {
30
31
  input.executing_as || null,
31
32
  input.status || null,
32
33
  ]);
33
- return rows[0];
34
+ const task = rows[0];
35
+ (0, publish_1.publishTaskEvent)({
36
+ type: 'task.created',
37
+ source: 'service',
38
+ workflowId: task.workflow_id || '',
39
+ workflowName: task.workflow_type || '',
40
+ taskQueue: task.task_queue || '',
41
+ taskId: task.id,
42
+ originId: task.origin_id || undefined,
43
+ status: task.status || 'pending',
44
+ });
45
+ return task;
34
46
  }
35
47
  async function updateTask(id, input) {
36
48
  const pool = (0, db_1.getPool)();
@@ -59,7 +71,29 @@ async function updateTask(id, input) {
59
71
  }
60
72
  values.push(id);
61
73
  const { rows } = await pool.query(`UPDATE lt_tasks SET ${sets.join(', ')} WHERE id = $${idx} RETURNING *`, values);
62
- return rows[0];
74
+ const task = rows[0];
75
+ // Publish status-driven events from the single write path
76
+ if (input.status && task) {
77
+ const STATUS_EVENTS = {
78
+ in_progress: 'task.started',
79
+ completed: 'task.completed',
80
+ needs_intervention: 'task.escalated',
81
+ };
82
+ const eventType = STATUS_EVENTS[input.status];
83
+ if (eventType) {
84
+ (0, publish_1.publishTaskEvent)({
85
+ type: eventType,
86
+ source: 'service',
87
+ workflowId: task.workflow_id || '',
88
+ workflowName: task.workflow_type || '',
89
+ taskQueue: task.task_queue || '',
90
+ taskId: task.id,
91
+ originId: task.origin_id || undefined,
92
+ status: input.status,
93
+ });
94
+ }
95
+ }
96
+ return task;
63
97
  }
64
98
  async function appendMilestones(id, milestones) {
65
99
  const pool = (0, db_1.getPool)();
@@ -30,13 +30,14 @@ function startServer() {
30
30
  const prodDist = path_1.default.join(__dirname, '..', '..', 'dashboard', 'dist');
31
31
  const dashboardDist = (0, fs_1.existsSync)(devDist) ? devDist : prodDist;
32
32
  if ((0, fs_1.existsSync)(dashboardDist)) {
33
- app.use(express_1.default.static(dashboardDist));
33
+ app.use(express_1.default.static(dashboardDist, { index: false }));
34
34
  // SPA fallback — inject <base href="/"> so relative asset paths
35
35
  // resolve from root regardless of route depth (e.g. /admin/users).
36
- const rawHtml = (0, fs_1.readFileSync)(path_1.default.join(dashboardDist, 'index.html'), 'utf-8');
37
- const indexHtml = rawHtml.replace('<head>', '<head><base href="/">');
36
+ // Read on each request so dashboard rebuilds take effect without restart.
37
+ const indexPath = path_1.default.join(dashboardDist, 'index.html');
38
38
  app.get('/{*splat}', (_req, res) => {
39
- res.type('html').send(indexHtml);
39
+ const html = (0, fs_1.readFileSync)(indexPath, 'utf-8').replace('<head>', '<head><base href="/">');
40
+ res.type('html').send(html);
40
41
  });
41
42
  logger_1.loggerRegistry.info(`[long-tail] Dashboard: http://localhost:${config_1.config.PORT}/`);
42
43
  }