@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.
- package/build/adapters/express.js +14 -0
- package/build/api/escalations/claim.js +1 -10
- package/build/api/escalations/create.js +1 -11
- package/build/api/escalations/metadata.d.ts +2 -0
- package/build/api/escalations/metadata.js +6 -12
- package/build/api/escalations/resolve.js +4 -23
- package/build/api/settings.js +5 -6
- package/build/bin/ltc.js +2 -0
- package/build/index.js +2 -2
- package/build/lib/cli/commands/escalations.d.ts +2 -0
- package/build/lib/cli/commands/escalations.js +4 -0
- package/build/lib/events/nats-ws-proxy.d.ts +19 -0
- package/build/lib/events/nats-ws-proxy.js +68 -0
- package/build/lib/events/nats.d.ts +16 -0
- package/build/lib/events/nats.js +23 -1
- package/build/lib/events/publish.js +2 -0
- package/build/modules/config.d.ts +3 -0
- package/build/modules/config.js +3 -0
- package/build/routes/escalations/metadata.js +4 -2
- package/build/routes/nats-credentials.js +4 -4
- package/build/sdk/index.d.ts +2 -0
- package/build/services/escalation/crud.d.ts +1 -1
- package/build/services/escalation/crud.js +56 -6
- package/build/services/escalation/sql.d.ts +2 -2
- package/build/services/escalation/sql.js +5 -2
- package/build/services/interceptor/activities/escalation.js +1 -11
- package/build/services/interceptor/activities/task.js +2 -23
- package/build/services/interceptor/completion.js +2 -22
- package/build/services/interceptor/escalation.js +5 -44
- package/build/services/interceptor/index.js +26 -2
- package/build/services/interceptor/lifecycle.d.ts +1 -1
- package/build/services/interceptor/lifecycle.js +18 -32
- package/build/services/task/crud.js +36 -2
- package/build/start/index.js +14 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/startup.d.ts +3 -0
- package/dashboard/dist/assets/{AdminDashboard-BuqyRY2r.js → AdminDashboard-Cfo0mwL2.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BuqyRY2r.js.map → AdminDashboard-Cfo0mwL2.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-Bum1dUIi.js → AgentConfigPage-DBtvb2x5.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-Bum1dUIi.js.map → AgentConfigPage-DBtvb2x5.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-0Kq-tBF2.js → AgentDetailPage-3mZA7SOb.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-0Kq-tBF2.js.map → AgentDetailPage-3mZA7SOb.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-B5gYDSOX.js → AgentsPage-CTVocfBb.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-B5gYDSOX.js.map → AgentsPage-CTVocfBb.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-BWHThQDC.js → AvailableEscalationsPage-CA9x9o5s.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-BWHThQDC.js.map → AvailableEscalationsPage-CA9x9o5s.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-BQ336piW.js → BotPicker-BQp_Vs73.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BQ336piW.js.map → BotPicker-BQp_Vs73.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-CkiJROX-.js → CapabilitiesPage-wpVtkGeU.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-CkiJROX-.js.map → CapabilitiesPage-wpVtkGeU.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-SM8_UjNe.js → CollapsibleSection-2eZMMZiG.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-SM8_UjNe.js.map → CollapsibleSection-2eZMMZiG.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-f6niro9_.js → CredentialsPage-DJGLssm0.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-f6niro9_.js.map → CredentialsPage-DJGLssm0.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DINmdqoe.js → CronLabel-DY8VdTS9.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DINmdqoe.js.map → CronLabel-DY8VdTS9.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-BCUcYxfB.js → CustomDurationPicker-DbyqfK35.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-BCUcYxfB.js.map → CustomDurationPicker-DbyqfK35.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-DPYZnXsX.js → ElapsedCell-BPYm8RA7.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-DPYZnXsX.js.map → ElapsedCell-BPYm8RA7.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CTB8AEBd.js → EscalationsOverview-kYGHfnLf.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CTB8AEBd.js.map → EscalationsOverview-kYGHfnLf.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-8_r3Tg09.js → EventTable-DSDzJMer.js} +2 -2
- package/dashboard/dist/assets/{EventTable-8_r3Tg09.js.map → EventTable-DSDzJMer.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-Bjxnjv6p.js → HomePage-CwRebzmO.js} +2 -2
- package/dashboard/dist/assets/{HomePage-Bjxnjv6p.js.map → HomePage-CwRebzmO.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-B60JrvJ9.js → ListToolbar-DEef1_-T.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-B60JrvJ9.js.map → ListToolbar-DEef1_-T.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-whVRP_Nj.js → McpOverview-CZFW5qMb.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-whVRP_Nj.js.map → McpOverview-CZFW5qMb.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-DPuujJkH.js → McpQueryDetailPage-q9xH-QRo.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-DPuujJkH.js.map → McpQueryDetailPage-q9xH-QRo.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DciK6r7r.js → McpQueryPage-D14466yi.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DciK6r7r.js.map → McpQueryPage-D14466yi.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-QEz8BCTu.js → McpRunDetailPage-X0sfRFTk.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-QEz8BCTu.js.map → McpRunDetailPage-X0sfRFTk.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BA6AVpi_.js → McpRunsPage-aZg057y3.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BA6AVpi_.js.map → McpRunsPage-aZg057y3.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-DrUMzwnl.js → OperatorDashboard-iZEHnndU.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DrUMzwnl.js.map → OperatorDashboard-iZEHnndU.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-Dc5ASJpQ.js → ProcessDetailPage-DyzNjwu8.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-Dc5ASJpQ.js.map → ProcessDetailPage-DyzNjwu8.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-Sa-bjC-g.js → ProcessesListPage-CT_3b5Wt.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-Sa-bjC-g.js.map → ProcessesListPage-CT_3b5Wt.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DmO8Jlbw.js → RolesPage-CpRJq-sg.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DmO8Jlbw.js.map → RolesPage-CpRJq-sg.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-yWEwIZRe.js → RunAsSelector-C20rdNsC.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-yWEwIZRe.js.map → RunAsSelector-C20rdNsC.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CmzfFQ09.js → SwimlaneTimeline-CbFaU4bq.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CmzfFQ09.js.map → SwimlaneTimeline-CbFaU4bq.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-CI4JTC62.js → TaskDetailPage-22cJsFmM.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-CI4JTC62.js.map → TaskDetailPage-22cJsFmM.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-xdNmQsNE.js → TasksListPage-BDmaUIKu.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-xdNmQsNE.js.map → TasksListPage-BDmaUIKu.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-B_um9BWR.js → TimeAgo-7wqEp87-.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-B_um9BWR.js.map → TimeAgo-7wqEp87-.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BJ6trAqW.js → TimestampCell-BBCf8zsN.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BJ6trAqW.js.map → TimestampCell-BBCf8zsN.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-DMQhLDES.js → ToolTestPanel-Dosq1cqG.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-DMQhLDES.js.map → ToolTestPanel-Dosq1cqG.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-YeGQA0vD.js → TopicDetailPage-DW97-YHQ.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-YeGQA0vD.js.map → TopicDetailPage-DW97-YHQ.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-B3QZNlWz.js → TopicsPage-tVPdz-k0.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-B3QZNlWz.js.map → TopicsPage-tVPdz-k0.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-MpSZ2_EH.js → UserName-DX7IBjFn.js} +2 -2
- package/dashboard/dist/assets/{UserName-MpSZ2_EH.js.map → UserName-DX7IBjFn.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DqMqDb1h.js → WorkflowExecutionPage-BjC0j9_L.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DqMqDb1h.js.map → WorkflowExecutionPage-BjC0j9_L.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-BF7FpMmk.js → WorkflowsDashboard-eCH4gpAk.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-BF7FpMmk.js.map → WorkflowsDashboard-eCH4gpAk.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-YFc_KBMS.js → WorkflowsOverview-DaJRDkNy.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-YFc_KBMS.js.map → WorkflowsOverview-DaJRDkNy.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-BOLs5KTB.js → YamlWorkflowsPage-CkpQaUmz.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-BOLs5KTB.js.map → YamlWorkflowsPage-CkpQaUmz.js.map} +1 -1
- package/dashboard/dist/assets/{agents-CPYVSCQ3.js → agents-B-P5MlEx.js} +2 -2
- package/dashboard/dist/assets/{agents-CPYVSCQ3.js.map → agents-B-P5MlEx.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DCXjHjID.js → bots-CZz9iVys.js} +2 -2
- package/dashboard/dist/assets/{bots-DCXjHjID.js.map → bots-CZz9iVys.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CreogBYU.js → capabilities-DrZ8Vw_v.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CreogBYU.js.map → capabilities-DrZ8Vw_v.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-Cm_-Gb1x.js → controlplane-cj-1c-1C.js} +2 -2
- package/dashboard/dist/assets/{controlplane-Cm_-Gb1x.js.map → controlplane-cj-1c-1C.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-ulsBFHVb.js → escalation-BEVFyQnE.js} +2 -2
- package/dashboard/dist/assets/{escalation-ulsBFHVb.js.map → escalation-BEVFyQnE.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CLqe28Ba.js → escalation-columns-Beox3TXH.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CLqe28Ba.js.map → escalation-columns-Beox3TXH.js.map} +1 -1
- package/dashboard/dist/assets/{helpers-etjHeZEI.js → helpers-B4gzNq9h.js} +2 -2
- package/dashboard/dist/assets/{helpers-etjHeZEI.js.map → helpers-B4gzNq9h.js.map} +1 -1
- package/dashboard/dist/assets/{index-BkOv2dQA.js → index-3n5VREXN.js} +2 -2
- package/dashboard/dist/assets/{index-BkOv2dQA.js.map → index-3n5VREXN.js.map} +1 -1
- package/dashboard/dist/assets/{index-CKDOaej4.js → index-BAXzN-QB.js} +2 -2
- package/dashboard/dist/assets/{index-CKDOaej4.js.map → index-BAXzN-QB.js.map} +1 -1
- package/dashboard/dist/assets/{index-DVqtJBno.js → index-BCQ65lNu.js} +2 -2
- package/dashboard/dist/assets/{index-DVqtJBno.js.map → index-BCQ65lNu.js.map} +1 -1
- package/dashboard/dist/assets/{index-BkCkBW_D.js → index-BYXiz05a.js} +2 -2
- package/dashboard/dist/assets/{index-BkCkBW_D.js.map → index-BYXiz05a.js.map} +1 -1
- package/dashboard/dist/assets/{index-CcvHiZW-.js → index-Bh-PnP17.js} +2 -2
- package/dashboard/dist/assets/{index-CcvHiZW-.js.map → index-Bh-PnP17.js.map} +1 -1
- package/dashboard/dist/assets/{index-DYmrNJ_H.js → index-BpN31nuC.js} +17 -17
- package/dashboard/dist/assets/index-BpN31nuC.js.map +1 -0
- package/dashboard/dist/assets/{index-DT68ewTC.js → index-C5dHozmW.js} +2 -2
- package/dashboard/dist/assets/{index-DT68ewTC.js.map → index-C5dHozmW.js.map} +1 -1
- package/dashboard/dist/assets/{index-7Fbktqcl.js → index-D1MywQ2z.js} +2 -2
- package/dashboard/dist/assets/{index-7Fbktqcl.js.map → index-D1MywQ2z.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cnpo94XG.js → index-D4KGadbW.js} +2 -2
- package/dashboard/dist/assets/{index-Cnpo94XG.js.map → index-D4KGadbW.js.map} +1 -1
- package/dashboard/dist/assets/{index-DT0JeuiL.js → index-DdKbIZNE.js} +2 -2
- package/dashboard/dist/assets/{index-DT0JeuiL.js.map → index-DdKbIZNE.js.map} +1 -1
- package/dashboard/dist/assets/{index-DFuHrLll.js → index-UtAfnStw.js} +2 -2
- package/dashboard/dist/assets/{index-DFuHrLll.js.map → index-UtAfnStw.js.map} +1 -1
- package/dashboard/dist/assets/{index-DGpIF_Td.js → index-_DfbFHXk.js} +2 -2
- package/dashboard/dist/assets/{index-DGpIF_Td.js.map → index-_DfbFHXk.js.map} +1 -1
- package/dashboard/dist/assets/{index-CihScSLF.js → index-aJRDh4zW.js} +2 -2
- package/dashboard/dist/assets/{index-CihScSLF.js.map → index-aJRDh4zW.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CXA2DJwY.js → knowledge-DhtKWMON.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CXA2DJwY.js.map → knowledge-DhtKWMON.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-DeC-PpeL.js → mcp-BXN7-wGF.js} +2 -2
- package/dashboard/dist/assets/{mcp-DeC-PpeL.js.map → mcp-BXN7-wGF.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DldD_RPZ.js → mcp-query-BIJP4mQJ.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DldD_RPZ.js.map → mcp-query-BIJP4mQJ.js.map} +1 -1
- package/dashboard/dist/assets/{namespaces-BIGZ6exX.js → namespaces-ne_yDQZX.js} +2 -2
- package/dashboard/dist/assets/{namespaces-BIGZ6exX.js.map → namespaces-ne_yDQZX.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BtihifKT.js → pipelines-Bcz62DoS.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BtihifKT.js.map → pipelines-Bcz62DoS.js.map} +1 -1
- package/dashboard/dist/assets/{roles-4DocbpKy.js → roles-De2CzGCy.js} +2 -2
- package/dashboard/dist/assets/{roles-4DocbpKy.js.map → roles-De2CzGCy.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-B9P_7SR_.js → tasks-4yL5EfxI.js} +2 -2
- package/dashboard/dist/assets/{tasks-B9P_7SR_.js.map → tasks-4yL5EfxI.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CcLT-IrY.js → topics-DDKHpRwP.js} +2 -2
- package/dashboard/dist/assets/{topics-CcLT-IrY.js.map → topics-DDKHpRwP.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-B9UOxef_.js → useEventHooks-NzIyvoGY.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-B9UOxef_.js.map → useEventHooks-NzIyvoGY.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-V_MENSI5.js → useYamlActivityEvents-Dv6GhDkh.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-V_MENSI5.js.map → useYamlActivityEvents-Dv6GhDkh.js.map} +1 -1
- package/dashboard/dist/assets/{users-BHF3YOU1.js → users-pSMWP58G.js} +2 -2
- package/dashboard/dist/assets/{users-BHF3YOU1.js.map → users-pSMWP58G.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-DorgmYSk.js → workflows-COYPOe2I.js} +2 -2
- package/dashboard/dist/assets/{workflows-DorgmYSk.js.map → workflows-COYPOe2I.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DTGpqnEG.js → yaml-workflows-1dF3ig6u.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DTGpqnEG.js.map → yaml-workflows-1dF3ig6u.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/escalations.md +6 -4
- package/docs/api/http/settings.md +1 -1
- package/docs/api/sdk/escalations.md +6 -4
- package/package.json +3 -2
- 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
|
-
(
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
package/build/api/settings.js
CHANGED
|
@@ -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
|
|
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 =
|
|
27
|
-
const transport = forceNats &&
|
|
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:
|
|
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:
|
|
175
|
-
? { nats: { url: config_1.config.NATS_URL, token:
|
|
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()`.
|
package/build/lib/events/nats.js
CHANGED
|
@@ -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 ||
|
|
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
|
/**
|
package/build/modules/config.js
CHANGED
|
@@ -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
|
|
14
|
-
if (!
|
|
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:
|
|
19
|
-
natsToken:
|
|
18
|
+
natsWsUrl: natsAdapter.wsUrl,
|
|
19
|
+
natsToken: natsAdapter.authToken,
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
22
|
exports.default = router;
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -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>;
|