@hotmeshio/long-tail 0.31.1 → 0.32.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.
Files changed (320) hide show
  1. package/build/api/escalations/create.js +17 -6
  2. package/build/api/escalations/files.d.ts +18 -0
  3. package/build/api/escalations/files.js +73 -0
  4. package/build/api/escalations/index.d.ts +1 -0
  5. package/build/api/escalations/index.js +4 -2
  6. package/build/api/escalations/metadata.js +5 -4
  7. package/build/api/escalations/resolve.js +6 -4
  8. package/build/bin/ltc.js +4 -2
  9. package/build/index.d.ts +2 -0
  10. package/build/index.js +13 -2
  11. package/build/lib/cli/commands/escalations.d.ts +2 -0
  12. package/build/lib/cli/commands/escalations.js +12 -4
  13. package/build/lib/storage/s3.js +1 -0
  14. package/build/modules/config.d.ts +9 -0
  15. package/build/modules/config.js +9 -0
  16. package/build/routes/escalations/single.js +11 -0
  17. package/build/sdk/index.d.ts +4 -0
  18. package/build/sdk/index.js +2 -0
  19. package/build/services/escalation/aggregate-resolved-sql.d.ts +19 -0
  20. package/build/services/escalation/aggregate-resolved-sql.js +57 -0
  21. package/build/services/escalation/aggregate-sql.d.ts +6 -1
  22. package/build/services/escalation/aggregate-sql.js +33 -12
  23. package/build/services/escalation/aggregate-validate.d.ts +5 -2
  24. package/build/services/escalation/aggregate-validate.js +7 -4
  25. package/build/services/escalation/aggregates.js +5 -3
  26. package/build/services/escalation/crud.js +3 -0
  27. package/build/services/escalation/file-links.d.ts +39 -0
  28. package/build/services/escalation/file-links.js +118 -0
  29. package/build/services/escalation/resolver-validation.d.ts +33 -0
  30. package/build/services/escalation/resolver-validation.js +22 -6
  31. package/build/services/orchestrator/condition.d.ts +20 -4
  32. package/build/services/orchestrator/condition.js +27 -8
  33. package/build/shared/form-validation/display-only-widgets.d.ts +3 -2
  34. package/build/shared/form-validation/display-only-widgets.js +3 -2
  35. package/build/shared/form-validation/index.d.ts +2 -0
  36. package/build/shared/form-validation/index.js +2 -0
  37. package/build/shared/form-validation/x-lt-confidence-facets.d.ts +27 -0
  38. package/build/shared/form-validation/x-lt-confidence-facets.js +60 -0
  39. package/build/shared/form-validation/x-lt-confidence.d.ts +57 -0
  40. package/build/shared/form-validation/x-lt-confidence.js +177 -0
  41. package/build/shared/form-validation/x-lt-help.d.ts +1 -1
  42. package/build/shared/form-validation/x-lt-help.js +1 -1
  43. package/build/system/mcp-servers/admin/escalations.js +4 -2
  44. package/build/system/mcp-servers/admin/labels-schemas.d.ts +4 -4
  45. package/build/system/mcp-servers/admin/schemas.d.ts +111 -70
  46. package/build/system/mcp-servers/admin/schemas.js +8 -3
  47. package/build/system/mcp-servers/human-queue-files.d.ts +8 -0
  48. package/build/system/mcp-servers/human-queue-files.js +32 -0
  49. package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -0
  50. package/build/system/mcp-servers/human-queue-schemas.js +4 -1
  51. package/build/system/mcp-servers/human-queue.d.ts +1 -0
  52. package/build/system/mcp-servers/human-queue.js +23 -16
  53. package/build/system/seed/tool-manifests-admin.js +1 -1
  54. package/build/system/seed/tool-manifests-escalation.js +13 -0
  55. package/build/tsconfig.tsbuildinfo +1 -1
  56. package/build/types/analytics.d.ts +14 -3
  57. package/build/types/analytics.js +3 -1
  58. package/build/types/escalation.d.ts +34 -0
  59. package/build/types/escalation.js +72 -1
  60. package/build/types/index.d.ts +4 -4
  61. package/build/types/index.js +5 -1
  62. package/dashboard/dist/assets/{AdminDashboard-BafKaq50.js → AdminDashboard-C25co77C.js} +2 -2
  63. package/dashboard/dist/assets/{AdminDashboard-BafKaq50.js.map → AdminDashboard-C25co77C.js.map} +1 -1
  64. package/dashboard/dist/assets/{AgentConfigPage-CFHf31DT.js → AgentConfigPage-CsCpI15j.js} +5 -5
  65. package/dashboard/dist/assets/{AgentConfigPage-CFHf31DT.js.map → AgentConfigPage-CsCpI15j.js.map} +1 -1
  66. package/dashboard/dist/assets/{AgentDetailPage-CEvz5rJr.js → AgentDetailPage-ByaepsB5.js} +3 -3
  67. package/dashboard/dist/assets/{AgentDetailPage-CEvz5rJr.js.map → AgentDetailPage-ByaepsB5.js.map} +1 -1
  68. package/dashboard/dist/assets/{AgentsPage-DjQaio0O.js → AgentsPage-ByHU42SO.js} +2 -2
  69. package/dashboard/dist/assets/{AgentsPage-DjQaio0O.js.map → AgentsPage-ByHU42SO.js.map} +1 -1
  70. package/dashboard/dist/assets/{AvailableEscalationsPage-UB03VTJx.js → AvailableEscalationsPage--o6qcz7-.js} +2 -2
  71. package/dashboard/dist/assets/{AvailableEscalationsPage-UB03VTJx.js.map → AvailableEscalationsPage--o6qcz7-.js.map} +1 -1
  72. package/dashboard/dist/assets/{BotPicker-C7MNWOF7.js → BotPicker-B3y3H3fs.js} +2 -2
  73. package/dashboard/dist/assets/{BotPicker-C7MNWOF7.js.map → BotPicker-B3y3H3fs.js.map} +1 -1
  74. package/dashboard/dist/assets/{BulkAssignModal-h5fX-_cV.js → BulkAssignModal-DMNIkIn6.js} +2 -2
  75. package/dashboard/dist/assets/{BulkAssignModal-h5fX-_cV.js.map → BulkAssignModal-DMNIkIn6.js.map} +1 -1
  76. package/dashboard/dist/assets/{CapabilitiesPage-BIzDl-ZT.js → CapabilitiesPage-BekfKHlk.js} +2 -2
  77. package/dashboard/dist/assets/{CapabilitiesPage-BIzDl-ZT.js.map → CapabilitiesPage-BekfKHlk.js.map} +1 -1
  78. package/dashboard/dist/assets/{CollapsibleSection-B5TivtEg.js → CollapsibleSection-BAteHgBG.js} +2 -2
  79. package/dashboard/dist/assets/{CollapsibleSection-B5TivtEg.js.map → CollapsibleSection-BAteHgBG.js.map} +1 -1
  80. package/dashboard/dist/assets/{ConfirmDeleteModal-CB4nKePb.js → ConfirmDeleteModal-BNY287W9.js} +2 -2
  81. package/dashboard/dist/assets/{ConfirmDeleteModal-CB4nKePb.js.map → ConfirmDeleteModal-BNY287W9.js.map} +1 -1
  82. package/dashboard/dist/assets/{ConnectedAppsPage-B3S5gVWw.js → ConnectedAppsPage-LLiiH3da.js} +2 -2
  83. package/dashboard/dist/assets/{ConnectedAppsPage-B3S5gVWw.js.map → ConnectedAppsPage-LLiiH3da.js.map} +1 -1
  84. package/dashboard/dist/assets/{CountdownTimer-BHVIq3kA.js → CountdownTimer-DBLURjxh.js} +2 -2
  85. package/dashboard/dist/assets/{CountdownTimer-BHVIq3kA.js.map → CountdownTimer-DBLURjxh.js.map} +1 -1
  86. package/dashboard/dist/assets/{CredentialConfirmModal-w0AGmCIe.js → CredentialConfirmModal-BqpY3yen.js} +2 -2
  87. package/dashboard/dist/assets/{CredentialConfirmModal-w0AGmCIe.js.map → CredentialConfirmModal-BqpY3yen.js.map} +1 -1
  88. package/dashboard/dist/assets/{CredentialsPage-BtCGBJrT.js → CredentialsPage-CW3_dbm2.js} +2 -2
  89. package/dashboard/dist/assets/{CredentialsPage-BtCGBJrT.js.map → CredentialsPage-CW3_dbm2.js.map} +1 -1
  90. package/dashboard/dist/assets/{CronLabel-BG1rZK-5.js → CronLabel-CR6DiZZr.js} +2 -2
  91. package/dashboard/dist/assets/{CronLabel-BG1rZK-5.js.map → CronLabel-CR6DiZZr.js.map} +1 -1
  92. package/dashboard/dist/assets/{DataTable-FjFhx0SE.js → DataTable-C-IlbLhY.js} +2 -2
  93. package/dashboard/dist/assets/{DataTable-FjFhx0SE.js.map → DataTable-C-IlbLhY.js.map} +1 -1
  94. package/dashboard/dist/assets/{DropZone-D8ZVdEb5.js → DropZone-CHmz59w4.js} +2 -2
  95. package/dashboard/dist/assets/{DropZone-D8ZVdEb5.js.map → DropZone-CHmz59w4.js.map} +1 -1
  96. package/dashboard/dist/assets/{ElapsedCell-l4m8Yvfv.js → ElapsedCell-CEapQvgU.js} +2 -2
  97. package/dashboard/dist/assets/{ElapsedCell-l4m8Yvfv.js.map → ElapsedCell-CEapQvgU.js.map} +1 -1
  98. package/dashboard/dist/assets/{EntityTimelinePanel-BOHlIaxF.js → EntityTimelinePanel-DqD_BpJM.js} +2 -2
  99. package/dashboard/dist/assets/{EntityTimelinePanel-BOHlIaxF.js.map → EntityTimelinePanel-DqD_BpJM.js.map} +1 -1
  100. package/dashboard/dist/assets/{EscalationListSchemaPage-BotlwlX3.js → EscalationListSchemaPage-DDKcrVbb.js} +3 -3
  101. package/dashboard/dist/assets/{EscalationListSchemaPage-BotlwlX3.js.map → EscalationListSchemaPage-DDKcrVbb.js.map} +1 -1
  102. package/dashboard/dist/assets/{EscalationSchemaPage-CfZSVOSD.js → EscalationSchemaPage-BZHZfJiQ.js} +3 -3
  103. package/dashboard/dist/assets/{EscalationSchemaPage-CfZSVOSD.js.map → EscalationSchemaPage-BZHZfJiQ.js.map} +1 -1
  104. package/dashboard/dist/assets/{EscalationTimeline-CCKpuRBU.js → EscalationTimeline-Dv0XUgQX.js} +2 -2
  105. package/dashboard/dist/assets/{EscalationTimeline-CCKpuRBU.js.map → EscalationTimeline-Dv0XUgQX.js.map} +1 -1
  106. package/dashboard/dist/assets/{EscalationTitleSelect-cpTzPHiW.js → EscalationTitleSelect-BN7D52wT.js} +2 -2
  107. package/dashboard/dist/assets/{EscalationTitleSelect-cpTzPHiW.js.map → EscalationTitleSelect-BN7D52wT.js.map} +1 -1
  108. package/dashboard/dist/assets/{EscalationsOverview-DS-nK0qV.js → EscalationsOverview-DE6EPkhT.js} +2 -2
  109. package/dashboard/dist/assets/{EscalationsOverview-DS-nK0qV.js.map → EscalationsOverview-DE6EPkhT.js.map} +1 -1
  110. package/dashboard/dist/assets/{EventTable-UfebhJf0.js → EventTable-CiV62txY.js} +2 -2
  111. package/dashboard/dist/assets/{EventTable-UfebhJf0.js.map → EventTable-CiV62txY.js.map} +1 -1
  112. package/dashboard/dist/assets/{FilterBar-newA5l-X.js → FilterBar-WyNQPyQ1.js} +2 -2
  113. package/dashboard/dist/assets/{FilterBar-newA5l-X.js.map → FilterBar-WyNQPyQ1.js.map} +1 -1
  114. package/dashboard/dist/assets/{GraphInvokePage-6SCDyQcK.js → GraphInvokePage--gn48yUD.js} +2 -2
  115. package/dashboard/dist/assets/{GraphInvokePage-6SCDyQcK.js.map → GraphInvokePage--gn48yUD.js.map} +1 -1
  116. package/dashboard/dist/assets/{HomePage-BEc-XdKj.js → HomePage-IR_jgBE8.js} +2 -2
  117. package/dashboard/dist/assets/{HomePage-BEc-XdKj.js.map → HomePage-IR_jgBE8.js.map} +1 -1
  118. package/dashboard/dist/assets/{LabelJobsPage-BO50zXT5.js → LabelJobsPage-C8LSts4O.js} +2 -2
  119. package/dashboard/dist/assets/{LabelJobsPage-BO50zXT5.js.map → LabelJobsPage-C8LSts4O.js.map} +1 -1
  120. package/dashboard/dist/assets/{LinePage-NYxJQ-ex.js → LinePage-CS7uUv00.js} +2 -2
  121. package/dashboard/dist/assets/{LinePage-NYxJQ-ex.js.map → LinePage-CS7uUv00.js.map} +1 -1
  122. package/dashboard/dist/assets/{LinesPage-RbWTaQRh.js → LinesPage-CJprjG39.js} +3 -3
  123. package/dashboard/dist/assets/{LinesPage-RbWTaQRh.js.map → LinesPage-CJprjG39.js.map} +1 -1
  124. package/dashboard/dist/assets/{ListToolbar-B-E9-toh.js → ListToolbar-YP3uwvXC.js} +2 -2
  125. package/dashboard/dist/assets/{ListToolbar-B-E9-toh.js.map → ListToolbar-YP3uwvXC.js.map} +1 -1
  126. package/dashboard/dist/assets/{McpOverview-Shcf9QhZ.js → McpOverview-Ce-m2JON.js} +2 -2
  127. package/dashboard/dist/assets/{McpOverview-Shcf9QhZ.js.map → McpOverview-Ce-m2JON.js.map} +1 -1
  128. package/dashboard/dist/assets/{McpQueryDetailPage-D8kmjy2v.js → McpQueryDetailPage-CtnUqO1v.js} +2 -2
  129. package/dashboard/dist/assets/{McpQueryDetailPage-D8kmjy2v.js.map → McpQueryDetailPage-CtnUqO1v.js.map} +1 -1
  130. package/dashboard/dist/assets/{McpQueryPage-ck-o5m8A.js → McpQueryPage-C-lqUPlg.js} +2 -2
  131. package/dashboard/dist/assets/{McpQueryPage-ck-o5m8A.js.map → McpQueryPage-C-lqUPlg.js.map} +1 -1
  132. package/dashboard/dist/assets/{McpRunDetailPage-BJKkM9-3.js → McpRunDetailPage-MnIe0hwz.js} +2 -2
  133. package/dashboard/dist/assets/{McpRunDetailPage-BJKkM9-3.js.map → McpRunDetailPage-MnIe0hwz.js.map} +1 -1
  134. package/dashboard/dist/assets/{McpRunsPage-DqhHfD5G.js → McpRunsPage-CpYLXVPF.js} +2 -2
  135. package/dashboard/dist/assets/{McpRunsPage-DqhHfD5G.js.map → McpRunsPage-CpYLXVPF.js.map} +1 -1
  136. package/dashboard/dist/assets/{NamespacePill--uIaGtrN.js → NamespacePill-DilSgLyE.js} +2 -2
  137. package/dashboard/dist/assets/{NamespacePill--uIaGtrN.js.map → NamespacePill-DilSgLyE.js.map} +1 -1
  138. package/dashboard/dist/assets/{OperationsPage-D6B9Vv__.js → OperationsPage-xe6bAwaq.js} +2 -2
  139. package/dashboard/dist/assets/{OperationsPage-D6B9Vv__.js.map → OperationsPage-xe6bAwaq.js.map} +1 -1
  140. package/dashboard/dist/assets/{OperatorDashboard-CIH1cxjQ.js → OperatorDashboard-Cm9_C0EP.js} +2 -2
  141. package/dashboard/dist/assets/{OperatorDashboard-CIH1cxjQ.js.map → OperatorDashboard-Cm9_C0EP.js.map} +1 -1
  142. package/dashboard/dist/assets/{PageHeader-DClJ33fV.js → PageHeader-B7SOvLT8.js} +2 -2
  143. package/dashboard/dist/assets/{PageHeader-DClJ33fV.js.map → PageHeader-B7SOvLT8.js.map} +1 -1
  144. package/dashboard/dist/assets/{PageHeaderWithStats-C-TrbKQL.js → PageHeaderWithStats-DWKap7gs.js} +2 -2
  145. package/dashboard/dist/assets/{PageHeaderWithStats-C-TrbKQL.js.map → PageHeaderWithStats-DWKap7gs.js.map} +1 -1
  146. package/dashboard/dist/assets/{PersonaDetailPage-DjvfyIph.js → PersonaDetailPage-CvstNkh3.js} +2 -2
  147. package/dashboard/dist/assets/{PersonaDetailPage-DjvfyIph.js.map → PersonaDetailPage-CvstNkh3.js.map} +1 -1
  148. package/dashboard/dist/assets/{PersonasPage-D7ryA8Vc.js → PersonasPage-ba1KeInW.js} +2 -2
  149. package/dashboard/dist/assets/{PersonasPage-D7ryA8Vc.js.map → PersonasPage-ba1KeInW.js.map} +1 -1
  150. package/dashboard/dist/assets/{PortalPage-D3ybr0mo.js → PortalPage-GDgG88TM.js} +2 -2
  151. package/dashboard/dist/assets/{PortalPage-D3ybr0mo.js.map → PortalPage-GDgG88TM.js.map} +1 -1
  152. package/dashboard/dist/assets/{PrintLabelsPanel-D0HF5x8b.js → PrintLabelsPanel-BkUN00Qd.js} +2 -2
  153. package/dashboard/dist/assets/{PrintLabelsPanel-D0HF5x8b.js.map → PrintLabelsPanel-BkUN00Qd.js.map} +1 -1
  154. package/dashboard/dist/assets/{ProcessDetailPage-0xS9EdHe.js → ProcessDetailPage-BKu9_wWv.js} +2 -2
  155. package/dashboard/dist/assets/{ProcessDetailPage-0xS9EdHe.js.map → ProcessDetailPage-BKu9_wWv.js.map} +1 -1
  156. package/dashboard/dist/assets/{ProcessesListPage-93SMj1Fd.js → ProcessesListPage-BfJYTU_v.js} +2 -2
  157. package/dashboard/dist/assets/{ProcessesListPage-93SMj1Fd.js.map → ProcessesListPage-BfJYTU_v.js.map} +1 -1
  158. package/dashboard/dist/assets/ResolverForm-DZmY6wJV.js +8 -0
  159. package/dashboard/dist/assets/ResolverForm-DZmY6wJV.js.map +1 -0
  160. package/dashboard/dist/assets/{RoleDetailPage-DlUOJWSB.js → RoleDetailPage-vGeth3ve.js} +3 -3
  161. package/dashboard/dist/assets/{RoleDetailPage-DlUOJWSB.js.map → RoleDetailPage-vGeth3ve.js.map} +1 -1
  162. package/dashboard/dist/assets/{RolePill-BjD1Qw5y.js → RolePill-KhT-Yehm.js} +2 -2
  163. package/dashboard/dist/assets/{RolePill-BjD1Qw5y.js.map → RolePill-KhT-Yehm.js.map} +1 -1
  164. package/dashboard/dist/assets/{RolesPage-DqhHSvaw.js → RolesPage-CwxHOkqF.js} +2 -2
  165. package/dashboard/dist/assets/{RolesPage-DqhHSvaw.js.map → RolesPage-CwxHOkqF.js.map} +1 -1
  166. package/dashboard/dist/assets/{RosterWidget-BrIq61HR.js → RosterWidget-DRVj9xyk.js} +2 -2
  167. package/dashboard/dist/assets/{RosterWidget-BrIq61HR.js.map → RosterWidget-DRVj9xyk.js.map} +1 -1
  168. package/dashboard/dist/assets/{RunAsSelector-D6zQrCNr.js → RunAsSelector-DvPX3XmA.js} +2 -2
  169. package/dashboard/dist/assets/{RunAsSelector-D6zQrCNr.js.map → RunAsSelector-DvPX3XmA.js.map} +1 -1
  170. package/dashboard/dist/assets/{ScanCodesPage-B2S9DR2f.js → ScanCodesPage-Cptbe7h8.js} +2 -2
  171. package/dashboard/dist/assets/{ScanCodesPage-B2S9DR2f.js.map → ScanCodesPage-Cptbe7h8.js.map} +1 -1
  172. package/dashboard/dist/assets/{ScanSchemeDetailPage-gpxKN-pL.js → ScanSchemeDetailPage-DquNJ7Or.js} +4 -4
  173. package/dashboard/dist/assets/{ScanSchemeDetailPage-gpxKN-pL.js.map → ScanSchemeDetailPage-DquNJ7Or.js.map} +1 -1
  174. package/dashboard/dist/assets/{ScanStationPage-B-UTgXsG.js → ScanStationPage-DaRfGGa8.js} +2 -2
  175. package/dashboard/dist/assets/{ScanStationPage-B-UTgXsG.js.map → ScanStationPage-DaRfGGa8.js.map} +1 -1
  176. package/dashboard/dist/assets/{SchemeMatchFields-BK24aa7K.js → SchemeMatchFields-w-pffi98.js} +2 -2
  177. package/dashboard/dist/assets/{SchemeMatchFields-BK24aa7K.js.map → SchemeMatchFields-w-pffi98.js.map} +1 -1
  178. package/dashboard/dist/assets/{ScopeBadge-ofLQ6HW-.js → ScopeBadge-HeuiMJhW.js} +2 -2
  179. package/dashboard/dist/assets/{ScopeBadge-ofLQ6HW-.js.map → ScopeBadge-HeuiMJhW.js.map} +1 -1
  180. package/dashboard/dist/assets/{StickyPagination-CgVv7vc_.js → StickyPagination-D6fDHCcJ.js} +2 -2
  181. package/dashboard/dist/assets/{StickyPagination-CgVv7vc_.js.map → StickyPagination-D6fDHCcJ.js.map} +1 -1
  182. package/dashboard/dist/assets/{StreamMessageDetail-B9sxDVw4.js → StreamMessageDetail-BmYVQrzl.js} +2 -2
  183. package/dashboard/dist/assets/{StreamMessageDetail-B9sxDVw4.js.map → StreamMessageDetail-BmYVQrzl.js.map} +1 -1
  184. package/dashboard/dist/assets/{SwimlaneTimeline-DQc0CYSL.js → SwimlaneTimeline-KCqA-PeL.js} +2 -2
  185. package/dashboard/dist/assets/{SwimlaneTimeline-DQc0CYSL.js.map → SwimlaneTimeline-KCqA-PeL.js.map} +1 -1
  186. package/dashboard/dist/assets/{TagInput-47qVYzke.js → TagInput-CZBAu1Hy.js} +2 -2
  187. package/dashboard/dist/assets/{TagInput-47qVYzke.js.map → TagInput-CZBAu1Hy.js.map} +1 -1
  188. package/dashboard/dist/assets/{TaskDetailPage-D6VOsA1f.js → TaskDetailPage-WtVv2z7T.js} +2 -2
  189. package/dashboard/dist/assets/{TaskDetailPage-D6VOsA1f.js.map → TaskDetailPage-WtVv2z7T.js.map} +1 -1
  190. package/dashboard/dist/assets/{TaskQueuePill-C5KmdXAl.js → TaskQueuePill-DWGn3CWx.js} +2 -2
  191. package/dashboard/dist/assets/{TaskQueuePill-C5KmdXAl.js.map → TaskQueuePill-DWGn3CWx.js.map} +1 -1
  192. package/dashboard/dist/assets/{TasksListPage-DG8hvO8G.js → TasksListPage-DMYQNDIw.js} +2 -2
  193. package/dashboard/dist/assets/{TasksListPage-DG8hvO8G.js.map → TasksListPage-DMYQNDIw.js.map} +1 -1
  194. package/dashboard/dist/assets/{TimeAgo-CL02EhFi.js → TimeAgo-BkY4lahi.js} +2 -2
  195. package/dashboard/dist/assets/{TimeAgo-CL02EhFi.js.map → TimeAgo-BkY4lahi.js.map} +1 -1
  196. package/dashboard/dist/assets/{TimestampCell-BE7oKVJg.js → TimestampCell-BBPb9TI2.js} +2 -2
  197. package/dashboard/dist/assets/{TimestampCell-BE7oKVJg.js.map → TimestampCell-BBPb9TI2.js.map} +1 -1
  198. package/dashboard/dist/assets/{ToolPill-Cp9Drk1s.js → ToolPill-B2aRk0o1.js} +2 -2
  199. package/dashboard/dist/assets/{ToolPill-Cp9Drk1s.js.map → ToolPill-B2aRk0o1.js.map} +1 -1
  200. package/dashboard/dist/assets/{ToolTestPanel-CRecLh6S.js → ToolTestPanel-CNMbmymK.js} +2 -2
  201. package/dashboard/dist/assets/{ToolTestPanel-CRecLh6S.js.map → ToolTestPanel-CNMbmymK.js.map} +1 -1
  202. package/dashboard/dist/assets/{TopicDetailPage-QzkinTfN.js → TopicDetailPage-CodBRylU.js} +2 -2
  203. package/dashboard/dist/assets/{TopicDetailPage-QzkinTfN.js.map → TopicDetailPage-CodBRylU.js.map} +1 -1
  204. package/dashboard/dist/assets/TopicsPage-BtD8jTU7.js +2 -0
  205. package/dashboard/dist/assets/{TopicsPage-D8dW6J65.js.map → TopicsPage-BtD8jTU7.js.map} +1 -1
  206. package/dashboard/dist/assets/{UserName-Dw3R_zrl.js → UserName-D6y9AnuY.js} +2 -2
  207. package/dashboard/dist/assets/{UserName-Dw3R_zrl.js.map → UserName-D6y9AnuY.js.map} +1 -1
  208. package/dashboard/dist/assets/{WorkflowExecutionPage-BTocv8or.js → WorkflowExecutionPage-BeffqV13.js} +2 -2
  209. package/dashboard/dist/assets/{WorkflowExecutionPage-BTocv8or.js.map → WorkflowExecutionPage-BeffqV13.js.map} +1 -1
  210. package/dashboard/dist/assets/{WorkflowPill-BiLYq__w.js → WorkflowPill-BNm3R4pP.js} +2 -2
  211. package/dashboard/dist/assets/{WorkflowPill-BiLYq__w.js.map → WorkflowPill-BNm3R4pP.js.map} +1 -1
  212. package/dashboard/dist/assets/{WorkflowsDashboard-CIPEt3et.js → WorkflowsDashboard-m4Co5diK.js} +2 -2
  213. package/dashboard/dist/assets/{WorkflowsDashboard-CIPEt3et.js.map → WorkflowsDashboard-m4Co5diK.js.map} +1 -1
  214. package/dashboard/dist/assets/{WorkflowsOverview-Bj4MJIE-.js → WorkflowsOverview-DNoI9qY8.js} +2 -2
  215. package/dashboard/dist/assets/{WorkflowsOverview-Bj4MJIE-.js.map → WorkflowsOverview-DNoI9qY8.js.map} +1 -1
  216. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DMEk5k9-.js → YamlWorkflowDetailPage-8Vpc4Oxy.js} +2 -2
  217. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DMEk5k9-.js.map → YamlWorkflowDetailPage-8Vpc4Oxy.js.map} +1 -1
  218. package/dashboard/dist/assets/{YamlWorkflowsPage-F2yyyoiB.js → YamlWorkflowsPage-D1JNwDSg.js} +2 -2
  219. package/dashboard/dist/assets/{YamlWorkflowsPage-F2yyyoiB.js.map → YamlWorkflowsPage-D1JNwDSg.js.map} +1 -1
  220. package/dashboard/dist/assets/{agents-mSgxEPpI.js → agents-LTHUsfv3.js} +2 -2
  221. package/dashboard/dist/assets/{agents-mSgxEPpI.js.map → agents-LTHUsfv3.js.map} +1 -1
  222. package/dashboard/dist/assets/{bots-p4Hp0CV6.js → bots-CQxehfBo.js} +2 -2
  223. package/dashboard/dist/assets/{bots-p4Hp0CV6.js.map → bots-CQxehfBo.js.map} +1 -1
  224. package/dashboard/dist/assets/{capabilities-D_-I_SXR.js → capabilities-DECTnJrK.js} +2 -2
  225. package/dashboard/dist/assets/{capabilities-D_-I_SXR.js.map → capabilities-DECTnJrK.js.map} +1 -1
  226. package/dashboard/dist/assets/{controlplane-DjdoQnRU.js → controlplane-Dx20db5g.js} +2 -2
  227. package/dashboard/dist/assets/{controlplane-DjdoQnRU.js.map → controlplane-Dx20db5g.js.map} +1 -1
  228. package/dashboard/dist/assets/{escalation-columns-R_IEVQjQ.js → escalation-columns-CVFGUB79.js} +2 -2
  229. package/dashboard/dist/assets/{escalation-columns-R_IEVQjQ.js.map → escalation-columns-CVFGUB79.js.map} +1 -1
  230. package/dashboard/dist/assets/escalation-items-Bj7bkwWy.js +2 -0
  231. package/dashboard/dist/assets/escalation-items-Bj7bkwWy.js.map +1 -0
  232. package/dashboard/dist/assets/index-BD4O-ISx.js +13 -0
  233. package/dashboard/dist/assets/{index-Dk2KKo0z.js.map → index-BD4O-ISx.js.map} +1 -1
  234. package/dashboard/dist/assets/{index-D9RAN9sA.js → index-BL8XOMHT.js} +2 -2
  235. package/dashboard/dist/assets/{index-D9RAN9sA.js.map → index-BL8XOMHT.js.map} +1 -1
  236. package/dashboard/dist/assets/index-C2vRDf96.js +2 -0
  237. package/dashboard/dist/assets/{index-C5osluV3.js.map → index-C2vRDf96.js.map} +1 -1
  238. package/dashboard/dist/assets/{index-DUYAGxwc.js → index-CNgyKRQ8.js} +2 -2
  239. package/dashboard/dist/assets/{index-DUYAGxwc.js.map → index-CNgyKRQ8.js.map} +1 -1
  240. package/dashboard/dist/assets/{index-DlJkZ12b.js → index-CdXPbBgs.js} +2 -2
  241. package/dashboard/dist/assets/{index-DlJkZ12b.js.map → index-CdXPbBgs.js.map} +1 -1
  242. package/dashboard/dist/assets/{index-BuCEhhnl.js → index-CnBUFCV7.js} +2 -2
  243. package/dashboard/dist/assets/{index-BuCEhhnl.js.map → index-CnBUFCV7.js.map} +1 -1
  244. package/dashboard/dist/assets/index-CoLciFzq.css +1 -0
  245. package/dashboard/dist/assets/{index-D-FYj9jT.js → index-D_TSx-k_.js} +2 -2
  246. package/dashboard/dist/assets/{index-D-FYj9jT.js.map → index-D_TSx-k_.js.map} +1 -1
  247. package/dashboard/dist/assets/{index-C_dAJUzh.js → index-Do9Y6Fgt.js} +16 -16
  248. package/dashboard/dist/assets/index-Do9Y6Fgt.js.map +1 -0
  249. package/dashboard/dist/assets/{index-D6K_IgCz.js → index-Dq1zjilj.js} +2 -2
  250. package/dashboard/dist/assets/{index-D6K_IgCz.js.map → index-Dq1zjilj.js.map} +1 -1
  251. package/dashboard/dist/assets/{index-BEMdD58x.js → index-Dz4LSzA2.js} +2 -2
  252. package/dashboard/dist/assets/{index-BEMdD58x.js.map → index-Dz4LSzA2.js.map} +1 -1
  253. package/dashboard/dist/assets/{index-D7L_VoBD.js → index-g1MmARVR.js} +2 -2
  254. package/dashboard/dist/assets/{index-D7L_VoBD.js.map → index-g1MmARVR.js.map} +1 -1
  255. package/dashboard/dist/assets/{index-BxbQmeqh.js → index-qEd4FVmN.js} +2 -2
  256. package/dashboard/dist/assets/{index-BxbQmeqh.js.map → index-qEd4FVmN.js.map} +1 -1
  257. package/dashboard/dist/assets/index-v4rQ8ctJ.js +3 -0
  258. package/dashboard/dist/assets/index-v4rQ8ctJ.js.map +1 -0
  259. package/dashboard/dist/assets/{knowledge-DSsPTqkK.js → knowledge-CT1I1t1S.js} +2 -2
  260. package/dashboard/dist/assets/{knowledge-DSsPTqkK.js.map → knowledge-CT1I1t1S.js.map} +1 -1
  261. package/dashboard/dist/assets/{machines-DSgGtqqr.js → machines-Dsuw-l1y.js} +2 -2
  262. package/dashboard/dist/assets/{machines-DSgGtqqr.js.map → machines-Dsuw-l1y.js.map} +1 -1
  263. package/dashboard/dist/assets/{mcp-Cg-_uLw8.js → mcp-C3o5wzO8.js} +2 -2
  264. package/dashboard/dist/assets/{mcp-Cg-_uLw8.js.map → mcp-C3o5wzO8.js.map} +1 -1
  265. package/dashboard/dist/assets/{mcp-query-DQombEK_.js → mcp-query-IvkIG7gH.js} +2 -2
  266. package/dashboard/dist/assets/{mcp-query-DQombEK_.js.map → mcp-query-IvkIG7gH.js.map} +1 -1
  267. package/dashboard/dist/assets/pdf-CcZYcL52.js +13 -0
  268. package/dashboard/dist/assets/pdf-CcZYcL52.js.map +1 -0
  269. package/dashboard/dist/assets/pdf.worker.min-DgRcL-GR.js +2 -0
  270. package/dashboard/dist/assets/pdf.worker.min-DgRcL-GR.js.map +1 -0
  271. package/dashboard/dist/assets/pdf.worker.min-yatZIOMy.mjs +21 -0
  272. package/dashboard/dist/assets/{personas-DYrcoVBu.js → personas-zWlWjj6j.js} +2 -2
  273. package/dashboard/dist/assets/{personas-DYrcoVBu.js.map → personas-zWlWjj6j.js.map} +1 -1
  274. package/dashboard/dist/assets/{pipelines-wdb4xsey.js → pipelines-BKNvBMdf.js} +2 -2
  275. package/dashboard/dist/assets/{pipelines-wdb4xsey.js.map → pipelines-BKNvBMdf.js.map} +1 -1
  276. package/dashboard/dist/assets/{tasks-Bil7gvm9.js → tasks-BQSO3Sjv.js} +2 -2
  277. package/dashboard/dist/assets/{tasks-Bil7gvm9.js.map → tasks-BQSO3Sjv.js.map} +1 -1
  278. package/dashboard/dist/assets/{topics-wBqaVhRR.js → topics-Dr_1TtUM.js} +2 -2
  279. package/dashboard/dist/assets/{topics-wBqaVhRR.js.map → topics-Dr_1TtUM.js.map} +1 -1
  280. package/dashboard/dist/assets/{useContainerWidth-DSLp1gEm.js → useContainerWidth-D38m8eub.js} +2 -2
  281. package/dashboard/dist/assets/{useContainerWidth-DSLp1gEm.js.map → useContainerWidth-D38m8eub.js.map} +1 -1
  282. package/dashboard/dist/assets/{useDebouncedValue-CwrY8TpV.js → useDebouncedValue-C5ESASfo.js} +2 -2
  283. package/dashboard/dist/assets/{useDebouncedValue-CwrY8TpV.js.map → useDebouncedValue-C5ESASfo.js.map} +1 -1
  284. package/dashboard/dist/assets/{useNamespace-Sod_xApz.js → useNamespace-DLLOJRYY.js} +2 -2
  285. package/dashboard/dist/assets/{useNamespace-Sod_xApz.js.map → useNamespace-DLLOJRYY.js.map} +1 -1
  286. package/dashboard/dist/assets/{useYamlActivityEvents-CKLInV3C.js → useYamlActivityEvents-D0XNXli1.js} +2 -2
  287. package/dashboard/dist/assets/{useYamlActivityEvents-CKLInV3C.js.map → useYamlActivityEvents-D0XNXli1.js.map} +1 -1
  288. package/dashboard/dist/assets/{validate-CYhW1xMJ.js → validate-Be4GWnJ1.js} +2 -2
  289. package/dashboard/dist/assets/{validate-CYhW1xMJ.js.map → validate-Be4GWnJ1.js.map} +1 -1
  290. package/dashboard/dist/assets/{vendor-icons-ed7mYQw4.js → vendor-icons-D48ijXZU.js} +209 -189
  291. package/dashboard/dist/assets/vendor-icons-D48ijXZU.js.map +1 -0
  292. package/dashboard/dist/assets/{yaml-workflows-C20qHo3L.js → yaml-workflows-BQpO-G-I.js} +2 -2
  293. package/dashboard/dist/assets/{yaml-workflows-C20qHo3L.js.map → yaml-workflows-BQpO-G-I.js.map} +1 -1
  294. package/dashboard/dist/index.html +3 -3
  295. package/docs/api/http/escalations.md +54 -7
  296. package/docs/api/mcp/admin.md +7 -5
  297. package/docs/api/mcp/human-queue.md +17 -1
  298. package/docs/api/sdk/escalations.md +30 -4
  299. package/docs/api/sdk/files.md +19 -0
  300. package/docs/cli.md +4 -1
  301. package/docs/escalation-analytics.md +17 -0
  302. package/docs/hitl/files.md +104 -0
  303. package/docs/hitl/x-lt-confidence.md +139 -0
  304. package/docs/hitl/x-lt-layout.md +19 -0
  305. package/docs/hitl/x-lt-widget.md +20 -0
  306. package/docs/hitl-guide.md +6 -0
  307. package/docs/mcp.md +2 -1
  308. package/package.json +1 -1
  309. package/dashboard/dist/assets/ResolverForm-DfogHDzl.js +0 -8
  310. package/dashboard/dist/assets/ResolverForm-DfogHDzl.js.map +0 -1
  311. package/dashboard/dist/assets/TopicsPage-D8dW6J65.js +0 -2
  312. package/dashboard/dist/assets/escalation-items-BGZlJMpk.js +0 -2
  313. package/dashboard/dist/assets/escalation-items-BGZlJMpk.js.map +0 -1
  314. package/dashboard/dist/assets/index-BUmz0NMg.css +0 -1
  315. package/dashboard/dist/assets/index-C5osluV3.js +0 -2
  316. package/dashboard/dist/assets/index-C_dAJUzh.js.map +0 -1
  317. package/dashboard/dist/assets/index-Dk2KKo0z.js +0 -13
  318. package/dashboard/dist/assets/index-FiNThtNU.js +0 -3
  319. package/dashboard/dist/assets/index-FiNThtNU.js.map +0 -1
  320. package/dashboard/dist/assets/vendor-icons-ed7mYQw4.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"yaml-workflows-C20qHo3L.js","sources":["../../src/api/yaml-workflows.ts"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\nimport type { LTYamlWorkflowRecord, LTYamlWorkflowStatus, LTYamlWorkflowVersion } from './types';\n\ninterface YamlWorkflowListResponse {\n workflows: LTYamlWorkflowRecord[];\n total: number;\n}\n\ninterface YamlWorkflowFilters {\n status?: LTYamlWorkflowStatus;\n graph_topic?: string;\n app_id?: string;\n search?: string;\n set_id?: string;\n limit?: number;\n offset?: number;\n}\n\nexport function useYamlWorkflows(filters: YamlWorkflowFilters = {}) {\n const params = new URLSearchParams();\n if (filters.status) params.set('status', filters.status);\n if (filters.graph_topic) params.set('graph_topic', filters.graph_topic);\n if (filters.app_id) params.set('app_id', filters.app_id);\n if (filters.search) params.set('search', filters.search);\n if (filters.set_id) params.set('set_id', filters.set_id);\n if (filters.limit) params.set('limit', String(filters.limit));\n if (filters.offset !== undefined) params.set('offset', String(filters.offset));\n\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', filters],\n queryFn: () => apiFetch(`/yaml-workflows?${params}`),\n });\n}\n\nexport function useYamlWorkflowAppIds() {\n return useQuery<{ app_ids: string[] }>({\n queryKey: ['yamlWorkflowAppIds'],\n queryFn: () => apiFetch('/yaml-workflows/app-ids'),\n });\n}\n\nexport function useYamlWorkflowByTopic(graphTopic: string | undefined, appId?: string) {\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', 'byTopic', graphTopic, appId],\n queryFn: () => {\n const params = new URLSearchParams({ graph_topic: graphTopic!, limit: '1' });\n if (appId) params.set('app_id', appId);\n return apiFetch(`/yaml-workflows?${params}`);\n },\n enabled: !!graphTopic,\n });\n}\n\nexport function useYamlWorkflow(id: string) {\n return useQuery<LTYamlWorkflowRecord>({\n queryKey: ['yamlWorkflows', id],\n queryFn: () => apiFetch(`/yaml-workflows/${id}`),\n enabled: !!id,\n });\n}\n\nexport function useCreateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (input: {\n workflow_id: string;\n task_queue: string;\n workflow_name: string;\n name: string;\n description?: string;\n app_id?: string;\n subscribes?: string;\n tags?: string[];\n compilation_feedback?: string;\n }) =>\n apiFetch<LTYamlWorkflowRecord>('/yaml-workflows', {\n method: 'POST',\n body: JSON.stringify(input),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeployYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/deploy`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useActivateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/activate`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useInvokeYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, data, sync, execute_as }: { id: string; data: Record<string, unknown>; sync?: boolean; execute_as?: string }) =>\n apiFetch<{ result?: unknown; job_id?: string }>(`/yaml-workflows/${id}/invoke`, {\n method: 'POST',\n body: JSON.stringify({ data, sync, ...(execute_as ? { execute_as } : {}) }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRegenerateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, task_queue, compilation_feedback }: { id: string; task_queue?: string; compilation_feedback?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/regenerate`, {\n method: 'POST',\n body: JSON.stringify({ task_queue, compilation_feedback }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useArchiveYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/archive`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRestoreYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/restore`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflow'], refetchType: 'all' });\n },\n });\n}\n\nexport function useUpdateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, ...updates }: { id: string; yaml_content?: string; name?: string; description?: string; input_schema?: Record<string, unknown>; output_schema?: Record<string, unknown>; tags?: string[]; app_id?: string; graph_topic?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeleteYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<{ deleted: boolean }>(`/yaml-workflows/${id}`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Cron scheduling ─────────────────────────────────────────────\n\nexport function useSetYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, cron_schedule, cron_envelope, execute_as }: {\n id: string;\n cron_schedule: string;\n cron_envelope?: Record<string, unknown> | null;\n execute_as?: string | null;\n }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'PUT',\n body: JSON.stringify({ cron_schedule, cron_envelope, execute_as }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useClearYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Version history ─────────────────────────────────────────────\n\nexport function useYamlWorkflowVersions(id: string) {\n return useQuery<{ versions: LTYamlWorkflowVersion[]; total: number }>({\n queryKey: ['yamlWorkflows', id, 'versions'],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions`),\n enabled: !!id,\n });\n}\n\nexport function useYamlWorkflowVersion(id: string, version: number | null) {\n return useQuery<LTYamlWorkflowVersion>({\n queryKey: ['yamlWorkflows', id, 'versions', version],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions/${version}`),\n enabled: !!id && version !== null,\n });\n}\n"],"names":["useYamlWorkflows","filters","params","useQuery","apiFetch","useYamlWorkflowAppIds","useYamlWorkflow","id","useCreateYamlWorkflow","queryClient","useQueryClient","useMutation","input","useDeployYamlWorkflow","useActivateYamlWorkflow","useInvokeYamlWorkflow","data","sync","execute_as","useRegenerateYamlWorkflow","task_queue","compilation_feedback","useArchiveYamlWorkflow","useRestoreYamlWorkflow","useUpdateYamlWorkflow","updates","useDeleteYamlWorkflow","useYamlWorkflowVersions","useYamlWorkflowVersion","version"],"mappings":"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"}
1
+ {"version":3,"file":"yaml-workflows-BQpO-G-I.js","sources":["../../src/api/yaml-workflows.ts"],"sourcesContent":["import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { apiFetch } from './client';\nimport type { LTYamlWorkflowRecord, LTYamlWorkflowStatus, LTYamlWorkflowVersion } from './types';\n\ninterface YamlWorkflowListResponse {\n workflows: LTYamlWorkflowRecord[];\n total: number;\n}\n\ninterface YamlWorkflowFilters {\n status?: LTYamlWorkflowStatus;\n graph_topic?: string;\n app_id?: string;\n search?: string;\n set_id?: string;\n limit?: number;\n offset?: number;\n}\n\nexport function useYamlWorkflows(filters: YamlWorkflowFilters = {}) {\n const params = new URLSearchParams();\n if (filters.status) params.set('status', filters.status);\n if (filters.graph_topic) params.set('graph_topic', filters.graph_topic);\n if (filters.app_id) params.set('app_id', filters.app_id);\n if (filters.search) params.set('search', filters.search);\n if (filters.set_id) params.set('set_id', filters.set_id);\n if (filters.limit) params.set('limit', String(filters.limit));\n if (filters.offset !== undefined) params.set('offset', String(filters.offset));\n\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', filters],\n queryFn: () => apiFetch(`/yaml-workflows?${params}`),\n });\n}\n\nexport function useYamlWorkflowAppIds() {\n return useQuery<{ app_ids: string[] }>({\n queryKey: ['yamlWorkflowAppIds'],\n queryFn: () => apiFetch('/yaml-workflows/app-ids'),\n });\n}\n\nexport function useYamlWorkflowByTopic(graphTopic: string | undefined, appId?: string) {\n return useQuery<YamlWorkflowListResponse>({\n queryKey: ['yamlWorkflows', 'byTopic', graphTopic, appId],\n queryFn: () => {\n const params = new URLSearchParams({ graph_topic: graphTopic!, limit: '1' });\n if (appId) params.set('app_id', appId);\n return apiFetch(`/yaml-workflows?${params}`);\n },\n enabled: !!graphTopic,\n });\n}\n\nexport function useYamlWorkflow(id: string) {\n return useQuery<LTYamlWorkflowRecord>({\n queryKey: ['yamlWorkflows', id],\n queryFn: () => apiFetch(`/yaml-workflows/${id}`),\n enabled: !!id,\n });\n}\n\nexport function useCreateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (input: {\n workflow_id: string;\n task_queue: string;\n workflow_name: string;\n name: string;\n description?: string;\n app_id?: string;\n subscribes?: string;\n tags?: string[];\n compilation_feedback?: string;\n }) =>\n apiFetch<LTYamlWorkflowRecord>('/yaml-workflows', {\n method: 'POST',\n body: JSON.stringify(input),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeployYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/deploy`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useActivateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/activate`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useInvokeYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, data, sync, execute_as }: { id: string; data: Record<string, unknown>; sync?: boolean; execute_as?: string }) =>\n apiFetch<{ result?: unknown; job_id?: string }>(`/yaml-workflows/${id}/invoke`, {\n method: 'POST',\n body: JSON.stringify({ data, sync, ...(execute_as ? { execute_as } : {}) }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRegenerateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, task_queue, compilation_feedback }: { id: string; task_queue?: string; compilation_feedback?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/regenerate`, {\n method: 'POST',\n body: JSON.stringify({ task_queue, compilation_feedback }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useArchiveYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/archive`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useRestoreYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/restore`, {\n method: 'POST',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflow'], refetchType: 'all' });\n },\n });\n}\n\nexport function useUpdateYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, ...updates }: { id: string; yaml_content?: string; name?: string; description?: string; input_schema?: Record<string, unknown>; output_schema?: Record<string, unknown>; tags?: string[]; app_id?: string; graph_topic?: string }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useDeleteYamlWorkflow() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<{ deleted: boolean }>(`/yaml-workflows/${id}`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Cron scheduling ─────────────────────────────────────────────\n\nexport function useSetYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ id, cron_schedule, cron_envelope, execute_as }: {\n id: string;\n cron_schedule: string;\n cron_envelope?: Record<string, unknown> | null;\n execute_as?: string | null;\n }) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'PUT',\n body: JSON.stringify({ cron_schedule, cron_envelope, execute_as }),\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\nexport function useClearYamlCron() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n apiFetch<LTYamlWorkflowRecord>(`/yaml-workflows/${id}/cron`, {\n method: 'DELETE',\n }),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['yamlWorkflows'], refetchType: 'all' });\n },\n });\n}\n\n// ── Version history ─────────────────────────────────────────────\n\nexport function useYamlWorkflowVersions(id: string) {\n return useQuery<{ versions: LTYamlWorkflowVersion[]; total: number }>({\n queryKey: ['yamlWorkflows', id, 'versions'],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions`),\n enabled: !!id,\n });\n}\n\nexport function useYamlWorkflowVersion(id: string, version: number | null) {\n return useQuery<LTYamlWorkflowVersion>({\n queryKey: ['yamlWorkflows', id, 'versions', version],\n queryFn: () => apiFetch(`/yaml-workflows/${id}/versions/${version}`),\n enabled: !!id && version !== null,\n });\n}\n"],"names":["useYamlWorkflows","filters","params","useQuery","apiFetch","useYamlWorkflowAppIds","useYamlWorkflow","id","useCreateYamlWorkflow","queryClient","useQueryClient","useMutation","input","useDeployYamlWorkflow","useActivateYamlWorkflow","useInvokeYamlWorkflow","data","sync","execute_as","useRegenerateYamlWorkflow","task_queue","compilation_feedback","useArchiveYamlWorkflow","useRestoreYamlWorkflow","useUpdateYamlWorkflow","updates","useDeleteYamlWorkflow","useYamlWorkflowVersions","useYamlWorkflowVersion","version"],"mappings":"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"}
@@ -8,11 +8,11 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
10
  <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
11
- <script type="module" crossorigin src="./assets/index-C_dAJUzh.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-Do9Y6Fgt.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="./assets/vendor-query-DvWWuNIB.js">
13
13
  <link rel="modulepreload" crossorigin href="./assets/vendor-react-_9U4mKFr.js">
14
- <link rel="modulepreload" crossorigin href="./assets/vendor-icons-ed7mYQw4.js">
15
- <link rel="stylesheet" crossorigin href="./assets/index-BUmz0NMg.css">
14
+ <link rel="modulepreload" crossorigin href="./assets/vendor-icons-D48ijXZU.js">
15
+ <link rel="stylesheet" crossorigin href="./assets/index-CoLciFzq.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -24,7 +24,7 @@ A role is a task queue with four verbs — **search** (list/get), **claim**, **a
24
24
 
25
25
  - `read_scope` governs which escalations a member **sees** — list, `/available`, get-by-id, find-by-metadata, and stats. `self` means escalations assigned to the member (`assigned_to = user`); `all` means the whole role queue.
26
26
  - `write_scope` governs which escalations a member may **act on** — claim, resolve, cancel. `self` means only items already assigned to them; `none` is read-only.
27
- - Releasing, escalating and assigning by query are queue-management verbs and require `write_scope=all`. Creating a standalone escalation (`POST /api/escalations`) requires `write_scope=all` or global escalation access.
27
+ - Releasing, escalating and assigning by query are queue-management verbs and require `write_scope=all`. Creating a standalone escalation (`POST /api/escalations`) requires `write_scope=all` or global escalation access. An envelope that names stored files (`envelope.files`) also requires builder access (superadmin or engineer).
28
28
 
29
29
  Defaults are `read_scope=all` and `write_scope=all` — the full-queue worker — so a plain `member` works the whole queue. See [Work-Surface Scope](roles.md#work-surface-scope) in the Roles API for the five member profiles and the **write ⊆ read** constraint.
30
30
 
@@ -157,6 +157,28 @@ GET /api/escalations/:id
157
157
  { "error": "Escalation not found" }
158
158
  ```
159
159
 
160
+ ## Get escalation files
161
+
162
+ ```
163
+ GET /api/escalations/:id/files
164
+ ```
165
+
166
+ Signs the stored files the row names (`envelope.files`). The refs ARE the grant: any user who may read the escalation receives time-limited links to exactly those files. A link lives for the ref's `expiresIn` (default `LT_ESCALATION_FILE_URL_TTL_SECONDS`), stretched to cover the caller's own live claim, within the configured bounds. Answers with `Cache-Control: no-store`. See [files](../../hitl/files.md).
167
+
168
+ **Scope:** Enforces the same read scope as `GET /api/escalations/:id`.
169
+
170
+ **Response 200:**
171
+
172
+ ```json
173
+ {
174
+ "files": [
175
+ { "as": "application", "path": "intake/APP-1042/application.pdf", "name": "application.pdf",
176
+ "contentType": "application/pdf", "url": "https://…", "expiresAt": "2026-11-09T15:39:31.859Z" },
177
+ { "as": "card", "path": "scans/8f2c41", "name": "ID card", "contentType": "image/jpeg", "error": "…" }
178
+ ]
179
+ }
180
+ ```
181
+
160
182
  ## Get escalation lookups
161
183
 
162
184
  ```
@@ -1356,7 +1378,7 @@ Batch-claim individual rows matching a facet query (`FOR UPDATE SKIP LOCKED`), a
1356
1378
  POST /api/escalations/aggregate-by-facets
1357
1379
  ```
1358
1380
 
1359
- Grouped analytics over the escalation intervals. Every escalation is one open interval `[created_at, ended_at)` — `ended_at` is the instant the row left the live set (resolved / cancelled / expired), `NULL` while live. The aggregate reads that time-series two ways: **membership** (rows — or, with `distinctBy`, distinct entities — whose interval is open at an instant; a past `asOf` reconstructs the live set at that moment) and **dwell** (open-seconds per group within a half-open `[from, to)` window, clipped to it on both ends). One call replaces N per-filter count round-trips. See [escalation-analytics.md](../../escalation-analytics.md) for the full guide.
1381
+ Grouped analytics over the escalation intervals. Every escalation is one open interval `[created_at, ended_at)` — `ended_at` is the instant the row left the live set (resolved / cancelled / expired), `NULL` while live. The aggregate reads that time-series three ways: **membership** (rows — or, with `distinctBy`, distinct entities — whose interval is open at an instant; a past `asOf` reconstructs the live set at that moment), **dwell** (open-seconds per group within a half-open `[from, to)` window, clipped to it on both ends), and **resolved** (rows resolved within a half-open window, optionally per UTC `day`, `week` or `month` bucket: the trend measure). One call replaces N per-filter count round-trips. See [escalation-analytics.md](../../escalation-analytics.md) for the full guide.
1360
1382
 
1361
1383
  **Request body:**
1362
1384
 
@@ -1364,11 +1386,11 @@ Grouped analytics over the escalation intervals. Every escalation is one open in
1364
1386
  |-------|------|----------|-------------|
1365
1387
  | `query` | `object` | yes | The filter — `role`/`roles` (or `entity`), `facets`, `anyOf` (rows carrying ANY of the given facet sets, max 200 — target an explicit entity set such as one table page), `block`, `range`, `exists`, and `prefix` (case-insensitive prefix match on facet values — the locate affordance, e.g. `{"serialNumber":"PRN-00"}`). `entity` names an entity facet key and resolves server-side to every role declaring it as its `entity_facet` — the entity's **system**; mutually exclusive with `role`/`roles`, and it implies `exists: [entity]` so stray rows without the key stay out |
1366
1388
  | `groupBy` | `object` | yes | Group keys — `columns` (whitelisted: `role`, `subtype`, `status`), `facets` (metadata keys, projected as text; `NULL` group key when absent), and `state` (group by the derived state label: each role contributes per its `entity_state_source` — its subtypes or itself; mutually exclusive with `states[]`). An empty object yields one total row |
1367
- | `measure` | `object` | yes | Exactly one kind: `{ "kind": "membership", "asOf"? }` (default anchor: now) or `{ "kind": "dwell", "window": { "from", "to" } }` |
1368
- | `distinctBy` | `string` | no | Membership only — count DISTINCT of this metadata facet per group (entities, not rows). Omit to count rows |
1389
+ | `measure` | `object` | yes | Exactly one kind: `{ "kind": "membership", "asOf"? }` (default anchor: now), `{ "kind": "dwell", "window": { "from", "to" } }`, or `{ "kind": "resolved", "window": { "from", "to" }, "bucket"? }` (`bucket`: `day`, `week` or `month`; requires `role`, `roles` or `entity`; window up to `LT_ANALYTICS_MAX_RESOLVED_WINDOW_DAYS`, default 366) |
1390
+ | `distinctBy` | `string` | no | Membership and resolved: count DISTINCT of this metadata facet per group (entities, not rows). Omit to count rows |
1369
1391
  | `states` | `array` | no | Pure labeling: tag each group with the FIRST matching `{ name, match }` entry, evaluated top-to-bottom; `match` compares grouped columns/facets. Grouping is unchanged |
1370
1392
  | `liveStatuses` | `string[]` | no | Statuses considered live (default `["pending"]`) |
1371
- | `orderBy` | `array` | no | Order the RESULT groups: `{ field, direction? }` — `count`, `dwellSeconds`, `sampleCount`, a grouped column, or a grouped facet key |
1393
+ | `orderBy` | `array` | no | Order the RESULT groups: `{ field, direction? }` — `count`, `dwellSeconds`, `sampleCount`, `bucket` (bucketed resolved), a grouped column, or a grouped facet key. Bucketed resolved results default to bucket order |
1372
1394
  | `limit` / `offset` | `integer` | no | Result-group paging, capped at `LT_ANALYTICS_MAX_GROUPS` |
1373
1395
 
1374
1396
  The filter takes the WHAT fields only. `status`, `available`, and `jeopardy` are rejected — liveness derives from the interval, `liveStatuses`, and the measure anchor. Query-level `orderBy`/`limit`/`offset` are rejected too — order and paginate the result groups with the top-level fields.
@@ -1402,6 +1424,30 @@ The filter takes the WHAT fields only. `status`, `available`, and `jeopardy` are
1402
1424
 
1403
1425
  Adding `"facets": ["model"]` to `groupBy` slices the same bands per model value (`p1s` vs `h2s`).
1404
1426
 
1427
+ **Example**: weekly review outcomes per extractor version. Rows resolved on a form with [review facets](../../hitl/x-lt-confidence.md#review-facets) carry `review_outcome`; the workflow records `extractor` when it creates the row:
1428
+
1429
+ ```json
1430
+ {
1431
+ "query": { "role": "intake-verifier" },
1432
+ "groupBy": { "facets": ["extractor", "review_outcome"] },
1433
+ "measure": {
1434
+ "kind": "resolved",
1435
+ "window": { "from": "2026-10-01T00:00:00Z", "to": "2026-11-01T00:00:00Z" },
1436
+ "bucket": "week"
1437
+ }
1438
+ }
1439
+ ```
1440
+
1441
+ ```json
1442
+ {
1443
+ "groups": [
1444
+ { "bucket": "2026-09-28T00:00:00.000Z", "facets": { "extractor": "intake-extractor-v1", "review_outcome": "accepted" }, "count": 1088, "sampleCount": 1088 },
1445
+ { "bucket": "2026-09-28T00:00:00.000Z", "facets": { "extractor": "intake-extractor-v1", "review_outcome": "corrected" }, "count": 412, "sampleCount": 412 }
1446
+ ],
1447
+ "overflow": false
1448
+ }
1449
+ ```
1450
+
1405
1451
  **Response fields (per group):**
1406
1452
 
1407
1453
  | Field | Type | Description |
@@ -1409,13 +1455,14 @@ Adding `"facets": ["model"]` to `groupBy` slices the same bands per model value
1409
1455
  | `role` / `subtype` / `status` | `string` | Present iff requested in `groupBy.columns`. `status` is the row's status NOW — status history is not stored, so a past `asOf` still groups by current status |
1410
1456
  | `facets` | `object` | One entry per `groupBy.facets` key; `null` when the facet is absent on the underlying rows |
1411
1457
  | `state` | `string` | Present when `groupBy.state` derived it or a `states[]` entry matched |
1412
- | `count` | `number` | Membership: entities (with `distinctBy`) or rows (without) |
1458
+ | `count` | `number` | Membership and resolved: entities (with `distinctBy`) or rows (without) |
1459
+ | `bucket` | `string` | Bucketed resolved: the bucket's start instant (UTC, ISO) |
1413
1460
  | `dwellSeconds` | `number` | Dwell: summed open-seconds within the window |
1414
1461
  | `sampleCount` | `number` | Underlying escalation rows contributing to the group (pre-distinct) |
1415
1462
 
1416
1463
  `overflow: true` means the group cap was hit — more groups exist beyond this page.
1417
1464
 
1418
- **Response 400** — a caller-input problem: a liveness field (`status`/`available`/`jeopardy`) or `orderBy`/`limit`/`offset` on the filter; `entity` together with `role`/`roles`; `groupBy.state` together with `states[]`; an unknown status in `liveStatuses`; an empty window or one wider than `LT_ANALYTICS_MAX_WINDOW_DAYS`; a future `asOf`; a malformed facet key; a `states[]` match referencing a key the query never groups by.
1465
+ **Response 400** — a caller-input problem: a liveness field (`status`/`available`/`jeopardy`) or `orderBy`/`limit`/`offset` on the filter; `entity` together with `role`/`roles`; `groupBy.state` together with `states[]`; an unknown status in `liveStatuses`; an empty window or one wider than `LT_ANALYTICS_MAX_WINDOW_DAYS` (`LT_ANALYTICS_MAX_RESOLVED_WINDOW_DAYS` for resolved); a resolved measure without a role scope, with `liveStatuses`, or with an unknown `bucket`; a future `asOf`; a malformed facet key; a `states[]` match referencing a key the query never groups by.
1419
1466
 
1420
1467
  **Response 403** — the caller must hold `read_all` on every role in scope (for `entity`, every role in the derived system); a filter with no role scope spans every pond and requires a global principal (superadmin/admin). While `features.publicPaceBoard` stands (default on), counts-only groupings — no `groupBy.facets` keys — are readable by any login, the same data class the Pace Board exposes; a facet-keyed grouping emits facet values (entity ids) as group keys and always takes the full gate.
1421
1468
 
@@ -517,10 +517,12 @@ Batch-claim individual rows matching a facet query (`FOR UPDATE SKIP LOCKED`), a
517
517
  ### aggregate_by_facets
518
518
 
519
519
  Grouped analytics over the escalation intervals. Every escalation is one open
520
- interval `[created_at, ended_at)`; this tool reads it two ways: **membership**
520
+ interval `[created_at, ended_at)`; this tool reads it three ways: **membership**
521
521
  (rows or, with `distinctBy`, distinct entities open at an instant — a past
522
- `asOf` reconstructs the live set then) and **dwell** (open-seconds per group
523
- within a half-open `[from, to)` window). Group by role/subtype/status columns
522
+ `asOf` reconstructs the live set then), **dwell** (open-seconds per group
523
+ within a half-open `[from, to)` window), and **resolved** (rows resolved within
524
+ a window, optionally per `day`, `week` or `month`: trends such as weekly review
525
+ outcomes per extractor). Group by role/subtype/status columns
524
526
  plus metadata facet keys; optional `states[]` label each group. One call
525
527
  replaces N per-filter count round-trips. Mirrors
526
528
  `POST /api/escalations/aggregate-by-facets`.
@@ -535,8 +537,8 @@ replaces N per-filter count round-trips. Mirrors
535
537
  |-------|------|----------|-------------|
536
538
  | query | object | Yes | The filter (WHAT only — no status/available/jeopardy): `role`/`roles` or `entity` (the entity facet key, resolved to every role declaring it — the entity's system), plus `facets`, `block`, `range`, `exists` |
537
539
  | groupBy | object | Yes | Group keys: `columns` (`role`, `subtype`, `status`), `facets` (metadata keys), `state` (derived state label per each role's `entity_state_source`; mutually exclusive with `states`). Empty object → one total row |
538
- | measure | object | Yes | `{ kind: "membership", asOf? }` or `{ kind: "dwell", window: { from, to } }` |
539
- | distinctBy | string | No | Membership only: count DISTINCT of this metadata facet (entities, not rows) |
540
+ | measure | object | Yes | `{ kind: "membership", asOf? }`, `{ kind: "dwell", window: { from, to } }`, or `{ kind: "resolved", window: { from, to }, bucket? }` (requires `role`, `roles` or `entity`) |
541
+ | distinctBy | string | No | Membership and resolved: count DISTINCT of this metadata facet (entities, not rows) |
540
542
  | states | array | No | Pure labeling: tag each group with the FIRST matching state name |
541
543
  | liveStatuses | string[] | No | Statuses considered live (default `["pending"]`) |
542
544
  | orderBy | array | No | Order the RESULT groups: `{ field, direction? }` |
@@ -13,7 +13,7 @@ Built-in escalation and human queue management. Exposes the escalation API as MC
13
13
 
14
14
  These tools act with full authority. At `/mcp` they are listed for superadmin accounts only. Other accounts work the queue through the role-checked escalation tools on [long-tail-admin](admin.md).
15
15
 
16
- `get_escalation_lookups` is listed for every account. It runs as the caller, with the read check `GET /api/escalations/:id/lookups` runs.
16
+ `get_escalation_lookups` and `get_escalation_files` are listed for every account. Each runs as the caller, with the read check its REST route runs.
17
17
 
18
18
  ## Compile Hints
19
19
 
@@ -71,6 +71,22 @@ Any caller who may read the escalation may call it: a superadmin, a member of th
71
71
  |-------|------|----------|-------------|
72
72
  | escalation_id | string | Yes | The escalation whose pinned knowledge lookups to resolve |
73
73
 
74
+ ### get_escalation_files
75
+
76
+ Sign the stored files an escalation names (`envelope.files`). Each ref answers with `as`, `path`, `name`, `contentType`, a time-limited `url` and its `expiresAt`; a ref that cannot be signed answers with `error`. A link stretches to cover the caller's own live claim. See [files.md](../../hitl/files.md).
77
+
78
+ Any caller who may read the escalation may call it, under the same read check as `get_escalation_lookups`. An internal call reads as lt-system.
79
+
80
+ | | |
81
+ |---|---|
82
+ | Read-safe | Yes |
83
+
84
+ **Parameters:**
85
+
86
+ | Field | Type | Required | Description |
87
+ |-------|------|----------|-------------|
88
+ | escalation_id | string | Yes | The escalation whose stored files to sign |
89
+
74
90
  ### get_available_work
75
91
 
76
92
  List available escalations for a role. Returns pending, unassigned escalations.
@@ -197,6 +197,25 @@ const result = await lt.escalations.get({ id: 'esc_123' });
197
197
 
198
198
  ---
199
199
 
200
+ ## getFiles
201
+
202
+ Sign the stored files an escalation names (`envelope.files`). Enforces the same read scope as `get`; the refs on the row grant links to exactly the files they name. See [files](../../hitl/files.md).
203
+
204
+ ```typescript
205
+ const result = await lt.escalations.getFiles({ id: 'esc_123' });
206
+ // result.data.files → [{ as, path, name, contentType, url?, expiresAt?, error? }]
207
+ ```
208
+
209
+ **Parameters:**
210
+
211
+ | Field | Type | Required | Description |
212
+ |-------|------|----------|-------------|
213
+ | `id` | `string` | Yes | Escalation UUID |
214
+
215
+ **Returns:** `LTApiResult<{ files }>`
216
+
217
+ ---
218
+
200
219
  ## getLookups
201
220
 
202
221
  Resolve the versioned knowledge lookups pinned on an escalation (`envelope.lookups`). Enforces the same read scope as `get`; the refs on the row grant exactly the pinned editions they name. See [lookups](../../hitl/lookups.md).
@@ -1150,7 +1169,7 @@ const result = await lt.escalations.claimByFacets({
1150
1169
 
1151
1170
  ## aggregateByFacets
1152
1171
 
1153
- Grouped analytics over the escalation intervals — every escalation is one open interval `[created_at, ended_at)`, `ended_at` `NULL` while live. Two measures: **membership** (rows or, with `distinctBy`, distinct entities open at an instant; a past `asOf` reconstructs the live set then) and **dwell** (open-seconds per group within a half-open `[from, to)` window, clipped to it). `query.entity` names an entity facet key and scopes to every role declaring it as its `entity_facet` — the entity's system (mutually exclusive with `role`/`roles`); `groupBy.state` groups by the derived state label, each role contributing per its `entity_state_source`.
1172
+ Grouped analytics over the escalation intervals — every escalation is one open interval `[created_at, ended_at)`, `ended_at` `NULL` while live. Three measures: **membership** (rows or, with `distinctBy`, distinct entities open at an instant; a past `asOf` reconstructs the live set then), **dwell** (open-seconds per group within a half-open `[from, to)` window, clipped to it), and **resolved** (rows resolved within a window, optionally per UTC `day`, `week` or `month` bucket; requires a role scope). `query.entity` names an entity facet key and scopes to every role declaring it as its `entity_facet` — the entity's system (mutually exclusive with `role`/`roles`); `groupBy.state` groups by the derived state label, each role contributing per its `entity_state_source`.
1154
1173
 
1155
1174
  ```typescript
1156
1175
  // The printer fleet: how the entities spent the window, one row per state
@@ -1167,19 +1186,26 @@ await lt.escalations.aggregateByFacets({
1167
1186
  groupBy: { state: true, facets: ['model'] },
1168
1187
  measure: { kind: 'dwell', window: { from: '2026-08-01T00:00:00Z', to: '2026-08-02T00:00:00Z' } },
1169
1188
  });
1189
+
1190
+ // The trend: weekly review outcomes per extractor version
1191
+ await lt.escalations.aggregateByFacets({
1192
+ query: { role: 'intake-verifier' },
1193
+ groupBy: { facets: ['extractor', 'review_outcome'] },
1194
+ measure: { kind: 'resolved', window: { from: '2026-10-01T00:00:00Z', to: '2026-11-01T00:00:00Z' }, bucket: 'week' },
1195
+ });
1170
1196
  ```
1171
1197
 
1172
1198
  | Field | Type | Required | Description |
1173
1199
  |-------|------|----------|-------------|
1174
1200
  | `query` | `AnalyticsQuery` | Yes | The filter — `role`/`roles` or `entity`, plus `facets`, `anyOf` (rows carrying ANY of the given facet sets, max 200), `block`, `range`, `exists`, and `prefix` (case-insensitive prefix match on facet values — the locate affordance). `status`/`available`/`jeopardy` and query-level paging are rejected with 400: liveness derives from the interval, `liveStatuses`, and the measure anchor |
1175
1201
  | `groupBy` | `FacetGroupBy` | Yes | `columns` (`role`, `subtype`, `status`), `facets` (metadata keys), `state` (derived state label; mutually exclusive with `states[]`). Empty object → one total row |
1176
- | `measure` | `AggregateMeasure` | Yes | `{ kind: 'membership', asOf? }` or `{ kind: 'dwell', window }` |
1177
- | `distinctBy` | `string` | No | Membership only — count DISTINCT of this facet (entities, not rows) |
1202
+ | `measure` | `AggregateMeasure` | Yes | `{ kind: 'membership', asOf? }`, `{ kind: 'dwell', window }`, or `{ kind: 'resolved', window, bucket? }` |
1203
+ | `distinctBy` | `string` | No | Membership and resolved: count DISTINCT of this facet (entities, not rows) |
1178
1204
  | `states` | `Array<{ name, match }>` | No | Pure labeling: tag each group with the first matching state name |
1179
1205
  | `liveStatuses` | `string[]` | No | Statuses considered live (default `['pending']`) |
1180
1206
  | `orderBy` / `limit` / `offset` | — | No | Order and page the RESULT groups (capped at `LT_ANALYTICS_MAX_GROUPS`) |
1181
1207
 
1182
- **Returns:** `LTApiResult<{ groups: AggregateRow[]; overflow: boolean }>` — each group carries the grouped keys, `count` or `dwellSeconds`, and `sampleCount`. Gate: `read_all` on every role in scope (entity-derived roles included); a roleless filter requires a global principal; counts-only groupings (no `groupBy.facets`) are open to any login while `features.publicPaceBoard` stands. Mirrors `POST /api/escalations/aggregate-by-facets`.
1208
+ **Returns:** `LTApiResult<{ groups: AggregateRow[]; overflow: boolean }>` — each group carries the grouped keys, `count` or `dwellSeconds`, `bucket` when bucketed, and `sampleCount`. Gate: `read_all` on every role in scope (entity-derived roles included); a roleless filter requires a global principal; counts-only groupings (no `groupBy.facets`) are open to any login while `features.publicPaceBoard` stands. Mirrors `POST /api/escalations/aggregate-by-facets`.
1183
1209
 
1184
1210
  ## timelineByFacet
1185
1211
 
@@ -49,6 +49,25 @@ const result = await lt.files.delete({ filePath: 'screenshots/page.png' });
49
49
 
50
50
  **Returns:** `LTApiResult<{ deleted, path }>`
51
51
 
52
+ ## upload
53
+
54
+ Store bytes at a path, with their SHA-256 kept beside them. Name the digest you expect and a mismatch answers `422` with nothing stored.
55
+
56
+ ```typescript
57
+ const result = await lt.files.upload({
58
+ path: 'intake/APP-1042/application.pdf',
59
+ buffer: pdfBytes,
60
+ });
61
+ ```
62
+
63
+ | Parameter | Type | Required | Description |
64
+ |-----------|------|----------|-------------|
65
+ | `path` | `string` | Yes | Storage key |
66
+ | `buffer` | `Buffer` | Yes | The bytes |
67
+ | `sha256` | `string` | No | The expected digest, 64 hex characters |
68
+
69
+ **Returns:** `LTApiResult<{ path, size, content_type, sha256 }>`
70
+
52
71
  ## generateSignedUrl
53
72
 
54
73
  Generate a time-limited signed URL for sharing.
package/docs/cli.md CHANGED
@@ -85,9 +85,12 @@ ltc esc aggregate-facets --entity serialNumber --group-state \
85
85
  --window '{"from":"2026-08-01T00:00:00Z","to":"2026-08-02T00:00:00Z"}'
86
86
  # The individual: one printer's ordered interval timeline
87
87
  ltc esc timeline serialNumber PRN-001 --entity serialNumber
88
+ # The trend: weekly review outcomes per extractor version
89
+ ltc esc aggregate-facets --role intake-verifier --group-facets extractor,review_outcome \
90
+ --resolved '{"from":"2026-10-01T00:00:00Z","to":"2026-11-01T00:00:00Z"}' --bucket week
88
91
  ```
89
92
 
90
- `aggregate-facets` runs grouped analytics over the escalation intervals — membership at an instant (`--as-of`, default now), or dwell over a window (`--window` switches the measure). Scope with `--role`, `--roles`, or `--entity <key>` (the entity facet key — scopes to every role declaring it, the entity's system; no role at all spans every pond, global principals only). Group with `--group-columns role,subtype,status`, `--group-facets <list>`, or `--group-state` (the derived state label — each role's subtypes or itself). Refine with `--facets`/`--exists`, `--distinct-by <key>` (count entities, not rows; membership only), `--live-statuses`, and page the result groups with `--order-by`/`--limit`/`--offset`.
93
+ `aggregate-facets` runs grouped analytics over the escalation intervals — membership at an instant (`--as-of`, default now), dwell over a window (`--window` switches the measure), or rows resolved in a window (`--resolved`, with `--bucket day|week|month` for a trend; needs a role scope). Scope with `--role`, `--roles`, or `--entity <key>` (the entity facet key — scopes to every role declaring it, the entity's system; no role at all spans every pond, global principals only). Group with `--group-columns role,subtype,status`, `--group-facets <list>`, or `--group-state` (the derived state label — each role's subtypes or itself). Refine with `--facets`/`--exists`, `--distinct-by <key>` (count entities, not rows; membership and resolved), `--live-statuses`, and page the result groups with `--order-by`/`--limit`/`--offset`.
91
94
 
92
95
  `timeline <key> <value>` prints one entity's ordered escalation-interval timeline (gaps = untracked time). `--entity` scopes to the entity's system (every role declaring that entity facet); `--roles` restricts to specific roles; a call with neither spans every pond and requires a global principal. `--from`/`--to` keep only overlapping intervals; `--select-facets` surfaces metadata keys per interval.
93
96
 
@@ -101,6 +101,23 @@ await client.escalations.aggregateByFacets({
101
101
  // → one group per state, count = printers (not rows)
102
102
  ```
103
103
 
104
+ **Resolved** counts rows resolved within a window, optionally per UTC `day`,
105
+ `week` or `month` bucket. It answers trend questions: throughput per station
106
+ per week, or review outcomes per extractor version. It requires a role scope
107
+ (`role`, `roles` or `entity`) and reads the role-led resolved-rows index, so
108
+ its cost grows with the rows resolved in the window for those roles; the
109
+ window may span up to `LT_ANALYTICS_MAX_RESOLVED_WINDOW_DAYS` (default 366).
110
+
111
+ ```typescript
112
+ // Weekly review outcomes per extractor version
113
+ await client.escalations.aggregateByFacets({
114
+ query: { role: 'intake-verifier' },
115
+ groupBy: { facets: ['extractor', 'review_outcome'] },
116
+ measure: { kind: 'resolved', window: { from, to }, bucket: 'week' },
117
+ });
118
+ // → one group per (bucket, extractor, review_outcome), each with its count
119
+ ```
120
+
104
121
  ### Q2 — the slice: the same, compared by any facet
105
122
 
106
123
  Q1 plus `groupBy.facets` — each value gets an independent state split, and a
@@ -0,0 +1,104 @@
1
+ # Stored Files on an Escalation
2
+
3
+ An escalation can name **stored files** for the person who works it: the PDF a model read, a scanned card, a photo of a part. The refs ride the row; the bytes stay in file storage (S3, GCS through its S3 API, or MinIO locally). Readers receive time-limited signed links, and forms show the files through the `file.*` context domain with the `document` widget.
4
+
5
+ ---
6
+
7
+ ## The Ref
8
+
9
+ ```json
10
+ { "path": "referrals/R-1042.pdf", "as": "referral" }
11
+ { "path": "scans/8f2c41", "as": "card", "name": "ID card", "contentType": "image/jpeg", "expiresIn": 1800 }
12
+ ```
13
+
14
+ | Field | Required | Meaning |
15
+ |-------|----------|---------|
16
+ | `path` | yes | The storage key. A leading `/` is dropped; `.` and `..` segments are refused |
17
+ | `as` | yes | The form-context address, `file.<as>`: a letter or `_`, then letters, digits, `_` or `-` |
18
+ | `name` | no | The name the viewer shows and downloads under. Defaults to the key's last segment |
19
+ | `contentType` | no | The media type, for keys without an extension. Defaults to the type the extension names |
20
+ | `expiresIn` | no | The signed link's lifetime in seconds. Defaults to `LT_ESCALATION_FILE_URL_TTL_SECONDS` |
21
+
22
+ An escalation carries up to 32 refs, each `as` once. Refs live under the reserved `envelope.files` key: unindexed, beside `formDefaults` and `lookups`, never on the facet surface.
23
+
24
+ ## Creating an Escalation with Files
25
+
26
+ Pass `files` to `conditional`:
27
+
28
+ ```typescript
29
+ const review = await conditional<IntakeReviewV1>(signalId, {
30
+ role: 'intake-verifier',
31
+ description: `Account application — ${applicationId}`,
32
+ envelope: { formDefaults: extraction.values, confidence: extraction.confidence },
33
+ files: [
34
+ { path: `intake/${applicationId}/application.pdf`, as: 'application' },
35
+ { path: `intake/${applicationId}/id-card.jpg`, as: 'id_card', name: 'ID card' },
36
+ ],
37
+ schemaVersion: 1,
38
+ });
39
+ ```
40
+
41
+ The refs fold into `envelope.files` as a pure transform, so a wait with files costs what one without does. A malformed ref throws before the row is written. Over `POST /api/escalations` the same check answers `400`, and naming any file takes builder access (superadmin or engineer): a ref hands every reader of the row a link to that object, the same reach as the file browser.
42
+
43
+ ## The Grant and the Signing Window
44
+
45
+ The refs on the row are the grant. Any user who may read the escalation receives links to exactly the files it names:
46
+
47
+ ```
48
+ GET /api/escalations/:id/files
49
+ → { "files": [{ "as": "application", "path": "intake/APP-1042/application.pdf", "name": "application.pdf",
50
+ "contentType": "application/pdf", "url": "https://…", "expiresAt": "2026-11-09T15:39:31.859Z" }] }
51
+ ```
52
+
53
+ A link lives for the ref's `expiresIn`, or the default. When the reader holds the live claim, the link stretches to the claim's end, so a claimant's documents stay open for the whole claim. Every window is held within `LT_ESCALATION_FILE_URL_MIN_SECONDS` and `LT_ESCALATION_FILE_URL_MAX_SECONDS`.
54
+
55
+ | Variable | Default | Meaning |
56
+ |----------|---------|---------|
57
+ | `LT_ESCALATION_FILE_URL_TTL_SECONDS` | `900` | A link's lifetime when the ref names none |
58
+ | `LT_ESCALATION_FILE_URL_MIN_SECONDS` | `60` | The shortest link signed |
59
+ | `LT_ESCALATION_FILE_URL_MAX_SECONDS` | `14400` | The longest link signed, claim included |
60
+
61
+ A ref that cannot be signed answers with `error` in its entry; the batch always answers. The response carries `Cache-Control: no-store`.
62
+
63
+ The dashboard signs when the detail page opens and again on claim. A re-signed link for the same file keeps the open document and its place. A document that has not loaded and whose link has lapsed offers **Get a fresh link**; an open document outlives its link.
64
+
65
+ An agent reads the same answer with the `get_escalation_files` MCP tool, as the account it signed in with and under the same read check. SDK callers use `lt.escalations.getFiles({ id })`.
66
+
67
+ ## Showing a File
68
+
69
+ The `document` widget renders a file in place. Point `x-lt-source` at the ref's address:
70
+
71
+ ```json
72
+ {
73
+ "application": {
74
+ "type": "string",
75
+ "title": "Application",
76
+ "description": "The signed application as received.",
77
+ "x-lt-widget": "document",
78
+ "x-lt-source": "file.application"
79
+ }
80
+ }
81
+ ```
82
+
83
+ - **PDF**: continuous pages, fit to width, with paging, zoom and rotation. Pages paint as they near the view, so a long document opens fast.
84
+ - **Image**: fit to the frame, zoom and quarter-turn rotation, scrollable at any zoom.
85
+ - **Anything else**: an open link.
86
+
87
+ Every viewer carries open-in-a-new-tab and download. The field is display-only: it carries no answer and never reaches the payload. It stays readable and pageable before the claim and on a resolved row.
88
+
89
+ `x-lt-source` also takes an ordered list, and a field without a source shows its own value when that is an `http(s)` link. Conditions and help read the domain too: `"x-lt-showIf": "file.application"` shows a field when the row names that file, on the dashboard and in the server's enforcement pass alike.
90
+
91
+ ### Beside the fields: `x-lt-layout: "split"`
92
+
93
+ A split form puts its documents in a pane beside the fields they verify. The pane stays in view while the fields scroll, and a lone document fills it. Below the split width the pane stacks above the fields. See [x-lt-layout.md](x-lt-layout.md#split-layout).
94
+
95
+ ## Storage
96
+
97
+ - **S3 and MinIO**: links are presigned GETs against `LT_S3_PUBLIC_ENDPOINT`. The PDF viewer fetches the bytes, so the bucket's CORS rules must allow `GET` from the dashboard origin and expose `Accept-Ranges`, `Content-Range` and `Content-Length`; MinIO allows every origin by default. Images and open links need no CORS. Presigned links signed with temporary credentials end when those credentials do; keep `LT_ESCALATION_FILE_URL_MAX_SECONDS` within the session length.
98
+ - **Local**: links are `/api/files/<key>?token=…`, a JWT bound to the key, served same-origin under the app's base path.
99
+
100
+ Writes through the storage backend record each object's content type from its extension.
101
+
102
+ ## Reference Example
103
+
104
+ `examples/workflows/document-intake/` stores a sample application (PDF) and ID card (image), proposes values with a confidence score each, and parks one review on `intake-verifier`. See [x-lt-confidence.md](x-lt-confidence.md).