@solidxai/core-ui 0.1.19 → 0.1.20-beta.1

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 (282) hide show
  1. package/dist/components/common/Link.d.ts.map +1 -1
  2. package/dist/components/common/Link.js +2 -1
  3. package/dist/components/common/Link.js.map +1 -1
  4. package/dist/components/common/Link.tsx +2 -1
  5. package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.d.ts +1 -0
  6. package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.d.ts.map +1 -1
  7. package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js +109 -23
  8. package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js.map +1 -1
  9. package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.tsx +155 -34
  10. package/dist/components/core/chatter/SolidChatter.js +2 -2
  11. package/dist/components/core/chatter/SolidChatter.js.map +1 -1
  12. package/dist/components/core/chatter/SolidChatter.tsx +2 -2
  13. package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.js +20 -19
  14. package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.js.map +1 -1
  15. package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.tsx +16 -16
  16. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.d.ts.map +1 -1
  17. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js +3 -10
  18. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js.map +1 -1
  19. package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.tsx +3 -8
  20. package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.d.ts.map +1 -1
  21. package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.js +36 -9
  22. package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.js.map +1 -1
  23. package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.tsx +78 -7
  24. package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.d.ts +1 -0
  25. package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.d.ts.map +1 -1
  26. package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.js +1 -1
  27. package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.js.map +1 -1
  28. package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.tsx +1 -1
  29. package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.d.ts +4 -0
  30. package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.d.ts.map +1 -0
  31. package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.js +131 -0
  32. package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.js.map +1 -0
  33. package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.tsx +151 -0
  34. package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.d.ts +4 -0
  35. package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.d.ts.map +1 -0
  36. package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.js +13 -0
  37. package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.js.map +1 -0
  38. package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.tsx +20 -0
  39. package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
  40. package/dist/components/core/form/SolidFormView.js +4 -0
  41. package/dist/components/core/form/SolidFormView.js.map +1 -1
  42. package/dist/components/core/form/SolidFormView.tsx +4 -0
  43. package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
  44. package/dist/components/core/kanban/SolidKanbanView.js +50 -15
  45. package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
  46. package/dist/components/core/kanban/SolidKanbanView.tsx +22 -3
  47. package/dist/components/core/list/SolidListView.d.ts.map +1 -1
  48. package/dist/components/core/list/SolidListView.js +16 -3
  49. package/dist/components/core/list/SolidListView.js.map +1 -1
  50. package/dist/components/core/list/SolidListView.tsx +16 -2
  51. package/dist/components/core/list/columns/SolidMediaMultipleColumn.d.ts.map +1 -1
  52. package/dist/components/core/list/columns/SolidMediaMultipleColumn.js +4 -1
  53. package/dist/components/core/list/columns/SolidMediaMultipleColumn.js.map +1 -1
  54. package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +4 -1
  55. package/dist/components/core/module/ModulePackageDialog.css +102 -0
  56. package/dist/components/core/module/ModulePackageDialog.d.ts +2 -1
  57. package/dist/components/core/module/ModulePackageDialog.d.ts.map +1 -1
  58. package/dist/components/core/module/ModulePackageDialog.js +216 -68
  59. package/dist/components/core/module/ModulePackageDialog.js.map +1 -1
  60. package/dist/components/core/module/ModulePackageDialog.tsx +356 -76
  61. package/dist/components/core/solid-agent/SolidAgentChat.d.ts.map +1 -1
  62. package/dist/components/core/solid-agent/SolidAgentChat.js +9 -3
  63. package/dist/components/core/solid-agent/SolidAgentChat.js.map +1 -1
  64. package/dist/components/core/solid-agent/SolidAgentChat.tsx +9 -4
  65. package/dist/components/core/solid-agent/SolidAgentMarkdown.d.ts.map +1 -1
  66. package/dist/components/core/solid-agent/SolidAgentMarkdown.js +25 -6
  67. package/dist/components/core/solid-agent/SolidAgentMarkdown.js.map +1 -1
  68. package/dist/components/core/solid-agent/SolidAgentMarkdown.tsx +15 -1
  69. package/dist/components/core/solid-agent/client/agentRuntime.d.ts +5 -0
  70. package/dist/components/core/solid-agent/client/agentRuntime.d.ts.map +1 -1
  71. package/dist/components/core/solid-agent/client/agentRuntime.js +77 -20
  72. package/dist/components/core/solid-agent/client/agentRuntime.js.map +1 -1
  73. package/dist/components/core/solid-agent/client/agentRuntime.ts +29 -1
  74. package/dist/components/core/solid-agent/client/agentSocket.d.ts +5 -1
  75. package/dist/components/core/solid-agent/client/agentSocket.d.ts.map +1 -1
  76. package/dist/components/core/solid-agent/client/agentSocket.js +27 -4
  77. package/dist/components/core/solid-agent/client/agentSocket.js.map +1 -1
  78. package/dist/components/core/solid-agent/client/agentSocket.ts +14 -3
  79. package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.js +2 -2
  80. package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.js.map +1 -1
  81. package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.tsx +5 -5
  82. package/dist/components/core/solid-agent/embed/agentEmbedProtocol.d.ts +2 -0
  83. package/dist/components/core/solid-agent/embed/agentEmbedProtocol.d.ts.map +1 -1
  84. package/dist/components/core/solid-agent/embed/agentEmbedProtocol.js +2 -2
  85. package/dist/components/core/solid-agent/embed/agentEmbedProtocol.js.map +1 -1
  86. package/dist/components/core/solid-agent/embed/agentEmbedProtocol.ts +4 -4
  87. package/dist/components/core/solid-agent/thread/AgentThread.d.ts.map +1 -1
  88. package/dist/components/core/solid-agent/thread/AgentThread.js +61 -26
  89. package/dist/components/core/solid-agent/thread/AgentThread.js.map +1 -1
  90. package/dist/components/core/solid-agent/thread/AgentThread.tsx +74 -40
  91. package/dist/components/core/solid-agent/thread/SolidAgentChatItem.d.ts +2 -1
  92. package/dist/components/core/solid-agent/thread/SolidAgentChatItem.d.ts.map +1 -1
  93. package/dist/components/core/solid-agent/thread/SolidAgentChatItem.js +2 -1
  94. package/dist/components/core/solid-agent/thread/SolidAgentChatItem.js.map +1 -1
  95. package/dist/components/core/solid-agent/thread/SolidAgentChatItem.tsx +3 -1
  96. package/dist/components/core/solid-agent/types.d.ts +3 -0
  97. package/dist/components/core/solid-agent/types.d.ts.map +1 -1
  98. package/dist/components/core/solid-agent/types.js +0 -9
  99. package/dist/components/core/solid-agent/types.js.map +1 -1
  100. package/dist/components/core/solid-agent/types.ts +4 -2
  101. package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.d.ts +1 -1
  102. package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.d.ts.map +1 -1
  103. package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.js +5 -2
  104. package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.js.map +1 -1
  105. package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.tsx +11 -5
  106. package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.js +3 -0
  107. package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.js.map +1 -1
  108. package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.tsx +4 -0
  109. package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.js +3 -0
  110. package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.js.map +1 -1
  111. package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.tsx +4 -0
  112. package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.js +3 -0
  113. package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.js.map +1 -1
  114. package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.tsx +4 -0
  115. package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.js +3 -0
  116. package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.js.map +1 -1
  117. package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.tsx +4 -0
  118. package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.js +3 -0
  119. package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.js.map +1 -1
  120. package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.tsx +4 -0
  121. package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.js +3 -0
  122. package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.js.map +1 -1
  123. package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.tsx +4 -0
  124. package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.js +3 -0
  125. package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.js.map +1 -1
  126. package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.tsx +4 -0
  127. package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.js +3 -0
  128. package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.js.map +1 -1
  129. package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.tsx +4 -0
  130. package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.js +3 -0
  131. package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.js.map +1 -1
  132. package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.tsx +4 -0
  133. package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.js +19 -0
  134. package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.js.map +1 -1
  135. package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.tsx +20 -0
  136. package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.js +3 -0
  137. package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.js.map +1 -1
  138. package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.tsx +4 -0
  139. package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.js +3 -0
  140. package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.js.map +1 -1
  141. package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.tsx +4 -0
  142. package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.js +3 -0
  143. package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.js.map +1 -1
  144. package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.tsx +4 -0
  145. package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.js +3 -0
  146. package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.js.map +1 -1
  147. package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.tsx +4 -0
  148. package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.js +3 -0
  149. package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.js.map +1 -1
  150. package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.tsx +4 -0
  151. package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.js +3 -0
  152. package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.js.map +1 -1
  153. package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.tsx +4 -0
  154. package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.js +3 -0
  155. package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.js.map +1 -1
  156. package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.tsx +4 -0
  157. package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.js +3 -0
  158. package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.js.map +1 -1
  159. package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.tsx +4 -0
  160. package/dist/components/core/solid-agent/widgets/solidChatWidgets.module.css +9 -1
  161. package/dist/components/core/users/CreateUser.d.ts.map +1 -1
  162. package/dist/components/core/users/CreateUser.js +23 -8
  163. package/dist/components/core/users/CreateUser.js.map +1 -1
  164. package/dist/components/core/users/CreateUser.tsx +10 -6
  165. package/dist/components/layout/AdminHeaderActions.d.ts.map +1 -1
  166. package/dist/components/layout/AdminHeaderActions.js +1 -29
  167. package/dist/components/layout/AdminHeaderActions.js.map +1 -1
  168. package/dist/components/layout/AdminHeaderActions.tsx +0 -42
  169. package/dist/components/layout/AdminTopHeader.js +2 -2
  170. package/dist/components/layout/AdminTopHeader.js.map +1 -1
  171. package/dist/components/layout/AdminTopHeader.tsx +2 -2
  172. package/dist/components/layout/AppSidebar.d.ts.map +1 -1
  173. package/dist/components/layout/AppSidebar.js +21 -5
  174. package/dist/components/layout/AppSidebar.js.map +1 -1
  175. package/dist/components/layout/AppSidebar.tsx +24 -6
  176. package/dist/components/layout/SolidAiStudioLayout.d.ts +0 -1
  177. package/dist/components/layout/SolidAiStudioLayout.d.ts.map +1 -1
  178. package/dist/components/layout/SolidAiStudioLayout.js +8 -161
  179. package/dist/components/layout/SolidAiStudioLayout.js.map +1 -1
  180. package/dist/components/layout/SolidAiStudioLayout.tsx +6 -136
  181. package/dist/components/layout/user-profile-menu.js +10 -10
  182. package/dist/components/layout/user-profile-menu.js.map +1 -1
  183. package/dist/components/layout/user-profile-menu.tsx +3 -3
  184. package/dist/components/shad-cn-ui/SolidLightbox.d.ts +2 -1
  185. package/dist/components/shad-cn-ui/SolidLightbox.d.ts.map +1 -1
  186. package/dist/components/shad-cn-ui/SolidLightbox.js +11 -4
  187. package/dist/components/shad-cn-ui/SolidLightbox.js.map +1 -1
  188. package/dist/components/shad-cn-ui/SolidLightbox.tsx +14 -1
  189. package/dist/helpers/modelViewPersistence.d.ts +2 -0
  190. package/dist/helpers/modelViewPersistence.d.ts.map +1 -1
  191. package/dist/helpers/modelViewPersistence.js +72 -0
  192. package/dist/helpers/modelViewPersistence.js.map +1 -1
  193. package/dist/helpers/modelViewPersistence.ts +79 -0
  194. package/dist/helpers/registry.d.ts +6 -2
  195. package/dist/helpers/registry.d.ts.map +1 -1
  196. package/dist/helpers/registry.js +68 -3
  197. package/dist/helpers/registry.js.map +1 -1
  198. package/dist/helpers/registry.ts +62 -4
  199. package/dist/hooks/useModelsDevModels.d.ts +43 -0
  200. package/dist/hooks/useModelsDevModels.d.ts.map +1 -0
  201. package/dist/hooks/useModelsDevModels.js +81 -0
  202. package/dist/hooks/useModelsDevModels.js.map +1 -0
  203. package/dist/hooks/useModelsDevModels.ts +106 -0
  204. package/dist/hooks/useRouter.d.ts.map +1 -1
  205. package/dist/hooks/useRouter.js +3 -2
  206. package/dist/hooks/useRouter.js.map +1 -1
  207. package/dist/hooks/useRouter.ts +3 -2
  208. package/dist/index.d.ts +2 -2
  209. package/dist/index.d.ts.map +1 -1
  210. package/dist/index.js +1 -1
  211. package/dist/index.js.map +1 -1
  212. package/dist/index.ts +4 -1
  213. package/dist/modules/solidUiModule.d.ts +3 -2
  214. package/dist/modules/solidUiModule.d.ts.map +1 -1
  215. package/dist/modules/solidUiModule.js +1 -1
  216. package/dist/modules/solidUiModule.js.map +1 -1
  217. package/dist/modules/solidUiModule.ts +5 -1
  218. package/dist/redux/api/moduleApi.d.ts +12 -2
  219. package/dist/redux/api/moduleApi.d.ts.map +1 -1
  220. package/dist/redux/api/moduleApi.js +33 -3
  221. package/dist/redux/api/moduleApi.js.map +1 -1
  222. package/dist/redux/api/moduleApi.ts +17 -2
  223. package/dist/redux/api/solidChatterMessageApi.d.ts +3 -1
  224. package/dist/redux/api/solidChatterMessageApi.d.ts.map +1 -1
  225. package/dist/redux/api/solidChatterMessageApi.js +9 -1
  226. package/dist/redux/api/solidChatterMessageApi.js.map +1 -1
  227. package/dist/redux/api/solidChatterMessageApi.ts +9 -1
  228. package/dist/redux/store/defaultStoreConfig.d.ts +9 -1
  229. package/dist/redux/store/defaultStoreConfig.d.ts.map +1 -1
  230. package/dist/resources/globals.css +30 -0
  231. package/dist/resources/solid-custom.css +10 -6
  232. package/dist/resources/solid-tailwind-generated.css +1 -1
  233. package/dist/routes/AppEventListener.d.ts.map +1 -1
  234. package/dist/routes/AppEventListener.js +3 -3
  235. package/dist/routes/AppEventListener.js.map +1 -1
  236. package/dist/routes/AppEventListener.tsx +2 -3
  237. package/dist/routes/pages/admin/core/AgentHubTagsField.css +21 -0
  238. package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts +17 -0
  239. package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts.map +1 -0
  240. package/dist/routes/pages/admin/core/AgentHubTagsField.js +171 -0
  241. package/dist/routes/pages/admin/core/AgentHubTagsField.js.map +1 -0
  242. package/dist/routes/pages/admin/core/AgentHubTagsField.tsx +125 -0
  243. package/dist/routes/pages/admin/core/AgentPersonaHistory.css +130 -0
  244. package/dist/routes/pages/admin/core/AgentPersonaHistory.d.ts +7 -0
  245. package/dist/routes/pages/admin/core/AgentPersonaHistory.d.ts.map +1 -0
  246. package/dist/routes/pages/admin/core/AgentPersonaHistory.js +228 -0
  247. package/dist/routes/pages/admin/core/AgentPersonaHistory.js.map +1 -0
  248. package/dist/routes/pages/admin/core/AgentPersonaHistory.tsx +234 -0
  249. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.css +13 -14
  250. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.d.ts.map +1 -1
  251. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js +218 -165
  252. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js.map +1 -1
  253. package/dist/routes/pages/admin/core/AgentRegistryEditorPage.tsx +221 -127
  254. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.d.ts.map +1 -1
  255. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js +14 -69
  256. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js.map +1 -1
  257. package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx +15 -83
  258. package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts +11 -0
  259. package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts.map +1 -0
  260. package/dist/routes/pages/admin/core/AgentToolActivationDialog.js +166 -0
  261. package/dist/routes/pages/admin/core/AgentToolActivationDialog.js.map +1 -0
  262. package/dist/routes/pages/admin/core/AgentToolActivationDialog.tsx +140 -0
  263. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.css +26 -0
  264. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.d.ts.map +1 -1
  265. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js +94 -71
  266. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js.map +1 -1
  267. package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx +60 -52
  268. package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.d.ts +2 -0
  269. package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.d.ts.map +1 -0
  270. package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.js +108 -0
  271. package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.js.map +1 -0
  272. package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.tsx +96 -0
  273. package/dist/routes/solidRoutes.d.ts.map +1 -1
  274. package/dist/routes/solidRoutes.js +2 -0
  275. package/dist/routes/solidRoutes.js.map +1 -1
  276. package/dist/routes/solidRoutes.tsx +2 -0
  277. package/dist/types/extension-registry.d.ts +12 -0
  278. package/dist/types/extension-registry.d.ts.map +1 -1
  279. package/dist/types/extension-registry.js.map +1 -1
  280. package/dist/types/extension-registry.ts +15 -0
  281. package/dist/types/solid-core.d.ts +2 -0
  282. package/package.json +2 -1
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
- import { createPortal } from "react-dom";
3
- import { ArrowLeft, ChevronDown, ExternalLink, FlaskConical, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
2
+ import { ArrowLeft, Ellipsis, ExternalLink, Eye, FlaskConical, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";
4
3
  import { useDispatch } from "react-redux";
5
4
  import { useNavigate, useParams } from "react-router-dom";
6
5
  import { createSolidEntityApi } from "../../../../redux/api/solidEntityApi";
@@ -8,130 +7,137 @@ import { useGetSolidSettingsQuery } from "../../../../redux/api/solidSettingsApi
8
7
  import { getSettingsMap } from "../../../../helpers/settingsPayload";
9
8
  import { showToast } from "../../../../redux/features/toastSlice";
10
9
  import { AgentRegistryAuditPanel } from "./AgentRegistryAuditPanel";
10
+ import { AgentPersonaHistory } from "./AgentPersonaHistory";
11
+ import { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload, type AgentHubTag } from "./AgentHubTagsField";
11
12
  import { AgentResourceCardWidget } from "../../../../components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget";
12
13
  import { AgentSessionsPanel } from "../../../../components/core/extension/solid-core/agentToolRegistry/AgentToolSessionsPanel";
13
14
  import { AgentProcessesPanel } from "../../../../components/core/extension/solid-core/agentToolRegistry/AgentProcessesPanel";
14
15
  import type { SolidKanbanCardWidgetProps } from "../../../../types/solid-core";
15
16
  import { SolidWorkflowStatusPill } from "../../../../components/core/form/SolidDraftPublishWorkflow";
16
- import { ALLOWED_MODELS_BY_PROVIDER, type AllowedModelProvider } from "../../../../constants/allowed-ai-models";
17
- import { SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidIconPicker, SolidInput, SolidTabGroup } from "../../../../components/shad-cn-ui";
17
+ import { getModelsDevModels, useModelsDevCatalog } from "../../../../hooks/useModelsDevModels";
18
+ import { SolidAutocomplete, SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidDropdownMenu, SolidDropdownMenuContent, SolidDropdownMenuItem, SolidDropdownMenuTrigger, SolidIconPicker, SolidInput, SolidTabGroup } from "../../../../components/shad-cn-ui";
18
19
  import { SolidAgentEmbedded } from "../../../../components/core/solid-agent/SolidAgentEmbedded";
20
+ import { SolidAgentMarkdown } from "../../../../components/core/solid-agent/SolidAgentMarkdown";
19
21
  import { AgentEmbeddingPanel } from "../../../../components/core/solid-agent/embed/AgentEmbeddingPanel";
20
22
  import "./AgentRegistryEditorPage.css";
21
23
 
22
24
  type Item = { id: number; name?: string; title?: string; displayName?: string; description?: string; iconName?: string; key?: string; module?: { id?: number; displayName?: string }; [key: string]: any };
23
25
  type Link = { id: number; agentSkillRegistry?: Item; agentToolRegistry?: Item; roleMetadata?: Item; secret?: Item; envVarName?: string; alwaysInclude?: boolean; requiresApproval?: boolean };
24
- type Input = { name: string; description: string; dataType: string };
26
+ type Input = { name: string; description: string; dataType: string; defaultValue?: unknown; optional: boolean };
25
27
  type Agent = Item & {
26
28
  configVersion?: number;
27
29
  systemPrompt?: string; requiredInputs?: string; reasoningModelKey?: string; fastModelKey?: string; status?: string;
28
30
  stepLimit?: number; turnStepLimit?: number; costLimit?: number;
29
31
  agentSkills?: Link[]; agentTools?: Link[]; agentRoles?: Link[]; agentSecrets?: Link[];
32
+ tags?: AgentHubTag[];
30
33
  };
31
- type ProviderModelOption = { provider: AllowedModelProvider; model: string; value: string };
34
+ type ProviderModelOption = { provider: string; providerLabel: string; model: string; value: string; note?: string };
32
35
 
33
- const PROVIDER_LABELS: Record<AllowedModelProvider, string> = {
36
+ const PROVIDER_LABELS: Record<string, string> = {
34
37
  anthropic: "Anthropic",
35
38
  openai: "OpenAI",
36
39
  openrouter: "OpenRouter",
37
40
  };
41
+ const BUILT_IN_PROVIDER_TYPES = ["openai", "anthropic"];
38
42
 
39
- function ModelPicker({ value, options, placeholder, onChange }: {
43
+ type AiProviderConfig = { type?: string; apiKey?: unknown; region?: string };
44
+ type AiModelConfig = { providerId?: string; model?: string };
45
+
46
+ /**
47
+ * Build picker options from the AI settings: every provider with an API key, its models from
48
+ * models.dev, plus the models chosen in settings and any already-saved values for this agent.
49
+ */
50
+ function buildModelOptions(
51
+ providers: Record<string, AiProviderConfig>,
52
+ settingsModels: Record<string, AiModelConfig | undefined>,
53
+ catalog: Parameters<typeof getModelsDevModels>[0],
54
+ savedValues: string[],
55
+ ): ProviderModelOption[] {
56
+ const enabled = Object.entries(providers)
57
+ .filter(([, entry]) => typeof entry?.apiKey === "string" && entry.apiKey.trim().length > 0);
58
+ const options: ProviderModelOption[] = [];
59
+ const seen = new Set<string>();
60
+ const add = (provider: string, model: string, note?: string) => {
61
+ const value = `${provider}:${model}`;
62
+ if (!model || seen.has(value)) return;
63
+ seen.add(value);
64
+ options.push({ provider, providerLabel: PROVIDER_LABELS[provider] ?? provider, model, value, note });
65
+ };
66
+ for (const [provider, entry] of enabled) {
67
+ for (const [role, config] of Object.entries(settingsModels)) {
68
+ if (config?.providerId === provider && config.model) add(provider, config.model, `${role} model in AI settings`);
69
+ }
70
+ for (const value of savedValues) {
71
+ if (value.startsWith(`${provider}:`)) add(provider, value.slice(provider.length + 1), "currently saved");
72
+ }
73
+ const type = entry.type && BUILT_IN_PROVIDER_TYPES.includes(entry.type) ? entry.type : undefined;
74
+ for (const model of getModelsDevModels(catalog, [provider, type])) add(provider, model.id);
75
+ }
76
+ return options;
77
+ }
78
+
79
+ const OTHER_MODEL = "__other_model__";
80
+
81
+ function SearchableSelect({ value, options, placeholder, disabled, onChange }: {
40
82
  value: string;
41
- options: ProviderModelOption[];
83
+ options: { label: string; value: string }[];
42
84
  placeholder: string;
85
+ disabled?: boolean;
43
86
  onChange: (value: string) => void;
44
87
  }) {
45
- const rootRef = React.useRef<HTMLDivElement>(null);
46
- const menuRef = React.useRef<HTMLDivElement>(null);
47
- const [open, setOpen] = React.useState(false);
48
88
  const [query, setQuery] = React.useState("");
49
- const [activeIndex, setActiveIndex] = React.useState(0);
50
- const [menuStyle, setMenuStyle] = React.useState<React.CSSProperties>({});
51
- const selected = options.find((option) => option.value === value);
52
- const filtered = options.filter((option) =>
53
- `${PROVIDER_LABELS[option.provider]} ${option.model}`.toLowerCase().includes(query.trim().toLowerCase()));
54
- const groups = (Object.keys(ALLOWED_MODELS_BY_PROVIDER) as AllowedModelProvider[])
55
- .map((provider) => ({ provider, options: filtered.filter((option) => option.provider === provider) }))
56
- .filter((group) => group.options.length > 0);
89
+ const selectedLabel = options.find((option) => option.value === value)?.label;
90
+ const selected = React.useMemo(() => selectedLabel ? { label: selectedLabel, value } : null, [selectedLabel, value]);
91
+ const suggestions = options.filter((option) =>
92
+ `${option.label} ${option.value}`.toLowerCase().includes(query.trim().toLowerCase()));
57
93
 
58
- React.useEffect(() => {
59
- if (!open) return;
60
- const positionMenu = () => {
61
- const bounds = rootRef.current?.getBoundingClientRect();
62
- if (!bounds) return;
63
- const gap = 6;
64
- const maxMenuHeight = Math.min(288, window.innerHeight - 24);
65
- const spaceBelow = window.innerHeight - bounds.bottom - gap - 12;
66
- const spaceAbove = bounds.top - gap - 12;
67
- const openAbove = spaceBelow < Math.min(220, maxMenuHeight) && spaceAbove > spaceBelow;
68
- const availableHeight = Math.max(120, Math.min(maxMenuHeight, openAbove ? spaceAbove : spaceBelow));
69
- setMenuStyle({
70
- position: "fixed",
71
- left: bounds.left,
72
- width: bounds.width,
73
- maxHeight: availableHeight,
74
- ...(openAbove
75
- ? { bottom: window.innerHeight - bounds.top + gap }
76
- : { top: bounds.bottom + gap }),
77
- });
78
- };
79
- positionMenu();
80
- window.addEventListener("resize", positionMenu);
81
- window.addEventListener("scroll", positionMenu, true);
82
- const handleOutsideClick = (event: MouseEvent) => {
83
- const target = event.target as Node;
84
- if (!rootRef.current?.contains(target) && !menuRef.current?.contains(target)) setOpen(false);
85
- };
86
- document.addEventListener("mousedown", handleOutsideClick);
87
- return () => {
88
- window.removeEventListener("resize", positionMenu);
89
- window.removeEventListener("scroll", positionMenu, true);
90
- document.removeEventListener("mousedown", handleOutsideClick);
91
- };
92
- }, [open]);
94
+ return <SolidAutocomplete
95
+ className="solid-standard-autocomplete w-full"
96
+ value={selected}
97
+ suggestions={suggestions}
98
+ completeMethod={({ query: next }) => setQuery(next)}
99
+ onChange={(event) => onChange(event.value?.value ?? "")}
100
+ field="label"
101
+ placeholder={placeholder}
102
+ disabled={disabled}
103
+ dropdown
104
+ forceSelection
105
+ portal
106
+ />;
107
+ }
93
108
 
94
- const choose = (option: ProviderModelOption) => {
95
- onChange(option.value);
96
- setQuery("");
97
- setOpen(false);
98
- };
99
- let flatIndex = -1;
100
-
101
- return <div className="agent-editor__model-picker" ref={rootRef}>
102
- <div className="agent-editor__model-control">
103
- <input
104
- role="combobox"
105
- aria-expanded={open}
106
- aria-autocomplete="list"
107
- aria-label={placeholder}
108
- placeholder={selected ? `${PROVIDER_LABELS[selected.provider]} / ${selected.model}` : value || placeholder}
109
- value={open ? query : ""}
110
- onFocus={() => { setQuery(""); setActiveIndex(0); setOpen(true); }}
111
- onChange={(event) => { setQuery(event.target.value); setActiveIndex(0); setOpen(true); }}
112
- onKeyDown={(event) => {
113
- if (event.key === "Escape") { setOpen(false); setQuery(""); }
114
- if (event.key === "ArrowDown") { event.preventDefault(); setOpen(true); setActiveIndex((index) => Math.min(index + 1, filtered.length - 1)); }
115
- if (event.key === "ArrowUp") { event.preventDefault(); setActiveIndex((index) => Math.max(index - 1, 0)); }
116
- if (event.key === "Enter" && open && filtered[activeIndex]) { event.preventDefault(); choose(filtered[activeIndex]); }
117
- }}
118
- />
119
- <button type="button" aria-label={open ? "Close model options" : "Show model options"} onMouseDown={(event) => event.preventDefault()} onClick={() => { setOpen((current) => !current); setQuery(""); }}><ChevronDown size={16} /></button>
109
+ function ModelPicker({ value, options, providers, providerConfig, onChange }: {
110
+ value: string;
111
+ options: ProviderModelOption[];
112
+ providers: { label: string; value: string }[];
113
+ providerConfig: Record<string, AiProviderConfig>;
114
+ onChange: (value: string) => void;
115
+ }) {
116
+ const separator = value.indexOf(":");
117
+ const provider = separator < 0 ? "" : value.slice(0, separator);
118
+ const model = separator < 0 ? "" : value.slice(separator + 1);
119
+ const availableModels = options.filter((option) => option.provider === provider);
120
+ const [otherSelected, setOtherSelected] = React.useState(false);
121
+ const showOther = !!provider && (otherSelected || (!!model && !availableModels.some((option) => option.model === model)));
122
+
123
+ return <div className="agent-editor__stack">
124
+ <div className="agent-editor__field"><span>Provider *</span>
125
+ <SearchableSelect value={provider} options={providers} placeholder="Select provider"
126
+ onChange={(next) => { setOtherSelected(false); onChange(`${next}:`); }} />
127
+ {providerConfig[provider]?.type === "bedrock" && providerConfig[provider]?.region &&
128
+ <small><em>Region: {providerConfig[provider].region}</em></small>}
129
+ </div>
130
+ <div className="agent-editor__field"><span>Model *</span>
131
+ <SearchableSelect value={showOther ? OTHER_MODEL : model}
132
+ options={[...availableModels.map((option) => ({ label: option.model, value: option.model })), { label: "Other", value: OTHER_MODEL }]}
133
+ placeholder="Select model" disabled={!provider}
134
+ onChange={(next) => {
135
+ setOtherSelected(next === OTHER_MODEL);
136
+ onChange(`${provider}:${next === OTHER_MODEL ? "" : next}`);
137
+ }} />
138
+ {showOther && <SolidInput className="w-full" aria-label="Custom model ID" placeholder="Enter model ID" value={model}
139
+ onChange={(event) => onChange(`${provider}:${event.target.value}`)} />}
120
140
  </div>
121
- {open && createPortal(<div ref={menuRef} className="agent-editor__model-menu" style={menuStyle} role="listbox">
122
- {!groups.length ? <div className="agent-editor__model-empty">{options.length ? "No matching models." : "No enabled providers. Add an API key in AI Settings."}</div>
123
- : groups.map((group) => <section className="agent-editor__model-group" key={group.provider}>
124
- <h3>{PROVIDER_LABELS[group.provider]}</h3>
125
- {group.options.map((option) => {
126
- flatIndex += 1;
127
- const index = flatIndex;
128
- return <button type="button" role="option" aria-selected={option.value === value} className={`agent-editor__model-option${index === activeIndex ? " is-active" : ""}`}
129
- key={option.value} onMouseDown={(event) => event.preventDefault()} onMouseEnter={() => setActiveIndex(index)} onClick={() => choose(option)}>
130
- <span>{option.model}</span><small>{option.provider}:{option.model}</small>
131
- </button>;
132
- })}
133
- </section>)}
134
- </div>, document.body)}
135
141
  </div>;
136
142
  }
137
143
 
@@ -146,7 +152,7 @@ const agentRoleApi = createSolidEntityApi("agentRole");
146
152
  const agentSecretApi = createSolidEntityApi("agentSecret");
147
153
  const jobApi = createSolidEntityApi("agentJob");
148
154
 
149
- const skillFields = ["id", "name", "iconName", "description", "tags"];
155
+ const skillFields = ["id", "name", "iconName", "description"];
150
156
  const toolFields = [...skillFields, "type", "status", "lastLoadError"];
151
157
 
152
158
  function fieldsQuery(fields: string[]): string {
@@ -159,7 +165,7 @@ const detailFields = [
159
165
  ];
160
166
 
161
167
  const detailQuery = [
162
- "agentRoles", "agentRoles.roleMetadata", "agentSecrets", "agentSecrets.secret",
168
+ "agentRoles", "agentRoles.roleMetadata", "agentSecrets", "agentSecrets.secret", "tags",
163
169
  ].map((name, index) => `populate[${index}]=${name}`).join("&") + "&" + fieldsQuery(detailFields);
164
170
 
165
171
  // Group by link ID to project summary columns without populating full registry records.
@@ -199,7 +205,7 @@ function agentFormFromRecord(record: Agent) {
199
205
  name: record.name ?? "", title: record.title ?? "", description: record.description ?? "", iconName: record.iconName ?? "",
200
206
  inputs: parseInputs(record.requiredInputs), reasoningModelKey: record.reasoningModelKey ?? "", fastModelKey: record.fastModelKey ?? "",
201
207
  systemPrompt: record.systemPrompt ?? "", stepLimit: record.stepLimit ?? 100, turnStepLimit: record.turnStepLimit ?? 20,
202
- costLimit: Number(record.costLimit ?? 3), skillIds: skills.map((link) => link.agentSkillRegistry?.id).filter(Boolean),
208
+ costLimit: Number(record.costLimit ?? 3), tags: agentHubTagsFrom(record.tags), skillIds: skills.map((link) => link.agentSkillRegistry?.id).filter(Boolean),
203
209
  toolIds: tools.map((link) => link.agentToolRegistry?.id).filter(Boolean),
204
210
  roleIds: items(record.agentRoles).map((link) => link.roleMetadata?.id).filter(Boolean),
205
211
  secretIds: secrets.map((link) => link.secret?.id).filter(Boolean),
@@ -214,17 +220,41 @@ function parseInputs(value: unknown): Input[] {
214
220
  const parsed = typeof value === "string" ? JSON.parse(value) : value;
215
221
  if (Array.isArray(parsed)) return parsed.map((input) => ({
216
222
  name: String(input.name ?? input.variableName ?? ""), description: String(input.description ?? ""),
217
- dataType: String(input.dataType ?? input.type ?? "string"),
223
+ dataType: String(input.dataType ?? input.type ?? "string"), defaultValue: input.defaultValue ?? null,
224
+ optional: input.optional === true,
218
225
  }));
219
226
  // Existing agent definitions may use a name-keyed object.
220
227
  if (parsed && typeof parsed === "object") return Object.entries(parsed).map(([name, definition]: [string, any]) => ({
221
228
  name, description: String(definition?.description ?? ""),
222
- dataType: String(definition?.dataType ?? definition?.type ?? "string"),
229
+ dataType: String(definition?.dataType ?? definition?.type ?? "string"), defaultValue: definition?.defaultValue ?? null,
230
+ optional: definition?.optional === true,
223
231
  }));
224
232
  } catch { /* Keep malformed historical values from crashing the editor. */ }
225
233
  return [];
226
234
  }
227
235
 
236
+ function parseDefaultValue(raw: string, dataType: string): unknown {
237
+ if (dataType === "string" || dataType === "date" || dataType === "datetime") return raw;
238
+ if (dataType === "boolean") {
239
+ if (raw !== "true" && raw !== "false") throw new Error(`Default value must be true or false for ${dataType}.`);
240
+ return raw === "true";
241
+ }
242
+ if (dataType === "number" || dataType === "integer") {
243
+ const value = Number(raw);
244
+ if (!Number.isFinite(value) || (dataType === "integer" && !Number.isSafeInteger(value))) throw new Error(`Default value must be a valid ${dataType}.`);
245
+ return value;
246
+ }
247
+ const value = JSON.parse(raw);
248
+ if (dataType === "array" && !Array.isArray(value)) throw new Error("Default value must be a JSON array.");
249
+ if (dataType === "object" && (!value || typeof value !== "object" || Array.isArray(value))) throw new Error("Default value must be a JSON object.");
250
+ return value;
251
+ }
252
+
253
+ function formatDefaultValue(value: unknown): string {
254
+ if (value == null) return "";
255
+ return typeof value === "string" ? value : JSON.stringify(value);
256
+ }
257
+
228
258
  function apiError(error: any): string {
229
259
  const value = error?.data?.data?.message ?? error?.data?.message ?? error?.message;
230
260
  return Array.isArray(value) ? value.join("; ") : typeof value === "string" ? value : "The save failed.";
@@ -235,21 +265,47 @@ function useCatalog(api: typeof skillApi, query = "offset=0&limit=1000") {
235
265
  return { records: items(data?.records) as Item[], isLoading, refetch };
236
266
  }
237
267
 
238
- function LinkPicker({ label, description, options, selected, onAdd, onRemove, createUrl, render, renderSettings, linkFor }: {
268
+ function ResourcePreviewDialog({ item, kind, onClose }: { item: Item; kind: "skill" | "tool"; onClose: () => void }) {
269
+ const api = kind === "skill" ? skillApi : toolApi;
270
+ const field = kind === "skill" ? "body" : "sourceCode";
271
+ const { currentData, isFetching, isError, refetch } = api.useGetSolidEntityByIdQuery(
272
+ { id: item.id, qs: fieldsQuery(["id", field]) }, { refetchOnMountOrArgChange: true });
273
+ const record = recordFrom(currentData);
274
+ const content = record?.[field] ?? "";
275
+
276
+ return <SolidDialog open onOpenChange={(open) => { if (!open) onClose(); }} header={item.name ?? `View ${kind}`}
277
+ style={{ width: "min(64rem, 94vw)", maxWidth: "94vw" }}>
278
+ <SolidDialogBody className="agent-editor__resource-preview-body">
279
+ {isFetching ? <div className="agent-editor__empty" role="status">Loading {kind}…</div>
280
+ : isError || !record ? <div className="agent-editor__empty"><p role="alert">This {kind} could not be loaded.</p><SolidButton variant="secondary" onClick={() => void refetch()}>Retry</SolidButton></div>
281
+ : !content ? <div className="agent-editor__empty">No {kind === "skill" ? "skill body" : "source code"} available.</div>
282
+ : kind === "skill" ? <SolidAgentMarkdown text={content} />
283
+ : <SolidCodeEditor value={content} language="python" readOnly fontSize={12} height="min(65vh, 42rem)" />}
284
+ </SolidDialogBody>
285
+ </SolidDialog>;
286
+ }
287
+
288
+ function LinkPicker({ label, description, options, selected, onAdd, onRemove, createUrl, render, renderSettings, linkFor, onView, editUrlFor }: {
239
289
  label: string; description: string; options: Item[]; selected: Item[];
240
290
  onAdd: (id: number) => void; onRemove: (id: number) => void; createUrl?: string;
241
291
  render: (item: Item, link?: Link) => React.ReactNode;
242
292
  renderSettings?: (item: Item, link?: Link) => React.ReactNode;
243
293
  linkFor?: (id: number) => Link | undefined;
294
+ onView?: (item: Item) => void;
295
+ editUrlFor?: (item: Item) => string;
244
296
  }) {
245
297
  const [search, setSearch] = React.useState("");
246
298
  const [open, setOpen] = React.useState(false);
299
+ const showAssociatedCount = label === "Skills" || label === "Tools";
247
300
  const available = options.filter((item) => !selected.some((selectedItem) => selectedItem.id === item.id)
248
301
  && `${item.name ?? item.displayName ?? item.key ?? ""} ${item.description ?? ""}`.toLowerCase().includes(search.toLowerCase())).slice(0, 20);
249
302
  return <section className="agent-editor__section">
250
303
  <div className="agent-editor__section-head"><div><h2>{label}</h2><p>{description}</p></div>
251
304
  {createUrl && <a href={createUrl} target="_blank" rel="noopener noreferrer" className="agent-editor__new-link">Create {label === "Skills" ? "skill" : "tool"} <ExternalLink size={14} /></a>}
252
305
  </div>
306
+ {showAssociatedCount && <div className="agent-editor__linked-count" role="status">
307
+ {selected.length} {label.toLowerCase()} associated
308
+ </div>}
253
309
  <div className="agent-editor__picker">
254
310
  <SolidInput value={search} placeholder={`Search and add ${label.toLowerCase()}…`} aria-label={`Search ${label.toLowerCase()}`}
255
311
  onFocus={() => setOpen(true)} onChange={(event) => { setSearch(event.target.value); setOpen(true); }} />
@@ -262,7 +318,14 @@ function LinkPicker({ label, description, options, selected, onAdd, onRemove, cr
262
318
  {selected.length ? <div className="agent-editor__cards">{selected.map((item) => <div className="agent-editor__linked-card" key={item.id}>
263
319
  <div className="agent-editor__card-content">{render(item, linkFor?.(item.id))}</div>
264
320
  {renderSettings?.(item, linkFor?.(item.id))}
265
- <button type="button" aria-label={`Remove ${item.name ?? item.displayName ?? item.key}`} onClick={() => onRemove(item.id)}><Trash2 size={16} /></button>
321
+ {onView && editUrlFor ? <SolidDropdownMenu>
322
+ <SolidDropdownMenuTrigger asChild><button type="button" className="agent-editor__resource-menu-trigger" aria-label={`Actions for ${item.name ?? item.displayName ?? item.key}`}><Ellipsis size={18} /></button></SolidDropdownMenuTrigger>
323
+ <SolidDropdownMenuContent className="agent-editor__resource-menu">
324
+ <SolidDropdownMenuItem onSelect={() => onView(item)}><Eye size={16} /> View</SolidDropdownMenuItem>
325
+ <SolidDropdownMenuItem asChild><a href={editUrlFor(item)} target="_blank" rel="noopener noreferrer"><Pencil size={16} /> Edit</a></SolidDropdownMenuItem>
326
+ <SolidDropdownMenuItem className="agent-editor__resource-delete" onSelect={() => onRemove(item.id)}><Trash2 size={16} /> Delete</SolidDropdownMenuItem>
327
+ </SolidDropdownMenuContent>
328
+ </SolidDropdownMenu> : <button type="button" aria-label={`Remove ${item.name ?? item.displayName ?? item.key}`} onClick={() => onRemove(item.id)}><Trash2 size={16} /></button>}
266
329
  </div>)}</div> : <div className="agent-editor__empty">No {label.toLowerCase()} linked yet.</div>}
267
330
  </section>;
268
331
  }
@@ -288,8 +351,8 @@ export function AgentRegistryEditorPage() {
288
351
  };
289
352
  }, [agentResult.currentData, skillLinks.currentData, toolLinks.currentData]);
290
353
  const { data: settings, isError: settingsError } = useGetSolidSettingsQuery(undefined);
291
- const skills = useCatalog(skillApi, `offset=0&limit=1000&${fieldsQuery(skillFields)}`);
292
- const tools = useCatalog(toolApi, `offset=0&limit=1000&${fieldsQuery(toolFields)}`);
354
+ const skills = useCatalog(skillApi, `offset=0&limit=1000&populate[0]=tags&${fieldsQuery(skillFields)}`);
355
+ const tools = useCatalog(toolApi, `offset=0&limit=1000&populate[0]=tags&${fieldsQuery(toolFields)}`);
293
356
  const roles = useCatalog(roleApi, "offset=0&limit=1000&populate[0]=module");
294
357
  const secrets = useCatalog(secretApi, "offset=0&limit=1000&fields[0]=id&fields[1]=key&fields[2]=displayName&fields[3]=description");
295
358
  const [createAgent, { isLoading: creating }] = entityApi.useCreateSolidEntityMutation();
@@ -315,6 +378,7 @@ export function AgentRegistryEditorPage() {
315
378
  if (tab === "jobs") void jobs.refetch();
316
379
  };
317
380
  const [testAgentOpen, setTestAgentOpen] = React.useState(false);
381
+ const [preview, setPreview] = React.useState<{ item: Item; kind: "skill" | "tool" } | null>(null);
318
382
  const [testAgentWindowMode, setTestAgentWindowMode] = React.useState<"docked" | "maximized">("maximized");
319
383
  const [name, setName] = React.useState("");
320
384
  const [title, setTitle] = React.useState("");
@@ -327,6 +391,8 @@ export function AgentRegistryEditorPage() {
327
391
  const [stepLimit, setStepLimit] = React.useState(100);
328
392
  const [turnStepLimit, setTurnStepLimit] = React.useState(20);
329
393
  const [costLimit, setCostLimit] = React.useState(3);
394
+ const [tags, setTags] = React.useState<AgentHubTag[]>([]);
395
+ const [creatingTag, setCreatingTag] = React.useState(false);
330
396
  const [skillIds, setSkillIds] = React.useState<number[]>([]);
331
397
  const [toolIds, setToolIds] = React.useState<number[]>([]);
332
398
  const [roleIds, setRoleIds] = React.useState<number[]>([]);
@@ -343,7 +409,7 @@ export function AgentRegistryEditorPage() {
343
409
  const baseline = React.useRef("");
344
410
 
345
411
  const currentForm = () => JSON.stringify({ name, title, description, iconName, inputs, reasoningModelKey, fastModelKey, systemPrompt,
346
- stepLimit: Number(stepLimit), turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit), skillIds, toolIds, roleIds, secretIds,
412
+ stepLimit: Number(stepLimit), turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit), tags, skillIds, toolIds, roleIds, secretIds,
347
413
  alwaysIncludeValues, requiresApprovalValues, secretEnvVarNames });
348
414
 
349
415
  React.useEffect(() => {
@@ -354,6 +420,7 @@ export function AgentRegistryEditorPage() {
354
420
  setReasoningModelKey(record.reasoningModelKey ?? ""); setFastModelKey(record.fastModelKey ?? "");
355
421
  setSystemPrompt(record.systemPrompt ?? ""); setStepLimit(record.stepLimit ?? 100);
356
422
  setTurnStepLimit(record.turnStepLimit ?? 20); setCostLimit(Number(record.costLimit ?? 3));
423
+ setTags(agentHubTagsFrom(record.tags));
357
424
  setSkillIds(items(record.agentSkills).map((link) => link.agentSkillRegistry?.id).filter(Boolean));
358
425
  setToolIds(items(record.agentTools).map((link) => link.agentToolRegistry?.id).filter(Boolean));
359
426
  setRoleIds(items(record.agentRoles).map((link) => link.roleMetadata?.id).filter(Boolean));
@@ -377,18 +444,26 @@ export function AgentRegistryEditorPage() {
377
444
  }, [skills.refetch, tools.refetch]);
378
445
 
379
446
  const configValue = getSettingsMap(settings).solidXGenAiCodeBuilderConfig;
380
- let enabledProviders: Record<string, { apiKey?: unknown }> = {};
447
+ let aiConfig: { providers?: Record<string, AiProviderConfig>; models?: { default?: AiModelConfig; main?: AiModelConfig; fast?: AiModelConfig } } = {};
381
448
  try {
382
- const config = typeof configValue === "string" ? JSON.parse(configValue) : configValue;
383
- enabledProviders = config?.providers ?? {};
449
+ aiConfig = (typeof configValue === "string" ? JSON.parse(configValue) : configValue) ?? {};
384
450
  } catch { /* Invalid configuration has no enabled providers. */ }
385
- const modelOptions = (Object.keys(ALLOWED_MODELS_BY_PROVIDER) as AllowedModelProvider[])
386
- .filter((provider) => typeof enabledProviders[provider]?.apiKey === "string" && (enabledProviders[provider].apiKey as string).trim().length > 0)
387
- .flatMap((provider) => ALLOWED_MODELS_BY_PROVIDER[provider].map((model) => ({
388
- provider,
389
- model,
390
- value: `${provider}:${model}`,
391
- })));
451
+ const { catalog: modelsCatalog } = useModelsDevCatalog();
452
+ const savedModelKeys = [record?.reasoningModelKey, record?.fastModelKey].filter((key): key is string => !!key);
453
+ const modelOptions = buildModelOptions(
454
+ aiConfig.providers ?? {},
455
+ { Reasoning: aiConfig.models?.default ?? aiConfig.models?.main, Fast: aiConfig.models?.fast },
456
+ modelsCatalog,
457
+ savedModelKeys,
458
+ );
459
+ const providerOptions = Object.entries(aiConfig.providers ?? {})
460
+ .filter(([, entry]) => typeof entry?.apiKey === "string" && entry.apiKey.trim().length > 0)
461
+ .map(([provider]) => ({ label: modelsCatalog?.[provider]?.name ?? PROVIDER_LABELS[provider] ?? provider, value: provider }));
462
+ const isValidModelKey = (value: string) => {
463
+ const separator = value.indexOf(":");
464
+ return separator > 0 && providerOptions.some((provider) => provider.value === value.slice(0, separator)) &&
465
+ !!value.slice(separator + 1).trim();
466
+ };
392
467
  const toggle = (setter: React.Dispatch<React.SetStateAction<number[]>>, value: number) =>
393
468
  setter((current) => current.includes(value) ? current.filter((id) => id !== value) : [...current, value]);
394
469
 
@@ -413,12 +488,13 @@ export function AgentRegistryEditorPage() {
413
488
  };
414
489
 
415
490
  const save = async (nextStatus?: "draft" | "active" | "disabled") => {
491
+ if (creatingTag) return;
416
492
  const next: Record<string, string> = {};
417
493
  if (!name.trim()) next.name = "Name is required.";
418
494
  if (!title.trim()) next.title = "Title is required.";
419
495
  if (!systemPrompt.trim()) next.systemPrompt = "Persona instructions are required.";
420
- if (!modelOptions.some((option) => option.value === reasoningModelKey)) next.reasoningModelKey = "Choose an enabled reasoning provider and model.";
421
- if (!modelOptions.some((option) => option.value === fastModelKey)) next.fastModelKey = "Choose an enabled fast provider and model.";
496
+ if (!isValidModelKey(reasoningModelKey)) next.reasoningModelKey = "Choose an enabled reasoning provider and model.";
497
+ if (!isValidModelKey(fastModelKey)) next.fastModelKey = "Choose an enabled fast provider and model.";
422
498
  if (inputs.some((input) => !input.name.trim() || !input.dataType)) next.inputs = "Each input needs a name and data type.";
423
499
  if (new Set(inputs.map((input) => input.name.trim().toLowerCase())).size !== inputs.length) next.inputs = "Input names must be unique.";
424
500
  if (stepLimit < 1 || turnStepLimit < 1 || costLimit < 0) next.limits = "Step limits must be positive and cost limit cannot be negative.";
@@ -428,11 +504,22 @@ export function AgentRegistryEditorPage() {
428
504
  dispatch(showToast({ severity: "error", summary: "Missing information", detail: Object.values(next).join(" ") }));
429
505
  return;
430
506
  }
507
+ let normalizedInputs: Input[];
508
+ try {
509
+ normalizedInputs = inputs.map((input) => ({ ...input, name: input.name.trim(), description: input.description.trim(),
510
+ defaultValue: input.defaultValue === "" || input.defaultValue == null ? null : parseDefaultValue(String(input.defaultValue), input.dataType) }));
511
+ } catch (error) {
512
+ next.inputs = error instanceof Error ? error.message : "Check the default input values.";
513
+ setErrors(next);
514
+ setTab("basics");
515
+ return;
516
+ }
431
517
  const payload = {
432
518
  name: name.trim(), title: title.trim(), description: description.trim(), iconName,
433
- requiredInputs: JSON.stringify(inputs.map((input) => ({ ...input, name: input.name.trim(), description: input.description.trim() }))),
519
+ requiredInputs: JSON.stringify(normalizedInputs),
434
520
  reasoningModelKey, fastModelKey, systemPrompt, stepLimit: Number(stepLimit),
435
521
  turnStepLimit: Number(turnStepLimit), costLimit: Number(costLimit),
522
+ ...agentHubTagsPayload(tags),
436
523
  status: nextStatus ?? record?.status ?? "draft",
437
524
  };
438
525
  let newlyCreatedId: number | undefined;
@@ -507,25 +594,28 @@ export function AgentRegistryEditorPage() {
507
594
  <div className="agent-editor__grid">{field("Name", name, setName, "name", true)}{field("Title", title, setTitle, "title", true)}
508
595
  {field("Description", description, setDescription, "description")}<div className="agent-editor__field"><span>Icon</span><SolidIconPicker value={iconName} onChange={setIconName} /></div>
509
596
  </div>
510
- <section className="agent-editor__section"><div className="agent-editor__section-head"><div><h2>Required inputs</h2><p>Define the variables people must provide when starting this agent.</p></div>
511
- {inputs.length > 0 && <SolidButton type="button" variant="secondary" size="small" onClick={() => setInputs((current) => [...current, { name: "", description: "", dataType: "string" }])}><Plus size={15} /> Add input</SolidButton>}
597
+ <AgentHubTagsField value={tags} onChange={setTags} disabled={creating || updating || isLoading || isFetching || isError} onBusyChange={setCreatingTag} />
598
+ <section className="agent-editor__section"><div className="agent-editor__section-head"><div><h2>Inputs</h2><p>Define the variables this agent can use. Mark inputs optional or provide a default value when people do not need to enter them.</p></div>
599
+ {inputs.length > 0 && <SolidButton type="button" variant="secondary" size="small" onClick={() => setInputs((current) => [...current, { name: "", description: "", dataType: "string", defaultValue: null, optional: false }])}><Plus size={15} /> Add input</SolidButton>}
512
600
  </div>
513
- {!inputs.length ? <div className="agent-editor__empty">This agent has no required inputs. <button type="button" onClick={() => setInputs([{ name: "", description: "", dataType: "string" }])}><Plus size={15} /> Add an input variable</button></div>
601
+ {!inputs.length ? <div className="agent-editor__empty">This agent has no inputs. <button type="button" onClick={() => setInputs([{ name: "", description: "", dataType: "string", defaultValue: null, optional: false }])}><Plus size={15} /> Add an input variable</button></div>
514
602
  : <div className="agent-editor__inputs">{inputs.map((input, index) => <div className="agent-editor__input-row" key={index}>
515
603
  <SolidInput aria-label={`Input ${index + 1} name`} placeholder="Variable name" value={input.name} onChange={(event) => setInputs((current) => current.map((item, i) => i === index ? { ...item, name: event.target.value } : item))} />
516
604
  <SolidInput aria-label={`Input ${index + 1} description`} placeholder="Description" value={input.description} onChange={(event) => setInputs((current) => current.map((item, i) => i === index ? { ...item, description: event.target.value } : item))} />
605
+ <SolidInput aria-label={`Input ${index + 1} default value`} placeholder="Default value" value={formatDefaultValue(input.defaultValue)} onChange={(event) => setInputs((current) => current.map((item, i) => i === index ? { ...item, defaultValue: event.target.value } : item))} />
517
606
  <select aria-label={`Input ${index + 1} data type`} value={input.dataType} onChange={(event) => setInputs((current) => current.map((item, i) => i === index ? { ...item, dataType: event.target.value } : item))}>
518
607
  {["string", "number", "integer", "boolean", "date", "datetime", "object", "array"].map((type) => <option key={type} value={type}>{type}</option>)}
519
608
  </select>
609
+ <label className="agent-editor__input-optional"><input type="checkbox" checked={input.optional} onChange={(event) => setInputs((current) => current.map((item, i) => i === index ? { ...item, optional: event.target.checked } : item))} /> Optional</label>
520
610
  <button type="button" aria-label={`Remove input ${index + 1}`} onClick={() => setInputs((current) => current.filter((_, i) => i !== index))}><Trash2 size={17} /></button>
521
611
  </div>)}</div>}
522
612
  {errors.inputs && <small className="agent-editor__error">{errors.inputs}</small>}</section>
523
- <section className="agent-editor__section"><h2>Models</h2><p>Choose any configured provider and model pair for each role. Both lists use the models enabled in AI settings.</p><div className="agent-editor__grid">
613
+ <section className="agent-editor__section agent-editor__models"><h2>Models</h2><p>Choose a configured provider and model for each role. Select Other to enter a model ID manually.</p><div className="agent-editor__grid">
524
614
  {([["Reasoning model", reasoningModelKey, setReasoningModelKey, "reasoningModelKey"], ["Fast model", fastModelKey, setFastModelKey, "fastModelKey"]] as const).map(([label, value, setter, key]) =>
525
- <label className="agent-editor__field" key={key}><span>{label} *</span><ModelPicker value={value} options={modelOptions} placeholder="Search providers and models…" onChange={(next) => setter(next)} />
526
- {errors[key] && <small className="agent-editor__error">{errors[key]}</small>}</label>)}
615
+ <div className="agent-editor__field" key={key}><span>{label}</span><ModelPicker value={value} options={modelOptions} providers={providerOptions} providerConfig={aiConfig.providers ?? {}} onChange={setter} />
616
+ {errors[key] && <small className="agent-editor__error">{errors[key]}</small>}</div>)}
527
617
  </div>{settingsError ? <p className="agent-editor__hint">Settings could not be loaded. Try refreshing this page.</p>
528
- : !modelOptions.length && <p className="agent-editor__hint">No configured models are available. Check the AI settings and your permission to view encrypted settings.</p>}</section>
618
+ : !providerOptions.length && <p className="agent-editor__hint">No enabled providers are available. Check the AI settings and your permission to view encrypted settings.</p>}</section>
529
619
  <section className="agent-editor__section agent-editor__workflow" aria-labelledby="agent-lifecycle-title">
530
620
  <div className="agent-editor__section-head"><div><h2 id="agent-lifecycle-title">Agent lifecycle</h2><p>Track this agent through its available stages. Select a stage to update its status.</p></div><div className="agent-editor__workflow-meta">{record?.configVersion != null && <span className="agent-editor__config-version" aria-label={`Configuration version ${record.configVersion}`}>Config v{record.configVersion}</span>}<SolidWorkflowStatusPill label={agentStatus} /></div></div>
531
621
  <div className="agent-editor__workflow-stages" aria-label={`Current agent stage: ${agentStatus}`}>
@@ -546,17 +636,20 @@ export function AgentRegistryEditorPage() {
546
636
  <small className="agent-editor__workflow-save-hint">Changing stage saves the current form and its linked skills, tools, roles, and secrets.</small>
547
637
  </section>
548
638
  </div> },
549
- { value: "persona", label: "Persona", content: <section className="agent-editor__section agent-editor__persona"><div className="agent-editor__section-head"><div><h2>System prompt *</h2><p>Describe the agent's role, behavior, and instructions in Markdown.</p></div></div>
639
+ { value: "persona", label: "Persona", content: <section className="agent-editor__section agent-editor__persona"><div className="agent-editor__section-head"><div><h2>System prompt *</h2><p>Describe the agent's role, behavior, and instructions in Markdown.</p></div>
640
+ {record?.id && <AgentPersonaHistory agentId={record.id} savedPrompt={record.systemPrompt ?? ""} refreshVersion={auditVersion} />}</div>
550
641
  <SolidCodeEditor value={systemPrompt} onChange={(value) => { setSystemPrompt(value ?? ""); setErrors((current) => ({ ...current, systemPrompt: "" })); }} language="markdown" fontSize={11} height="max(34rem, calc(100dvh - 18rem))" />
551
642
  {errors.systemPrompt && <small className="agent-editor__error">{errors.systemPrompt}</small>}</section> },
552
643
  { value: "skills", label: "Skills", content: <LinkPicker label="Skills" description="Skills available to this agent." options={skills.records} selected={linked(skillIds, skills.records, items(record?.agentSkills).map((link) => link.agentSkillRegistry).filter(Boolean))}
553
644
  onAdd={(id) => toggle(setSkillIds, id)} onRemove={(id) => toggle(setSkillIds, id)} createUrl="/admin/core/solid-core/agent-skill-registry/editor/new"
645
+ onView={(item) => setPreview({ item, kind: "skill" })} editUrlFor={(item) => `/admin/core/solid-core/agent-skill-registry/editor/${item.id}`}
554
646
  linkFor={(id) => linkForTarget(record?.agentSkills, "agentSkillRegistry", id)}
555
647
  render={(item) => <AgentResourceCardWidget {...({ rowData: item } as SolidKanbanCardWidgetProps)} />}
556
648
  renderSettings={(item) => <div className="agent-editor__link-settings">{linkSetting("Always include", alwaysIncludeValues[item.id] ?? true,
557
649
  (checked) => setAlwaysIncludeValues((current) => ({ ...current, [item.id]: checked })), "Add the full skill to the agent prompt. Turn off to load it on demand.")}</div>} /> },
558
650
  { value: "tools", label: "Tools", content: <LinkPicker label="Tools" description="Tools available to this agent." options={tools.records} selected={linked(toolIds, tools.records, items(record?.agentTools).map((link) => link.agentToolRegistry).filter(Boolean))}
559
651
  onAdd={(id) => toggle(setToolIds, id)} onRemove={(id) => toggle(setToolIds, id)} createUrl="/admin/core/solid-core/agent-tool-registry/editor/new"
652
+ onView={(item) => setPreview({ item, kind: "tool" })} editUrlFor={(item) => `/admin/core/solid-core/agent-tool-registry/editor/${item.id}`}
560
653
  linkFor={(id) => linkForTarget(record?.agentTools, "agentToolRegistry", id)}
561
654
  render={(item) => <AgentResourceCardWidget {...({ rowData: item } as SolidKanbanCardWidgetProps)} />}
562
655
  renderSettings={(item) => <div className="agent-editor__link-settings">{linkSetting("Require approval", requiresApprovalValues[item.id] ?? false,
@@ -592,8 +685,9 @@ export function AgentRegistryEditorPage() {
592
685
  return <main className="agent-editor"><header className="agent-editor__header"><div className="agent-editor__heading-with-refresh"><h1>{record?.id ? "Edit Agent" : "Create Agent"}</h1>{record?.id && <button type="button" className={`agent-editor__refresh${isFetching ? " is-loading" : ""}`} aria-label="Refresh agent" title="Refresh agent" disabled={isFetching || updating} onClick={requestRefresh}><RefreshCw size={14} /></button>}</div><div className="agent-editor__actions">
593
686
  <SolidButton variant="secondary" leftIcon={<ArrowLeft size={16} />} onClick={() => navigate(-1)}>Back</SolidButton>
594
687
  {record?.id && <SolidButton variant="secondary" leftIcon={<FlaskConical size={16} />} onClick={openAgentTest}>Test Agent</SolidButton>}
595
- <SolidButton loading={creating || updating} disabled={isLoading || isFetching || isError || (id !== "new" && !record?.id)} onClick={() => void save()}>Save Agent</SolidButton>
688
+ <SolidButton loading={creating || updating} disabled={creatingTag || isLoading || isFetching || isError || (id !== "new" && !record?.id)} onClick={() => void save()}>Save Agent</SolidButton>
596
689
  </div></header>
690
+ {preview && <ResourcePreviewDialog item={preview.item} kind={preview.kind} onClose={() => setPreview(null)} />}
597
691
  <SolidDialog open={confirmRefresh} onOpenChange={setConfirmRefresh} header="Discard unsaved changes?" style={{ width: "min(28rem, 94vw)" }}
598
692
  footer={<><SolidButton type="button" variant="secondary" onClick={() => setConfirmRefresh(false)}>Cancel</SolidButton><SolidButton type="button" disabled={isFetching} onClick={() => { setConfirmRefresh(false); void refetch(); }}>Refresh and discard</SolidButton></>}>
599
693
  <SolidDialogBody><p>You have unsaved changes. Refreshing will discard them and load the latest agent content.</p></SolidDialogBody>
@@ -1 +1 @@
1
- {"version":3,"file":"AgentSkillRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":"AAgBA,OAAO,oCAAoC,CAAC;AAiG5C,wBAAgB,4BAA4B,4CA0V3C"}
1
+ {"version":3,"file":"AgentSkillRegistryEditorPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx"],"names":[],"mappings":"AAiBA,OAAO,oCAAoC,CAAC;AA8E5C,wBAAgB,4BAA4B,4CAwS3C"}