@hotmeshio/long-tail 0.10.8 → 0.10.10

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 (296) hide show
  1. package/build/api/escalations/bulk.js +7 -1
  2. package/build/api/escalations/helpers.d.ts +10 -1
  3. package/build/api/escalations/helpers.js +52 -12
  4. package/build/api/index.d.ts +1 -0
  5. package/build/api/index.js +2 -1
  6. package/build/api/personas.d.ts +121 -0
  7. package/build/api/personas.js +341 -0
  8. package/build/bin/ltc.js +23 -0
  9. package/build/lib/cli/commands/personas.d.ts +16 -0
  10. package/build/lib/cli/commands/personas.js +42 -0
  11. package/build/lib/db/schemas/024_personas.sql +53 -0
  12. package/build/lib/events/matching.d.ts +10 -0
  13. package/build/lib/events/matching.js +14 -0
  14. package/build/lib/events/publish.d.ts +8 -2
  15. package/build/lib/events/publish.js +9 -2
  16. package/build/lib/events/socketio.d.ts +8 -2
  17. package/build/lib/events/socketio.js +36 -3
  18. package/build/lib/events/system-events.js +9 -1
  19. package/build/routes/index.js +2 -0
  20. package/build/routes/personas.d.ts +2 -0
  21. package/build/routes/personas.js +118 -0
  22. package/build/routes/users.js +35 -0
  23. package/build/sdk/index.d.ts +15 -0
  24. package/build/sdk/index.js +16 -0
  25. package/build/services/escalation/crud.js +40 -2
  26. package/build/services/orchestrator/condition.d.ts +1 -1
  27. package/build/services/orchestrator/condition.js +1 -1
  28. package/build/services/persona/index.d.ts +92 -0
  29. package/build/services/persona/index.js +217 -0
  30. package/build/services/persona/sql.d.ts +24 -0
  31. package/build/services/persona/sql.js +158 -0
  32. package/build/services/persona/types.d.ts +23 -0
  33. package/build/services/persona/types.js +33 -0
  34. package/build/services/topics/system-topics.d.ts +0 -4
  35. package/build/services/topics/system-topics.js +57 -14
  36. package/build/services/user/sql.d.ts +8 -5
  37. package/build/services/user/sql.js +15 -5
  38. package/build/system/mcp-servers/admin/index.d.ts +1 -0
  39. package/build/system/mcp-servers/admin/index.js +5 -2
  40. package/build/system/mcp-servers/admin/personas.d.ts +8 -0
  41. package/build/system/mcp-servers/admin/personas.js +186 -0
  42. package/build/system/mcp-servers/admin/schemas.d.ts +91 -0
  43. package/build/system/mcp-servers/admin/schemas.js +42 -2
  44. package/build/system/seed/tool-manifests-admin.d.ts +975 -0
  45. package/build/system/seed/tool-manifests-admin.js +11 -0
  46. package/build/tsconfig.tsbuildinfo +1 -1
  47. package/build/types/events.d.ts +11 -3
  48. package/build/types/index.d.ts +1 -0
  49. package/build/types/persona.d.ts +56 -0
  50. package/build/types/persona.js +2 -0
  51. package/build/types/user.d.ts +2 -0
  52. package/dashboard/dist/assets/{AdminDashboard-D0HdEkT9.js → AdminDashboard-cGYuppUP.js} +2 -2
  53. package/dashboard/dist/assets/{AdminDashboard-D0HdEkT9.js.map → AdminDashboard-cGYuppUP.js.map} +1 -1
  54. package/dashboard/dist/assets/{AgentConfigPage-CtURUMOV.js → AgentConfigPage-DwaUyoCy.js} +2 -2
  55. package/dashboard/dist/assets/{AgentConfigPage-CtURUMOV.js.map → AgentConfigPage-DwaUyoCy.js.map} +1 -1
  56. package/dashboard/dist/assets/AgentDetailPage-DxpFaltM.js +4 -0
  57. package/dashboard/dist/assets/AgentDetailPage-DxpFaltM.js.map +1 -0
  58. package/dashboard/dist/assets/{AgentsPage-DBequneI.js → AgentsPage-ByOoA8oT.js} +2 -2
  59. package/dashboard/dist/assets/{AgentsPage-DBequneI.js.map → AgentsPage-ByOoA8oT.js.map} +1 -1
  60. package/dashboard/dist/assets/AutoGrowTextarea-y-oNY51_.js +2 -0
  61. package/dashboard/dist/assets/AutoGrowTextarea-y-oNY51_.js.map +1 -0
  62. package/dashboard/dist/assets/{AvailableEscalationsPage-Bk7fFV2e.js → AvailableEscalationsPage-C1vtTvqP.js} +2 -2
  63. package/dashboard/dist/assets/AvailableEscalationsPage-C1vtTvqP.js.map +1 -0
  64. package/dashboard/dist/assets/{BotPicker-BMXokkH7.js → BotPicker-Dohv8dhR.js} +2 -2
  65. package/dashboard/dist/assets/{BotPicker-BMXokkH7.js.map → BotPicker-Dohv8dhR.js.map} +1 -1
  66. package/dashboard/dist/assets/{CapabilitiesPage-w-D6xraE.js → CapabilitiesPage-DeijFG3J.js} +2 -2
  67. package/dashboard/dist/assets/{CapabilitiesPage-w-D6xraE.js.map → CapabilitiesPage-DeijFG3J.js.map} +1 -1
  68. package/dashboard/dist/assets/{CollapsibleSection-IPL1H1bQ.js → CollapsibleSection-BPNwS4eO.js} +2 -2
  69. package/dashboard/dist/assets/{CollapsibleSection-IPL1H1bQ.js.map → CollapsibleSection-BPNwS4eO.js.map} +1 -1
  70. package/dashboard/dist/assets/CountdownTimer-BF71ldGF.js +2 -0
  71. package/dashboard/dist/assets/CountdownTimer-BF71ldGF.js.map +1 -0
  72. package/dashboard/dist/assets/{CredentialsPage-DR48hDES.js → CredentialsPage-oeNmMzTM.js} +2 -2
  73. package/dashboard/dist/assets/{CredentialsPage-DR48hDES.js.map → CredentialsPage-oeNmMzTM.js.map} +1 -1
  74. package/dashboard/dist/assets/{CronLabel-KQEj0cDS.js → CronLabel-CebR1m2k.js} +2 -2
  75. package/dashboard/dist/assets/{CronLabel-KQEj0cDS.js.map → CronLabel-CebR1m2k.js.map} +1 -1
  76. package/dashboard/dist/assets/CustomDurationPicker-Bh9QdBVw.js +2 -0
  77. package/dashboard/dist/assets/CustomDurationPicker-Bh9QdBVw.js.map +1 -0
  78. package/dashboard/dist/assets/{DropZone-BrnAkQxF.js → DropZone-Bavzt2QR.js} +2 -2
  79. package/dashboard/dist/assets/{DropZone-BrnAkQxF.js.map → DropZone-Bavzt2QR.js.map} +1 -1
  80. package/dashboard/dist/assets/ElapsedCell-Caa6CU_y.js +2 -0
  81. package/dashboard/dist/assets/{ElapsedCell-Cflz7Pb5.js.map → ElapsedCell-Caa6CU_y.js.map} +1 -1
  82. package/dashboard/dist/assets/{EscalationListSchemaPage-BTBZ8OBY.js → EscalationListSchemaPage-CAGfq0eK.js} +3 -3
  83. package/dashboard/dist/assets/{EscalationListSchemaPage-BTBZ8OBY.js.map → EscalationListSchemaPage-CAGfq0eK.js.map} +1 -1
  84. package/dashboard/dist/assets/{EscalationSchemaPage-Cd9fR2EA.js → EscalationSchemaPage-qDD4ur6P.js} +2 -2
  85. package/dashboard/dist/assets/{EscalationSchemaPage-Cd9fR2EA.js.map → EscalationSchemaPage-qDD4ur6P.js.map} +1 -1
  86. package/dashboard/dist/assets/{EscalationsOverview-BzNFcA0i.js → EscalationsOverview-CC1wRTzy.js} +2 -2
  87. package/dashboard/dist/assets/{EscalationsOverview-BzNFcA0i.js.map → EscalationsOverview-CC1wRTzy.js.map} +1 -1
  88. package/dashboard/dist/assets/{EventTable-S2BJqOt2.js → EventTable-4JeTcXr_.js} +2 -2
  89. package/dashboard/dist/assets/{EventTable-S2BJqOt2.js.map → EventTable-4JeTcXr_.js.map} +1 -1
  90. package/dashboard/dist/assets/{FilterBar-CeXwNVn6.js → FilterBar-BOV8DWIO.js} +2 -2
  91. package/dashboard/dist/assets/{FilterBar-CeXwNVn6.js.map → FilterBar-BOV8DWIO.js.map} +1 -1
  92. package/dashboard/dist/assets/{GraphInvokePage-CBjXjOLX.js → GraphInvokePage-C0i1speW.js} +2 -2
  93. package/dashboard/dist/assets/{GraphInvokePage-CBjXjOLX.js.map → GraphInvokePage-C0i1speW.js.map} +1 -1
  94. package/dashboard/dist/assets/HomePage-HPCd8SjF.js +2 -0
  95. package/dashboard/dist/assets/HomePage-HPCd8SjF.js.map +1 -0
  96. package/dashboard/dist/assets/{ListToolbar-Dx6DuFdR.js → ListToolbar-BFHVOba6.js} +2 -2
  97. package/dashboard/dist/assets/{ListToolbar-Dx6DuFdR.js.map → ListToolbar-BFHVOba6.js.map} +1 -1
  98. package/dashboard/dist/assets/{McpOverview-Cj8_UyWJ.js → McpOverview-Chn2zIXr.js} +2 -2
  99. package/dashboard/dist/assets/{McpOverview-Cj8_UyWJ.js.map → McpOverview-Chn2zIXr.js.map} +1 -1
  100. package/dashboard/dist/assets/McpQueryDetailPage-Cv1FKrvw.js +5 -0
  101. package/dashboard/dist/assets/McpQueryDetailPage-Cv1FKrvw.js.map +1 -0
  102. package/dashboard/dist/assets/McpQueryPage-Dzn8JE4E.js +2 -0
  103. package/dashboard/dist/assets/McpQueryPage-Dzn8JE4E.js.map +1 -0
  104. package/dashboard/dist/assets/{McpRunDetailPage-BqhRwkGk.js → McpRunDetailPage-CuNtR4Ed.js} +2 -2
  105. package/dashboard/dist/assets/{McpRunDetailPage-BqhRwkGk.js.map → McpRunDetailPage-CuNtR4Ed.js.map} +1 -1
  106. package/dashboard/dist/assets/{McpRunsPage-CNXYU4iX.js → McpRunsPage-C8iifeKN.js} +2 -2
  107. package/dashboard/dist/assets/{McpRunsPage-CNXYU4iX.js.map → McpRunsPage-C8iifeKN.js.map} +1 -1
  108. package/dashboard/dist/assets/{NamespacePill-DQGzN0Ph.js → NamespacePill-ep9Zmokr.js} +2 -2
  109. package/dashboard/dist/assets/{NamespacePill-DQGzN0Ph.js.map → NamespacePill-ep9Zmokr.js.map} +1 -1
  110. package/dashboard/dist/assets/{OperationsPage-C7UB_d-X.js → OperationsPage-flrZ-EJ9.js} +2 -2
  111. package/dashboard/dist/assets/{OperationsPage-C7UB_d-X.js.map → OperationsPage-flrZ-EJ9.js.map} +1 -1
  112. package/dashboard/dist/assets/OperatorDashboard-Dhs2eo8p.js +2 -0
  113. package/dashboard/dist/assets/OperatorDashboard-Dhs2eo8p.js.map +1 -0
  114. package/dashboard/dist/assets/{PageHeader-DlcE3U5L.js → PageHeader-Bw8RNkqR.js} +2 -2
  115. package/dashboard/dist/assets/{PageHeader-DlcE3U5L.js.map → PageHeader-Bw8RNkqR.js.map} +1 -1
  116. package/dashboard/dist/assets/{PageHeaderWithStats-BMhnR3-9.js → PageHeaderWithStats-NR_4idn6.js} +2 -2
  117. package/dashboard/dist/assets/{PageHeaderWithStats-BMhnR3-9.js.map → PageHeaderWithStats-NR_4idn6.js.map} +1 -1
  118. package/dashboard/dist/assets/PersonaDetailPage-DKILoUqL.js +2 -0
  119. package/dashboard/dist/assets/PersonaDetailPage-DKILoUqL.js.map +1 -0
  120. package/dashboard/dist/assets/PersonasPage-qvzHTrFw.js +2 -0
  121. package/dashboard/dist/assets/PersonasPage-qvzHTrFw.js.map +1 -0
  122. package/dashboard/dist/assets/ProcessDetailPage-C3LfeKvi.js +2 -0
  123. package/dashboard/dist/assets/ProcessDetailPage-C3LfeKvi.js.map +1 -0
  124. package/dashboard/dist/assets/{ProcessesListPage-DatKHVkd.js → ProcessesListPage-OoZ_u4ty.js} +2 -2
  125. package/dashboard/dist/assets/{ProcessesListPage-DatKHVkd.js.map → ProcessesListPage-OoZ_u4ty.js.map} +1 -1
  126. package/dashboard/dist/assets/RoleDetailPage-D70jTLZm.js +8 -0
  127. package/dashboard/dist/assets/RoleDetailPage-D70jTLZm.js.map +1 -0
  128. package/dashboard/dist/assets/{RolePill-dzo14hB_.js → RolePill-TySZq7dB.js} +2 -2
  129. package/dashboard/dist/assets/{RolePill-dzo14hB_.js.map → RolePill-TySZq7dB.js.map} +1 -1
  130. package/dashboard/dist/assets/RolesPage-CNueMVuJ.js +2 -0
  131. package/dashboard/dist/assets/RolesPage-CNueMVuJ.js.map +1 -0
  132. package/dashboard/dist/assets/{RunAsSelector-VbBn0o7s.js → RunAsSelector-CwWEpiSF.js} +2 -2
  133. package/dashboard/dist/assets/{RunAsSelector-VbBn0o7s.js.map → RunAsSelector-CwWEpiSF.js.map} +1 -1
  134. package/dashboard/dist/assets/ScopeBadge-C7Uixtmk.js +2 -0
  135. package/dashboard/dist/assets/ScopeBadge-C7Uixtmk.js.map +1 -0
  136. package/dashboard/dist/assets/StatCard-Ca-ngCaD.js +2 -0
  137. package/dashboard/dist/assets/StatCard-Ca-ngCaD.js.map +1 -0
  138. package/dashboard/dist/assets/{StatusBadge-BbqghFMi.js → StatusBadge-BwUvykDo.js} +2 -2
  139. package/dashboard/dist/assets/{StatusBadge-BbqghFMi.js.map → StatusBadge-BwUvykDo.js.map} +1 -1
  140. package/dashboard/dist/assets/{StickyPagination-BI8tDf2V.js → StickyPagination-DvIF3kQK.js} +2 -2
  141. package/dashboard/dist/assets/{StickyPagination-BI8tDf2V.js.map → StickyPagination-DvIF3kQK.js.map} +1 -1
  142. package/dashboard/dist/assets/{StreamMessageDetail-BObbEz7P.js → StreamMessageDetail-DkFK_XGD.js} +2 -2
  143. package/dashboard/dist/assets/StreamMessageDetail-DkFK_XGD.js.map +1 -0
  144. package/dashboard/dist/assets/{SwimlaneTimeline-BHjAtOGC.js → SwimlaneTimeline-CMw-Et6h.js} +2 -2
  145. package/dashboard/dist/assets/{SwimlaneTimeline-BHjAtOGC.js.map → SwimlaneTimeline-CMw-Et6h.js.map} +1 -1
  146. package/dashboard/dist/assets/{TagInput-cyhTZTwe.js → TagInput-D8gSp48D.js} +2 -2
  147. package/dashboard/dist/assets/{TagInput-cyhTZTwe.js.map → TagInput-D8gSp48D.js.map} +1 -1
  148. package/dashboard/dist/assets/{TaskDetailPage-B-E1dqUw.js → TaskDetailPage-BhXuChOf.js} +2 -2
  149. package/dashboard/dist/assets/{TaskDetailPage-B-E1dqUw.js.map → TaskDetailPage-BhXuChOf.js.map} +1 -1
  150. package/dashboard/dist/assets/{TaskQueuePill-_zIpG4bG.js → TaskQueuePill-CHqolBmU.js} +2 -2
  151. package/dashboard/dist/assets/{TaskQueuePill-_zIpG4bG.js.map → TaskQueuePill-CHqolBmU.js.map} +1 -1
  152. package/dashboard/dist/assets/{TasksListPage-urJ4XiUi.js → TasksListPage-6JHQQ5QZ.js} +2 -2
  153. package/dashboard/dist/assets/{TasksListPage-urJ4XiUi.js.map → TasksListPage-6JHQQ5QZ.js.map} +1 -1
  154. package/dashboard/dist/assets/{TimeAgo-D6Dg0SQs.js → TimeAgo-CInx-vzY.js} +2 -2
  155. package/dashboard/dist/assets/{TimeAgo-D6Dg0SQs.js.map → TimeAgo-CInx-vzY.js.map} +1 -1
  156. package/dashboard/dist/assets/{TimestampCell-DG__Gr-e.js → TimestampCell-Fq17Zrsu.js} +2 -2
  157. package/dashboard/dist/assets/{TimestampCell-DG__Gr-e.js.map → TimestampCell-Fq17Zrsu.js.map} +1 -1
  158. package/dashboard/dist/assets/{ToolPill-CKHYG6eV.js → ToolPill-BbgMDhaE.js} +2 -2
  159. package/dashboard/dist/assets/{ToolPill-CKHYG6eV.js.map → ToolPill-BbgMDhaE.js.map} +1 -1
  160. package/dashboard/dist/assets/{ToolTestPanel-D-hGLf95.js → ToolTestPanel-DhjEe59s.js} +2 -2
  161. package/dashboard/dist/assets/{ToolTestPanel-D-hGLf95.js.map → ToolTestPanel-DhjEe59s.js.map} +1 -1
  162. package/dashboard/dist/assets/{TopicDetailPage-B10i4xV2.js → TopicDetailPage-DbIdmQpQ.js} +3 -3
  163. package/dashboard/dist/assets/{TopicDetailPage-B10i4xV2.js.map → TopicDetailPage-DbIdmQpQ.js.map} +1 -1
  164. package/dashboard/dist/assets/TopicsPage-CAP-GUbr.js +2 -0
  165. package/dashboard/dist/assets/{TopicsPage-C5THflVQ.js.map → TopicsPage-CAP-GUbr.js.map} +1 -1
  166. package/dashboard/dist/assets/{UserName-CZTpouta.js → UserName-DggcLkSc.js} +2 -2
  167. package/dashboard/dist/assets/{UserName-CZTpouta.js.map → UserName-DggcLkSc.js.map} +1 -1
  168. package/dashboard/dist/assets/{WorkflowExecutionPage-mbnj6saI.js → WorkflowExecutionPage-Bmra5fVt.js} +2 -2
  169. package/dashboard/dist/assets/{WorkflowExecutionPage-mbnj6saI.js.map → WorkflowExecutionPage-Bmra5fVt.js.map} +1 -1
  170. package/dashboard/dist/assets/{WorkflowPill-DlSVXnnj.js → WorkflowPill-CcUUVugA.js} +2 -2
  171. package/dashboard/dist/assets/{WorkflowPill-DlSVXnnj.js.map → WorkflowPill-CcUUVugA.js.map} +1 -1
  172. package/dashboard/dist/assets/{WorkflowsDashboard-DC_9GrpY.js → WorkflowsDashboard-BQsZAGYU.js} +2 -2
  173. package/dashboard/dist/assets/{WorkflowsDashboard-DC_9GrpY.js.map → WorkflowsDashboard-BQsZAGYU.js.map} +1 -1
  174. package/dashboard/dist/assets/{WorkflowsOverview-ClSH1UwG.js → WorkflowsOverview-CeliraHZ.js} +2 -2
  175. package/dashboard/dist/assets/{WorkflowsOverview-ClSH1UwG.js.map → WorkflowsOverview-CeliraHZ.js.map} +1 -1
  176. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BkgoB7oD.js → YamlWorkflowDetailPage-DGxlonrV.js} +2 -2
  177. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BkgoB7oD.js.map → YamlWorkflowDetailPage-DGxlonrV.js.map} +1 -1
  178. package/dashboard/dist/assets/{YamlWorkflowsPage-Db_REA2f.js → YamlWorkflowsPage-DnT8UiyQ.js} +2 -2
  179. package/dashboard/dist/assets/{YamlWorkflowsPage-Db_REA2f.js.map → YamlWorkflowsPage-DnT8UiyQ.js.map} +1 -1
  180. package/dashboard/dist/assets/{agents-Dvb8j9AB.js → agents-mRV7m4sh.js} +2 -2
  181. package/dashboard/dist/assets/{agents-Dvb8j9AB.js.map → agents-mRV7m4sh.js.map} +1 -1
  182. package/dashboard/dist/assets/{bots-D9jYHjBM.js → bots-SONCZlCM.js} +2 -2
  183. package/dashboard/dist/assets/{bots-D9jYHjBM.js.map → bots-SONCZlCM.js.map} +1 -1
  184. package/dashboard/dist/assets/{capabilities-BAto9JcQ.js → capabilities-DZjCMN32.js} +2 -2
  185. package/dashboard/dist/assets/{capabilities-BAto9JcQ.js.map → capabilities-DZjCMN32.js.map} +1 -1
  186. package/dashboard/dist/assets/{controlplane-2Aic2Tfm.js → controlplane-RQNXjna2.js} +2 -2
  187. package/dashboard/dist/assets/{controlplane-2Aic2Tfm.js.map → controlplane-RQNXjna2.js.map} +1 -1
  188. package/dashboard/dist/assets/{escalation-columns-DPKPJtw3.js → escalation-columns-XLEcZRCg.js} +2 -2
  189. package/dashboard/dist/assets/{escalation-columns-DPKPJtw3.js.map → escalation-columns-XLEcZRCg.js.map} +1 -1
  190. package/dashboard/dist/assets/index-2BwHxjCw.css +1 -0
  191. package/dashboard/dist/assets/{index-BZbDwh_Y.js → index-C6GsrvX1.js} +2 -2
  192. package/dashboard/dist/assets/{index-BZbDwh_Y.js.map → index-C6GsrvX1.js.map} +1 -1
  193. package/dashboard/dist/assets/{index-BzQIzZfd.js → index-CK-6m8e_.js} +2 -2
  194. package/dashboard/dist/assets/{index-BzQIzZfd.js.map → index-CK-6m8e_.js.map} +1 -1
  195. package/dashboard/dist/assets/index-CkeSxuZ0.js +2 -0
  196. package/dashboard/dist/assets/{index-B5JgykZD.js.map → index-CkeSxuZ0.js.map} +1 -1
  197. package/dashboard/dist/assets/{index-BW7-Q9Qf.js → index-CxVGlkK6.js} +2 -2
  198. package/dashboard/dist/assets/{index-BW7-Q9Qf.js.map → index-CxVGlkK6.js.map} +1 -1
  199. package/dashboard/dist/assets/index-D2CfSx_x.js +5 -0
  200. package/dashboard/dist/assets/index-D2CfSx_x.js.map +1 -0
  201. package/dashboard/dist/assets/{index-4zRmxPwA.js → index-DFJF8aWz.js} +3 -3
  202. package/dashboard/dist/assets/{index-4zRmxPwA.js.map → index-DFJF8aWz.js.map} +1 -1
  203. package/dashboard/dist/assets/index-DYKRtstT.js +2 -0
  204. package/dashboard/dist/assets/index-DYKRtstT.js.map +1 -0
  205. package/dashboard/dist/assets/index-DY_hlZCQ.js +2 -0
  206. package/dashboard/dist/assets/index-DY_hlZCQ.js.map +1 -0
  207. package/dashboard/dist/assets/{index-KkikDsJ2.js → index-DbZpL10z.js} +2 -2
  208. package/dashboard/dist/assets/{index-KkikDsJ2.js.map → index-DbZpL10z.js.map} +1 -1
  209. package/dashboard/dist/assets/index-Dh3CVChT.js +63 -0
  210. package/dashboard/dist/assets/index-Dh3CVChT.js.map +1 -0
  211. package/dashboard/dist/assets/{index-peRHL38z.js → index-DqsLfO-0.js} +2 -2
  212. package/dashboard/dist/assets/{index-peRHL38z.js.map → index-DqsLfO-0.js.map} +1 -1
  213. package/dashboard/dist/assets/{index-C-T1Wq0Z.js → index-iHV3d7o3.js} +2 -2
  214. package/dashboard/dist/assets/{index-C-T1Wq0Z.js.map → index-iHV3d7o3.js.map} +1 -1
  215. package/dashboard/dist/assets/{index-CeM012DJ.js → index-ymm58cTW.js} +2 -2
  216. package/dashboard/dist/assets/{index-CeM012DJ.js.map → index-ymm58cTW.js.map} +1 -1
  217. package/dashboard/dist/assets/{knowledge-DO8idX0e.js → knowledge-Bawo8u7l.js} +2 -2
  218. package/dashboard/dist/assets/{knowledge-DO8idX0e.js.map → knowledge-Bawo8u7l.js.map} +1 -1
  219. package/dashboard/dist/assets/{mcp-BGpQlkFp.js → mcp-CKIpbpRZ.js} +2 -2
  220. package/dashboard/dist/assets/{mcp-BGpQlkFp.js.map → mcp-CKIpbpRZ.js.map} +1 -1
  221. package/dashboard/dist/assets/{mcp-query-DT0SCB9l.js → mcp-query-vld4hYxQ.js} +2 -2
  222. package/dashboard/dist/assets/{mcp-query-DT0SCB9l.js.map → mcp-query-vld4hYxQ.js.map} +1 -1
  223. package/dashboard/dist/assets/personas-BsARc3df.js +2 -0
  224. package/dashboard/dist/assets/personas-BsARc3df.js.map +1 -0
  225. package/dashboard/dist/assets/{pipelines-CYk7cN6-.js → pipelines-BTSL-5ko.js} +2 -2
  226. package/dashboard/dist/assets/{pipelines-CYk7cN6-.js.map → pipelines-BTSL-5ko.js.map} +1 -1
  227. package/dashboard/dist/assets/{tasks-B4Y5xbF0.js → tasks-DggQdNbj.js} +2 -2
  228. package/dashboard/dist/assets/{tasks-B4Y5xbF0.js.map → tasks-DggQdNbj.js.map} +1 -1
  229. package/dashboard/dist/assets/{topics-CVnqDw3B.js → topics-DzAKa34X.js} +2 -2
  230. package/dashboard/dist/assets/{topics-CVnqDw3B.js.map → topics-DzAKa34X.js.map} +1 -1
  231. package/dashboard/dist/assets/useEventHooks-5uI9oI5W.js +2 -0
  232. package/dashboard/dist/assets/useEventHooks-5uI9oI5W.js.map +1 -0
  233. package/dashboard/dist/assets/{useNamespace-B1t3hsGf.js → useNamespace-CEKzFIqe.js} +2 -2
  234. package/dashboard/dist/assets/{useNamespace-B1t3hsGf.js.map → useNamespace-CEKzFIqe.js.map} +1 -1
  235. package/dashboard/dist/assets/{useYamlActivityEvents-B8Ru07xQ.js → useYamlActivityEvents-hHgX1Z50.js} +2 -2
  236. package/dashboard/dist/assets/{useYamlActivityEvents-B8Ru07xQ.js.map → useYamlActivityEvents-hHgX1Z50.js.map} +1 -1
  237. package/dashboard/dist/assets/{users-C8H4jjTq.js → users-AO8lUyNr.js} +2 -2
  238. package/dashboard/dist/assets/{users-C8H4jjTq.js.map → users-AO8lUyNr.js.map} +1 -1
  239. package/dashboard/dist/assets/{vendor-icons-BE_WrH2z.js → vendor-icons-DN9yGSuM.js} +134 -129
  240. package/dashboard/dist/assets/vendor-icons-DN9yGSuM.js.map +1 -0
  241. package/dashboard/dist/assets/{workflows-BAdI5k--.js → workflows-PtnlRK09.js} +2 -2
  242. package/dashboard/dist/assets/{workflows-BAdI5k--.js.map → workflows-PtnlRK09.js.map} +1 -1
  243. package/dashboard/dist/assets/{yaml-workflows-Bf2aQS-M.js → yaml-workflows-DPu3Y8vG.js} +2 -2
  244. package/dashboard/dist/assets/{yaml-workflows-Bf2aQS-M.js.map → yaml-workflows-DPu3Y8vG.js.map} +1 -1
  245. package/dashboard/dist/index.html +3 -3
  246. package/docs/api/http/escalations.md +1 -1
  247. package/docs/api/http/personas.md +160 -0
  248. package/docs/api/sdk/escalations.md +2 -2
  249. package/docs/cli.md +12 -0
  250. package/docs/dashboard.md +16 -1
  251. package/docs/design-principles.md +9 -5
  252. package/docs/events.md +4 -2
  253. package/docs/hitl/escalation.md +1 -1
  254. package/docs/hitl/x-lt-list-schema.md +12 -5
  255. package/docs/iam.md +47 -0
  256. package/docs/sdk.md +1 -0
  257. package/package.json +1 -1
  258. package/dashboard/dist/assets/AgentDetailPage-C5AnjpD9.js +0 -4
  259. package/dashboard/dist/assets/AgentDetailPage-C5AnjpD9.js.map +0 -1
  260. package/dashboard/dist/assets/AvailableEscalationsPage-Bk7fFV2e.js.map +0 -1
  261. package/dashboard/dist/assets/CountdownTimer-D-CpxYDO.js +0 -2
  262. package/dashboard/dist/assets/CountdownTimer-D-CpxYDO.js.map +0 -1
  263. package/dashboard/dist/assets/CustomDurationPicker-_KceggR9.js +0 -2
  264. package/dashboard/dist/assets/CustomDurationPicker-_KceggR9.js.map +0 -1
  265. package/dashboard/dist/assets/ElapsedCell-Cflz7Pb5.js +0 -2
  266. package/dashboard/dist/assets/HomePage-NMLaXTvf.js +0 -2
  267. package/dashboard/dist/assets/HomePage-NMLaXTvf.js.map +0 -1
  268. package/dashboard/dist/assets/McpQueryDetailPage-Bqh8GChr.js +0 -5
  269. package/dashboard/dist/assets/McpQueryDetailPage-Bqh8GChr.js.map +0 -1
  270. package/dashboard/dist/assets/McpQueryPage-CqFkBwBR.js +0 -2
  271. package/dashboard/dist/assets/McpQueryPage-CqFkBwBR.js.map +0 -1
  272. package/dashboard/dist/assets/OperatorDashboard-DwbPAPaf.js +0 -2
  273. package/dashboard/dist/assets/OperatorDashboard-DwbPAPaf.js.map +0 -1
  274. package/dashboard/dist/assets/ProcessDetailPage-ChGWcwSp.js +0 -2
  275. package/dashboard/dist/assets/ProcessDetailPage-ChGWcwSp.js.map +0 -1
  276. package/dashboard/dist/assets/RoleDetailPage-GJ_coHsM.js +0 -8
  277. package/dashboard/dist/assets/RoleDetailPage-GJ_coHsM.js.map +0 -1
  278. package/dashboard/dist/assets/RolesPage-CPKw336d.js +0 -2
  279. package/dashboard/dist/assets/RolesPage-CPKw336d.js.map +0 -1
  280. package/dashboard/dist/assets/StatCard-DBANWIss.js +0 -2
  281. package/dashboard/dist/assets/StatCard-DBANWIss.js.map +0 -1
  282. package/dashboard/dist/assets/StreamMessageDetail-BObbEz7P.js.map +0 -1
  283. package/dashboard/dist/assets/TopicsPage-C5THflVQ.js +0 -2
  284. package/dashboard/dist/assets/index-B5JgykZD.js +0 -2
  285. package/dashboard/dist/assets/index-CKxFjMtw.js +0 -63
  286. package/dashboard/dist/assets/index-CKxFjMtw.js.map +0 -1
  287. package/dashboard/dist/assets/index-Pmvw74oY.css +0 -1
  288. package/dashboard/dist/assets/index-_Q1Wf2A8.js +0 -2
  289. package/dashboard/dist/assets/index-_Q1Wf2A8.js.map +0 -1
  290. package/dashboard/dist/assets/index-jkVeGCkD.js +0 -5
  291. package/dashboard/dist/assets/index-jkVeGCkD.js.map +0 -1
  292. package/dashboard/dist/assets/index-oHU-ramT.js +0 -2
  293. package/dashboard/dist/assets/index-oHU-ramT.js.map +0 -1
  294. package/dashboard/dist/assets/useEventHooks-D8bVEx-w.js +0 -2
  295. package/dashboard/dist/assets/useEventHooks-D8bVEx-w.js.map +0 -1
  296. package/dashboard/dist/assets/vendor-icons-BE_WrH2z.js.map +0 -1
@@ -0,0 +1,160 @@
1
+ # Personas API
2
+
3
+ A persona is a named bundle of roles with a per-role **relationship** scope — shorthand for adding a user to each linked role at the linked scope. Assignment fans out to ordinary role memberships (`lt_user_roles` stays the single source of authorization truth); the persona records why the memberships exist. Full semantics — provenance, highest-allowance union, overlay-on-reassign — are in [iam.md](../../iam.md#personas).
4
+
5
+ All endpoints require authentication plus role-management access (`admin` type, `superadmin`, or the `engineer` role) — the same audience that manages users and roles.
6
+
7
+ Relationship values map onto the member scope lattice:
8
+
9
+ | relationship | read_scope | write_scope |
10
+ |--------------|-----------|-------------|
11
+ | `write-all` | `all` | `all` |
12
+ | `write-self` | `all` | `self` |
13
+ | `read-all` | `all` | `none` |
14
+
15
+ `write-none` is accepted anywhere as a synonym for `read-all`.
16
+
17
+ ## List personas
18
+
19
+ ```
20
+ GET /api/personas
21
+ ```
22
+
23
+ **Response 200:**
24
+
25
+ ```json
26
+ {
27
+ "personas": [
28
+ {
29
+ "id": "a1b2c3d4-...",
30
+ "key": "production-manager",
31
+ "title": "Production Manager",
32
+ "description": "Runs the pipeline: works design and review, watches print and the fleet.",
33
+ "roles": [
34
+ { "role": "design", "relationship": "write-all" },
35
+ { "role": "review", "relationship": "write-all" },
36
+ { "role": "print", "relationship": "read-all" }
37
+ ],
38
+ "user_count": 2,
39
+ "created_at": "2026-07-01T08:00:00.000Z",
40
+ "updated_at": "2026-07-01T08:00:00.000Z"
41
+ }
42
+ ]
43
+ }
44
+ ```
45
+
46
+ ## Get a persona
47
+
48
+ ```
49
+ GET /api/personas/:key
50
+ ```
51
+
52
+ **Response 200:** the persona record plus `assignees` — `[{ id, external_id, display_name, email, assigned_at }]`. **404** when the key is unknown.
53
+
54
+ ## Create a persona
55
+
56
+ ```
57
+ POST /api/personas
58
+ ```
59
+
60
+ **Body:**
61
+
62
+ | Field | Type | Description |
63
+ |-------|------|-------------|
64
+ | `key` | `string` | Required. Stable identifier, role-name alphabet (`^[a-z][a-z0-9_-]*$`) |
65
+ | `title` | `string` | Display title |
66
+ | `description` | `string` | The day-in-the-life, one paragraph |
67
+
68
+ **Response 201** with the created record. **409** when the key already exists.
69
+
70
+ ## Update a persona
71
+
72
+ ```
73
+ PATCH /api/personas/:key
74
+ ```
75
+
76
+ PATCH semantics on `title` and `description` — omitted fields keep their values; `null` clears.
77
+
78
+ ## Delete a persona
79
+
80
+ ```
81
+ DELETE /api/personas/:key
82
+ ```
83
+
84
+ Memberships the persona sustains are removed — or re-homed to a sibling persona the user still holds — before the persona row is deleted. Direct grants are never touched.
85
+
86
+ **Response 200:** `{ "deleted": true, "recompute": { "granted": 0, "refreshed": 0, "raised": 0, "removed": 3 } }`
87
+
88
+ ## Link a role
89
+
90
+ ```
91
+ PUT /api/personas/:key/roles/:role
92
+ ```
93
+
94
+ **Body:** `{ "relationship": "write-all" }` — also updates an existing link's relationship. The role is created if absent, and every current holder's memberships are reconciled in the same transaction.
95
+
96
+ **Response 201:** `{ "role": "design", "relationship": "write-all", "recompute": { ... } }`
97
+
98
+ ## Unlink a role
99
+
100
+ ```
101
+ DELETE /api/personas/:key/roles/:role
102
+ ```
103
+
104
+ Removes the link and reconciles every holder. **Response 200:** `{ "unlinked": true, "recompute": { ... } }`
105
+
106
+ ## Seed personas (declarative)
107
+
108
+ ```
109
+ POST /api/personas/seed
110
+ ```
111
+
112
+ **Body:** `{ "personas": [{ "key", "title?", "description?", "roles": [{ "role", "relationship" }] }] }`
113
+
114
+ Idempotent and authoritative per spec: title/description are overlaid, role links are synced (links absent from the spec are pruned), linked roles are ensured as FK targets, and every current holder is reconciled. The SDK twin is `lt.personas.seed(specs)` — declare personas in the same seed pass that declares roles and `default_pins`.
115
+
116
+ **Response 200:** `{ "personas": 2, "links": 6, "recompute": { ... } }`
117
+
118
+ ## Personas for a user
119
+
120
+ ```
121
+ GET /api/users/:id/personas
122
+ ```
123
+
124
+ **Response 200:**
125
+
126
+ ```json
127
+ {
128
+ "personas": [
129
+ { "id": "a1b2c3d4-...", "key": "production-manager", "title": "Production Manager", "description": "...", "roles": [ ... ], "assigned_at": "2026-07-10T12:00:00.000Z" }
130
+ ],
131
+ "roles": [
132
+ { "role": "design", "read_scope": "all", "write_scope": "all", "granted_by_persona": "production-manager" },
133
+ { "role": "review", "read_scope": "all", "write_scope": "all", "granted_by_persona": null }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ `roles` is the composed role/scope map: every membership with the persona sustaining it (`null` = direct grant).
139
+
140
+ ## Assign a persona
141
+
142
+ ```
143
+ POST /api/users/:id/personas
144
+ ```
145
+
146
+ **Body:** `{ "persona": "production-manager" }`
147
+
148
+ Idempotent — re-assigning overlays fresh from the persona's current role links. Highest allowance wins across held personas; a direct grant's scope is only ever raised toward the union, never lowered.
149
+
150
+ **Response 200:** `{ "assigned": true, "recompute": { "granted": 3, "refreshed": 0, "raised": 1, "removed": 0 } }` — `granted` = memberships inserted, `refreshed` = persona-sustained rows overlaid, `raised` = direct rows lifted to the union, `removed` = sustained rows no held persona still grants.
151
+
152
+ ## Unassign a persona
153
+
154
+ ```
155
+ DELETE /api/users/:id/personas/:key
156
+ ```
157
+
158
+ Removes only memberships the persona sustains; rows another held persona still grants are re-homed to it. Direct grants — including a membership added directly on top of a persona grant — are never touched.
159
+
160
+ **Response 200:** `{ "unassigned": true, "recompute": { ... } }`. **404** when the user does not hold the persona.
@@ -362,7 +362,7 @@ Reach for native `condition(signalId, config)` when you want the leanest path; r
362
362
 
363
363
  ### Atomic form (recommended)
364
364
 
365
- Pass an escalation config as the second argument. The escalation row is written inside the workflow's Leg1 checkpoint — one commit, crash-safe: no separate `ltCreateEscalation` activity, no enrich step. `signal_key` is set to `signalId`, so the dashboard resolve endpoint (resolve-by-id → Path 0) and `POST /escalations/resolve-by-signal-key` resume *this* job in place, and `system.escalation.{id}.created` fires automatically.
365
+ Pass an escalation config as the second argument. The escalation row is written inside the workflow's Leg1 checkpoint — one commit, crash-safe: no separate `ltCreateEscalation` activity, no enrich step. `signal_key` is set to `signalId`, so the dashboard resolve endpoint (resolve-by-id → Path 0) and `POST /escalations/resolve-by-signal-key` resume *this* job in place, and `system.escalation.{role}.{id}.created` fires automatically.
366
366
 
367
367
  `conditionLT` returns `T | false | null`:
368
368
  - `T` — the resolver's payload (normal resolution)
@@ -393,7 +393,7 @@ export async function stationWorker(envelope: LTEnvelope) {
393
393
  if (decision === false) {
394
394
  // SLA passed: the workflow resumed on the timer and the engine transitioned
395
395
  // the row pending → expired atomically. A late resolve returns
396
- // already-expired, and system.escalation.{id}.expired fired for dashboards.
396
+ // already-expired, and system.escalation.{role}.{id}.expired fired for dashboards.
397
397
  return { type: 'return' as const, data: { autoRejected: 'sla' } };
398
398
  }
399
399
  if (decision === null) {
package/docs/cli.md CHANGED
@@ -140,6 +140,18 @@ ltc roles save-schema reviewer --file schema.json --summary "Added lotNumber"
140
140
  # Save the escalation form schema (a change creates the next version)
141
141
  ```
142
142
 
143
+ ### Personas
144
+
145
+ Personas bundle roles into one-step assignments — each link carries a relationship scope (`write-all`, `write-self`, `read-all`). See [iam.md](iam.md#personas) for the semantics.
146
+
147
+ ```bash
148
+ ltc personas list # Personas with role and holder counts
149
+ ltc personas get production-manager # Role links + assignees
150
+ ltc personas assign production-manager USER_ID
151
+ ltc personas unassign production-manager USER_ID
152
+ ltc personas for-user USER_ID # Personas held + composed role/scope map
153
+ ```
154
+
143
155
  ### Compiler
144
156
 
145
157
  ```bash
package/docs/dashboard.md CHANGED
@@ -57,6 +57,7 @@ The LLM authoring add-on. Appears when an Anthropic key is configured.
57
57
  |------|-------|---------|
58
58
  | **Accounts** | `/admin/users` | User accounts and service accounts (bots). Create, edit, assign roles, manage API keys. |
59
59
  | **Roles** | `/admin/roles` | Define roles — the queues, forms, and membership that connect workflows to people. Escalation chains, capacity settings, and versioned schemas live here. |
60
+ | **Personas** | `/admin/personas` | Bundle roles into named, one-step assignments. Each linked role carries a relationship scope (write-all, write-self, read-all); assigning a persona composes the member's whole surface from its roles' pins and schemas. |
60
61
 
61
62
  ### Infrastructure
62
63
 
@@ -210,8 +211,9 @@ User Accounts and Service Accounts live on the same page, separated by a tab tog
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
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.
212
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
+ - **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.
213
215
 
214
- **API:** `GET /api/users` lists accounts. `POST /api/users` creates. `PUT /api/users/:id/roles` assigns roles.
216
+ **API:** `GET /api/users` lists accounts. `POST /api/users` creates. `PUT /api/users/:id/roles` assigns roles. `GET/POST /api/users/:id/personas` reads and assigns personas.
215
217
 
216
218
  ### Roles
217
219
 
@@ -276,6 +278,19 @@ Accessible at `/admin/roles/:role/list-schema`. The versioned rich view for the
276
278
 
277
279
  **API:** `GET /api/roles/:role/list-schema` (latest or `?version=`), `GET /api/roles/:role/list-schema/versions`, and `PATCH /api/roles/:role` with `list_schema` (+ optional `change_summary`).
278
280
 
281
+ ### Personas
282
+
283
+ Accessible at `/admin/personas` for admins, superadmins, and engineers — the same audience that manages [Accounts](#accounts) and [Roles](#roles). A persona is a named bundle of roles with a per-role relationship scope: assigning it adds a user to every linked role at the linked scope in one step, and each role's own pins and schemas compose the member's sidebar and forms — the composition ("this human runs the floor, which means these roles") is a first-class, auditable record. Full semantics — provenance, highest-allowance union, overlay-on-reassign — are in [iam.md](iam.md#personas).
284
+
285
+ **Master list** — the working surface. One row per persona: display title, key, description, a preview of the linked role pills, and the holder count; search matches all of them. Select a row to target the **Assignees** panel on the right — assign a user there and they join every linked role in one step, sidebar pins and forms composing from the roles. Unassign from the same panel, or from the account's role panel on [Accounts](#accounts). The row's pencil opens configuration.
286
+
287
+ **Configuration** (`/admin/personas/:key`) —
288
+
289
+ - **Identity** — title and description, PATCH-saved.
290
+ - **Roles** — the bundle's rules. Each link shows the role pill, its scope badge, and a relationship picker (`Write · act on all`, `Write · act on self`, `Read-only observer`); changing a relationship or unlinking reconciles every holder immediately. Link new roles from the role picker.
291
+
292
+ **API:** `GET /api/personas` lists. `POST /api/personas` creates; `PATCH`/`DELETE /api/personas/:key` edit and remove. `PUT`/`DELETE /api/personas/:key/roles/:role` manage links. `POST /api/personas/seed` applies a declarative spec set idempotently.
293
+
279
294
  ### DB Maintenance
280
295
 
281
296
  Database housekeeping tools for keeping PostgreSQL healthy under sustained workflow load.
@@ -207,11 +207,15 @@ Nothing loops, nothing floats.
207
207
  owner, urgency, age — always renders. Enrichment columns (workflow,
208
208
  metadata facets) return only when the table's container has room
209
209
  (`showFrom: '@split' | '@wall'`); below that they fold into card pairs.
210
- The list is a jumping-off spot: the metadata cell carries the refine
211
- icons — filter within the role, search across roles, shift+click to AND
212
- facets the ELK-style drill the whole product surfaces.
213
- 6. **Refine icons are always visible enough to tap** half-opacity at
214
- rest, full on hover. Hover-only affordances do not exist on the floor.
210
+ The list is a jumping-off spot: the ELK-style drill the whole product
211
+ surfaces.
212
+ 6. **Refining is a ROW gesture, never a cell tax.** Cells spend their full
213
+ width on data. One always-visible magnifier per row (or board card)
214
+ opens the refine dialog: the row's metadata-bound facts as full-width
215
+ touch rows, multi-select ANDing facets, with filter-in-role /
216
+ search-everywhere / add-to-filters actions. Per-cell icon pairs are a
217
+ defect — twelve columns × two icons starves every value into an
218
+ ellipsis. Hover-only affordances do not exist on the floor.
215
219
  7. **Disclosure order**: drop priority-3 columns, fold priority-2 into
216
220
  pairs, keep priority-1 always.
217
221
  8. **Touch parity**: every hover-only affordance has a tap equivalent —
package/docs/events.md CHANGED
@@ -71,13 +71,15 @@ System families declare the fields they populate. Which fields exist is a functi
71
71
  |---|---|---|
72
72
  | workflow | `system.workflow.{id}.{started\|completed\|failed}` | `workflowId`, `workflowName`, `taskQueue`, `status` |
73
73
  | task | `system.task.{taskId}.{created\|started\|completed\|escalated\|failed}` | + `taskId` |
74
- | escalation | `system.escalation.{id}.{created\|resolved\|claimed\|released}` | `escalationId` (+ workflow context), `status` |
74
+ | escalation | `system.escalation.{role}.{id}.{created\|resolved\|claimed\|released\|cancelled\|reassigned\|expired}` | `escalationId`, `role` (+ workflow context), `status` |
75
75
  | activity | `system.activity.{wfId}.{activity}.{started\|completed\|failed}` | `activityName` (+ workflow context) |
76
76
  | milestone | `system.milestone.{wfId}` | `milestones` (+ workflow context) |
77
77
  | agent | `system.agent.{name}.{started\|completed\|failed\|…}` | `workflowId`=agentId, `workflowName`=agentName |
78
78
  | knowledge / file | `system.knowledge.{domain}.*` / `system.file.*` | none — payload only |
79
79
 
80
- `status` is a **per-family vocabulary**, not one global enum: workflow `started|in_progress|running|completed|failed`; task `created|in_progress|completed|needs_intervention|failed`; escalation `pending|claimed|released|resolved|cancelled`.
80
+ `status` is a **per-family vocabulary**, not one global enum: workflow `started|in_progress|running|completed|failed`; task `created|in_progress|completed|needs_intervention|failed`; escalation `pending|claimed|released|resolved|cancelled|expired`.
81
+
82
+ Escalation subjects carry the **role** (the queue) as the organizing token. Subscribe to one queue (`system.escalation.{role}.>`), one verb across queues (`system.escalation.*.*.created`), or one item across role hops (`system.escalation.*.{id}.>`). The role token is sanitized to subject-safe characters (`[A-Za-z0-9_-]`); a `reassigned` event publishes under **both** the departing and arriving role so either queue's subscribers observe the move.
81
83
 
82
84
  Consumers (adapters, the agent trigger registry, input_mapping) type against the broad **`LTEvent`** — the base plus every extension as **optional** — since they can't assume any extension is present. Producers (`lib/events/publish.ts`) construct the precise `LT*Event` family types, all assignable to `LTEvent`.
83
85
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## `conditionLT` — Atomic Pattern
4
4
 
5
- Pass an escalation config to `conditionLT`. The escalation row, its metadata, and the resume timer all commit inside the workflow's Leg1 checkpoint — one write, crash-safe. The `signal_key` on the row is the resume key: the dashboard resolve endpoint and `POST /api/escalations/resolve-by-signal-key` both resume this job in place, and the `system.escalation.{id}.created` event fires automatically.
5
+ Pass an escalation config to `conditionLT`. The escalation row, its metadata, and the resume timer all commit inside the workflow's Leg1 checkpoint — one write, crash-safe. The `signal_key` on the row is the resume key: the dashboard resolve endpoint and `POST /api/escalations/resolve-by-signal-key` both resume this job in place, and the `system.escalation.{role}.{id}.created` event fires automatically.
6
6
 
7
7
  ```typescript
8
8
  import { conditionLT } from '@hotmeshio/long-tail';
@@ -1,6 +1,6 @@
1
1
  # List Schema (`x-lt-list-schema`)
2
2
 
3
- The form schema formats one escalation on the detail page. A role can also own a `list_schema` that formats its whole list page — the list-page analog of the resolve form. It is opt-in and applies only when the list is scoped to exactly one role (`/escalations/available?role=<role>`). Absent, the list renders the standard engineer table; present, a rich role-authored view renders with a "Table view" toggle one click away.
3
+ The form schema formats one escalation on the detail page. A role can also own a `list_schema` that formats its whole list page — the list-page analog of the resolve form. It is opt-in and applies only when the list is scoped to exactly one role (`/escalations/available?role=<role>`, and the personal inbox at `/escalations/queue?role=<role>`). Absent, the list renders the standard engineer table; present, a rich role-authored view renders with a "Table view" toggle one click away.
4
4
 
5
5
  The list schema is versioned independently of the form schema — a list edit never bumps the form version. Edit it at `/admin/roles/:role/list-schema`. The list always renders the latest version.
6
6
 
@@ -16,7 +16,7 @@ Every string is a markdown/text template run through the same `{{domain.path}}`
16
16
  | `x-lt-help` | schema | Optional markdown header, interpolated with the active row |
17
17
  | `x-lt-active` | schema | The live item card: `{ title, subtitle?, body?, fields?: [{ label, value }] }` |
18
18
  | `x-lt-history` | schema | History column: `{ row: { title, subtitle?, meta? }, limit?, status? }` |
19
- | `x-lt-columns` | schema | Column definitions for `facet-table` layout: `[{ label, value, format? }]` |
19
+ | `x-lt-columns` | schema | Column definitions for `facet-table` layout: `[{ label, value, format?, priority? }]` |
20
20
  | `x-lt-group-by` | schema | `facet-board`: the `"domain.path"` whose value identifies each entity |
21
21
  | `x-lt-card` | schema | `facet-board`: the per-entity card — `{ title, state?, fields?: [{ label, value, format? }] }` |
22
22
  | `x-lt-row-action` | schema | The per-row action button: `{ action?, label?, durationMinutes? }` — see below |
@@ -39,6 +39,8 @@ Every layout carries a persistent action button — the active card's CTA, a tra
39
39
 
40
40
  `claim` is one click: the row is claimed for the template's duration and the detail page opens already claimed — the fast path for working a queue. The button appears only on claimable rows (pending, no live claim window), and a rejected claim (someone else won the race) surfaces its message inline. `view` opens the detail page — for read-only templates where claiming from the list is wrong. Row and card clicks continue to navigate; the button is the deliberate gesture.
41
41
 
42
+ On My Escalations (`/escalations/queue`) every row is already held by the viewer, so a `claim` template renders as a View action there: the button opens the detail page with the default "View" label. Authored `view` actions keep their label.
43
+
42
44
  ---
43
45
 
44
46
  ## Layouts
@@ -91,7 +93,13 @@ Use when the queue contains many concurrent rows and the role's context is best
91
93
  }
92
94
  ```
93
95
 
94
- A status dot precedes the first column automatically. ISO datetime values render as a readable relative date with a full-timestamp tooltip. Missing token values render as an em dash. Clicking any row navigates to the detail page. `x-lt-help` and `x-lt-active` are ignored in this layout.
96
+ A status dot precedes the first column automatically. ISO datetime values render as a readable relative date with a full-timestamp tooltip. Missing token values render as an em dash. Clicking any row navigates to the detail page. The table stands alone — `x-lt-help` and `x-lt-active` are ignored in this layout; totals live in the pagination bar.
97
+
98
+ The table renders through the same engine as the platform's built-in tables: padded cells, a sticky header, and a card fold at narrow widths — **a table never scrolls horizontally, it folds**. Below the fold threshold each row becomes a console card: `priority: 1` columns form the card's title line, `priority: 2` columns fold into label/value pairs, and `priority: 3` columns are dropped. Undeclared, the first column is the identity and the rest fold — declare priorities when the author knows which columns matter at a glance.
99
+
100
+ The seeded `print` role (ortho pipeline) is the reference example for this layout, including fold priorities.
101
+
102
+ Cells carry data only — the full column width belongs to the value, with the full text on hover. Refining is a **row** gesture: every row with at least one pure metadata binding (`{{metadata.key}}`) carries a magnifier that opens the refine dialog — the row's metadata-bound facts as touch-sized rows, each a toggle. Pick one or several (selections AND into one query) and drill: **Filter <role>** narrows this role's queue, **Search everywhere** spans every role, **Add to filters** merges the selection into the live filter set. A row with a single fact arrives preselected — two taps to drill.
95
103
 
96
104
  ### `"facet-board"` — entity board
97
105
 
@@ -119,7 +127,6 @@ Cards are fully interactive (`x-lt-group-by` should be a `metadata.*` path so th
119
127
 
120
128
  - **Click** opens the group's latest row in the detail view.
121
129
  - **⇧ click** adds the entity's facet to the live filter set — additive, so shift-clicking narrows the board in place and the facet chips row shows each condition with its own remove.
122
- - **Hovering the card footer** reveals the entity's history as the filtered **table** or **timeline** view (the same view modes the queue offers everywhere else).
123
- - **Fields bound to a pure `{{metadata.KEY}}` token** carry the same hover pair the table's metadata cells offer: **filter** (narrows within the current role; ⇧ click adds to the current filters) and **search** (the facet across all roles).
130
+ - **The header magnifier** opens the card's refine dialog the entity identity plus every field bound to a pure `{{metadata.KEY}}` token, as touch-sized toggle rows. Selections AND into one query: **Filter <role>**, **Search everywhere**, or **Add to filters** (merge into the live set). The same row gesture the facet table carries, always visible — no hover required.
124
131
 
125
132
  The reference: `examples/seed-fleet-sim.ts` — one advert per machine, a `format: "age"` "Since" field, and role default pins (see [pinned-views.md](pinned-views.md)).
package/docs/iam.md CHANGED
@@ -41,6 +41,53 @@ Scope makes limited-surface users first-class. A workflow assigns an escalation
41
41
 
42
42
  See the [Roles API](api/http/roles.md#work-surface-scope) for the assignment contract and [roles.md](hitl/roles.md#role-based-routing) in the HITL guide for the workflow-side flow.
43
43
 
44
+ ## Personas
45
+
46
+ A persona is a named bundle of roles with a per-role **relationship** scope — shorthand for "add this user to these roles with these scoped privileges." Assigning a persona performs the equivalent of adding the user to each linked role at the linked scope; because each role carries its own pins, list schema, and form schema, one assignment composes the member's entire dashboard surface. Personas are a suggestion, the same way a `default_pins` entry is: admins can always hand-tune memberships per user through the existing users/roles surfaces, and the persona is the repeatable 95% path.
47
+
48
+ The relationship names a point on the member scope lattice (a persona grant is always `type=member`):
49
+
50
+ | relationship | read_scope | write_scope | Grants |
51
+ |--------------|-----------|-------------|--------|
52
+ | `write-all` | `all` | `all` | Full worker — claim, resolve, submit forms |
53
+ | `write-self` | `all` | `self` | Sees the whole queue, acts only on own assignments |
54
+ | `read-all` | `all` | `none` | Observer — sees the pond, the pins, the counts; cannot act |
55
+
56
+ `write-none` is accepted everywhere as a synonym for `read-all`.
57
+
58
+ ### Membership stays the source of truth
59
+
60
+ Personas are not a second authorization path. Assignment fans out to ordinary `lt_user_roles` rows; every RBAC query reads memberships exactly as before. The persona record explains *why* the memberships exist:
61
+
62
+ - **Provenance.** Each membership carries `granted_by_persona` — the persona sustaining it, or null for a direct grant. Unassigning a persona removes only the rows it sustains. A row a sibling persona still grants is re-homed to that persona instead of being removed. A direct role-add on a persona-sustained row takes the row over (provenance flips to direct), so a later unassign never removes a membership an admin set by hand.
63
+ - **Highest allowance wins.** A user holding several personas (or a direct grant) gets the union per role — the membership row stores the highest scope any grantor supplies. Direct grants are only ever raised toward the persona union, never lowered.
64
+ - **Overlay on re-assign.** Assignment is idempotent: re-assigning a persona reconciles the user's memberships against the persona's *current* role links, so "apply and reapply" is one call. Editing a persona's links (or its link relationships) reconciles every current holder in the same transaction.
65
+ - **Deletion is exact.** Deleting a persona removes the memberships it sustains (re-homing rows a sibling persona still grants) before the persona row goes away; direct grants are untouched.
66
+
67
+ ### Declaring personas
68
+
69
+ Personas are managed three equivalent ways — dashboard (**Admin → Personas**, visible to admins, superadmins, and engineers, the same audience that manages roles and users), API/SDK, and a declarative seed pass that lives in git beside the role declarations:
70
+
71
+ ```typescript
72
+ await lt.personas.seed([
73
+ {
74
+ key: 'production-manager',
75
+ title: 'Production Manager',
76
+ description: 'Runs the pipeline: works design and review, watches print and the fleet.',
77
+ roles: [
78
+ { role: 'design', relationship: 'write-all' },
79
+ { role: 'review', relationship: 'write-all' },
80
+ { role: 'print', relationship: 'read-all' },
81
+ { role: 'fleet-servicer', relationship: 'read-all' },
82
+ ],
83
+ },
84
+ ]);
85
+ ```
86
+
87
+ The seed is idempotent and authoritative per spec: title/description are overlaid, role links are synced (links absent from the spec are pruned), linked roles are ensured as FK targets, and every current holder is reconciled — re-running the seed after editing a spec re-applies it to everyone holding the persona.
88
+
89
+ HTTP surface: `GET/POST /api/personas`, `GET/PATCH/DELETE /api/personas/:key`, `PUT/DELETE /api/personas/:key/roles/:role`, `POST /api/personas/seed`, and per-user `GET/POST /api/users/:id/personas` plus `DELETE /api/users/:id/personas/:key`. `GET /api/users/:id/personas` returns the personas held and the composed role/scope map (each row naming its sustaining persona, or null for a direct grant) — the profile-page view. The same operations exist as `lt.personas.*` in the SDK, `ltc personas` in the CLI, and `*_persona` tools on the `long-tail-admin` MCP server.
90
+
44
91
  ### Enforcement
45
92
 
46
93
  Scope folds into the SQL, so it is atomic with no TOCTOU window. Read scope becomes part of the escalation search query — a member sees a row when `role ∈ allRoles OR (role ∈ selfRoles AND assigned_to = me)`. Write scope folds into the atomic resolve-by-metadata query and gates the by-id claim/resolve/cancel paths. `assigned_to` is indexed, so `self` scope scales to large queues.
package/docs/sdk.md CHANGED
@@ -68,6 +68,7 @@ The client mirrors the REST route structure:
68
68
  | `lt.yamlWorkflows` | `/api/yaml-workflows` | `list`, `get`, `create`, `deploy`, `activate`, `invoke`, `archive` |
69
69
  | `lt.users` | `/api/users` | `list`, `get`, `create`, `update`, `delete`, `getRoles`, `addRole`, `removeRole` |
70
70
  | `lt.roles` | `/api/roles` | `list`, `listWithDetails`, `create`, `delete`, `getEscalationChains` |
71
+ | `lt.personas` | `/api/personas` | `list`, `get`, `create`, `update`, `delete`, `linkRole`, `unlinkRole`, `assign`, `unassign`, `forUser`, `seed` |
71
72
  | `lt.auth` | `/api/auth` | `login` |
72
73
  | `lt.mcp` | `/api/mcp` | `listServers`, `createServer`, `getServer`, `connectServer`, `listTools`, `callTool` |
73
74
  | `lt.pipelines` | `/api/pipelines` | `listEntities`, `listJobs`, `getExecution`, `interrupt` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.10.8",
3
+ "version": "0.10.10",
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",
@@ -1,4 +0,0 @@
1
- import{j as e,a as N}from"./vendor-query-B2UbickB.js";import{a as W,b as K,c as M}from"./agents-Dvb8j9AB.js";import{u as U,j as I,c as O,N as V}from"./index-CKxFjMtw.js";import{u as F,E as _,C as A}from"./CronLabel-KQEj0cDS.js";import{j as H}from"./useEventHooks-D8bVEx-w.js";import{W as b}from"./WorkflowPill-DlSVXnnj.js";import{c as z,B as G,a0 as J,g as X,b2 as Y,T as Q,b3 as Z,R as E,aj as ee,l as se,ar as te,b4 as ae}from"./vendor-icons-BE_WrH2z.js";import{e as ne,a as P}from"./vendor-react-BpdAFEQc.js";function ie(a){return new Date(a).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function u({icon:a,color:n,children:i,actions:o}){return e.jsxs("div",{className:"flex items-center justify-between mb-3 pb-2 border-b border-surface-border",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a,{className:`w-4 h-4 ${n}`,strokeWidth:1.5}),e.jsx("h2",{className:"section-h2",children:i})]}),o]})}function g({text:a}){return e.jsx("p",{className:"text-2xs text-text-quaternary py-2",children:a})}function j({to:a,label:n}){const i=P();return e.jsx("button",{onClick:()=>i(a),className:"text-text-quaternary hover:text-accent transition-colors",title:`View ${n}`,"aria-label":`View ${n}`,children:e.jsx(ae,{className:"w-3.5 h-3.5",strokeWidth:1.5})})}let re=0;function ce(a){const[n,i]=N.useState([]),[o,v]=N.useState(!1),x=N.useCallback(s=>{var d,m,p;if((d=s.type)!=null&&d.startsWith("mesh."))return;const f=s.activityName||((m=s.data)==null?void 0:m.domain)||((p=s.workflowId)==null?void 0:p.slice(0,16))||"";i(h=>[{id:++re,type:s.type,timestamp:s.timestamp,label:f},...h].slice(0,10)),v(!0),setTimeout(()=>v(!1),2e3)},[]);return O(a?`${V}.system.agent.${a}.>`:"",x),{events:n,pulse:o}}function ge(){var w,k,$,S,C;const{id:a}=ne(),n=P(),{data:i}=U(),o=I(),x=(o!==null?o:!!((w=i==null?void 0:i.ai)!=null&&w.enabled))?"Agent":"Automation",{data:s,isLoading:f}=W(a??null),{data:d}=F(a??null),m=K(),p=M(),{events:h,pulse:q}=ce(a);if(H(),f)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-48"}),e.jsx("div",{className:"h-40 bg-surface-sunken rounded"})]});if(!s)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-center",children:[e.jsx(z,{className:"w-12 h-12 text-text-quaternary mb-4",strokeWidth:1}),e.jsxs("h2",{className:"heading-3 mb-2",children:[x," not found"]}),e.jsxs("button",{onClick:()=>n("/agents"),className:"text-sm text-accent hover:text-accent-hover transition-colors",children:["Back to ",x.toLowerCase(),"s"]})]});const T=s.status==="active"?"bg-status-success":s.status==="paused"?"bg-status-warning":s.status==="error"?"bg-status-error":"bg-surface-border",r=(d==null?void 0:d.subscriptions)??[],B=s.status==="active"?"Active":s.status==="paused"?"Paused":s.status==="error"?"Error":"Inactive",c=(k=s.behaviors)==null?void 0:k.schedules,y=($=s.behaviors)==null?void 0:$.cron,l=(c==null?void 0:c.length)||(y?1:0),D=()=>{const t=[`Pause "${s.id}"?`,"","This will:",r.length>0?`• Stop ${r.length} event subscription${r.length!==1?"s":""}`:null,l>0?`• Stop ${l} schedule${l!==1?"s":""}`:null,"","Knowledge and workflow history are preserved. You can reactivate anytime."].filter(Boolean).join(`
2
- `);confirm(t)&&m.mutate({id:s.id,status:"paused"})},L=()=>{const t=[`Delete "${s.id}"?`,"","This permanently removes:","• The agent configuration",r.length>0?`• ${r.length} event subscription${r.length!==1?"s":""}`:null,l>0?`• ${l} schedule${l!==1?"s":""}`:null,"","Knowledge entries and workflow history are preserved."].filter(Boolean).join(`
3
- `);confirm(t)&&p.mutate(s.id,{onSuccess:()=>n("/agents")})};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-start justify-between mb-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("h1",{className:"heading-1",children:[x,": ",s.id]}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:agents.md"},className:"text-text-quaternary hover:text-accent transition-colors mt-1",title:"Docs",children:e.jsx(G,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"flex items-center gap-1.5 mr-2",children:[e.jsx("span",{className:`w-2 h-2 rounded-full dot-ring ${T}`}),e.jsx("span",{className:"text-xs text-text-secondary capitalize",children:B})]}),e.jsxs("button",{onClick:()=>n(`/agents/${s.id}/edit`),className:"flex items-center gap-1.5 px-4 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors",children:[e.jsx(J,{className:"w-3 h-3"})," Edit"]}),s.status!=="active"&&e.jsxs("button",{onClick:()=>m.mutate({id:s.id,status:"active"}),className:"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-status-success hover:bg-status-success/10 transition-colors",children:[e.jsx(X,{className:"w-3 h-3"})," Activate"]}),s.status==="active"&&e.jsxs("button",{onClick:D,className:"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-text-tertiary hover:text-text-primary hover:bg-surface-hover transition-colors",children:[e.jsx(Y,{className:"w-3 h-3"})," Pause"]}),e.jsxs("button",{onClick:L,className:"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-status-error/60 hover:text-status-error hover:bg-status-error/10 transition-colors",children:[e.jsx(Q,{className:"w-3 h-3"})," Delete"]})]})]}),s.description&&e.jsx("div",{className:"border-l-2 border-accent/30 pl-4 py-1 mb-10",children:e.jsx("p",{className:"text-sm text-text-secondary italic leading-relaxed",children:s.description})}),(s.goals||s.rules)&&e.jsxs("div",{className:"mb-10",children:[e.jsx(u,{icon:Z,color:"text-accent",actions:e.jsx(j,{to:`/agents/${s.id}/edit?step=2`,label:"Motivation"}),children:"Motivation"}),e.jsxs("div",{className:"grid grid-cols-2 gap-x-14 bg-surface-sunken/20 rounded-lg px-5 py-4",children:[s.goals&&e.jsxs("div",{children:[e.jsx("p",{className:"text-2xs text-text-quaternary uppercase tracking-widest mb-1.5",children:"Goals"}),e.jsx("p",{className:"text-sm text-text-primary leading-relaxed",children:s.goals})]}),s.rules&&e.jsxs("div",{children:[e.jsx("p",{className:"text-2xs text-text-quaternary uppercase tracking-widest mb-1.5",children:"Rules"}),e.jsx("p",{className:"text-sm text-text-primary leading-relaxed",children:s.rules})]})]})]}),e.jsxs("div",{className:"grid grid-cols-1 @wall:grid-cols-3 gap-x-14 gap-y-10",children:[e.jsxs("div",{children:[e.jsxs(u,{icon:E,color:"text-accent",actions:e.jsx(j,{to:`/agents/${s.id}/edit?step=4`,label:"Subscriptions"}),children:["Subscriptions (",r.length,")"]}),r.length===0?e.jsx(g,{text:"No event subscriptions"}):e.jsx("div",{className:"divide-y divide-surface-border/30",children:r.map(t=>e.jsxs("div",{className:"flex items-center py-2",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx(_,{topic:t.topic})}),e.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[e.jsx("span",{className:"text-text-quaternary text-2xs",children:"→"}),e.jsx(b,{type:t.reaction_type==="capability"?t.tool_name:t.workflow_type||t.reaction_type,variant:t.reaction_type==="pipeline"?"pipeline":t.reaction_type==="capability"?"capability":"durable"})]})]},t.id))})]}),e.jsxs("div",{children:[e.jsxs(u,{icon:ee,color:"text-accent",actions:e.jsx(j,{to:`/agents/${s.id}/edit?step=5`,label:"Schedules"}),children:["Schedules (",l,")"]}),c!=null&&c.length?e.jsx("div",{className:"divide-y divide-surface-border/30",children:c.map((t,R)=>e.jsxs("div",{className:"flex items-center py-2",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx(A,{cron:t.cron})}),e.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[e.jsx("span",{className:"text-text-quaternary text-2xs",children:"→"}),e.jsx(b,{type:t.workflow_type||"workflow"})]})]},R))}):y?e.jsxs("div",{className:"flex items-center py-1",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsx(A,{cron:y})}),s.workflow_type&&e.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[e.jsx("span",{className:"text-text-quaternary text-2xs",children:"→"}),e.jsx(b,{type:s.workflow_type})]})]}):e.jsx(g,{text:"No schedules configured"})]}),e.jsxs("div",{className:"space-y-10",children:[e.jsxs("div",{children:[e.jsx(u,{icon:se,color:"text-accent",actions:e.jsx(j,{to:s.knowledge_domain?`/knowledge?domain=${s.knowledge_domain}`:`/agents/${s.id}/edit?step=3`,label:"Knowledge"}),children:"Knowledge"}),s.knowledge_domain?e.jsxs("button",{onClick:()=>n(`/knowledge?domain=${s.knowledge_domain}`),className:"group text-left flex items-center gap-3",children:[e.jsx("span",{className:"text-sm font-mono text-text-primary group-hover:text-accent transition-colors",children:s.knowledge_domain}),e.jsxs("span",{className:"text-2xs text-text-quaternary",children:[((C=(S=s.stats)==null?void 0:S.knowledge_count)==null?void 0:C.toLocaleString())??0," entries"]}),e.jsx(te,{className:"w-3 h-3 text-accent opacity-0 group-hover:opacity-100 transition-opacity"})]}):e.jsx(g,{text:"No knowledge domain"})]}),e.jsxs("div",{children:[e.jsx(u,{icon:E,color:"text-accent",actions:e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full dot-ring transition-colors duration-500 ${q?"bg-status-success":"bg-surface-border"}`}),e.jsx("span",{className:"text-2xs text-text-quaternary",children:"live"})]}),children:"Activity"}),h.length===0?e.jsx(g,{text:"Events appear here as the agent runs"}):e.jsx("div",{className:"space-y-1.5",children:h.map(t=>e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-0.5",children:[e.jsx("span",{className:"text-2xs text-text-primary font-mono truncate flex-1",children:t.label||"—"}),e.jsx("span",{className:"text-2xs text-text-quaternary shrink-0 ml-2",children:ie(t.timestamp)})]}),e.jsx(_,{topic:t.type})]},t.id))})]})]})]})]})}export{ge as AgentDetailPage};
4
- //# sourceMappingURL=AgentDetailPage-C5AnjpD9.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentDetailPage-C5AnjpD9.js","sources":["../../src/pages/agents/AgentDetailPage.tsx"],"sourcesContent":["import { useState, useCallback } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n Bot, Play, Pause, Trash2, ArrowRight, ArrowUpRight, Pencil, BookOpen,\n Radio, Clock, Brain, Compass,\n} from 'lucide-react';\nimport { useAgent, useUpdateAgent, useDeleteAgent } from '../../api/agents';\nimport { useSettings } from '../../api/settings';\nimport { getAiOverride } from '../../lib/view-as';\nimport { useAgentSubscriptions } from '../../api/agent-subscriptions';\nimport { useAgentEvents } from '../../hooks/useEventHooks';\nimport { useEventSubscription } from '../../hooks/useEventContext';\nimport { NATS_SUBJECT_PREFIX } from '../../lib/nats/config';\nimport { EventTopicPill } from '../../components/common/display/EventTopicPill';\nimport { CronLabel } from '../../components/common/display/CronLabel';\nimport { WorkflowPill } from '../../components/common/display/WorkflowPill';\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n}\n\nfunction SectionHeader({ icon: Icon, color, children, actions }: { icon: React.ElementType; color: string; children: React.ReactNode; actions?: React.ReactNode }) {\n return (\n <div className=\"flex items-center justify-between mb-3 pb-2 border-b border-surface-border\">\n <div className=\"flex items-center gap-2\">\n <Icon className={`w-4 h-4 ${color}`} strokeWidth={1.5} />\n <h2 className=\"section-h2\">{children}</h2>\n </div>\n {actions}\n </div>\n );\n}\n\nfunction EmptyHint({ text }: { text: string }) {\n return <p className=\"text-2xs text-text-quaternary py-2\">{text}</p>;\n}\n\n/** Per-section deeplink — jumps straight to that section instead of Edit → navigate. */\nfunction SectionViewLink({ to, label }: { to: string; label: string }) {\n const navigate = useNavigate();\n return (\n <button\n onClick={() => navigate(to)}\n className=\"text-text-quaternary hover:text-accent transition-colors\"\n title={`View ${label}`}\n aria-label={`View ${label}`}\n >\n <ArrowUpRight className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n </button>\n );\n}\n\n// ── Live feed ───────────────────────────────────────────────────────────────\n\ninterface FeedEvent { id: number; type: string; timestamp: string; label: string; }\nlet feedCounter = 0;\n\nfunction useAgentFeed(agentName?: string) {\n const [events, setEvents] = useState<FeedEvent[]>([]);\n const [pulse, setPulse] = useState(false);\n const handler = useCallback((event: any) => {\n if (event.type?.startsWith('mesh.')) return;\n const label = event.activityName || event.data?.domain || event.workflowId?.slice(0, 16) || '';\n setEvents((prev) => [{ id: ++feedCounter, type: event.type, timestamp: event.timestamp, label }, ...prev].slice(0, 10));\n setPulse(true);\n setTimeout(() => setPulse(false), 2000);\n }, []);\n useEventSubscription(\n agentName ? `${NATS_SUBJECT_PREFIX}.system.agent.${agentName}.>` : '',\n handler,\n );\n return { events, pulse };\n}\n\n// ── Page ─────────────────────────────────────────────────────────────────────\n\nexport function AgentDetailPage() {\n const { id } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const { data: settings } = useSettings();\n const aiOverride = getAiOverride();\n const aiEnabled = aiOverride !== null ? aiOverride : !!settings?.ai?.enabled;\n const label = aiEnabled ? 'Agent' : 'Automation';\n const { data: agent, isLoading } = useAgent(id ?? null);\n const { data: subsData } = useAgentSubscriptions(id ?? null);\n const updateMutation = useUpdateAgent();\n const deleteMutation = useDeleteAgent();\n const { events: liveEvents, pulse } = useAgentFeed(id);\n useAgentEvents();\n\n if (isLoading) {\n return <div className=\"animate-pulse space-y-4\"><div className=\"h-8 bg-surface-sunken rounded w-48\" /><div className=\"h-40 bg-surface-sunken rounded\" /></div>;\n }\n\n if (!agent) {\n return (\n <div className=\"flex flex-col items-center justify-center py-20 text-center\">\n <Bot className=\"w-12 h-12 text-text-quaternary mb-4\" strokeWidth={1} />\n <h2 className=\"heading-3 mb-2\">{label} not found</h2>\n <button onClick={() => navigate('/agents')} className=\"text-sm text-accent hover:text-accent-hover transition-colors\">Back to {label.toLowerCase()}s</button>\n </div>\n );\n }\n\n const statusDot = agent.status === 'active' ? 'bg-status-success' : agent.status === 'paused' ? 'bg-status-warning' : agent.status === 'error' ? 'bg-status-error' : 'bg-surface-border';\n const subs = subsData?.subscriptions ?? [];\n const statusLabel = agent.status === 'active' ? 'Active' : agent.status === 'paused' ? 'Paused' : agent.status === 'error' ? 'Error' : 'Inactive';\n const schedules = (agent.behaviors as any)?.schedules as any[] | undefined;\n const legacyCron = agent.behaviors?.cron;\n const schedCount = schedules?.length || (legacyCron ? 1 : 0);\n\n const handlePause = () => {\n const msg = [\n `Pause \"${agent.id}\"?`,\n '',\n 'This will:',\n subs.length > 0 ? `• Stop ${subs.length} event subscription${subs.length !== 1 ? 's' : ''}` : null,\n schedCount > 0 ? `• Stop ${schedCount} schedule${schedCount !== 1 ? 's' : ''}` : null,\n '',\n 'Knowledge and workflow history are preserved. You can reactivate anytime.',\n ].filter(Boolean).join('\\n');\n if (confirm(msg)) updateMutation.mutate({ id: agent.id, status: 'paused' as any });\n };\n\n const handleDelete = () => {\n const msg = [\n `Delete \"${agent.id}\"?`,\n '',\n 'This permanently removes:',\n '• The agent configuration',\n subs.length > 0 ? `• ${subs.length} event subscription${subs.length !== 1 ? 's' : ''}` : null,\n schedCount > 0 ? `• ${schedCount} schedule${schedCount !== 1 ? 's' : ''}` : null,\n '',\n 'Knowledge entries and workflow history are preserved.',\n ].filter(Boolean).join('\\n');\n if (confirm(msg)) deleteMutation.mutate(agent.id, { onSuccess: () => navigate('/agents') });\n };\n\n return (\n <div>\n {/* ── Hero ──────────────────────────────────────────────────────────── */}\n <div className=\"flex items-start justify-between mb-3\">\n <div className=\"flex items-center gap-2\">\n <h1 className=\"heading-1\">{label}: {agent.id}</h1>\n <button onClick={() => { window.location.hash = '#docs:agents.md'; }} className=\"text-text-quaternary hover:text-accent transition-colors mt-1\" title=\"Docs\">\n <BookOpen className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center gap-1.5 mr-2\">\n <span className={`w-2 h-2 rounded-full dot-ring ${statusDot}`} />\n <span className=\"text-xs text-text-secondary capitalize\">{statusLabel}</span>\n </div>\n <button onClick={() => navigate(`/agents/${agent.id}/edit`)} className=\"flex items-center gap-1.5 px-4 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors\">\n <Pencil className=\"w-3 h-3\" /> Edit\n </button>\n {agent.status !== 'active' && (\n <button onClick={() => updateMutation.mutate({ id: agent.id, status: 'active' as any })} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-status-success hover:bg-status-success/10 transition-colors\">\n <Play className=\"w-3 h-3\" /> Activate\n </button>\n )}\n {agent.status === 'active' && (\n <button onClick={handlePause} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-text-tertiary hover:text-text-primary hover:bg-surface-hover transition-colors\">\n <Pause className=\"w-3 h-3\" /> Pause\n </button>\n )}\n <button onClick={handleDelete} className=\"flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-md text-status-error/60 hover:text-status-error hover:bg-status-error/10 transition-colors\">\n <Trash2 className=\"w-3 h-3\" /> Delete\n </button>\n </div>\n </div>\n\n {/* Description callout */}\n {agent.description && (\n <div className=\"border-l-2 border-accent/30 pl-4 py-1 mb-10\">\n <p className=\"text-sm text-text-secondary italic leading-relaxed\">{agent.description}</p>\n </div>\n )}\n\n {/* Motivation */}\n {(agent.goals || agent.rules) && (\n <div className=\"mb-10\">\n <SectionHeader\n icon={Compass}\n color=\"text-accent\"\n actions={<SectionViewLink to={`/agents/${agent.id}/edit?step=2`} label=\"Motivation\" />}\n >Motivation</SectionHeader>\n <div className=\"grid grid-cols-2 gap-x-14 bg-surface-sunken/20 rounded-lg px-5 py-4\">\n {agent.goals && (\n <div>\n <p className=\"text-2xs text-text-quaternary uppercase tracking-widest mb-1.5\">Goals</p>\n <p className=\"text-sm text-text-primary leading-relaxed\">{agent.goals}</p>\n </div>\n )}\n {agent.rules && (\n <div>\n <p className=\"text-2xs text-text-quaternary uppercase tracking-widest mb-1.5\">Rules</p>\n <p className=\"text-sm text-text-primary leading-relaxed\">{agent.rules}</p>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* ── 3-column grid ─────────────────────────────────────────────────── */}\n <div className=\"grid grid-cols-1 @wall:grid-cols-3 gap-x-14 gap-y-10\">\n\n {/* Col 1: Subscriptions */}\n <div>\n <SectionHeader\n icon={Radio}\n color=\"text-accent\"\n actions={<SectionViewLink to={`/agents/${agent.id}/edit?step=4`} label=\"Subscriptions\" />}\n >\n Subscriptions ({subs.length})\n </SectionHeader>\n {subs.length === 0 ? (\n <EmptyHint text=\"No event subscriptions\" />\n ) : (\n <div className=\"divide-y divide-surface-border/30\">\n {subs.map((sub: any) => (\n <div key={sub.id} className=\"flex items-center py-2\">\n <div className=\"flex-1 min-w-0\"><EventTopicPill topic={sub.topic} /></div>\n <div className=\"flex items-center gap-1.5 shrink-0\">\n <span className=\"text-text-quaternary text-2xs\">→</span>\n <WorkflowPill\n type={sub.reaction_type === 'capability' ? sub.tool_name : sub.workflow_type || sub.reaction_type}\n variant={sub.reaction_type === 'pipeline' ? 'pipeline' : sub.reaction_type === 'capability' ? 'capability' : 'durable'}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Col 2: Schedules */}\n <div>\n <SectionHeader\n icon={Clock}\n color=\"text-accent\"\n actions={<SectionViewLink to={`/agents/${agent.id}/edit?step=5`} label=\"Schedules\" />}\n >Schedules ({schedCount})</SectionHeader>\n {schedules?.length ? (\n <div className=\"divide-y divide-surface-border/30\">\n {schedules.map((s: any, i: number) => (\n <div key={i} className=\"flex items-center py-2\">\n <div className=\"flex-1 min-w-0\"><CronLabel cron={s.cron} /></div>\n <div className=\"flex items-center gap-1.5 shrink-0\"><span className=\"text-text-quaternary text-2xs\">→</span><WorkflowPill type={s.workflow_type || 'workflow'} /></div>\n </div>\n ))}\n </div>\n ) : legacyCron ? (\n <div className=\"flex items-center py-1\">\n <div className=\"flex-1 min-w-0\"><CronLabel cron={legacyCron} /></div>\n {agent.workflow_type && <div className=\"flex items-center gap-1.5 shrink-0\"><span className=\"text-text-quaternary text-2xs\">→</span><WorkflowPill type={agent.workflow_type} /></div>}\n </div>\n ) : (\n <EmptyHint text=\"No schedules configured\" />\n )}\n </div>\n\n {/* Col 3: Knowledge + Activity */}\n <div className=\"space-y-10\">\n <div>\n <SectionHeader\n icon={Brain}\n color=\"text-accent\"\n actions={\n <SectionViewLink\n to={agent.knowledge_domain ? `/knowledge?domain=${agent.knowledge_domain}` : `/agents/${agent.id}/edit?step=3`}\n label=\"Knowledge\"\n />\n }\n >Knowledge</SectionHeader>\n {agent.knowledge_domain ? (\n <button onClick={() => navigate(`/knowledge?domain=${agent.knowledge_domain}`)} className=\"group text-left flex items-center gap-3\">\n <span className=\"text-sm font-mono text-text-primary group-hover:text-accent transition-colors\">{agent.knowledge_domain}</span>\n <span className=\"text-2xs text-text-quaternary\">{agent.stats?.knowledge_count?.toLocaleString() ?? 0} entries</span>\n <ArrowRight className=\"w-3 h-3 text-accent opacity-0 group-hover:opacity-100 transition-opacity\" />\n </button>\n ) : (\n <EmptyHint text=\"No knowledge domain\" />\n )}\n </div>\n\n <div>\n <SectionHeader icon={Radio} color=\"text-accent\"\n actions={\n <div className=\"flex items-center gap-1.5\">\n <span className={`w-1.5 h-1.5 rounded-full dot-ring transition-colors duration-500 ${pulse ? 'bg-status-success' : 'bg-surface-border'}`} />\n <span className=\"text-2xs text-text-quaternary\">live</span>\n </div>\n }\n >\n Activity\n </SectionHeader>\n {liveEvents.length === 0 ? (\n <EmptyHint text=\"Events appear here as the agent runs\" />\n ) : (\n <div className=\"space-y-1.5\">\n {liveEvents.map((ev) => (\n <div key={ev.id}>\n <div className=\"flex items-center justify-between mb-0.5\">\n <span className=\"text-2xs text-text-primary font-mono truncate flex-1\">{ev.label || '—'}</span>\n <span className=\"text-2xs text-text-quaternary shrink-0 ml-2\">{formatTime(ev.timestamp)}</span>\n </div>\n <EventTopicPill topic={ev.type} />\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["formatTime","iso","SectionHeader","Icon","color","children","actions","jsxs","jsx","EmptyHint","text","SectionViewLink","to","label","navigate","useNavigate","ArrowUpRight","feedCounter","useAgentFeed","agentName","events","setEvents","useState","pulse","setPulse","handler","useCallback","event","_a","_b","_c","prev","useEventSubscription","NATS_SUBJECT_PREFIX","AgentDetailPage","id","useParams","settings","useSettings","aiOverride","getAiOverride","agent","isLoading","useAgent","subsData","useAgentSubscriptions","updateMutation","useUpdateAgent","deleteMutation","useDeleteAgent","liveEvents","useAgentEvents","Bot","statusDot","subs","statusLabel","schedules","legacyCron","schedCount","handlePause","msg","handleDelete","BookOpen","Pencil","Play","Pause","Trash2","Compass","Radio","sub","EventTopicPill","WorkflowPill","Clock","s","i","CronLabel","Brain","_e","_d","ArrowRight","ev"],"mappings":"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"}