@hotmeshio/long-tail 0.12.0 → 0.13.0
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 +1 -0
- package/build/api/escalations/helpers.js +4 -2
- package/build/api/settings.js +3 -0
- package/build/services/agent/index.d.ts +11 -0
- package/build/services/agent/index.js +32 -0
- package/build/services/agent/sql.d.ts +7 -0
- package/build/services/agent/sql.js +32 -1
- package/build/services/agent/subscription-sql.d.ts +6 -0
- package/build/services/agent/subscription-sql.js +32 -1
- package/build/services/agent/subscriptions.d.ts +6 -0
- package/build/services/agent/subscriptions.js +23 -0
- package/build/services/config/index.d.ts +1 -1
- package/build/services/config/index.js +2 -1
- package/build/services/config/write.d.ts +10 -0
- package/build/services/config/write.js +49 -2
- package/build/services/domain/seed.d.ts +12 -5
- package/build/services/domain/seed.js +25 -6
- package/build/services/mcp/db.d.ts +16 -0
- package/build/services/mcp/db.js +24 -0
- package/build/services/mcp/sql.d.ts +8 -0
- package/build/services/mcp/sql.js +24 -1
- package/build/services/role/seed.d.ts +21 -0
- package/build/services/role/seed.js +113 -0
- package/build/services/role/sql.d.ts +8 -0
- package/build/services/role/sql.js +24 -1
- package/build/services/role/types.d.ts +7 -3
- package/build/services/role/types.js +7 -3
- package/build/services/topics/index.d.ts +2 -0
- package/build/services/topics/index.js +7 -0
- package/build/services/topics/sql.d.ts +2 -0
- package/build/services/topics/sql.js +5 -1
- package/build/services/topics/system-topics.d.ts +3 -2
- package/build/services/topics/system-topics.js +4 -3
- package/build/services/user/index.d.ts +1 -1
- package/build/services/user/index.js +2 -1
- package/build/services/user/roles.d.ts +8 -0
- package/build/services/user/roles.js +29 -0
- package/build/services/user/sql.d.ts +6 -0
- package/build/services/user/sql.js +9 -1
- package/build/services/user/sso-provision.js +14 -3
- package/build/start/apply-report.d.ts +26 -0
- package/build/start/apply-report.js +65 -0
- package/build/start/config.js +8 -1
- package/build/start/workers.js +170 -33
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/auth.d.ts +27 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/startup.d.ts +108 -4
- package/dashboard/dist/assets/{AdminDashboard-CahUELrr.js → AdminDashboard-D2unnS2b.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-CahUELrr.js.map → AdminDashboard-D2unnS2b.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CkMv-cTV.js → AgentConfigPage-CBkf403g.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-CkMv-cTV.js.map → AgentConfigPage-CBkf403g.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-ZGea3Z4A.js → AgentDetailPage-CAIU3yzo.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-ZGea3Z4A.js.map → AgentDetailPage-CAIU3yzo.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-BMWSUJGi.js → AgentsPage-qP9fWMyT.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-BMWSUJGi.js.map → AgentsPage-qP9fWMyT.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-DvWaiafI.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-DN8tq7pz.js → BotPicker-BN-MKITV.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-DN8tq7pz.js.map → BotPicker-BN-MKITV.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-EAO3Ae0S.js → CapabilitiesPage-CJfmWokN.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-EAO3Ae0S.js.map → CapabilitiesPage-CJfmWokN.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-J-RejbjG.js → CollapsibleSection-BvMHlHyt.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-J-RejbjG.js.map → CollapsibleSection-BvMHlHyt.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-Dw8N9tmQ.js → CountdownTimer-By4rbMDN.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-Dw8N9tmQ.js.map → CountdownTimer-By4rbMDN.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CTurxwRn.js → CredentialsPage-2TvvRwGJ.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CTurxwRn.js.map → CredentialsPage-2TvvRwGJ.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DZ5TmIQG.js → CronLabel-HxmsDSnV.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DZ5TmIQG.js.map → CronLabel-HxmsDSnV.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-BES_FTrm.js → CustomDurationPicker-8Ao-1pKA.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-BES_FTrm.js.map → CustomDurationPicker-8Ao-1pKA.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-BWD9aGOz.js → DropZone-DovkhN2p.js} +2 -2
- package/dashboard/dist/assets/{DropZone-BWD9aGOz.js.map → DropZone-DovkhN2p.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CIGRporU.js → ElapsedCell-BkRu9Xpd.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CIGRporU.js.map → ElapsedCell-BkRu9Xpd.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel--E6hLMCM.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-CKIFsDOB.js.map → EntityTimelinePanel--E6hLMCM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DOrv-quD.js → EscalationListSchemaPage-CdFtqEEX.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DOrv-quD.js.map → EscalationListSchemaPage-CdFtqEEX.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DAOVAxAM.js → EscalationSchemaPage-BsjS2axz.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-DAOVAxAM.js.map → EscalationSchemaPage-BsjS2axz.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-B27sDn5O.js → EscalationsOverview-FL-xteVc.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-B27sDn5O.js.map → EscalationsOverview-FL-xteVc.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Co1d40Qq.js → EventTable-BOcgZ78i.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Co1d40Qq.js.map → EventTable-BOcgZ78i.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-2ZfU21EA.js → FilterBar-DfCiCmm-.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-2ZfU21EA.js.map → FilterBar-DfCiCmm-.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-pdvc9VSv.js → GraphInvokePage-DfVeiN-8.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-pdvc9VSv.js.map → GraphInvokePage-DfVeiN-8.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-CLlDsBnw.js → HomePage-C2IhF9WB.js} +2 -2
- package/dashboard/dist/assets/{HomePage-CLlDsBnw.js.map → HomePage-C2IhF9WB.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-DMremj2e.js → ListToolbar-DA0PTOl5.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-DMremj2e.js.map → ListToolbar-DA0PTOl5.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BhztmhoL.js → McpOverview-DstPch5M.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BhztmhoL.js.map → McpOverview-DstPch5M.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BseZfrhc.js → McpQueryDetailPage-Csv0PKE0.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BseZfrhc.js.map → McpQueryDetailPage-Csv0PKE0.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DMzkble7.js → McpQueryPage-DxmqCkly.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DMzkble7.js.map → McpQueryPage-DxmqCkly.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DqaBQAnn.js → McpRunDetailPage-CcJOlp_B.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DqaBQAnn.js.map → McpRunDetailPage-CcJOlp_B.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-Du8GnHFv.js → McpRunsPage-BZCR043j.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-Du8GnHFv.js.map → McpRunsPage-BZCR043j.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-C09QuOEz.js → NamespacePill-BeifzjUm.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-C09QuOEz.js.map → NamespacePill-BeifzjUm.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-CL2feqwS.js → OperationsPage-DMsPXITh.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-CL2feqwS.js.map → OperationsPage-DMsPXITh.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-BHiGQZN_.js → OperatorDashboard-DSloftQ5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-BHiGQZN_.js.map → OperatorDashboard-DSloftQ5.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-B7YJxa4o.js → PageHeader-BpeBHqyc.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-B7YJxa4o.js.map → PageHeader-BpeBHqyc.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-gT-5ovJh.js → PageHeaderWithStats-JXeUFa_g.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-gT-5ovJh.js.map → PageHeaderWithStats-JXeUFa_g.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-D6GGZgUS.js → PersonaDetailPage-jDVRCLbU.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-D6GGZgUS.js.map → PersonaDetailPage-jDVRCLbU.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BQYCdmAs.js → PersonasPage-DnDDwXoy.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BQYCdmAs.js.map → PersonasPage-DnDDwXoy.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-P45jOLim.js → ProcessDetailPage-CfAUU6q2.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-P45jOLim.js.map → ProcessDetailPage-CfAUU6q2.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CgdzgCY6.js → ProcessesListPage-CnAXzaVv.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CgdzgCY6.js.map → ProcessesListPage-CnAXzaVv.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-Dg1p6Qz_.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-Dg1p6Qz_.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-CtYI1_k1.js → RolePill-EocCXZh0.js} +2 -2
- package/dashboard/dist/assets/{RolePill-CtYI1_k1.js.map → RolePill-EocCXZh0.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-Ci7_PbPt.js → RolesPage-DeRVQux8.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-Ci7_PbPt.js.map → RolesPage-DeRVQux8.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-CB0pV097.js → RunAsSelector-BFNqQGuG.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-CB0pV097.js.map → RunAsSelector-BFNqQGuG.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-DpbPhAj1.js → ScanCodesPage-D0GOdk5m.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-DpbPhAj1.js.map → ScanCodesPage-D0GOdk5m.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CGnMGlt0.js → ScanSchemeDetailPage-vFqoe_P4.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CGnMGlt0.js.map → ScanSchemeDetailPage-vFqoe_P4.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-DH1ynTX9.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-BTeV7TGy.js.map → ScanStationPage-DH1ynTX9.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-B76rOtA0.js → ScopeBadge-H5dEqeHi.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-B76rOtA0.js.map → ScopeBadge-H5dEqeHi.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-DH-0JEyx.js → StickyPagination-B99hVu95.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-DH-0JEyx.js.map → StickyPagination-B99hVu95.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-u-pDrHfS.js → StreamMessageDetail-DcDGISrv.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-u-pDrHfS.js.map → StreamMessageDetail-DcDGISrv.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-vN1N8BGy.js → SwimlaneTimeline-BP3mSQAg.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-vN1N8BGy.js.map → SwimlaneTimeline-BP3mSQAg.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BQAPOp17.js → TagInput-Ch5u6iPH.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BQAPOp17.js.map → TagInput-Ch5u6iPH.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-CAQm6avs.js → TaskDetailPage-_XWLJzt-.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-CAQm6avs.js.map → TaskDetailPage-_XWLJzt-.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-C2NImrwl.js → TaskQueuePill-Bz146p-P.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-C2NImrwl.js.map → TaskQueuePill-Bz146p-P.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-C1bT3DT9.js → TasksListPage-iGriKiO2.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-C1bT3DT9.js.map → TasksListPage-iGriKiO2.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-qZxkJ8Am.js → TimeAgo-BO33VeFl.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-qZxkJ8Am.js.map → TimeAgo-BO33VeFl.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-CC3dz6FG.js → TimestampCell-KAjX7w35.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-CC3dz6FG.js.map → TimestampCell-KAjX7w35.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-FOZm67TS.js → ToolPill-sj8OkBB0.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-FOZm67TS.js.map → ToolPill-sj8OkBB0.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-C3sSQUvw.js → ToolTestPanel-BchG2yC6.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-C3sSQUvw.js.map → ToolTestPanel-BchG2yC6.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-ClI0I8Mu.js → TopicDetailPage-BaK8H0o1.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-ClI0I8Mu.js.map → TopicDetailPage-BaK8H0o1.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CNf2VZud.js → TopicsPage-DEyvm669.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CNf2VZud.js.map → TopicsPage-DEyvm669.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BdMHmyL3.js → UserName-BV6SKI9P.js} +2 -2
- package/dashboard/dist/assets/{UserName-BdMHmyL3.js.map → UserName-BV6SKI9P.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-Ba4mYFoW.js → WorkflowExecutionPage-1sKoEFNC.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-Ba4mYFoW.js.map → WorkflowExecutionPage-1sKoEFNC.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-C5TEWlfO.js → WorkflowPill-BcA7S3gI.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-C5TEWlfO.js.map → WorkflowPill-BcA7S3gI.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-ImEm16tX.js → WorkflowsDashboard-YTHDZZOD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-ImEm16tX.js.map → WorkflowsDashboard-YTHDZZOD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BpWyV_tj.js → WorkflowsOverview-ucXPLTtm.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BpWyV_tj.js.map → WorkflowsOverview-ucXPLTtm.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BFBlw1YY.js → YamlWorkflowDetailPage-C_RTZKqZ.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BFBlw1YY.js.map → YamlWorkflowDetailPage-C_RTZKqZ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-C9gxapRg.js → YamlWorkflowsPage-Usid3w2W.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-C9gxapRg.js.map → YamlWorkflowsPage-Usid3w2W.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BJQtJTiz.js → agents-BTDsRK8e.js} +2 -2
- package/dashboard/dist/assets/{agents-BJQtJTiz.js.map → agents-BTDsRK8e.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DDlU1gMy.js → bots-DxLrfdfr.js} +2 -2
- package/dashboard/dist/assets/{bots-DDlU1gMy.js.map → bots-DxLrfdfr.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-qYrUpdid.js → capabilities-DbTmeW-S.js} +2 -2
- package/dashboard/dist/assets/{capabilities-qYrUpdid.js.map → capabilities-DbTmeW-S.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DnJ1VDTs.js → controlplane-CEBntAL4.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DnJ1VDTs.js.map → controlplane-CEBntAL4.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-Carqdwoh.js +2 -0
- package/dashboard/dist/assets/escalation-columns-Carqdwoh.js.map +1 -0
- package/dashboard/dist/assets/{index-KotwPxGB.js → index-B2hz0pUh.js} +2 -2
- package/dashboard/dist/assets/{index-KotwPxGB.js.map → index-B2hz0pUh.js.map} +1 -1
- package/dashboard/dist/assets/{index-04QQsxMp.js → index-B9m7fA3M.js} +2 -2
- package/dashboard/dist/assets/{index-04QQsxMp.js.map → index-B9m7fA3M.js.map} +1 -1
- package/dashboard/dist/assets/{index-B5q8ksfv.js → index-BhapT-Vl.js} +2 -2
- package/dashboard/dist/assets/{index-B5q8ksfv.js.map → index-BhapT-Vl.js.map} +1 -1
- package/dashboard/dist/assets/{index-CtAPxA03.js → index-Bqm4zu46.js} +2 -2
- package/dashboard/dist/assets/{index-CtAPxA03.js.map → index-Bqm4zu46.js.map} +1 -1
- package/dashboard/dist/assets/{index-LiLVAQzB.js → index-C0hSttF5.js} +2 -2
- package/dashboard/dist/assets/{index-LiLVAQzB.js.map → index-C0hSttF5.js.map} +1 -1
- package/dashboard/dist/assets/{index-DhRdWzz0.js → index-CDkg6iOE.js} +4 -4
- package/dashboard/dist/assets/{index-DhRdWzz0.js.map → index-CDkg6iOE.js.map} +1 -1
- package/dashboard/dist/assets/{index-D-5F3Bw-.js → index-CVBBkW8V.js} +2 -2
- package/dashboard/dist/assets/{index-D-5F3Bw-.js.map → index-CVBBkW8V.js.map} +1 -1
- package/dashboard/dist/assets/{index-BUpB9ezn.js → index-CgIBjZta.js} +2 -2
- package/dashboard/dist/assets/{index-BUpB9ezn.js.map → index-CgIBjZta.js.map} +1 -1
- package/dashboard/dist/assets/{index-C991QfUN.js → index-DBXm49S6.js} +27 -27
- package/dashboard/dist/assets/index-DBXm49S6.js.map +1 -0
- package/dashboard/dist/assets/{index-BAqQSgxn.js → index-De8iV1y2.js} +2 -2
- package/dashboard/dist/assets/{index-BAqQSgxn.js.map → index-De8iV1y2.js.map} +1 -1
- package/dashboard/dist/assets/{index-BHbO4F8Z.js → index-DsgjFRvA.js} +2 -2
- package/dashboard/dist/assets/{index-BHbO4F8Z.js.map → index-DsgjFRvA.js.map} +1 -1
- package/dashboard/dist/assets/{index-CFlmubaP.js → index-kes8V4Xw.js} +2 -2
- package/dashboard/dist/assets/{index-CFlmubaP.js.map → index-kes8V4Xw.js.map} +1 -1
- package/dashboard/dist/assets/{index-CroJTX8g.js → index-nwLh3CK2.js} +2 -2
- package/dashboard/dist/assets/{index-CroJTX8g.js.map → index-nwLh3CK2.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CnMeg8Rw.js → knowledge-oFYAanUp.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CnMeg8Rw.js.map → knowledge-oFYAanUp.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CHPSFv7m.js → mcp-C9Kw4Ow8.js} +2 -2
- package/dashboard/dist/assets/{mcp-CHPSFv7m.js.map → mcp-C9Kw4Ow8.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-C19EGwdN.js → mcp-query-BwzpZ91Z.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-C19EGwdN.js.map → mcp-query-BwzpZ91Z.js.map} +1 -1
- package/dashboard/dist/assets/{personas-Br1Vo2S3.js → personas-D5ehmtRb.js} +2 -2
- package/dashboard/dist/assets/{personas-Br1Vo2S3.js.map → personas-D5ehmtRb.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-QMrFoJZX.js → pipelines-xgPKGEdD.js} +2 -2
- package/dashboard/dist/assets/{pipelines-QMrFoJZX.js.map → pipelines-xgPKGEdD.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-Doy_7cGX.js → tasks-CLyrl-MU.js} +2 -2
- package/dashboard/dist/assets/{tasks-Doy_7cGX.js.map → tasks-CLyrl-MU.js.map} +1 -1
- package/dashboard/dist/assets/{topics-BcJS4G09.js → topics-B_gO7CQ0.js} +2 -2
- package/dashboard/dist/assets/{topics-BcJS4G09.js.map → topics-B_gO7CQ0.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-ldE5o0ok.js → useEventHooks-BdWYm63U.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-ldE5o0ok.js.map → useEventHooks-BdWYm63U.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CCu8fZc6.js → useNamespace-C238M4Qn.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CCu8fZc6.js.map → useNamespace-C238M4Qn.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-DDrXwFXX.js → useYamlActivityEvents-B2ryEK4S.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-DDrXwFXX.js.map → useYamlActivityEvents-B2ryEK4S.js.map} +1 -1
- package/dashboard/dist/assets/{users-BvKhSq1i.js → users-BFaTe6Mt.js} +2 -2
- package/dashboard/dist/assets/{users-BvKhSq1i.js.map → users-BFaTe6Mt.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-Aw7bzBxa.js → vendor-icons-BPsNpK3Y.js} +142 -137
- package/dashboard/dist/assets/vendor-icons-BPsNpK3Y.js.map +1 -0
- package/dashboard/dist/assets/{workflows-D09ysQF1.js → workflows-DXz7tZxp.js} +2 -2
- package/dashboard/dist/assets/{workflows-D09ysQF1.js.map → workflows-DXz7tZxp.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BFHrxEl4.js → yaml-workflows-u3xuRAnS.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BFHrxEl4.js.map → yaml-workflows-u3xuRAnS.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/code-owned-configuration.md +131 -0
- package/docs/hitl/x-lt-transition.md +13 -0
- package/docs/scan-codes.md +24 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BjsbfsWW.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BjsbfsWW.js.map +0 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CKIFsDOB.js +0 -2
- package/dashboard/dist/assets/RoleDetailPage-Dme2pa9z.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-Dme2pa9z.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-BTeV7TGy.js +0 -2
- package/dashboard/dist/assets/escalation-columns-BCnVWr_n.js +0 -2
- package/dashboard/dist/assets/escalation-columns-BCnVWr_n.js.map +0 -1
- package/dashboard/dist/assets/index-C991QfUN.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-Aw7bzBxa.js.map +0 -1
package/README.md
CHANGED
|
@@ -230,6 +230,7 @@ All modes share PostgreSQL and scale independently. See [Cloud Deployment](https
|
|
|
230
230
|
| [CLI](https://github.com/hotmeshio/long-tail/blob/main/docs/cli.md) | `ltc` — terminal access to workflows, escalations, knowledge, MCP |
|
|
231
231
|
| [Escalation Strategies](https://github.com/hotmeshio/long-tail/blob/main/docs/escalation-strategies.md) | Default, MCP triage, custom handlers |
|
|
232
232
|
| [Schema Enforcement](https://github.com/hotmeshio/long-tail/blob/main/docs/schema-enforcement.md) | form_schema as an enforced API contract on every resolve surface |
|
|
233
|
+
| [Code-Owned Configuration](https://github.com/hotmeshio/long-tail/blob/main/docs/code-owned-configuration.md) | `configSource` — declared config compared and applied at every boot |
|
|
233
234
|
| [Faceted Routing](https://github.com/hotmeshio/long-tail/blob/main/docs/faceted-routing.md) | Query and atomically claim the queue by facets; dispatcher pattern |
|
|
234
235
|
| [SDK](https://github.com/hotmeshio/long-tail/blob/main/docs/sdk.md) | Embedded usage, `createClient`, event subscriptions |
|
|
235
236
|
| [Architecture](https://github.com/hotmeshio/long-tail/blob/main/docs/architecture.md) | Project structure, conventions, discovery |
|
|
@@ -245,9 +245,11 @@ async function ensureRoleMembership(userId, requiredRole, callerUserId, provisio
|
|
|
245
245
|
const declaredRole = provisionIfAbsent.roles?.find((r) => r.role === requiredRole);
|
|
246
246
|
if (!declaredRole)
|
|
247
247
|
return false;
|
|
248
|
-
// Add the role
|
|
248
|
+
// Add the role only when ABSENT (ON CONFLICT DO NOTHING). Provisioning is a
|
|
249
|
+
// sync of membership, never of scope: a grant the admin already restricted
|
|
250
|
+
// (e.g. write:none on a station) must survive every claim-time provision.
|
|
249
251
|
try {
|
|
250
|
-
await userService.
|
|
252
|
+
await userService.grantRoleIfAbsent(userId, requiredRole, (declaredRole.type || 'member'), {
|
|
251
253
|
read_scope: declaredRole.read_scope,
|
|
252
254
|
write_scope: declaredRole.write_scope,
|
|
253
255
|
});
|
package/build/api/settings.js
CHANGED
|
@@ -68,6 +68,9 @@ async function getSettings(req) {
|
|
|
68
68
|
auth: {
|
|
69
69
|
sso: (0, sso_1.isSSOEnabled)(),
|
|
70
70
|
ssoLogoutUrl: (0, sso_1.getSSOConfig)()?.logoutUrl ?? null,
|
|
71
|
+
// Session keepalive dials for the SPA (null = no keepalive / no idle gate).
|
|
72
|
+
ssoKeepaliveSeconds: (0, sso_1.getSSOConfig)()?.keepaliveSeconds ?? null,
|
|
73
|
+
ssoKeepaliveIdleTimeoutSeconds: (0, sso_1.getSSOConfig)()?.keepaliveIdleTimeoutSeconds ?? null,
|
|
71
74
|
},
|
|
72
75
|
ai: {
|
|
73
76
|
enabled: (0, llm_1.hasLLMApiKey)(),
|
|
@@ -9,6 +9,8 @@ export declare function listAgents(filters?: ListAgentsFilters): Promise<{
|
|
|
9
9
|
agents: LTAgent[];
|
|
10
10
|
total: number;
|
|
11
11
|
}>;
|
|
12
|
+
/** Every agent id — the startup orphan report's candidate set. */
|
|
13
|
+
export declare function listAgentIds(): Promise<string[]>;
|
|
12
14
|
export declare function getAgent(id: string): Promise<LTAgent | null>;
|
|
13
15
|
export declare function createAgent(data: Partial<LTAgent> & {
|
|
14
16
|
id: string;
|
|
@@ -23,6 +25,15 @@ export declare function deleteAgent(id: string): Promise<boolean>;
|
|
|
23
25
|
export declare function seedAgent(data: Partial<LTAgent> & {
|
|
24
26
|
id: string;
|
|
25
27
|
}): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Apply an agent declaration at startup (code is source of truth).
|
|
30
|
+
* Declared fields — description, status, knowledge domain, behaviors, goals,
|
|
31
|
+
* rules, reaction targets — are written when they differ; runtime state
|
|
32
|
+
* (user_id, capabilities, metadata, last_run_at) is never touched.
|
|
33
|
+
*/
|
|
34
|
+
export declare function applyAgent(data: Partial<LTAgent> & {
|
|
35
|
+
id: string;
|
|
36
|
+
}): Promise<'applied' | 'unchanged'>;
|
|
26
37
|
/**
|
|
27
38
|
* Aggregate stats for an agent: knowledge entry count, pending escalation count,
|
|
28
39
|
* and last workflow execution time.
|
|
@@ -34,11 +34,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.listAgents = listAgents;
|
|
37
|
+
exports.listAgentIds = listAgentIds;
|
|
37
38
|
exports.getAgent = getAgent;
|
|
38
39
|
exports.createAgent = createAgent;
|
|
39
40
|
exports.updateAgent = updateAgent;
|
|
40
41
|
exports.deleteAgent = deleteAgent;
|
|
41
42
|
exports.seedAgent = seedAgent;
|
|
43
|
+
exports.applyAgent = applyAgent;
|
|
42
44
|
exports.getAgentStats = getAgentStats;
|
|
43
45
|
const db_1 = require("../../lib/db");
|
|
44
46
|
const logger_1 = require("../../lib/logger");
|
|
@@ -59,6 +61,12 @@ async function listAgents(filters = {}) {
|
|
|
59
61
|
total: countRes.rows[0]?.total ?? 0,
|
|
60
62
|
};
|
|
61
63
|
}
|
|
64
|
+
/** Every agent id — the startup orphan report's candidate set. */
|
|
65
|
+
async function listAgentIds() {
|
|
66
|
+
const pool = (0, db_1.getPool)();
|
|
67
|
+
const { rows } = await pool.query(sql_1.LIST_AGENT_IDS);
|
|
68
|
+
return rows.map((r) => r.id);
|
|
69
|
+
}
|
|
62
70
|
async function getAgent(id) {
|
|
63
71
|
const pool = (0, db_1.getPool)();
|
|
64
72
|
const { rows } = await pool.query(sql_1.GET_AGENT, [id]);
|
|
@@ -179,6 +187,30 @@ async function seedAgent(data) {
|
|
|
179
187
|
}
|
|
180
188
|
return inserted;
|
|
181
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Apply an agent declaration at startup (code is source of truth).
|
|
192
|
+
* Declared fields — description, status, knowledge domain, behaviors, goals,
|
|
193
|
+
* rules, reaction targets — are written when they differ; runtime state
|
|
194
|
+
* (user_id, capabilities, metadata, last_run_at) is never touched.
|
|
195
|
+
*/
|
|
196
|
+
async function applyAgent(data) {
|
|
197
|
+
const pool = (0, db_1.getPool)();
|
|
198
|
+
const { rowCount } = await pool.query(sql_1.APPLY_AGENT, [
|
|
199
|
+
data.id,
|
|
200
|
+
data.description ?? null,
|
|
201
|
+
data.status ?? 'inactive',
|
|
202
|
+
data.user_id ?? null,
|
|
203
|
+
data.knowledge_domain ?? null,
|
|
204
|
+
JSON.stringify(data.capabilities ?? []),
|
|
205
|
+
JSON.stringify(data.behaviors ?? {}),
|
|
206
|
+
data.goals ?? null,
|
|
207
|
+
data.rules ?? null,
|
|
208
|
+
data.workflow_type ?? null,
|
|
209
|
+
data.pipeline_id ?? null,
|
|
210
|
+
JSON.stringify(data.metadata ?? {}),
|
|
211
|
+
]);
|
|
212
|
+
return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
|
|
213
|
+
}
|
|
182
214
|
/**
|
|
183
215
|
* Aggregate stats for an agent: knowledge entry count, pending escalation count,
|
|
184
216
|
* and last workflow execution time.
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
export declare const LIST_AGENTS = "\n SELECT a.*,\n COALESCE(s.sub_count, 0)::int AS subscription_count,\n s.sub_topics\n FROM lt_agents a\n LEFT JOIN LATERAL (\n SELECT COUNT(*)::int AS sub_count,\n array_agg(topic ORDER BY created_at) AS sub_topics\n FROM lt_agent_subscriptions\n WHERE agent_id = a.id AND enabled = true\n ) s ON true\n WHERE ($1::text IS NULL OR a.status = $1)\n AND ($2::text IS NULL OR a.knowledge_domain = $2)\n ORDER BY a.updated_at DESC\n LIMIT $3 OFFSET $4\n";
|
|
2
2
|
export declare const COUNT_AGENTS = "\n SELECT COUNT(*)::int AS total FROM lt_agents\n WHERE ($1::text IS NULL OR status = $1)\n AND ($2::text IS NULL OR knowledge_domain = $2)\n";
|
|
3
3
|
export declare const GET_AGENT = "\n SELECT * FROM lt_agents WHERE id = $1\n";
|
|
4
|
+
export declare const LIST_AGENT_IDS = "\n SELECT id FROM lt_agents ORDER BY id\n";
|
|
4
5
|
export declare const INSERT_AGENT = "\n INSERT INTO lt_agents (id, description, status, user_id, knowledge_domain,\n capabilities, behaviors, goals, rules, workflow_type, pipeline_id, metadata)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\n RETURNING *\n";
|
|
5
6
|
export declare const UPDATE_AGENT = "\n UPDATE lt_agents SET\n description = COALESCE($2, description),\n status = COALESCE($3, status),\n user_id = COALESCE($4, user_id),\n knowledge_domain = COALESCE($5, knowledge_domain),\n capabilities = COALESCE($6, capabilities),\n behaviors = COALESCE($7, behaviors),\n goals = COALESCE($8, goals),\n rules = COALESCE($9, rules),\n workflow_type = COALESCE($10, workflow_type),\n pipeline_id = COALESCE($11, pipeline_id),\n metadata = COALESCE($12, metadata),\n last_run_at = COALESCE($13, last_run_at)\n WHERE id = $1\n RETURNING *\n";
|
|
6
7
|
export declare const DELETE_AGENT = "\n DELETE FROM lt_agents WHERE id = $1\n";
|
|
7
8
|
export declare const SEED_AGENT = "\n INSERT INTO lt_agents (id, description, status, user_id, knowledge_domain,\n capabilities, behaviors, goals, rules, workflow_type, pipeline_id, metadata)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\n ON CONFLICT (id) DO NOTHING\n";
|
|
9
|
+
/**
|
|
10
|
+
* Apply — code is source of truth for the declared fields. Runtime state
|
|
11
|
+
* (user_id, capabilities, metadata, last_run_at) is never touched; the
|
|
12
|
+
* IS DISTINCT FROM guard makes an unchanged declaration a zero-row no-op.
|
|
13
|
+
*/
|
|
14
|
+
export declare const APPLY_AGENT = "\n INSERT INTO lt_agents (id, description, status, user_id, knowledge_domain,\n capabilities, behaviors, goals, rules, workflow_type, pipeline_id, metadata)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\n ON CONFLICT (id) DO UPDATE SET\n description = EXCLUDED.description,\n status = EXCLUDED.status,\n knowledge_domain = EXCLUDED.knowledge_domain,\n behaviors = EXCLUDED.behaviors,\n goals = EXCLUDED.goals,\n rules = EXCLUDED.rules,\n workflow_type = EXCLUDED.workflow_type,\n pipeline_id = EXCLUDED.pipeline_id,\n updated_at = NOW()\n WHERE (lt_agents.description, lt_agents.status, lt_agents.knowledge_domain,\n lt_agents.behaviors, lt_agents.goals, lt_agents.rules,\n lt_agents.workflow_type, lt_agents.pipeline_id)\n IS DISTINCT FROM\n (EXCLUDED.description, EXCLUDED.status, EXCLUDED.knowledge_domain,\n EXCLUDED.behaviors, EXCLUDED.goals, EXCLUDED.rules,\n EXCLUDED.workflow_type, EXCLUDED.pipeline_id)\n RETURNING (xmax = 0) AS inserted\n";
|
|
8
15
|
export declare const KNOWLEDGE_COUNT = "\n SELECT COUNT(*)::int AS count FROM lt_knowledge WHERE domain = $1\n";
|
|
9
16
|
export declare const ESCALATION_COUNT = "\n SELECT COUNT(*)::int AS count FROM lt_escalations\n WHERE status = 'pending' AND created_by = $1\n";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ESCALATION_COUNT = exports.KNOWLEDGE_COUNT = exports.SEED_AGENT = exports.DELETE_AGENT = exports.UPDATE_AGENT = exports.INSERT_AGENT = exports.GET_AGENT = exports.COUNT_AGENTS = exports.LIST_AGENTS = void 0;
|
|
3
|
+
exports.ESCALATION_COUNT = exports.KNOWLEDGE_COUNT = exports.APPLY_AGENT = exports.SEED_AGENT = exports.DELETE_AGENT = exports.UPDATE_AGENT = exports.INSERT_AGENT = exports.LIST_AGENT_IDS = exports.GET_AGENT = exports.COUNT_AGENTS = exports.LIST_AGENTS = void 0;
|
|
4
4
|
exports.LIST_AGENTS = `
|
|
5
5
|
SELECT a.*,
|
|
6
6
|
COALESCE(s.sub_count, 0)::int AS subscription_count,
|
|
@@ -25,6 +25,9 @@ exports.COUNT_AGENTS = `
|
|
|
25
25
|
exports.GET_AGENT = `
|
|
26
26
|
SELECT * FROM lt_agents WHERE id = $1
|
|
27
27
|
`;
|
|
28
|
+
exports.LIST_AGENT_IDS = `
|
|
29
|
+
SELECT id FROM lt_agents ORDER BY id
|
|
30
|
+
`;
|
|
28
31
|
exports.INSERT_AGENT = `
|
|
29
32
|
INSERT INTO lt_agents (id, description, status, user_id, knowledge_domain,
|
|
30
33
|
capabilities, behaviors, goals, rules, workflow_type, pipeline_id, metadata)
|
|
@@ -57,6 +60,34 @@ exports.SEED_AGENT = `
|
|
|
57
60
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
58
61
|
ON CONFLICT (id) DO NOTHING
|
|
59
62
|
`;
|
|
63
|
+
/**
|
|
64
|
+
* Apply — code is source of truth for the declared fields. Runtime state
|
|
65
|
+
* (user_id, capabilities, metadata, last_run_at) is never touched; the
|
|
66
|
+
* IS DISTINCT FROM guard makes an unchanged declaration a zero-row no-op.
|
|
67
|
+
*/
|
|
68
|
+
exports.APPLY_AGENT = `
|
|
69
|
+
INSERT INTO lt_agents (id, description, status, user_id, knowledge_domain,
|
|
70
|
+
capabilities, behaviors, goals, rules, workflow_type, pipeline_id, metadata)
|
|
71
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
72
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
73
|
+
description = EXCLUDED.description,
|
|
74
|
+
status = EXCLUDED.status,
|
|
75
|
+
knowledge_domain = EXCLUDED.knowledge_domain,
|
|
76
|
+
behaviors = EXCLUDED.behaviors,
|
|
77
|
+
goals = EXCLUDED.goals,
|
|
78
|
+
rules = EXCLUDED.rules,
|
|
79
|
+
workflow_type = EXCLUDED.workflow_type,
|
|
80
|
+
pipeline_id = EXCLUDED.pipeline_id,
|
|
81
|
+
updated_at = NOW()
|
|
82
|
+
WHERE (lt_agents.description, lt_agents.status, lt_agents.knowledge_domain,
|
|
83
|
+
lt_agents.behaviors, lt_agents.goals, lt_agents.rules,
|
|
84
|
+
lt_agents.workflow_type, lt_agents.pipeline_id)
|
|
85
|
+
IS DISTINCT FROM
|
|
86
|
+
(EXCLUDED.description, EXCLUDED.status, EXCLUDED.knowledge_domain,
|
|
87
|
+
EXCLUDED.behaviors, EXCLUDED.goals, EXCLUDED.rules,
|
|
88
|
+
EXCLUDED.workflow_type, EXCLUDED.pipeline_id)
|
|
89
|
+
RETURNING (xmax = 0) AS inserted
|
|
90
|
+
`;
|
|
60
91
|
exports.KNOWLEDGE_COUNT = `
|
|
61
92
|
SELECT COUNT(*)::int AS count FROM lt_knowledge WHERE domain = $1
|
|
62
93
|
`;
|
|
@@ -4,4 +4,10 @@ export declare const INSERT_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptio
|
|
|
4
4
|
export declare const UPDATE_SUBSCRIPTION = "\n UPDATE lt_agent_subscriptions SET\n topic = COALESCE($2, topic),\n filter = COALESCE($3, filter),\n reaction_type = COALESCE($4, reaction_type),\n workflow_type = COALESCE($5, workflow_type),\n pipeline_id = COALESCE($6, pipeline_id),\n mcp_prompt = COALESCE($7, mcp_prompt),\n input_mapping = COALESCE($8, input_mapping),\n execute_as = COALESCE($9, execute_as),\n enabled = COALESCE($10, enabled),\n server_id = COALESCE($11, server_id),\n tool_name = COALESCE($12, tool_name)\n WHERE id = $1\n RETURNING *\n";
|
|
5
5
|
export declare const DELETE_SUBSCRIPTION = "\n DELETE FROM lt_agent_subscriptions WHERE id = $1\n";
|
|
6
6
|
export declare const SEED_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled, server_id, tool_name)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)\n ON CONFLICT (agent_id, topic) DO NOTHING\n";
|
|
7
|
+
/**
|
|
8
|
+
* Apply — code is source of truth for the reaction fields. `enabled` is left
|
|
9
|
+
* alone on update (an admin kill-switch stays honored); the IS DISTINCT FROM
|
|
10
|
+
* guard makes an unchanged declaration a zero-row no-op.
|
|
11
|
+
*/
|
|
12
|
+
export declare const APPLY_SUBSCRIPTION = "\n INSERT INTO lt_agent_subscriptions\n (agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,\n input_mapping, execute_as, enabled, server_id, tool_name)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)\n ON CONFLICT (agent_id, topic) DO UPDATE SET\n filter = EXCLUDED.filter,\n reaction_type = EXCLUDED.reaction_type,\n workflow_type = EXCLUDED.workflow_type,\n pipeline_id = EXCLUDED.pipeline_id,\n mcp_prompt = EXCLUDED.mcp_prompt,\n input_mapping = EXCLUDED.input_mapping,\n execute_as = EXCLUDED.execute_as,\n server_id = EXCLUDED.server_id,\n tool_name = EXCLUDED.tool_name\n WHERE (lt_agent_subscriptions.filter, lt_agent_subscriptions.reaction_type,\n lt_agent_subscriptions.workflow_type, lt_agent_subscriptions.pipeline_id,\n lt_agent_subscriptions.mcp_prompt, lt_agent_subscriptions.input_mapping,\n lt_agent_subscriptions.execute_as, lt_agent_subscriptions.server_id,\n lt_agent_subscriptions.tool_name)\n IS DISTINCT FROM\n (EXCLUDED.filter, EXCLUDED.reaction_type, EXCLUDED.workflow_type,\n EXCLUDED.pipeline_id, EXCLUDED.mcp_prompt, EXCLUDED.input_mapping,\n EXCLUDED.execute_as, EXCLUDED.server_id, EXCLUDED.tool_name)\n RETURNING (xmax = 0) AS inserted\n";
|
|
7
13
|
export declare const LIST_ACTIVE_SUBSCRIPTIONS = "\n SELECT s.*, a.id AS agent_name, a.user_id AS agent_user_id\n FROM lt_agent_subscriptions s\n JOIN lt_agents a ON s.agent_id = a.id\n WHERE s.enabled = true AND a.status = 'active'\n ORDER BY s.created_at\n";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LIST_ACTIVE_SUBSCRIPTIONS = exports.SEED_SUBSCRIPTION = exports.DELETE_SUBSCRIPTION = exports.UPDATE_SUBSCRIPTION = exports.INSERT_SUBSCRIPTION = exports.GET_SUBSCRIPTION = exports.LIST_SUBSCRIPTIONS = void 0;
|
|
3
|
+
exports.LIST_ACTIVE_SUBSCRIPTIONS = exports.APPLY_SUBSCRIPTION = exports.SEED_SUBSCRIPTION = exports.DELETE_SUBSCRIPTION = exports.UPDATE_SUBSCRIPTION = exports.INSERT_SUBSCRIPTION = exports.GET_SUBSCRIPTION = exports.LIST_SUBSCRIPTIONS = void 0;
|
|
4
4
|
exports.LIST_SUBSCRIPTIONS = `
|
|
5
5
|
SELECT * FROM lt_agent_subscriptions
|
|
6
6
|
WHERE agent_id = $1
|
|
@@ -42,6 +42,37 @@ exports.SEED_SUBSCRIPTION = `
|
|
|
42
42
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)
|
|
43
43
|
ON CONFLICT (agent_id, topic) DO NOTHING
|
|
44
44
|
`;
|
|
45
|
+
/**
|
|
46
|
+
* Apply — code is source of truth for the reaction fields. `enabled` is left
|
|
47
|
+
* alone on update (an admin kill-switch stays honored); the IS DISTINCT FROM
|
|
48
|
+
* guard makes an unchanged declaration a zero-row no-op.
|
|
49
|
+
*/
|
|
50
|
+
exports.APPLY_SUBSCRIPTION = `
|
|
51
|
+
INSERT INTO lt_agent_subscriptions
|
|
52
|
+
(agent_id, topic, filter, reaction_type, workflow_type, pipeline_id, mcp_prompt,
|
|
53
|
+
input_mapping, execute_as, enabled, server_id, tool_name)
|
|
54
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10, $11)
|
|
55
|
+
ON CONFLICT (agent_id, topic) DO UPDATE SET
|
|
56
|
+
filter = EXCLUDED.filter,
|
|
57
|
+
reaction_type = EXCLUDED.reaction_type,
|
|
58
|
+
workflow_type = EXCLUDED.workflow_type,
|
|
59
|
+
pipeline_id = EXCLUDED.pipeline_id,
|
|
60
|
+
mcp_prompt = EXCLUDED.mcp_prompt,
|
|
61
|
+
input_mapping = EXCLUDED.input_mapping,
|
|
62
|
+
execute_as = EXCLUDED.execute_as,
|
|
63
|
+
server_id = EXCLUDED.server_id,
|
|
64
|
+
tool_name = EXCLUDED.tool_name
|
|
65
|
+
WHERE (lt_agent_subscriptions.filter, lt_agent_subscriptions.reaction_type,
|
|
66
|
+
lt_agent_subscriptions.workflow_type, lt_agent_subscriptions.pipeline_id,
|
|
67
|
+
lt_agent_subscriptions.mcp_prompt, lt_agent_subscriptions.input_mapping,
|
|
68
|
+
lt_agent_subscriptions.execute_as, lt_agent_subscriptions.server_id,
|
|
69
|
+
lt_agent_subscriptions.tool_name)
|
|
70
|
+
IS DISTINCT FROM
|
|
71
|
+
(EXCLUDED.filter, EXCLUDED.reaction_type, EXCLUDED.workflow_type,
|
|
72
|
+
EXCLUDED.pipeline_id, EXCLUDED.mcp_prompt, EXCLUDED.input_mapping,
|
|
73
|
+
EXCLUDED.execute_as, EXCLUDED.server_id, EXCLUDED.tool_name)
|
|
74
|
+
RETURNING (xmax = 0) AS inserted
|
|
75
|
+
`;
|
|
45
76
|
exports.LIST_ACTIVE_SUBSCRIPTIONS = `
|
|
46
77
|
SELECT s.*, a.id AS agent_name, a.user_id AS agent_user_id
|
|
47
78
|
FROM lt_agent_subscriptions s
|
|
@@ -30,3 +30,9 @@ export declare function listActiveSubscriptions(): Promise<ActiveSubscription[]>
|
|
|
30
30
|
* Conflict on (agent_id, topic) — DB is source of truth after first boot.
|
|
31
31
|
*/
|
|
32
32
|
export declare function seedSubscription(agentId: string, data: Partial<AgentSubscription>): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Apply a subscription declaration at startup (code is source of truth).
|
|
35
|
+
* Reaction fields are written when they differ; `enabled` is honored as an
|
|
36
|
+
* admin kill-switch and never flipped on update.
|
|
37
|
+
*/
|
|
38
|
+
export declare function applySubscription(agentId: string, data: Partial<AgentSubscription>): Promise<'applied' | 'unchanged'>;
|
|
@@ -7,6 +7,7 @@ exports.updateSubscription = updateSubscription;
|
|
|
7
7
|
exports.deleteSubscription = deleteSubscription;
|
|
8
8
|
exports.listActiveSubscriptions = listActiveSubscriptions;
|
|
9
9
|
exports.seedSubscription = seedSubscription;
|
|
10
|
+
exports.applySubscription = applySubscription;
|
|
10
11
|
const db_1 = require("../../lib/db");
|
|
11
12
|
const subscription_sql_1 = require("./subscription-sql");
|
|
12
13
|
async function listSubscriptions(agentId) {
|
|
@@ -86,3 +87,25 @@ async function seedSubscription(agentId, data) {
|
|
|
86
87
|
]);
|
|
87
88
|
return (rowCount ?? 0) > 0;
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Apply a subscription declaration at startup (code is source of truth).
|
|
92
|
+
* Reaction fields are written when they differ; `enabled` is honored as an
|
|
93
|
+
* admin kill-switch and never flipped on update.
|
|
94
|
+
*/
|
|
95
|
+
async function applySubscription(agentId, data) {
|
|
96
|
+
const pool = (0, db_1.getPool)();
|
|
97
|
+
const { rowCount } = await pool.query(subscription_sql_1.APPLY_SUBSCRIPTION, [
|
|
98
|
+
agentId,
|
|
99
|
+
data.topic,
|
|
100
|
+
data.filter ? JSON.stringify(data.filter) : null,
|
|
101
|
+
data.reaction_type,
|
|
102
|
+
data.workflow_type ?? null,
|
|
103
|
+
data.pipeline_id ?? null,
|
|
104
|
+
data.mcp_prompt ?? null,
|
|
105
|
+
JSON.stringify(data.input_mapping ?? {}),
|
|
106
|
+
data.execute_as ?? null,
|
|
107
|
+
data.server_id ?? null,
|
|
108
|
+
data.tool_name ?? null,
|
|
109
|
+
]);
|
|
110
|
+
return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
|
|
111
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getWorkflowConfig, listWorkflowConfigs } from './read';
|
|
2
|
-
export { upsertWorkflowConfig, deleteWorkflowConfig } from './write';
|
|
2
|
+
export { upsertWorkflowConfig, deleteWorkflowConfig, applyWorkflowConfig } from './write';
|
|
3
3
|
export { loadAllConfigs } from './cache';
|
|
4
4
|
export { getProviderData } from './provider';
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getProviderData = exports.loadAllConfigs = exports.deleteWorkflowConfig = exports.upsertWorkflowConfig = exports.listWorkflowConfigs = exports.getWorkflowConfig = void 0;
|
|
3
|
+
exports.getProviderData = exports.loadAllConfigs = exports.applyWorkflowConfig = exports.deleteWorkflowConfig = exports.upsertWorkflowConfig = exports.listWorkflowConfigs = exports.getWorkflowConfig = void 0;
|
|
4
4
|
var read_1 = require("./read");
|
|
5
5
|
Object.defineProperty(exports, "getWorkflowConfig", { enumerable: true, get: function () { return read_1.getWorkflowConfig; } });
|
|
6
6
|
Object.defineProperty(exports, "listWorkflowConfigs", { enumerable: true, get: function () { return read_1.listWorkflowConfigs; } });
|
|
7
7
|
var write_1 = require("./write");
|
|
8
8
|
Object.defineProperty(exports, "upsertWorkflowConfig", { enumerable: true, get: function () { return write_1.upsertWorkflowConfig; } });
|
|
9
9
|
Object.defineProperty(exports, "deleteWorkflowConfig", { enumerable: true, get: function () { return write_1.deleteWorkflowConfig; } });
|
|
10
|
+
Object.defineProperty(exports, "applyWorkflowConfig", { enumerable: true, get: function () { return write_1.applyWorkflowConfig; } });
|
|
10
11
|
var cache_1 = require("./cache");
|
|
11
12
|
Object.defineProperty(exports, "loadAllConfigs", { enumerable: true, get: function () { return cache_1.loadAllConfigs; } });
|
|
12
13
|
var provider_1 = require("./provider");
|
|
@@ -9,3 +9,13 @@ export declare function deleteWorkflowConfig(workflowType: string): Promise<bool
|
|
|
9
9
|
* but do not overwrite. Returns true if inserted, false if already existed.
|
|
10
10
|
*/
|
|
11
11
|
export declare function seedWorkflowConfig(config: LTWorkflowConfig): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Apply a workflow config at startup (code is source of truth).
|
|
14
|
+
*
|
|
15
|
+
* The declared config is diffed against the stored row — jsonb fields as
|
|
16
|
+
* parsed values, role lists order-insensitively — and written through the
|
|
17
|
+
* same full-replace transaction the admin surface uses only when something
|
|
18
|
+
* actually differs. `certified` is explicit-only on this path: an omitted
|
|
19
|
+
* flag registers the workflow as NOT certified.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyWorkflowConfig(config: LTWorkflowConfig): Promise<'applied' | 'unchanged'>;
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.upsertWorkflowConfig = upsertWorkflowConfig;
|
|
4
4
|
exports.deleteWorkflowConfig = deleteWorkflowConfig;
|
|
5
5
|
exports.seedWorkflowConfig = seedWorkflowConfig;
|
|
6
|
+
exports.applyWorkflowConfig = applyWorkflowConfig;
|
|
7
|
+
const node_util_1 = require("node:util");
|
|
6
8
|
const db_1 = require("../../lib/db");
|
|
7
9
|
const read_1 = require("./read");
|
|
8
10
|
const logger_1 = require("../../lib/logger");
|
|
@@ -16,7 +18,13 @@ function resolveCertified(config) {
|
|
|
16
18
|
return (config.certified ??
|
|
17
19
|
((config.roles?.length ?? 0) > 0 || (config.consumes?.length ?? 0) > 0));
|
|
18
20
|
}
|
|
19
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Full replace of one workflow config in a single transaction: FK role
|
|
23
|
+
* ensures, the workflow row upsert, and replace semantics for the roles and
|
|
24
|
+
* invocation-roles side tables. Both the admin upsert and the startup apply
|
|
25
|
+
* write through here — they differ only in how `certified` resolves.
|
|
26
|
+
*/
|
|
27
|
+
async function replaceWorkflowConfig(config, certified) {
|
|
20
28
|
const pool = (0, db_1.getPool)();
|
|
21
29
|
const client = await pool.connect();
|
|
22
30
|
try {
|
|
@@ -43,7 +51,7 @@ async function upsertWorkflowConfig(config) {
|
|
|
43
51
|
config.cron_schedule ?? null,
|
|
44
52
|
config.tool_tags || [],
|
|
45
53
|
config.execute_as ?? null,
|
|
46
|
-
|
|
54
|
+
certified,
|
|
47
55
|
]);
|
|
48
56
|
// Replace roles
|
|
49
57
|
await client.query(sql_1.DELETE_CONFIG_ROLES, [config.workflow_type]);
|
|
@@ -64,6 +72,9 @@ async function upsertWorkflowConfig(config) {
|
|
|
64
72
|
finally {
|
|
65
73
|
client.release();
|
|
66
74
|
}
|
|
75
|
+
}
|
|
76
|
+
async function upsertWorkflowConfig(config) {
|
|
77
|
+
await replaceWorkflowConfig(config, resolveCertified(config));
|
|
67
78
|
return (await (0, read_1.getWorkflowConfig)(config.workflow_type));
|
|
68
79
|
}
|
|
69
80
|
async function deleteWorkflowConfig(workflowType) {
|
|
@@ -136,3 +147,39 @@ async function seedWorkflowConfig(config) {
|
|
|
136
147
|
}
|
|
137
148
|
return inserted;
|
|
138
149
|
}
|
|
150
|
+
/** Order-insensitive comparison for role lists and other unordered arrays. */
|
|
151
|
+
function sortedEqual(a, b) {
|
|
152
|
+
return (0, node_util_1.isDeepStrictEqual)([...a].sort(), [...b].sort());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Apply a workflow config at startup (code is source of truth).
|
|
156
|
+
*
|
|
157
|
+
* The declared config is diffed against the stored row — jsonb fields as
|
|
158
|
+
* parsed values, role lists order-insensitively — and written through the
|
|
159
|
+
* same full-replace transaction the admin surface uses only when something
|
|
160
|
+
* actually differs. `certified` is explicit-only on this path: an omitted
|
|
161
|
+
* flag registers the workflow as NOT certified.
|
|
162
|
+
*/
|
|
163
|
+
async function applyWorkflowConfig(config) {
|
|
164
|
+
const certified = config.certified ?? false;
|
|
165
|
+
const existing = await (0, read_1.getWorkflowConfig)(config.workflow_type);
|
|
166
|
+
if (existing) {
|
|
167
|
+
const unchanged = existing.invocable === config.invocable &&
|
|
168
|
+
existing.task_queue === config.task_queue &&
|
|
169
|
+
existing.default_role === config.default_role &&
|
|
170
|
+
(existing.description ?? null) === (config.description ?? null) &&
|
|
171
|
+
existing.certified === certified &&
|
|
172
|
+
(existing.cron_schedule ?? null) === (config.cron_schedule ?? null) &&
|
|
173
|
+
(existing.execute_as ?? null) === (config.execute_as ?? null) &&
|
|
174
|
+
sortedEqual(existing.consumes ?? [], config.consumes ?? []) &&
|
|
175
|
+
sortedEqual(existing.tool_tags ?? [], config.tool_tags ?? []) &&
|
|
176
|
+
sortedEqual(existing.roles ?? [], config.roles ?? []) &&
|
|
177
|
+
sortedEqual(existing.invocation_roles ?? [], config.invocation_roles ?? []) &&
|
|
178
|
+
(0, node_util_1.isDeepStrictEqual)(existing.envelope_schema ?? null, config.envelope_schema ?? null) &&
|
|
179
|
+
(0, node_util_1.isDeepStrictEqual)(existing.resolver_schema ?? null, config.resolver_schema ?? null);
|
|
180
|
+
if (unchanged)
|
|
181
|
+
return 'unchanged';
|
|
182
|
+
}
|
|
183
|
+
await replaceWorkflowConfig(config, certified);
|
|
184
|
+
return 'applied';
|
|
185
|
+
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Seed the domain dictionary from a host-declared JSON file
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Seed the domain dictionary from a host-declared JSON file.
|
|
3
|
+
*
|
|
4
|
+
* Default (db-owned): the same insert-if-absent + drift-log contract as
|
|
5
|
+
* seedWorkflowConfig/seedMcpServer — the DB row is runtime truth, an existing
|
|
6
|
+
* row is never overwritten, and a name/version mismatch against the file logs
|
|
7
|
+
* one drift warning.
|
|
8
|
+
*
|
|
9
|
+
* With `apply` (code-owned): the file is compared against the stored document
|
|
10
|
+
* as parsed values; a changed document is written through the same upsert the
|
|
11
|
+
* PUT path uses, advancing the row's version counter exactly once. An
|
|
12
|
+
* identical document is a no-op.
|
|
6
13
|
*
|
|
7
14
|
* WARN-ONLY validation: hosts commonly seed roles after long-tail boots, so
|
|
8
15
|
* unknown references log warnings here (the PUT path enforces them hard).
|
|
9
16
|
* Never throws — a missing or malformed file must not brick boot.
|
|
10
17
|
*/
|
|
11
|
-
export declare function seedDomainDictionary(dictionaryPath: string): Promise<void>;
|
|
18
|
+
export declare function seedDomainDictionary(dictionaryPath: string, apply?: boolean): Promise<void>;
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.seedDomainDictionary = seedDomainDictionary;
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const node_util_1 = require("node:util");
|
|
9
10
|
const db_1 = require("../../lib/db");
|
|
10
11
|
const logger_1 = require("../../lib/logger");
|
|
11
12
|
const validate_1 = require("./validate");
|
|
@@ -13,16 +14,23 @@ const write_1 = require("./write");
|
|
|
13
14
|
const read_1 = require("./read");
|
|
14
15
|
const sql_1 = require("./sql");
|
|
15
16
|
/**
|
|
16
|
-
* Seed the domain dictionary from a host-declared JSON file
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Seed the domain dictionary from a host-declared JSON file.
|
|
18
|
+
*
|
|
19
|
+
* Default (db-owned): the same insert-if-absent + drift-log contract as
|
|
20
|
+
* seedWorkflowConfig/seedMcpServer — the DB row is runtime truth, an existing
|
|
21
|
+
* row is never overwritten, and a name/version mismatch against the file logs
|
|
22
|
+
* one drift warning.
|
|
23
|
+
*
|
|
24
|
+
* With `apply` (code-owned): the file is compared against the stored document
|
|
25
|
+
* as parsed values; a changed document is written through the same upsert the
|
|
26
|
+
* PUT path uses, advancing the row's version counter exactly once. An
|
|
27
|
+
* identical document is a no-op.
|
|
20
28
|
*
|
|
21
29
|
* WARN-ONLY validation: hosts commonly seed roles after long-tail boots, so
|
|
22
30
|
* unknown references log warnings here (the PUT path enforces them hard).
|
|
23
31
|
* Never throws — a missing or malformed file must not brick boot.
|
|
24
32
|
*/
|
|
25
|
-
async function seedDomainDictionary(dictionaryPath) {
|
|
33
|
+
async function seedDomainDictionary(dictionaryPath, apply = false) {
|
|
26
34
|
const resolved = path_1.default.isAbsolute(dictionaryPath)
|
|
27
35
|
? dictionaryPath
|
|
28
36
|
: path_1.default.join(process.cwd(), dictionaryPath);
|
|
@@ -51,9 +59,20 @@ async function seedDomainDictionary(dictionaryPath) {
|
|
|
51
59
|
`(${derived.terms?.length ?? 0} terms, ${derived.runbooks?.length ?? 0} runbooks)`);
|
|
52
60
|
return;
|
|
53
61
|
}
|
|
54
|
-
// Row already existed — drift check on name/version only (no deep diff).
|
|
55
62
|
const existing = await (0, db_1.getPool)().query(sql_1.GET_DOMAIN);
|
|
56
63
|
const doc = existing.rows[0]?.doc;
|
|
64
|
+
if (apply) {
|
|
65
|
+
// Code-owned: compare parsed documents (jsonb loses key order) and
|
|
66
|
+
// write only on a real change — one version bump per changed file.
|
|
67
|
+
if (doc && (0, node_util_1.isDeepStrictEqual)(doc, derived))
|
|
68
|
+
return;
|
|
69
|
+
await (0, db_1.getPool)().query(sql_1.UPSERT_DOMAIN, [JSON.stringify(derived), null]);
|
|
70
|
+
read_1.domainCache.invalidate();
|
|
71
|
+
logger_1.loggerRegistry.info(`[lt-domain] dictionary applied: ${derived.name} v${derived.version} ` +
|
|
72
|
+
`(${derived.terms?.length ?? 0} terms, ${derived.runbooks?.length ?? 0} runbooks)`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Row already existed — drift check on name/version only (no deep diff).
|
|
57
76
|
if (doc && (doc.name !== dictionary.name || doc.version !== dictionary.version)) {
|
|
58
77
|
logger_1.loggerRegistry.warn(`[lt-domain] dictionary drift: DB holds "${doc.name}" v${doc.version}, ` +
|
|
59
78
|
`file declares "${dictionary.name}" v${dictionary.version} — DB is runtime truth`);
|
|
@@ -38,6 +38,22 @@ export declare function seedMcpServer(input: {
|
|
|
38
38
|
credentialProviders?: string[];
|
|
39
39
|
toolManifest?: any[];
|
|
40
40
|
}): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Apply an MCP server declaration at startup (code is source of truth).
|
|
43
|
+
* Config fields — description, tags, category, compile hints, credential
|
|
44
|
+
* providers — are written when they differ; runtime state (tool manifest,
|
|
45
|
+
* connection status) is never touched. Returns 'applied' when the row was
|
|
46
|
+
* inserted or updated, 'unchanged' when the declaration already matches.
|
|
47
|
+
*/
|
|
48
|
+
export declare function applyMcpServer(input: {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
tags?: string[];
|
|
52
|
+
category?: string;
|
|
53
|
+
compileHints?: string;
|
|
54
|
+
credentialProviders?: string[];
|
|
55
|
+
toolManifest?: any[];
|
|
56
|
+
}): Promise<'applied' | 'unchanged'>;
|
|
41
57
|
/**
|
|
42
58
|
* Remove builtin MCP servers that are no longer declared in factory config.
|
|
43
59
|
*/
|
package/build/services/mcp/db.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.listMcpServers = listMcpServers;
|
|
|
10
10
|
exports.getAutoConnectServers = getAutoConnectServers;
|
|
11
11
|
exports.findServersByTags = findServersByTags;
|
|
12
12
|
exports.seedMcpServer = seedMcpServer;
|
|
13
|
+
exports.applyMcpServer = applyMcpServer;
|
|
13
14
|
exports.cleanStaleBuiltinServers = cleanStaleBuiltinServers;
|
|
14
15
|
const db_1 = require("../../lib/db");
|
|
15
16
|
const logger_1 = require("../../lib/logger");
|
|
@@ -190,6 +191,29 @@ async function seedMcpServer(input) {
|
|
|
190
191
|
}
|
|
191
192
|
return inserted;
|
|
192
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Apply an MCP server declaration at startup (code is source of truth).
|
|
196
|
+
* Config fields — description, tags, category, compile hints, credential
|
|
197
|
+
* providers — are written when they differ; runtime state (tool manifest,
|
|
198
|
+
* connection status) is never touched. Returns 'applied' when the row was
|
|
199
|
+
* inserted or updated, 'unchanged' when the declaration already matches.
|
|
200
|
+
*/
|
|
201
|
+
async function applyMcpServer(input) {
|
|
202
|
+
const pool = (0, db_1.getPool)();
|
|
203
|
+
const { rowCount } = await pool.query(sql_1.APPLY_MCP_SERVER, [
|
|
204
|
+
input.name,
|
|
205
|
+
input.description || null,
|
|
206
|
+
'stdio',
|
|
207
|
+
JSON.stringify({ builtin: true, process: 'in-memory' }),
|
|
208
|
+
JSON.stringify(input.toolManifest || []),
|
|
209
|
+
JSON.stringify({ builtin: true }),
|
|
210
|
+
input.tags || [],
|
|
211
|
+
input.compileHints || null,
|
|
212
|
+
input.credentialProviders || [],
|
|
213
|
+
input.category || null,
|
|
214
|
+
]);
|
|
215
|
+
return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
|
|
216
|
+
}
|
|
193
217
|
/**
|
|
194
218
|
* Remove builtin MCP servers that are no longer declared in factory config.
|
|
195
219
|
*/
|
|
@@ -19,3 +19,11 @@ export declare const DELETE_STALE_BUILTIN_SERVERS = "\n DELETE FROM lt_mcp_serv
|
|
|
19
19
|
export declare const UPSERT_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, NOW())\n ON CONFLICT (name) DO UPDATE SET\n tool_manifest = EXCLUDED.tool_manifest,\n metadata = EXCLUDED.metadata,\n description = EXCLUDED.description,\n tags = EXCLUDED.tags,\n compile_hints = EXCLUDED.compile_hints,\n credential_providers = EXCLUDED.credential_providers,\n status = 'connected',\n last_connected_at = NOW()";
|
|
20
20
|
/** Seed — insert-if-absent. DB is source of truth after first boot. */
|
|
21
21
|
export declare const SEED_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())\n ON CONFLICT (name) DO NOTHING";
|
|
22
|
+
/**
|
|
23
|
+
* Apply — code is source of truth for the CONFIG fields only. On conflict the
|
|
24
|
+
* update rewrites description/tags/category/compile_hints/credential_providers
|
|
25
|
+
* and leaves runtime state (tool_manifest, status, last_connected_at,
|
|
26
|
+
* transport_config) untouched; the IS DISTINCT FROM guard makes an unchanged
|
|
27
|
+
* declaration a zero-row no-op. `(xmax = 0)` distinguishes insert from update.
|
|
28
|
+
*/
|
|
29
|
+
export declare const APPLY_MCP_SERVER = "\n INSERT INTO lt_mcp_servers\n (name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)\n VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())\n ON CONFLICT (name) DO UPDATE SET\n description = EXCLUDED.description,\n tags = EXCLUDED.tags,\n category = EXCLUDED.category,\n compile_hints = EXCLUDED.compile_hints,\n credential_providers = EXCLUDED.credential_providers\n WHERE (lt_mcp_servers.description, lt_mcp_servers.tags, lt_mcp_servers.category,\n lt_mcp_servers.compile_hints, lt_mcp_servers.credential_providers)\n IS DISTINCT FROM\n (EXCLUDED.description, EXCLUDED.tags, EXCLUDED.category,\n EXCLUDED.compile_hints, EXCLUDED.credential_providers)\n RETURNING (xmax = 0) AS inserted";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ─── MCP server CRUD ────────────────────────────────────────────────────────
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.SEED_MCP_SERVER = exports.UPSERT_MCP_SERVER = exports.DELETE_STALE_BUILTIN_SERVERS = exports.HEALTH_DURABLE_WORKFLOWS = exports.HEALTH_WORKFLOW_CONFIGS = exports.HEALTH_COMPILED_WORKFLOWS = exports.HEALTH_MCP_SERVER_LIST = exports.HEALTH_MCP_SERVERS = exports.HEALTH_RECENT_ACTIVITY = exports.HEALTH_ACTIVE_WORKFLOW_TYPES = exports.HEALTH_ESCALATION_COUNTS = exports.HEALTH_TASK_COUNTS = exports.GET_AUTO_CONNECT_SERVERS = exports.UPDATE_STATUS = exports.UPDATE_STATUS_CONNECTED = exports.DELETE_MCP_SERVER = exports.GET_MCP_SERVER_BY_NAME = exports.GET_MCP_SERVER = exports.CREATE_MCP_SERVER = void 0;
|
|
4
|
+
exports.APPLY_MCP_SERVER = exports.SEED_MCP_SERVER = exports.UPSERT_MCP_SERVER = exports.DELETE_STALE_BUILTIN_SERVERS = exports.HEALTH_DURABLE_WORKFLOWS = exports.HEALTH_WORKFLOW_CONFIGS = exports.HEALTH_COMPILED_WORKFLOWS = exports.HEALTH_MCP_SERVER_LIST = exports.HEALTH_MCP_SERVERS = exports.HEALTH_RECENT_ACTIVITY = exports.HEALTH_ACTIVE_WORKFLOW_TYPES = exports.HEALTH_ESCALATION_COUNTS = exports.HEALTH_TASK_COUNTS = exports.GET_AUTO_CONNECT_SERVERS = exports.UPDATE_STATUS = exports.UPDATE_STATUS_CONNECTED = exports.DELETE_MCP_SERVER = exports.GET_MCP_SERVER_BY_NAME = exports.GET_MCP_SERVER = exports.CREATE_MCP_SERVER = void 0;
|
|
5
5
|
exports.CREATE_MCP_SERVER = `
|
|
6
6
|
INSERT INTO lt_mcp_servers
|
|
7
7
|
(name, description, transport_type, transport_config, auto_connect, metadata, tags, compile_hints, credential_providers)
|
|
@@ -97,3 +97,26 @@ exports.SEED_MCP_SERVER = `
|
|
|
97
97
|
(name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)
|
|
98
98
|
VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())
|
|
99
99
|
ON CONFLICT (name) DO NOTHING`;
|
|
100
|
+
/**
|
|
101
|
+
* Apply — code is source of truth for the CONFIG fields only. On conflict the
|
|
102
|
+
* update rewrites description/tags/category/compile_hints/credential_providers
|
|
103
|
+
* and leaves runtime state (tool_manifest, status, last_connected_at,
|
|
104
|
+
* transport_config) untouched; the IS DISTINCT FROM guard makes an unchanged
|
|
105
|
+
* declaration a zero-row no-op. `(xmax = 0)` distinguishes insert from update.
|
|
106
|
+
*/
|
|
107
|
+
exports.APPLY_MCP_SERVER = `
|
|
108
|
+
INSERT INTO lt_mcp_servers
|
|
109
|
+
(name, description, transport_type, transport_config, auto_connect, status, tool_manifest, metadata, tags, compile_hints, credential_providers, category, last_connected_at)
|
|
110
|
+
VALUES ($1, $2, $3, $4, true, 'connected', $5, $6, $7, $8, $9, $10, NOW())
|
|
111
|
+
ON CONFLICT (name) DO UPDATE SET
|
|
112
|
+
description = EXCLUDED.description,
|
|
113
|
+
tags = EXCLUDED.tags,
|
|
114
|
+
category = EXCLUDED.category,
|
|
115
|
+
compile_hints = EXCLUDED.compile_hints,
|
|
116
|
+
credential_providers = EXCLUDED.credential_providers
|
|
117
|
+
WHERE (lt_mcp_servers.description, lt_mcp_servers.tags, lt_mcp_servers.category,
|
|
118
|
+
lt_mcp_servers.compile_hints, lt_mcp_servers.credential_providers)
|
|
119
|
+
IS DISTINCT FROM
|
|
120
|
+
(EXCLUDED.description, EXCLUDED.tags, EXCLUDED.category,
|
|
121
|
+
EXCLUDED.compile_hints, EXCLUDED.credential_providers)
|
|
122
|
+
RETURNING (xmax = 0) AS inserted`;
|