@hotmeshio/long-tail 0.5.0 → 0.5.2
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 +41 -1
- package/build/adapters/express.d.ts +1 -0
- package/build/adapters/express.js +4 -0
- package/build/api/yaml-workflows/crud.d.ts +1 -0
- package/build/api/yaml-workflows/crud.js +2 -2
- package/build/routes/mcp-endpoint.js +3 -5
- package/build/services/topics/system-topics.js +27 -27
- package/build/services/yaml-workflow/invoke.js +77 -6
- package/build/start/graph-workflows.d.ts +14 -0
- package/build/start/graph-workflows.js +126 -0
- package/build/start/workers.js +14 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/startup.d.ts +28 -0
- package/dashboard/dist/assets/{AdminDashboard-CgJC8ZZF.js → AdminDashboard-CMzR4d-w.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-CgJC8ZZF.js.map → AdminDashboard-CMzR4d-w.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-Bjl2Lsvo.js → AgentConfigPage-DHCpN4xk.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-Bjl2Lsvo.js.map → AgentConfigPage-DHCpN4xk.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-D5dHrfaM.js → AgentDetailPage-CSrejvSl.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-D5dHrfaM.js.map → AgentDetailPage-CSrejvSl.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-Mom3N1Av.js → AgentsPage-ntuzWHCD.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-Mom3N1Av.js.map → AgentsPage-ntuzWHCD.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-B2ZAb41C.js → AvailableEscalationsPage-Ci24fdxC.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-B2ZAb41C.js.map → AvailableEscalationsPage-Ci24fdxC.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-dCvnjynP.js → BotPicker-lj42d48P.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-dCvnjynP.js.map → BotPicker-lj42d48P.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-Bea9yLmU.js +2 -0
- package/dashboard/dist/assets/CapabilitiesPage-Bea9yLmU.js.map +1 -0
- package/dashboard/dist/assets/{CollapsibleSection-bW0UZN9b.js → CollapsibleSection-BeBsI1M4.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-bW0UZN9b.js.map → CollapsibleSection-BeBsI1M4.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-DVOK3aaR.js → CredentialsPage-BDzFa3HV.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-DVOK3aaR.js.map → CredentialsPage-BDzFa3HV.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Cv5em7OP.js → CronLabel-DeNm1I4r.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Cv5em7OP.js.map → CronLabel-DeNm1I4r.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-Dy4NBqhZ.js → CustomDurationPicker-C2OH9YcV.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-Dy4NBqhZ.js.map → CustomDurationPicker-C2OH9YcV.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-CptiQ0wc.js → DropZone-Dwpgbueb.js} +2 -2
- package/dashboard/dist/assets/{DropZone-CptiQ0wc.js.map → DropZone-Dwpgbueb.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-TQqWaVRq.js → ElapsedCell-WdzqA0dR.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-TQqWaVRq.js.map → ElapsedCell-WdzqA0dR.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Cv5UvuHI.js → EscalationsOverview-BIEeflEV.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Cv5UvuHI.js.map → EscalationsOverview-BIEeflEV.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Doky6fCO.js → EventTable-NIhWP__B.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Doky6fCO.js.map → EventTable-NIhWP__B.js.map} +1 -1
- package/dashboard/dist/assets/GraphInvokePage-DtAW8ilc.js +2 -0
- package/dashboard/dist/assets/GraphInvokePage-DtAW8ilc.js.map +1 -0
- package/dashboard/dist/assets/HomePage-HsO-M8ub.js +2 -0
- package/dashboard/dist/assets/{HomePage-CzvVyTq4.js.map → HomePage-HsO-M8ub.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Cfec9gz_.js → ListToolbar-DqaRlXrF.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Cfec9gz_.js.map → ListToolbar-DqaRlXrF.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BN4GsBGI.js → McpOverview-B4GsHxij.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BN4GsBGI.js.map → McpOverview-B4GsHxij.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DZKpzWST.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-DZKpzWST.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-BK5L2PqJ.js → McpQueryPage-B-8WR3GV.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BK5L2PqJ.js.map → McpQueryPage-B-8WR3GV.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-Dt7Ai3qB.js +2 -0
- package/dashboard/dist/assets/McpRunDetailPage-Dt7Ai3qB.js.map +1 -0
- package/dashboard/dist/assets/{McpRunsPage-QsXid9Xe.js → McpRunsPage-Bdke-HoQ.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-QsXid9Xe.js.map → McpRunsPage-Bdke-HoQ.js.map} +1 -1
- package/dashboard/dist/assets/NamespacePill-DnJl4Lre.js +2 -0
- package/dashboard/dist/assets/NamespacePill-DnJl4Lre.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-CZQSINho.js → OperatorDashboard-VZ97mufd.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-CZQSINho.js.map → OperatorDashboard-VZ97mufd.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BuJpMxyu.js → PageHeader-Bnt2iQQa.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BuJpMxyu.js.map → PageHeader-Bnt2iQQa.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-yD_PTbOl.js → PageHeaderWithStats-BuKc9MKt.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-yD_PTbOl.js.map → PageHeaderWithStats-BuKc9MKt.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DUCOOvOK.js → ProcessDetailPage-BLfLfmWX.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DUCOOvOK.js.map → ProcessDetailPage-BLfLfmWX.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CXvSLTIM.js → ProcessesListPage-DG54t-Nd.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CXvSLTIM.js.map → ProcessesListPage-DG54t-Nd.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-SasQKc_B.js → RolePill-DQTT1s9v.js} +2 -2
- package/dashboard/dist/assets/{RolePill-SasQKc_B.js.map → RolePill-DQTT1s9v.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DlQR0Iz_.js → RolesPage-Bdlv3DdW.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DlQR0Iz_.js.map → RolesPage-Bdlv3DdW.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-DP-jxsv6.js → RunAsSelector-BFxxMvL3.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-DP-jxsv6.js.map → RunAsSelector-BFxxMvL3.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BmASA0nN.js → SwimlaneTimeline-BZmad7WQ.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BmASA0nN.js.map → SwimlaneTimeline-BZmad7WQ.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-DvF3j8MA.js → TagInput-B00uqhjX.js} +2 -2
- package/dashboard/dist/assets/{TagInput-DvF3j8MA.js.map → TagInput-B00uqhjX.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-CRowpkeZ.js → TaskDetailPage-CLl2mgBC.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-CRowpkeZ.js.map → TaskDetailPage-CLl2mgBC.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BCQrS2oK.js → TaskQueuePill-CUsofm0X.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BCQrS2oK.js.map → TaskQueuePill-CUsofm0X.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-uJ6z37J-.js → TasksListPage-DoHXxZF-.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-uJ6z37J-.js.map → TasksListPage-DoHXxZF-.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BxwngK1D.js → TimeAgo-DZF9w8Rl.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BxwngK1D.js.map → TimeAgo-DZF9w8Rl.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-CDmichOM.js → TimestampCell-DPpoTdrw.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-CDmichOM.js.map → TimestampCell-DPpoTdrw.js.map} +1 -1
- package/dashboard/dist/assets/ToolPill-DjvedZSn.js +2 -0
- package/dashboard/dist/assets/ToolPill-DjvedZSn.js.map +1 -0
- package/dashboard/dist/assets/ToolTestPanel-DtAgJQfr.js +2 -0
- package/dashboard/dist/assets/ToolTestPanel-DtAgJQfr.js.map +1 -0
- package/dashboard/dist/assets/TopicDetailPage-W9RKkNNp.js +9 -0
- package/dashboard/dist/assets/TopicDetailPage-W9RKkNNp.js.map +1 -0
- package/dashboard/dist/assets/{TopicsPage-letISGGD.js → TopicsPage-Bc-4ne6V.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-letISGGD.js.map → TopicsPage-Bc-4ne6V.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-W6_Iz2Qb.js → UserName-O2Q4-E6E.js} +2 -2
- package/dashboard/dist/assets/{UserName-W6_Iz2Qb.js.map → UserName-O2Q4-E6E.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-Cfx-xlRT.js → WorkflowExecutionPage-DEDsBmn1.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-Cfx-xlRT.js.map → WorkflowExecutionPage-DEDsBmn1.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-Z-zHRKOK.js → WorkflowPill-F1oKUzmc.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-Z-zHRKOK.js.map → WorkflowPill-F1oKUzmc.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DC4XHMWt.js → WorkflowsDashboard-Bcf17vCt.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DC4XHMWt.js.map → WorkflowsDashboard-Bcf17vCt.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-GefO_yn0.js → WorkflowsOverview-Cwo2rqGT.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-GefO_yn0.js.map → WorkflowsOverview-Cwo2rqGT.js.map} +1 -1
- package/dashboard/dist/assets/YamlWorkflowDetailPage-Bv8ZFwO-.js +33 -0
- package/dashboard/dist/assets/YamlWorkflowDetailPage-Bv8ZFwO-.js.map +1 -0
- package/dashboard/dist/assets/YamlWorkflowsPage-DOiEQDOq.js +2 -0
- package/dashboard/dist/assets/YamlWorkflowsPage-DOiEQDOq.js.map +1 -0
- package/dashboard/dist/assets/{agents-BI5OeN84.js → agents-D09G0HCv.js} +2 -2
- package/dashboard/dist/assets/{agents-BI5OeN84.js.map → agents-D09G0HCv.js.map} +1 -1
- package/dashboard/dist/assets/{bots-1UzUCsrR.js → bots-D0LhyZZM.js} +2 -2
- package/dashboard/dist/assets/{bots-1UzUCsrR.js.map → bots-D0LhyZZM.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BUbl-ojp.js → capabilities-DON4-NXs.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BUbl-ojp.js.map → capabilities-DON4-NXs.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DTFrH_vN.js → controlplane-Bihd1kXf.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DTFrH_vN.js.map → controlplane-Bihd1kXf.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-BQhCt4W0.js → escalation-CP2XbdXK.js} +2 -2
- package/dashboard/dist/assets/{escalation-BQhCt4W0.js.map → escalation-CP2XbdXK.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-J20k5CcY.js → escalation-columns-9aw8Y4qq.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-J20k5CcY.js.map → escalation-columns-9aw8Y4qq.js.map} +1 -1
- package/dashboard/dist/assets/helpers-DzO-OGPe.js +2 -0
- package/dashboard/dist/assets/helpers-DzO-OGPe.js.map +1 -0
- package/dashboard/dist/assets/{index-CVGgSoda.js → index-B-BK3vtk.js} +2 -2
- package/dashboard/dist/assets/{index-CVGgSoda.js.map → index-B-BK3vtk.js.map} +1 -1
- package/dashboard/dist/assets/{index-CWEOhAiK.js → index-B7lEd0cY.js} +25 -25
- package/dashboard/dist/assets/index-B7lEd0cY.js.map +1 -0
- package/dashboard/dist/assets/index-BBBGETMs.js +6 -0
- package/dashboard/dist/assets/index-BBBGETMs.js.map +1 -0
- package/dashboard/dist/assets/index-BFyzZGtv.css +1 -0
- package/dashboard/dist/assets/{index-vgxjge70.js → index-BInTEEIX.js} +2 -2
- package/dashboard/dist/assets/{index-vgxjge70.js.map → index-BInTEEIX.js.map} +1 -1
- package/dashboard/dist/assets/index-BTp73vYK.js +2 -0
- package/dashboard/dist/assets/index-BTp73vYK.js.map +1 -0
- package/dashboard/dist/assets/index-CCup2uaP.js +2 -0
- package/dashboard/dist/assets/{index-C9ClHiiW.js.map → index-CCup2uaP.js.map} +1 -1
- package/dashboard/dist/assets/index-CMRW_PE-.js +9 -0
- package/dashboard/dist/assets/index-CMRW_PE-.js.map +1 -0
- package/dashboard/dist/assets/index-Cb7aSzox.js +2 -0
- package/dashboard/dist/assets/{index-si70YcIP.js.map → index-Cb7aSzox.js.map} +1 -1
- package/dashboard/dist/assets/index-Cjb8ulHm.js +2 -0
- package/dashboard/dist/assets/{index-WQQJ_cp7.js.map → index-Cjb8ulHm.js.map} +1 -1
- package/dashboard/dist/assets/index-DgLZ8Ix5.js +2 -0
- package/dashboard/dist/assets/{index-DasoTRjT.js.map → index-DgLZ8Ix5.js.map} +1 -1
- package/dashboard/dist/assets/index-H5Yb8CY2.js +2 -0
- package/dashboard/dist/assets/index-H5Yb8CY2.js.map +1 -0
- package/dashboard/dist/assets/{index-CLUYzdwz.js → index-_JsRJPds.js} +2 -2
- package/dashboard/dist/assets/{index-CLUYzdwz.js.map → index-_JsRJPds.js.map} +1 -1
- package/dashboard/dist/assets/{index-C-mbURj-.js → index-rbuNUyAh.js} +2 -2
- package/dashboard/dist/assets/{index-C-mbURj-.js.map → index-rbuNUyAh.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-D9Tuh-o-.js → knowledge-Bl_KaoKJ.js} +2 -2
- package/dashboard/dist/assets/{knowledge-D9Tuh-o-.js.map → knowledge-Bl_KaoKJ.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BO8QnWyk.js → mcp-DXbFGoA8.js} +2 -2
- package/dashboard/dist/assets/{mcp-BO8QnWyk.js.map → mcp-DXbFGoA8.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-WLtQtr51.js → mcp-query-Bg69DF2x.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-WLtQtr51.js.map → mcp-query-Bg69DF2x.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BAVf9xud.js → pipelines-DK9LTg9F.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BAVf9xud.js.map → pipelines-DK9LTg9F.js.map} +1 -1
- package/dashboard/dist/assets/{roles-mGO2-2hA.js → roles-BrsBN4hO.js} +2 -2
- package/dashboard/dist/assets/{roles-mGO2-2hA.js.map → roles-BrsBN4hO.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-JVRVCx0f.js → tasks-CwjvPECN.js} +2 -2
- package/dashboard/dist/assets/{tasks-JVRVCx0f.js.map → tasks-CwjvPECN.js.map} +1 -1
- package/dashboard/dist/assets/{topics-BLVnahd7.js → topics-BrwkmaFR.js} +2 -2
- package/dashboard/dist/assets/{topics-BLVnahd7.js.map → topics-BrwkmaFR.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-BwjAi0Qq.js → useEventHooks-Cd1GM1NG.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-BwjAi0Qq.js.map → useEventHooks-Cd1GM1NG.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DkHmXddZ.js → useNamespace-D9lghZ25.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DkHmXddZ.js.map → useNamespace-D9lghZ25.js.map} +1 -1
- package/dashboard/dist/assets/useYamlActivityEvents-vOhAwmKO.js +2 -0
- package/dashboard/dist/assets/useYamlActivityEvents-vOhAwmKO.js.map +1 -0
- package/dashboard/dist/assets/{users-BvizpAkV.js → users-ChQ7soaq.js} +2 -2
- package/dashboard/dist/assets/{users-BvizpAkV.js.map → users-ChQ7soaq.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-Doy0g69_.js → vendor-icons-Dj2F0Jrb.js} +38 -38
- package/dashboard/dist/assets/vendor-icons-Dj2F0Jrb.js.map +1 -0
- package/dashboard/dist/assets/workflows-BLKji1_1.js +2 -0
- package/dashboard/dist/assets/{workflows-CyEYa01a.js.map → workflows-BLKji1_1.js.map} +1 -1
- package/dashboard/dist/assets/yaml-workflows-BUhMfdaw.js +2 -0
- package/dashboard/dist/assets/{yaml-workflows-i3GzrEme.js.map → yaml-workflows-BUhMfdaw.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/story.md +13 -9
- package/package.json +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CK2fJ9Sy.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-CK2fJ9Sy.js.map +0 -1
- package/dashboard/dist/assets/HomePage-CzvVyTq4.js +0 -2
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-lCW668WQ.js.map +0 -1
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-CQOeYqxa.js.map +0 -1
- package/dashboard/dist/assets/ServerName-CHspudaC.js +0 -2
- package/dashboard/dist/assets/ServerName-CHspudaC.js.map +0 -1
- package/dashboard/dist/assets/StepIndicator-CuUIGxKk.js +0 -2
- package/dashboard/dist/assets/StepIndicator-CuUIGxKk.js.map +0 -1
- package/dashboard/dist/assets/ToolPill-1aTqYtzp.js +0 -2
- package/dashboard/dist/assets/ToolPill-1aTqYtzp.js.map +0 -1
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-xjTn8sU8.js.map +0 -1
- package/dashboard/dist/assets/TopicDetailPage-Dm0hDlS8.js +0 -9
- package/dashboard/dist/assets/TopicDetailPage-Dm0hDlS8.js.map +0 -1
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js +0 -2
- package/dashboard/dist/assets/YamlWorkflowsPage-CMsrFooO.js.map +0 -1
- package/dashboard/dist/assets/helpers-ge6Eu90Y.js +0 -2
- package/dashboard/dist/assets/helpers-ge6Eu90Y.js.map +0 -1
- package/dashboard/dist/assets/index-C--SEsU7.css +0 -1
- package/dashboard/dist/assets/index-C45DvtAZ.js +0 -15
- package/dashboard/dist/assets/index-C45DvtAZ.js.map +0 -1
- package/dashboard/dist/assets/index-C9ClHiiW.js +0 -2
- package/dashboard/dist/assets/index-CWEOhAiK.js.map +0 -1
- package/dashboard/dist/assets/index-CWlP6vHG.js +0 -6
- package/dashboard/dist/assets/index-CWlP6vHG.js.map +0 -1
- package/dashboard/dist/assets/index-DasoTRjT.js +0 -2
- package/dashboard/dist/assets/index-FhasoOjO.js +0 -2
- package/dashboard/dist/assets/index-FhasoOjO.js.map +0 -1
- package/dashboard/dist/assets/index-WQQJ_cp7.js +0 -2
- package/dashboard/dist/assets/index-hAZiac0C.js +0 -2
- package/dashboard/dist/assets/index-hAZiac0C.js.map +0 -1
- package/dashboard/dist/assets/index-si70YcIP.js +0 -2
- package/dashboard/dist/assets/useExpandedRows-CkcEntB-.js +0 -2
- package/dashboard/dist/assets/useExpandedRows-CkcEntB-.js.map +0 -1
- package/dashboard/dist/assets/useYamlActivityEvents-CsaR5dWj.js +0 -2
- package/dashboard/dist/assets/useYamlActivityEvents-CsaR5dWj.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-Doy0g69_.js.map +0 -1
- package/dashboard/dist/assets/workflows-CyEYa01a.js +0 -2
- package/dashboard/dist/assets/yaml-workflows-i3GzrEme.js +0 -2
package/README.md
CHANGED
|
@@ -74,10 +74,12 @@ curl -X PUT http://localhost:3000/api/workflows/reviewContent/config \
|
|
|
74
74
|
|
|
75
75
|
**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.
|
|
76
76
|
|
|
77
|
-
**Step 4 — Compile what repeats.** The
|
|
77
|
+
**Step 4 — Compile what repeats.** The same workflow has two forms. What you wrote in Step 1 is the *procedural* form — readable, Temporal-like, emulated atop the graph: cheap to maintain, heavier to run. The Designer compiles a working execution into the *graph* form — the same durable workflow as a deterministic DAG: no LLM at runtime, no replay overhead, typed in and out, roughly 3x faster. Every procedural pattern has a graph equivalent and the reverse; you pick readability or speed without giving up durability, escalation, or transactional guarantees. It deploys as a reusable tool that any workflow or API call can invoke.
|
|
78
78
|
|
|
79
79
|
Over time, the system accumulates compiled tools. Problems that once required a human, then required AI reasoning, eventually require neither.
|
|
80
80
|
|
|
81
|
+
These four steps map to how the dashboard is organized. **React** is the reactive side (Step 3) — topics, subscriptions, automations. **Orchestrate** is the orchestrated side (Steps 1 and 4) — procedural and graph flows side by side, both durable and pull-based under the hood. **Design** is the optional bridge: with an `ANTHROPIC_API_KEY` it turns a description or a tool run into a graph flow; without one, choreography and orchestration stand on their own, no tradeoff.
|
|
82
|
+
|
|
81
83
|
## Register MCP tools
|
|
82
84
|
|
|
83
85
|
Long Tail connects to any MCP server. Registered tools become durable activities and are available to the Pipeline Designer.
|
|
@@ -145,6 +147,43 @@ npx ltc compile workflows/
|
|
|
145
147
|
|
|
146
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).
|
|
147
149
|
|
|
150
|
+
## Register a graph flow by hand
|
|
151
|
+
|
|
152
|
+
`graphWorkflows` is the graph-form peer of `workers`: hand-author the HotMesh YAML and it's created, deployed, and activated at startup. This hello-world assembles a greeting from the input with a single trigger mapping:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const lt = await start({
|
|
156
|
+
database: { connectionString: process.env.DATABASE_URL },
|
|
157
|
+
graphWorkflows: [{
|
|
158
|
+
name: 'hello_world',
|
|
159
|
+
namespace: 'graph',
|
|
160
|
+
inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
|
|
161
|
+
yaml: `
|
|
162
|
+
app:
|
|
163
|
+
id: graph
|
|
164
|
+
version: '1'
|
|
165
|
+
graphs:
|
|
166
|
+
- subscribes: hello_world
|
|
167
|
+
publishes: hello_world.done
|
|
168
|
+
input: { schema: { type: object, properties: { name: { type: string } } } }
|
|
169
|
+
output: { schema: { type: object, properties: { greeting: { type: string } } } }
|
|
170
|
+
activities:
|
|
171
|
+
trigger:
|
|
172
|
+
type: trigger
|
|
173
|
+
job:
|
|
174
|
+
maps:
|
|
175
|
+
greeting:
|
|
176
|
+
'@pipe':
|
|
177
|
+
- ['Hello, ', '{$self.input.data.name}', '!']
|
|
178
|
+
- ['{@string.concat}']
|
|
179
|
+
transitions: {}
|
|
180
|
+
`,
|
|
181
|
+
}],
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
It appears under **Orchestrate › Graph** and runs the same way a procedural workflow does — durable, transactional, invocable from the dashboard or API.
|
|
186
|
+
|
|
148
187
|
## Full configuration
|
|
149
188
|
|
|
150
189
|
```typescript
|
|
@@ -153,6 +192,7 @@ const lt = await start({
|
|
|
153
192
|
workers: [{ taskQueue: 'default', workflow: reviewContent }],
|
|
154
193
|
|
|
155
194
|
// Everything below is optional
|
|
195
|
+
graphWorkflows: [{ name: 'hello_world', namespace: 'graph', yaml: helloWorldYaml }],
|
|
156
196
|
seed: { admin: { externalId: 'admin', password: process.env.ADMIN_PASSWORD } },
|
|
157
197
|
mcp: { server: { enabled: true }, serverFactories: { 'my-tools': createMyToolsServer } },
|
|
158
198
|
escalation: { strategy: 'mcp' },
|
|
@@ -59,6 +59,7 @@ export declare class LTExpressAdapter {
|
|
|
59
59
|
/**
|
|
60
60
|
* Return a self-contained Express Router that serves:
|
|
61
61
|
* - `/api/*` — Long Tail API routes (auth, tasks, escalations, etc.)
|
|
62
|
+
* - `/mcp` — MCP streamable-HTTP transport (Claude Desktop, Cursor, agents)
|
|
62
63
|
* - `/health` — health check
|
|
63
64
|
* - Static dashboard assets
|
|
64
65
|
* - SPA fallback with injected `<base href>` and `window.__LT_BASE__`
|
|
@@ -41,6 +41,7 @@ const fs_1 = require("fs");
|
|
|
41
41
|
const path_1 = __importDefault(require("path"));
|
|
42
42
|
const express_1 = __importStar(require("express"));
|
|
43
43
|
const routes_1 = __importDefault(require("../routes"));
|
|
44
|
+
const mcp_endpoint_1 = __importDefault(require("../routes/mcp-endpoint"));
|
|
44
45
|
const events_1 = require("../lib/events");
|
|
45
46
|
const socketio_1 = require("../lib/events/socketio");
|
|
46
47
|
const nats_1 = require("../lib/events/nats");
|
|
@@ -134,6 +135,7 @@ class LTExpressAdapter {
|
|
|
134
135
|
/**
|
|
135
136
|
* Return a self-contained Express Router that serves:
|
|
136
137
|
* - `/api/*` — Long Tail API routes (auth, tasks, escalations, etc.)
|
|
138
|
+
* - `/mcp` — MCP streamable-HTTP transport (Claude Desktop, Cursor, agents)
|
|
137
139
|
* - `/health` — health check
|
|
138
140
|
* - Static dashboard assets
|
|
139
141
|
* - SPA fallback with injected `<base href>` and `window.__LT_BASE__`
|
|
@@ -147,6 +149,8 @@ class LTExpressAdapter {
|
|
|
147
149
|
});
|
|
148
150
|
// API routes — internal routes handle their own JWT auth
|
|
149
151
|
router.use('/api', routes_1.default);
|
|
152
|
+
// MCP streamable-HTTP transport — same endpoint as standalone server
|
|
153
|
+
router.use('/mcp', mcp_endpoint_1.default);
|
|
150
154
|
// Dashboard static assets
|
|
151
155
|
const dashboardDist = this.resolveDashboardDist();
|
|
152
156
|
if (dashboardDist) {
|
|
@@ -216,7 +216,7 @@ async function createYamlWorkflow(input) {
|
|
|
216
216
|
*/
|
|
217
217
|
async function createYamlWorkflowDirect(input) {
|
|
218
218
|
try {
|
|
219
|
-
const { name, description, yaml_content, input_schema, activity_manifest, tags, app_id, graph_topic } = input;
|
|
219
|
+
const { name, description, yaml_content, input_schema, output_schema, activity_manifest, tags, app_id, graph_topic } = input;
|
|
220
220
|
if (!name || !yaml_content) {
|
|
221
221
|
return { status: 400, error: 'name and yaml_content are required' };
|
|
222
222
|
}
|
|
@@ -258,7 +258,7 @@ async function createYamlWorkflowDirect(input) {
|
|
|
258
258
|
yaml_content: finalYaml,
|
|
259
259
|
graph_topic: graphTopic,
|
|
260
260
|
input_schema: input_schema || {},
|
|
261
|
-
output_schema: {},
|
|
261
|
+
output_schema: output_schema || {},
|
|
262
262
|
activity_manifest: normalizeManifestToolNames(activity_manifest) || [],
|
|
263
263
|
tags: tags || [],
|
|
264
264
|
original_prompt: description,
|
|
@@ -22,10 +22,8 @@ const logger_1 = require("../lib/logger");
|
|
|
22
22
|
const external_server_1 = require("../services/mcp/external-server");
|
|
23
23
|
const exposure_1 = require("../services/mcp/exposure");
|
|
24
24
|
const router = (0, express_1.Router)();
|
|
25
|
-
// All MCP endpoint requests require authentication
|
|
26
|
-
router.use(auth_1.requireAuth);
|
|
27
25
|
// POST /mcp — JSON-RPC messages
|
|
28
|
-
router.post('/', async (req, res) => {
|
|
26
|
+
router.post('/', auth_1.requireAuth, async (req, res) => {
|
|
29
27
|
try {
|
|
30
28
|
const exposure = (0, exposure_1.getExposureConfig)();
|
|
31
29
|
const callerScopes = req.auth?.scopes;
|
|
@@ -52,7 +50,7 @@ router.post('/', async (req, res) => {
|
|
|
52
50
|
}
|
|
53
51
|
});
|
|
54
52
|
// GET /mcp — SSE stream (not supported in stateless mode)
|
|
55
|
-
router.get('/', (_req, res) => {
|
|
53
|
+
router.get('/', auth_1.requireAuth, (_req, res) => {
|
|
56
54
|
res.status(405).json({
|
|
57
55
|
jsonrpc: '2.0',
|
|
58
56
|
error: { code: -32000, message: 'Method not allowed. Use POST for stateless requests.' },
|
|
@@ -60,7 +58,7 @@ router.get('/', (_req, res) => {
|
|
|
60
58
|
});
|
|
61
59
|
});
|
|
62
60
|
// DELETE /mcp — session close (not supported in stateless mode)
|
|
63
|
-
router.delete('/', (_req, res) => {
|
|
61
|
+
router.delete('/', auth_1.requireAuth, (_req, res) => {
|
|
64
62
|
res.status(405).json({
|
|
65
63
|
jsonrpc: '2.0',
|
|
66
64
|
error: { code: -32000, message: 'Method not allowed. Stateless mode has no sessions.' },
|
|
@@ -20,7 +20,7 @@ const SYSTEM_TOPICS = [
|
|
|
20
20
|
// Task lifecycle
|
|
21
21
|
{
|
|
22
22
|
topic: 'system.task.*.created',
|
|
23
|
-
description: 'A new task has been
|
|
23
|
+
description: 'A new task has been queued.',
|
|
24
24
|
category: 'task',
|
|
25
25
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string', description: 'Task ID' }, status: STATUS_FIELD, data: { type: 'object', description: 'Task input data' } }),
|
|
26
26
|
example_payload: { taskId: 'tsk-001', status: 'pending', workflowName: 'processOrder' },
|
|
@@ -28,7 +28,7 @@ const SYSTEM_TOPICS = [
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
topic: 'system.task.*.started',
|
|
31
|
-
description: 'A task has
|
|
31
|
+
description: 'A task has started.',
|
|
32
32
|
category: 'task',
|
|
33
33
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD }),
|
|
34
34
|
example_payload: { taskId: 'tsk-001', status: 'running', workflowName: 'processOrder' },
|
|
@@ -36,7 +36,7 @@ const SYSTEM_TOPICS = [
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
topic: 'system.task.*.completed',
|
|
39
|
-
description: 'A task has finished
|
|
39
|
+
description: 'A task has finished.',
|
|
40
40
|
category: 'task',
|
|
41
41
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD, milestones: { type: 'array', items: { type: 'object' }, description: 'Milestones reported' }, data: { type: 'object', description: 'Task result data' } }),
|
|
42
42
|
example_payload: { taskId: 'tsk-001', status: 'completed', workflowName: 'processOrder' },
|
|
@@ -44,7 +44,7 @@ const SYSTEM_TOPICS = [
|
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
topic: 'system.task.*.escalated',
|
|
47
|
-
description: 'A task has been escalated
|
|
47
|
+
description: 'A task has been escalated.',
|
|
48
48
|
category: 'task',
|
|
49
49
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object' } }),
|
|
50
50
|
example_payload: { taskId: 'tsk-001', status: 'escalated', workflowName: 'processOrder' },
|
|
@@ -52,7 +52,7 @@ const SYSTEM_TOPICS = [
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
topic: 'system.task.*.failed',
|
|
55
|
-
description: 'A task has failed
|
|
55
|
+
description: 'A task has failed.',
|
|
56
56
|
category: 'task',
|
|
57
57
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object', description: 'Error details' } }),
|
|
58
58
|
example_payload: { taskId: 'tsk-001', status: 'failed', workflowName: 'processOrder' },
|
|
@@ -61,7 +61,7 @@ const SYSTEM_TOPICS = [
|
|
|
61
61
|
// Workflow lifecycle
|
|
62
62
|
{
|
|
63
63
|
topic: 'system.workflow.*.started',
|
|
64
|
-
description: 'A workflow
|
|
64
|
+
description: 'A workflow has started.',
|
|
65
65
|
category: 'workflow',
|
|
66
66
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD }),
|
|
67
67
|
example_payload: { workflowId: 'wf-abc', workflowName: 'processOrder', status: 'running' },
|
|
@@ -69,7 +69,7 @@ const SYSTEM_TOPICS = [
|
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
topic: 'system.workflow.*.completed',
|
|
72
|
-
description: 'A workflow
|
|
72
|
+
description: 'A workflow has completed.',
|
|
73
73
|
category: 'workflow',
|
|
74
74
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object' } }),
|
|
75
75
|
example_payload: { workflowId: 'wf-abc', workflowName: 'processOrder', status: 'completed' },
|
|
@@ -77,7 +77,7 @@ const SYSTEM_TOPICS = [
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
topic: 'system.workflow.*.failed',
|
|
80
|
-
description: 'A workflow
|
|
80
|
+
description: 'A workflow has failed.',
|
|
81
81
|
category: 'workflow',
|
|
82
82
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, taskId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object', description: 'Error details' } }),
|
|
83
83
|
example_payload: { workflowId: 'wf-abc', workflowName: 'processOrder', status: 'failed' },
|
|
@@ -86,7 +86,7 @@ const SYSTEM_TOPICS = [
|
|
|
86
86
|
// Escalation lifecycle
|
|
87
87
|
{
|
|
88
88
|
topic: 'system.escalation.*.created',
|
|
89
|
-
description: '
|
|
89
|
+
description: 'An escalation has been created.',
|
|
90
90
|
category: 'escalation',
|
|
91
91
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, escalationId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object' } }),
|
|
92
92
|
example_payload: { escalationId: 'esc-001', status: 'pending', workflowName: 'processOrder' },
|
|
@@ -94,7 +94,7 @@ const SYSTEM_TOPICS = [
|
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
topic: 'system.escalation.*.resolved',
|
|
97
|
-
description: 'An escalation has been resolved
|
|
97
|
+
description: 'An escalation has been resolved.',
|
|
98
98
|
category: 'escalation',
|
|
99
99
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, escalationId: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object' } }),
|
|
100
100
|
example_payload: { escalationId: 'esc-001', status: 'resolved', workflowName: 'processOrder' },
|
|
@@ -102,7 +102,7 @@ const SYSTEM_TOPICS = [
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
topic: 'system.escalation.*.claimed',
|
|
105
|
-
description: 'An escalation has been claimed
|
|
105
|
+
description: 'An escalation has been claimed.',
|
|
106
106
|
category: 'escalation',
|
|
107
107
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, escalationId: { type: 'string' }, status: STATUS_FIELD }),
|
|
108
108
|
example_payload: { escalationId: 'esc-001', status: 'claimed' },
|
|
@@ -110,7 +110,7 @@ const SYSTEM_TOPICS = [
|
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
112
|
topic: 'system.escalation.*.released',
|
|
113
|
-
description: 'An escalation has been
|
|
113
|
+
description: 'An escalation has been returned to the queue.',
|
|
114
114
|
category: 'escalation',
|
|
115
115
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, escalationId: { type: 'string' }, status: STATUS_FIELD }),
|
|
116
116
|
example_payload: { escalationId: 'esc-001', status: 'pending' },
|
|
@@ -119,32 +119,32 @@ const SYSTEM_TOPICS = [
|
|
|
119
119
|
// Activity lifecycle
|
|
120
120
|
{
|
|
121
121
|
topic: 'system.activity.*.*.started',
|
|
122
|
-
description: 'A
|
|
122
|
+
description: 'A workflow activity has started.',
|
|
123
123
|
category: 'activity',
|
|
124
124
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, activityName: { type: 'string', description: 'Activity step name' } }),
|
|
125
125
|
example_payload: { workflowId: 'wf-abc', activityName: 'fetchOrder', workflowName: 'processOrder' },
|
|
126
|
-
tags: ['lifecycle', '
|
|
126
|
+
tags: ['lifecycle', 'graph'],
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
topic: 'system.activity.*.*.completed',
|
|
130
|
-
description: 'A
|
|
130
|
+
description: 'A workflow activity has completed.',
|
|
131
131
|
category: 'activity',
|
|
132
132
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, activityName: { type: 'string' }, data: { type: 'object' } }),
|
|
133
133
|
example_payload: { workflowId: 'wf-abc', activityName: 'fetchOrder', workflowName: 'processOrder' },
|
|
134
|
-
tags: ['lifecycle', '
|
|
134
|
+
tags: ['lifecycle', 'graph'],
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
topic: 'system.activity.*.*.failed',
|
|
138
|
-
description: 'A
|
|
138
|
+
description: 'A workflow activity has failed.',
|
|
139
139
|
category: 'activity',
|
|
140
140
|
payload_schema: objectSchema({ ...WORKFLOW_CONTEXT_PROPS, activityName: { type: 'string' }, data: { type: 'object', description: 'Error details' } }),
|
|
141
141
|
example_payload: { workflowId: 'wf-abc', activityName: 'fetchOrder', workflowName: 'processOrder' },
|
|
142
|
-
tags: ['lifecycle', '
|
|
142
|
+
tags: ['lifecycle', 'graph', 'error'],
|
|
143
143
|
},
|
|
144
144
|
// Knowledge lifecycle
|
|
145
145
|
{
|
|
146
146
|
topic: 'system.knowledge.*.stored',
|
|
147
|
-
description: 'A knowledge entry has been
|
|
147
|
+
description: 'A knowledge entry has been saved.',
|
|
148
148
|
category: 'knowledge',
|
|
149
149
|
payload_schema: objectSchema({ domain: { type: 'string', description: 'Knowledge domain' }, key: { type: 'string', description: 'Knowledge entry key' } }),
|
|
150
150
|
example_payload: { domain: 'orders', key: 'order-12345' },
|
|
@@ -152,7 +152,7 @@ const SYSTEM_TOPICS = [
|
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
topic: 'system.knowledge.*.deleted',
|
|
155
|
-
description: 'A knowledge entry has been
|
|
155
|
+
description: 'A knowledge entry has been deleted.',
|
|
156
156
|
category: 'knowledge',
|
|
157
157
|
payload_schema: objectSchema({ domain: { type: 'string', description: 'Knowledge domain' }, key: { type: 'string', description: 'Knowledge entry key' } }),
|
|
158
158
|
example_payload: { domain: 'orders', key: 'order-12345' },
|
|
@@ -161,7 +161,7 @@ const SYSTEM_TOPICS = [
|
|
|
161
161
|
// File storage
|
|
162
162
|
{
|
|
163
163
|
topic: 'system.file.stored',
|
|
164
|
-
description: 'A file has been
|
|
164
|
+
description: 'A file has been saved to storage.',
|
|
165
165
|
category: 'file',
|
|
166
166
|
payload_schema: objectSchema({
|
|
167
167
|
path: { type: 'string', description: 'File path in storage' },
|
|
@@ -176,7 +176,7 @@ const SYSTEM_TOPICS = [
|
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
topic: 'system.file.deleted',
|
|
179
|
-
description: 'A file has been
|
|
179
|
+
description: 'A file has been deleted from storage.',
|
|
180
180
|
category: 'file',
|
|
181
181
|
payload_schema: objectSchema({
|
|
182
182
|
path: { type: 'string', description: 'File path in storage' },
|
|
@@ -190,7 +190,7 @@ const SYSTEM_TOPICS = [
|
|
|
190
190
|
// Agent lifecycle
|
|
191
191
|
{
|
|
192
192
|
topic: 'system.agent.*.started',
|
|
193
|
-
description: 'An agent
|
|
193
|
+
description: 'An agent automation has started in response to an event.',
|
|
194
194
|
category: 'agent',
|
|
195
195
|
payload_schema: objectSchema({ agentId: { type: 'string', description: 'Agent ID' }, agentName: { type: 'string', description: 'Agent name' }, status: STATUS_FIELD, data: { type: 'object', description: 'Trigger context' } }),
|
|
196
196
|
example_payload: { agentId: 'agt-001', agentName: 'error-handler', status: 'running' },
|
|
@@ -198,7 +198,7 @@ const SYSTEM_TOPICS = [
|
|
|
198
198
|
},
|
|
199
199
|
{
|
|
200
200
|
topic: 'system.agent.*.completed',
|
|
201
|
-
description: 'An agent
|
|
201
|
+
description: 'An agent automation has completed.',
|
|
202
202
|
category: 'agent',
|
|
203
203
|
payload_schema: objectSchema({ agentId: { type: 'string' }, agentName: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object' } }),
|
|
204
204
|
example_payload: { agentId: 'agt-001', agentName: 'error-handler', status: 'completed' },
|
|
@@ -206,7 +206,7 @@ const SYSTEM_TOPICS = [
|
|
|
206
206
|
},
|
|
207
207
|
{
|
|
208
208
|
topic: 'system.agent.*.failed',
|
|
209
|
-
description: 'An agent
|
|
209
|
+
description: 'An agent automation has failed.',
|
|
210
210
|
category: 'agent',
|
|
211
211
|
payload_schema: objectSchema({ agentId: { type: 'string' }, agentName: { type: 'string' }, status: STATUS_FIELD, data: { type: 'object', description: 'Error details' } }),
|
|
212
212
|
example_payload: { agentId: 'agt-001', agentName: 'error-handler', status: 'failed' },
|
|
@@ -214,7 +214,7 @@ const SYSTEM_TOPICS = [
|
|
|
214
214
|
},
|
|
215
215
|
{
|
|
216
216
|
topic: 'system.agent.*.status_changed',
|
|
217
|
-
description: 'An agent\'s status has changed
|
|
217
|
+
description: 'An agent automation\'s status has changed.',
|
|
218
218
|
category: 'agent',
|
|
219
219
|
payload_schema: objectSchema({ agentId: { type: 'string' }, agentName: { type: 'string' }, status: STATUS_FIELD }),
|
|
220
220
|
example_payload: { agentId: 'agt-001', agentName: 'error-handler', status: 'active' },
|
|
@@ -223,7 +223,7 @@ const SYSTEM_TOPICS = [
|
|
|
223
223
|
// Milestone
|
|
224
224
|
{
|
|
225
225
|
topic: 'system.milestone.*',
|
|
226
|
-
description: 'A workflow or activity has reported progress
|
|
226
|
+
description: 'A workflow or workflow activity has reported progress.',
|
|
227
227
|
category: 'milestone',
|
|
228
228
|
payload_schema: objectSchema({
|
|
229
229
|
...WORKFLOW_CONTEXT_PROPS,
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.invokeYamlWorkflow = invokeYamlWorkflow;
|
|
37
37
|
const yamlDeployer = __importStar(require("./deployer"));
|
|
38
38
|
const principal_1 = require("../iam/principal");
|
|
39
|
+
const publish_1 = require("../../lib/events/publish");
|
|
39
40
|
/**
|
|
40
41
|
* Invoke a YAML workflow with scope injection.
|
|
41
42
|
* Shared by HTTP route and cron callback.
|
|
@@ -71,14 +72,84 @@ async function invokeYamlWorkflow(wf, options = {}) {
|
|
|
71
72
|
data._metadata = {};
|
|
72
73
|
data._metadata.source = options.source;
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
const wfMeta = {
|
|
76
|
+
workflowName: wf.graph_topic,
|
|
77
|
+
taskQueue: wf.app_id,
|
|
78
|
+
};
|
|
78
79
|
if (options.sync) {
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
(0, publish_1.publishWorkflowEvent)({
|
|
81
|
+
type: 'workflow.started',
|
|
82
|
+
source: 'graph',
|
|
83
|
+
workflowId: options.jobId || wf.graph_topic,
|
|
84
|
+
...wfMeta,
|
|
85
|
+
status: 'running',
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
const { job_id, result } = await yamlDeployer.invokeYamlWorkflowSync(wf.app_id, wf.graph_topic, data, options.timeout, wf.graph_topic);
|
|
89
|
+
(0, publish_1.publishWorkflowEvent)({
|
|
90
|
+
type: 'workflow.completed',
|
|
91
|
+
source: 'graph',
|
|
92
|
+
workflowId: job_id,
|
|
93
|
+
...wfMeta,
|
|
94
|
+
status: 'completed',
|
|
95
|
+
data: typeof result === 'object' && result !== null ? result : undefined,
|
|
96
|
+
});
|
|
97
|
+
return { job_id, result };
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
(0, publish_1.publishWorkflowEvent)({
|
|
101
|
+
type: 'workflow.failed',
|
|
102
|
+
source: 'graph',
|
|
103
|
+
workflowId: options.jobId || wf.graph_topic,
|
|
104
|
+
...wfMeta,
|
|
105
|
+
status: 'failed',
|
|
106
|
+
data: { error: err?.message ?? String(err) },
|
|
107
|
+
});
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
81
110
|
}
|
|
111
|
+
// Async path — include ngn so HotMesh routes the completion reply back to
|
|
112
|
+
// this engine instance, enabling fire-and-forget lifecycle event tracking.
|
|
113
|
+
const engine = await yamlDeployer.getEngine(wf.app_id);
|
|
114
|
+
const internalEngine = engine.engine;
|
|
115
|
+
const ngn = internalEngine?.guid;
|
|
116
|
+
const context = (options.jobId || ngn)
|
|
117
|
+
? {
|
|
118
|
+
metadata: {
|
|
119
|
+
...(options.jobId ? { jid: options.jobId } : {}),
|
|
120
|
+
...(ngn ? { ngn } : {}),
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
: undefined;
|
|
82
124
|
const jobId = await yamlDeployer.invokeYamlWorkflow(wf.app_id, wf.graph_topic, data, wf.graph_topic, context);
|
|
125
|
+
(0, publish_1.publishWorkflowEvent)({
|
|
126
|
+
type: 'workflow.started',
|
|
127
|
+
source: 'graph',
|
|
128
|
+
workflowId: jobId,
|
|
129
|
+
...wfMeta,
|
|
130
|
+
status: 'running',
|
|
131
|
+
});
|
|
132
|
+
// Register a best-effort completion callback. Fires when HotMesh routes the
|
|
133
|
+
// job reply back to this engine (requires ngn set above). Cleans itself up
|
|
134
|
+
// after 5 minutes regardless so there is no unbounded callback accumulation.
|
|
135
|
+
if (ngn && internalEngine?.registerJobCallback) {
|
|
136
|
+
const timeoutMs = 5 * 60_000;
|
|
137
|
+
const timer = setTimeout(() => internalEngine.delistJobCallback?.(jobId), timeoutMs);
|
|
138
|
+
internalEngine.registerJobCallback(jobId, (_topic, output) => {
|
|
139
|
+
clearTimeout(timer);
|
|
140
|
+
internalEngine.delistJobCallback?.(jobId);
|
|
141
|
+
const failed = !!output?.metadata?.err;
|
|
142
|
+
(0, publish_1.publishWorkflowEvent)({
|
|
143
|
+
type: failed ? 'workflow.failed' : 'workflow.completed',
|
|
144
|
+
source: 'graph',
|
|
145
|
+
workflowId: jobId,
|
|
146
|
+
...wfMeta,
|
|
147
|
+
status: failed ? 'failed' : 'completed',
|
|
148
|
+
data: failed
|
|
149
|
+
? { error: output.metadata.err }
|
|
150
|
+
: (output?.data && typeof output.data === 'object' ? output.data : undefined),
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
83
154
|
return { job_id: jobId };
|
|
84
155
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LTGraphWorkflowConfig } from '../types/startup';
|
|
2
|
+
/**
|
|
3
|
+
* Register declarative graph (YAML/DAG) workflows at startup — the graph-form
|
|
4
|
+
* peer of durable `workers`. Each flow is created insert-if-absent, then
|
|
5
|
+
* deployed + activated through the same path the dashboard uses.
|
|
6
|
+
*
|
|
7
|
+
* On a re-boot where the flow already exists:
|
|
8
|
+
* - description and output_schema are synced if stale
|
|
9
|
+
* - when the YAML version bumps, yaml_content is updated and the flow is redeployed
|
|
10
|
+
*
|
|
11
|
+
* Per-flow failures are logged and skipped so a single malformed flow can never
|
|
12
|
+
* block boot.
|
|
13
|
+
*/
|
|
14
|
+
export declare function seedGraphWorkflows(configs: LTGraphWorkflowConfig[]): Promise<void>;
|
|
@@ -0,0 +1,126 @@
|
|
|
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.seedGraphWorkflows = seedGraphWorkflows;
|
|
37
|
+
const logger_1 = require("../lib/logger");
|
|
38
|
+
const utils_1 = require("../modules/utils");
|
|
39
|
+
function extractYamlVersion(yaml) {
|
|
40
|
+
const m = yaml.match(/^\s*version:\s*['"]?(\S+?)['"]?\s*$/m);
|
|
41
|
+
return m?.[1] ?? '0';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Register declarative graph (YAML/DAG) workflows at startup — the graph-form
|
|
45
|
+
* peer of durable `workers`. Each flow is created insert-if-absent, then
|
|
46
|
+
* deployed + activated through the same path the dashboard uses.
|
|
47
|
+
*
|
|
48
|
+
* On a re-boot where the flow already exists:
|
|
49
|
+
* - description and output_schema are synced if stale
|
|
50
|
+
* - when the YAML version bumps, yaml_content is updated and the flow is redeployed
|
|
51
|
+
*
|
|
52
|
+
* Per-flow failures are logged and skipped so a single malformed flow can never
|
|
53
|
+
* block boot.
|
|
54
|
+
*/
|
|
55
|
+
async function seedGraphWorkflows(configs) {
|
|
56
|
+
const { createYamlWorkflowDirect, listYamlWorkflows, updateYamlWorkflow } = await Promise.resolve().then(() => __importStar(require('../api/yaml-workflows/crud')));
|
|
57
|
+
const { deployYamlWorkflow } = await Promise.resolve().then(() => __importStar(require('../api/yaml-workflows/deploy')));
|
|
58
|
+
for (const gf of configs) {
|
|
59
|
+
const namespace = (0, utils_1.sanitizeServerName)(gf.namespace ?? 'graph');
|
|
60
|
+
const graphTopic = (0, utils_1.sanitizeToolName)(gf.name);
|
|
61
|
+
try {
|
|
62
|
+
const created = await createYamlWorkflowDirect({
|
|
63
|
+
name: gf.name,
|
|
64
|
+
description: gf.description,
|
|
65
|
+
yaml_content: gf.yaml,
|
|
66
|
+
input_schema: gf.inputSchema,
|
|
67
|
+
output_schema: gf.outputSchema,
|
|
68
|
+
app_id: namespace,
|
|
69
|
+
tags: gf.tags,
|
|
70
|
+
});
|
|
71
|
+
if (created.status === 409) {
|
|
72
|
+
// Flow already exists — sync stale fields and redeploy if YAML version bumped.
|
|
73
|
+
const listing = await listYamlWorkflows({ app_id: namespace, graph_topic: graphTopic, limit: 1 });
|
|
74
|
+
const match = listing.data?.workflows?.[0];
|
|
75
|
+
if (match) {
|
|
76
|
+
const updates = {};
|
|
77
|
+
if (gf.description && match.description !== gf.description)
|
|
78
|
+
updates.description = gf.description;
|
|
79
|
+
if (gf.outputSchema)
|
|
80
|
+
updates.output_schema = gf.outputSchema;
|
|
81
|
+
if (gf.inputSchema)
|
|
82
|
+
updates.input_schema = gf.inputSchema;
|
|
83
|
+
const storedVersion = extractYamlVersion(match.yaml_content ?? '');
|
|
84
|
+
const newVersion = extractYamlVersion(gf.yaml);
|
|
85
|
+
const yamlChanged = newVersion !== storedVersion;
|
|
86
|
+
if (yamlChanged) {
|
|
87
|
+
updates.yaml_content = gf.yaml;
|
|
88
|
+
}
|
|
89
|
+
if (Object.keys(updates).length > 0) {
|
|
90
|
+
await updateYamlWorkflow({ id: match.id, ...updates });
|
|
91
|
+
logger_1.loggerRegistry.info(`[long-tail] graph flow updated: ${gf.name}`);
|
|
92
|
+
}
|
|
93
|
+
if (yamlChanged) {
|
|
94
|
+
const deployed = await deployYamlWorkflow({ id: match.id });
|
|
95
|
+
if (deployed.status !== 200) {
|
|
96
|
+
logger_1.loggerRegistry.warn(`[long-tail] graph flow redeploy failed for ${gf.name}: ${deployed.error ?? 'unknown error'}`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
logger_1.loggerRegistry.info(`[long-tail] graph flow redeployed: ${gf.name} (v${newVersion})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
logger_1.loggerRegistry.info(`[long-tail] graph flow already registered: ${gf.name}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
logger_1.loggerRegistry.info(`[long-tail] graph flow already registered: ${gf.name}`);
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (created.status !== 200 || !created.data?.id) {
|
|
112
|
+
logger_1.loggerRegistry.warn(`[long-tail] graph flow create failed for ${gf.name}: ${created.error ?? 'unknown error'}`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const deployed = await deployYamlWorkflow({ id: created.data.id });
|
|
116
|
+
if (deployed.status !== 200) {
|
|
117
|
+
logger_1.loggerRegistry.warn(`[long-tail] graph flow deploy failed for ${gf.name}: ${deployed.error ?? 'unknown error'}`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
logger_1.loggerRegistry.info(`[long-tail] graph flow registered + deployed: ${gf.name} (namespace: ${namespace})`);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
logger_1.loggerRegistry.warn(`[long-tail] graph flow seed error for ${gf.name}: ${err.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
package/build/start/workers.js
CHANGED
|
@@ -238,6 +238,20 @@ async function startWorkers(startConfig, workers, builtinMcpServerFactories) {
|
|
|
238
238
|
}
|
|
239
239
|
// 3. Clean stale builtin servers no longer in factory list
|
|
240
240
|
await cleanStaleBuiltinServers(Object.keys(allFactories));
|
|
241
|
+
// Seed static graph (YAML/DAG) workflows — the graph-form peer of `workers`.
|
|
242
|
+
// Hand-authored flows from config, plus the hello-world example when enabled.
|
|
243
|
+
// Runs before worker registration so newly-deployed flows are picked up.
|
|
244
|
+
if (!isReadonly) {
|
|
245
|
+
const graphFlows = [...(startConfig.graphWorkflows ?? [])];
|
|
246
|
+
if (startConfig.examples) {
|
|
247
|
+
const { EXAMPLE_GRAPH_WORKFLOWS } = await Promise.resolve().then(() => __importStar(require('../examples')));
|
|
248
|
+
graphFlows.push(...EXAMPLE_GRAPH_WORKFLOWS);
|
|
249
|
+
}
|
|
250
|
+
if (graphFlows.length) {
|
|
251
|
+
const { seedGraphWorkflows } = await Promise.resolve().then(() => __importStar(require('./graph-workflows')));
|
|
252
|
+
await seedGraphWorkflows(graphFlows);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
241
255
|
// Register workers for active YAML (deterministic) workflows
|
|
242
256
|
await yamlWorkflowWorkers.registerAllActiveWorkers();
|
|
243
257
|
}
|