@hotmeshio/long-tail 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build/api/escalations/accumulate.d.ts +96 -0
- package/build/api/escalations/accumulate.js +516 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +10 -1
- package/build/api/roles.d.ts +4 -5
- package/build/api/roles.js +53 -4
- package/build/api/scan-codes/execute.js +2 -0
- package/build/api/scan-codes/verbs.d.ts +15 -0
- package/build/api/scan-codes/verbs.js +65 -0
- package/build/index.js +60 -0
- package/build/lib/db/schemas/036_role_portals.sql +12 -0
- package/build/routes/escalations/accumulate.d.ts +7 -0
- package/build/routes/escalations/accumulate.js +150 -0
- package/build/routes/escalations/index.js +5 -0
- package/build/sdk/index.d.ts +25 -0
- package/build/sdk/index.js +8 -0
- package/build/services/escalation/accumulate.d.ts +81 -0
- package/build/services/escalation/accumulate.js +154 -0
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +1 -0
- package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
- package/build/services/orchestrator/condition.d.ts +40 -3
- package/build/services/orchestrator/condition.js +42 -2
- package/build/services/role/index.js +1 -0
- package/build/services/role/seed.js +6 -1
- package/build/services/role/sql.d.ts +6 -3
- package/build/services/role/sql.js +7 -2
- package/build/services/role/types.d.ts +38 -10
- package/build/services/role/types.js +10 -1
- package/build/services/scan-code/validate.js +16 -0
- package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
- package/build/shared/form-validation/display-only-widgets.js +25 -0
- package/build/shared/form-validation/index.d.ts +2 -0
- package/build/shared/form-validation/index.js +2 -0
- package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
- package/build/shared/form-validation/x-lt-bind.js +12 -8
- package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
- package/build/shared/form-validation/x-lt-invoke.js +103 -0
- package/build/system/mcp-servers/admin/escalations.js +39 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +192 -13
- package/build/system/mcp-servers/admin/schemas.js +39 -3
- package/build/system/mcp-servers/admin/users.js +1 -0
- package/build/system/mcp-servers/docs.js +4 -0
- package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
- package/build/system/mcp-servers/human-queue-schemas.js +19 -1
- package/build/system/mcp-servers/human-queue.d.ts +2 -0
- package/build/system/mcp-servers/human-queue.js +77 -0
- package/build/system/seed/tool-manifests-admin.d.ts +922 -103
- package/build/system/seed/tool-manifests-admin.js +4 -1
- package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
- package/build/system/seed/tool-manifests-escalation.js +56 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +52 -0
- package/build/types/escalation.js +29 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.js +3 -1
- package/build/types/scan-code.d.ts +24 -0
- package/build/types/scan-code.js +9 -0
- package/build/types/startup.d.ts +20 -0
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-uarpHB88.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-uarpHB88.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-BcUaDD5E.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-BcUaDD5E.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-BaZBhK6i.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-BaZBhK6i.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage-CuVFSDc4.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage-CuVFSDc4.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-CClMby6B.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-CClMby6B.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-BL8FRgkN.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BL8FRgkN.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-D53ogPor.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-D53ogPor.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-ow8jpbtD.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-ow8jpbtD.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-CeEDt9iJ.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-CeEDt9iJ.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-CSqyZMCG.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-CSqyZMCG.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-Dx7SxA23.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-Dx7SxA23.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-LYPxpvNN.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-LYPxpvNN.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
- package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BZJTSm9N.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BZJTSm9N.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-0wIIW2en.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-0wIIW2en.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-CoYvtMzj.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-CoYvtMzj.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListView-DWFHPufv.js +2 -0
- package/dashboard/dist/assets/EscalationListView-DWFHPufv.js.map +1 -0
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-C9Xu_A25.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-C9Xu_A25.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js.map +1 -0
- package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js +2 -0
- package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js.map +1 -0
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-CW57FaP9.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-CW57FaP9.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-D1ctWhKf.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-D1ctWhKf.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-C-iur-Nj.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-C-iur-Nj.js.map} +1 -1
- package/dashboard/dist/assets/GraphInvokePage-CcA_44M4.js +2 -0
- package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-CcA_44M4.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-Dc085ghJ.js +2 -0
- package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-Dc085ghJ.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-h_ziBt4O.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-h_ziBt4O.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-qXXhbNWV.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-qXXhbNWV.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-SEzSbZrd.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-SEzSbZrd.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-Cy0V0kv9.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-Cy0V0kv9.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-DjJO5vSb.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-DjJO5vSb.js.map} +1 -1
- package/dashboard/dist/assets/McpRunsPage-BfjiJ8mM.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-BfjiJ8mM.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-dJcER0T_.js +3 -0
- package/dashboard/dist/assets/OperationsPage-dJcER0T_.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-zCkW4eqk.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-zCkW4eqk.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-Cx6L3Jvu.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-Cx6L3Jvu.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-DOgGUlJl.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-DOgGUlJl.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js +2 -0
- package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BFcFSDUv.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BFcFSDUv.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-BaHV2cXp.js +2 -0
- package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BaHV2cXp.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js +7 -0
- package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-DSqqKPbv.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-DSqqKPbv.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-B29iWwel.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-B29iWwel.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-S8aAJfnC.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js.map → ScanCodesPage-S8aAJfnC.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js → ScanSchemeDetailPage-CUBRAtmJ.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js.map → ScanSchemeDetailPage-CUBRAtmJ.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-R9t1-CeQ.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-R9t1-CeQ.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-CkW_A507.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-CkW_A507.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-yzWX0wac.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-yzWX0wac.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-Cf4DXFxj.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-Cf4DXFxj.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-DCDcEps9.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-DCDcEps9.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
- package/dashboard/dist/assets/TasksListPage-BBATgpf7.js +2 -0
- package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-BBATgpf7.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-CSNVEjch.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-CSNVEjch.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-Du1nBrPn.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-Du1nBrPn.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-CF-h_5Rg.js +2 -0
- package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-CF-h_5Rg.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-Dr1UmWcp.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-Dr1UmWcp.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-CUUo-Ylf.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-CUUo-Ylf.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-kBh1dc39.js} +2 -2
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-kBh1dc39.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-CCRSbnDx.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-CCRSbnDx.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-BNQVvyek.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-BNQVvyek.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-DswubNJN.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-DswubNJN.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-Cw9Dlmup.js} +11 -11
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-Cw9Dlmup.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-DB8xnIXy.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-DB8xnIXy.js.map} +1 -1
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-BwEnf6N9.js} +2 -2
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-BwEnf6N9.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B97itB3I.js → bots-CCmJTT2u.js} +2 -2
- package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-CCmJTT2u.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-BZHgp_nh.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-BZHgp_nh.js.map} +1 -1
- package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
- package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CyfwUlFA.js} +2 -2
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CyfwUlFA.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js +2 -0
- package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js.map +1 -0
- package/dashboard/dist/assets/index-3gbd5neL.js +67 -0
- package/dashboard/dist/assets/index-3gbd5neL.js.map +1 -0
- package/dashboard/dist/assets/index-BAAVTyZ-.js +2 -0
- package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-BAAVTyZ-.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9BBCqLI.js → index-BC6Jenlo.js} +2 -2
- package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-BC6Jenlo.js.map} +1 -1
- package/dashboard/dist/assets/index-C7KHqOTQ.js +2 -0
- package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-C7KHqOTQ.js.map} +1 -1
- package/dashboard/dist/assets/index-CDrqqbSR.js +3 -0
- package/dashboard/dist/assets/index-CDrqqbSR.js.map +1 -0
- package/dashboard/dist/assets/index-CVwzCZ43.js +2 -0
- package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-CVwzCZ43.js.map} +1 -1
- package/dashboard/dist/assets/index-CaGF6TCC.js +2 -0
- package/dashboard/dist/assets/index-CaGF6TCC.js.map +1 -0
- package/dashboard/dist/assets/index-ClVbfe4z.js +13 -0
- package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-ClVbfe4z.js.map} +1 -1
- package/dashboard/dist/assets/{index-DMeaiKgf.js → index-CuVkSmj5.js} +2 -2
- package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-CuVkSmj5.js.map} +1 -1
- package/dashboard/dist/assets/{index-ipqwPavs.js → index-DAuX_PlL.js} +2 -2
- package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-DAuX_PlL.js.map} +1 -1
- package/dashboard/dist/assets/{index-CIpHj4di.js → index-DBWS5QL8.js} +2 -2
- package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DBWS5QL8.js.map} +1 -1
- package/dashboard/dist/assets/index-DIWCI6HC.js +2 -0
- package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-DIWCI6HC.js.map} +1 -1
- package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DZ8X_Gp4.js} +2 -2
- package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DZ8X_Gp4.js.map} +1 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CqyLhUMg.js} +2 -2
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CqyLhUMg.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Cvu6bFYH.js} +2 -2
- package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Cvu6bFYH.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-qC6A3e9l.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-qC6A3e9l.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
- package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-BKN_lJuV.js} +2 -2
- package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-BKN_lJuV.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-BldIfv85.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-BldIfv85.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-B-Uay8uL.js} +2 -2
- package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-B-Uay8uL.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics-438EQogt.js} +2 -2
- package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics-438EQogt.js.map} +1 -1
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Cw8hYZ8y.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Cw8hYZ8y.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-D1218GQ8.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-D1218GQ8.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-BAQf_y_U.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-BAQf_y_U.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-CN01gEB0.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-CN01gEB0.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +113 -0
- package/docs/api/http/escalations.md +89 -0
- package/docs/api/http/roles.md +1 -0
- package/docs/api/sdk/escalations.md +91 -0
- package/docs/api/sdk/roles.md +2 -0
- package/docs/architecture.md +1 -1
- package/docs/code-owned-configuration.md +2 -1
- package/docs/dashboard.md +10 -4
- package/docs/hitl/design.md +1 -1
- package/docs/hitl/escalation.md +37 -1
- package/docs/hitl/invoke-form.md +4 -0
- package/docs/hitl/pinned-views.md +4 -0
- package/docs/hitl/portal.md +97 -0
- package/docs/hitl/resolution.md +41 -0
- package/docs/hitl/x-lt-embed.md +1 -1
- package/docs/hitl/x-lt-invoke.md +95 -0
- package/docs/hitl/x-lt-list-schema.md +3 -1
- package/docs/hitl/x-lt-widget.md +1 -0
- package/docs/hitl-guide.md +8 -1
- package/docs/scan-codes.md +15 -2
- package/docs/sdk.md +1 -1
- package/docs/workflows.md +2 -2
- package/package.json +4 -2
- package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
- package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
- package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
- package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
- package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
- package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
- package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
- package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
- package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
- package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
- package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
- package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
- package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
- package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
- package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
- package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
- package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
- package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
- package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
- package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
- package/docs/compilation.md +0 -152
- package/docs/compiler.md +0 -311
- package/docs/contributing.md +0 -56
- package/docs/design-principles.md +0 -245
- package/docs/schema-exchange.md +0 -173
- package/docs/self-test.md +0 -106
- package/docs/story.md +0 -184
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolver-payload-m9AGKZ3a.js","sources":["../../../types/validation.ts","../../src/components/escalation/ErrorsPanel.tsx","../../../shared/form-validation/x-lt-require-any.ts","../../../shared/form-validation/x-lt-require-sum.ts","../../../shared/form-validation/validate-resolver-payload.ts","../../src/lib/resolver-payload.ts"],"sourcesContent":["/**\n * Canonical validation-error shapes — one vocabulary across every surface.\n *\n * When server-side resolver schema enforcement rejects a payload, the API\n * layer returns status 422 with `LTValidationErrorBody` as the response body.\n * The same body shape flows to every consumer:\n * - HTTP routes serialize it as the JSON response body\n * - SDK callers receive it as `result.data` (with `result.code` set)\n * - MCP resolve tools return it as the tool's JSON error content\n * - the CLI prints the violation list beneath the error line\n * - the dashboard maps `violations` into the same errors panel the\n * pre-submission pass feeds\n */\n\n/** Machine-readable error codes carried on error envelopes and bodies. */\nexport const LT_ERROR_CODES = {\n /** The resolver payload failed the role's enforced form schema. */\n SCHEMA_VALIDATION: 'schema_validation',\n} as const;\n\nexport type LTErrorCode = (typeof LT_ERROR_CODES)[keyof typeof LT_ERROR_CODES];\n\n/**\n * One field-level violation — the same `{ field, message }` pair the dashboard\n * validation panel renders. Bulk surfaces add `escalationId` so a violation is\n * attributable to the row that produced it.\n */\nexport interface LTFieldViolation {\n field: string;\n message: string;\n escalationId?: string;\n}\n\n/** The 422 response body for a schema-validation rejection. */\nexport interface LTValidationErrorBody {\n /** Human-readable summary, e.g. \"resolverPayload failed schema validation (2 violations)\". */\n error: string;\n code: typeof LT_ERROR_CODES.SCHEMA_VALIDATION;\n /** Every field-level violation, in schema property order. */\n violations: LTFieldViolation[];\n /** The role whose enforced schema rejected the payload; null for a workflow input schema. */\n role: string | null;\n /** The schema version validated against; null when the role's live (unversioned) schema applied. */\n schemaVersion: number | null;\n /** The workflow whose input_schema rejected the data (invoke surface only). */\n workflowType?: string;\n}\n\n/** Narrow an unknown response body to the canonical validation-error shape. */\nexport function isValidationErrorBody(body: unknown): body is LTValidationErrorBody {\n return (\n typeof body === 'object' && body !== null\n && (body as Record<string, unknown>).code === LT_ERROR_CODES.SCHEMA_VALIDATION\n && Array.isArray((body as Record<string, unknown>).violations)\n );\n}\n","import { AlertCircle } from 'lucide-react';\nimport { deriveFieldLabel } from '../../lib/derive-field-label';\nimport type { FieldError } from '../../lib/field-validator';\n\n/**\n * The form's issue list. Each row names the field through its schema title\n * and, on click, scrolls to and focuses the input carrying that\n * data-field-key. Shared by the escalation side panel and the invoke panel.\n */\nexport function ErrorsPanel({ errors, schema }: { errors: FieldError[]; schema?: Record<string, unknown> | null }) {\n const focusField = (field: string) => {\n const el = document.querySelector<HTMLElement>(`[data-field-key=\"${field}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.focus({ preventScroll: true });\n };\n\n if (errors.length === 0) {\n return <p className=\"text-xs text-text-tertiary italic\">No errors to display.</p>;\n }\n\n return (\n <div className=\"space-y-1\" role=\"alert\" aria-live=\"polite\">\n <p className=\"text-2xs font-semibold uppercase tracking-wider text-status-error mb-4\">\n {errors.length} {errors.length === 1 ? 'issue' : 'issues'} to resolve\n </p>\n <div className=\"space-y-1.5\">\n {errors.map(({ field, message }) => (\n <button\n key={field}\n onClick={() => focusField(field)}\n className=\"w-full text-left flex items-start gap-3 px-3 py-2.5 rounded hover:bg-status-error/5 transition-colors group\"\n >\n <AlertCircle className=\"w-3.5 h-3.5 mt-0.5 shrink-0 text-status-error/60 group-hover:text-status-error transition-colors\" />\n <div>\n <p className=\"text-2xs font-semibold text-text-primary leading-snug\">\n {deriveFieldLabel(field, (schema?.properties as Record<string, Record<string, unknown>> | undefined)?.[field])}\n </p>\n <p className=\"text-2xs text-text-tertiary group-hover:text-text-secondary transition-colors leading-snug mt-0.5\">\n {message}\n </p>\n </div>\n </button>\n ))}\n </div>\n <p className=\"text-2xs text-text-quaternary mt-4 px-3\">\n Click an issue to scroll to and focus the field.\n </p>\n </div>\n );\n}\n","/**\n * x-lt-require-any — \"at least one of this set\" as a root-schema token. A\n * form_schema declares groups of field names; a submission passes when every\n * group has a value in at least one member. The canonical case: a Left\n * quantity and a Right quantity where either satisfies, but blank-both fails.\n *\n * x-lt-require-any string[][] — e.g. [[\"left_quantity\", \"right_quantity\"]]\n *\n * Visibility rules compose: a member hidden by its `x-lt-showIf` (or naming\n * no schema property) can neither satisfy the group nor be demanded of the\n * submitter, and a group whose members are ALL hidden is waived. `false` and\n * `0` are answers; `''`, null, and undefined are not.\n */\n\nexport const X_LT_REQUIRE_ANY = 'x-lt-require-any';\n\n/**\n * The schema's require-any groups. Malformed declarations (non-array token,\n * non-array groups, non-string members) read as no groups — a bad token never\n * bricks submission.\n */\nexport function readRequireAnyGroups(\n schema: Record<string, unknown> | null | undefined,\n): string[][] {\n const raw = schema?.[X_LT_REQUIRE_ANY];\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((group): group is unknown[] => Array.isArray(group))\n .map((group) => group.filter((m): m is string => typeof m === 'string' && m.length > 0))\n .filter((group) => group.length > 0);\n}\n\n/** Present = an actual answer: `false` and `0` count; `''`/null/undefined do not. */\nexport function hasRequireAnyValue(value: unknown): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n return true;\n}\n","/**\n * x-lt-require-sum — \"these quantities must total at least N\" as a\n * root-schema token. Where x-lt-require-any asks that one member carry any\n * answer (so a count defaulting to `0` vacuously satisfies it), require-sum\n * reads the members as numbers and demands their sum reach a minimum. The\n * canonical case: a Left quantity and a Right quantity that both default to\n * `0`, where at least one side must be positive.\n *\n * x-lt-require-sum { fields: string[], minimum?: number }[]\n * — e.g. [{ \"fields\": [\"left_quantity\", \"right_quantity\"] }]\n *\n * `minimum` defaults to 1. Numbers contribute their value and numeric strings\n * coerce (the same reading as dynamic bounds); everything else contributes 0.\n * Visibility rules compose the same way as require-any: a member hidden by\n * its `x-lt-showIf` (or naming no schema property) contributes nothing and is\n * not demanded, and a group whose members are ALL hidden is waived.\n */\n\nexport const X_LT_REQUIRE_SUM = 'x-lt-require-sum';\n\nexport interface RequireSumGroup {\n fields: string[];\n minimum: number;\n}\n\n/**\n * The schema's require-sum groups. Malformed declarations (non-array token,\n * groups without a fields array, non-string members, non-numeric minimum)\n * read as no groups — a bad token never bricks submission.\n */\nexport function readRequireSumGroups(\n schema: Record<string, unknown> | null | undefined,\n): RequireSumGroup[] {\n const raw = schema?.[X_LT_REQUIRE_SUM];\n if (!Array.isArray(raw)) return [];\n const groups: RequireSumGroup[] = [];\n for (const entry of raw) {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;\n const { fields, minimum } = entry as Record<string, unknown>;\n if (!Array.isArray(fields)) continue;\n const members = fields.filter((m): m is string => typeof m === 'string' && m.length > 0);\n if (members.length === 0) continue;\n if (minimum !== undefined && typeof minimum !== 'number') continue;\n groups.push({ fields: members, minimum: typeof minimum === 'number' ? minimum : 1 });\n }\n return groups;\n}\n\n/** A member's numeric contribution: numbers as-is, numeric strings coerced, all else 0. */\nexport function requireSumContribution(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value.trim() !== '') {\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n }\n return 0;\n}\n","/**\n * The full pre-submission validation pass over a resolver form schema — the\n * same pass on both sides of the wire. The dashboard runs it on the flat form\n * values before submitting; the API layer runs it on the submitted (bound,\n * nested) payload by inverting x-lt-bind first. Because both entry points\n * funnel into one loop, a payload that passes the client panel passes the\n * server gate, and a 422's violation list is exactly what the panel shows.\n *\n * Semantics per field:\n * - x-lt-showIf-hidden fields are skipped entirely (a field the submitter\n * cannot see never blocks submission)\n * - required (schema.required membership), with checklist/empty-object rules\n * - declared-type check (string/number/integer/boolean/array/object)\n * - enum membership\n * - x-lt-require-all against the checklist items resolved from context\n * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)\n *\n * Root-level x-lt-require-any groups run after the per-field pass: each group\n * needs a value in at least one visible member (all-hidden groups are waived).\n * x-lt-require-sum groups follow the same visibility rules but read members\n * as numbers: the group's visible members must sum to at least its minimum.\n *\n * The showIf/`resolver.*` domain is always the FLAT form representation, so a\n * condition like `resolver.approved` reads the same on both sides.\n */\nimport { type FieldError, validateField } from './field-validator';\nimport { evaluateShowIf, type ShowIfContext } from './x-lt-show-if';\nimport { mapPayloadToForm } from './x-lt-bind';\nimport { readRequireAnyGroups, hasRequireAnyValue } from './x-lt-require-any';\nimport { readRequireSumGroups, requireSumContribution } from './x-lt-require-sum';\n\nexport type { FieldError } from './field-validator';\n\n/**\n * The escalation-surface context the pass evaluates showIf conditions and\n * dynamic constraints against. `resolver` is supplied by the pass itself\n * (the flat form values under validation) — callers provide the rest.\n */\nexport type ResolverValidationContext = Omit<ShowIfContext, 'resolver' | 'input'>;\n\n/**\n * Validate FLAT form values against the form schema. This is the dashboard's\n * entry point (the values the user edits, keyed by field name).\n */\nexport function validateResolverForm(\n schema: Record<string, unknown> | null | undefined,\n formValues: Record<string, unknown>,\n ctx?: ResolverValidationContext | null,\n): FieldError[] {\n if (!schema) return [];\n const properties = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[] | undefined) ?? []);\n const liveCtx: ShowIfContext = {\n ...(ctx ?? {}),\n resolver: formValues as Record<string, unknown>,\n input: formValues as Record<string, unknown>,\n };\n\n const errors: FieldError[] = [];\n for (const [field, fieldSchema] of Object.entries(properties)) {\n if (!evaluateShowIf(fieldSchema['x-lt-showIf'], liveCtx)) continue;\n const err = validateField(\n formValues[field],\n fieldSchema,\n required.has(field),\n true,\n liveCtx as Record<string, unknown>,\n );\n if (err) errors.push({ field, message: err });\n }\n\n // Require-any groups: at least one VISIBLE member per group carries a value.\n // A member hidden by showIf (or naming no property) can neither satisfy nor\n // be demanded; an all-hidden group is waived.\n for (const group of readRequireAnyGroups(schema)) {\n const visible = group.filter(\n (k) => properties[k] && evaluateShowIf(properties[k]['x-lt-showIf'], liveCtx),\n );\n if (visible.length === 0) continue;\n if (visible.some((k) => hasRequireAnyValue(formValues[k]))) continue;\n const titles = visible.map((k) => (properties[k].title as string | undefined) ?? k);\n errors.push({\n field: visible[0],\n message: `Enter a value for at least one of: ${titles.join(', ')}`,\n });\n }\n\n // Require-sum groups: the numeric values of VISIBLE members must total at\n // least the group's minimum. A `0` is a real number here — unlike\n // require-any, defaulted-zero quantities do not satisfy the group.\n for (const group of readRequireSumGroups(schema)) {\n const visible = group.fields.filter(\n (k) => properties[k] && evaluateShowIf(properties[k]['x-lt-showIf'], liveCtx),\n );\n if (visible.length === 0) continue;\n const total = visible.reduce((sum, k) => sum + requireSumContribution(formValues[k]), 0);\n if (total >= group.minimum) continue;\n const titles = visible.map((k) => (properties[k].title as string | undefined) ?? k);\n errors.push({\n field: visible[0],\n message: `Combined value of ${titles.join(', ')} must be at least ${group.minimum}`,\n });\n }\n return errors;\n}\n\n/**\n * Validate a SUBMITTED resolver payload (the bound, nested shape the workflow\n * consumes) against the form schema. This is the API layer's entry point: the\n * payload is inverted through each field's x-lt-bind path back to the flat\n * form representation, then run through the same pass the client uses.\n */\nexport function validateResolverPayload(\n schema: Record<string, unknown> | null | undefined,\n payload: Record<string, unknown>,\n ctx?: ResolverValidationContext | null,\n): FieldError[] {\n if (!schema) return [];\n const formValues = mapPayloadToForm(payload, schema as Record<string, any>);\n return validateResolverForm(schema, formValues, ctx);\n}\n","import { mapFormToPayload } from './x-lt-bind';\nimport { validateResolverForm, type FieldError } from './field-validator';\nimport type { ShowIfContext } from './x-lt-show-if';\n\nexport interface ResolverPayloadResult {\n /** The resolver payload ready to submit — null when the JSON is unparseable or validation failed. */\n payload: Record<string, unknown> | null;\n /** Field errors against the embedded _form_schema (empty when the form is valid). */\n errors: FieldError[];\n /** Set when the edited JSON string itself is malformed. */\n parseError: string | null;\n}\n\n/**\n * Build the resolver payload from the form's edited JSON string.\n *\n * 1. Parse the JSON — a malformed string yields `parseError`.\n * 2. Validate every visible field against the embedded `_form_schema` — hidden\n * fields (x-lt-showIf falsy against the live context) are skipped, matching\n * the server's enforcement pass. Any failures yield `errors`.\n * 3. Strip the UI-only schema and map flat form fields into their nested shape\n * via x-lt-bind — the payload IS the payload.\n *\n * The single path shared by the footer's Submit button and the submit-on-claim\n * shortcut, so both produce identical payloads and identical error lists.\n */\nexport function buildResolverPayload(\n json: string,\n context?: ShowIfContext,\n): ResolverPayloadResult {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(json) as Record<string, unknown>;\n } catch {\n return { payload: null, errors: [], parseError: 'Invalid JSON' };\n }\n\n const schema = parsed._form_schema as Record<string, unknown> | undefined;\n if (schema) {\n const errors = validateResolverForm(schema, parsed, context);\n if (errors.length > 0) return { payload: null, errors, parseError: null };\n }\n\n const { _form_schema, ...formValues } = parsed;\n return {\n payload: mapFormToPayload(formValues, schema as Record<string, any> | undefined),\n errors: [],\n parseError: null,\n };\n}\n"],"names":["LT_ERROR_CODES","isValidationErrorBody","body","ErrorsPanel","errors","schema","focusField","field","el","jsx","jsxs","message","AlertCircle","deriveFieldLabel","_a","X_LT_REQUIRE_ANY","readRequireAnyGroups","raw","group","m","hasRequireAnyValue","value","X_LT_REQUIRE_SUM","readRequireSumGroups","groups","entry","fields","minimum","members","requireSumContribution","n","validateResolverForm","formValues","ctx","properties","required","liveCtx","fieldSchema","evaluateShowIf","err","validateField","visible","k","titles","sum","buildResolverPayload","json","context","parsed","_form_schema","mapFormToPayload"],"mappings":"iNAeO,MAAMA,EAAiB,CAE5B,kBAAmB,mBACrB,EA+BO,SAASC,EAAsBC,EAA8C,CAClF,OACE,OAAOA,GAAS,UAAYA,IAAS,MACjCA,EAAiC,OAASF,EAAe,mBAC1D,MAAM,QAASE,EAAiC,UAAU,CAEjE,CC9CO,SAASC,EAAY,CAAE,OAAAC,EAAQ,OAAAC,GAA6E,CACjH,MAAMC,EAAcC,GAAkB,CACpC,MAAMC,EAAK,SAAS,cAA2B,oBAAoBD,CAAK,IAAI,EACvEC,IACLA,EAAG,eAAe,CAAE,SAAU,SAAU,MAAO,SAAU,EACzDA,EAAG,MAAM,CAAE,cAAe,EAAA,CAAM,EAClC,EAEA,OAAIJ,EAAO,SAAW,EACbK,EAAAA,IAAC,IAAA,CAAE,UAAU,oCAAoC,SAAA,wBAAqB,SAI5E,MAAA,CAAI,UAAU,YAAY,KAAK,QAAQ,YAAU,SAChD,SAAA,CAAAC,EAAAA,KAAC,IAAA,CAAE,UAAU,yEACV,SAAA,CAAAN,EAAO,OAAO,IAAEA,EAAO,SAAW,EAAI,QAAU,SAAS,aAAA,EAC5D,EACAK,EAAAA,IAAC,MAAA,CAAI,UAAU,cACZ,SAAAL,EAAO,IAAI,CAAC,CAAE,MAAAG,EAAO,QAAAI,CAAA,IAAQ,OAC5BD,OAAAA,EAAAA,KAAC,SAAA,CAEC,QAAS,IAAMJ,EAAWC,CAAK,EAC/B,UAAU,8GAEV,SAAA,CAAAE,EAAAA,IAACG,EAAA,CAAY,UAAU,kGAAA,CAAmG,SACzH,MAAA,CACC,SAAA,CAAAH,EAAAA,IAAC,IAAA,CAAE,UAAU,wDACV,SAAAI,EAAiBN,GAAQO,EAAAT,GAAA,YAAAA,EAAQ,aAAR,YAAAS,EAA6EP,EAAM,CAAA,CAC/G,EACAE,EAAAA,IAAC,IAAA,CAAE,UAAU,oGACV,SAAAE,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,EAZKJ,CAAA,EAcR,EACH,EACAE,EAAAA,IAAC,IAAA,CAAE,UAAU,0CAA0C,SAAA,kDAAA,CAEvD,CAAA,EACF,CAEJ,CCpCO,MAAMM,EAAmB,mBAOzB,SAASC,EACdX,EACY,CACZ,MAAMY,EAAMZ,GAAA,YAAAA,EAASU,GACrB,OAAK,MAAM,QAAQE,CAAG,EACfA,EACJ,OAAQC,GAA8B,MAAM,QAAQA,CAAK,CAAC,EAC1D,IAAKA,GAAUA,EAAM,OAAQC,GAAmB,OAAOA,GAAM,UAAYA,EAAE,OAAS,CAAC,CAAC,EACtF,OAAQD,GAAUA,EAAM,OAAS,CAAC,EAJL,CAAA,CAKlC,CAGO,SAASE,EAAmBC,EAAyB,CAC1D,OAA2BA,GAAU,KAAa,GAC9C,OAAOA,GAAU,SAAiBA,EAAM,KAAA,EAAO,OAAS,EACrD,EACT,CCnBO,MAAMC,EAAmB,mBAYzB,SAASC,EACdlB,EACmB,CACnB,MAAMY,EAAMZ,GAAA,YAAAA,EAASiB,GACrB,GAAI,CAAC,MAAM,QAAQL,CAAG,QAAU,CAAA,EAChC,MAAMO,EAA4B,CAAA,EAClC,UAAWC,KAASR,EAAK,CACvB,GAAI,CAACQ,GAAS,OAAOA,GAAU,UAAY,MAAM,QAAQA,CAAK,EAAG,SACjE,KAAM,CAAE,OAAAC,EAAQ,QAAAC,CAAA,EAAYF,EAC5B,GAAI,CAAC,MAAM,QAAQC,CAAM,EAAG,SAC5B,MAAME,EAAUF,EAAO,OAAQP,GAAmB,OAAOA,GAAM,UAAYA,EAAE,OAAS,CAAC,EACnFS,EAAQ,SAAW,IACnBD,IAAY,QAAa,OAAOA,GAAY,UAChDH,EAAO,KAAK,CAAE,OAAQI,EAAS,QAAS,OAAOD,GAAY,SAAWA,EAAU,EAAG,EACrF,CACA,OAAOH,CACT,CAGO,SAASK,EAAuBR,EAAwB,CAC7D,GAAI,OAAOA,GAAU,UAAY,OAAO,SAASA,CAAK,EAAG,OAAOA,EAChE,GAAI,OAAOA,GAAU,UAAYA,EAAM,KAAA,IAAW,GAAI,CACpD,MAAMS,EAAI,OAAOT,CAAK,EACtB,GAAI,CAAC,OAAO,MAAMS,CAAC,EAAG,OAAOA,CAC/B,CACA,MAAO,EACT,CCZO,SAASC,EACd1B,EACA2B,EACAC,EACc,CACd,GAAI,CAAC5B,EAAQ,MAAO,CAAA,EACpB,MAAM6B,EAAc7B,EAAO,YAAc,CAAA,EACnC8B,EAAW,IAAI,IAAK9B,EAAO,UAAqC,CAAA,CAAE,EAClE+B,EAAyB,CAC7B,GAAIH,GAAO,CAAA,EACX,SAAUD,EACV,MAAOA,CAAA,EAGH5B,EAAuB,CAAA,EAC7B,SAAW,CAACG,EAAO8B,CAAW,IAAK,OAAO,QAAQH,CAAU,EAAG,CAC7D,GAAI,CAACI,EAAeD,EAAY,aAAa,EAAGD,CAAO,EAAG,SAC1D,MAAMG,EAAMC,EACVR,EAAWzB,CAAK,EAChB8B,EACAF,EAAS,IAAI5B,CAAK,EAClB,GACA6B,CAAA,EAEEG,GAAKnC,EAAO,KAAK,CAAE,MAAAG,EAAO,QAASgC,EAAK,CAC9C,CAKA,UAAWrB,KAASF,EAAqBX,CAAM,EAAG,CAChD,MAAMoC,EAAUvB,EAAM,OACnBwB,GAAMR,EAAWQ,CAAC,GAAKJ,EAAeJ,EAAWQ,CAAC,EAAE,aAAa,EAAGN,CAAO,CAAA,EAG9E,GADIK,EAAQ,SAAW,GACnBA,EAAQ,KAAMC,GAAMtB,EAAmBY,EAAWU,CAAC,CAAC,CAAC,EAAG,SAC5D,MAAMC,EAASF,EAAQ,IAAKC,GAAOR,EAAWQ,CAAC,EAAE,OAAgCA,CAAC,EAClFtC,EAAO,KAAK,CACV,MAAOqC,EAAQ,CAAC,EAChB,QAAS,sCAAsCE,EAAO,KAAK,IAAI,CAAC,EAAA,CACjE,CACH,CAKA,UAAWzB,KAASK,EAAqBlB,CAAM,EAAG,CAChD,MAAMoC,EAAUvB,EAAM,OAAO,OAC1BwB,GAAMR,EAAWQ,CAAC,GAAKJ,EAAeJ,EAAWQ,CAAC,EAAE,aAAa,EAAGN,CAAO,CAAA,EAI9E,GAFIK,EAAQ,SAAW,GACTA,EAAQ,OAAO,CAACG,EAAKF,IAAME,EAAMf,EAAuBG,EAAWU,CAAC,CAAC,EAAG,CAAC,GAC1ExB,EAAM,QAAS,SAC5B,MAAMyB,EAASF,EAAQ,IAAKC,GAAOR,EAAWQ,CAAC,EAAE,OAAgCA,CAAC,EAClFtC,EAAO,KAAK,CACV,MAAOqC,EAAQ,CAAC,EAChB,QAAS,qBAAqBE,EAAO,KAAK,IAAI,CAAC,qBAAqBzB,EAAM,OAAO,EAAA,CAClF,CACH,CACA,OAAOd,CACT,CC9EO,SAASyC,EACdC,EACAC,EACuB,CACvB,IAAIC,EACJ,GAAI,CACFA,EAAS,KAAK,MAAMF,CAAI,CAC1B,MAAQ,CACN,MAAO,CAAE,QAAS,KAAM,OAAQ,CAAA,EAAI,WAAY,cAAA,CAClD,CAEA,MAAMzC,EAAS2C,EAAO,aACtB,GAAI3C,EAAQ,CACV,MAAMD,EAAS2B,EAAqB1B,EAAQ2C,EAAQD,CAAO,EAC3D,GAAI3C,EAAO,OAAS,EAAG,MAAO,CAAE,QAAS,KAAM,OAAAA,EAAQ,WAAY,IAAA,CACrE,CAEA,KAAM,CAAE,aAAA6C,EAAc,GAAGjB,CAAA,EAAegB,EACxC,MAAO,CACL,QAASE,EAAiBlB,EAAY3B,CAAyC,EAC/E,OAAQ,CAAA,EACR,WAAY,IAAA,CAEhB"}
|
package/docs/compilation.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# The Compilation Pipeline
|
|
2
|
-
|
|
3
|
-
Every AI-driven execution carries cost. An LLM reasons through each step, selects tools, interprets results, and decides what to do next. It works, but it is slow, non-deterministic, and consumes tokens on every run.
|
|
4
|
-
|
|
5
|
-
Long Tail records what the LLM did, extracts the pattern, and compiles it into a deterministic workflow. The next time the same problem appears, it runs without an LLM — no reasoning, no token cost, same result.
|
|
6
|
-
|
|
7
|
-
This guide follows a single query through the full lifecycle: dynamic execution, compilation, deterministic replay, and automatic routing. All steps take place in the dashboard's **Pipeline Designer** page (sidebar: **MCP Workflows → Pipeline Designer**).
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## The Dynamic Execution
|
|
12
|
-
|
|
13
|
-
Open **Pipeline Designer** from the sidebar. The page lists previous MCP query runs and provides a prompt field to start a new one. Describe what you need in natural language — for example, "Log into the dashboard, discover all navigation pages, and screenshot each one." Optionally constrain which MCP tool tags to search.
|
|
14
|
-
|
|
15
|
-
When the query is submitted, the `mcpQuery` workflow starts. It discovers available tools by tag (GIN-indexed full-text search), then enters an agentic loop: the LLM selects a tool, calls it, reads the result, and decides the next step. Every tool call is checkpointed by the workflow engine. If the process crashes mid-execution, it resumes from the last checkpoint — no work is lost, no step runs twice.
|
|
16
|
-
|
|
17
|
-
The run appears in the **Pipeline Designer** list once it completes. Click into it to open the **Compilation Wizard**.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## The Compilation Wizard
|
|
22
|
-
|
|
23
|
-
The wizard has six steps, shown as numbered circles in a sticky bar at the top of the page. Each step represents one stage of converting the dynamic execution into a deployable deterministic workflow:
|
|
24
|
-
|
|
25
|
-
1. **Describe**
|
|
26
|
-
2. **Discover**
|
|
27
|
-
3. **Compile**
|
|
28
|
-
4. **Deploy**
|
|
29
|
-
5. **Test**
|
|
30
|
-
6. **Verify**
|
|
31
|
-
|
|
32
|
-
Steps unlock sequentially — you must complete each before advancing.
|
|
33
|
-
|
|
34
|
-
### 1. Describe
|
|
35
|
-
|
|
36
|
-
**Subtitle:** *Dynamic LLM-orchestrated execution — the discovery run*
|
|
37
|
-
|
|
38
|
-
The first panel displays what the LLM produced: the input envelope on the left and the structured output on the right. Duration is shown. This is the reference point — whatever the compiled workflow produces will be compared against it.
|
|
39
|
-
|
|
40
|
-
### 2. Discover
|
|
41
|
-
|
|
42
|
-
**Subtitle:** *Activity swimlane showing tool calls and their durations*
|
|
43
|
-
|
|
44
|
-
A swimlane visualization of the execution. Each row is an MCP server, each block is a tool call, positioned on a time axis. The pattern is visible at a glance: the LLM logged in, extracted navigation links, then looped through each page to capture a screenshot.
|
|
45
|
-
|
|
46
|
-
### 3. Compile
|
|
47
|
-
|
|
48
|
-
**Subtitle:** *Define the deterministic workflow tool from this execution*
|
|
49
|
-
|
|
50
|
-
The workflow needs an identity. This panel presents a form with:
|
|
51
|
-
|
|
52
|
-
- **Namespace** — a required alphanumeric identifier for the workflow's application scope.
|
|
53
|
-
- **Tool Name** — the workflow's MCP tool name for discovery. This is how other agents and workflows will find and invoke it.
|
|
54
|
-
- **Description** — auto-generated from the execution trace. Editable.
|
|
55
|
-
- **Tags** — suggested from the execution trace. Add or remove tags to control discoverability.
|
|
56
|
-
|
|
57
|
-
An optional **Refine compilation** toggle reveals a feedback textarea where you can provide additional instructions to the compiler.
|
|
58
|
-
|
|
59
|
-
Clicking **Compile Pipeline** triggers the five-stage compilation pipeline:
|
|
60
|
-
|
|
61
|
-
1. **Extract** — parse the execution trace into an ordered step sequence
|
|
62
|
-
2. **Analyze** — detect iteration patterns (the screenshot loop), classify inputs as dynamic (user-provided) or fixed (implementation detail)
|
|
63
|
-
3. **Compile** — an LLM produces a blueprint with data-flow edges and session threading, guided by per-server **compile hints** stored in the database (e.g., which output fields to use as transform sources, how to thread browser session handles)
|
|
64
|
-
4. **Build** — generate a deterministic YAML DAG with activity wiring
|
|
65
|
-
5. **Validate** — check for missing wiring, lost session handles, broken iteration boundaries
|
|
66
|
-
|
|
67
|
-
Once compilation succeeds, the panel switches to a read-only view showing the workflow name, status badge, namespace, topic, description, activity pipeline chain, and tags.
|
|
68
|
-
|
|
69
|
-
### 4. Deploy
|
|
70
|
-
|
|
71
|
-
**Subtitle:** *Review configuration, input/output schemas, and YAML definition*
|
|
72
|
-
|
|
73
|
-
The deploy panel displays the compiled YAML definition, input schema, and output schema. The YAML encodes the DAG: each step names an MCP tool, declares its inputs (either from the user's request or from a prior step's output), and specifies data-flow edges.
|
|
74
|
-
|
|
75
|
-
Two toggle buttons are available:
|
|
76
|
-
|
|
77
|
-
- **Recompile with Feedback** — provide notes to the compiler and regenerate the YAML.
|
|
78
|
-
- **Manual Edit** — directly edit the YAML, schemas, or activity manifest.
|
|
79
|
-
|
|
80
|
-
A version history panel on the right tracks all edits. The step label changes from "Deploy" to "Redeploy" when the workflow is already active.
|
|
81
|
-
|
|
82
|
-
Clicking **Deploy & Activate** registers the workflow as a live MCP tool — tagged for discovery, versioned, invocable by any agent, workflow, or API call.
|
|
83
|
-
|
|
84
|
-
### 5. Test
|
|
85
|
-
|
|
86
|
-
**Header:** *Compare Runs*
|
|
87
|
-
|
|
88
|
-
The test panel runs the compiled workflow and compares it against the original dynamic execution. Two columns show:
|
|
89
|
-
|
|
90
|
-
- **Left — Original MCP Query**: the dynamic LLM-orchestrated run with its input, output, and duration.
|
|
91
|
-
- **Right — Compiled Pipeline Run**: the deterministic run with its input, output, and duration. A dropdown allows selecting from multiple test runs.
|
|
92
|
-
|
|
93
|
-
Click **Run Test** to invoke the compiled workflow with the original input. An invocation modal appears with the pre-populated input schema.
|
|
94
|
-
|
|
95
|
-
The difference is structural:
|
|
96
|
-
|
|
97
|
-
| | Dynamic (LLM) | Deterministic |
|
|
98
|
-
|---|---|---|
|
|
99
|
-
| **Tool calls** | N (LLM selects each) | 1 pipeline (pre-wired DAG) |
|
|
100
|
-
| **LLM usage** | Every step | Route + input extraction only |
|
|
101
|
-
| **Determinism** | Varies per run | Identical every time |
|
|
102
|
-
|
|
103
|
-
The deterministic path is faster because the LLM is used only at the edges — routing the request and extracting structured inputs from the prompt. The DAG itself executes tool calls directly with pre-wired data flow. No per-step reasoning, no tool selection, no interpretation.
|
|
104
|
-
|
|
105
|
-
### 6. Verify
|
|
106
|
-
|
|
107
|
-
**Header:** *End-to-End Verification*
|
|
108
|
-
|
|
109
|
-
The final panel confirms end-to-end routing. The original prompt is pre-filled in an editable textarea on the left. Click **Submit** to send it through the `mcpQueryRouter` — the same entry point any future request would use. A **Reset to original** button restores the prompt if you modify it.
|
|
110
|
-
|
|
111
|
-
The right column shows the result: a status badge, confidence percentage (when the deterministic path is used), and the full output in a JSON viewer. A **RouterProgressTracker** displays real-time routing progress during execution.
|
|
112
|
-
|
|
113
|
-
The router performs full-text search and tag matching to find candidate workflows, then uses an LLM judge to confirm scope. When confidence exceeds the threshold, the request goes straight to the compiled workflow.
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
User prompt → Router → Discovery (FTS + tags) → LLM Judge
|
|
117
|
-
│ │
|
|
118
|
-
│ confidence ≥ 0.7 │ no match
|
|
119
|
-
▼ ▼
|
|
120
|
-
Deterministic Dynamic
|
|
121
|
-
(compiled DAG, no LLM) (agentic loop)
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## How It Accumulates
|
|
127
|
-
|
|
128
|
-
The first time a problem appears, the dynamic path runs. An LLM reasons through it — slow and expensive, but it works.
|
|
129
|
-
|
|
130
|
-
The wizard compiles the solution into a deterministic pipeline. A human reviews the DAG, adjusts if needed, and deploys.
|
|
131
|
-
|
|
132
|
-
Every subsequent occurrence is routed automatically. A single LLM call extracts structured inputs from the prompt, then the DAG executes without further reasoning.
|
|
133
|
-
|
|
134
|
-
Each compiled workflow is itself a discoverable MCP tool. Other workflows and agents can invoke it. Solutions compose. The inventory of deterministic pathways grows with every problem the system solves, and the fraction of requests that require LLM reasoning shrinks.
|
|
135
|
-
|
|
136
|
-
The dynamic path remains for genuinely new problems. But the long tail gets shorter.
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Compilation from Source Code
|
|
141
|
-
|
|
142
|
-
The Pipeline Designer compiles from execution traces — the dynamic path. But there's a second entry point: compiling directly from source code.
|
|
143
|
-
|
|
144
|
-
If you've written a durable workflow using the durable workflow API (`proxyActivities`, `sleep`, `condition`, `startChild`), you can compile it to a YAML DAG without executing it first. The `ltc` CLI reads your TypeScript source, extracts the orchestration structure, and produces an equivalent DAG that runs without replay overhead.
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
ltc compile workflows/assembly-line.ts
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
The source is the spec. The compiled YAML is the optimized execution. Both live in the repo.
|
|
151
|
-
|
|
152
|
-
See the [Compiler Guide](compiler.md) for the full walkthrough.
|
package/docs/compiler.md
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
# The Workflow Compiler
|
|
2
|
-
|
|
3
|
-
You wrote a durable workflow. It works. `proxyActivities`, `sleep`, `condition` — the durable API is productive and familiar. But under the hood, the durable engine replays the entire workflow function on every wake-up. Sleep three times in a ten-step workflow? Steps 1–3 replay on wake one. Steps 1–6 replay on wake two. Steps 1–9 replay on wake three. The replay is deterministic — it skips completed activities — but the function still executes from the top every time.
|
|
4
|
-
|
|
5
|
-
The compiled YAML DAG does the same work without replay. Each step fires exactly once. State flows explicitly between activities through input mappings. No function re-execution, no replay loop, no wasted cycles.
|
|
6
|
-
|
|
7
|
-
`ltc` is the compiler. It reads your TypeScript source and produces an equivalent YAML DAG. Write procedural because it's productive. Run the DAG because it's fast.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## The Analogy
|
|
12
|
-
|
|
13
|
-
`tsc` compiles TypeScript to JavaScript. You write in the language that's expressive. You run the artifact that's efficient. The source is authoritative — you edit it, test it, review it. The compiled output is what actually executes.
|
|
14
|
-
|
|
15
|
-
`ltc` does the same for workflows:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
TypeScript source ltc compile YAML DAG
|
|
19
|
-
(developer-friendly) ──────────────────→ (execution-optimized)
|
|
20
|
-
|
|
21
|
-
assembly-line.ts → assembly-line.compiled.yaml
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The `.ts` file is the spec. The `.compiled.yaml` is the optimized execution. Both live in the repo. A reviewer reads both side-by-side and traces every line of orchestration logic to its DAG equivalent.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Quick Start
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npm install -g @hotmeshio/long-tail
|
|
32
|
-
export ANTHROPIC_API_KEY=sk-ant-...
|
|
33
|
-
|
|
34
|
-
ltc compile workflows/basic-echo/index.ts
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Output:
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
✓ index.ts → workflows/basic-echo/index.compiled.yaml
|
|
41
|
-
1 activities · 2 inputs (message, sleepSeconds) · topic: basic.echo
|
|
42
|
-
|
|
43
|
-
Compiled 1 workflow in 18.1s
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
The compiled YAML appears adjacent to the source file.
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Before and After
|
|
51
|
-
|
|
52
|
-
### The source (procedural)
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import { Durable } from '@hotmeshio/hotmesh';
|
|
56
|
-
import * as activities from './activities';
|
|
57
|
-
|
|
58
|
-
const { echo } = Durable.workflow.proxyActivities<typeof activities>({
|
|
59
|
-
activities,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
export async function basicEcho(envelope: LTEnvelope): Promise<any> {
|
|
63
|
-
const { message = 'Hello, Long Tail!', sleepSeconds = 1 } = envelope.data;
|
|
64
|
-
|
|
65
|
-
// 1. Durable sleep — the engine replays to this point on wake-up
|
|
66
|
-
await Durable.workflow.sleep(`${sleepSeconds} seconds`);
|
|
67
|
-
|
|
68
|
-
// 2. Activity call — replayed as a no-op if already completed
|
|
69
|
-
const echoResult = await echo({ message });
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
type: 'return' as const,
|
|
73
|
-
data: { ...echoResult, sleepSeconds, userId: envelope.lt?.userId },
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
This function executes three times: once on initial invocation, once when the sleep timer fires, and once when the echo activity completes. Each time, the engine replays from the top, skipping completed steps. For a two-step workflow this is fine. For a twenty-step workflow with multiple sleeps, the replay cost compounds.
|
|
79
|
-
|
|
80
|
-
### The compiled output (DAG)
|
|
81
|
-
|
|
82
|
-
```yaml
|
|
83
|
-
app:
|
|
84
|
-
id: longtail
|
|
85
|
-
version: '1'
|
|
86
|
-
graphs:
|
|
87
|
-
- subscribes: basic.echo
|
|
88
|
-
expire: 300
|
|
89
|
-
input:
|
|
90
|
-
schema:
|
|
91
|
-
type: object
|
|
92
|
-
properties:
|
|
93
|
-
message:
|
|
94
|
-
type: string
|
|
95
|
-
default: 'Hello, Long Tail!'
|
|
96
|
-
sleepSeconds:
|
|
97
|
-
type: number
|
|
98
|
-
default: 1
|
|
99
|
-
activities:
|
|
100
|
-
trigger_m7qz:
|
|
101
|
-
type: trigger
|
|
102
|
-
output:
|
|
103
|
-
schema:
|
|
104
|
-
type: object
|
|
105
|
-
properties:
|
|
106
|
-
message: { type: string }
|
|
107
|
-
sleepSeconds: { type: number }
|
|
108
|
-
|
|
109
|
-
delay_m7qz:
|
|
110
|
-
type: hook
|
|
111
|
-
sleep: '{trigger_m7qz.output.data.sleepSeconds}'
|
|
112
|
-
|
|
113
|
-
echo_m7qz:
|
|
114
|
-
type: worker
|
|
115
|
-
topic: basic.echo
|
|
116
|
-
input:
|
|
117
|
-
maps:
|
|
118
|
-
message: '{trigger_m7qz.output.data.message}'
|
|
119
|
-
workflowName: echo
|
|
120
|
-
|
|
121
|
-
transitions:
|
|
122
|
-
trigger_m7qz:
|
|
123
|
-
- to: delay_m7qz
|
|
124
|
-
delay_m7qz:
|
|
125
|
-
- to: echo_m7qz
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### The mapping
|
|
129
|
-
|
|
130
|
-
| TypeScript | YAML | What happens |
|
|
131
|
-
|---|---|---|
|
|
132
|
-
| `envelope.data` destructuring | `trigger` activity with input schema | Inputs declared as typed schema with defaults |
|
|
133
|
-
| `Durable.workflow.sleep(N)` | `hook` activity with `sleep` field | Engine sets a timer; no replay on wake |
|
|
134
|
-
| `await echo({ message })` | `worker` activity with input `maps` | Worker fires once; result stored in job hash |
|
|
135
|
-
| `return { data: ... }` | `job.maps` on the final activity | Output fields plucked from activity results |
|
|
136
|
-
|
|
137
|
-
Each step executes exactly once. The `sleep` hook pauses the DAG. When the timer fires, execution resumes at `echo_m7qz` — not from the top of the function.
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Discovery
|
|
142
|
-
|
|
143
|
-
Point `ltc` at a directory and it finds workflow files automatically:
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
ltc compile examples/workflows/ --dry-run
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
Found 10 workflows:
|
|
151
|
-
|
|
152
|
-
● assembly-line/index.ts
|
|
153
|
-
Function: assemblyLine · HotMesh Durable
|
|
154
|
-
Control flow: startChild, condition
|
|
155
|
-
|
|
156
|
-
● basic-echo/index.ts
|
|
157
|
-
Function: basicEcho · HotMesh Durable
|
|
158
|
-
Activities: echo
|
|
159
|
-
Control flow: sleep
|
|
160
|
-
|
|
161
|
-
● basic-signal/index.ts
|
|
162
|
-
Function: basicSignal · HotMesh Durable
|
|
163
|
-
Activities: ltCreateEscalation, processApproval
|
|
164
|
-
Control flow: conditional
|
|
165
|
-
|
|
166
|
-
● kitchen-sink/index.ts
|
|
167
|
-
Function: kitchenSink · HotMesh Durable
|
|
168
|
-
Activities: greet, fetchData, transformData, notifyComplete
|
|
169
|
-
Control flow: sleep, executeLT
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### What the scanner looks for
|
|
173
|
-
|
|
174
|
-
| Pattern | Classification |
|
|
175
|
-
|---|---|
|
|
176
|
-
| `proxyActivities` / `Durable.workflow.proxyActivities` | HotMesh Durable workflow |
|
|
177
|
-
| `@temporalio/workflow` import | Temporal workflow |
|
|
178
|
-
| `sleep`, `condition`, `signal` | Control flow primitives |
|
|
179
|
-
| `startChild`, `executeChild`, `executeLT` | Composition (parent workflow) |
|
|
180
|
-
| Exported async function | Workflow entry point |
|
|
181
|
-
|
|
182
|
-
Files in `node_modules/`, `build/`, `dist/`, and test files (`*.test.ts`, `*.spec.ts`) are excluded.
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## How Compilation Works
|
|
187
|
-
|
|
188
|
-
The compiler is not an AST parser. It uses the LLM to translate orchestration logic, grounded by structural metadata extracted from the source.
|
|
189
|
-
|
|
190
|
-
1. **Read source** — file or inline string
|
|
191
|
-
2. **Extract metadata** — lightweight regex extraction: activity names, durable primitives, envelope fields, import paths, control flow markers (loops, Promise.all, conditionals, escalation)
|
|
192
|
-
3. **Resolve activities** — if the source imports activity modules, the compiler reads them too and includes them in the LLM context
|
|
193
|
-
4. **LLM translation** — the source code, extracted metadata, and the full HotMesh YAML specification are sent to the LLM. Temperature 0. Up to 3 retry attempts on parse failure.
|
|
194
|
-
5. **Fix patterns** — known LLM anti-patterns in YAML pipe expressions are corrected deterministically
|
|
195
|
-
|
|
196
|
-
The metadata extraction is intentionally lightweight — regex, not a TypeScript AST. It gives the LLM structural hints (which functions are activities, which primitives are used) without requiring `ts-morph` or the TypeScript compiler API as a dependency.
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## Composition
|
|
201
|
-
|
|
202
|
-
When a workflow uses `startChild` or `executeChild`, the compiler resolves the child workflow source through imports and compiles children first (leaf-first ordering). The parent's compiled YAML references each child by topic using the `await` activity type — the same mechanism used by the Pipeline Designer's Plan Build mode.
|
|
203
|
-
|
|
204
|
-
```
|
|
205
|
-
parent.ts ──→ parent.compiled.yaml
|
|
206
|
-
└─ startChild(worker)
|
|
207
|
-
└─ worker.ts ──→ worker.compiled.yaml
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
All compiled workflows in the same composition share the same `app.id` namespace, enabling cross-graph invocation.
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## Three Surfaces
|
|
215
|
-
|
|
216
|
-
The compiler is the same function regardless of how you invoke it.
|
|
217
|
-
|
|
218
|
-
### CLI
|
|
219
|
-
|
|
220
|
-
```bash
|
|
221
|
-
ltc compile workflows/assembly-line.ts
|
|
222
|
-
ltc compile src/workflows/ --dry-run
|
|
223
|
-
ltc compile --model claude-sonnet-4-6
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### HTTP API
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
curl -X POST http://localhost:3000/api/yaml-workflows/from-durable \
|
|
230
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
231
|
-
-H "Content-Type: application/json" \
|
|
232
|
-
-d '{
|
|
233
|
-
"source": "export async function basicEcho(envelope) { ... }",
|
|
234
|
-
"workflow_name": "basicEcho",
|
|
235
|
-
"name": "basic_echo"
|
|
236
|
-
}'
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### SDK
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
import { createClient } from '@hotmeshio/long-tail/sdk';
|
|
243
|
-
|
|
244
|
-
const lt = createClient({ auth: { userId: 'system' } });
|
|
245
|
-
|
|
246
|
-
const result = await lt.yamlWorkflows.compileDurable({
|
|
247
|
-
source: fs.readFileSync('workflows/assembly-line.ts', 'utf-8'),
|
|
248
|
-
workflow_name: 'assemblyLine',
|
|
249
|
-
name: 'assembly_line',
|
|
250
|
-
});
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
The CLI writes `.compiled.yaml` files to disk. The HTTP and SDK surfaces store the compiled workflow in the database and return the record. All three use the same underlying `compileDurableToYaml()` function.
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Configuration
|
|
258
|
-
|
|
259
|
-
| Variable | Default | Description |
|
|
260
|
-
|---|---|---|
|
|
261
|
-
| `ANTHROPIC_API_KEY` | — | Required for Claude models |
|
|
262
|
-
| `OPENAI_API_KEY` | — | Required for OpenAI models |
|
|
263
|
-
| `LT_LLM_MODEL_PRIMARY` | `claude-sonnet-4-6` | Model used for compilation |
|
|
264
|
-
| `LT_LLM_BASE_URL` | — | Custom endpoint for OpenAI-compatible models |
|
|
265
|
-
|
|
266
|
-
The CLI loads `.env` automatically if present in the current directory.
|
|
267
|
-
|
|
268
|
-
---
|
|
269
|
-
|
|
270
|
-
## CLI Reference
|
|
271
|
-
|
|
272
|
-
```
|
|
273
|
-
Usage: ltc compile [options] [target]
|
|
274
|
-
|
|
275
|
-
Compile durable TypeScript workflows to YAML DAGs
|
|
276
|
-
|
|
277
|
-
Arguments:
|
|
278
|
-
target File or directory to compile (default: current directory)
|
|
279
|
-
|
|
280
|
-
Options:
|
|
281
|
-
--dry-run Show discovered workflows without compiling
|
|
282
|
-
-o, --output <dir> Output directory (default: adjacent to source file)
|
|
283
|
-
--model <model> LLM model to use (default: claude-sonnet-4-6)
|
|
284
|
-
--function <name> Workflow function name (auto-detected if omitted)
|
|
285
|
-
-h, --help Display help
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Examples
|
|
289
|
-
|
|
290
|
-
```bash
|
|
291
|
-
# Compile a single file
|
|
292
|
-
ltc compile workflows/basic-echo/index.ts
|
|
293
|
-
|
|
294
|
-
# Scan and compile all workflows in a directory
|
|
295
|
-
ltc compile src/workflows/
|
|
296
|
-
|
|
297
|
-
# Compile everything in the current directory
|
|
298
|
-
ltc compile
|
|
299
|
-
|
|
300
|
-
# Preview what would be compiled
|
|
301
|
-
ltc compile examples/workflows/ --dry-run
|
|
302
|
-
|
|
303
|
-
# Use a specific model
|
|
304
|
-
ltc compile workflows/complex.ts --model claude-opus-4-6
|
|
305
|
-
|
|
306
|
-
# Write output to a separate directory
|
|
307
|
-
ltc compile workflows/ -o compiled/
|
|
308
|
-
|
|
309
|
-
# Compile a specific function from a multi-export file
|
|
310
|
-
ltc compile workflows/multi.ts --function assemblyLine
|
|
311
|
-
```
|
package/docs/contributing.md
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
## Running the Demo
|
|
4
|
-
|
|
5
|
-
The repository includes a working server with example workflows (`reviewContent`, `kitchenSink`, `basicEcho`, and more), Postgres, NATS, and a React dashboard.
|
|
6
|
-
|
|
7
|
-
### Prerequisites
|
|
8
|
-
|
|
9
|
-
- [Docker](https://docs.docker.com/get-docker/)
|
|
10
|
-
|
|
11
|
-
### Run
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
git clone https://github.com/hotmeshio/long-tail.git
|
|
15
|
-
cd long-tail
|
|
16
|
-
docker compose up
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Postgres, NATS, the API server, and the dashboard start together. The dashboard is built during the Docker image build and served as static assets. Migrations run automatically.
|
|
20
|
-
|
|
21
|
-
Default ports are `3000` (API), `5432` (Postgres), `4222`/`8222` (NATS). Override any of them:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
LT_PORT=3001 LT_PG_PORT=5433 LT_NATS_PORT=4223 docker compose up
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Testing
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# Start Postgres and NATS
|
|
31
|
-
docker compose up -d postgres nats
|
|
32
|
-
|
|
33
|
-
# Run all tests
|
|
34
|
-
npm test
|
|
35
|
-
|
|
36
|
-
# Run workflow tests
|
|
37
|
-
npm run test:workflows
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Development Setup
|
|
41
|
-
|
|
42
|
-
1. Fork the repository and clone your fork
|
|
43
|
-
2. Install dependencies: `npm install`
|
|
44
|
-
3. Start infrastructure: `docker compose up -d postgres nats`
|
|
45
|
-
4. Run tests to verify your setup: `npm test`
|
|
46
|
-
|
|
47
|
-
## Pull Requests
|
|
48
|
-
|
|
49
|
-
- Create a feature branch from `main`
|
|
50
|
-
- Keep changes focused — one concern per PR
|
|
51
|
-
- Add or update tests for any new behavior
|
|
52
|
-
- Run `npm test` before submitting
|
|
53
|
-
|
|
54
|
-
## Issues
|
|
55
|
-
|
|
56
|
-
Report bugs and request features at [github.com/hotmeshio/long-tail/issues](https://github.com/hotmeshio/long-tail/issues).
|