@hotmeshio/long-tail 0.16.2 → 0.17.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 (222) hide show
  1. package/build/api/exports.d.ts +15 -0
  2. package/build/api/exports.js +35 -0
  3. package/build/api/users.d.ts +31 -1
  4. package/build/api/users.js +54 -1
  5. package/build/bin/ltc.js +11 -0
  6. package/build/lib/cli/commands/users.d.ts +11 -0
  7. package/build/lib/cli/commands/users.js +59 -0
  8. package/build/lib/cli/commands/workflows.d.ts +3 -0
  9. package/build/lib/cli/commands/workflows.js +22 -0
  10. package/build/routes/exports.js +11 -0
  11. package/build/routes/users.js +26 -0
  12. package/build/sdk/index.d.ts +3 -0
  13. package/build/sdk/index.js +3 -0
  14. package/build/services/export/index.d.ts +19 -0
  15. package/build/services/export/index.js +53 -33
  16. package/build/services/user/crud.d.ts +32 -1
  17. package/build/services/user/crud.js +108 -0
  18. package/build/services/user/index.d.ts +2 -2
  19. package/build/services/user/index.js +5 -1
  20. package/build/services/user/sql.d.ts +16 -0
  21. package/build/services/user/sql.js +33 -1
  22. package/build/services/user/types.d.ts +11 -0
  23. package/build/shared/form-validation/field-validator.d.ts +8 -6
  24. package/build/shared/form-validation/field-validator.js +23 -15
  25. package/build/shared/form-validation/x-lt-options.js +35 -21
  26. package/build/system/mcp-servers/admin/exports.js +15 -0
  27. package/build/system/mcp-servers/admin/schemas.d.ts +37 -14
  28. package/build/system/mcp-servers/admin/schemas.js +12 -3
  29. package/build/system/mcp-servers/admin/users.js +26 -0
  30. package/build/system/seed/tool-manifests-admin.d.ts +445 -0
  31. package/build/system/seed/tool-manifests-admin.js +2 -0
  32. package/dashboard/dist/assets/{AdminDashboard-BrOvvDHF.js → AdminDashboard-Bx5G6Qb_.js} +2 -2
  33. package/dashboard/dist/assets/{AdminDashboard-BrOvvDHF.js.map → AdminDashboard-Bx5G6Qb_.js.map} +1 -1
  34. package/dashboard/dist/assets/{AgentConfigPage-CtVq8J0L.js → AgentConfigPage-S-YfPwCG.js} +2 -2
  35. package/dashboard/dist/assets/{AgentConfigPage-CtVq8J0L.js.map → AgentConfigPage-S-YfPwCG.js.map} +1 -1
  36. package/dashboard/dist/assets/{AgentDetailPage-DTfTQDug.js → AgentDetailPage-pFVqLY4c.js} +2 -2
  37. package/dashboard/dist/assets/{AgentDetailPage-DTfTQDug.js.map → AgentDetailPage-pFVqLY4c.js.map} +1 -1
  38. package/dashboard/dist/assets/{AgentsPage-vCTc3Qvj.js → AgentsPage-DjAluFkM.js} +2 -2
  39. package/dashboard/dist/assets/{AgentsPage-vCTc3Qvj.js.map → AgentsPage-DjAluFkM.js.map} +1 -1
  40. package/dashboard/dist/assets/{AvailableEscalationsPage-DJODShd7.js → AvailableEscalationsPage-BHsRZk4v.js} +2 -2
  41. package/dashboard/dist/assets/{AvailableEscalationsPage-DJODShd7.js.map → AvailableEscalationsPage-BHsRZk4v.js.map} +1 -1
  42. package/dashboard/dist/assets/{BotPicker-GU44inXA.js → BotPicker-h2YrxQS2.js} +2 -2
  43. package/dashboard/dist/assets/{BotPicker-GU44inXA.js.map → BotPicker-h2YrxQS2.js.map} +1 -1
  44. package/dashboard/dist/assets/{BulkAssignModal-ChqzG6FY.js → BulkAssignModal-CNKZBgK5.js} +2 -2
  45. package/dashboard/dist/assets/{BulkAssignModal-ChqzG6FY.js.map → BulkAssignModal-CNKZBgK5.js.map} +1 -1
  46. package/dashboard/dist/assets/{CapabilitiesPage-Y2hycdPY.js → CapabilitiesPage-DGsnIiJi.js} +2 -2
  47. package/dashboard/dist/assets/{CapabilitiesPage-Y2hycdPY.js.map → CapabilitiesPage-DGsnIiJi.js.map} +1 -1
  48. package/dashboard/dist/assets/{CollapsibleSection-CmCwt_Rs.js → CollapsibleSection-ptEsXSl6.js} +2 -2
  49. package/dashboard/dist/assets/{CollapsibleSection-CmCwt_Rs.js.map → CollapsibleSection-ptEsXSl6.js.map} +1 -1
  50. package/dashboard/dist/assets/{CountdownTimer-Bx2XXJOd.js → CountdownTimer-Cvif0QtN.js} +2 -2
  51. package/dashboard/dist/assets/{CountdownTimer-Bx2XXJOd.js.map → CountdownTimer-Cvif0QtN.js.map} +1 -1
  52. package/dashboard/dist/assets/{CredentialsPage-CoX_PNBe.js → CredentialsPage-CwKUAtAR.js} +2 -2
  53. package/dashboard/dist/assets/{CredentialsPage-CoX_PNBe.js.map → CredentialsPage-CwKUAtAR.js.map} +1 -1
  54. package/dashboard/dist/assets/{CronLabel-CVYKRipP.js → CronLabel-B9RbqMR-.js} +2 -2
  55. package/dashboard/dist/assets/{CronLabel-CVYKRipP.js.map → CronLabel-B9RbqMR-.js.map} +1 -1
  56. package/dashboard/dist/assets/{ElapsedCell-jRURiCRW.js → ElapsedCell-BirS3yZq.js} +2 -2
  57. package/dashboard/dist/assets/{ElapsedCell-jRURiCRW.js.map → ElapsedCell-BirS3yZq.js.map} +1 -1
  58. package/dashboard/dist/assets/{EntityTimelinePanel-G6nzvgpl.js → EntityTimelinePanel-D3QNqDiL.js} +2 -2
  59. package/dashboard/dist/assets/{EntityTimelinePanel-G6nzvgpl.js.map → EntityTimelinePanel-D3QNqDiL.js.map} +1 -1
  60. package/dashboard/dist/assets/{EscalationListSchemaPage-D-rVTQ1m.js → EscalationListSchemaPage-Bke-30FY.js} +2 -2
  61. package/dashboard/dist/assets/{EscalationListSchemaPage-D-rVTQ1m.js.map → EscalationListSchemaPage-Bke-30FY.js.map} +1 -1
  62. package/dashboard/dist/assets/{EscalationSchemaPage-CV0R_xY9.js → EscalationSchemaPage-CTFE9vko.js} +2 -2
  63. package/dashboard/dist/assets/{EscalationSchemaPage-CV0R_xY9.js.map → EscalationSchemaPage-CTFE9vko.js.map} +1 -1
  64. package/dashboard/dist/assets/{EscalationsOverview-DMdx15CQ.js → EscalationsOverview-C2FaSmXk.js} +2 -2
  65. package/dashboard/dist/assets/{EscalationsOverview-DMdx15CQ.js.map → EscalationsOverview-C2FaSmXk.js.map} +1 -1
  66. package/dashboard/dist/assets/{EventTable-CIvsdt-q.js → EventTable-zFqzbEdC.js} +2 -2
  67. package/dashboard/dist/assets/{EventTable-CIvsdt-q.js.map → EventTable-zFqzbEdC.js.map} +1 -1
  68. package/dashboard/dist/assets/{FilterBar-DWYGkVRH.js → FilterBar-fwUqeM-5.js} +2 -2
  69. package/dashboard/dist/assets/{FilterBar-DWYGkVRH.js.map → FilterBar-fwUqeM-5.js.map} +1 -1
  70. package/dashboard/dist/assets/{GraphInvokePage-BGHlXh4r.js → GraphInvokePage-CA_XYI2W.js} +2 -2
  71. package/dashboard/dist/assets/{GraphInvokePage-BGHlXh4r.js.map → GraphInvokePage-CA_XYI2W.js.map} +1 -1
  72. package/dashboard/dist/assets/{HomePage-BHOnp8SK.js → HomePage-C2HnqdFX.js} +2 -2
  73. package/dashboard/dist/assets/{HomePage-BHOnp8SK.js.map → HomePage-C2HnqdFX.js.map} +1 -1
  74. package/dashboard/dist/assets/{ListToolbar-iOgn_db5.js → ListToolbar-BEogxu1f.js} +2 -2
  75. package/dashboard/dist/assets/{ListToolbar-iOgn_db5.js.map → ListToolbar-BEogxu1f.js.map} +1 -1
  76. package/dashboard/dist/assets/{McpOverview-Be9sMKCA.js → McpOverview-CdMR-5qh.js} +2 -2
  77. package/dashboard/dist/assets/{McpOverview-Be9sMKCA.js.map → McpOverview-CdMR-5qh.js.map} +1 -1
  78. package/dashboard/dist/assets/{McpQueryDetailPage-BIgpmGJN.js → McpQueryDetailPage-BXo4UjJF.js} +2 -2
  79. package/dashboard/dist/assets/{McpQueryDetailPage-BIgpmGJN.js.map → McpQueryDetailPage-BXo4UjJF.js.map} +1 -1
  80. package/dashboard/dist/assets/{McpQueryPage-Okcxw_Um.js → McpQueryPage-BvvM0Ya1.js} +2 -2
  81. package/dashboard/dist/assets/{McpQueryPage-Okcxw_Um.js.map → McpQueryPage-BvvM0Ya1.js.map} +1 -1
  82. package/dashboard/dist/assets/{McpRunDetailPage-DT8kOfih.js → McpRunDetailPage-5eaJeupC.js} +2 -2
  83. package/dashboard/dist/assets/{McpRunDetailPage-DT8kOfih.js.map → McpRunDetailPage-5eaJeupC.js.map} +1 -1
  84. package/dashboard/dist/assets/{McpRunsPage-BXhoP77D.js → McpRunsPage-B5_-3NUF.js} +2 -2
  85. package/dashboard/dist/assets/{McpRunsPage-BXhoP77D.js.map → McpRunsPage-B5_-3NUF.js.map} +1 -1
  86. package/dashboard/dist/assets/{OperationsPage-rVhC8JPv.js → OperationsPage-CJXTw02Z.js} +2 -2
  87. package/dashboard/dist/assets/{OperationsPage-rVhC8JPv.js.map → OperationsPage-CJXTw02Z.js.map} +1 -1
  88. package/dashboard/dist/assets/{OperatorDashboard-CIt061hu.js → OperatorDashboard-Dx7639os.js} +2 -2
  89. package/dashboard/dist/assets/{OperatorDashboard-CIt061hu.js.map → OperatorDashboard-Dx7639os.js.map} +1 -1
  90. package/dashboard/dist/assets/{PersonaDetailPage-r46uNF4E.js → PersonaDetailPage-BHQ44UIu.js} +2 -2
  91. package/dashboard/dist/assets/{PersonaDetailPage-r46uNF4E.js.map → PersonaDetailPage-BHQ44UIu.js.map} +1 -1
  92. package/dashboard/dist/assets/{PersonasPage-CayYv9-j.js → PersonasPage-Cnmb4uox.js} +2 -2
  93. package/dashboard/dist/assets/{PersonasPage-CayYv9-j.js.map → PersonasPage-Cnmb4uox.js.map} +1 -1
  94. package/dashboard/dist/assets/{ProcessDetailPage-dn7lkM4c.js → ProcessDetailPage-CZ09xiWf.js} +2 -2
  95. package/dashboard/dist/assets/{ProcessDetailPage-dn7lkM4c.js.map → ProcessDetailPage-CZ09xiWf.js.map} +1 -1
  96. package/dashboard/dist/assets/{ProcessesListPage-DOp5J6Be.js → ProcessesListPage-BT76_7bW.js} +2 -2
  97. package/dashboard/dist/assets/{ProcessesListPage-DOp5J6Be.js.map → ProcessesListPage-BT76_7bW.js.map} +1 -1
  98. package/dashboard/dist/assets/{RoleDetailPage-DOlNoiAK.js → RoleDetailPage-CDsJKPvV.js} +2 -2
  99. package/dashboard/dist/assets/{RoleDetailPage-DOlNoiAK.js.map → RoleDetailPage-CDsJKPvV.js.map} +1 -1
  100. package/dashboard/dist/assets/{RolesPage-DPppT6Zl.js → RolesPage-D2cV92bL.js} +2 -2
  101. package/dashboard/dist/assets/{RolesPage-DPppT6Zl.js.map → RolesPage-D2cV92bL.js.map} +1 -1
  102. package/dashboard/dist/assets/{RunAsSelector-BgntKfSA.js → RunAsSelector-Cvi8x8xx.js} +2 -2
  103. package/dashboard/dist/assets/{RunAsSelector-BgntKfSA.js.map → RunAsSelector-Cvi8x8xx.js.map} +1 -1
  104. package/dashboard/dist/assets/{ScanCodesPage-DPm1lG79.js → ScanCodesPage-BWt_iRCu.js} +2 -2
  105. package/dashboard/dist/assets/{ScanCodesPage-DPm1lG79.js.map → ScanCodesPage-BWt_iRCu.js.map} +1 -1
  106. package/dashboard/dist/assets/{ScanSchemeDetailPage-CuoG89q1.js → ScanSchemeDetailPage-C6mRYkxL.js} +2 -2
  107. package/dashboard/dist/assets/{ScanSchemeDetailPage-CuoG89q1.js.map → ScanSchemeDetailPage-C6mRYkxL.js.map} +1 -1
  108. package/dashboard/dist/assets/{ScanStationPage-2SLXqqs0.js → ScanStationPage-YQiijAKy.js} +2 -2
  109. package/dashboard/dist/assets/{ScanStationPage-2SLXqqs0.js.map → ScanStationPage-YQiijAKy.js.map} +1 -1
  110. package/dashboard/dist/assets/{StickyPagination-Bc_Mzu_R.js → StickyPagination-BsbSade1.js} +2 -2
  111. package/dashboard/dist/assets/{StickyPagination-Bc_Mzu_R.js.map → StickyPagination-BsbSade1.js.map} +1 -1
  112. package/dashboard/dist/assets/{StreamMessageDetail-S1cnLGkf.js → StreamMessageDetail-jczXwuBw.js} +2 -2
  113. package/dashboard/dist/assets/{StreamMessageDetail-S1cnLGkf.js.map → StreamMessageDetail-jczXwuBw.js.map} +1 -1
  114. package/dashboard/dist/assets/{SwimlaneTimeline-BUu2sPmY.js → SwimlaneTimeline-DSO6QXmX.js} +2 -2
  115. package/dashboard/dist/assets/{SwimlaneTimeline-BUu2sPmY.js.map → SwimlaneTimeline-DSO6QXmX.js.map} +1 -1
  116. package/dashboard/dist/assets/{TaskDetailPage-BMfNNtbN.js → TaskDetailPage-DWLfcAF4.js} +2 -2
  117. package/dashboard/dist/assets/{TaskDetailPage-BMfNNtbN.js.map → TaskDetailPage-DWLfcAF4.js.map} +1 -1
  118. package/dashboard/dist/assets/{TasksListPage-BmNnopOU.js → TasksListPage-B0at3vJ3.js} +2 -2
  119. package/dashboard/dist/assets/{TasksListPage-BmNnopOU.js.map → TasksListPage-B0at3vJ3.js.map} +1 -1
  120. package/dashboard/dist/assets/{TimeAgo-Dip7gQQx.js → TimeAgo-poxwErGl.js} +2 -2
  121. package/dashboard/dist/assets/{TimeAgo-Dip7gQQx.js.map → TimeAgo-poxwErGl.js.map} +1 -1
  122. package/dashboard/dist/assets/{TimestampCell-DRAYnIrx.js → TimestampCell-Be6tvFQd.js} +2 -2
  123. package/dashboard/dist/assets/{TimestampCell-DRAYnIrx.js.map → TimestampCell-Be6tvFQd.js.map} +1 -1
  124. package/dashboard/dist/assets/{ToolTestPanel-CQVYC3Ba.js → ToolTestPanel-CYOqnqMz.js} +2 -2
  125. package/dashboard/dist/assets/{ToolTestPanel-CQVYC3Ba.js.map → ToolTestPanel-CYOqnqMz.js.map} +1 -1
  126. package/dashboard/dist/assets/{TopicDetailPage-Bmtwuksg.js → TopicDetailPage-C82WIKaU.js} +2 -2
  127. package/dashboard/dist/assets/{TopicDetailPage-Bmtwuksg.js.map → TopicDetailPage-C82WIKaU.js.map} +1 -1
  128. package/dashboard/dist/assets/{TopicsPage-DIgF7-mJ.js → TopicsPage-COH547ZD.js} +2 -2
  129. package/dashboard/dist/assets/{TopicsPage-DIgF7-mJ.js.map → TopicsPage-COH547ZD.js.map} +1 -1
  130. package/dashboard/dist/assets/{UserName-DNKFz7X9.js → UserName-D2SoVbe9.js} +2 -2
  131. package/dashboard/dist/assets/{UserName-DNKFz7X9.js.map → UserName-D2SoVbe9.js.map} +1 -1
  132. package/dashboard/dist/assets/{WorkflowExecutionPage-DraIBNpl.js → WorkflowExecutionPage-C82Q-TYC.js} +2 -2
  133. package/dashboard/dist/assets/{WorkflowExecutionPage-DraIBNpl.js.map → WorkflowExecutionPage-C82Q-TYC.js.map} +1 -1
  134. package/dashboard/dist/assets/{WorkflowsDashboard-BH7kmFjM.js → WorkflowsDashboard-DDWwCT-v.js} +2 -2
  135. package/dashboard/dist/assets/{WorkflowsDashboard-BH7kmFjM.js.map → WorkflowsDashboard-DDWwCT-v.js.map} +1 -1
  136. package/dashboard/dist/assets/{WorkflowsOverview-C98pCjQX.js → WorkflowsOverview-DdKRtWdK.js} +2 -2
  137. package/dashboard/dist/assets/{WorkflowsOverview-C98pCjQX.js.map → WorkflowsOverview-DdKRtWdK.js.map} +1 -1
  138. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BWQjXenZ.js → YamlWorkflowDetailPage-D3qvyy_4.js} +2 -2
  139. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BWQjXenZ.js.map → YamlWorkflowDetailPage-D3qvyy_4.js.map} +1 -1
  140. package/dashboard/dist/assets/{YamlWorkflowsPage-BGTI_sdP.js → YamlWorkflowsPage-BJsxZOBC.js} +2 -2
  141. package/dashboard/dist/assets/{YamlWorkflowsPage-BGTI_sdP.js.map → YamlWorkflowsPage-BJsxZOBC.js.map} +1 -1
  142. package/dashboard/dist/assets/{agents-DfMrlw54.js → agents-OQHCkIfJ.js} +2 -2
  143. package/dashboard/dist/assets/{agents-DfMrlw54.js.map → agents-OQHCkIfJ.js.map} +1 -1
  144. package/dashboard/dist/assets/{bots-B9zS0z7D.js → bots-e8jsNOf4.js} +2 -2
  145. package/dashboard/dist/assets/{bots-B9zS0z7D.js.map → bots-e8jsNOf4.js.map} +1 -1
  146. package/dashboard/dist/assets/{capabilities-DkLM1xgH.js → capabilities-CEo0AB79.js} +2 -2
  147. package/dashboard/dist/assets/{capabilities-DkLM1xgH.js.map → capabilities-CEo0AB79.js.map} +1 -1
  148. package/dashboard/dist/assets/{controlplane-SJK1yvbm.js → controlplane-CD6ti-QB.js} +2 -2
  149. package/dashboard/dist/assets/{controlplane-SJK1yvbm.js.map → controlplane-CD6ti-QB.js.map} +1 -1
  150. package/dashboard/dist/assets/{escalation-columns-BvAylNM1.js → escalation-columns-CUtDSbxl.js} +2 -2
  151. package/dashboard/dist/assets/{escalation-columns-BvAylNM1.js.map → escalation-columns-CUtDSbxl.js.map} +1 -1
  152. package/dashboard/dist/assets/{index-DSfY8oDp.js → index-B0C6wSrQ.js} +2 -2
  153. package/dashboard/dist/assets/{index-DSfY8oDp.js.map → index-B0C6wSrQ.js.map} +1 -1
  154. package/dashboard/dist/assets/index-B2aiEKtM.js +2 -0
  155. package/dashboard/dist/assets/index-B2aiEKtM.js.map +1 -0
  156. package/dashboard/dist/assets/{index-DKXOIcO3.js → index-B76fjEom.js} +2 -2
  157. package/dashboard/dist/assets/{index-DKXOIcO3.js.map → index-B76fjEom.js.map} +1 -1
  158. package/dashboard/dist/assets/{index-DvmyIGeZ.js → index-BYIN0l5M.js} +2 -2
  159. package/dashboard/dist/assets/{index-DvmyIGeZ.js.map → index-BYIN0l5M.js.map} +1 -1
  160. package/dashboard/dist/assets/{index-CXe2d5kg.js → index-Bf4IPu7I.js} +2 -2
  161. package/dashboard/dist/assets/{index-CXe2d5kg.js.map → index-Bf4IPu7I.js.map} +1 -1
  162. package/dashboard/dist/assets/index-BpwkKV5f.js +3 -0
  163. package/dashboard/dist/assets/index-BpwkKV5f.js.map +1 -0
  164. package/dashboard/dist/assets/{index-Cw-V0VhS.js → index-BsP7vujM.js} +2 -2
  165. package/dashboard/dist/assets/{index-Cw-V0VhS.js.map → index-BsP7vujM.js.map} +1 -1
  166. package/dashboard/dist/assets/{index-PjiXOVdw.js → index-C8VhbKFU.js} +2 -2
  167. package/dashboard/dist/assets/{index-PjiXOVdw.js.map → index-C8VhbKFU.js.map} +1 -1
  168. package/dashboard/dist/assets/{index-D2IRxjSf.js → index-COUj4v_W.js} +2 -2
  169. package/dashboard/dist/assets/{index-D2IRxjSf.js.map → index-COUj4v_W.js.map} +1 -1
  170. package/dashboard/dist/assets/{index-ClVNU3G3.js → index-CTZEzzN3.js} +2 -2
  171. package/dashboard/dist/assets/{index-ClVNU3G3.js.map → index-CTZEzzN3.js.map} +1 -1
  172. package/dashboard/dist/assets/{index-DazfFRUx.js → index-DIHr2CvI.js} +2 -2
  173. package/dashboard/dist/assets/{index-DazfFRUx.js.map → index-DIHr2CvI.js.map} +1 -1
  174. package/dashboard/dist/assets/{index-zrTQcPjB.js → index-DSdqso-_.js} +3 -3
  175. package/dashboard/dist/assets/{index-zrTQcPjB.js.map → index-DSdqso-_.js.map} +1 -1
  176. package/dashboard/dist/assets/{index-CLxuBb17.js → index-VsZyCFz8.js} +2 -2
  177. package/dashboard/dist/assets/{index-CLxuBb17.js.map → index-VsZyCFz8.js.map} +1 -1
  178. package/dashboard/dist/assets/{index-CJV2pWNH.css → index-fUqvRHOe.css} +1 -1
  179. package/dashboard/dist/assets/{knowledge-BNp6MH-4.js → knowledge-C89zT4Qe.js} +2 -2
  180. package/dashboard/dist/assets/{knowledge-BNp6MH-4.js.map → knowledge-C89zT4Qe.js.map} +1 -1
  181. package/dashboard/dist/assets/{mcp-Bb1k5rv-.js → mcp-BLKHykZS.js} +2 -2
  182. package/dashboard/dist/assets/{mcp-Bb1k5rv-.js.map → mcp-BLKHykZS.js.map} +1 -1
  183. package/dashboard/dist/assets/{mcp-query-QVakMQnS.js → mcp-query-CfiqUNDV.js} +2 -2
  184. package/dashboard/dist/assets/{mcp-query-QVakMQnS.js.map → mcp-query-CfiqUNDV.js.map} +1 -1
  185. package/dashboard/dist/assets/{personas-DV2JUjVj.js → personas-B1HzC94M.js} +2 -2
  186. package/dashboard/dist/assets/{personas-DV2JUjVj.js.map → personas-B1HzC94M.js.map} +1 -1
  187. package/dashboard/dist/assets/{pipelines-BkVB7Q0p.js → pipelines-C73X50ES.js} +2 -2
  188. package/dashboard/dist/assets/{pipelines-BkVB7Q0p.js.map → pipelines-C73X50ES.js.map} +1 -1
  189. package/dashboard/dist/assets/{tasks-DvYWcASM.js → tasks-DHbFpQk4.js} +2 -2
  190. package/dashboard/dist/assets/{tasks-DvYWcASM.js.map → tasks-DHbFpQk4.js.map} +1 -1
  191. package/dashboard/dist/assets/{topics-B9zXFuVG.js → topics-Fu8qCUOd.js} +2 -2
  192. package/dashboard/dist/assets/{topics-B9zXFuVG.js.map → topics-Fu8qCUOd.js.map} +1 -1
  193. package/dashboard/dist/assets/{useEventHooks-JDpifqGZ.js → useEventHooks-DL3Vhz4g.js} +2 -2
  194. package/dashboard/dist/assets/{useEventHooks-JDpifqGZ.js.map → useEventHooks-DL3Vhz4g.js.map} +1 -1
  195. package/dashboard/dist/assets/{useNamespace-Bqr-LdWx.js → useNamespace-CpO5Hogb.js} +2 -2
  196. package/dashboard/dist/assets/{useNamespace-Bqr-LdWx.js.map → useNamespace-CpO5Hogb.js.map} +1 -1
  197. package/dashboard/dist/assets/{useYamlActivityEvents-n3naCEbw.js → useYamlActivityEvents-BwIl6_d2.js} +2 -2
  198. package/dashboard/dist/assets/{useYamlActivityEvents-n3naCEbw.js.map → useYamlActivityEvents-BwIl6_d2.js.map} +1 -1
  199. package/dashboard/dist/assets/users-C0ke1Z-8.js +2 -0
  200. package/dashboard/dist/assets/users-C0ke1Z-8.js.map +1 -0
  201. package/dashboard/dist/assets/{workflows-D8uMBPvQ.js → workflows-DR9OQcuq.js} +2 -2
  202. package/dashboard/dist/assets/{workflows-D8uMBPvQ.js.map → workflows-DR9OQcuq.js.map} +1 -1
  203. package/dashboard/dist/assets/{yaml-workflows-DVDOQM3Y.js → yaml-workflows-DjEHh9Wy.js} +2 -2
  204. package/dashboard/dist/assets/{yaml-workflows-DVDOQM3Y.js.map → yaml-workflows-DjEHh9Wy.js.map} +1 -1
  205. package/dashboard/dist/index.html +2 -2
  206. package/docs/api/http/users.md +53 -1
  207. package/docs/api/http/workflows.md +35 -0
  208. package/docs/api/mcp/admin.md +31 -0
  209. package/docs/api/sdk/users.md +24 -0
  210. package/docs/api/sdk/workflows.md +21 -0
  211. package/docs/dashboard.md +1 -1
  212. package/docs/hitl/lookups.md +10 -0
  213. package/docs/hitl/x-lt-validation.md +2 -1
  214. package/docs/hitl/x-lt-widget.md +1 -1
  215. package/docs/hitl-guide.md +2 -2
  216. package/package.json +2 -2
  217. package/dashboard/dist/assets/index-DTZxHZJO.js +0 -3
  218. package/dashboard/dist/assets/index-DTZxHZJO.js.map +0 -1
  219. package/dashboard/dist/assets/index-DamcWcqG.js +0 -2
  220. package/dashboard/dist/assets/index-DamcWcqG.js.map +0 -1
  221. package/dashboard/dist/assets/users-BNXLRVTS.js +0 -2
  222. package/dashboard/dist/assets/users-BNXLRVTS.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"yaml-workflows-DVDOQM3Y.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-DjEHh9Wy.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-zrTQcPjB.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-DSdqso-_.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="./assets/vendor-query-RUZdMvN6.js">
13
13
  <link rel="modulepreload" crossorigin href="./assets/vendor-react-CdqEC2zv.js">
14
14
  <link rel="modulepreload" crossorigin href="./assets/vendor-icons-h-jlRSb9.js">
15
- <link rel="stylesheet" crossorigin href="./assets/index-CJV2pWNH.css">
15
+ <link rel="stylesheet" crossorigin href="./assets/index-fUqvRHOe.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -149,7 +149,7 @@ Partial update — only the fields you include are changed.
149
149
  | `email` | `string` | New email address |
150
150
  | `display_name` | `string` | New display name |
151
151
  | `status` | `string` | `active`, `inactive`, or `suspended` |
152
- | `metadata` | `object` | Replacement metadata |
152
+ | `metadata` | `object` | **Replaces the whole properties dictionary** — for per-key edits use `PATCH /:id/properties`, which never clobbers siblings |
153
153
 
154
154
  **Example request:**
155
155
 
@@ -168,6 +168,58 @@ Partial update — only the fields you include are changed.
168
168
  { "error": "User not found" }
169
169
  ```
170
170
 
171
+ ## Patch user properties
172
+
173
+ ```
174
+ PATCH /api/users/:id/properties
175
+ ```
176
+
177
+ Atomically patch the user's properties dictionary (`metadata`) — one statement, never read-merge-write. Editing one property can never clobber another; a rename preserves its value with no key-absent window. Builder only (the same gate as every other user write).
178
+
179
+ **Request body:**
180
+
181
+ | Field | Type | Description |
182
+ |-------|------|-------------|
183
+ | `set` | `object` | Properties to set. Values are typed JSON — numbers, booleans, and objects round-trip intact |
184
+ | `remove` | `string[]` | Property keys to delete. Deleting is explicit: a key absent from the patch is kept |
185
+ | `rename` | `object` | `{ "oldKey": "newKey" }` renames, values preserved |
186
+
187
+ Precedence on key collision: `set` > `rename` > existing.
188
+
189
+ **Example request:**
190
+
191
+ ```json
192
+ {
193
+ "set": { "badgeSlug": "gluer-june", "shift": "night" },
194
+ "remove": ["legacy_pin"],
195
+ "rename": { "station": "station_affinity" }
196
+ }
197
+ ```
198
+
199
+ **Response 200:** The updated user object.
200
+
201
+ **Response 400:** malformed patch (empty key, a key both set and removed, self-rename).
202
+
203
+ **Response 409:** an **identity-binding** value already belongs to another active user. Keys named as an enabled identity scan scheme's `target_facet` (e.g. `badge_id`) are how the platform resolves badge scans to people — the patch asserts, in the same statement, that no other active user carries the value, the write-side counterpart of the resolver's ambiguity error.
204
+
205
+ ```json
206
+ { "error": "\"badge_id\" value is already bound to another active user" }
207
+ ```
208
+
209
+ ## System property keys
210
+
211
+ ```
212
+ GET /api/users/system-property-keys
213
+ ```
214
+
215
+ The property keys the platform itself resolves identities against — every enabled identity scan scheme's `target_facet`. The dashboard marks these as system properties in the editor.
216
+
217
+ **Response 200:**
218
+
219
+ ```json
220
+ { "keys": ["badge_id"] }
221
+ ```
222
+
171
223
  ## Delete user
172
224
 
173
225
  ```
@@ -471,6 +471,41 @@ Every event is faithfully reconstructed from the durable execution log — activ
471
471
 
472
472
  **Verbose mode** includes nested `children` arrays for orchestrator workflows, where each child contains its own full event sequence. Use `maxDepth` to limit recursion for deeply nested orchestrations.
473
473
 
474
+ ### Workflow envelopes — input and output
475
+
476
+ ```
477
+ GET /api/workflow-states/:workflowId/envelopes
478
+ ```
479
+
480
+ The effortless read: what went in, what came out. Two narrow lookups — the input is a single field read available for the life of the job; the output is a single state read that never blocks. No event stream, no full export, so the call stays cheap on the largest jobs.
481
+
482
+ **Response 200 (running):**
483
+
484
+ ```json
485
+ {
486
+ "workflow_id": "reviewContent-a1b2c3d4",
487
+ "status": "running",
488
+ "input": { "data": { "contentId": "c-1" }, "metadata": { "source": "dashboard" } },
489
+ "output": null
490
+ }
491
+ ```
492
+
493
+ **Response 200 (completed):**
494
+
495
+ ```json
496
+ {
497
+ "workflow_id": "reviewContent-a1b2c3d4",
498
+ "status": "completed",
499
+ "input": { "data": { "contentId": "c-1" }, "metadata": { "source": "dashboard" } },
500
+ "output": { "type": "return", "data": { "approved": true } }
501
+ }
502
+ ```
503
+
504
+ - `input` — the workflow's input envelope, exactly as invoked. A one-argument workflow (the long-tail convention) answers the envelope itself; a multi-argument workflow answers the args array.
505
+ - `output` — the workflow's return envelope, or `null` while the run is in flight (`status: "running"`) — this endpoint is the natural polling body. A failed run answers `status: "failed"`, `output: null`, and an `error` message.
506
+
507
+ **Response 404:** the workflow does not exist or its data has expired.
508
+
474
509
  ### Workflow status semaphore
475
510
 
476
511
  ```
@@ -740,6 +740,23 @@ Assign a role to a user. For a `member`, optional scope narrows the work surface
740
740
  | read_scope | string | No | Member search breadth: `self` or `all` (default `all`) |
741
741
  | write_scope | string | No | Member claim/ack/delete breadth: `none`, `self`, or `all` (default `all`) |
742
742
 
743
+ ### patch_user_properties
744
+
745
+ Atomically patch a user's properties dictionary (`lt_users.metadata`) — set/remove/rename keys in one statement, never read-merge-write. Identity-binding keys (badge scheme target facets) assert uniqueness among active users.
746
+
747
+ | | |
748
+ |---|---|
749
+ | Read-safe | No |
750
+
751
+ **Parameters:**
752
+
753
+ | Field | Type | Required | Description |
754
+ |-------|------|----------|-------------|
755
+ | user_id | string | Yes | User UUID |
756
+ | set | object | No | Properties to set — typed JSON values |
757
+ | remove | array | No | Property keys to delete |
758
+ | rename | object | No | `{ oldKey: newKey }` renames — values preserved |
759
+
743
760
  ### remove_user_role
744
761
 
745
762
  Remove a role from a user.
@@ -1531,6 +1548,20 @@ Export workflow state as a structured execution event history.
1531
1548
  | mode | string | No | Export mode |
1532
1549
  | maxDepth | integer | No | Max traversal depth |
1533
1550
 
1551
+ ### get_workflow_envelopes
1552
+
1553
+ The workflow's input and output envelopes — two narrow lookups, no event stream. Output is `null` with status `running` until the workflow completes; a failed run carries its error message. The token-cheap read when you only need what went in and what came out.
1554
+
1555
+ | | |
1556
+ |---|---|
1557
+ | Read-safe | Yes |
1558
+
1559
+ **Parameters:**
1560
+
1561
+ | Field | Type | Required | Description |
1562
+ |-------|------|----------|-------------|
1563
+ | workflow_id | string | Yes | Workflow ID whose input/output envelopes to fetch |
1564
+
1534
1565
  ### get_export_status
1535
1566
 
1536
1567
  Return the numeric status semaphore for a workflow.
@@ -117,6 +117,30 @@ const result = await lt.users.update({
117
117
 
118
118
  ---
119
119
 
120
+ ## patchProperties
121
+
122
+ Atomically patch the user's properties dictionary — one statement, never read-merge-write. Deleting is explicit (`remove`); an absent key is kept; `rename` preserves the value. Identity-binding keys (badge scheme facets) assert uniqueness among active users (409 on conflict).
123
+
124
+ ```typescript
125
+ const result = await lt.users.patchProperties({
126
+ id: 'user-uuid',
127
+ set: { badgeSlug: 'gluer-june', shift: 'night' },
128
+ remove: ['legacy_pin'],
129
+ rename: { station: 'station_affinity' },
130
+ });
131
+ ```
132
+
133
+ **Returns:** `LTApiResult<User>` — 400 malformed patch, 404 unknown user, 409 identity conflict.
134
+
135
+ ## getSystemPropertyKeys
136
+
137
+ The property keys the platform resolves identities against (enabled identity scan schemes' target facets).
138
+
139
+ ```typescript
140
+ const result = await lt.users.getSystemPropertyKeys();
141
+ // result.data → { keys: ['badge_id'] }
142
+ ```
143
+
120
144
  ## delete
121
145
 
122
146
  Delete a user by ID.
@@ -52,6 +52,27 @@ const result = await lt.workflows.getStatus({ workflowId: 'wf_abc' });
52
52
 
53
53
  ---
54
54
 
55
+ ## getEnvelopes
56
+
57
+ The workflow's input and output envelopes — two narrow lookups, never blocking. `output` is `null` with `status: 'running'` while the run is in flight; a failed run answers `status: 'failed'` with the workflow's `error` message.
58
+
59
+ ```typescript
60
+ const result = await lt.workflows.getEnvelopes({ workflowId: 'reviewContent-a1b2c3d4' });
61
+ // result.data → { workflow_id, status, input, output, error? }
62
+ ```
63
+
64
+ **Parameters:**
65
+
66
+ | Field | Type | Required | Description |
67
+ |-------|------|----------|-------------|
68
+ | `workflowId` | `string` | Yes | The workflow's unique identifier |
69
+
70
+ **Returns:** `LTApiResult<{ workflow_id, status: 'running' | 'completed' | 'failed', input, output, error? }>` — 404 when the workflow is unknown or expired.
71
+
72
+ **Auth:** Not required
73
+
74
+ ---
75
+
55
76
  ## getResult
56
77
 
57
78
  Get the result of a completed workflow.
package/docs/dashboard.md CHANGED
@@ -208,7 +208,7 @@ Lists all procedural workflow runs across the system.
208
208
 
209
209
  User Accounts and Service Accounts live on the same page, separated by a tab toggle.
210
210
 
211
- - **User Accounts** — human operators. Create users, assign display names, and grant roles. Roles determine which escalations a user can see and claim, and which workflows they can invoke from the dashboard. A `member` grant carries a work-surface scope (read/write breadth) chosen from the Scope picker; the five named profiles are documented under [Role Detail](#role-detail).
211
+ - **User Accounts** — human operators. Create users, assign display names, and grant roles. The side panel's **Properties** table edits the user's free-form dictionary (badge bindings, shift, any per-person attribute) one key at a time — every edit is an atomic patch that never clobbers sibling keys, and keys the platform resolves identities against (badge scheme facets) carry a **system** mark with a confirm step. Roles determine which escalations a user can see and claim, and which workflows they can invoke from the dashboard. A `member` grant carries a work-surface scope (read/write breadth) chosen from the Scope picker; the five named profiles are documented under [Role Detail](#role-detail).
212
212
  - **Service Accounts** — programmatic callers (bots, CI pipelines, external systems). Each service account has an API key for authentication. Assign roles to control access just like human users. Service accounts with the `reviewer` role can claim and resolve escalations programmatically.
213
213
  - **Role assignment** — both account types participate in the same role system. Click any account to edit roles, change display name, or manage credentials.
214
214
  - **Personas** — the role panel also assigns [personas](#personas): pick one to add the account to every linked role at the linked scope in one step. Memberships a persona sustains show a mask icon; direct grants show none and survive persona unassignment.
@@ -126,6 +126,16 @@ With a `catalog/geo` entry shaped as:
126
126
 
127
127
  Interpolation works in `x-lt-source` the same way, so checklist item sets can follow an answer too.
128
128
 
129
+ ### Migrating a field to a lookup — strand-free
130
+
131
+ `x-lt-options` and `x-lt-source` accept an **ordered array of paths**; the first that resolves wins. That makes an embedded list and a pinned lookup fully interchangeable behind one shared schema:
132
+
133
+ ```json
134
+ "reasonId": { "type": "string", "x-lt-options": ["lookup.reasons.items", "envelope.reject_reason_items"] }
135
+ ```
136
+
137
+ New escalations pin the ref and render from the edition; rows parked before the migration carry no ref and fall through to the envelope list they were minted with — the same select either way. Flip the shared role schema, deploy, and no in-flight row strands; the reverse migration is equally safe.
138
+
129
139
  A lookup-sourced checklist can declare `"x-lt-default-checked": true` to start every item checked (uncheck the exceptions). The widget applies the default when the edition resolves, so a pure escalation-minting step never needs to enumerate the item ids — see [x-lt-widget.md](x-lt-widget.md#first-load-default-x-lt-default-checked).
130
140
 
131
141
  ## Efficiency
@@ -115,11 +115,12 @@ A select's option list can ride the escalation instead of the schema. The field-
115
115
 
116
116
  When the envelope carries `left_quantity_options: [0, 1, 2, 3]`, the field renders as a dropdown offering exactly those values — an out-of-range answer is structurally impossible. The workflow mints only the small per-row array; the form itself stays on the role.
117
117
 
118
+ - The token is a `"domain.path"` string or an **ordered array of paths** — `["lookup.reasons.items", "envelope.reject_reason_items"]`. With an array, the **first path that resolves to options wins**, so lookup-backed and envelope-embedded rows render the same shared schema interchangeably: migrate a field to a versioned lookup and rows parked before the migration fall through to the envelope they already carry. A plain string behaves exactly as a one-element array.
118
119
  - Entries are scalars or `{ value, label }` objects (`{ id, label }` accepted as an alias): the select shows the label and the submitted answer is the value — a pick list can display text while storing its foreign key. A scalar is both. Mixed arrays resolve each entry independently; malformed entries are dropped.
119
120
  - A static `enum` takes precedence when both are present — the same static-over-dynamic rule as the bounds tokens.
120
121
  - The declared `type` governs the value: a number-typed field emits the picked option as a number, a string-typed field as a string.
121
122
  - While the current value is outside the option list (an empty init, options that shrank per-row), the select opens on an explicit disabled **Choose…** placeholder — never an implicit first option.
122
- - A path that resolves to nothing (missing, empty array, no scalar entries) yields no options: the field renders as the plain input for its type and membership is not enforced for that submission.
123
+ - When no path resolves (missing, empty array, no valid entries) the field renders as the plain input for its type and membership is not enforced for that submission — unless any path embeds `{{domain.path}}` interpolation, in which case the field stays a disabled select and a present value fails closed (a cascade child never becomes free text).
123
124
  - Membership is enforced on both sides of the wire — always on the option VALUE, never the label: the dashboard constrains the choices, and an enforced role's server gate rejects a payload whose value is outside the row's resolved list with the canonical 422 (`Must be one of: 0, 1, 2, 3`).
124
125
  - Option lists can also come from version-pinned knowledge entries (the `lookup` domain), and paths may embed `{{domain.path}}` interpolation segments for cascading selects — a dependent select whose parent is unanswered renders disabled and fails closed. See [lookups.md](lookups.md).
125
126
 
@@ -142,7 +142,7 @@ The field type must be `"object"`. The submitted value is `Record<string, boolea
142
142
  }
143
143
  ```
144
144
 
145
- `x-lt-source` uses the `"domain.path"` convention (same as `x-lt-showIf` and `x-lt-help` tokens), and may embed `{{domain.path}}` interpolation segments. The renderer expects an array of `{ id: string; label: string; required?: boolean }` objects at that path.
145
+ `x-lt-source` uses the `"domain.path"` convention (same as `x-lt-showIf` and `x-lt-help` tokens), and may embed `{{domain.path}}` interpolation segments. The token is a single path or an **ordered array of paths** — the first that resolves to items wins, so a lookup-backed row and an envelope-embedded row render the same shared schema interchangeably. The renderer expects an array of `{ id: string; label: string; required?: boolean }` objects at the resolved path.
146
146
 
147
147
  - `"envelope"` — for item definitions that are render data only (no query cost). The workflow puts them in `conditional`'s `envelope` parameter.
148
148
  - `"lookup"` — for item sets shared by many rows: a version-pinned knowledge edition (see [lookups.md](lookups.md)).
@@ -104,7 +104,7 @@ Ordered as a learning path — each file adds one capability to the same form:
104
104
  | Keyword | Level | Purpose |
105
105
  |---------|-------|---------|
106
106
  | `x-lt-widget` | field | Rich control: `file-upload`, `code-editor`, `signature`, `rich-text`, `markdown`, `checklist`, `attachment` (alias `image`) |
107
- | `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"`; may embed `{{domain.path}}` interpolation segments |
107
+ | `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"` or an ordered array of paths (first to resolve wins); may embed `{{domain.path}}` interpolation segments |
108
108
  | `x-lt-require-all` | field | Checklist completion guard — every item must be checked, except items declared `required: false` |
109
109
  | `x-lt-default-checked` | field | Checklist first-load default — an unanswered field initializes to every item checked (affirm-then-exception); saved answers are never clobbered |
110
110
  | `x-lt-require-any` | schema | At-least-one guard — each `string[]` group needs a value in one visible member; `0`/`false` count as answers |
@@ -116,7 +116,7 @@ Ordered as a learning path — each file adds one capability to the same form:
116
116
  | `x-lt-showIf` | field | Show field when a value is truthy at `domain.path`; prefix `!` to invert; `=VALUE` / `!=VALUE` compare the string form |
117
117
  | `x-lt-hide-if-empty` | field | `true` — suppress the field when its value is null, `""`, `false`, or `0` |
118
118
  | `x-lt-section` | field | Section group label |
119
- | `x-lt-options` | field | Dynamic select options — resolves a `"domain.path"` to the field's option list (scalars or `{ value, label }`); static `enum` wins; `{{domain.path}}` segments make cascading selects |
119
+ | `x-lt-options` | field | Dynamic select options — resolves a `"domain.path"` (or an ordered array of paths, first to resolve wins) to the field's option list (scalars or `{ value, label }`); static `enum` wins; `{{domain.path}}` segments make cascading selects |
120
120
  | `x-lt-minimum` | field | Dynamic lower bound — resolves a `"domain.path"` from the escalation context |
121
121
  | `x-lt-maximum` | field | Dynamic upper bound — resolves a `"domain.path"` from the escalation context |
122
122
  | `x-lt-min-length` | field | Dynamic minimum string length — resolves a `"domain.path"` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -73,7 +73,7 @@
73
73
  "@anthropic-ai/sdk": "^0.92.0",
74
74
  "@aws-sdk/client-s3": "^3.1017.0",
75
75
  "@aws-sdk/s3-request-presigner": "^3.1045.0",
76
- "@hotmeshio/hotmesh": "^0.27.0",
76
+ "@hotmeshio/hotmesh": "^0.27.1",
77
77
  "@modelcontextprotocol/sdk": "^1.27.1",
78
78
  "@opentelemetry/exporter-trace-otlp-proto": "^0.215.0",
79
79
  "@opentelemetry/resources": "^2.5.1",