@hotmeshio/long-tail 0.4.12 → 0.4.14
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/README.md +76 -100
- package/build/api/escalations/helpers.d.ts +14 -0
- package/build/api/escalations/helpers.js +14 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +5 -1
- package/build/api/escalations/metadata.d.ts +56 -0
- package/build/api/escalations/metadata.js +178 -0
- package/build/api/index.d.ts +2 -1
- package/build/api/index.js +3 -2
- package/build/api/{mcp-runs.d.ts → pipelines.d.ts} +18 -0
- package/build/api/{mcp-runs.js → pipelines.js} +36 -4
- package/build/api/workflows/discovery.js +1 -1
- package/build/bin/ltc.js +17 -0
- package/build/lib/cli/commands/escalations.d.ts +9 -0
- package/build/lib/cli/commands/escalations.js +36 -0
- package/build/lib/db/schemas/010_metadata_gin.sql +5 -0
- package/build/routes/escalations/index.js +3 -0
- package/build/routes/escalations/metadata.d.ts +6 -0
- package/build/routes/escalations/metadata.js +86 -0
- package/build/routes/index.js +3 -2
- package/build/routes/{mcp-runs.js → pipelines.js} +17 -4
- package/build/sdk/index.d.ts +30 -4
- package/build/sdk/index.js +15 -5
- package/build/services/escalation/crud.d.ts +5 -0
- package/build/services/escalation/crud.js +27 -0
- package/build/services/escalation/sql.d.ts +5 -0
- package/build/services/escalation/sql.js +39 -1
- package/build/services/interceptor/activities/escalation.js +11 -0
- package/build/services/{mcp-runs → pipelines}/sql.js +1 -1
- package/build/start/adapters.js +3 -6
- package/build/start/server.js +7 -3
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/startup.d.ts +3 -3
- package/dashboard/dist/assets/{AdminDashboard-B7AFFt4L.js → AdminDashboard-BuqyRY2r.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-B7AFFt4L.js.map → AdminDashboard-BuqyRY2r.js.map} +1 -1
- package/dashboard/dist/assets/AgentConfigPage-Bum1dUIi.js +16 -0
- package/dashboard/dist/assets/AgentConfigPage-Bum1dUIi.js.map +1 -0
- package/dashboard/dist/assets/{AgentDetailPage-DnHaUCS5.js → AgentDetailPage-0Kq-tBF2.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-DnHaUCS5.js.map → AgentDetailPage-0Kq-tBF2.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-BR2-PdTq.js → AgentsPage-B5gYDSOX.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-BR2-PdTq.js.map → AgentsPage-B5gYDSOX.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BWHThQDC.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-BWHThQDC.js.map +1 -0
- package/dashboard/dist/assets/BotPicker-BQ336piW.js +2 -0
- package/dashboard/dist/assets/{BotPicker-CAowL3ib.js.map → BotPicker-BQ336piW.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CkiJROX-.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-CSUKBvEN.js.map → CapabilitiesPage-CkiJROX-.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-Bv6ixURp.js → CollapsibleSection-SM8_UjNe.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-Bv6ixURp.js.map → CollapsibleSection-SM8_UjNe.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CdPKxRBj.js → CredentialsPage-f6niro9_.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CdPKxRBj.js.map → CredentialsPage-f6niro9_.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-BtdXRDqs.js → CronLabel-DINmdqoe.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-BtdXRDqs.js.map → CronLabel-DINmdqoe.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-Mq3SLUuv.js → CustomDurationPicker-BCUcYxfB.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-Mq3SLUuv.js.map → CustomDurationPicker-BCUcYxfB.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-lw2wmqty.js → DropZone-BkfRoUcm.js} +2 -2
- package/dashboard/dist/assets/{DropZone-lw2wmqty.js.map → DropZone-BkfRoUcm.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-DOTqB4ZX.js → ElapsedCell-DPYZnXsX.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-DOTqB4ZX.js.map → ElapsedCell-DPYZnXsX.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DSM8Mnb-.js → EscalationsOverview-CTB8AEBd.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DSM8Mnb-.js.map → EscalationsOverview-CTB8AEBd.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-C-HagWbs.js → EventTable-8_r3Tg09.js} +2 -2
- package/dashboard/dist/assets/{EventTable-C-HagWbs.js.map → EventTable-8_r3Tg09.js.map} +1 -1
- package/dashboard/dist/assets/{EventTopicPill-RaASGdZz.js → EventTopicPill-CCWCs07y.js} +2 -2
- package/dashboard/dist/assets/{EventTopicPill-RaASGdZz.js.map → EventTopicPill-CCWCs07y.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-Bjxnjv6p.js +2 -0
- package/dashboard/dist/assets/HomePage-Bjxnjv6p.js.map +1 -0
- package/dashboard/dist/assets/ListToolbar-B60JrvJ9.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-o8xSCSVv.js.map → ListToolbar-B60JrvJ9.js.map} +1 -1
- package/dashboard/dist/assets/McpOverview-whVRP_Nj.js +2 -0
- package/dashboard/dist/assets/McpOverview-whVRP_Nj.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryDetailPage-UR0bySPJ.js → McpQueryDetailPage-DPuujJkH.js} +2 -2
- package/dashboard/dist/assets/McpQueryDetailPage-DPuujJkH.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-C-mzOcGH.js → McpQueryPage-DciK6r7r.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-C-mzOcGH.js.map → McpQueryPage-DciK6r7r.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-QEz8BCTu.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-QEz8BCTu.js.map +1 -0
- package/dashboard/dist/assets/McpRunsPage-BA6AVpi_.js +2 -0
- package/dashboard/dist/assets/McpRunsPage-BA6AVpi_.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-DrUMzwnl.js +2 -0
- package/dashboard/dist/assets/OperatorDashboard-DrUMzwnl.js.map +1 -0
- package/dashboard/dist/assets/{PageHeader-B4w-LDUF.js → PageHeader-CR6TpJG_.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-B4w-LDUF.js.map → PageHeader-CR6TpJG_.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DQmNXYcG.js → PageHeaderWithStats-CRcQEAO1.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DQmNXYcG.js.map → PageHeaderWithStats-CRcQEAO1.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-8cJEBC_E.js → ProcessDetailPage-Dc5ASJpQ.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-8cJEBC_E.js.map → ProcessDetailPage-Dc5ASJpQ.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CiprI5Wj.js → ProcessesListPage-Sa-bjC-g.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CiprI5Wj.js.map → ProcessesListPage-Sa-bjC-g.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-Dk-YUxCm.js → RolePill-BC54Vn-U.js} +2 -2
- package/dashboard/dist/assets/{RolePill-Dk-YUxCm.js.map → RolePill-BC54Vn-U.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-xo6AgPym.js → RolesPage-DmO8Jlbw.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-xo6AgPym.js.map → RolesPage-DmO8Jlbw.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-DPXWgduq.js → RunAsSelector-yWEwIZRe.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-DPXWgduq.js.map → RunAsSelector-yWEwIZRe.js.map} +1 -1
- package/dashboard/dist/assets/{ServerName-A6Wlv3vZ.js → ServerName-Q6okiv4f.js} +2 -2
- package/dashboard/dist/assets/{ServerName-A6Wlv3vZ.js.map → ServerName-Q6okiv4f.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BzG8QxYs.js → SwimlaneTimeline-CmzfFQ09.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BzG8QxYs.js.map → SwimlaneTimeline-CmzfFQ09.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CYh3PFNq.js → TagInput-D6l1SPWd.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CYh3PFNq.js.map → TagInput-D6l1SPWd.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Ck_0-iO2.js → TaskDetailPage-CI4JTC62.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Ck_0-iO2.js.map → TaskDetailPage-CI4JTC62.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BSFLiBcf.js → TaskQueuePill-iDBVCEQQ.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BSFLiBcf.js.map → TaskQueuePill-iDBVCEQQ.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-DtR4F0ho.js → TasksListPage-xdNmQsNE.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-DtR4F0ho.js.map → TasksListPage-xdNmQsNE.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BLNstYO1.js → TimeAgo-B_um9BWR.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BLNstYO1.js.map → TimeAgo-B_um9BWR.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DxIz3l1J.js → TimestampCell-BJ6trAqW.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DxIz3l1J.js.map → TimestampCell-BJ6trAqW.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-CcKNnnrK.js → ToolPill-HcRTggHo.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-CcKNnnrK.js.map → ToolPill-HcRTggHo.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-AVDlqGQI.js → ToolTestPanel-DMQhLDES.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-AVDlqGQI.js.map → ToolTestPanel-DMQhLDES.js.map} +1 -1
- package/dashboard/dist/assets/TopicDetailPage-YeGQA0vD.js +9 -0
- package/dashboard/dist/assets/TopicDetailPage-YeGQA0vD.js.map +1 -0
- package/dashboard/dist/assets/{TopicsPage-BdnJ7E_S.js → TopicsPage-B3QZNlWz.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BdnJ7E_S.js.map → TopicsPage-B3QZNlWz.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-Bk-pzKYb.js → UserName-MpSZ2_EH.js} +2 -2
- package/dashboard/dist/assets/{UserName-Bk-pzKYb.js.map → UserName-MpSZ2_EH.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-DqMqDb1h.js +2 -0
- package/dashboard/dist/assets/WorkflowExecutionPage-DqMqDb1h.js.map +1 -0
- package/dashboard/dist/assets/WorkflowPill-54px0YiY.js +2 -0
- package/dashboard/dist/assets/WorkflowPill-54px0YiY.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-nXLTR0OO.js → WorkflowsDashboard-BF7FpMmk.js} +2 -2
- package/dashboard/dist/assets/WorkflowsDashboard-BF7FpMmk.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowsOverview-BdSHBzzd.js → WorkflowsOverview-YFc_KBMS.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BdSHBzzd.js.map → WorkflowsOverview-YFc_KBMS.js.map} +1 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-BOLs5KTB.js +2 -0
- package/dashboard/dist/assets/{YamlWorkflowsPage-BsO4L_SW.js.map → YamlWorkflowsPage-BOLs5KTB.js.map} +1 -1
- package/dashboard/dist/assets/{agents-CtF0uBav.js → agents-CPYVSCQ3.js} +2 -2
- package/dashboard/dist/assets/{agents-CtF0uBav.js.map → agents-CPYVSCQ3.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DOP_eck8.js → bots-DCXjHjID.js} +2 -2
- package/dashboard/dist/assets/{bots-DOP_eck8.js.map → bots-DCXjHjID.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DvxG02aF.js → capabilities-CreogBYU.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DvxG02aF.js.map → capabilities-CreogBYU.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-Dmq81vAY.js → controlplane-Cm_-Gb1x.js} +2 -2
- package/dashboard/dist/assets/{controlplane-Dmq81vAY.js.map → controlplane-Cm_-Gb1x.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-CLqe28Ba.js +2 -0
- package/dashboard/dist/assets/escalation-columns-CLqe28Ba.js.map +1 -0
- package/dashboard/dist/assets/{escalation-BP3UWfIe.js → escalation-ulsBFHVb.js} +2 -2
- package/dashboard/dist/assets/{escalation-BP3UWfIe.js.map → escalation-ulsBFHVb.js.map} +1 -1
- package/dashboard/dist/assets/{helpers-B_PYr0pL.js → helpers-etjHeZEI.js} +2 -2
- package/dashboard/dist/assets/{helpers-B_PYr0pL.js.map → helpers-etjHeZEI.js.map} +1 -1
- package/dashboard/dist/assets/index-7Fbktqcl.js +2 -0
- package/dashboard/dist/assets/index-7Fbktqcl.js.map +1 -0
- package/dashboard/dist/assets/{index-DQs-LMoa.js → index-BkCkBW_D.js} +2 -2
- package/dashboard/dist/assets/{index-DQs-LMoa.js.map → index-BkCkBW_D.js.map} +1 -1
- package/dashboard/dist/assets/index-BkOv2dQA.js +2 -0
- package/dashboard/dist/assets/{index-Bb1ycul8.js.map → index-BkOv2dQA.js.map} +1 -1
- package/dashboard/dist/assets/index-C37LMzJa.css +1 -0
- package/dashboard/dist/assets/{index-CkcPZdQm.js → index-CKDOaej4.js} +6 -6
- package/dashboard/dist/assets/index-CKDOaej4.js.map +1 -0
- package/dashboard/dist/assets/{index-Do1x4kN0.js → index-CcvHiZW-.js} +2 -2
- package/dashboard/dist/assets/{index-Do1x4kN0.js.map → index-CcvHiZW-.js.map} +1 -1
- package/dashboard/dist/assets/{index-B80zLZVl.js → index-CihScSLF.js} +2 -2
- package/dashboard/dist/assets/{index-B80zLZVl.js.map → index-CihScSLF.js.map} +1 -1
- package/dashboard/dist/assets/{index-B3wGNZN2.js → index-Cnpo94XG.js} +2 -2
- package/dashboard/dist/assets/{index-B3wGNZN2.js.map → index-Cnpo94XG.js.map} +1 -1
- package/dashboard/dist/assets/index-DFuHrLll.js +15 -0
- package/dashboard/dist/assets/index-DFuHrLll.js.map +1 -0
- package/dashboard/dist/assets/{index-DzQBDt3K.js → index-DGpIF_Td.js} +2 -2
- package/dashboard/dist/assets/{index-DzQBDt3K.js.map → index-DGpIF_Td.js.map} +1 -1
- package/dashboard/dist/assets/index-DT0JeuiL.js +2 -0
- package/dashboard/dist/assets/index-DT0JeuiL.js.map +1 -0
- package/dashboard/dist/assets/index-DT68ewTC.js +2 -0
- package/dashboard/dist/assets/{index-EqKHsaVz.js.map → index-DT68ewTC.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bv0eLXZq.js → index-DVqtJBno.js} +4 -4
- package/dashboard/dist/assets/{index-Bv0eLXZq.js.map → index-DVqtJBno.js.map} +1 -1
- package/dashboard/dist/assets/{index-BnB7G5bA.js → index-DYmrNJ_H.js} +23 -23
- package/dashboard/dist/assets/index-DYmrNJ_H.js.map +1 -0
- package/dashboard/dist/assets/{knowledge--SApApck.js → knowledge-CXA2DJwY.js} +2 -2
- package/dashboard/dist/assets/{knowledge--SApApck.js.map → knowledge-CXA2DJwY.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-dn9iPrzm.js → mcp-DeC-PpeL.js} +2 -2
- package/dashboard/dist/assets/{mcp-dn9iPrzm.js.map → mcp-DeC-PpeL.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CgiU2UR6.js → mcp-query-DldD_RPZ.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CgiU2UR6.js.map → mcp-query-DldD_RPZ.js.map} +1 -1
- package/dashboard/dist/assets/{namespaces-D93H3wFO.js → namespaces-BIGZ6exX.js} +2 -2
- package/dashboard/dist/assets/{namespaces-D93H3wFO.js.map → namespaces-BIGZ6exX.js.map} +1 -1
- package/dashboard/dist/assets/pipelines-BtihifKT.js +2 -0
- package/dashboard/dist/assets/pipelines-BtihifKT.js.map +1 -0
- package/dashboard/dist/assets/{roles-DuOWZTpx.js → roles-4DocbpKy.js} +2 -2
- package/dashboard/dist/assets/{roles-DuOWZTpx.js.map → roles-4DocbpKy.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DoCbLKz4.js → tasks-B9P_7SR_.js} +2 -2
- package/dashboard/dist/assets/{tasks-DoCbLKz4.js.map → tasks-B9P_7SR_.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CS7Sxf_-.js → topics-CcLT-IrY.js} +2 -2
- package/dashboard/dist/assets/{topics-CS7Sxf_-.js.map → topics-CcLT-IrY.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-CrIe_Ulh.js → useEventHooks-B9UOxef_.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-CrIe_Ulh.js.map → useEventHooks-B9UOxef_.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-JzvzGsUR.js → useYamlActivityEvents-V_MENSI5.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-JzvzGsUR.js.map → useYamlActivityEvents-V_MENSI5.js.map} +1 -1
- package/dashboard/dist/assets/{users-DnxSh2dX.js → users-BHF3YOU1.js} +2 -2
- package/dashboard/dist/assets/{users-DnxSh2dX.js.map → users-BHF3YOU1.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-5gSix3t2.js → vendor-icons-CrrAvF2g.js} +131 -111
- package/dashboard/dist/assets/vendor-icons-CrrAvF2g.js.map +1 -0
- package/dashboard/dist/assets/{workflows-zFmmxc08.js → workflows-DorgmYSk.js} +2 -2
- package/dashboard/dist/assets/{workflows-zFmmxc08.js.map → workflows-DorgmYSk.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-VSax0tKa.js → yaml-workflows-DTGpqnEG.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-VSax0tKa.js.map → yaml-workflows-DTGpqnEG.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +96 -0
- package/docs/api/http/{mcp-runs.md → pipelines.md} +39 -25
- package/docs/api/sdk/escalations.md +84 -0
- package/docs/cli.md +8 -0
- package/docs/dashboard.md +1 -1
- package/docs/sdk.md +2 -2
- package/package.json +1 -1
- package/dashboard/dist/assets/AgentConfigPage-CjuCbr5J.js +0 -16
- package/dashboard/dist/assets/AgentConfigPage-CjuCbr5J.js.map +0 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CEkeo_N4.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CEkeo_N4.js.map +0 -1
- package/dashboard/dist/assets/BotPicker-CAowL3ib.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-CSUKBvEN.js +0 -2
- package/dashboard/dist/assets/HomePage-BkMEYnRK.js +0 -2
- package/dashboard/dist/assets/HomePage-BkMEYnRK.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-o8xSCSVv.js +0 -2
- package/dashboard/dist/assets/McpOverview-C4man2br.js +0 -2
- package/dashboard/dist/assets/McpOverview-C4man2br.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-UR0bySPJ.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-bJl08JSG.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-bJl08JSG.js.map +0 -1
- package/dashboard/dist/assets/McpRunsPage-i2FGJ6yf.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-i2FGJ6yf.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-DLpqyLle.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-DLpqyLle.js.map +0 -1
- package/dashboard/dist/assets/TopicDetailPage-DQkoAlsj.js +0 -9
- package/dashboard/dist/assets/TopicDetailPage-DQkoAlsj.js.map +0 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-B6mBqWq6.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-B6mBqWq6.js.map +0 -1
- package/dashboard/dist/assets/WorkflowPill-BkfIn8N3.js +0 -2
- package/dashboard/dist/assets/WorkflowPill-BkfIn8N3.js.map +0 -1
- package/dashboard/dist/assets/WorkflowsDashboard-nXLTR0OO.js.map +0 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-BsO4L_SW.js +0 -2
- package/dashboard/dist/assets/escalation-columns-BayccZzU.js +0 -2
- package/dashboard/dist/assets/escalation-columns-BayccZzU.js.map +0 -1
- package/dashboard/dist/assets/index-Bb1ycul8.js +0 -2
- package/dashboard/dist/assets/index-BnB7G5bA.js.map +0 -1
- package/dashboard/dist/assets/index-BnVnJcXw.js +0 -2
- package/dashboard/dist/assets/index-BnVnJcXw.js.map +0 -1
- package/dashboard/dist/assets/index-CkcPZdQm.js.map +0 -1
- package/dashboard/dist/assets/index-CsagXf3M.js +0 -2
- package/dashboard/dist/assets/index-CsagXf3M.js.map +0 -1
- package/dashboard/dist/assets/index-DZI2L4ag.css +0 -1
- package/dashboard/dist/assets/index-EqKHsaVz.js +0 -2
- package/dashboard/dist/assets/index-ox042ec_.js +0 -15
- package/dashboard/dist/assets/index-ox042ec_.js.map +0 -1
- package/dashboard/dist/assets/mcp-runs-BN5MrKai.js +0 -2
- package/dashboard/dist/assets/mcp-runs-BN5MrKai.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-5gSix3t2.js.map +0 -1
- /package/build/routes/{mcp-runs.d.ts → pipelines.d.ts} +0 -0
- /package/build/services/{mcp-runs → pipelines}/enrichment.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/enrichment.js +0 -0
- /package/build/services/{mcp-runs → pipelines}/events.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/events.js +0 -0
- /package/build/services/{mcp-runs → pipelines}/execution-builder.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/execution-builder.js +0 -0
- /package/build/services/{mcp-runs → pipelines}/index.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/index.js +0 -0
- /package/build/services/{mcp-runs → pipelines}/queries.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/queries.js +0 -0
- /package/build/services/{mcp-runs → pipelines}/sql.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/types.d.ts +0 -0
- /package/build/services/{mcp-runs → pipelines}/types.js +0 -0
- /package/docs/api/sdk/{mcp-runs.md → pipelines.md} +0 -0
package/README.md
CHANGED
|
@@ -1,41 +1,14 @@
|
|
|
1
1
|
# Long Tail
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Write durable workflows in TypeScript. When they need a human, they escalate. When they need AI, they orchestrate. When a pattern repeats, they compile it away. Postgres is the engine.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install @hotmeshio/long-tail
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## How it works
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- **Identity everywhere** — Workflows know who started them, whose credentials govern their execution, and what permissions are in play. IAM is not bolted on — it's woven into every activity call.
|
|
13
|
-
- **Human-in-the-loop** — When confidence is low, the workflow escalates. RBAC-scoped escalation chains route work to the right reviewer. Approval workflows, content review, document verification — the pattern is the same.
|
|
14
|
-
- **AI triage** — When human-in-the-loop teams can't resolve a request, AI takes over. Its tool calls are checkpointed. And when the fix works, it compiles into a deterministic pipeline for next time.
|
|
15
|
-
- **MCP tool orchestration** — Describe what you need. If you've registered the tools, the Pipeline Designer builds the workflow. Every compiled pipeline deploys as a reusable MCP tool.
|
|
16
|
-
|
|
17
|
-
A dashboard, REST API, and live event stream ship with the package. Use what you need.
|
|
18
|
-
|
|
19
|
-
## Start
|
|
20
|
-
|
|
21
|
-
Point at Postgres. Everything else is optional.
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
import { start } from '@hotmeshio/long-tail';
|
|
25
|
-
import * as myWorkflow from './workflows/my-workflow';
|
|
26
|
-
|
|
27
|
-
const lt = await start({
|
|
28
|
-
database: { host: 'localhost', port: 5432, user: 'postgres', password: 'password', database: 'mydb' },
|
|
29
|
-
workers: [{ taskQueue: 'default', workflow: myWorkflow.reviewContent }],
|
|
30
|
-
auth: { secret: process.env.JWT_SECRET },
|
|
31
|
-
});
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Dashboard at [http://localhost:3000](http://localhost:3000). The [boilerplate](https://github.com/hotmeshio/long-tail-boilerplate) has a working project with custom MCP servers, MinIO, and example workflows.
|
|
35
|
-
|
|
36
|
-
## Write a Durable Workflow
|
|
37
|
-
|
|
38
|
-
A workflow receives an envelope and returns a result. Each activity call checkpoints — no work is lost, no step runs twice.
|
|
11
|
+
You write a workflow function. Each activity call checkpoints to Postgres — if the process crashes, it resumes from the last completed step.
|
|
39
12
|
|
|
40
13
|
```typescript
|
|
41
14
|
import { Durable } from '@hotmeshio/hotmesh';
|
|
@@ -51,6 +24,7 @@ export async function reviewContent(envelope: LTEnvelope) {
|
|
|
51
24
|
return { type: 'return' as const, data: { approved: true, analysis } };
|
|
52
25
|
}
|
|
53
26
|
|
|
27
|
+
// Low confidence — escalate to a human reviewer
|
|
54
28
|
return {
|
|
55
29
|
type: 'escalation' as const,
|
|
56
30
|
role: 'reviewer',
|
|
@@ -60,32 +34,39 @@ export async function reviewContent(envelope: LTEnvelope) {
|
|
|
60
34
|
}
|
|
61
35
|
```
|
|
62
36
|
|
|
63
|
-
|
|
37
|
+
That's a complete workflow. It runs, checkpoints, and when confidence is low, it hands off to a human. The human resolves it through the dashboard or API, and the workflow completes. No separate queue system, no webhook callbacks — the escalation is part of the execution.
|
|
38
|
+
|
|
39
|
+
Activities are plain functions:
|
|
64
40
|
|
|
65
41
|
```typescript
|
|
66
|
-
// activities.ts
|
|
67
42
|
export async function analyzeContent(content: string) {
|
|
68
43
|
const result = await llm.classify(content);
|
|
69
44
|
return { confidence: result.confidence, flags: result.flags };
|
|
70
45
|
}
|
|
71
46
|
```
|
|
72
47
|
|
|
73
|
-
##
|
|
48
|
+
## Start
|
|
74
49
|
|
|
75
|
-
|
|
50
|
+
Point at Postgres. Everything else is optional.
|
|
76
51
|
|
|
77
|
-
```
|
|
78
|
-
|
|
52
|
+
```typescript
|
|
53
|
+
import { start } from '@hotmeshio/long-tail';
|
|
79
54
|
|
|
80
|
-
|
|
81
|
-
|
|
55
|
+
const lt = await start({
|
|
56
|
+
database: { host: 'localhost', port: 5432, user: 'postgres', password: 'password', database: 'mydb' },
|
|
57
|
+
workers: [{ taskQueue: 'default', workflow: reviewContent }],
|
|
58
|
+
});
|
|
82
59
|
```
|
|
83
60
|
|
|
84
|
-
|
|
61
|
+
Dashboard at [http://localhost:3000](http://localhost:3000). The [boilerplate](https://github.com/hotmeshio/long-tail-boilerplate) has a working project with workflows, MCP servers, and MinIO.
|
|
62
|
+
|
|
63
|
+
## The pattern
|
|
85
64
|
|
|
86
|
-
|
|
65
|
+
Most systems start with a durable workflow and stop there. Long Tail keeps going.
|
|
87
66
|
|
|
88
|
-
|
|
67
|
+
**Step 1 — Author a durable workflow.** Your function checkpoints to Postgres. It can sleep, branch, call child workflows, wait for signals. Standard durable execution.
|
|
68
|
+
|
|
69
|
+
**Step 2 — Certify it.** Promotion to certified adds interceptor guarantees: failures escalate instead of throwing, escalation chains route through RBAC-scoped roles, and every error is either handled or surfaced. It cannot silently fail.
|
|
89
70
|
|
|
90
71
|
```bash
|
|
91
72
|
curl -X PUT http://localhost:3000/api/workflows/reviewContent/config \
|
|
@@ -93,13 +74,17 @@ curl -X PUT http://localhost:3000/api/workflows/reviewContent/config \
|
|
|
93
74
|
-d '{ "invocable": true, "task_queue": "default", "default_role": "reviewer" }'
|
|
94
75
|
```
|
|
95
76
|
|
|
96
|
-
|
|
77
|
+
**Step 3 — React to events.** Workflows publish topics. Agents subscribe. When `activity.failed` fires, an automation can re-run the step, notify a team, or trigger a different workflow. The choreography is dynamic — add subscribers through the dashboard without changing code.
|
|
78
|
+
|
|
79
|
+
**Step 4 — Compile what repeats.** The Pipeline Designer takes a working execution and compiles it into a deterministic YAML DAG. No LLM at runtime, no replay overhead, typed inputs and outputs. It deploys as a reusable tool that any workflow or API call can invoke.
|
|
80
|
+
|
|
81
|
+
Over time, the system accumulates compiled tools. Problems that once required a human, then required AI reasoning, eventually require neither.
|
|
97
82
|
|
|
98
|
-
## Register MCP
|
|
83
|
+
## Register MCP tools
|
|
99
84
|
|
|
100
|
-
Long Tail connects to any MCP server
|
|
85
|
+
Long Tail connects to any MCP server. Registered tools become durable activities and are available to the Pipeline Designer.
|
|
101
86
|
|
|
102
|
-
**
|
|
87
|
+
**Existing package — no code:**
|
|
103
88
|
|
|
104
89
|
```bash
|
|
105
90
|
curl -X POST http://localhost:3000/api/mcp/servers \
|
|
@@ -113,21 +98,14 @@ curl -X POST http://localhost:3000/api/mcp/servers \
|
|
|
113
98
|
}'
|
|
114
99
|
```
|
|
115
100
|
|
|
116
|
-
**
|
|
101
|
+
**Remote server — point at a URL:**
|
|
117
102
|
|
|
118
103
|
```bash
|
|
119
104
|
curl -X POST http://localhost:3000/api/mcp/servers \
|
|
120
|
-
-
|
|
121
|
-
-d '{
|
|
122
|
-
"name": "my-python-server",
|
|
123
|
-
"transport_type": "sse",
|
|
124
|
-
"transport_config": { "url": "http://python-service:8000/mcp" },
|
|
125
|
-
"tags": ["ml", "classification"],
|
|
126
|
-
"compile_hints": "Returns confidence scores. Use threshold 0.85 for auto-approve."
|
|
127
|
-
}'
|
|
105
|
+
-d '{ "name": "my-python-server", "transport_type": "sse", "transport_config": { "url": "http://python-service:8000/mcp" } }'
|
|
128
106
|
```
|
|
129
107
|
|
|
130
|
-
**
|
|
108
|
+
**In-process — write your own:**
|
|
131
109
|
|
|
132
110
|
```typescript
|
|
133
111
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
@@ -139,8 +117,8 @@ export function createImageToolsServer(): McpServer {
|
|
|
139
117
|
|
|
140
118
|
registerMcpTool(server, 'resize_image', 'Resize an image.', {
|
|
141
119
|
path: z.string().describe('Path to the image'),
|
|
142
|
-
width: z.number().optional()
|
|
143
|
-
height: z.number().optional()
|
|
120
|
+
width: z.number().optional(),
|
|
121
|
+
height: z.number().optional(),
|
|
144
122
|
}, async (args: any) => ({
|
|
145
123
|
content: [{ type: 'text', text: JSON.stringify(await resize(args)) }],
|
|
146
124
|
}));
|
|
@@ -152,36 +130,33 @@ export function createImageToolsServer(): McpServer {
|
|
|
152
130
|
```typescript
|
|
153
131
|
const lt = await start({
|
|
154
132
|
// ...
|
|
155
|
-
mcp: {
|
|
156
|
-
serverFactories: { 'image-tools': createImageToolsServer },
|
|
157
|
-
},
|
|
133
|
+
mcp: { serverFactories: { 'image-tools': createImageToolsServer } },
|
|
158
134
|
});
|
|
159
135
|
```
|
|
160
136
|
|
|
161
|
-
All three paths produce the same outcome: tools callable as durable activities.
|
|
137
|
+
All three paths produce the same outcome: tools callable as durable activities. See the [MCP guide](docs/mcp.md).
|
|
162
138
|
|
|
163
|
-
##
|
|
139
|
+
## Compile workflows
|
|
164
140
|
|
|
165
|
-
|
|
141
|
+
The `ltc` compiler scans TypeScript workflow files and compiles them to YAML DAGs — like `tsc` for workflows.
|
|
166
142
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
143
|
+
```bash
|
|
144
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
145
|
+
npx ltc compile workflows/
|
|
146
|
+
```
|
|
170
147
|
|
|
171
|
-
The
|
|
148
|
+
The source is the spec. The compiled YAML is the optimized execution. Both live in the repo. See the [Compiler Guide](docs/compiler.md).
|
|
172
149
|
|
|
173
|
-
## Full
|
|
150
|
+
## Full configuration
|
|
174
151
|
|
|
175
152
|
```typescript
|
|
176
153
|
const lt = await start({
|
|
177
154
|
database: { connectionString: process.env.DATABASE_URL },
|
|
178
|
-
workers: [{ taskQueue: 'default', workflow:
|
|
155
|
+
workers: [{ taskQueue: 'default', workflow: reviewContent }],
|
|
179
156
|
|
|
180
157
|
// Everything below is optional
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
serverFactories: { 'my-tools': createMyToolsServer },
|
|
184
|
-
},
|
|
158
|
+
seed: { admin: { externalId: 'admin', password: process.env.ADMIN_PASSWORD } },
|
|
159
|
+
mcp: { server: { enabled: true }, serverFactories: { 'my-tools': createMyToolsServer } },
|
|
185
160
|
escalation: { strategy: 'mcp' },
|
|
186
161
|
auth: { secret: process.env.JWT_SECRET },
|
|
187
162
|
telemetry: { honeycomb: { apiKey: process.env.HNY } },
|
|
@@ -190,56 +165,57 @@ const lt = await start({
|
|
|
190
165
|
});
|
|
191
166
|
```
|
|
192
167
|
|
|
193
|
-
##
|
|
168
|
+
## Embed in an existing app
|
|
194
169
|
|
|
195
|
-
Long Tail
|
|
170
|
+
Long Tail runs as an embedded package inside NestJS, Express, or any Node.js application. No extra HTTP server, no extra ports.
|
|
196
171
|
|
|
197
172
|
```typescript
|
|
198
173
|
import { start, createClient } from '@hotmeshio/long-tail';
|
|
199
174
|
|
|
200
|
-
await start({
|
|
175
|
+
const lt = await start({
|
|
201
176
|
database: { connectionString: process.env.DATABASE_URL },
|
|
202
177
|
server: { enabled: false },
|
|
203
|
-
|
|
178
|
+
seed: { admin: { externalId: 'system' } },
|
|
179
|
+
workers: [{ taskQueue: 'default', workflow: reviewContent }],
|
|
204
180
|
});
|
|
205
181
|
|
|
206
|
-
const
|
|
182
|
+
const client = createClient({ auth: { userId: lt.adminUserId } });
|
|
207
183
|
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
const result = await lt.escalations.claim({ id: 'esc_123', durationMinutes: 30 });
|
|
184
|
+
const tasks = await client.tasks.list({ status: 'completed', limit: 10 });
|
|
185
|
+
const result = await client.escalations.claim({ id: 'esc_123', durationMinutes: 30 });
|
|
211
186
|
```
|
|
212
187
|
|
|
213
|
-
|
|
188
|
+
Mount the dashboard at a subpath:
|
|
214
189
|
|
|
215
190
|
```typescript
|
|
216
|
-
|
|
217
|
-
console.log('done:', event.workflowId);
|
|
218
|
-
});
|
|
191
|
+
import { LTExpressAdapter } from '@hotmeshio/long-tail';
|
|
219
192
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
193
|
+
const adapter = new LTExpressAdapter();
|
|
194
|
+
adapter.setBasePath('/admin/longtail');
|
|
195
|
+
app.use('/admin/longtail', adapter.getRouter());
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Subscribe to events with callbacks:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
client.events.on('task.completed', (event) => console.log('done:', event.workflowId));
|
|
202
|
+
client.events.on('escalation.*', (event) => notifyTeam(event));
|
|
223
203
|
```
|
|
224
204
|
|
|
225
|
-
Every SDK call returns an `LTApiResult` — same status codes, same validation, same RBAC.
|
|
205
|
+
Every SDK call returns an `LTApiResult` — same status codes, same validation, same RBAC. See the [SDK guide](docs/sdk.md).
|
|
226
206
|
|
|
227
207
|
## Deployment
|
|
228
208
|
|
|
229
209
|
Three modes from the same codebase:
|
|
230
210
|
|
|
231
211
|
```typescript
|
|
232
|
-
//
|
|
212
|
+
// Standalone — dashboard + API + workers
|
|
233
213
|
await start({ database: { connectionString: process.env.DATABASE_URL } });
|
|
234
214
|
|
|
235
|
-
//
|
|
236
|
-
await start({
|
|
237
|
-
database: { connectionString: process.env.DATABASE_URL },
|
|
238
|
-
server: { enabled: false },
|
|
239
|
-
workers: [{ taskQueue: 'default', workflow: reviewContent.reviewContent }],
|
|
240
|
-
});
|
|
215
|
+
// Worker-only — no HTTP server
|
|
216
|
+
await start({ database: { connectionString: process.env.DATABASE_URL }, server: { enabled: false }, workers: [...] });
|
|
241
217
|
|
|
242
|
-
//
|
|
218
|
+
// Embedded — inside your app, SDK calls only
|
|
243
219
|
await start({ database: { connectionString: process.env.DATABASE_URL }, server: { enabled: false } });
|
|
244
220
|
const lt = createClient({ auth: { userId: 'service' } });
|
|
245
221
|
```
|
|
@@ -250,12 +226,12 @@ All modes share PostgreSQL and scale independently. See [Cloud Deployment](docs/
|
|
|
250
226
|
|
|
251
227
|
| Guide | What it covers |
|
|
252
228
|
|-------|---------------|
|
|
253
|
-
| [The Long Tail Story](docs/story.md) | Why this exists, what accumulates over time
|
|
229
|
+
| [The Long Tail Story](docs/story.md) | Why this exists, what accumulates over time |
|
|
254
230
|
| [Workflows](docs/workflows.md) | Activities, interceptor, escalation lifecycle, composition |
|
|
255
231
|
| [IAM](docs/iam.md) | Identity propagation, service accounts, credential exchange |
|
|
256
232
|
| [Dashboard](docs/dashboard.md) | Navigation, key pages, event feed |
|
|
257
233
|
| [MCP](docs/mcp.md) | Server registration, tool calls, human queue |
|
|
258
|
-
| [Compilation](docs/compilation.md) | Dynamic
|
|
234
|
+
| [Compilation](docs/compilation.md) | Dynamic to deterministic pipeline wizard |
|
|
259
235
|
| [Compiler](docs/compiler.md) | `ltc compile` — durable TypeScript to YAML DAGs |
|
|
260
236
|
| [CLI](docs/cli.md) | `ltc` — terminal access to workflows, escalations, knowledge, MCP |
|
|
261
237
|
| [Escalation Strategies](docs/escalation-strategies.md) | Default, MCP triage, custom handlers |
|
|
@@ -266,7 +242,7 @@ All modes share PostgreSQL and scale independently. See [Cloud Deployment](docs/
|
|
|
266
242
|
|
|
267
243
|
**Adapters:** [Auth](docs/auth.md) · [Events](docs/events.md) · [Telemetry](docs/telemetry.md) · [Logging](docs/logging.md) · [Maintenance](docs/maintenance.md) · [OAuth](docs/oauth-and-delegation.md)
|
|
268
244
|
|
|
269
|
-
**HTTP API:** [Workflows](docs/api/http/workflows.md) · [Tasks](docs/api/http/tasks.md) · [Escalations](docs/api/http/escalations.md) · [YAML Workflows](docs/api/http/yaml-workflows.md) · [Users](docs/api/http/users.md) · [Roles](docs/api/http/roles.md) · [Service Accounts](docs/api/http/service-accounts.md) · [MCP Servers](docs/api/http/mcp-servers.md) · [
|
|
245
|
+
**HTTP API:** [Workflows](docs/api/http/workflows.md) · [Tasks](docs/api/http/tasks.md) · [Escalations](docs/api/http/escalations.md) · [YAML Workflows](docs/api/http/yaml-workflows.md) · [Users](docs/api/http/users.md) · [Roles](docs/api/http/roles.md) · [Service Accounts](docs/api/http/service-accounts.md) · [MCP Servers](docs/api/http/mcp-servers.md) · [Pipelines](docs/api/http/pipelines.md) · [Exports](docs/api/http/exports.md)
|
|
270
246
|
|
|
271
247
|
**SDK:** [Overview](docs/sdk.md) · [Workflows](docs/api/sdk/workflows.md) · [Tasks](docs/api/sdk/tasks.md) · [Escalations](docs/api/sdk/escalations.md) · [YAML Workflows](docs/api/sdk/yaml-workflows.md) · [MCP](docs/api/sdk/mcp.md) · [Events](docs/api/sdk/events.md)
|
|
272
248
|
|
|
@@ -7,4 +7,18 @@ export declare function checkBulkPermission(userId: string, ids: string[]): Prom
|
|
|
7
7
|
status: 403;
|
|
8
8
|
error: string;
|
|
9
9
|
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve an optional assignee external_id to an internal userId.
|
|
12
|
+
* When omitted, returns the caller's userId from auth.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveAssignee(assignee: string | undefined, auth: {
|
|
15
|
+
userId: string;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
userId: string;
|
|
18
|
+
} | {
|
|
19
|
+
error: {
|
|
20
|
+
status: number;
|
|
21
|
+
error: string;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
10
24
|
export declare function publishBulkClaimEvents(ids: string[], assignedTo: string): void;
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.getVisibleRoles = getVisibleRoles;
|
|
37
37
|
exports.validateIds = validateIds;
|
|
38
38
|
exports.checkBulkPermission = checkBulkPermission;
|
|
39
|
+
exports.resolveAssignee = resolveAssignee;
|
|
39
40
|
exports.publishBulkClaimEvents = publishBulkClaimEvents;
|
|
40
41
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
41
42
|
const userService = __importStar(require("../../services/user"));
|
|
@@ -64,6 +65,19 @@ async function checkBulkPermission(userId, ids) {
|
|
|
64
65
|
}
|
|
65
66
|
return { allowed: true };
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve an optional assignee external_id to an internal userId.
|
|
70
|
+
* When omitted, returns the caller's userId from auth.
|
|
71
|
+
*/
|
|
72
|
+
async function resolveAssignee(assignee, auth) {
|
|
73
|
+
if (!assignee)
|
|
74
|
+
return { userId: auth.userId };
|
|
75
|
+
const user = await userService.getUserByExternalId(assignee);
|
|
76
|
+
if (!user) {
|
|
77
|
+
return { error: { status: 404, error: `User not found for external_id: ${assignee}` } };
|
|
78
|
+
}
|
|
79
|
+
return { userId: user.id };
|
|
80
|
+
}
|
|
67
81
|
function publishBulkClaimEvents(ids, assignedTo) {
|
|
68
82
|
for (const id of ids) {
|
|
69
83
|
(0, publish_1.publishEscalationEvent)({
|
|
@@ -4,3 +4,4 @@ export { getEscalation, getEscalationsByWorkflowId, escalateToRole } from './sin
|
|
|
4
4
|
export { claimEscalation, releaseEscalation } from './claim';
|
|
5
5
|
export { releaseExpiredClaims, updatePriority, bulkClaim, bulkAssign, bulkEscalate, bulkTriage } from './bulk';
|
|
6
6
|
export { resolveEscalation } from './resolve';
|
|
7
|
+
export { findByMetadata, claimByMetadata, resolveByMetadata } from './metadata';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getEscalationStats = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
3
|
+
exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getEscalationStats = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
4
4
|
var create_1 = require("./create");
|
|
5
5
|
Object.defineProperty(exports, "createEscalation", { enumerable: true, get: function () { return create_1.createEscalation; } });
|
|
6
6
|
var list_1 = require("./list");
|
|
@@ -24,3 +24,7 @@ Object.defineProperty(exports, "bulkEscalate", { enumerable: true, get: function
|
|
|
24
24
|
Object.defineProperty(exports, "bulkTriage", { enumerable: true, get: function () { return bulk_1.bulkTriage; } });
|
|
25
25
|
var resolve_1 = require("./resolve");
|
|
26
26
|
Object.defineProperty(exports, "resolveEscalation", { enumerable: true, get: function () { return resolve_1.resolveEscalation; } });
|
|
27
|
+
var metadata_1 = require("./metadata");
|
|
28
|
+
Object.defineProperty(exports, "findByMetadata", { enumerable: true, get: function () { return metadata_1.findByMetadata; } });
|
|
29
|
+
Object.defineProperty(exports, "claimByMetadata", { enumerable: true, get: function () { return metadata_1.claimByMetadata; } });
|
|
30
|
+
Object.defineProperty(exports, "resolveByMetadata", { enumerable: true, get: function () { return metadata_1.resolveByMetadata; } });
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Find escalations by a metadata key-value pair.
|
|
4
|
+
*
|
|
5
|
+
* Uses JSONB containment (`@>`) backed by a GIN index.
|
|
6
|
+
* Results are RBAC-scoped to the caller's visible roles.
|
|
7
|
+
*
|
|
8
|
+
* @param input.key — metadata field name (e.g. `"orderId"`)
|
|
9
|
+
* @param input.value — metadata field value (e.g. `"order-123"`)
|
|
10
|
+
* @param input.status — optional status filter (e.g. `"pending"`)
|
|
11
|
+
* @returns `{ status: 200, data: { escalations, total } }`
|
|
12
|
+
*/
|
|
13
|
+
export declare function findByMetadata(input: {
|
|
14
|
+
key: string;
|
|
15
|
+
value: string;
|
|
16
|
+
status?: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
offset?: number;
|
|
19
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Claim an escalation by metadata key-value pair.
|
|
22
|
+
*
|
|
23
|
+
* Finds one available (pending + unassigned/expired) escalation matching
|
|
24
|
+
* the metadata and claims it atomically. Optionally resolves an assignee
|
|
25
|
+
* from an external_id.
|
|
26
|
+
*
|
|
27
|
+
* @param input.key — metadata field name
|
|
28
|
+
* @param input.value — metadata field value
|
|
29
|
+
* @param input.durationMinutes — claim duration (default 30)
|
|
30
|
+
* @param input.assignee — optional external_id of the user to claim as
|
|
31
|
+
* @returns `{ status: 200, data: { escalation, isExtension } }`
|
|
32
|
+
*/
|
|
33
|
+
export declare function claimByMetadata(input: {
|
|
34
|
+
key: string;
|
|
35
|
+
value: string;
|
|
36
|
+
durationMinutes?: number;
|
|
37
|
+
assignee?: string;
|
|
38
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve an escalation by metadata key-value pair.
|
|
41
|
+
*
|
|
42
|
+
* Finds the pending escalation, auto-claims if unclaimed, then delegates
|
|
43
|
+
* to the standard resolve logic (supports all 5 resolution paths).
|
|
44
|
+
*
|
|
45
|
+
* @param input.key — metadata field name
|
|
46
|
+
* @param input.value — metadata field value
|
|
47
|
+
* @param input.resolverPayload — resolution data for the workflow
|
|
48
|
+
* @param input.assignee — optional external_id of the resolving user
|
|
49
|
+
* @returns result from the standard resolve endpoint
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveByMetadata(input: {
|
|
52
|
+
key: string;
|
|
53
|
+
value: string;
|
|
54
|
+
resolverPayload: Record<string, any>;
|
|
55
|
+
assignee?: string;
|
|
56
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.findByMetadata = findByMetadata;
|
|
37
|
+
exports.claimByMetadata = claimByMetadata;
|
|
38
|
+
exports.resolveByMetadata = resolveByMetadata;
|
|
39
|
+
const escalationService = __importStar(require("../../services/escalation"));
|
|
40
|
+
const userService = __importStar(require("../../services/user"));
|
|
41
|
+
const publish_1 = require("../../lib/events/publish");
|
|
42
|
+
const helpers_1 = require("./helpers");
|
|
43
|
+
/**
|
|
44
|
+
* Find escalations by a metadata key-value pair.
|
|
45
|
+
*
|
|
46
|
+
* Uses JSONB containment (`@>`) backed by a GIN index.
|
|
47
|
+
* Results are RBAC-scoped to the caller's visible roles.
|
|
48
|
+
*
|
|
49
|
+
* @param input.key — metadata field name (e.g. `"orderId"`)
|
|
50
|
+
* @param input.value — metadata field value (e.g. `"order-123"`)
|
|
51
|
+
* @param input.status — optional status filter (e.g. `"pending"`)
|
|
52
|
+
* @returns `{ status: 200, data: { escalations, total } }`
|
|
53
|
+
*/
|
|
54
|
+
async function findByMetadata(input, auth) {
|
|
55
|
+
try {
|
|
56
|
+
if (!input.key || !input.value) {
|
|
57
|
+
return { status: 400, error: 'key and value are required' };
|
|
58
|
+
}
|
|
59
|
+
const result = await escalationService.findByMetadata(input.key, input.value, input.status, input.limit, input.offset);
|
|
60
|
+
// RBAC: scope to visible roles
|
|
61
|
+
const visibleRoles = await (0, helpers_1.getVisibleRoles)(auth.userId);
|
|
62
|
+
if (visibleRoles) {
|
|
63
|
+
const roleSet = new Set(visibleRoles);
|
|
64
|
+
result.escalations = result.escalations.filter(e => roleSet.has(e.role));
|
|
65
|
+
result.total = result.escalations.length;
|
|
66
|
+
}
|
|
67
|
+
return { status: 200, data: result };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return { status: 500, error: err.message };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Claim an escalation by metadata key-value pair.
|
|
75
|
+
*
|
|
76
|
+
* Finds one available (pending + unassigned/expired) escalation matching
|
|
77
|
+
* the metadata and claims it atomically. Optionally resolves an assignee
|
|
78
|
+
* from an external_id.
|
|
79
|
+
*
|
|
80
|
+
* @param input.key — metadata field name
|
|
81
|
+
* @param input.value — metadata field value
|
|
82
|
+
* @param input.durationMinutes — claim duration (default 30)
|
|
83
|
+
* @param input.assignee — optional external_id of the user to claim as
|
|
84
|
+
* @returns `{ status: 200, data: { escalation, isExtension } }`
|
|
85
|
+
*/
|
|
86
|
+
async function claimByMetadata(input, auth) {
|
|
87
|
+
try {
|
|
88
|
+
if (!input.key || !input.value) {
|
|
89
|
+
return { status: 400, error: 'key and value are required' };
|
|
90
|
+
}
|
|
91
|
+
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth);
|
|
92
|
+
if ('error' in resolved)
|
|
93
|
+
return resolved.error;
|
|
94
|
+
const claimUserId = resolved.userId;
|
|
95
|
+
// RBAC: find the candidate to check role membership before atomic claim
|
|
96
|
+
const candidates = await escalationService.findByMetadata(input.key, input.value, 'pending', 1, 0);
|
|
97
|
+
if (candidates.escalations.length === 0) {
|
|
98
|
+
return { status: 404, error: 'No pending escalation found for this metadata' };
|
|
99
|
+
}
|
|
100
|
+
const candidate = candidates.escalations[0];
|
|
101
|
+
const isSuperAdmin = await userService.isSuperAdmin(auth.userId);
|
|
102
|
+
if (!isSuperAdmin) {
|
|
103
|
+
const userHasRole = await userService.hasRole(claimUserId, candidate.role);
|
|
104
|
+
if (!userHasRole) {
|
|
105
|
+
return { status: 403, error: `User must have the "${candidate.role}" role to claim this escalation` };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes);
|
|
109
|
+
if (!result) {
|
|
110
|
+
return { status: 409, error: 'Escalation not available for claim' };
|
|
111
|
+
}
|
|
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
|
+
});
|
|
122
|
+
return { status: 200, data: result };
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
return { status: 500, error: err.message };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Resolve an escalation by metadata key-value pair.
|
|
130
|
+
*
|
|
131
|
+
* Finds the pending escalation, auto-claims if unclaimed, then delegates
|
|
132
|
+
* to the standard resolve logic (supports all 5 resolution paths).
|
|
133
|
+
*
|
|
134
|
+
* @param input.key — metadata field name
|
|
135
|
+
* @param input.value — metadata field value
|
|
136
|
+
* @param input.resolverPayload — resolution data for the workflow
|
|
137
|
+
* @param input.assignee — optional external_id of the resolving user
|
|
138
|
+
* @returns result from the standard resolve endpoint
|
|
139
|
+
*/
|
|
140
|
+
async function resolveByMetadata(input, auth) {
|
|
141
|
+
try {
|
|
142
|
+
if (!input.key || !input.value) {
|
|
143
|
+
return { status: 400, error: 'key and value are required' };
|
|
144
|
+
}
|
|
145
|
+
if (!input.resolverPayload) {
|
|
146
|
+
return { status: 400, error: 'resolverPayload is required' };
|
|
147
|
+
}
|
|
148
|
+
const candidates = await escalationService.findByMetadata(input.key, input.value, 'pending', 1, 0);
|
|
149
|
+
if (candidates.escalations.length === 0) {
|
|
150
|
+
return { status: 404, error: 'No pending escalation found for this metadata' };
|
|
151
|
+
}
|
|
152
|
+
const escalation = candidates.escalations[0];
|
|
153
|
+
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth);
|
|
154
|
+
if ('error' in resolved)
|
|
155
|
+
return resolved.error;
|
|
156
|
+
const resolveUserId = resolved.userId;
|
|
157
|
+
const isSuperAdmin = await userService.isSuperAdmin(auth.userId);
|
|
158
|
+
if (!isSuperAdmin) {
|
|
159
|
+
const userHasRole = await userService.hasRole(resolveUserId, escalation.role);
|
|
160
|
+
if (!userHasRole) {
|
|
161
|
+
return { status: 403, error: `User must have the "${escalation.role}" role` };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Auto-claim if unclaimed or expired
|
|
165
|
+
const isClaimed = escalation.assigned_to &&
|
|
166
|
+
escalation.assigned_until &&
|
|
167
|
+
new Date(escalation.assigned_until) > new Date();
|
|
168
|
+
if (!isClaimed) {
|
|
169
|
+
await escalationService.claimEscalation(escalation.id, resolveUserId, 5);
|
|
170
|
+
}
|
|
171
|
+
// Delegate to the full resolve logic (handles all 5 resolution paths)
|
|
172
|
+
const { resolveEscalation } = await Promise.resolve().then(() => __importStar(require('./resolve')));
|
|
173
|
+
return resolveEscalation({ id: escalation.id, resolverPayload: input.resolverPayload }, auth);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return { status: 500, error: err.message };
|
|
177
|
+
}
|
|
178
|
+
}
|
package/build/api/index.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ export * as users from './users';
|
|
|
6
6
|
export * as roles from './roles';
|
|
7
7
|
export * as auth from './auth';
|
|
8
8
|
export * as mcp from './mcp';
|
|
9
|
-
export * as
|
|
9
|
+
export * as pipelines from './pipelines';
|
|
10
|
+
export * as mcpRuns from './pipelines';
|
|
10
11
|
export * as insight from './insight';
|
|
11
12
|
export * as settings from './settings';
|
|
12
13
|
export * as exports from './exports';
|