@hotmeshio/long-tail 0.25.1 → 0.25.3

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 (273) hide show
  1. package/build/api/escalations/batch-flag.d.ts +19 -0
  2. package/build/api/escalations/batch-flag.js +138 -0
  3. package/build/api/escalations/index.d.ts +2 -0
  4. package/build/api/escalations/index.js +8 -1
  5. package/build/api/escalations/roster-action.d.ts +37 -0
  6. package/build/api/escalations/roster-action.js +179 -0
  7. package/build/api/scan-codes/choice-roles.d.ts +3 -0
  8. package/build/api/scan-codes/choice-roles.js +48 -0
  9. package/build/api/scan-codes/choice.js +8 -0
  10. package/build/api/scan-codes/fill-labels.d.ts +15 -0
  11. package/build/api/scan-codes/fill-labels.js +99 -0
  12. package/build/api/scan-codes/hold.js +1 -0
  13. package/build/api/scan-codes/present.js +7 -2
  14. package/build/api/scan-codes/verb-fill.js +22 -5
  15. package/build/routes/escalations/resolve.js +45 -0
  16. package/build/sdk/index.d.ts +11 -0
  17. package/build/sdk/index.js +3 -0
  18. package/build/services/escalation/batch-flag.d.ts +25 -0
  19. package/build/services/escalation/batch-flag.js +51 -0
  20. package/build/services/escalation/index.d.ts +1 -0
  21. package/build/services/escalation/index.js +1 -0
  22. package/build/services/escalation/roster.d.ts +3 -1
  23. package/build/services/escalation/roster.js +6 -1
  24. package/build/services/scan-code/validate-subject.js +16 -0
  25. package/build/services/scan-code/validate.js +7 -0
  26. package/build/shared/form-validation/index.d.ts +1 -0
  27. package/build/shared/form-validation/index.js +1 -0
  28. package/build/shared/form-validation/x-lt-actions.d.ts +80 -0
  29. package/build/shared/form-validation/x-lt-actions.js +133 -0
  30. package/build/shared/form-validation/x-lt-roster.d.ts +2 -0
  31. package/build/shared/form-validation/x-lt-roster.js +28 -3
  32. package/build/tsconfig.tsbuildinfo +1 -1
  33. package/build/types/escalation.d.ts +19 -0
  34. package/build/types/escalation.js +4 -0
  35. package/build/types/index.d.ts +1 -1
  36. package/build/types/scan-choice.d.ts +9 -0
  37. package/build/types/scan-code/response.d.ts +2 -0
  38. package/build/types/scan-code/rule.d.ts +17 -0
  39. package/dashboard/dist/assets/{AdminDashboard-C_0ShYrm.js → AdminDashboard-DlItqxFS.js} +2 -2
  40. package/dashboard/dist/assets/{AdminDashboard-C_0ShYrm.js.map → AdminDashboard-DlItqxFS.js.map} +1 -1
  41. package/dashboard/dist/assets/{AgentConfigPage-Cc9dI8lO.js → AgentConfigPage-BUmT4a7n.js} +2 -2
  42. package/dashboard/dist/assets/{AgentConfigPage-Cc9dI8lO.js.map → AgentConfigPage-BUmT4a7n.js.map} +1 -1
  43. package/dashboard/dist/assets/{AgentDetailPage-Sdmt5j-k.js → AgentDetailPage-Cww8rlBi.js} +3 -3
  44. package/dashboard/dist/assets/{AgentDetailPage-Sdmt5j-k.js.map → AgentDetailPage-Cww8rlBi.js.map} +1 -1
  45. package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +2 -0
  46. package/dashboard/dist/assets/{AgentsPage-BuzXc1mg.js.map → AgentsPage-C9UuUKhr.js.map} +1 -1
  47. package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +2 -0
  48. package/dashboard/dist/assets/{AvailableEscalationsPage-DU84iaBN.js.map → AvailableEscalationsPage-DrvfXz70.js.map} +1 -1
  49. package/dashboard/dist/assets/{BotPicker-Ci5PUrkl.js → BotPicker-CDq9XRMp.js} +2 -2
  50. package/dashboard/dist/assets/{BotPicker-Ci5PUrkl.js.map → BotPicker-CDq9XRMp.js.map} +1 -1
  51. package/dashboard/dist/assets/{BulkAssignModal-PLx7SLvF.js → BulkAssignModal-jsvqtrEA.js} +2 -2
  52. package/dashboard/dist/assets/{BulkAssignModal-PLx7SLvF.js.map → BulkAssignModal-jsvqtrEA.js.map} +1 -1
  53. package/dashboard/dist/assets/{CapabilitiesPage-DuSfgr6i.js → CapabilitiesPage-CSCrI6B1.js} +2 -2
  54. package/dashboard/dist/assets/{CapabilitiesPage-DuSfgr6i.js.map → CapabilitiesPage-CSCrI6B1.js.map} +1 -1
  55. package/dashboard/dist/assets/{CollapsibleSection-KOO37qs6.js → CollapsibleSection-uD9mn-CQ.js} +2 -2
  56. package/dashboard/dist/assets/{CollapsibleSection-KOO37qs6.js.map → CollapsibleSection-uD9mn-CQ.js.map} +1 -1
  57. package/dashboard/dist/assets/{ConfirmDeleteModal-CI1eE-Nr.js → ConfirmDeleteModal-BRmx2hA4.js} +2 -2
  58. package/dashboard/dist/assets/{ConfirmDeleteModal-CI1eE-Nr.js.map → ConfirmDeleteModal-BRmx2hA4.js.map} +1 -1
  59. package/dashboard/dist/assets/{ConnectedAppsPage-DZgbCC0G.js → ConnectedAppsPage-DlMzE5a-.js} +2 -2
  60. package/dashboard/dist/assets/{ConnectedAppsPage-DZgbCC0G.js.map → ConnectedAppsPage-DlMzE5a-.js.map} +1 -1
  61. package/dashboard/dist/assets/{CountdownTimer-C-Ngk8oq.js → CountdownTimer-sRuM4eM5.js} +2 -2
  62. package/dashboard/dist/assets/{CountdownTimer-C-Ngk8oq.js.map → CountdownTimer-sRuM4eM5.js.map} +1 -1
  63. package/dashboard/dist/assets/{CredentialsPage-BR7s6eVu.js → CredentialsPage-bLYydwqa.js} +2 -2
  64. package/dashboard/dist/assets/{CredentialsPage-BR7s6eVu.js.map → CredentialsPage-bLYydwqa.js.map} +1 -1
  65. package/dashboard/dist/assets/{CronLabel-BQ7Y1Nfd.js → CronLabel-D_ATDL2N.js} +2 -2
  66. package/dashboard/dist/assets/{CronLabel-BQ7Y1Nfd.js.map → CronLabel-D_ATDL2N.js.map} +1 -1
  67. package/dashboard/dist/assets/{DropZone-DCZpORx-.js → DropZone-u1JGfR9G.js} +2 -2
  68. package/dashboard/dist/assets/{DropZone-DCZpORx-.js.map → DropZone-u1JGfR9G.js.map} +1 -1
  69. package/dashboard/dist/assets/{ElapsedCell-BT49mUIc.js → ElapsedCell-groSMfqB.js} +2 -2
  70. package/dashboard/dist/assets/{ElapsedCell-BT49mUIc.js.map → ElapsedCell-groSMfqB.js.map} +1 -1
  71. package/dashboard/dist/assets/{EntityTimelinePanel-BtARWy3R.js → EntityTimelinePanel-D-F3_A9m.js} +2 -2
  72. package/dashboard/dist/assets/{EntityTimelinePanel-BtARWy3R.js.map → EntityTimelinePanel-D-F3_A9m.js.map} +1 -1
  73. package/dashboard/dist/assets/{EscalationListSchemaPage-EEBsNpTe.js → EscalationListSchemaPage-Bad6Jrmr.js} +2 -2
  74. package/dashboard/dist/assets/{EscalationListSchemaPage-EEBsNpTe.js.map → EscalationListSchemaPage-Bad6Jrmr.js.map} +1 -1
  75. package/dashboard/dist/assets/{EscalationSchemaPage-BHSC46Ow.js → EscalationSchemaPage-BKi_npI9.js} +3 -3
  76. package/dashboard/dist/assets/{EscalationSchemaPage-BHSC46Ow.js.map → EscalationSchemaPage-BKi_npI9.js.map} +1 -1
  77. package/dashboard/dist/assets/EscalationTimeline-DQUUm3b1.js +2 -0
  78. package/dashboard/dist/assets/{EscalationTimeline-BWTUBxUf.js.map → EscalationTimeline-DQUUm3b1.js.map} +1 -1
  79. package/dashboard/dist/assets/{EscalationTitleSelect-DOsfY4u8.js → EscalationTitleSelect-3mhXh77a.js} +2 -2
  80. package/dashboard/dist/assets/{EscalationTitleSelect-DOsfY4u8.js.map → EscalationTitleSelect-3mhXh77a.js.map} +1 -1
  81. package/dashboard/dist/assets/{EscalationsOverview-Bl8g53x-.js → EscalationsOverview-Qaov-uML.js} +2 -2
  82. package/dashboard/dist/assets/{EscalationsOverview-Bl8g53x-.js.map → EscalationsOverview-Qaov-uML.js.map} +1 -1
  83. package/dashboard/dist/assets/{EventTable-Bjx17W_i.js → EventTable-V4RF_n58.js} +2 -2
  84. package/dashboard/dist/assets/{EventTable-Bjx17W_i.js.map → EventTable-V4RF_n58.js.map} +1 -1
  85. package/dashboard/dist/assets/{FilterBar-Dnse0soD.js → FilterBar-BygWrnB1.js} +2 -2
  86. package/dashboard/dist/assets/{FilterBar-Dnse0soD.js.map → FilterBar-BygWrnB1.js.map} +1 -1
  87. package/dashboard/dist/assets/{GraphInvokePage-HQEvbHTd.js → GraphInvokePage-Djslhf96.js} +2 -2
  88. package/dashboard/dist/assets/{GraphInvokePage-HQEvbHTd.js.map → GraphInvokePage-Djslhf96.js.map} +1 -1
  89. package/dashboard/dist/assets/{HomePage-DizTklVg.js → HomePage-EjcNxlKx.js} +2 -2
  90. package/dashboard/dist/assets/{HomePage-DizTklVg.js.map → HomePage-EjcNxlKx.js.map} +1 -1
  91. package/dashboard/dist/assets/{ListToolbar-B0qe2QZ5.js → ListToolbar-RrEAePOX.js} +2 -2
  92. package/dashboard/dist/assets/{ListToolbar-B0qe2QZ5.js.map → ListToolbar-RrEAePOX.js.map} +1 -1
  93. package/dashboard/dist/assets/{McpOverview-DmH-qtX9.js → McpOverview-8gqiL3Vj.js} +2 -2
  94. package/dashboard/dist/assets/{McpOverview-DmH-qtX9.js.map → McpOverview-8gqiL3Vj.js.map} +1 -1
  95. package/dashboard/dist/assets/{McpQueryDetailPage-B-qtmwLd.js → McpQueryDetailPage-COyn6Ak5.js} +2 -2
  96. package/dashboard/dist/assets/{McpQueryDetailPage-B-qtmwLd.js.map → McpQueryDetailPage-COyn6Ak5.js.map} +1 -1
  97. package/dashboard/dist/assets/{McpQueryPage-DX1T-Ugq.js → McpQueryPage-Dj6Qj72w.js} +2 -2
  98. package/dashboard/dist/assets/{McpQueryPage-DX1T-Ugq.js.map → McpQueryPage-Dj6Qj72w.js.map} +1 -1
  99. package/dashboard/dist/assets/{McpRunDetailPage-DNdl10nB.js → McpRunDetailPage-80fQn9iX.js} +2 -2
  100. package/dashboard/dist/assets/{McpRunDetailPage-DNdl10nB.js.map → McpRunDetailPage-80fQn9iX.js.map} +1 -1
  101. package/dashboard/dist/assets/{McpRunsPage-DVXVB4AJ.js → McpRunsPage-DaSsI-EM.js} +2 -2
  102. package/dashboard/dist/assets/{McpRunsPage-DVXVB4AJ.js.map → McpRunsPage-DaSsI-EM.js.map} +1 -1
  103. package/dashboard/dist/assets/{NamespacePill-CSZT2fA4.js → NamespacePill-C5epAgq6.js} +2 -2
  104. package/dashboard/dist/assets/{NamespacePill-CSZT2fA4.js.map → NamespacePill-C5epAgq6.js.map} +1 -1
  105. package/dashboard/dist/assets/{OperationsPage-BxgWQq8v.js → OperationsPage-BSu1o2gB.js} +2 -2
  106. package/dashboard/dist/assets/{OperationsPage-BxgWQq8v.js.map → OperationsPage-BSu1o2gB.js.map} +1 -1
  107. package/dashboard/dist/assets/OperatorDashboard-HFI4WGIV.js +2 -0
  108. package/dashboard/dist/assets/{OperatorDashboard-Cw86vOPg.js.map → OperatorDashboard-HFI4WGIV.js.map} +1 -1
  109. package/dashboard/dist/assets/{PageHeader-C4z1ExF7.js → PageHeader-BSWIspNB.js} +2 -2
  110. package/dashboard/dist/assets/{PageHeader-C4z1ExF7.js.map → PageHeader-BSWIspNB.js.map} +1 -1
  111. package/dashboard/dist/assets/{PageHeaderWithStats-B_f_Sz_Q.js → PageHeaderWithStats-DDjopQ-k.js} +2 -2
  112. package/dashboard/dist/assets/{PageHeaderWithStats-B_f_Sz_Q.js.map → PageHeaderWithStats-DDjopQ-k.js.map} +1 -1
  113. package/dashboard/dist/assets/{PersonaDetailPage-BTIJ4A6p.js → PersonaDetailPage-D0qlBuGi.js} +2 -2
  114. package/dashboard/dist/assets/{PersonaDetailPage-BTIJ4A6p.js.map → PersonaDetailPage-D0qlBuGi.js.map} +1 -1
  115. package/dashboard/dist/assets/{PersonasPage-D11PokPb.js → PersonasPage-BJClu-5H.js} +2 -2
  116. package/dashboard/dist/assets/{PersonasPage-D11PokPb.js.map → PersonasPage-BJClu-5H.js.map} +1 -1
  117. package/dashboard/dist/assets/PortalPage-CucNZn_w.js +2 -0
  118. package/dashboard/dist/assets/{PortalPage-1rXm0cNK.js.map → PortalPage-CucNZn_w.js.map} +1 -1
  119. package/dashboard/dist/assets/{ProcessDetailPage-Cp5-969g.js → ProcessDetailPage-B9wMw0RV.js} +2 -2
  120. package/dashboard/dist/assets/{ProcessDetailPage-Cp5-969g.js.map → ProcessDetailPage-B9wMw0RV.js.map} +1 -1
  121. package/dashboard/dist/assets/{ProcessesListPage-assXQe-x.js → ProcessesListPage-B6k4RpmR.js} +2 -2
  122. package/dashboard/dist/assets/{ProcessesListPage-assXQe-x.js.map → ProcessesListPage-B6k4RpmR.js.map} +1 -1
  123. package/dashboard/dist/assets/ResolverForm-ZVufJ4G-.js +8 -0
  124. package/dashboard/dist/assets/ResolverForm-ZVufJ4G-.js.map +1 -0
  125. package/dashboard/dist/assets/{RoleDetailPage-c_Qij0Tf.js → RoleDetailPage-CTbq0mz4.js} +2 -2
  126. package/dashboard/dist/assets/{RoleDetailPage-c_Qij0Tf.js.map → RoleDetailPage-CTbq0mz4.js.map} +1 -1
  127. package/dashboard/dist/assets/{RolePill-Bw_n7EpR.js → RolePill-CoETDpjF.js} +2 -2
  128. package/dashboard/dist/assets/{RolePill-Bw_n7EpR.js.map → RolePill-CoETDpjF.js.map} +1 -1
  129. package/dashboard/dist/assets/{RolesPage-D4oaYgTg.js → RolesPage-DBKxeam4.js} +2 -2
  130. package/dashboard/dist/assets/{RolesPage-D4oaYgTg.js.map → RolesPage-DBKxeam4.js.map} +1 -1
  131. package/dashboard/dist/assets/RosterWidget-BkLAwEYB.js +2 -0
  132. package/dashboard/dist/assets/RosterWidget-BkLAwEYB.js.map +1 -0
  133. package/dashboard/dist/assets/{RunAsSelector-Fptil_sB.js → RunAsSelector-D2DC4iDf.js} +2 -2
  134. package/dashboard/dist/assets/{RunAsSelector-Fptil_sB.js.map → RunAsSelector-D2DC4iDf.js.map} +1 -1
  135. package/dashboard/dist/assets/{ScanCodesPage-BeZA_YJW.js → ScanCodesPage-BlKleaT0.js} +2 -2
  136. package/dashboard/dist/assets/{ScanCodesPage-BeZA_YJW.js.map → ScanCodesPage-BlKleaT0.js.map} +1 -1
  137. package/dashboard/dist/assets/{ScanSchemeDetailPage-Bxi15xNr.js → ScanSchemeDetailPage-CTW6gofi.js} +2 -2
  138. package/dashboard/dist/assets/{ScanSchemeDetailPage-Bxi15xNr.js.map → ScanSchemeDetailPage-CTW6gofi.js.map} +1 -1
  139. package/dashboard/dist/assets/ScanStationPage-DPRjSPyT.js +2 -0
  140. package/dashboard/dist/assets/ScanStationPage-DPRjSPyT.js.map +1 -0
  141. package/dashboard/dist/assets/{ScopeBadge-CKgfwTy3.js → ScopeBadge-CGsTtqFr.js} +2 -2
  142. package/dashboard/dist/assets/{ScopeBadge-CKgfwTy3.js.map → ScopeBadge-CGsTtqFr.js.map} +1 -1
  143. package/dashboard/dist/assets/{StickyPagination-C2drZk7w.js → StickyPagination-CkmX3-Gu.js} +2 -2
  144. package/dashboard/dist/assets/{StickyPagination-C2drZk7w.js.map → StickyPagination-CkmX3-Gu.js.map} +1 -1
  145. package/dashboard/dist/assets/{StreamMessageDetail-x-l5653y.js → StreamMessageDetail-Xm_n510s.js} +2 -2
  146. package/dashboard/dist/assets/{StreamMessageDetail-x-l5653y.js.map → StreamMessageDetail-Xm_n510s.js.map} +1 -1
  147. package/dashboard/dist/assets/{SwimlaneTimeline-Ds_CqLXL.js → SwimlaneTimeline-De48aJan.js} +2 -2
  148. package/dashboard/dist/assets/{SwimlaneTimeline-Ds_CqLXL.js.map → SwimlaneTimeline-De48aJan.js.map} +1 -1
  149. package/dashboard/dist/assets/{TagInput-B6fMAqxd.js → TagInput-S7UuVT_M.js} +2 -2
  150. package/dashboard/dist/assets/{TagInput-B6fMAqxd.js.map → TagInput-S7UuVT_M.js.map} +1 -1
  151. package/dashboard/dist/assets/{TaskDetailPage-BJGKEnIo.js → TaskDetailPage-HycMx3O9.js} +2 -2
  152. package/dashboard/dist/assets/{TaskDetailPage-BJGKEnIo.js.map → TaskDetailPage-HycMx3O9.js.map} +1 -1
  153. package/dashboard/dist/assets/{TaskQueuePill-BnDp_DE6.js → TaskQueuePill-BlHNpYiZ.js} +2 -2
  154. package/dashboard/dist/assets/{TaskQueuePill-BnDp_DE6.js.map → TaskQueuePill-BlHNpYiZ.js.map} +1 -1
  155. package/dashboard/dist/assets/{TasksListPage-DyLaZvTT.js → TasksListPage-OIcFFp1C.js} +2 -2
  156. package/dashboard/dist/assets/{TasksListPage-DyLaZvTT.js.map → TasksListPage-OIcFFp1C.js.map} +1 -1
  157. package/dashboard/dist/assets/{TimeAgo-B_Ta97uy.js → TimeAgo-OTC_55oZ.js} +2 -2
  158. package/dashboard/dist/assets/{TimeAgo-B_Ta97uy.js.map → TimeAgo-OTC_55oZ.js.map} +1 -1
  159. package/dashboard/dist/assets/{TimestampCell-CiTYBQw-.js → TimestampCell-CAwIj_AI.js} +2 -2
  160. package/dashboard/dist/assets/{TimestampCell-CiTYBQw-.js.map → TimestampCell-CAwIj_AI.js.map} +1 -1
  161. package/dashboard/dist/assets/{ToolPill-BRZWo4l8.js → ToolPill-D40uLM_v.js} +2 -2
  162. package/dashboard/dist/assets/{ToolPill-BRZWo4l8.js.map → ToolPill-D40uLM_v.js.map} +1 -1
  163. package/dashboard/dist/assets/{ToolTestPanel-Dw8Zu6xr.js → ToolTestPanel-8Vf6pfw4.js} +2 -2
  164. package/dashboard/dist/assets/{ToolTestPanel-Dw8Zu6xr.js.map → ToolTestPanel-8Vf6pfw4.js.map} +1 -1
  165. package/dashboard/dist/assets/{TopicDetailPage-DPMAWKTN.js → TopicDetailPage-iZW8rK9L.js} +2 -2
  166. package/dashboard/dist/assets/{TopicDetailPage-DPMAWKTN.js.map → TopicDetailPage-iZW8rK9L.js.map} +1 -1
  167. package/dashboard/dist/assets/{TopicsPage-0Z2lAE0d.js → TopicsPage-CqiEcj-W.js} +2 -2
  168. package/dashboard/dist/assets/{TopicsPage-0Z2lAE0d.js.map → TopicsPage-CqiEcj-W.js.map} +1 -1
  169. package/dashboard/dist/assets/{UserName-DrAbCpdY.js → UserName-DQFjuoib.js} +2 -2
  170. package/dashboard/dist/assets/{UserName-DrAbCpdY.js.map → UserName-DQFjuoib.js.map} +1 -1
  171. package/dashboard/dist/assets/{WorkflowExecutionPage-DQITqX-6.js → WorkflowExecutionPage-Di08wCbs.js} +2 -2
  172. package/dashboard/dist/assets/{WorkflowExecutionPage-DQITqX-6.js.map → WorkflowExecutionPage-Di08wCbs.js.map} +1 -1
  173. package/dashboard/dist/assets/{WorkflowPill-Cly9Ln_3.js → WorkflowPill-DJLcK_CM.js} +2 -2
  174. package/dashboard/dist/assets/{WorkflowPill-Cly9Ln_3.js.map → WorkflowPill-DJLcK_CM.js.map} +1 -1
  175. package/dashboard/dist/assets/{WorkflowsDashboard-CMJPiR6G.js → WorkflowsDashboard-Bb8HlrTJ.js} +2 -2
  176. package/dashboard/dist/assets/{WorkflowsDashboard-CMJPiR6G.js.map → WorkflowsDashboard-Bb8HlrTJ.js.map} +1 -1
  177. package/dashboard/dist/assets/{WorkflowsOverview-DwVMLe1y.js → WorkflowsOverview-Dta1kurk.js} +2 -2
  178. package/dashboard/dist/assets/{WorkflowsOverview-DwVMLe1y.js.map → WorkflowsOverview-Dta1kurk.js.map} +1 -1
  179. package/dashboard/dist/assets/{YamlWorkflowDetailPage-Do6s_wmW.js → YamlWorkflowDetailPage-CfAajg68.js} +2 -2
  180. package/dashboard/dist/assets/{YamlWorkflowDetailPage-Do6s_wmW.js.map → YamlWorkflowDetailPage-CfAajg68.js.map} +1 -1
  181. package/dashboard/dist/assets/{YamlWorkflowsPage-8Sr6rZMZ.js → YamlWorkflowsPage-CQFUzT4t.js} +2 -2
  182. package/dashboard/dist/assets/{YamlWorkflowsPage-8Sr6rZMZ.js.map → YamlWorkflowsPage-CQFUzT4t.js.map} +1 -1
  183. package/dashboard/dist/assets/{agents-Maom-dbf.js → agents-PuftRTB2.js} +2 -2
  184. package/dashboard/dist/assets/{agents-Maom-dbf.js.map → agents-PuftRTB2.js.map} +1 -1
  185. package/dashboard/dist/assets/{bots-BESWftTA.js → bots-BmEiPAWY.js} +2 -2
  186. package/dashboard/dist/assets/{bots-BESWftTA.js.map → bots-BmEiPAWY.js.map} +1 -1
  187. package/dashboard/dist/assets/{capabilities-BnvJAmFQ.js → capabilities-CRii4Soa.js} +2 -2
  188. package/dashboard/dist/assets/{capabilities-BnvJAmFQ.js.map → capabilities-CRii4Soa.js.map} +1 -1
  189. package/dashboard/dist/assets/{controlplane-Cu7TD1RX.js → controlplane-DO_czaYo.js} +2 -2
  190. package/dashboard/dist/assets/{controlplane-Cu7TD1RX.js.map → controlplane-DO_czaYo.js.map} +1 -1
  191. package/dashboard/dist/assets/escalation-columns-CzCquCPh.js +2 -0
  192. package/dashboard/dist/assets/{escalation-columns-BPSH8qMx.js.map → escalation-columns-CzCquCPh.js.map} +1 -1
  193. package/dashboard/dist/assets/escalation-items-Cy0ZgJqV.js +2 -0
  194. package/dashboard/dist/assets/escalation-items-Cy0ZgJqV.js.map +1 -0
  195. package/dashboard/dist/assets/{index-BkVarz6E.js → index-2SM2_onB.js} +2 -2
  196. package/dashboard/dist/assets/{index-BkVarz6E.js.map → index-2SM2_onB.js.map} +1 -1
  197. package/dashboard/dist/assets/{index-BG7OpNg7.js → index-4YaDUcKd.js} +2 -2
  198. package/dashboard/dist/assets/{index-BG7OpNg7.js.map → index-4YaDUcKd.js.map} +1 -1
  199. package/dashboard/dist/assets/{index-D5JQweUm.js → index-CL_1VpGb.js} +2 -2
  200. package/dashboard/dist/assets/{index-D5JQweUm.js.map → index-CL_1VpGb.js.map} +1 -1
  201. package/dashboard/dist/assets/{index-BpWutGxS.js → index-CZ7A3AcD.js} +2 -2
  202. package/dashboard/dist/assets/{index-BpWutGxS.js.map → index-CZ7A3AcD.js.map} +1 -1
  203. package/dashboard/dist/assets/index-CfP2nKRc.js +3 -0
  204. package/dashboard/dist/assets/{index-kGSUZCOb.js.map → index-CfP2nKRc.js.map} +1 -1
  205. package/dashboard/dist/assets/{index-B4SNhwgt.js → index-Cga5IW3D.js} +2 -2
  206. package/dashboard/dist/assets/{index-B4SNhwgt.js.map → index-Cga5IW3D.js.map} +1 -1
  207. package/dashboard/dist/assets/{index-WA8py2Yc.js → index-Cx8xb-oU.js} +2 -2
  208. package/dashboard/dist/assets/{index-WA8py2Yc.js.map → index-Cx8xb-oU.js.map} +1 -1
  209. package/dashboard/dist/assets/index-DhSCCpqM.js +2 -0
  210. package/dashboard/dist/assets/{index-AJNPDsTI.js.map → index-DhSCCpqM.js.map} +1 -1
  211. package/dashboard/dist/assets/{index-BLlg1aVG.js → index-DiaRlFYI.js} +2 -2
  212. package/dashboard/dist/assets/{index-BLlg1aVG.js.map → index-DiaRlFYI.js.map} +1 -1
  213. package/dashboard/dist/assets/{index-BLbZsMRG.js → index-Dz6R8-Dw.js} +14 -14
  214. package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +1 -0
  215. package/dashboard/dist/assets/{index-BvI2_dSt.js → index-Rwqrflm-.js} +2 -2
  216. package/dashboard/dist/assets/{index-BvI2_dSt.js.map → index-Rwqrflm-.js.map} +1 -1
  217. package/dashboard/dist/assets/{index-_yHsJJTS.js → index-XntldBd0.js} +2 -2
  218. package/dashboard/dist/assets/{index-_yHsJJTS.js.map → index-XntldBd0.js.map} +1 -1
  219. package/dashboard/dist/assets/index-jL2K6us4.js +13 -0
  220. package/dashboard/dist/assets/{index-qY2KDGkM.js.map → index-jL2K6us4.js.map} +1 -1
  221. package/dashboard/dist/assets/{knowledge-DCFRNG8R.js → knowledge-CeUqGPuo.js} +2 -2
  222. package/dashboard/dist/assets/{knowledge-DCFRNG8R.js.map → knowledge-CeUqGPuo.js.map} +1 -1
  223. package/dashboard/dist/assets/{mcp-CZhOocmN.js → mcp-Cx96NTeD.js} +2 -2
  224. package/dashboard/dist/assets/{mcp-CZhOocmN.js.map → mcp-Cx96NTeD.js.map} +1 -1
  225. package/dashboard/dist/assets/{mcp-query-Wt8z6yAL.js → mcp-query-XAzWl0gm.js} +2 -2
  226. package/dashboard/dist/assets/{mcp-query-Wt8z6yAL.js.map → mcp-query-XAzWl0gm.js.map} +1 -1
  227. package/dashboard/dist/assets/{personas-D2_foqJm.js → personas--4kjwyOw.js} +2 -2
  228. package/dashboard/dist/assets/{personas-D2_foqJm.js.map → personas--4kjwyOw.js.map} +1 -1
  229. package/dashboard/dist/assets/{pipelines-Bb159fNz.js → pipelines-PgkwvG7f.js} +2 -2
  230. package/dashboard/dist/assets/{pipelines-Bb159fNz.js.map → pipelines-PgkwvG7f.js.map} +1 -1
  231. package/dashboard/dist/assets/{tasks-xAU6C6tb.js → tasks-CcYxdBa3.js} +2 -2
  232. package/dashboard/dist/assets/{tasks-xAU6C6tb.js.map → tasks-CcYxdBa3.js.map} +1 -1
  233. package/dashboard/dist/assets/{topics-DFdqb2Te.js → topics-_lik7cNY.js} +2 -2
  234. package/dashboard/dist/assets/{topics-DFdqb2Te.js.map → topics-_lik7cNY.js.map} +1 -1
  235. package/dashboard/dist/assets/{useDebouncedValue-CbHmpS4w.js → useDebouncedValue-Bm_AoxVx.js} +2 -2
  236. package/dashboard/dist/assets/{useDebouncedValue-CbHmpS4w.js.map → useDebouncedValue-Bm_AoxVx.js.map} +1 -1
  237. package/dashboard/dist/assets/{useNamespace-B_00X1yb.js → useNamespace-DgXXKdx5.js} +2 -2
  238. package/dashboard/dist/assets/{useNamespace-B_00X1yb.js.map → useNamespace-DgXXKdx5.js.map} +1 -1
  239. package/dashboard/dist/assets/{useYamlActivityEvents-B4F-s9g0.js → useYamlActivityEvents-Dj2qtGSd.js} +2 -2
  240. package/dashboard/dist/assets/{useYamlActivityEvents-B4F-s9g0.js.map → useYamlActivityEvents-Dj2qtGSd.js.map} +1 -1
  241. package/dashboard/dist/assets/validate-FlXCBBT6.js +2 -0
  242. package/dashboard/dist/assets/validate-FlXCBBT6.js.map +1 -0
  243. package/dashboard/dist/assets/{vendor-icons-C_DQEeBy.js → vendor-icons-DUYcKTjP.js} +2 -2
  244. package/dashboard/dist/assets/{vendor-icons-C_DQEeBy.js.map → vendor-icons-DUYcKTjP.js.map} +1 -1
  245. package/dashboard/dist/assets/{yaml-workflows-DyjbPFVp.js → yaml-workflows-B0_JxRYQ.js} +2 -2
  246. package/dashboard/dist/assets/{yaml-workflows-DyjbPFVp.js.map → yaml-workflows-B0_JxRYQ.js.map} +1 -1
  247. package/dashboard/dist/index.html +2 -2
  248. package/docs/accumulator.md +1 -1
  249. package/docs/api/http/escalations.md +33 -0
  250. package/docs/api/sdk/escalations.md +26 -1
  251. package/docs/hitl/escalation.md +9 -0
  252. package/docs/hitl/x-lt-embed.md +2 -0
  253. package/docs/hitl/x-lt-roster.md +31 -7
  254. package/docs/scan-codes.md +50 -3
  255. package/package.json +2 -2
  256. package/dashboard/dist/assets/AgentsPage-BuzXc1mg.js +0 -2
  257. package/dashboard/dist/assets/AvailableEscalationsPage-DU84iaBN.js +0 -2
  258. package/dashboard/dist/assets/EscalationTimeline-BWTUBxUf.js +0 -2
  259. package/dashboard/dist/assets/FormattedValue-DeVrRJy4.js +0 -2
  260. package/dashboard/dist/assets/FormattedValue-DeVrRJy4.js.map +0 -1
  261. package/dashboard/dist/assets/OperatorDashboard-Cw86vOPg.js +0 -2
  262. package/dashboard/dist/assets/PortalPage-1rXm0cNK.js +0 -2
  263. package/dashboard/dist/assets/ResolverForm-CMzNjmGG.js +0 -8
  264. package/dashboard/dist/assets/ResolverForm-CMzNjmGG.js.map +0 -1
  265. package/dashboard/dist/assets/ScanStationPage-t5Bz957t.js +0 -2
  266. package/dashboard/dist/assets/ScanStationPage-t5Bz957t.js.map +0 -1
  267. package/dashboard/dist/assets/escalation-columns-BPSH8qMx.js +0 -2
  268. package/dashboard/dist/assets/escalation-items-uDQTphVW.js +0 -2
  269. package/dashboard/dist/assets/escalation-items-uDQTphVW.js.map +0 -1
  270. package/dashboard/dist/assets/index-AJNPDsTI.js +0 -2
  271. package/dashboard/dist/assets/index-BLbZsMRG.js.map +0 -1
  272. package/dashboard/dist/assets/index-kGSUZCOb.js +0 -3
  273. package/dashboard/dist/assets/index-qY2KDGkM.js +0 -13
@@ -40,6 +40,7 @@ const resolve_batch_1 = require("../escalations/resolve-batch");
40
40
  const escalation_1 = require("../../types/escalation");
41
41
  const types_1 = require("../../types");
42
42
  const context_1 = require("./context");
43
+ const fill_labels_1 = require("./fill-labels");
43
44
  const grant_1 = require("./grant");
44
45
  const locate_1 = require("./locate");
45
46
  const subject_1 = require("./subject");
@@ -60,6 +61,18 @@ function codeOf(key, separator) {
60
61
  function keysFor(keys, target, separator) {
61
62
  return keys.filter((k) => codeOf(k, separator) === target);
62
63
  }
64
+ /** Labeled pending entries read as one line; labels may carry commas. */
65
+ const LABEL_JOIN = '; ';
66
+ /** The `{fill.pending}` and `{fill.next}` values for the open keys. */
67
+ function pendingCopy(pending, separator, labeler) {
68
+ const code = (key) => codeOf(key, separator);
69
+ if (!labeler) {
70
+ const codes = [...new Set(pending.map(code))];
71
+ return { pending: codes, ...(codes.length ? { next: codes[0] } : {}) };
72
+ }
73
+ const labels = (0, fill_labels_1.pendingLabels)(pending, code, labeler);
74
+ return { pending: labels.join(LABEL_JOIN), ...(labels.length ? { next: labels[0] } : {}) };
75
+ }
63
76
  function progress(batch, filledNow) {
64
77
  const remaining = Math.max(0, batch.pending.length - filledNow);
65
78
  return { filled: batch.keys.length - remaining, total: batch.keys.length, remaining };
@@ -82,10 +95,12 @@ async function fillStep(step, ctx) {
82
95
  if (!batch)
83
96
  return (0, context_1.conflict)('the held row is not a batch');
84
97
  // 2. Which open slot this scan fills, or why none
98
+ const labeler = (0, fill_labels_1.entryLabeler)(options, row, ctx.scheme);
99
+ const open = pendingCopy(batch.pending, separator, labeler);
85
100
  const tpl = {
86
101
  ...(0, context_1.templateContext)(ctx),
87
102
  fill: {
88
- pending: [...new Set(batch.pending.map((k) => codeOf(k, separator)))],
103
+ ...open,
89
104
  total: batch.keys.length,
90
105
  filled: batch.keys.length - batch.pending.length,
91
106
  },
@@ -96,9 +111,10 @@ async function fillStep(step, ctx) {
96
111
  const markdown = declared.length
97
112
  ? `All ${declared.length} of these are already checked off.`
98
113
  : scanCodeService.renderScanCopy(step.refuse?.markdown ?? STOCK_UNEXPECTED, tpl);
99
- const expected = ctx.scheme.encoding === types_1.SCAN_ENCODINGS.GTIN
100
- ? tpl.fill.pending.map((code) => scanCodeService.displayGtin(code))
101
- : tpl.fill.pending;
114
+ const codes = [...new Set(batch.pending.map((k) => codeOf(k, separator)))];
115
+ const expected = labeler
116
+ ? (0, fill_labels_1.pendingLabels)(batch.pending, (k) => codeOf(k, separator), labeler)
117
+ : codes.map((code) => (0, fill_labels_1.printedCode)(code, ctx.scheme));
102
118
  return (0, context_1.refused)(markdown, {
103
119
  refusal: { markdown, expected },
104
120
  progress: progress(batch, 0),
@@ -125,6 +141,7 @@ async function fillStep(step, ctx) {
125
141
  const data = result.data;
126
142
  const done = data.outcome === 'completed';
127
143
  const filled = progress(batch, batch.pending.length - (done ? 0 : (data.remaining ?? 0)));
144
+ const next = pendingCopy(batch.pending.filter((k) => k !== itemKey), separator, labeler).next;
128
145
  return (0, context_1.withDone)({
129
146
  status: 200,
130
147
  data: {
@@ -134,7 +151,7 @@ async function fillStep(step, ctx) {
134
151
  progress: filled,
135
152
  ...(done ? { clearSubject: true } : {}),
136
153
  },
137
- }, step, { ...tpl, fill: { ...tpl.fill, ...filled } });
154
+ }, step, { ...tpl, fill: { ...tpl.fill, ...filled, next } });
138
155
  }
139
156
  const outcome = result.data?.outcome;
140
157
  if (outcome === 'duplicate-item')
@@ -126,6 +126,51 @@ function registerResolveRoutes(router) {
126
126
  }, auth);
127
127
  res.status(result.status).json(result.data ?? { error: result.error });
128
128
  });
129
+ /**
130
+ * POST /api/escalations/:id/flag-batch-item
131
+ * Flag ONE pending key of a batch escalation (e.g. `Missing`). The key stays
132
+ * pending and still fills; a wait declared with `wakeOnFlag` ends on the flag.
133
+ * Body: { itemKey: string, label: string, payload?: Record<string, any> }
134
+ */
135
+ router.post('/:id/flag-batch-item', async (req, res) => {
136
+ const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
137
+ if (!auth)
138
+ return;
139
+ const result = await api.flagBatchItem({ id: req.params.id, itemKey: req.body?.itemKey, label: req.body?.label, payload: req.body?.payload }, auth);
140
+ res.status(result.status).json(result.data ?? { error: result.error });
141
+ });
142
+ /**
143
+ * POST /api/escalations/:id/unflag-batch-item
144
+ * Clear ONE key's flag while the batch escalation is pending.
145
+ * Body: { itemKey: string }
146
+ */
147
+ router.post('/:id/unflag-batch-item', async (req, res) => {
148
+ const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
149
+ if (!auth)
150
+ return;
151
+ const result = await api.unflagBatchItem({ id: req.params.id, itemKey: req.body?.itemKey }, auth);
152
+ res.status(result.status).json(result.data ?? { error: result.error });
153
+ });
154
+ /**
155
+ * POST /api/escalations/:id/roster-action
156
+ * Run one action a roster entry offers on this row's form. The server
157
+ * re-reads the action from the row's form schema, checks the entry and any
158
+ * role limit, and runs the act as the person acting: the badged person when
159
+ * X-LT-Acting-Token rides the request (spent only when the act runs).
160
+ * Body: { field: string, action: number, entry: string, code?: string }
161
+ */
162
+ router.post('/:id/roster-action', async (req, res) => {
163
+ const token = req.headers[acting_1.ACTING_TOKEN_HEADER];
164
+ const result = await api.runRosterAction({
165
+ id: req.params.id,
166
+ field: req.body?.field,
167
+ action: req.body?.action,
168
+ entry: req.body?.entry,
169
+ code: req.body?.code,
170
+ actingToken: typeof token === 'string' && token ? token : undefined,
171
+ }, req.auth);
172
+ res.status(result.status).json(result.data ?? { error: result.error });
173
+ });
129
174
  /**
130
175
  * POST /api/escalations/:id/resolve
131
176
  * Resolve a pending escalation with a human-provided payload. Routes by
@@ -247,6 +247,17 @@ export declare function createClient(options?: LTClientOptions): {
247
247
  metadata?: Record<string, any>;
248
248
  restrictRoles?: string[];
249
249
  }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
250
+ flagBatchItem: (input: {
251
+ id: string;
252
+ itemKey: string;
253
+ label: string;
254
+ payload?: Record<string, any>;
255
+ }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
256
+ unflagBatchItem: (input: {
257
+ id: string;
258
+ itemKey: string;
259
+ }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
260
+ runRosterAction: (input: import("../api/escalations/roster-action").RosterActionInput, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
250
261
  accumulate: (input: {
251
262
  id: string;
252
263
  } & import("../api/escalations/accumulate").AccumulateItemInput, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
@@ -146,6 +146,9 @@ function createClient(options = {}) {
146
146
  resolveBatchItem: bindAuth(escalationsApi.resolveBatchItem, auth),
147
147
  resolveBatchItemBySignalKey: bindAuth(escalationsApi.resolveBatchItemBySignalKey, auth),
148
148
  resolveBatchItemByMetadata: bindAuth(escalationsApi.resolveBatchItemByMetadata, auth),
149
+ flagBatchItem: bindAuth(escalationsApi.flagBatchItem, auth),
150
+ unflagBatchItem: bindAuth(escalationsApi.unflagBatchItem, auth),
151
+ runRosterAction: bindAuth(escalationsApi.runRosterAction, auth),
149
152
  // Open accumulation: add and remove held items, read the ordered collection.
150
153
  accumulate: bindAuth(escalationsApi.accumulateItem, auth),
151
154
  accumulateBySignalKey: bindAuth(escalationsApi.accumulateItemBySignalKey, auth),
@@ -0,0 +1,25 @@
1
+ import type { FlagBatchItemOutcome, LTEscalationRecord, UnflagBatchItemOutcome } from '../../types';
2
+ export interface FlagBatchItemInput {
3
+ label: string;
4
+ payload?: Record<string, any>;
5
+ actor?: string;
6
+ metadata?: Record<string, any>;
7
+ resolvedBy?: {
8
+ id: string;
9
+ email?: string;
10
+ };
11
+ }
12
+ export interface BatchFlagOutcome<O extends string> {
13
+ outcome: O;
14
+ /** The post-write row; null on every failure outcome. */
15
+ escalation: LTEscalationRecord | null;
16
+ }
17
+ /**
18
+ * Flag one pending key of a batch escalation in a single SDK statement. The
19
+ * key stays pending. A row whose wait declared `wakeOnFlag` resolves in the
20
+ * same statement and its workflow wakes; that publishes `escalation.resolved`,
21
+ * any other flag `escalation.updated`. Failures publish nothing.
22
+ */
23
+ export declare function flagBatchItem(id: string, itemKey: string, input: FlagBatchItemInput): Promise<BatchFlagOutcome<FlagBatchItemOutcome>>;
24
+ /** Clear one key's flag while the row is pending; publishes `escalation.updated`. */
25
+ export declare function unflagBatchItem(id: string, itemKey: string): Promise<BatchFlagOutcome<UnflagBatchItemOutcome>>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flagBatchItem = flagBatchItem;
4
+ exports.unflagBatchItem = unflagBatchItem;
5
+ const escalation_wire_1 = require("../../lib/events/escalation-wire");
6
+ const uuid_1 = require("../../lib/uuid");
7
+ const client_1 = require("./client");
8
+ const crud_1 = require("./crud");
9
+ const map_1 = require("./map");
10
+ /**
11
+ * Flag one pending key of a batch escalation in a single SDK statement. The
12
+ * key stays pending. A row whose wait declared `wakeOnFlag` resolves in the
13
+ * same statement and its workflow wakes; that publishes `escalation.resolved`,
14
+ * any other flag `escalation.updated`. Failures publish nothing.
15
+ */
16
+ async function flagBatchItem(id, itemKey, input) {
17
+ if (!(0, uuid_1.isUuid)(id))
18
+ return { outcome: 'not-found', escalation: null };
19
+ const client = await (0, client_1.escalations)();
20
+ const result = await client.flagBatchItem({ id, itemKey, ...input });
21
+ if (!result.ok)
22
+ return { outcome: result.outcome, escalation: null };
23
+ const escalation = (0, map_1.toEscalationRecord)(result.entry);
24
+ publishFlagChange(escalation, itemKey, result.outcome === 'completed');
25
+ return { outcome: result.outcome, escalation };
26
+ }
27
+ /** Clear one key's flag while the row is pending; publishes `escalation.updated`. */
28
+ async function unflagBatchItem(id, itemKey) {
29
+ if (!(0, uuid_1.isUuid)(id))
30
+ return { outcome: 'not-found', escalation: null };
31
+ const client = await (0, client_1.escalations)();
32
+ const result = await client.unflagBatchItem({ id, itemKey });
33
+ if (!result.ok)
34
+ return { outcome: result.outcome, escalation: null };
35
+ const escalation = (0, map_1.toEscalationRecord)(result.entry);
36
+ publishFlagChange(escalation, itemKey, false);
37
+ return { outcome: result.outcome, escalation };
38
+ }
39
+ function publishFlagChange(escalation, itemKey, completed) {
40
+ (0, crud_1.publishEscalationChange)({
41
+ type: completed ? 'escalation.resolved' : 'escalation.updated',
42
+ source: 'service',
43
+ workflowId: escalation.workflow_id || '',
44
+ workflowName: escalation.workflow_type || '',
45
+ taskQueue: escalation.task_queue || '',
46
+ escalationId: escalation.id,
47
+ role: escalation.role,
48
+ status: completed ? 'resolved' : 'pending',
49
+ data: (0, escalation_wire_1.escalationEventData)(escalation, { item_key: itemKey }),
50
+ });
51
+ }
@@ -2,6 +2,7 @@ export * from './types';
2
2
  export * from './crud';
3
3
  export { claimAssertedByMetadata } from './claim-asserted';
4
4
  export * from './batch';
5
+ export * from './batch-flag';
5
6
  export * from './accumulate';
6
7
  export * from './bulk';
7
8
  export * from './queries';
@@ -20,6 +20,7 @@ __exportStar(require("./crud"), exports);
20
20
  var claim_asserted_1 = require("./claim-asserted");
21
21
  Object.defineProperty(exports, "claimAssertedByMetadata", { enumerable: true, get: function () { return claim_asserted_1.claimAssertedByMetadata; } });
22
22
  __exportStar(require("./batch"), exports);
23
+ __exportStar(require("./batch-flag"), exports);
23
24
  __exportStar(require("./accumulate"), exports);
24
25
  __exportStar(require("./bulk"), exports);
25
26
  __exportStar(require("./queries"), exports);
@@ -8,6 +8,8 @@
8
8
  * Member rows are read with `global: true`: a resolver who cannot see a
9
9
  * member must never be told the roster is complete.
10
10
  */
11
- import { type RosterCounts, type ShowIfContext } from '../../shared/form-validation';
11
+ import { type RosterCounts, type RosterDef, type RosterResult, type ShowIfContext } from '../../shared/form-validation';
12
12
  /** Each roster field's counts, keyed by field name; empty when the schema declares none. */
13
13
  export declare function loadRosterCounts(schema: Record<string, unknown> | null | undefined, ctx: ShowIfContext): Promise<Record<string, RosterCounts>>;
14
+ /** One roster's entries and counts, read the way the widget reads them. */
15
+ export declare function loadRoster(def: RosterDef, ctx: ShowIfContext): Promise<RosterResult>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadRosterCounts = loadRosterCounts;
4
+ exports.loadRoster = loadRoster;
4
5
  /**
5
6
  * Server-side roster counts: the API-first counterpart of the dashboard's
6
7
  * roster widget. For each `x-lt-roster` field of a form schema, the member
@@ -18,10 +19,14 @@ async function loadRosterCounts(schema, ctx) {
18
19
  const defs = (0, form_validation_1.readRosterDefs)(schema);
19
20
  const counts = {};
20
21
  for (const [field, def] of Object.entries(defs)) {
21
- counts[field] = (0, form_validation_1.computeRoster)(def, ctx, await readMemberRows(def, ctx)).counts;
22
+ counts[field] = (await loadRoster(def, ctx)).counts;
22
23
  }
23
24
  return counts;
24
25
  }
26
+ /** One roster's entries and counts, read the way the widget reads them. */
27
+ async function loadRoster(def, ctx) {
28
+ return (0, form_validation_1.computeRoster)(def, ctx, await readMemberRows(def, ctx));
29
+ }
25
30
  async function readMemberRows(def, ctx) {
26
31
  const query = (0, form_validation_1.rosterQueryOf)(def);
27
32
  const scoped = query ? (0, form_validation_1.resolveRosterQuery)(query, ctx) : null;
@@ -10,6 +10,10 @@ function isSchemeList(value) {
10
10
  function isStringList(value) {
11
11
  return Array.isArray(value) && value.length > 0 && value.every((v) => typeof v === 'string' && v);
12
12
  }
13
+ /** A form field name, as `hold.show` names one. */
14
+ const HOLD_SHOW_FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;
15
+ /** A fill's label map lives on the batch row: `envelope.<path>` or `metadata.<path>`. */
16
+ const FILL_LABELS_PATH = /^(envelope|metadata)\.[A-Za-z0-9_.-]+$/;
13
17
  function isPlainObject(value) {
14
18
  return !!value && typeof value === 'object' && !Array.isArray(value);
15
19
  }
@@ -165,6 +169,9 @@ function assertValidHold(step, at) {
165
169
  throw new Error(`${at}: params.hold.expect.prompt must be markdown`);
166
170
  }
167
171
  }
172
+ if (hold.show !== undefined && (typeof hold.show !== 'string' || !HOLD_SHOW_FIELD.test(hold.show))) {
173
+ throw new Error(`${at}: params.hold.show must name a roster field of the held row's form`);
174
+ }
168
175
  }
169
176
  function assertValidFill(step, at) {
170
177
  const fill = step.params?.fill;
@@ -180,6 +187,15 @@ function assertValidFill(step, at) {
180
187
  if (fill.payload !== undefined && !isPlainObject(fill.payload)) {
181
188
  throw new Error(`${at}: params.fill.payload must be an object`);
182
189
  }
190
+ if (fill.labels !== undefined && (typeof fill.labels !== 'string' || !FILL_LABELS_PATH.test(fill.labels))) {
191
+ throw new Error(`${at}: params.fill.labels must name a map on the row, e.g. "envelope.labels"`);
192
+ }
193
+ if (fill.label !== undefined && (typeof fill.label !== 'string' || !fill.label.trim())) {
194
+ throw new Error(`${at}: params.fill.label must be a non-empty template`);
195
+ }
196
+ if (fill.label !== undefined && fill.labels === undefined) {
197
+ throw new Error(`${at}: params.fill.label requires params.fill.labels`);
198
+ }
183
199
  if (step.confirm)
184
200
  throw new Error(`${at}: fill cannot carry confirm`);
185
201
  }
@@ -127,6 +127,13 @@ function assertValidChoices(choices, at) {
127
127
  || choice.verb === types_1.SCAN_VERBS.FILL) {
128
128
  throw new Error(`${cat}: ${choice.verb} cannot be a choice verb`);
129
129
  }
130
+ if (choice.roles !== undefined && (!Array.isArray(choice.roles) || choice.roles.length === 0
131
+ || choice.roles.some((r) => typeof r !== 'string' || !r))) {
132
+ throw new Error(`${cat}: roles must be a non-empty array of role names`);
133
+ }
134
+ if (choice.refuse !== undefined && (typeof choice.refuse !== 'string' || !choice.refuse.trim())) {
135
+ throw new Error(`${cat}: refuse must be non-empty text`);
136
+ }
130
137
  if (choice.confirm && !choice.confirm.prompt) {
131
138
  throw new Error(`${cat}: confirm requires a prompt`);
132
139
  }
@@ -24,3 +24,4 @@ export * from './display-only-widgets';
24
24
  export * from './x-lt-invoke';
25
25
  export * from './x-lt-scan';
26
26
  export * from './x-lt-roster';
27
+ export * from './x-lt-actions';
@@ -40,3 +40,4 @@ __exportStar(require("./display-only-widgets"), exports);
40
40
  __exportStar(require("./x-lt-invoke"), exports);
41
41
  __exportStar(require("./x-lt-scan"), exports);
42
42
  __exportStar(require("./x-lt-roster"), exports);
43
+ __exportStar(require("./x-lt-actions"), exports);
@@ -0,0 +1,80 @@
1
+ /**
2
+ * x-lt-actions on a roster field: the acts an entry offers, read the same way
3
+ * by the dashboard (which shows them) and the API (which runs them). Each
4
+ * action is exactly one act:
5
+ *
6
+ * { "label": "Missing", "resolverPayload": { "outcome": "missing" } } resolve the member row
7
+ * { "label": "Key in", "fill": { "payload": { "source": "key-in" }, "enterCode": true } }
8
+ * { "label": "Missing", "flag": { "label": "Missing" } } flag the batch key
9
+ * { "label": "Found it", "unflag": true } clear the flag
10
+ *
11
+ * `when` names the entry states that offer it. `roles` limits who may run it:
12
+ * the action shows to everyone and runs only for a person holding one of the
13
+ * roles; `refuse` is what anyone else is told. The server re-reads the action
14
+ * from the row's form schema and decides; the dashboard only displays.
15
+ */
16
+ import { type HelpTokenContext } from './x-lt-help';
17
+ import { type RosterEntry, type RosterState } from './x-lt-roster';
18
+ export declare const X_LT_ACTIONS = "x-lt-actions";
19
+ export declare const ROSTER_ACTION_KINDS: {
20
+ readonly RESOLVE: "resolve";
21
+ readonly FILL: "fill";
22
+ readonly FLAG: "flag";
23
+ readonly UNFLAG: "unflag";
24
+ };
25
+ export type RosterActionKind = (typeof ROSTER_ACTION_KINDS)[keyof typeof ROSTER_ACTION_KINDS];
26
+ /** The separator of counted batch keys when the roster names none. */
27
+ export declare const ROSTER_KEY_SEPARATOR_DEFAULT = "#";
28
+ /** The payload key a key-in records the entered code under. */
29
+ export declare const ENTERED_CODE_KEY = "enteredCode";
30
+ export interface RosterActionDef {
31
+ label: string;
32
+ /** The entry states that offer it; the default follows the act. */
33
+ when?: RosterState | RosterState[];
34
+ /** A confirmation asked in place before firing; tokens interpolate per entry. */
35
+ confirm?: string;
36
+ /** Resolve the entry's member row with this canned payload (a query set). */
37
+ resolverPayload?: Record<string, unknown>;
38
+ /** Fill the entry's batch key; `enterCode` asks for the code and checks it against the key. */
39
+ fill?: {
40
+ payload?: Record<string, unknown>;
41
+ enterCode?: boolean;
42
+ };
43
+ /** Flag the entry's batch key. */
44
+ flag?: {
45
+ label: string;
46
+ payload?: Record<string, unknown>;
47
+ };
48
+ /** Clear the entry's flag. */
49
+ unflag?: true;
50
+ /** Runs only for a person holding one of these roles. */
51
+ roles?: string[];
52
+ /** What a person without the roles is told. */
53
+ refuse?: string;
54
+ }
55
+ /** The one act an action declares, or null when it declares none or several. */
56
+ export declare function rosterActionKind(action: RosterActionDef): RosterActionKind | null;
57
+ /** The field's actions with a label and exactly one act, in declared order. */
58
+ export declare function readRosterActions(fieldSchema: Record<string, unknown> | null | undefined): RosterActionDef[];
59
+ /**
60
+ * True when the entry offers the action: the entry is in one of its states,
61
+ * and the act fits the entry (a resolve needs a member row; batch acts need
62
+ * a batch set).
63
+ */
64
+ export declare function offersAction(action: RosterActionDef, entry: RosterEntry, batch: boolean): boolean;
65
+ /** True when a person holding `roles` may run the action. */
66
+ export declare function holdsActionRole(action: Pick<RosterActionDef, 'roles'>, roles: string[], superadmin?: boolean): boolean;
67
+ /** What a person without the action's roles is told. */
68
+ export declare function actionRefusal(action: Pick<RosterActionDef, 'label' | 'roles' | 'refuse'>): string;
69
+ /** Deep-walk a payload template: string leaves interpolate against the context; other types pass through typed. */
70
+ export declare function interpolatePayload(value: unknown, ctx: HelpTokenContext): unknown;
71
+ /** The code a batch key names, without its ordinal suffix. */
72
+ export declare function batchKeyCode(key: string, separator?: string): string;
73
+ /** The batch key's code as its label prints it: a GTIN in its EAN-13 or EAN-8 form. */
74
+ export declare function printedKeyCode(key: string, separator?: string): string;
75
+ /**
76
+ * True when an entered code names the batch key's code. GTINs compare in
77
+ * their 14-digit form, so a UPC-A typed from the label matches its GTIN-14
78
+ * key; anything else compares as trimmed text.
79
+ */
80
+ export declare function enteredCodeMatches(entered: string, key: string, separator?: string): boolean;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ENTERED_CODE_KEY = exports.ROSTER_KEY_SEPARATOR_DEFAULT = exports.ROSTER_ACTION_KINDS = exports.X_LT_ACTIONS = void 0;
4
+ exports.rosterActionKind = rosterActionKind;
5
+ exports.readRosterActions = readRosterActions;
6
+ exports.offersAction = offersAction;
7
+ exports.holdsActionRole = holdsActionRole;
8
+ exports.actionRefusal = actionRefusal;
9
+ exports.interpolatePayload = interpolatePayload;
10
+ exports.batchKeyCode = batchKeyCode;
11
+ exports.printedKeyCode = printedKeyCode;
12
+ exports.enteredCodeMatches = enteredCodeMatches;
13
+ /**
14
+ * x-lt-actions on a roster field: the acts an entry offers, read the same way
15
+ * by the dashboard (which shows them) and the API (which runs them). Each
16
+ * action is exactly one act:
17
+ *
18
+ * { "label": "Missing", "resolverPayload": { "outcome": "missing" } } resolve the member row
19
+ * { "label": "Key in", "fill": { "payload": { "source": "key-in" }, "enterCode": true } }
20
+ * { "label": "Missing", "flag": { "label": "Missing" } } flag the batch key
21
+ * { "label": "Found it", "unflag": true } clear the flag
22
+ *
23
+ * `when` names the entry states that offer it. `roles` limits who may run it:
24
+ * the action shows to everyone and runs only for a person holding one of the
25
+ * roles; `refuse` is what anyone else is told. The server re-reads the action
26
+ * from the row's form schema and decides; the dashboard only displays.
27
+ */
28
+ const x_lt_help_1 = require("./x-lt-help");
29
+ const x_lt_roster_1 = require("./x-lt-roster");
30
+ const gtin_1 = require("../scan-code/gtin");
31
+ exports.X_LT_ACTIONS = 'x-lt-actions';
32
+ exports.ROSTER_ACTION_KINDS = {
33
+ RESOLVE: 'resolve',
34
+ FILL: 'fill',
35
+ FLAG: 'flag',
36
+ UNFLAG: 'unflag',
37
+ };
38
+ /** The separator of counted batch keys when the roster names none. */
39
+ exports.ROSTER_KEY_SEPARATOR_DEFAULT = '#';
40
+ /** The payload key a key-in records the entered code under. */
41
+ exports.ENTERED_CODE_KEY = 'enteredCode';
42
+ const DEFAULT_WHEN = {
43
+ resolve: [x_lt_roster_1.ROSTER_STATES.WAITING],
44
+ fill: [x_lt_roster_1.ROSTER_STATES.WAITING, x_lt_roster_1.ROSTER_STATES.FLAGGED],
45
+ flag: [x_lt_roster_1.ROSTER_STATES.WAITING],
46
+ unflag: [x_lt_roster_1.ROSTER_STATES.FLAGGED],
47
+ };
48
+ function isRecord(v) {
49
+ return !!v && typeof v === 'object' && !Array.isArray(v);
50
+ }
51
+ /** The one act an action declares, or null when it declares none or several. */
52
+ function rosterActionKind(action) {
53
+ const kinds = [];
54
+ if (isRecord(action.resolverPayload))
55
+ kinds.push(exports.ROSTER_ACTION_KINDS.RESOLVE);
56
+ if (isRecord(action.fill))
57
+ kinds.push(exports.ROSTER_ACTION_KINDS.FILL);
58
+ if (isRecord(action.flag) && typeof action.flag.label === 'string' && action.flag.label) {
59
+ kinds.push(exports.ROSTER_ACTION_KINDS.FLAG);
60
+ }
61
+ if (action.unflag === true)
62
+ kinds.push(exports.ROSTER_ACTION_KINDS.UNFLAG);
63
+ return kinds.length === 1 ? kinds[0] : null;
64
+ }
65
+ /** The field's actions with a label and exactly one act, in declared order. */
66
+ function readRosterActions(fieldSchema) {
67
+ const raw = fieldSchema?.[exports.X_LT_ACTIONS];
68
+ if (!Array.isArray(raw))
69
+ return [];
70
+ return raw.filter((a) => isRecord(a) && typeof a.label === 'string' && !!a.label && rosterActionKind(a) !== null);
71
+ }
72
+ /**
73
+ * True when the entry offers the action: the entry is in one of its states,
74
+ * and the act fits the entry (a resolve needs a member row; batch acts need
75
+ * a batch set).
76
+ */
77
+ function offersAction(action, entry, batch) {
78
+ const kind = rosterActionKind(action);
79
+ if (!kind)
80
+ return false;
81
+ if (kind === exports.ROSTER_ACTION_KINDS.RESOLVE ? !entry.row : !batch)
82
+ return false;
83
+ const when = action.when === undefined ? DEFAULT_WHEN[kind]
84
+ : Array.isArray(action.when) ? action.when : [action.when];
85
+ return when.includes(entry.state);
86
+ }
87
+ /** True when a person holding `roles` may run the action. */
88
+ function holdsActionRole(action, roles, superadmin = false) {
89
+ const required = Array.isArray(action.roles) ? action.roles.filter((r) => typeof r === 'string' && r) : [];
90
+ return required.length === 0 || superadmin || required.some((r) => roles.includes(r));
91
+ }
92
+ /** What a person without the action's roles is told. */
93
+ function actionRefusal(action) {
94
+ if (typeof action.refuse === 'string' && action.refuse.trim())
95
+ return action.refuse;
96
+ const roles = (action.roles ?? []).filter(Boolean);
97
+ return `${action.label} needs ${roles.length > 1 ? 'one of these roles' : 'the role'}: ${roles.join(', ')}.`;
98
+ }
99
+ /** Deep-walk a payload template: string leaves interpolate against the context; other types pass through typed. */
100
+ function interpolatePayload(value, ctx) {
101
+ if (typeof value === 'string')
102
+ return (0, x_lt_help_1.interpolateHelp)(value, ctx);
103
+ if (Array.isArray(value))
104
+ return value.map((v) => interpolatePayload(v, ctx));
105
+ if (isRecord(value)) {
106
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, interpolatePayload(v, ctx)]));
107
+ }
108
+ return value;
109
+ }
110
+ /** The code a batch key names, without its ordinal suffix. */
111
+ function batchKeyCode(key, separator = exports.ROSTER_KEY_SEPARATOR_DEFAULT) {
112
+ const at = key.lastIndexOf(separator);
113
+ return at > 0 && /^[0-9]+$/.test(key.slice(at + 1)) ? key.slice(0, at) : key;
114
+ }
115
+ /** The batch key's code as its label prints it: a GTIN in its EAN-13 or EAN-8 form. */
116
+ function printedKeyCode(key, separator) {
117
+ const code = batchKeyCode(key, separator);
118
+ return (0, gtin_1.isValidGtin)(code) ? (0, gtin_1.displayGtin)((0, gtin_1.normalizeGtin)(code)) : code;
119
+ }
120
+ /**
121
+ * True when an entered code names the batch key's code. GTINs compare in
122
+ * their 14-digit form, so a UPC-A typed from the label matches its GTIN-14
123
+ * key; anything else compares as trimmed text.
124
+ */
125
+ function enteredCodeMatches(entered, key, separator) {
126
+ const typed = entered.trim();
127
+ const code = batchKeyCode(key, separator);
128
+ if (!typed)
129
+ return false;
130
+ if ((0, gtin_1.isValidGtin)(typed) && (0, gtin_1.isValidGtin)(code))
131
+ return (0, gtin_1.normalizeGtin)(typed) === (0, gtin_1.normalizeGtin)(code);
132
+ return typed === code;
133
+ }
@@ -40,6 +40,8 @@ export interface RosterDef {
40
40
  key?: string;
41
41
  in?: string[];
42
42
  flagged?: RosterFlagRule[];
43
+ /** The separator of counted keys: the nth occurrence of a code ticks `<code><sep>n`. */
44
+ countedBy?: string;
43
45
  }
44
46
  /** One member row's token context (the row's own domains). */
45
47
  export type RosterRow = HelpTokenContext & {
@@ -28,9 +28,14 @@ exports.rosterHeadline = rosterHeadline;
28
28
  * An entry is `in` when its key is held by the host row (`items`: the
29
29
  * accumulated keys, or a batch's filled keys) or appears in a named context
30
30
  * value (`resolver.<field>`, a string or an array). It is `flagged` when its
31
- * member row matches a `flagged` rule, and `waiting` otherwise. In wins over
31
+ * member row matches a `flagged` rule (or, on a batch set, when its key
32
+ * carries a flag in `envelope.batch_flags`), and `waiting` otherwise. In wins over
32
33
  * flagged, so a member flagged on its own row and then added reads in.
33
34
  *
35
+ * `countedBy` names the separator of counted keys (`<code>#1`, `<code>#2`):
36
+ * the nth occurrence of a code in a named context value ticks `<code>#n`,
37
+ * so two scans of one code tick both of its keys.
38
+ *
34
39
  * Isomorphic: the dashboard renders the widget and the form's `roster.*`
35
40
  * context from it, and the API layer computes the same counts to evaluate
36
41
  * showIf and the roster submit guard at resolve.
@@ -54,6 +59,7 @@ const DEFAULT_KEY = '{{escalation.id}}';
54
59
  const MISSING = '—';
55
60
  const BATCH_KEYS = 'batch_keys';
56
61
  const BATCH_PENDING = 'batch_pending';
62
+ const BATCH_FLAGS = 'batch_flags';
57
63
  const ACCUMULATE_KEYS = 'accumulate_keys';
58
64
  function isRecord(v) {
59
65
  return !!v && typeof v === 'object' && !Array.isArray(v);
@@ -144,16 +150,34 @@ function heldKeys(ctx) {
144
150
  }
145
151
  return new Set();
146
152
  }
153
+ /** Each value as given, and with `countedBy` its nth occurrence also as `<value><sep>n`. */
154
+ function countedKeys(values, separator) {
155
+ if (!separator)
156
+ return values;
157
+ const seen = new Map();
158
+ return values.flatMap((v) => {
159
+ const n = (seen.get(v) ?? 0) + 1;
160
+ seen.set(v, n);
161
+ return [v, `${v}${separator}${n}`];
162
+ });
163
+ }
147
164
  function arrivedKeys(def, ctx) {
148
165
  const arrived = new Set();
166
+ const separator = typeof def.countedBy === 'string' && def.countedBy ? def.countedBy : undefined;
149
167
  for (const source of def.in ?? [exports.ROSTER_ITEMS_SOURCE]) {
150
168
  const keys = source === exports.ROSTER_ITEMS_SOURCE
151
169
  ? [...heldKeys(ctx)]
152
- : strings((0, ctx_path_1.resolveCtxPath)(source, ctx));
170
+ : countedKeys(strings((0, ctx_path_1.resolveCtxPath)(source, ctx)), separator);
153
171
  keys.forEach((k) => arrived.add(k));
154
172
  }
155
173
  return arrived;
156
174
  }
175
+ /** A batch key's flag label, from `envelope.batch_flags[key].label`. */
176
+ function batchFlagLabel(ctx, key) {
177
+ const flags = (0, x_lt_bind_1.getDeep)(ctx.envelope, BATCH_FLAGS);
178
+ const flag = isRecord(flags) ? flags[key] : undefined;
179
+ return isRecord(flag) && typeof flag.label === 'string' && flag.label ? flag.label : undefined;
180
+ }
157
181
  function flagFor(def, row) {
158
182
  if (!row)
159
183
  return undefined;
@@ -219,10 +243,11 @@ function expectedEntries(def, ctx, rows) {
219
243
  */
220
244
  function computeRoster(def, ctx, rows = []) {
221
245
  const arrived = arrivedKeys(def, ctx);
246
+ const batch = 'batch' in def.expected;
222
247
  const entries = expectedEntries(def, ctx, rows).map((e) => {
223
248
  if (arrived.has(e.key))
224
249
  return { ...e, state: exports.ROSTER_STATES.IN };
225
- const flag = flagFor(def, e.row);
250
+ const flag = batch ? batchFlagLabel(ctx, e.key) : flagFor(def, e.row);
226
251
  return flag ? { ...e, state: exports.ROSTER_STATES.FLAGGED, flag } : { ...e, state: exports.ROSTER_STATES.WAITING };
227
252
  });
228
253
  const count = (s) => entries.filter((e) => e.state === s).length;