@hotmeshio/long-tail 0.12.1 → 0.13.1
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/auth-sso.d.ts +6 -3
- package/build/api/auth-sso.js +6 -3
- package/build/api/escalations/helpers.js +4 -2
- package/build/api/settings.js +3 -0
- package/build/modules/auth.js +9 -3
- package/build/routes/auth-sso.js +6 -1
- 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/scan-code/index.d.ts +1 -1
- package/build/services/scan-code/index.js +3 -1
- package/build/services/scan-code/sql.d.ts +7 -0
- package/build/services/scan-code/sql.js +55 -1
- package/build/services/scan-code/write.d.ts +8 -0
- package/build/services/scan-code/write.js +23 -1
- 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 +222 -33
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/auth.d.ts +44 -4
- package/build/types/index.d.ts +1 -1
- package/build/types/startup.d.ts +160 -4
- package/dashboard/dist/assets/{AdminDashboard-DpTZG5EL.js → AdminDashboard-D2unnS2b.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DpTZG5EL.js.map → AdminDashboard-D2unnS2b.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-DVTL0NvC.js → AgentConfigPage-CBkf403g.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-DVTL0NvC.js.map → AgentConfigPage-CBkf403g.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-DOLKNPJl.js → AgentDetailPage-CAIU3yzo.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-DOLKNPJl.js.map → AgentDetailPage-CAIU3yzo.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DiOZu6Xb.js → AgentsPage-qP9fWMyT.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DiOZu6Xb.js.map → AgentsPage-qP9fWMyT.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-CY5lfx27.js → AvailableEscalationsPage-DvWaiafI.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-CY5lfx27.js.map → AvailableEscalationsPage-DvWaiafI.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-ButjLJr2.js → BotPicker-BN-MKITV.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-ButjLJr2.js.map → BotPicker-BN-MKITV.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-CW_r2OlX.js → CapabilitiesPage-CJfmWokN.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-CW_r2OlX.js.map → CapabilitiesPage-CJfmWokN.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BOGRyCfm.js → CollapsibleSection-BvMHlHyt.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BOGRyCfm.js.map → CollapsibleSection-BvMHlHyt.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-UcHYZSg1.js → CountdownTimer-By4rbMDN.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-UcHYZSg1.js.map → CountdownTimer-By4rbMDN.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-A7OFYVsX.js → CredentialsPage-2TvvRwGJ.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-A7OFYVsX.js.map → CredentialsPage-2TvvRwGJ.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Dve2Udsm.js → CronLabel-HxmsDSnV.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Dve2Udsm.js.map → CronLabel-HxmsDSnV.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-BoPrA-Em.js → CustomDurationPicker-8Ao-1pKA.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-BoPrA-Em.js.map → CustomDurationPicker-8Ao-1pKA.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-B114P5mb.js → ElapsedCell-BkRu9Xpd.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-B114P5mb.js.map → ElapsedCell-BkRu9Xpd.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-BqDWyOa9.js → EntityTimelinePanel--E6hLMCM.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-BqDWyOa9.js.map → EntityTimelinePanel--E6hLMCM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DyyTyghx.js → EscalationListSchemaPage-CdFtqEEX.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-DyyTyghx.js.map → EscalationListSchemaPage-CdFtqEEX.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DLQG6EXQ.js → EscalationSchemaPage-BsjS2axz.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-DLQG6EXQ.js.map → EscalationSchemaPage-BsjS2axz.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-RrbkkEU0.js → EscalationsOverview-FL-xteVc.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-RrbkkEU0.js.map → EscalationsOverview-FL-xteVc.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DOxubt7O.js → EventTable-BOcgZ78i.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DOxubt7O.js.map → EventTable-BOcgZ78i.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-y659Gc3X.js → FilterBar-DfCiCmm-.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-y659Gc3X.js.map → FilterBar-DfCiCmm-.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-oHLgSAl6.js → GraphInvokePage-DfVeiN-8.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-oHLgSAl6.js.map → GraphInvokePage-DfVeiN-8.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-C9FUpD7x.js → HomePage-C2IhF9WB.js} +2 -2
- package/dashboard/dist/assets/{HomePage-C9FUpD7x.js.map → HomePage-C2IhF9WB.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-DfpSgWYU.js → ListToolbar-DA0PTOl5.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-DfpSgWYU.js.map → ListToolbar-DA0PTOl5.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-6Ubpr9QS.js → McpOverview-DstPch5M.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-6Ubpr9QS.js.map → McpOverview-DstPch5M.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-DFt-vQEp.js → McpQueryDetailPage-Csv0PKE0.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-DFt-vQEp.js.map → McpQueryDetailPage-Csv0PKE0.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DQiG0AE3.js → McpQueryPage-DxmqCkly.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DQiG0AE3.js.map → McpQueryPage-DxmqCkly.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-BgsSegyP.js → McpRunDetailPage-CcJOlp_B.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-BgsSegyP.js.map → McpRunDetailPage-CcJOlp_B.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-tCMxspqS.js → McpRunsPage-BZCR043j.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-tCMxspqS.js.map → McpRunsPage-BZCR043j.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DUaRmEPa.js → OperationsPage-DMsPXITh.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-DUaRmEPa.js.map → OperationsPage-DMsPXITh.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-CayyjMcf.js → OperatorDashboard-DSloftQ5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-CayyjMcf.js.map → OperatorDashboard-DSloftQ5.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-DBcxfdbN.js → PersonaDetailPage-jDVRCLbU.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-DBcxfdbN.js.map → PersonaDetailPage-jDVRCLbU.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DPq0HQAB.js → PersonasPage-DnDDwXoy.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DPq0HQAB.js.map → PersonasPage-DnDDwXoy.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-QQZNNNMw.js → ProcessDetailPage-CfAUU6q2.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-QQZNNNMw.js.map → ProcessDetailPage-CfAUU6q2.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-UKQMJ4Te.js → ProcessesListPage-CnAXzaVv.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-UKQMJ4Te.js.map → ProcessesListPage-CnAXzaVv.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-DT-3sSRD.js → RoleDetailPage-Dg1p6Qz_.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-DT-3sSRD.js.map → RoleDetailPage-Dg1p6Qz_.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DZg4niqL.js → RolesPage-DeRVQux8.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DZg4niqL.js.map → RolesPage-DeRVQux8.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-DkcNR7L6.js → RunAsSelector-BFNqQGuG.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-DkcNR7L6.js.map → RunAsSelector-BFNqQGuG.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-U-alpwWF.js → ScanCodesPage-D0GOdk5m.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-U-alpwWF.js.map → ScanCodesPage-D0GOdk5m.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-lXwlcraS.js → ScanSchemeDetailPage-vFqoe_P4.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-lXwlcraS.js.map → ScanSchemeDetailPage-vFqoe_P4.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-DYMiTp-v.js → ScanStationPage-DH1ynTX9.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-DYMiTp-v.js.map → ScanStationPage-DH1ynTX9.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-D896Wquq.js → StickyPagination-B99hVu95.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-D896Wquq.js.map → StickyPagination-B99hVu95.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-DIh5qEGJ.js → StreamMessageDetail-DcDGISrv.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-DIh5qEGJ.js.map → StreamMessageDetail-DcDGISrv.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B8SucVj5.js → SwimlaneTimeline-BP3mSQAg.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B8SucVj5.js.map → SwimlaneTimeline-BP3mSQAg.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Di-z_ZE2.js → TaskDetailPage-_XWLJzt-.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Di-z_ZE2.js.map → TaskDetailPage-_XWLJzt-.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-ClHGEdin.js → TasksListPage-iGriKiO2.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-ClHGEdin.js.map → TasksListPage-iGriKiO2.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BSDHd9Xo.js → TimeAgo-BO33VeFl.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BSDHd9Xo.js.map → TimeAgo-BO33VeFl.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-WQL3FxWl.js → TimestampCell-KAjX7w35.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-WQL3FxWl.js.map → TimestampCell-KAjX7w35.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-IVIkqZTi.js → ToolTestPanel-BchG2yC6.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-IVIkqZTi.js.map → ToolTestPanel-BchG2yC6.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-BOasQo68.js → TopicDetailPage-BaK8H0o1.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-BOasQo68.js.map → TopicDetailPage-BaK8H0o1.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-DV_orf_V.js → TopicsPage-DEyvm669.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-DV_orf_V.js.map → TopicsPage-DEyvm669.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-rshjKBtm.js → UserName-BV6SKI9P.js} +2 -2
- package/dashboard/dist/assets/{UserName-rshjKBtm.js.map → UserName-BV6SKI9P.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-BpNGLwbK.js → WorkflowExecutionPage-1sKoEFNC.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-BpNGLwbK.js.map → WorkflowExecutionPage-1sKoEFNC.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-BAXt8gv_.js → WorkflowsDashboard-YTHDZZOD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-BAXt8gv_.js.map → WorkflowsDashboard-YTHDZZOD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-DvOyzL6y.js → WorkflowsOverview-ucXPLTtm.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-DvOyzL6y.js.map → WorkflowsOverview-ucXPLTtm.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CraijGy6.js → YamlWorkflowDetailPage-C_RTZKqZ.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CraijGy6.js.map → YamlWorkflowDetailPage-C_RTZKqZ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CNz3ptmj.js → YamlWorkflowsPage-Usid3w2W.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CNz3ptmj.js.map → YamlWorkflowsPage-Usid3w2W.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BswSJR-t.js → agents-BTDsRK8e.js} +2 -2
- package/dashboard/dist/assets/{agents-BswSJR-t.js.map → agents-BTDsRK8e.js.map} +1 -1
- package/dashboard/dist/assets/{bots-VzlLx_GQ.js → bots-DxLrfdfr.js} +2 -2
- package/dashboard/dist/assets/{bots-VzlLx_GQ.js.map → bots-DxLrfdfr.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-B0bNlTTA.js → capabilities-DbTmeW-S.js} +2 -2
- package/dashboard/dist/assets/{capabilities-B0bNlTTA.js.map → capabilities-DbTmeW-S.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DBESTVZS.js → controlplane-CEBntAL4.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DBESTVZS.js.map → controlplane-CEBntAL4.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CoqsCdbP.js → escalation-columns-Carqdwoh.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CoqsCdbP.js.map → escalation-columns-Carqdwoh.js.map} +1 -1
- package/dashboard/dist/assets/{index-DUfdCp8e.js → index-B2hz0pUh.js} +2 -2
- package/dashboard/dist/assets/{index-DUfdCp8e.js.map → index-B2hz0pUh.js.map} +1 -1
- package/dashboard/dist/assets/{index-DJS-hvDt.js → index-B9m7fA3M.js} +2 -2
- package/dashboard/dist/assets/{index-DJS-hvDt.js.map → index-B9m7fA3M.js.map} +1 -1
- package/dashboard/dist/assets/{index-C_lA7ghl.js → index-BhapT-Vl.js} +2 -2
- package/dashboard/dist/assets/{index-C_lA7ghl.js.map → index-BhapT-Vl.js.map} +1 -1
- package/dashboard/dist/assets/{index-DsDFZzqr.js → index-Bqm4zu46.js} +2 -2
- package/dashboard/dist/assets/{index-DsDFZzqr.js.map → index-Bqm4zu46.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cd7jZylO.js → index-C0hSttF5.js} +2 -2
- package/dashboard/dist/assets/{index-Cd7jZylO.js.map → index-C0hSttF5.js.map} +1 -1
- package/dashboard/dist/assets/{index-ByUjwu37.js → index-CDkg6iOE.js} +2 -2
- package/dashboard/dist/assets/{index-ByUjwu37.js.map → index-CDkg6iOE.js.map} +1 -1
- package/dashboard/dist/assets/{index-Ci4lxPwS.js → index-CVBBkW8V.js} +2 -2
- package/dashboard/dist/assets/{index-Ci4lxPwS.js.map → index-CVBBkW8V.js.map} +1 -1
- package/dashboard/dist/assets/{index-DYDcjn-b.js → index-CgIBjZta.js} +2 -2
- package/dashboard/dist/assets/{index-DYDcjn-b.js.map → index-CgIBjZta.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cqrp5B5S.js → index-DBXm49S6.js} +25 -25
- package/dashboard/dist/assets/index-DBXm49S6.js.map +1 -0
- package/dashboard/dist/assets/{index-BBXmIWKx.js → index-De8iV1y2.js} +2 -2
- package/dashboard/dist/assets/{index-BBXmIWKx.js.map → index-De8iV1y2.js.map} +1 -1
- package/dashboard/dist/assets/{index-D8ljRGIb.js → index-DsgjFRvA.js} +2 -2
- package/dashboard/dist/assets/{index-D8ljRGIb.js.map → index-DsgjFRvA.js.map} +1 -1
- package/dashboard/dist/assets/{index-BLzwfbZV.js → index-kes8V4Xw.js} +2 -2
- package/dashboard/dist/assets/{index-BLzwfbZV.js.map → index-kes8V4Xw.js.map} +1 -1
- package/dashboard/dist/assets/{index-CALocCAr.js → index-nwLh3CK2.js} +2 -2
- package/dashboard/dist/assets/{index-CALocCAr.js.map → index-nwLh3CK2.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DB2DgDa_.js → knowledge-oFYAanUp.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DB2DgDa_.js.map → knowledge-oFYAanUp.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-D72yCeuf.js → mcp-C9Kw4Ow8.js} +2 -2
- package/dashboard/dist/assets/{mcp-D72yCeuf.js.map → mcp-C9Kw4Ow8.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Cyyc_0E8.js → mcp-query-BwzpZ91Z.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Cyyc_0E8.js.map → mcp-query-BwzpZ91Z.js.map} +1 -1
- package/dashboard/dist/assets/{personas-xMDV7yXb.js → personas-D5ehmtRb.js} +2 -2
- package/dashboard/dist/assets/{personas-xMDV7yXb.js.map → personas-D5ehmtRb.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-mlxfmi6m.js → pipelines-xgPKGEdD.js} +2 -2
- package/dashboard/dist/assets/{pipelines-mlxfmi6m.js.map → pipelines-xgPKGEdD.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CxgOp_9H.js → tasks-CLyrl-MU.js} +2 -2
- package/dashboard/dist/assets/{tasks-CxgOp_9H.js.map → tasks-CLyrl-MU.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CFb_L0Vs.js → topics-B_gO7CQ0.js} +2 -2
- package/dashboard/dist/assets/{topics-CFb_L0Vs.js.map → topics-B_gO7CQ0.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-nC5kH-QW.js → useEventHooks-BdWYm63U.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-nC5kH-QW.js.map → useEventHooks-BdWYm63U.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DQeDgRFR.js → useNamespace-C238M4Qn.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DQeDgRFR.js.map → useNamespace-C238M4Qn.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BuGC3oBE.js → useYamlActivityEvents-B2ryEK4S.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BuGC3oBE.js.map → useYamlActivityEvents-B2ryEK4S.js.map} +1 -1
- package/dashboard/dist/assets/{users-BZUTtM_6.js → users-BFaTe6Mt.js} +2 -2
- package/dashboard/dist/assets/{users-BZUTtM_6.js.map → users-BFaTe6Mt.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-DWhaZWVK.js → workflows-DXz7tZxp.js} +2 -2
- package/dashboard/dist/assets/{workflows-DWhaZWVK.js.map → workflows-DXz7tZxp.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-C1TeDIIk.js → yaml-workflows-u3xuRAnS.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-C1TeDIIk.js.map → yaml-workflows-u3xuRAnS.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/auth.md +26 -1
- package/docs/code-owned-configuration.md +158 -0
- package/docs/scan-codes.md +24 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/index-Cqrp5B5S.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 |
|
package/build/api/auth-sso.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import type { Request } from 'express';
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
2
|
import type { LTApiResult } from '../types/sdk';
|
|
3
3
|
/**
|
|
4
4
|
* Exchange host authentication for a Long Tail JWT.
|
|
5
5
|
*
|
|
6
|
-
* Calls `sso.resolve(req)` to extract the host identity, JIT provisions
|
|
6
|
+
* Calls `sso.resolve(req, res)` to extract the host identity, JIT provisions
|
|
7
7
|
* the user in `lt_users`, and returns a signed JWT the dashboard can
|
|
8
8
|
* store for subsequent API calls.
|
|
9
9
|
*
|
|
10
10
|
* No request body required — the host's cookies/headers carry the auth.
|
|
11
|
+
* `res` gives cookie-owning hosts the response handle at the exchange
|
|
12
|
+
* boundary (login and every keepalive beat) to set/refresh their session
|
|
13
|
+
* cookie — headers only; the route writes the response body.
|
|
11
14
|
*/
|
|
12
|
-
export declare function exchangeSSO(req: Request): Promise<LTApiResult>;
|
|
15
|
+
export declare function exchangeSSO(req: Request, res?: Response): Promise<LTApiResult>;
|
package/build/api/auth-sso.js
CHANGED
|
@@ -7,19 +7,22 @@ const auth_1 = require("../modules/auth");
|
|
|
7
7
|
/**
|
|
8
8
|
* Exchange host authentication for a Long Tail JWT.
|
|
9
9
|
*
|
|
10
|
-
* Calls `sso.resolve(req)` to extract the host identity, JIT provisions
|
|
10
|
+
* Calls `sso.resolve(req, res)` to extract the host identity, JIT provisions
|
|
11
11
|
* the user in `lt_users`, and returns a signed JWT the dashboard can
|
|
12
12
|
* store for subsequent API calls.
|
|
13
13
|
*
|
|
14
14
|
* No request body required — the host's cookies/headers carry the auth.
|
|
15
|
+
* `res` gives cookie-owning hosts the response handle at the exchange
|
|
16
|
+
* boundary (login and every keepalive beat) to set/refresh their session
|
|
17
|
+
* cookie — headers only; the route writes the response body.
|
|
15
18
|
*/
|
|
16
|
-
async function exchangeSSO(req) {
|
|
19
|
+
async function exchangeSSO(req, res) {
|
|
17
20
|
try {
|
|
18
21
|
const ssoConfig = (0, sso_1.getSSOConfig)();
|
|
19
22
|
if (!ssoConfig) {
|
|
20
23
|
return { status: 404, error: 'SSO not configured' };
|
|
21
24
|
}
|
|
22
|
-
const identity = await ssoConfig.resolve(req);
|
|
25
|
+
const identity = await ssoConfig.resolve(req, res);
|
|
23
26
|
if (!identity) {
|
|
24
27
|
return { status: 401, error: 'Host authentication required' };
|
|
25
28
|
}
|
|
@@ -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)(),
|
package/build/modules/auth.js
CHANGED
|
@@ -43,6 +43,7 @@ exports.signToken = signToken;
|
|
|
43
43
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
44
44
|
const config_1 = require("./config");
|
|
45
45
|
const sso_1 = require("./sso");
|
|
46
|
+
const logger_1 = require("../lib/logger");
|
|
46
47
|
const user_1 = require("../services/user");
|
|
47
48
|
const sso_provision_1 = require("../services/user/sso-provision");
|
|
48
49
|
const bot_api_key_1 = require("../services/auth/bot-api-key");
|
|
@@ -156,7 +157,10 @@ const requireAuth = async (req, res, next) => {
|
|
|
156
157
|
const mw = _authMiddleware || createAuthMiddleware(new JwtAuthAdapter());
|
|
157
158
|
return mw(req, res, next);
|
|
158
159
|
}
|
|
159
|
-
// SSO fallback: no Bearer, but host may have authenticated via cookies/headers
|
|
160
|
+
// SSO fallback: no Bearer, but host may have authenticated via cookies/headers.
|
|
161
|
+
// `res` is deliberately NOT passed to resolve here: this path runs on every
|
|
162
|
+
// cookie-bearing request, and ambient API traffic must never slide the host
|
|
163
|
+
// session — only the explicit exchange (login + gated keepalive beat) does.
|
|
160
164
|
const ssoConfig = (0, sso_1.getSSOConfig)();
|
|
161
165
|
if (ssoConfig) {
|
|
162
166
|
try {
|
|
@@ -177,8 +181,10 @@ const requireAuth = async (req, res, next) => {
|
|
|
177
181
|
return next();
|
|
178
182
|
}
|
|
179
183
|
}
|
|
180
|
-
catch {
|
|
181
|
-
// SSO resolve failed — fall through to 401
|
|
184
|
+
catch (err) {
|
|
185
|
+
// SSO resolve failed — fall through to 401, but leave a trace so host
|
|
186
|
+
// resolve errors are diagnosable.
|
|
187
|
+
logger_1.loggerRegistry.debug(`[long-tail] sso resolve failed on auth fallback: ${err?.message}`);
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
190
|
// No Bearer, no SSO — delegate to standard middleware (returns 401)
|
package/build/routes/auth-sso.js
CHANGED
|
@@ -45,7 +45,12 @@ const router = (0, express_1.Router)();
|
|
|
45
45
|
* login form with a transparent token exchange.
|
|
46
46
|
*/
|
|
47
47
|
router.post('/sso', async (req, res) => {
|
|
48
|
-
const result = await api.exchangeSSO(req);
|
|
48
|
+
const result = await api.exchangeSSO(req, res);
|
|
49
|
+
// A host's resolve may only set headers on `res`; if one violates the
|
|
50
|
+
// contract and writes the response, degrade to a skipped beat instead of
|
|
51
|
+
// a headers-after-send crash.
|
|
52
|
+
if (res.headersSent)
|
|
53
|
+
return;
|
|
49
54
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
50
55
|
});
|
|
51
56
|
exports.default = router;
|
|
@@ -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
|
*/
|