@hotmeshio/long-tail 0.14.4 → 0.16.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 +23 -9
- package/build/api/escalations/create.js +18 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +3 -1
- package/build/api/escalations/lookups.d.ts +20 -0
- package/build/api/escalations/lookups.js +90 -0
- package/build/api/escalations/metadata.d.ts +1 -1
- package/build/api/escalations/metadata.js +4 -4
- package/build/api/escalations/resolve.d.ts +1 -1
- package/build/api/escalations/resolve.js +6 -6
- package/build/api/knowledge.d.ts +9 -0
- package/build/api/knowledge.js +24 -0
- package/build/bin/ltc.js +10 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +3 -2
- package/build/lib/cli/commands/escalations.d.ts +3 -0
- package/build/lib/cli/commands/escalations.js +25 -0
- package/build/lib/cli/commands/knowledge.d.ts +5 -0
- package/build/lib/cli/commands/knowledge.js +17 -2
- package/build/lib/cli/scanner.js +2 -0
- package/build/lib/db/schemas/033_knowledge_versions.sql +33 -0
- package/build/routes/escalations/single.js +10 -0
- package/build/routes/knowledge.js +35 -2
- package/build/sdk/index.d.ts +5 -0
- package/build/sdk/index.js +3 -0
- package/build/services/diagnostics/patterns.js +1 -1
- package/build/services/escalation/crud.d.ts +3 -3
- package/build/services/escalation/crud.js +9 -2
- package/build/services/escalation/resolver-validation.js +6 -0
- package/build/services/escalation/sql.d.ts +1 -1
- package/build/services/escalation/sql.js +1 -1
- package/build/services/knowledge/index.d.ts +18 -0
- package/build/services/knowledge/index.js +52 -0
- package/build/services/knowledge/lookup-cache.d.ts +29 -0
- package/build/services/knowledge/lookup-cache.js +94 -0
- package/build/services/knowledge/sql.d.ts +2 -0
- package/build/services/knowledge/sql.js +14 -0
- package/build/services/mcp/server-tools.js +30 -0
- package/build/services/orchestrator/condition.d.ts +33 -13
- package/build/services/orchestrator/condition.js +41 -14
- package/build/services/yaml-workflow/durable-compiler/parser.js +4 -1
- package/build/shared/form-validation/ctx-path.d.ts +12 -0
- package/build/shared/form-validation/ctx-path.js +56 -0
- package/build/shared/form-validation/field-validator.d.ts +4 -2
- package/build/shared/form-validation/field-validator.js +22 -17
- package/build/shared/form-validation/index.d.ts +1 -0
- package/build/shared/form-validation/index.js +1 -0
- package/build/shared/form-validation/x-lt-help.d.ts +1 -1
- package/build/shared/form-validation/x-lt-help.js +2 -1
- package/build/shared/form-validation/x-lt-options.d.ts +7 -17
- package/build/shared/form-validation/x-lt-options.js +61 -27
- package/build/system/activities/knowledge.d.ts +3 -0
- package/build/system/activities/knowledge.js +5 -2
- package/build/system/activities/sql.d.ts +6 -10
- package/build/system/activities/sql.js +105 -49
- package/build/system/mcp-servers/admin/schemas.d.ts +4 -4
- package/build/system/mcp-servers/knowledge.js +23 -2
- package/build/system/seed/tool-manifests-escalation.js +12 -0
- package/build/system/seed/tool-manifests-knowledge.d.ts +36 -0
- package/build/system/seed/tool-manifests-knowledge.js +15 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +37 -3
- package/build/types/escalation.js +42 -2
- package/dashboard/dist/assets/{AdminDashboard-CUqnrc7h.js → AdminDashboard-Dnj4asuh.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-CUqnrc7h.js.map → AdminDashboard-Dnj4asuh.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-lmUOwyHO.js → AgentConfigPage-CS0CezLt.js} +6 -6
- package/dashboard/dist/assets/AgentConfigPage-CS0CezLt.js.map +1 -0
- package/dashboard/dist/assets/{AgentDetailPage-C_xAw6aF.js → AgentDetailPage-CG0HO-MG.js} +2 -2
- package/dashboard/dist/assets/AgentDetailPage-CG0HO-MG.js.map +1 -0
- package/dashboard/dist/assets/{AgentsPage-CHCGAkpN.js → AgentsPage-cLZPda64.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CHCGAkpN.js.map → AgentsPage-cLZPda64.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-Dv5GE_NU.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-BvQdHMl2.js.map → AvailableEscalationsPage-Dv5GE_NU.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-Dsr8Yyj_.js → BotPicker-BgXaJfUZ.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-Dsr8Yyj_.js.map → BotPicker-BgXaJfUZ.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-CbUftMR2.js → BulkAssignModal-BUfV9aba.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-CbUftMR2.js.map → BulkAssignModal-BUfV9aba.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CaiDhtmq.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-CPNUJPHs.js.map → CapabilitiesPage-CaiDhtmq.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-DffGX2tR.js → CollapsibleSection-C6R7Lhao.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-DffGX2tR.js.map → CollapsibleSection-C6R7Lhao.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-CFR2pPT9.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-CFR2pPT9.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-UXnD_Rau.js → CredentialsPage-9d2xZhfU.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-UXnD_Rau.js.map → CredentialsPage-9d2xZhfU.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CctUYUlI.js → CronLabel-BfIYBjTD.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CctUYUlI.js.map → CronLabel-BfIYBjTD.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-7UoXQ4qL.js → DropZone-Pv-v5RAs.js} +2 -2
- package/dashboard/dist/assets/{DropZone-7UoXQ4qL.js.map → DropZone-Pv-v5RAs.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-C7_Y8xXn.js → ElapsedCell-DV-35FDF.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-C7_Y8xXn.js.map → ElapsedCell-DV-35FDF.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-pRu91gZK.js → EntityTimelinePanel-mHaN_i7a.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-pRu91gZK.js.map → EntityTimelinePanel-mHaN_i7a.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-B3f2mjqg.js → EscalationListSchemaPage-Km5jnrIW.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-B3f2mjqg.js.map → EscalationListSchemaPage-Km5jnrIW.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-AJ85FRZy.js → EscalationSchemaPage-CAJGIBv2.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-AJ85FRZy.js.map → EscalationSchemaPage-CAJGIBv2.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DMLLWzjS.js → EscalationsOverview-nk9FXKmv.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DMLLWzjS.js.map → EscalationsOverview-nk9FXKmv.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-BlNuCTN6.js → EventTable-DNRaYzTn.js} +2 -2
- package/dashboard/dist/assets/{EventTable-BlNuCTN6.js.map → EventTable-DNRaYzTn.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-B-rkcWkV.js → FilterBar-CmRA_E6x.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-B-rkcWkV.js.map → FilterBar-CmRA_E6x.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-Bkt5tAFo.js → GraphInvokePage-HJfa82kv.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Bkt5tAFo.js.map → GraphInvokePage-HJfa82kv.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-CIE9bCFQ.js → HomePage-B2JDwmmh.js} +2 -2
- package/dashboard/dist/assets/{HomePage-CIE9bCFQ.js.map → HomePage-B2JDwmmh.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-CKuJ7HUH.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-C_-Utxqm.js.map → ListToolbar-CKuJ7HUH.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-c0p171OK.js → McpOverview-CZCzbiRs.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-c0p171OK.js.map → McpOverview-CZCzbiRs.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-B61I9-dM.js → McpQueryDetailPage-C081BBcH.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-B61I9-dM.js.map → McpQueryDetailPage-C081BBcH.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-841V8CXb.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-Viqi13Fa.js.map → McpQueryPage-841V8CXb.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CiAx_xyV.js → McpRunDetailPage-DZjlgp5W.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CiAx_xyV.js.map → McpRunDetailPage-DZjlgp5W.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BpfvNRbE.js → McpRunsPage-DW0VVd46.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BpfvNRbE.js.map → McpRunsPage-DW0VVd46.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-CKp_9EaI.js → NamespacePill-DONj6eUU.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-CKp_9EaI.js.map → NamespacePill-DONj6eUU.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DGKwUE6h.js → OperationsPage-DAw7z_Sh.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-DGKwUE6h.js.map → OperationsPage-DAw7z_Sh.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-ha-05tgB.js → OperatorDashboard-BAnQNuD6.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-ha-05tgB.js.map → OperatorDashboard-BAnQNuD6.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-CDDpHpdv.js → PageHeader-CFVw67M6.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-CDDpHpdv.js.map → PageHeader-CFVw67M6.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DIWH6fRv.js → PageHeaderWithStats-D9tQxILm.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DIWH6fRv.js.map → PageHeaderWithStats-D9tQxILm.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-DMH-D1ns.js → PersonaDetailPage-XENbpbSr.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-DMH-D1ns.js.map → PersonaDetailPage-XENbpbSr.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-YLjCcQcU.js → PersonasPage-CoWH5Fj8.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-YLjCcQcU.js.map → PersonasPage-CoWH5Fj8.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-W5_2FJHn.js → ProcessDetailPage-BDxOt-9L.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-W5_2FJHn.js.map → ProcessDetailPage-BDxOt-9L.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-5f_2S9ER.js → ProcessesListPage-BuNOmgig.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-5f_2S9ER.js.map → ProcessesListPage-BuNOmgig.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-CuDTO13n.js → RoleDetailPage-DAzkfZ4T.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-CuDTO13n.js.map → RoleDetailPage-DAzkfZ4T.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-C0hExOmI.js → RolePill-Di_5hfvw.js} +2 -2
- package/dashboard/dist/assets/{RolePill-C0hExOmI.js.map → RolePill-Di_5hfvw.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-McMYumsZ.js → RolesPage-C9jZL4aM.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-McMYumsZ.js.map → RolesPage-C9jZL4aM.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-CC87e67k.js → RunAsSelector-DswUl2-8.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-CC87e67k.js.map → RunAsSelector-DswUl2-8.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-Zk6Jorv_.js → ScanCodesPage-D_FDxJgT.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-Zk6Jorv_.js.map → ScanCodesPage-D_FDxJgT.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-B79pya8o.js → ScanSchemeDetailPage-Cbkpob5g.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-B79pya8o.js.map → ScanSchemeDetailPage-Cbkpob5g.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-BLlHMmd_.js → ScanStationPage-BI_cDWVp.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-BLlHMmd_.js.map → ScanStationPage-BI_cDWVp.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-BBQvz4pj.js → ScopeBadge-CqIIeWjK.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-BBQvz4pj.js.map → ScopeBadge-CqIIeWjK.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CnJgQPU1.js → StickyPagination-CfTEnlh5.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CnJgQPU1.js.map → StickyPagination-CfTEnlh5.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-CU5wrqO_.js → StreamMessageDetail-oa7Bx0lB.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-CU5wrqO_.js.map → StreamMessageDetail-oa7Bx0lB.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-D5m-_zgy.js → SwimlaneTimeline-CO96ep4N.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-D5m-_zgy.js.map → SwimlaneTimeline-CO96ep4N.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BXxXs1JD.js → TagInput-BLwxTNsI.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BXxXs1JD.js.map → TagInput-BLwxTNsI.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-SvVSH39Q.js → TaskDetailPage-BiO2eFQ0.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-SvVSH39Q.js.map → TaskDetailPage-BiO2eFQ0.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BKGJBVZG.js → TaskQueuePill-DVgcqd-h.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BKGJBVZG.js.map → TaskQueuePill-DVgcqd-h.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BtpwvxkS.js → TasksListPage-DQ4WJfJo.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BtpwvxkS.js.map → TasksListPage-DQ4WJfJo.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BPODA7Dm.js → TimeAgo-ZwSSU_EG.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BPODA7Dm.js.map → TimeAgo-ZwSSU_EG.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DEQXlxbH.js → TimestampCell-BHmJ7das.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DEQXlxbH.js.map → TimestampCell-BHmJ7das.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-BY6zLSfA.js → ToolPill-C6hkOqPx.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-BY6zLSfA.js.map → ToolPill-C6hkOqPx.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-Ztc0pRSh.js → ToolTestPanel-DARNx6e0.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-Ztc0pRSh.js.map → ToolTestPanel-DARNx6e0.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-BmpEqg-Q.js → TopicDetailPage-BYcF0lO8.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-BmpEqg-Q.js.map → TopicDetailPage-BYcF0lO8.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BVW5y6vE.js → TopicsPage-CG-IZfpq.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BVW5y6vE.js.map → TopicsPage-CG-IZfpq.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-D915g7ba.js → UserName-BGn4sSx1.js} +2 -2
- package/dashboard/dist/assets/{UserName-D915g7ba.js.map → UserName-BGn4sSx1.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-CIl9ESgk.js → WorkflowExecutionPage-Dt_lskas.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-CIl9ESgk.js.map → WorkflowExecutionPage-Dt_lskas.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-qp5UF3-y.js → WorkflowPill-CN-952iI.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-qp5UF3-y.js.map → WorkflowPill-CN-952iI.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DtkaGgdZ.js → WorkflowsDashboard-Dl3carpF.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DtkaGgdZ.js.map → WorkflowsDashboard-Dl3carpF.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-DANXhmXb.js → WorkflowsOverview-6CplKLvQ.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-DANXhmXb.js.map → WorkflowsOverview-6CplKLvQ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-m6Ub7qtE.js → YamlWorkflowDetailPage-CZf6zZ4Q.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-m6Ub7qtE.js.map → YamlWorkflowDetailPage-CZf6zZ4Q.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-5MOsxbLW.js → YamlWorkflowsPage-DRQ_3CZG.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-5MOsxbLW.js.map → YamlWorkflowsPage-DRQ_3CZG.js.map} +1 -1
- package/dashboard/dist/assets/{agents-DacpnIqz.js → agents-BvtecCN5.js} +2 -2
- package/dashboard/dist/assets/{agents-DacpnIqz.js.map → agents-BvtecCN5.js.map} +1 -1
- package/dashboard/dist/assets/{bots-El47Xy5a.js → bots-CSmIqXtL.js} +2 -2
- package/dashboard/dist/assets/{bots-El47Xy5a.js.map → bots-CSmIqXtL.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DGC__Aob.js → capabilities-xMqvjbWI.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DGC__Aob.js.map → capabilities-xMqvjbWI.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-Bzx-qd8m.js → controlplane-Bi-tz-Gr.js} +2 -2
- package/dashboard/dist/assets/{controlplane-Bzx-qd8m.js.map → controlplane-Bi-tz-Gr.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BmY7BriY.js → escalation-columns-DSalfPHI.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BmY7BriY.js.map → escalation-columns-DSalfPHI.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bwlnpbpd.js → index-BIK4b7Ei.js} +2 -2
- package/dashboard/dist/assets/{index-Bwlnpbpd.js.map → index-BIK4b7Ei.js.map} +1 -1
- package/dashboard/dist/assets/{index-BPK2cB4Q.js → index-BWyPrDYG.js} +4 -4
- package/dashboard/dist/assets/{index-BPK2cB4Q.js.map → index-BWyPrDYG.js.map} +1 -1
- package/dashboard/dist/assets/{index-Ce6ghhpn.js → index-BYukuL1u.js} +2 -2
- package/dashboard/dist/assets/{index-Ce6ghhpn.js.map → index-BYukuL1u.js.map} +1 -1
- package/dashboard/dist/assets/index-Bf9cfGX_.js +3 -0
- package/dashboard/dist/assets/index-Bf9cfGX_.js.map +1 -0
- package/dashboard/dist/assets/{index-CHwg51qz.js → index-BjxQVsbg.js} +2 -2
- package/dashboard/dist/assets/{index-CHwg51qz.js.map → index-BjxQVsbg.js.map} +1 -1
- package/dashboard/dist/assets/{index-DpsVlk5z.js → index-C8pPqnJb.js} +2 -2
- package/dashboard/dist/assets/{index-DpsVlk5z.js.map → index-C8pPqnJb.js.map} +1 -1
- package/dashboard/dist/assets/{index-DYz57kr_.js → index-CEsGT3c9.js} +2 -2
- package/dashboard/dist/assets/{index-DYz57kr_.js.map → index-CEsGT3c9.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cfw6FARc.js → index-DATqc8Gv.js} +2 -2
- package/dashboard/dist/assets/{index-Cfw6FARc.js.map → index-DATqc8Gv.js.map} +1 -1
- package/dashboard/dist/assets/{index-ZtpEajtq.js → index-cX2H_U7R.js} +2 -2
- package/dashboard/dist/assets/{index-ZtpEajtq.js.map → index-cX2H_U7R.js.map} +1 -1
- package/dashboard/dist/assets/{index-CoIh4ipz.js → index-gHDAcM64.js} +2 -2
- package/dashboard/dist/assets/{index-CoIh4ipz.js.map → index-gHDAcM64.js.map} +1 -1
- package/dashboard/dist/assets/{index-SU2xrnBD.js → index-sbfCx2CF.js} +31 -31
- package/dashboard/dist/assets/index-sbfCx2CF.js.map +1 -0
- package/dashboard/dist/assets/index-shnwALdy.js +2 -0
- package/dashboard/dist/assets/index-shnwALdy.js.map +1 -0
- package/dashboard/dist/assets/index-uqT6ovVQ.js +2 -0
- package/dashboard/dist/assets/{index-DH_xm9UQ.js.map → index-uqT6ovVQ.js.map} +1 -1
- package/dashboard/dist/assets/knowledge-DbDvUbq7.js +2 -0
- package/dashboard/dist/assets/knowledge-DbDvUbq7.js.map +1 -0
- package/dashboard/dist/assets/{mcp-BEqxxlW9.js → mcp-I2OmwD8P.js} +2 -2
- package/dashboard/dist/assets/{mcp-BEqxxlW9.js.map → mcp-I2OmwD8P.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-qXTlQfc_.js → mcp-query-DwTp77HP.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-qXTlQfc_.js.map → mcp-query-DwTp77HP.js.map} +1 -1
- package/dashboard/dist/assets/{personas-jJEDmBtg.js → personas-DDr8gQGC.js} +2 -2
- package/dashboard/dist/assets/{personas-jJEDmBtg.js.map → personas-DDr8gQGC.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BNPJh69x.js → pipelines-uptnM5Qj.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BNPJh69x.js.map → pipelines-uptnM5Qj.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DhD71qXJ.js → tasks-Em0f5Rsk.js} +2 -2
- package/dashboard/dist/assets/{tasks-DhD71qXJ.js.map → tasks-Em0f5Rsk.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CrXwwuW-.js → topics-B81zAt9U.js} +2 -2
- package/dashboard/dist/assets/{topics-CrXwwuW-.js.map → topics-B81zAt9U.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-DL7R0ASv.js → useEventHooks-B_Bqqzlo.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-DL7R0ASv.js.map → useEventHooks-B_Bqqzlo.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-ETqzJakA.js → useNamespace-CZfue_oE.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-ETqzJakA.js.map → useNamespace-CZfue_oE.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-SqY67S-F.js → useYamlActivityEvents-DjQ7rsOC.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-SqY67S-F.js.map → useYamlActivityEvents-DjQ7rsOC.js.map} +1 -1
- package/dashboard/dist/assets/{users-DF8dTbOo.js → users-CwUL9YJT.js} +2 -2
- package/dashboard/dist/assets/{users-DF8dTbOo.js.map → users-CwUL9YJT.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-BgsXTN4h.js → vendor-icons-h-jlRSb9.js} +141 -146
- package/dashboard/dist/assets/vendor-icons-h-jlRSb9.js.map +1 -0
- package/dashboard/dist/assets/{workflows-Bdke7fzx.js → workflows-gSjgU0KB.js} +2 -2
- package/dashboard/dist/assets/{workflows-Bdke7fzx.js.map → workflows-gSjgU0KB.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-UMxHYunb.js → yaml-workflows-a_7IO_a6.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-UMxHYunb.js.map → yaml-workflows-a_7IO_a6.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/api/http/escalations.md +31 -8
- package/docs/api/http/knowledge.md +24 -2
- package/docs/api/http/roles.md +1 -1
- package/docs/api/mcp/admin.md +1 -1
- package/docs/api/mcp/human-queue.md +14 -0
- package/docs/api/mcp/knowledge.md +17 -1
- package/docs/api/sdk/escalations.md +38 -15
- package/docs/api/sdk/knowledge.md +27 -0
- package/docs/api/sdk/roles.md +1 -1
- package/docs/compilation.md +1 -1
- package/docs/compiler.md +2 -2
- package/docs/dashboard.md +1 -1
- package/docs/data.md +3 -3
- package/docs/hitl/escalation.md +14 -12
- package/docs/hitl/iframe.md +2 -2
- package/docs/hitl/lookups.md +145 -0
- package/docs/hitl/resolution.md +4 -4
- package/docs/hitl/roles.md +4 -4
- package/docs/hitl/x-lt-show-if.md +1 -1
- package/docs/hitl/x-lt-transition.md +2 -2
- package/docs/hitl/x-lt-validation.md +4 -2
- package/docs/hitl/x-lt-widget.md +2 -2
- package/docs/hitl-guide.md +6 -3
- package/docs/story.md +1 -1
- package/package.json +1 -1
- package/dashboard/dist/assets/AgentConfigPage-lmUOwyHO.js.map +0 -1
- package/dashboard/dist/assets/AgentDetailPage-C_xAw6aF.js.map +0 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BvQdHMl2.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-CPNUJPHs.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-C_-Utxqm.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-Viqi13Fa.js +0 -2
- package/dashboard/dist/assets/index-B4ZNPgcz.js +0 -2
- package/dashboard/dist/assets/index-B4ZNPgcz.js.map +0 -1
- package/dashboard/dist/assets/index-Cqc7Wu5Y.js +0 -3
- package/dashboard/dist/assets/index-Cqc7Wu5Y.js.map +0 -1
- package/dashboard/dist/assets/index-DH_xm9UQ.js +0 -2
- package/dashboard/dist/assets/index-SU2xrnBD.js.map +0 -1
- package/dashboard/dist/assets/knowledge-k-5jr2BN.js +0 -2
- package/dashboard/dist/assets/knowledge-k-5jr2BN.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-BgsXTN4h.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
**The queue durable systems forgot.**
|
|
4
4
|
|
|
5
|
-
Durable platforms
|
|
5
|
+
Durable platforms queue deterministic work well — retries, timeouts, exactly-once — and give you `await condition()` to park a workflow until a signal arrives. But the wait itself is invisible: nothing to find, claim, or measure while it sits there.
|
|
6
6
|
|
|
7
|
-
Long Tail
|
|
7
|
+
Long Tail's `conditional` is that same wait made visible. Waiting mints a row that is searchable, claimable, deadlined, and role-gated on a shared metadata surface. A person or a machine answers it; the workflow resumes exactly where it paused.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install @hotmeshio/long-tail
|
|
@@ -12,26 +12,26 @@ npm install @hotmeshio/long-tail
|
|
|
12
12
|
|
|
13
13
|
## How it works
|
|
14
14
|
|
|
15
|
-
One workflow, both queues: `proxyActivities` for the deterministic one, `
|
|
15
|
+
One workflow, both queues: `proxyActivities` for the deterministic one, `conditional` for non-determinism.
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
18
|
import { Durable } from '@hotmeshio/hotmesh';
|
|
19
|
-
import type
|
|
19
|
+
import { conditional, type LTEnvelope } from '@hotmeshio/long-tail';
|
|
20
20
|
import * as activities from './activities';
|
|
21
21
|
|
|
22
22
|
const { analyzeContent } = Durable.workflow.proxyActivities<typeof activities>({ activities });
|
|
23
23
|
|
|
24
24
|
export async function reviewContent(envelope: LTEnvelope) {
|
|
25
|
-
//
|
|
25
|
+
// activity calls are checkpointed and crash-safe
|
|
26
26
|
const analysis = await analyzeContent(envelope.data.content);
|
|
27
27
|
|
|
28
28
|
if (analysis.confidence >= 0.85) {
|
|
29
29
|
return { data: { approved: true, analysis } };
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// low confidence: pause as a claimable, role-gated escalation
|
|
33
33
|
const { workflowId } = Durable.workflow.workflowInfo();
|
|
34
|
-
const decision = await
|
|
34
|
+
const decision = await conditional<{ approved: boolean; notes?: string }>(
|
|
35
35
|
`review-${workflowId}`,
|
|
36
36
|
{
|
|
37
37
|
role: 'reviewer',
|
|
@@ -40,14 +40,28 @@ export async function reviewContent(envelope: LTEnvelope) {
|
|
|
40
40
|
description: `Confidence ${analysis.confidence} — needs a human`,
|
|
41
41
|
metadata: { contentId: envelope.data.contentId },
|
|
42
42
|
envelope: { data: envelope.data, analysis },
|
|
43
|
+
schemaVersion: 1, // the reviewer form edition this code is written for
|
|
43
44
|
},
|
|
44
45
|
);
|
|
45
46
|
|
|
46
|
-
return { data: { approved: decision.approved, analysis } };
|
|
47
|
+
return { data: { approved: decision && decision.approved, analysis } };
|
|
47
48
|
}
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
The `reviewer` role owns a versioned form schema. The platform renders it as the resolver's UI, validates every submission against it, and `schemaVersion` pins the edition this code expects — evolve the form and the payload type together, and rows in flight keep the form they were minted for:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"title": "Content Review",
|
|
56
|
+
"required": ["approved"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"approved": { "type": "boolean", "description": "Approve this content?" },
|
|
59
|
+
"notes": { "type": "string", "format": "textarea", "description": "What you saw" }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Two surfaces, one model. A `proxyActivity` targets a machine: call it, get a result. `conditional` targets the external world — a reviewer, an operator, a factory cell. It suspends the workflow and writes a single escalation row carrying everything needed to route the work: the `role` that should act, its `type` and `priority`, and any `metadata` to display or filter on. People work that row through an RBAC-scoped surface — find it, claim it, resolve it — from the dashboard, the API, or MCP, and resolving it resumes the workflow exactly where it paused.
|
|
51
65
|
|
|
52
66
|
Activities are plain functions:
|
|
53
67
|
|
|
@@ -80,6 +80,24 @@ async function createEscalation(input, auth) {
|
|
|
80
80
|
// stamped here — omitting it means the resolve UI renders the role's latest
|
|
81
81
|
// form at fetch time.
|
|
82
82
|
const metadata = input.metadata ?? {};
|
|
83
|
+
// Lookup refs ride the envelope under a reserved key with a fixed
|
|
84
|
+
// contract: version required — a ref pins an immutable knowledge edition,
|
|
85
|
+
// never a moving target.
|
|
86
|
+
if (input.envelope) {
|
|
87
|
+
try {
|
|
88
|
+
const envelopeObj = JSON.parse(input.envelope);
|
|
89
|
+
if (envelopeObj && typeof envelopeObj === 'object'
|
|
90
|
+
&& envelopeObj[escalation_1.ESCALATION_ENVELOPE_KEYS.LOOKUPS] !== undefined) {
|
|
91
|
+
(0, escalation_1.assertLookupRefs)(envelopeObj[escalation_1.ESCALATION_ENVELOPE_KEYS.LOOKUPS]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (refErr) {
|
|
95
|
+
if (refErr instanceof SyntaxError) {
|
|
96
|
+
return { status: 400, error: 'envelope must be valid JSON' };
|
|
97
|
+
}
|
|
98
|
+
return { status: 400, error: refErr.message };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
83
101
|
const metadataSchema = await roleService.getRoleMetadataSchema(role);
|
|
84
102
|
if (metadataSchema) {
|
|
85
103
|
let validate;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createEscalation } from './create';
|
|
2
2
|
export { listEscalations, listAvailableEscalations, listDistinctTypes, listFacetKeys, getEscalationStats, getStationMetrics } from './list';
|
|
3
3
|
export { getEscalation, getEscalationsByWorkflowId, escalateToRole } from './single';
|
|
4
|
+
export { getEscalationLookups } from './lookups';
|
|
4
5
|
export { claimEscalation, releaseEscalation } from './claim';
|
|
5
6
|
export { releaseExpiredClaims, updatePriority, bulkClaim, bulkAssign, bulkUnassign, bulkEscalate, bulkTriage } from './bulk';
|
|
6
7
|
export { resolveEscalation, resolveBySignalKey, resolveByIds, resolveAllOrNone } from './resolve';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkUnassign = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
3
|
+
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkUnassign = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.getEscalationLookups = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
4
4
|
var create_1 = require("./create");
|
|
5
5
|
Object.defineProperty(exports, "createEscalation", { enumerable: true, get: function () { return create_1.createEscalation; } });
|
|
6
6
|
var list_1 = require("./list");
|
|
@@ -14,6 +14,8 @@ var single_1 = require("./single");
|
|
|
14
14
|
Object.defineProperty(exports, "getEscalation", { enumerable: true, get: function () { return single_1.getEscalation; } });
|
|
15
15
|
Object.defineProperty(exports, "getEscalationsByWorkflowId", { enumerable: true, get: function () { return single_1.getEscalationsByWorkflowId; } });
|
|
16
16
|
Object.defineProperty(exports, "escalateToRole", { enumerable: true, get: function () { return single_1.escalateToRole; } });
|
|
17
|
+
var lookups_1 = require("./lookups");
|
|
18
|
+
Object.defineProperty(exports, "getEscalationLookups", { enumerable: true, get: function () { return lookups_1.getEscalationLookups; } });
|
|
17
19
|
var claim_1 = require("./claim");
|
|
18
20
|
Object.defineProperty(exports, "claimEscalation", { enumerable: true, get: function () { return claim_1.claimEscalation; } });
|
|
19
21
|
Object.defineProperty(exports, "releaseEscalation", { enumerable: true, get: function () { return claim_1.releaseEscalation; } });
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type EscalationLookupRef } from '../../types/escalation';
|
|
2
|
+
import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
3
|
+
/** The refs riding the row's envelope under the reserved key, or []. */
|
|
4
|
+
export declare function readLookupRefs(envelope: string | null | undefined): EscalationLookupRef[];
|
|
5
|
+
/**
|
|
6
|
+
* Resolve an escalation's versioned knowledge lookups.
|
|
7
|
+
*
|
|
8
|
+
* The refs on `envelope.lookups` ARE the grant: any user who may read the
|
|
9
|
+
* escalation may read exactly the pinned editions it names — nothing else in
|
|
10
|
+
* the knowledge store. Snapshots are immutable, so responses are served from
|
|
11
|
+
* an in-process cache after the first read; a ref whose snapshot does not
|
|
12
|
+
* exist answers with `missing: true` rather than failing the batch.
|
|
13
|
+
*
|
|
14
|
+
* @param input.id — escalation UUID
|
|
15
|
+
* @param auth — authenticated user context (must hold the escalation's role)
|
|
16
|
+
* @returns `{ status: 200, data: { lookups: [{ domain, key, version, as?, data, missing? }] } }`
|
|
17
|
+
*/
|
|
18
|
+
export declare function getEscalationLookups(input: {
|
|
19
|
+
id: string;
|
|
20
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.readLookupRefs = readLookupRefs;
|
|
37
|
+
exports.getEscalationLookups = getEscalationLookups;
|
|
38
|
+
const escalationService = __importStar(require("../../services/escalation"));
|
|
39
|
+
const knowledge_1 = require("../../services/knowledge");
|
|
40
|
+
const escalation_1 = require("../../types/escalation");
|
|
41
|
+
const helpers_1 = require("./helpers");
|
|
42
|
+
// ── Lookups ────────────────────────────────────────────────────────────────
|
|
43
|
+
/** The refs riding the row's envelope under the reserved key, or []. */
|
|
44
|
+
function readLookupRefs(envelope) {
|
|
45
|
+
if (!envelope)
|
|
46
|
+
return [];
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(envelope);
|
|
49
|
+
const refs = parsed && typeof parsed === 'object'
|
|
50
|
+
? parsed[escalation_1.ESCALATION_ENVELOPE_KEYS.LOOKUPS]
|
|
51
|
+
: undefined;
|
|
52
|
+
return Array.isArray(refs) ? refs : [];
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve an escalation's versioned knowledge lookups.
|
|
60
|
+
*
|
|
61
|
+
* The refs on `envelope.lookups` ARE the grant: any user who may read the
|
|
62
|
+
* escalation may read exactly the pinned editions it names — nothing else in
|
|
63
|
+
* the knowledge store. Snapshots are immutable, so responses are served from
|
|
64
|
+
* an in-process cache after the first read; a ref whose snapshot does not
|
|
65
|
+
* exist answers with `missing: true` rather than failing the batch.
|
|
66
|
+
*
|
|
67
|
+
* @param input.id — escalation UUID
|
|
68
|
+
* @param auth — authenticated user context (must hold the escalation's role)
|
|
69
|
+
* @returns `{ status: 200, data: { lookups: [{ domain, key, version, as?, data, missing? }] } }`
|
|
70
|
+
*/
|
|
71
|
+
async function getEscalationLookups(input, auth) {
|
|
72
|
+
try {
|
|
73
|
+
const escalation = await escalationService.getEscalation(input.id);
|
|
74
|
+
if (!escalation) {
|
|
75
|
+
return { status: 404, error: 'Escalation not found' };
|
|
76
|
+
}
|
|
77
|
+
const denied = await (0, helpers_1.assertReadAccess)(auth.userId, escalation);
|
|
78
|
+
if (denied)
|
|
79
|
+
return denied;
|
|
80
|
+
const refs = readLookupRefs(escalation.envelope);
|
|
81
|
+
if (refs.length === 0) {
|
|
82
|
+
return { status: 200, data: { lookups: [] } };
|
|
83
|
+
}
|
|
84
|
+
const lookups = await (0, knowledge_1.resolveLookupRefs)(refs);
|
|
85
|
+
return { status: 200, data: { lookups } };
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
return { status: 500, error: err.message };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -43,7 +43,7 @@ export declare function claimByMetadata(input: {
|
|
|
43
43
|
* Single atomic query with signal guard:
|
|
44
44
|
* - No signal_id → claim + resolve atomically in SQL. One query. Done.
|
|
45
45
|
* - signal_id present → SQL returns the signal info without resolving.
|
|
46
|
-
* Caller signals the workflow;
|
|
46
|
+
* Caller signals the workflow; conditional resolves durably inside
|
|
47
47
|
* the workflow via ltResolveEscalation.
|
|
48
48
|
*
|
|
49
49
|
* Never does SELECT-then-UPDATE. The SQL CTE handles find + RBAC +
|
|
@@ -124,7 +124,7 @@ async function claimByMetadata(input, auth) {
|
|
|
124
124
|
* Single atomic query with signal guard:
|
|
125
125
|
* - No signal_id → claim + resolve atomically in SQL. One query. Done.
|
|
126
126
|
* - signal_id present → SQL returns the signal info without resolving.
|
|
127
|
-
* Caller signals the workflow;
|
|
127
|
+
* Caller signals the workflow; conditional resolves durably inside
|
|
128
128
|
* the workflow via ltResolveEscalation.
|
|
129
129
|
*
|
|
130
130
|
* Never does SELECT-then-UPDATE. The SQL CTE handles find + RBAC +
|
|
@@ -180,7 +180,7 @@ async function resolveByMetadata(input, auth) {
|
|
|
180
180
|
if (result.outcome === 'resolved') {
|
|
181
181
|
return { status: 200, data: { escalation: result.escalation } };
|
|
182
182
|
}
|
|
183
|
-
// Atomic
|
|
183
|
+
// Atomic conditional escalation (signal_key set) — SDK resolve atomically marks
|
|
184
184
|
// resolved AND delivers the signal to the waiting condition(), resuming the workflow.
|
|
185
185
|
if (result.signalKey) {
|
|
186
186
|
const resolved = await escalationService.resolveEscalation(result.escalationId, input.resolverPayload);
|
|
@@ -192,8 +192,8 @@ async function resolveByMetadata(input, auth) {
|
|
|
192
192
|
data: { signaled: true, escalationId: result.escalationId, workflowId: result.workflowId },
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
|
-
// Legacy
|
|
196
|
-
//
|
|
195
|
+
// Legacy conditional escalation (metadata.signal_id set) — signal the workflow,
|
|
196
|
+
// conditional interceptor resolves durably via ltResolveEscalation.
|
|
197
197
|
const { createClient } = await Promise.resolve().then(() => __importStar(require('../../workers')));
|
|
198
198
|
const client = createClient();
|
|
199
199
|
const handle = await client.workflow.getHandle(result.taskQueue, result.workflowType, result.workflowId);
|
|
@@ -4,7 +4,7 @@ import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
|
4
4
|
* Resolve a pending escalation with a human-provided payload.
|
|
5
5
|
*
|
|
6
6
|
* Handles multiple resolution paths:
|
|
7
|
-
* 1. **Condition signal** — lightweight `
|
|
7
|
+
* 1. **Condition signal** — lightweight `conditional` signal via metadata.signal_id
|
|
8
8
|
* 2. **Signal-routed** — full signal_routing via YAML engine or Durable handle
|
|
9
9
|
* 3. **Strategy triage** — escalation strategy redirects to a triage workflow
|
|
10
10
|
* 4. **Notification-only** — no workflow_type; acknowledge and close
|
|
@@ -54,7 +54,7 @@ const enforcement_cache_1 = require("../../services/role/enforcement-cache");
|
|
|
54
54
|
* Resolve a pending escalation with a human-provided payload.
|
|
55
55
|
*
|
|
56
56
|
* Handles multiple resolution paths:
|
|
57
|
-
* 1. **Condition signal** — lightweight `
|
|
57
|
+
* 1. **Condition signal** — lightweight `conditional` signal via metadata.signal_id
|
|
58
58
|
* 2. **Signal-routed** — full signal_routing via YAML engine or Durable handle
|
|
59
59
|
* 3. **Strategy triage** — escalation strategy redirects to a triage workflow
|
|
60
60
|
* 4. **Notification-only** — no workflow_type; acknowledge and close
|
|
@@ -105,7 +105,7 @@ async function resolveEscalation(input, auth) {
|
|
|
105
105
|
// workflow's contract, formed by the caller (the React app maps the form to
|
|
106
106
|
// the payload via x-lt-bind before submitting). No server-side transform.
|
|
107
107
|
// Resolution provenance, both surfaces at once: `resolvedBy` rides the
|
|
108
|
-
// signal to the waiting workflow ($resolution — see
|
|
108
|
+
// signal to the waiting workflow ($resolution — see conditional), and
|
|
109
109
|
// `resolved_by` merges into the row's GIN-indexed metadata inside the same
|
|
110
110
|
// atomic resolve, making "who resolved it" `@>`-queryable without a
|
|
111
111
|
// follow-up read.
|
|
@@ -116,7 +116,7 @@ async function resolveEscalation(input, auth) {
|
|
|
116
116
|
// single status='pending'-guarded UPDATE (HotMesh `resolve(metadata)`). Paths that
|
|
117
117
|
// resolve here pass it as the 3rd arg; paths that resume a workflow carry it on the
|
|
118
118
|
// signal so the downstream resolve commits it atomically.
|
|
119
|
-
// Path A:
|
|
119
|
+
// Path A: conditional signal
|
|
120
120
|
const metadataSignalId = escalation.metadata?.signal_id;
|
|
121
121
|
if (metadataSignalId && escalation.workflow_id && escalation.task_queue && escalation.workflow_type) {
|
|
122
122
|
return resolveViaConditionSignal(escalation, resolverPayload, outcome, resolvedBy);
|
|
@@ -378,15 +378,15 @@ async function resolveAllOrNone(input, auth) {
|
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
380
|
// ── Resolution paths ─────────────────────────────────────────────────────
|
|
381
|
-
/** Path A: lightweight
|
|
381
|
+
/** Path A: lightweight conditional signal — inject $escalation_id and signal the running workflow. */
|
|
382
382
|
async function resolveViaConditionSignal(escalation, resolverPayload, metadata, resolvedBy) {
|
|
383
383
|
const signalId = escalation.metadata.signal_id;
|
|
384
384
|
const client = (0, workers_1.createClient)();
|
|
385
385
|
const handle = await client.workflow.getHandle(escalation.task_queue, escalation.workflow_type, escalation.workflow_id);
|
|
386
|
-
// The row is resolved downstream by the workflow's `
|
|
386
|
+
// The row is resolved downstream by the workflow's `conditional` → `ltResolveEscalation`.
|
|
387
387
|
// Carry the outcome patch on the signal ($escalation_metadata, symmetric to $escalation_id)
|
|
388
388
|
// so it merges inside that single atomic resolve — never a separate write here.
|
|
389
|
-
// $resolution (provenance) is surfaced to the workflow by
|
|
389
|
+
// $resolution (provenance) is surfaced to the workflow by conditional and stripped
|
|
390
390
|
// from the stored resolver_payload, same as the other $-control keys.
|
|
391
391
|
await handle.signal(signalId, {
|
|
392
392
|
...resolverPayload,
|
package/build/api/knowledge.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export declare function getEntry(input: {
|
|
|
11
11
|
domain: string;
|
|
12
12
|
key: string;
|
|
13
13
|
}): Promise<LTApiResult>;
|
|
14
|
+
export declare function getEntryVersion(input: {
|
|
15
|
+
domain: string;
|
|
16
|
+
key: string;
|
|
17
|
+
version: number;
|
|
18
|
+
}): Promise<LTApiResult>;
|
|
19
|
+
export declare function listEntryVersions(input: {
|
|
20
|
+
domain: string;
|
|
21
|
+
key: string;
|
|
22
|
+
}): Promise<LTApiResult>;
|
|
14
23
|
export declare function storeEntry(input: {
|
|
15
24
|
domain: string;
|
|
16
25
|
key: string;
|
package/build/api/knowledge.js
CHANGED
|
@@ -36,11 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.listDomains = listDomains;
|
|
37
37
|
exports.listEntries = listEntries;
|
|
38
38
|
exports.getEntry = getEntry;
|
|
39
|
+
exports.getEntryVersion = getEntryVersion;
|
|
40
|
+
exports.listEntryVersions = listEntryVersions;
|
|
39
41
|
exports.storeEntry = storeEntry;
|
|
40
42
|
exports.setField = setField;
|
|
41
43
|
exports.removeField = removeField;
|
|
42
44
|
exports.deleteEntry = deleteEntry;
|
|
43
45
|
const knowledgeActivity = __importStar(require("../system/activities/knowledge"));
|
|
46
|
+
const knowledgeService = __importStar(require("../services/knowledge"));
|
|
44
47
|
async function listDomains() {
|
|
45
48
|
try {
|
|
46
49
|
const result = await knowledgeActivity.listDomains();
|
|
@@ -68,6 +71,27 @@ async function getEntry(input) {
|
|
|
68
71
|
return { status: 500, error: err.message };
|
|
69
72
|
}
|
|
70
73
|
}
|
|
74
|
+
async function getEntryVersion(input) {
|
|
75
|
+
try {
|
|
76
|
+
const result = await knowledgeService.getKnowledgeVersion(input.domain, input.key, input.version);
|
|
77
|
+
if (!result) {
|
|
78
|
+
return { status: 404, error: `No version ${input.version} of ${input.domain}/${input.key}` };
|
|
79
|
+
}
|
|
80
|
+
return { status: 200, data: result };
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
return { status: 500, error: err.message };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function listEntryVersions(input) {
|
|
87
|
+
try {
|
|
88
|
+
const versions = await knowledgeService.listKnowledgeVersions(input.domain, input.key);
|
|
89
|
+
return { status: 200, data: { domain: input.domain, key: input.key, versions } };
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return { status: 500, error: err.message };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
71
95
|
async function storeEntry(input) {
|
|
72
96
|
try {
|
|
73
97
|
const result = await knowledgeActivity.storeKnowledge(input);
|
package/build/bin/ltc.js
CHANGED
|
@@ -145,6 +145,10 @@ escCmd.command('list')
|
|
|
145
145
|
escCmd.command('get <id>')
|
|
146
146
|
.option('--json', 'JSON output')
|
|
147
147
|
.action(wrap(esc.getEscalation));
|
|
148
|
+
escCmd.command('lookups <id>')
|
|
149
|
+
.description('Resolve the versioned knowledge lookups pinned on an escalation')
|
|
150
|
+
.option('--json', 'JSON output')
|
|
151
|
+
.action(wrap(esc.getLookups));
|
|
148
152
|
escCmd.command('claim <id>')
|
|
149
153
|
.option('--duration <minutes>', 'Claim duration in minutes')
|
|
150
154
|
.action(wrap(esc.claimEscalation));
|
|
@@ -290,8 +294,14 @@ kbCmd.command('list <domain>')
|
|
|
290
294
|
.option('-q, --quiet', 'Keys only')
|
|
291
295
|
.action(wrap(kb.listEntries));
|
|
292
296
|
kbCmd.command('get <domain> <key>')
|
|
297
|
+
.option('--version <n>', 'Fetch this immutable edition instead of the live entry')
|
|
293
298
|
.option('--json', 'JSON output')
|
|
294
299
|
.action(wrap(kb.getEntry));
|
|
300
|
+
kbCmd.command('versions <domain> <key>')
|
|
301
|
+
.description('List every immutable edition of an entry, newest first')
|
|
302
|
+
.option('--json', 'JSON output')
|
|
303
|
+
.option('-q, --quiet', 'Versions only')
|
|
304
|
+
.action(wrap(kb.listVersions));
|
|
295
305
|
kbCmd.command('set <domain> <key> <path> <value>')
|
|
296
306
|
.option('--json', 'JSON output')
|
|
297
307
|
.description('Set a value at a dot-path (e.g., ltc kb set research screenshots google.holiday "Mother\'s Day")')
|
package/build/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { midnightTheme } from './themes/midnight';
|
|
|
3
3
|
export { registerLT, createLTInterceptor } from './services/interceptor';
|
|
4
4
|
export { createLTActivityInterceptor } from './services/interceptor/activity-interceptor';
|
|
5
5
|
export { executeLT } from './services/orchestrator';
|
|
6
|
-
export { conditionLT } from './services/orchestrator/condition';
|
|
6
|
+
export { conditional, conditionLT } from './services/orchestrator/condition';
|
|
7
7
|
export type { ExecuteLTOptions } from './services/orchestrator/types';
|
|
8
8
|
export { JwtAuthAdapter, createAuthMiddleware, requireAuth, requireAdmin, signToken, setAuthAdapter } from './modules/auth';
|
|
9
9
|
export * from './types';
|
package/build/index.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = void 0;
|
|
39
|
+
exports.getActivityIdentity = exports.McpEscalationStrategy = exports.DefaultEscalationStrategy = exports.escalationStrategyRegistry = exports.McpVisionServer = exports.McpTranslationServer = exports.McpServer = exports.McpClient = exports.McpService = exports.BuiltInMcpAdapter = exports.mcpRegistry = exports.defaultMaintenanceConfig = exports.maintenanceRegistry = exports.PinoLoggerAdapter = exports.loggerRegistry = exports.HoneycombTelemetryAdapter = exports.telemetryRegistry = exports.publishKnowledgeEvent = exports.publishAgentEvent = exports.publishWorkflowEvent = exports.publishActivityEvent = exports.publishEscalationEvent = exports.publishTaskEvent = exports.publishMilestoneEvent = exports.SocketIOEventAdapter = exports.InMemoryEventAdapter = exports.NatsEventAdapter = exports.eventRegistry = exports.ltConfig = exports.seedConfigTopics = exports.seedSystemTopics = exports.TopicService = exports.UserService = exports.ConfigService = exports.EscalationService = exports.TaskService = exports.setAuthAdapter = exports.signToken = exports.requireAdmin = exports.requireAuth = exports.createAuthMiddleware = exports.JwtAuthAdapter = exports.conditionLT = exports.conditional = exports.executeLT = exports.createLTActivityInterceptor = exports.createLTInterceptor = exports.registerLT = exports.midnightTheme = exports.start = void 0;
|
|
40
|
+
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = void 0;
|
|
41
41
|
const config_1 = require("./modules/config");
|
|
42
42
|
const logger_1 = require("./lib/logger");
|
|
43
43
|
const midnight_1 = require("./themes/midnight");
|
|
@@ -55,6 +55,7 @@ Object.defineProperty(exports, "createLTActivityInterceptor", { enumerable: true
|
|
|
55
55
|
var orchestrator_1 = require("./services/orchestrator");
|
|
56
56
|
Object.defineProperty(exports, "executeLT", { enumerable: true, get: function () { return orchestrator_1.executeLT; } });
|
|
57
57
|
var condition_1 = require("./services/orchestrator/condition");
|
|
58
|
+
Object.defineProperty(exports, "conditional", { enumerable: true, get: function () { return condition_1.conditional; } });
|
|
58
59
|
Object.defineProperty(exports, "conditionLT", { enumerable: true, get: function () { return condition_1.conditionLT; } });
|
|
59
60
|
var auth_1 = require("./modules/auth");
|
|
60
61
|
Object.defineProperty(exports, "JwtAuthAdapter", { enumerable: true, get: function () { return auth_1.JwtAuthAdapter; } });
|
|
@@ -17,6 +17,9 @@ export declare function listEscalations(opts: ListOptions): Promise<void>;
|
|
|
17
17
|
export declare function getEscalation(id: string, opts: {
|
|
18
18
|
json?: boolean;
|
|
19
19
|
}): Promise<void>;
|
|
20
|
+
export declare function getLookups(id: string, opts: {
|
|
21
|
+
json?: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
20
23
|
export declare function claimEscalation(id: string, opts: {
|
|
21
24
|
duration?: string;
|
|
22
25
|
}): Promise<void>;
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.listEscalations = listEscalations;
|
|
7
7
|
exports.getEscalation = getEscalation;
|
|
8
|
+
exports.getLookups = getLookups;
|
|
8
9
|
exports.claimEscalation = claimEscalation;
|
|
9
10
|
exports.releaseEscalation = releaseEscalation;
|
|
10
11
|
exports.resolveEscalation = resolveEscalation;
|
|
@@ -72,6 +73,30 @@ async function getEscalation(id, opts) {
|
|
|
72
73
|
console.log(` Created: ${(0, format_1.formatTime)(data.created_at)} Updated: ${(0, format_1.formatTime)(data.updated_at)}`);
|
|
73
74
|
console.log();
|
|
74
75
|
}
|
|
76
|
+
async function getLookups(id, opts) {
|
|
77
|
+
const data = await (0, client_1.apiFetch)(`/escalations/${id}/lookups`);
|
|
78
|
+
if (opts.json) {
|
|
79
|
+
console.log(JSON.stringify(data, null, 2));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const lookups = data.lookups ?? [];
|
|
83
|
+
if (lookups.length === 0) {
|
|
84
|
+
console.log(picocolors_1.default.dim('\n No lookup refs on this escalation.\n'));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log();
|
|
88
|
+
for (const l of lookups) {
|
|
89
|
+
const label = `${l.domain}/${l.key} v${l.version}${l.as ? ` (as ${l.as})` : ''}`;
|
|
90
|
+
if (l.missing) {
|
|
91
|
+
console.log(` ${picocolors_1.default.yellow('missing')} ${picocolors_1.default.bold(label)}`);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(` ${picocolors_1.default.green('✓')} ${picocolors_1.default.bold(label)}`);
|
|
95
|
+
console.log(` ${JSON.stringify(l.data)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
console.log();
|
|
99
|
+
}
|
|
75
100
|
async function claimEscalation(id, opts) {
|
|
76
101
|
const body = {};
|
|
77
102
|
if (opts.duration)
|
|
@@ -10,6 +10,11 @@ export declare function listEntries(domain: string, opts: {
|
|
|
10
10
|
}): Promise<void>;
|
|
11
11
|
export declare function getEntry(domain: string, key: string, opts: {
|
|
12
12
|
json?: boolean;
|
|
13
|
+
version?: string;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare function listVersions(domain: string, key: string, opts: {
|
|
16
|
+
json?: boolean;
|
|
17
|
+
quiet?: boolean;
|
|
13
18
|
}): Promise<void>;
|
|
14
19
|
export declare function setField(domain: string, key: string, path: string, value: string, opts: {
|
|
15
20
|
json?: boolean;
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.listDomains = listDomains;
|
|
7
7
|
exports.listEntries = listEntries;
|
|
8
8
|
exports.getEntry = getEntry;
|
|
9
|
+
exports.listVersions = listVersions;
|
|
9
10
|
exports.setField = setField;
|
|
10
11
|
exports.removeField = removeField;
|
|
11
12
|
exports.deleteEntry = deleteEntry;
|
|
@@ -42,6 +43,8 @@ async function listEntries(domain, opts) {
|
|
|
42
43
|
}
|
|
43
44
|
async function getEntry(domain, key, opts) {
|
|
44
45
|
const params = new URLSearchParams({ domain, key });
|
|
46
|
+
if (opts.version)
|
|
47
|
+
params.set('version', opts.version);
|
|
45
48
|
const data = await (0, client_1.apiFetch)(`/knowledge/entry?${params}`);
|
|
46
49
|
if (opts.json) {
|
|
47
50
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -51,13 +54,25 @@ async function getEntry(domain, key, opts) {
|
|
|
51
54
|
console.log(picocolors_1.default.yellow(`\n Not found: ${domain}/${key}\n`));
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
|
-
|
|
57
|
+
const versionLabel = data.version ?? data.current_version;
|
|
58
|
+
console.log(`\n ${picocolors_1.default.bold(`${domain}/${key}`)}${versionLabel != null ? ` ${picocolors_1.default.dim(`v${versionLabel}`)}` : ''} ${data.id ? picocolors_1.default.dim(data.id) : ''}`);
|
|
55
59
|
if (data.tags?.length)
|
|
56
60
|
console.log(` Tags: ${data.tags.join(', ')}`);
|
|
57
|
-
console.log(` Updated: ${(0, format_1.formatTime)(data.updated_at)}\n`);
|
|
61
|
+
console.log(` Updated: ${(0, format_1.formatTime)(data.updated_at ?? data.created_at)}\n`);
|
|
58
62
|
console.log(JSON.stringify(data.data, null, 2));
|
|
59
63
|
console.log();
|
|
60
64
|
}
|
|
65
|
+
const VERSION_COLUMNS = [
|
|
66
|
+
{ key: 'version', label: 'Version', width: 8, align: 'right' },
|
|
67
|
+
{ key: 'is_current', label: 'Current', width: 8, format: (v) => (v ? '●' : '') },
|
|
68
|
+
{ key: 'change_summary', label: 'Summary', width: 32, format: (v) => v ?? '' },
|
|
69
|
+
{ key: 'created_at', label: 'Created', width: 12, format: format_1.formatTime },
|
|
70
|
+
];
|
|
71
|
+
async function listVersions(domain, key, opts) {
|
|
72
|
+
const params = new URLSearchParams({ domain, key });
|
|
73
|
+
const data = await (0, client_1.apiFetch)(`/knowledge/entry/versions?${params}`);
|
|
74
|
+
(0, format_1.output)(data, data.versions || [], VERSION_COLUMNS, opts, 'version');
|
|
75
|
+
}
|
|
61
76
|
async function setField(domain, key, path, value, opts) {
|
|
62
77
|
// Try to parse as JSON, fall back to string
|
|
63
78
|
let parsed = value;
|
package/build/lib/cli/scanner.js
CHANGED
|
@@ -89,6 +89,8 @@ function extractPrimitives(source) {
|
|
|
89
89
|
primitives.push(p);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
+
if (/\bconditional\s*[<(]/.test(source) && !seen.has('conditional'))
|
|
93
|
+
primitives.push('conditional');
|
|
92
94
|
if (/conditionLT/.test(source) && !seen.has('conditionLT'))
|
|
93
95
|
primitives.push('conditionLT');
|
|
94
96
|
if (/executeLT/.test(source) && !seen.has('executeLT'))
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- Migration 033: Versioned knowledge entries.
|
|
2
|
+
--
|
|
3
|
+
-- Every knowledge entry carries a current_version counter, and every write
|
|
4
|
+
-- that changes `data` snapshots the new edition into lt_knowledge_versions
|
|
5
|
+
-- (same pattern as lt_role_schemas). Snapshots are immutable: escalation
|
|
6
|
+
-- lookup refs pin {domain, key, version} and always resolve to the exact
|
|
7
|
+
-- edition the workflow was written against.
|
|
8
|
+
--
|
|
9
|
+
-- ON DELETE CASCADE is deliberate: a delete-then-recreate restarts the entry
|
|
10
|
+
-- at version 1, and stale snapshots must not misattribute the old entry's
|
|
11
|
+
-- data to the new lineage. A pinned ref to a deleted entry fails visible
|
|
12
|
+
-- (missing) rather than resolving to the wrong list.
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS lt_knowledge_versions (
|
|
15
|
+
domain TEXT NOT NULL,
|
|
16
|
+
key TEXT NOT NULL,
|
|
17
|
+
version INTEGER NOT NULL,
|
|
18
|
+
data JSONB NOT NULL DEFAULT '{}',
|
|
19
|
+
tags TEXT[] NOT NULL DEFAULT '{}',
|
|
20
|
+
change_summary TEXT,
|
|
21
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
22
|
+
PRIMARY KEY (domain, key, version),
|
|
23
|
+
FOREIGN KEY (domain, key) REFERENCES lt_knowledge (domain, key) ON DELETE CASCADE
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
ALTER TABLE lt_knowledge
|
|
27
|
+
ADD COLUMN IF NOT EXISTS current_version INTEGER NOT NULL DEFAULT 1;
|
|
28
|
+
|
|
29
|
+
-- Backfill: every existing entry becomes version 1 of its lineage.
|
|
30
|
+
INSERT INTO lt_knowledge_versions (domain, key, version, data, tags)
|
|
31
|
+
SELECT domain, key, current_version, data, tags
|
|
32
|
+
FROM lt_knowledge
|
|
33
|
+
ON CONFLICT (domain, key, version) DO NOTHING;
|
|
@@ -57,6 +57,16 @@ function registerSingleRoutes(router) {
|
|
|
57
57
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
58
58
|
});
|
|
59
59
|
// -- Parameterized routes (must come after literal paths) --
|
|
60
|
+
/**
|
|
61
|
+
* GET /api/escalations/:id/lookups
|
|
62
|
+
* Resolve the escalation's versioned knowledge lookups. The refs on the row
|
|
63
|
+
* are the grant: readers of the escalation may fetch exactly the pinned
|
|
64
|
+
* editions it names.
|
|
65
|
+
*/
|
|
66
|
+
router.get('/:id/lookups', async (req, res) => {
|
|
67
|
+
const result = await api.getEscalationLookups({ id: req.params.id }, req.auth);
|
|
68
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
69
|
+
});
|
|
60
70
|
/**
|
|
61
71
|
* GET /api/escalations/:id
|
|
62
72
|
* Get a single escalation by ID.
|