@swiss-ai-hub/web 0.290.11

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 (313) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +479 -0
  3. package/app.config.ts +1 -0
  4. package/app.vue +52 -0
  5. package/assets/css/main.css +4 -0
  6. package/assets/images/logo.png +0 -0
  7. package/components/Agent/Avatar.vue +40 -0
  8. package/components/Agent/Card.vue +139 -0
  9. package/components/Agent/Configuration.vue +20 -0
  10. package/components/Agent/CreateModal.vue +287 -0
  11. package/components/Agent/EmptyCard.vue +35 -0
  12. package/components/Agent/List.vue +85 -0
  13. package/components/Agent/TemplateCard.vue +58 -0
  14. package/components/AppLoader.vue +55 -0
  15. package/components/Chat/Message.vue +90 -0
  16. package/components/Chat/SourceNodes.vue +120 -0
  17. package/components/Chat/Thread.vue +134 -0
  18. package/components/Costs/Table.vue +56 -0
  19. package/components/Dashboard/Component/BarChart.vue +46 -0
  20. package/components/Dashboard/Component/LineChart.vue +138 -0
  21. package/components/Dashboard/Component/Number.vue +31 -0
  22. package/components/Dashboard/Grid.vue +214 -0
  23. package/components/Dashboard/Item.vue +75 -0
  24. package/components/Dashboard/Trend.vue +34 -0
  25. package/components/Display/List/DisplayList.vue +93 -0
  26. package/components/Evaluation/Dataset/Card.vue +70 -0
  27. package/components/Evaluation/Dataset/Create.vue +81 -0
  28. package/components/Evaluation/Dataset/Edit.vue +132 -0
  29. package/components/Event/Display/AddMemoryToChatHistoryEvent.vue +60 -0
  30. package/components/Event/Display/AgentInTheLoopRequestEvent.vue +56 -0
  31. package/components/Event/Display/AgentInTheLoopResponseEvent.vue +17 -0
  32. package/components/Event/Display/Base.vue +125 -0
  33. package/components/Event/Display/BaseRetrieveMemoryEvent.vue +101 -0
  34. package/components/Event/Display/BaseStoreMemoryEvent.vue +182 -0
  35. package/components/Event/Display/ChunkEvent.vue +40 -0
  36. package/components/Event/Display/EmbeddingEvent.vue +25 -0
  37. package/components/Event/Display/ExceptionEvent.vue +21 -0
  38. package/components/Event/Display/GuardAcceptEvent.vue +25 -0
  39. package/components/Event/Display/GuardEvent.vue +17 -0
  40. package/components/Event/Display/GuardRejectionEvent.vue +25 -0
  41. package/components/Event/Display/HumanInTheLoopRequestEvent.vue +53 -0
  42. package/components/Event/Display/HumanInTheLoopResponseEvent.vue +40 -0
  43. package/components/Event/Display/LLMCostEvent.vue +25 -0
  44. package/components/Event/Display/LLMEvent.vue +92 -0
  45. package/components/Event/Display/LimitChatHistoryEvent.vue +60 -0
  46. package/components/Event/Display/RAGFailureStopEvent.vue +28 -0
  47. package/components/Event/Display/RAGStartEvent.vue +77 -0
  48. package/components/Event/Display/RAGSuccessStopEvent.vue +16 -0
  49. package/components/Event/Display/RawDataContent.vue +69 -0
  50. package/components/Event/Display/RerankerEvent.vue +39 -0
  51. package/components/Event/Display/RetrieverEvent.vue +22 -0
  52. package/components/Event/Display/RouterEvent.vue +54 -0
  53. package/components/Event/Display/StandaloneQuestionCondenserEvent.vue +38 -0
  54. package/components/Event/Display/StopEvent.vue +16 -0
  55. package/components/Event/Display/ThoughtEvent.vue +20 -0
  56. package/components/Event/Display/ToolEvent.vue +38 -0
  57. package/components/Event/Display/UnknownEvent.vue +17 -0
  58. package/components/Event/Display/UserMessageEvent.vue +35 -0
  59. package/components/Event/List/EventList.vue +249 -0
  60. package/components/Event/Statistics.vue +49 -0
  61. package/components/Event/Timeseries.vue +224 -0
  62. package/components/FormKit/AgentSelector.vue +307 -0
  63. package/components/FormKit/ChipsInput.vue +62 -0
  64. package/components/FormKit/DynamicConfiguration.vue +155 -0
  65. package/components/FormKit/IconSelector.vue +72 -0
  66. package/components/FormKit/KnowledgeDatabaseSelector.vue +92 -0
  67. package/components/FormKit/LocaleInput.vue +150 -0
  68. package/components/FormKit/ModelSelect.vue +110 -0
  69. package/components/FormKit/Repeater.vue +93 -0
  70. package/components/FormKit/VectorStoreInput.vue +247 -0
  71. package/components/Knowledge/Document/List.vue +140 -0
  72. package/components/Knowledge/Document/Overview.vue +28 -0
  73. package/components/Knowledge/Document/UploadModal.vue +298 -0
  74. package/components/Knowledge/Document/WithNodes.vue +105 -0
  75. package/components/Knowledge/Namespace/Card.vue +108 -0
  76. package/components/Knowledge/Namespace/CreateModal.vue +203 -0
  77. package/components/Knowledge/Namespace/EditModal.vue +134 -0
  78. package/components/Knowledge/Namespace/EmptyCard.vue +35 -0
  79. package/components/Knowledge/Node/Content.vue +71 -0
  80. package/components/Markdown/Renderer.vue +87 -0
  81. package/components/Memory/DetailPage.vue +48 -0
  82. package/components/Memory/Edit.vue +241 -0
  83. package/components/Memory/Graph.vue +318 -0
  84. package/components/Memory/List.vue +155 -0
  85. package/components/Memory/MemoryManagementPage.vue +178 -0
  86. package/components/Memory/OpenWebUIContent.vue +96 -0
  87. package/components/Memory/PageLayout.vue +72 -0
  88. package/components/Models/ModelDetailsPanel.vue +250 -0
  89. package/components/Models/NamespaceCard.vue +79 -0
  90. package/components/Navigation/Left.vue +85 -0
  91. package/components/Navigation/Top.vue +31 -0
  92. package/components/Notification/Item.vue +88 -0
  93. package/components/Notification/NotificationsOverlay.vue +164 -0
  94. package/components/Process/Card.vue +119 -0
  95. package/components/Process/Configuration.vue +20 -0
  96. package/components/Process/CreateModal.vue +276 -0
  97. package/components/Process/EmptyCard.vue +35 -0
  98. package/components/Process/Form.vue +153 -0
  99. package/components/Process/Starts.vue +44 -0
  100. package/components/Process/Walkthrough/List.vue +162 -0
  101. package/components/Role/AccessRulesEditor.vue +132 -0
  102. package/components/Role/Card.vue +68 -0
  103. package/components/Role/Create.vue +55 -0
  104. package/components/Role/Edit.vue +82 -0
  105. package/components/Role/UsageLimitsEditor.vue +225 -0
  106. package/components/Service/Selection.vue +148 -0
  107. package/components/Structural/Column.vue +74 -0
  108. package/components/Structural/Screen.vue +10 -0
  109. package/components/Structural/Substructure.vue +5 -0
  110. package/components/Tenant/Switcher.vue +102 -0
  111. package/components/Thread/Details.vue +135 -0
  112. package/components/Thread/Hierarchy.vue +136 -0
  113. package/components/Thread/Info.vue +41 -0
  114. package/components/Thread/List.vue +136 -0
  115. package/components/User/Bar.vue +74 -0
  116. package/components/User/List.vue +86 -0
  117. package/components/User/RoleChips.vue +83 -0
  118. package/components/User/Settings.vue +79 -0
  119. package/components/Workflow/Modal.vue +39 -0
  120. package/components/Workflow/NodeCard.vue +41 -0
  121. package/components/Workflow/StartNode.vue +24 -0
  122. package/components/Workflow/StepNode.vue +27 -0
  123. package/components/Workflow/StopNode.vue +24 -0
  124. package/components/Workflow/Visualization.vue +265 -0
  125. package/components/mdc/MarkdownFigure.vue +9 -0
  126. package/components/mdc/MarkdownTable.vue +9 -0
  127. package/components/mdc/ResolveImageComponent.vue +58 -0
  128. package/composables/agent/useAgentClass.ts +27 -0
  129. package/composables/agent/useAgentClassInstances.ts +27 -0
  130. package/composables/agent/useAgentClasses.ts +27 -0
  131. package/composables/agent/useAgentIconFromThread.ts +8 -0
  132. package/composables/agent/useAgentInstance.ts +28 -0
  133. package/composables/agent/useAgentInstanceThreads.ts +76 -0
  134. package/composables/agent/useAgentInstances.ts +25 -0
  135. package/composables/agent/useAgentNavigation.ts +35 -0
  136. package/composables/agent/useCreateAgentInstance.ts +33 -0
  137. package/composables/agent/useDeleteAgentInstance.ts +31 -0
  138. package/composables/agent/useUpdateAgentInstance.ts +40 -0
  139. package/composables/auth/useAuth.ts +54 -0
  140. package/composables/auth/useAuthProviders.ts +14 -0
  141. package/composables/chat/useChatCompletions.ts +30 -0
  142. package/composables/dashboard/useAgentNameFromDashboardWidget.ts +27 -0
  143. package/composables/dashboard/useDashboardComponent.ts +27 -0
  144. package/composables/dashboard/useSaveDashboard.ts +21 -0
  145. package/composables/document/useCreateNamespace.ts +26 -0
  146. package/composables/document/useDatabases.ts +23 -0
  147. package/composables/document/useDocument.ts +29 -0
  148. package/composables/document/useDocumentUrl.ts +20 -0
  149. package/composables/document/useDocuments.ts +107 -0
  150. package/composables/document/useNodes.ts +29 -0
  151. package/composables/document/useSummaryNodes.ts +32 -0
  152. package/composables/document/useUpdateNamespace.ts +22 -0
  153. package/composables/evaluation/useCreateDataset.ts +19 -0
  154. package/composables/evaluation/useDataset.ts +26 -0
  155. package/composables/evaluation/useDatasets.ts +25 -0
  156. package/composables/evaluation/useUpdateDataset.ts +23 -0
  157. package/composables/event/useBasicEventStatistics.ts +83 -0
  158. package/composables/event/useEventColor.ts +25 -0
  159. package/composables/event/useEventComponent.ts +87 -0
  160. package/composables/event/useEventTimeseries.ts +39 -0
  161. package/composables/event/useEventTimeseriesStats.ts +26 -0
  162. package/composables/file/useFileUpload.ts +91 -0
  163. package/composables/file/useSupportedFileTypes.ts +22 -0
  164. package/composables/form/useCreateInstanceForm.ts +251 -0
  165. package/composables/form/useFormKitTransform.ts +753 -0
  166. package/composables/memory/useMemoryCRUD.ts +88 -0
  167. package/composables/memory/useMemoryFactory.ts +319 -0
  168. package/composables/memory/useMemorySearchFilter.ts +74 -0
  169. package/composables/models/useModelsList.ts +24 -0
  170. package/composables/models/useSingleModel.ts +30 -0
  171. package/composables/notification/useNotificationPoller.ts +58 -0
  172. package/composables/notification/useNotifications.ts +57 -0
  173. package/composables/notification/useUpdateMultipleNotifications.ts +17 -0
  174. package/composables/notification/useUpdateNotification.ts +17 -0
  175. package/composables/process/useCreateProcessInstance.ts +32 -0
  176. package/composables/process/useDeleteProcessInstance.ts +31 -0
  177. package/composables/process/useProcessClasses.ts +27 -0
  178. package/composables/process/useProcessInstance.ts +28 -0
  179. package/composables/process/useProcessInstances.ts +27 -0
  180. package/composables/process/useProcessWalkthroughs.ts +73 -0
  181. package/composables/process/useSendProcessStartForm.ts +43 -0
  182. package/composables/process/useUpdateProcessInstance.ts +40 -0
  183. package/composables/role/useCreateRole.ts +19 -0
  184. package/composables/role/useDeleteRole.ts +21 -0
  185. package/composables/role/useRole.ts +30 -0
  186. package/composables/role/useRoles.ts +25 -0
  187. package/composables/role/useUpdateRole.ts +22 -0
  188. package/composables/suite/useApps.ts +31 -0
  189. package/composables/suite/useSuite.ts +26 -0
  190. package/composables/tenant/useActiveTenant.ts +27 -0
  191. package/composables/tenant/useSysadminNavigation.ts +19 -0
  192. package/composables/tenant/useTenant.ts +38 -0
  193. package/composables/tenant/useTenantMemberships.ts +15 -0
  194. package/composables/tenant/useTenantPath.ts +20 -0
  195. package/composables/tenant/useTenantPolling.ts +30 -0
  196. package/composables/tenant/useTenantReady.ts +12 -0
  197. package/composables/theme/useDarkMode.ts +5 -0
  198. package/composables/thread/useThread.ts +27 -0
  199. package/composables/thread/useThreadEvents.ts +91 -0
  200. package/composables/thread/useThreadUtils.ts +49 -0
  201. package/composables/thread/useThreads.ts +64 -0
  202. package/composables/thread/useThreadsInfinite.ts +56 -0
  203. package/composables/translation/useTranslate.ts +20 -0
  204. package/composables/useRouteReady.ts +21 -0
  205. package/composables/useTimeAgo.ts +40 -0
  206. package/composables/user/useAssignRoleToUser.ts +22 -0
  207. package/composables/user/useMyUser.ts +25 -0
  208. package/composables/user/useRevokeRoleFromUser.ts +21 -0
  209. package/composables/user/useUser.ts +30 -0
  210. package/composables/user/useUsers.ts +63 -0
  211. package/composables/utils/useJsonTree.ts +138 -0
  212. package/formkit.config.ts +44 -0
  213. package/i18n/locales/de.yaml +815 -0
  214. package/i18n/locales/en.yaml +804 -0
  215. package/i18n/locales/fr.yaml +812 -0
  216. package/i18n/locales/it.yaml +808 -0
  217. package/layouts/anonymous.vue +8 -0
  218. package/layouts/default.vue +116 -0
  219. package/middleware/auth.global.ts +62 -0
  220. package/nuxt.config.ts +145 -0
  221. package/package.json +114 -0
  222. package/pages/[tenant]/index.vue +31 -0
  223. package/pages/[tenant]/notifications/index.vue +235 -0
  224. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/chat.vue +67 -0
  225. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/configuration.vue +122 -0
  226. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories/[memory_id].vue +3 -0
  227. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories.vue +20 -0
  228. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/overview.vue +72 -0
  229. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/threads.vue +52 -0
  230. package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/workflow.vue +19 -0
  231. package/pages/[tenant]/service/agents/[agent_class]-[agent_id].vue +63 -0
  232. package/pages/[tenant]/service/agents/templates.vue +102 -0
  233. package/pages/[tenant]/service/agents.vue +185 -0
  234. package/pages/[tenant]/service/datasets/[dataset_id].vue +81 -0
  235. package/pages/[tenant]/service/datasets.vue +53 -0
  236. package/pages/[tenant]/service/health/index.vue +3 -0
  237. package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/nodes.vue +20 -0
  238. package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/overview.vue +40 -0
  239. package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/summary.vue +88 -0
  240. package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id].vue +48 -0
  241. package/pages/[tenant]/service/knowledge/[db]/[namespace].vue +144 -0
  242. package/pages/[tenant]/service/knowledge.vue +126 -0
  243. package/pages/[tenant]/service/models/[model_name].vue +84 -0
  244. package/pages/[tenant]/service/models.vue +61 -0
  245. package/pages/[tenant]/service/my-account.vue +117 -0
  246. package/pages/[tenant]/service/openai/[thread_id]/[display_id]/memories.vue +66 -0
  247. package/pages/[tenant]/service/openai/[thread_id]/[display_id]/sources.vue +100 -0
  248. package/pages/[tenant]/service/openai/[thread_id]/[display_id]/tracing.vue +49 -0
  249. package/pages/[tenant]/service/openai.vue +101 -0
  250. package/pages/[tenant]/service/organization-memories/graph.vue +97 -0
  251. package/pages/[tenant]/service/organization-memories/list/[memory_id].vue +3 -0
  252. package/pages/[tenant]/service/organization-memories/list.vue +150 -0
  253. package/pages/[tenant]/service/organization-memories.vue +3 -0
  254. package/pages/[tenant]/service/processes/[process_class]-[process_id]/[process_walkthrough_id].vue +7 -0
  255. package/pages/[tenant]/service/processes/[process_class]-[process_id]/configuration.vue +106 -0
  256. package/pages/[tenant]/service/processes/[process_class]-[process_id]/overview.vue +67 -0
  257. package/pages/[tenant]/service/processes/[process_class]-[process_id]/start.vue +26 -0
  258. package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs/[process_walkthrough_id]/overview.vue +14 -0
  259. package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs.vue +54 -0
  260. package/pages/[tenant]/service/processes/[process_class]-[process_id].vue +60 -0
  261. package/pages/[tenant]/service/processes.vue +129 -0
  262. package/pages/[tenant]/service/roles/[role_id].vue +54 -0
  263. package/pages/[tenant]/service/roles.vue +84 -0
  264. package/pages/[tenant]/service/threads/[thread_id]/chat.vue +51 -0
  265. package/pages/[tenant]/service/threads/[thread_id]/display/[display_id].vue +21 -0
  266. package/pages/[tenant]/service/threads/[thread_id]/display.vue +29 -0
  267. package/pages/[tenant]/service/threads/[thread_id]/hierarchy.vue +14 -0
  268. package/pages/[tenant]/service/threads/[thread_id]/memories/[memory_id].vue +3 -0
  269. package/pages/[tenant]/service/threads/[thread_id]/memories.vue +19 -0
  270. package/pages/[tenant]/service/threads/[thread_id]/overview.vue +100 -0
  271. package/pages/[tenant]/service/threads/[thread_id].vue +54 -0
  272. package/pages/[tenant]/service/threads.vue +52 -0
  273. package/pages/[tenant]/service/user-memories/graph.vue +97 -0
  274. package/pages/[tenant]/service/user-memories/list/[memory_id].vue +3 -0
  275. package/pages/[tenant]/service/user-memories/list.vue +150 -0
  276. package/pages/[tenant]/service/user-memories.vue +3 -0
  277. package/pages/[tenant]/service/users/[user_id].vue +117 -0
  278. package/pages/[tenant]/service/users.vue +88 -0
  279. package/pages/auth/callback.vue +52 -0
  280. package/pages/auth/login.vue +80 -0
  281. package/pages/auth/renew.vue +24 -0
  282. package/pages/index.vue +59 -0
  283. package/pages/select-tenant.vue +76 -0
  284. package/plugins/0.runtime-config.client.ts +55 -0
  285. package/plugins/apexcharts.client.ts +5 -0
  286. package/plugins/api-client.client.ts +38 -0
  287. package/plugins/dark-mode.client.ts +12 -0
  288. package/plugins/keycloak-client.ts +41 -0
  289. package/plugins/oidc-client.ts +78 -0
  290. package/sdk/client/client/client.gen.ts +237 -0
  291. package/sdk/client/client/index.ts +24 -0
  292. package/sdk/client/client/types.gen.ts +213 -0
  293. package/sdk/client/client/utils.gen.ts +407 -0
  294. package/sdk/client/client.gen.ts +25 -0
  295. package/sdk/client/core/auth.gen.ts +42 -0
  296. package/sdk/client/core/bodySerializer.gen.ts +96 -0
  297. package/sdk/client/core/params.gen.ts +181 -0
  298. package/sdk/client/core/pathSerializer.gen.ts +180 -0
  299. package/sdk/client/core/queryKeySerializer.gen.ts +136 -0
  300. package/sdk/client/core/serverSentEvents.gen.ts +265 -0
  301. package/sdk/client/core/types.gen.ts +118 -0
  302. package/sdk/client/core/utils.gen.ts +143 -0
  303. package/sdk/client/index.ts +1013 -0
  304. package/sdk/client/schemas.gen.ts +35395 -0
  305. package/sdk/client/sdk.gen.ts +3438 -0
  306. package/sdk/client/transformers.gen.ts +143 -0
  307. package/sdk/client/types.gen.ts +27567 -0
  308. package/tailwind.config.mjs +27 -0
  309. package/themes/aihub-theme.ts +125 -0
  310. package/types/DashboardWidget.ts +13 -0
  311. package/types/EventChartInput.ts +7 -0
  312. package/types/NavItem.ts +6 -0
  313. package/types/TimeseriesInput.ts +7 -0
@@ -0,0 +1,307 @@
1
+ <template>
2
+ <div class="flex flex-col gap-4">
3
+ <!-- Agent Class Selection -->
4
+ <div>
5
+ <label
6
+ for="agent-class-select"
7
+ class="mb-1 block text-sm font-medium"
8
+ >
9
+ {{ t('agent.selector.class.label') }}
10
+ </label>
11
+ <Select
12
+ v-model="selectedClass"
13
+ input-id="agent-class-select"
14
+ :options="filteredClassOptions"
15
+ option-label="displayName"
16
+ option-value="name"
17
+ :placeholder="classPlaceholder ?? t('agent.selector.class.placeholder')"
18
+ :filter="filter"
19
+ :loading="isLoading"
20
+ class="w-full"
21
+ >
22
+ <template #option="{ option }">
23
+ <div class="flex items-center gap-2">
24
+ <Icon
25
+ :name="option.icon || 'mage:robot'"
26
+ size="1.2em"
27
+ />
28
+ <span>{{ option.displayName }}</span>
29
+ </div>
30
+ </template>
31
+ <template #value="{ value }">
32
+ <div
33
+ v-if="value"
34
+ class="flex items-center gap-2"
35
+ >
36
+ <Icon
37
+ :name="getClassIcon(value)"
38
+ size="1.2em"
39
+ />
40
+ <span>{{ getClassDisplayName(value) }}</span>
41
+ </div>
42
+ </template>
43
+ </Select>
44
+ </div>
45
+
46
+ <!-- Agent ID Selection (shown when class selected) -->
47
+ <div v-if="selectedClass">
48
+ <label
49
+ for="agent-id-select"
50
+ class="mb-1 block text-sm font-medium"
51
+ >
52
+ {{ t('agent.selector.id.label') }}
53
+ </label>
54
+ <Select
55
+ v-model="selectedId"
56
+ input-id="agent-id-select"
57
+ :options="idOptions"
58
+ option-label="displayName"
59
+ option-value="id"
60
+ :placeholder="idPlaceholder ?? t('agent.selector.id.placeholder')"
61
+ :filter="filter"
62
+ :loading="isLoadingInstances"
63
+ class="w-full"
64
+ >
65
+ <template #option="{ option }">
66
+ <div class="flex items-center gap-2">
67
+ <Icon
68
+ :name="option.icon || 'mage:user'"
69
+ size="1.2em"
70
+ />
71
+ <span>{{ option.displayName }}</span>
72
+ </div>
73
+ </template>
74
+ <template #value="{ value }">
75
+ <div
76
+ v-if="value"
77
+ class="flex items-center gap-2"
78
+ >
79
+ <Icon
80
+ :name="getIdIcon(value)"
81
+ size="1.2em"
82
+ />
83
+ <span>{{ getIdDisplayName(value) }}</span>
84
+ </div>
85
+ </template>
86
+ </Select>
87
+ <small class="mt-1 text-surface-500">
88
+ {{ t('agent.selector.id.help') }}
89
+ </small>
90
+ </div>
91
+ </div>
92
+ </template>
93
+
94
+ <script setup lang="ts">
95
+ import { getAgentClasses, getAgentClassInstances } from '@core/sdk/client'
96
+ import { useChangeCase } from '@vueuse/integrations/useChangeCase'
97
+
98
+ import type { AgentClassDto, FullAgentInstanceDto, LocaleString } from '@core/sdk/client'
99
+
100
+ /**
101
+ * Extracts the localized string from a LocaleString object.
102
+ * Falls back to first available value if the requested locale is not available.
103
+ */
104
+ function getLocalizedValue(localeString: LocaleString | string | undefined, locale: string): string {
105
+ if (!localeString) return ''
106
+ if (typeof localeString === 'string') return localeString
107
+
108
+ // LocaleString object - try to get the current locale, fallback to en, then any
109
+ return (localeString as Record<string, string>)[locale]
110
+ || (localeString as Record<string, string>).en
111
+ || Object.values(localeString)[0]
112
+ || ''
113
+ }
114
+
115
+ interface AgentSelectorValue {
116
+ agent_class: string
117
+ agent_id: string
118
+ }
119
+
120
+ interface ClassOption {
121
+ name: string
122
+ displayName: string
123
+ icon: string
124
+ }
125
+
126
+ interface IdOption {
127
+ id: string
128
+ displayName: string
129
+ icon: string
130
+ }
131
+
132
+ interface AgentSelectorProps {
133
+ context: {
134
+ node: {
135
+ input: (value: AgentSelectorValue | null) => void
136
+ }
137
+ value?: AgentSelectorValue | null
138
+ attrs: Record<string, unknown>
139
+ startEvent?: string
140
+ classPlaceholder?: string
141
+ idPlaceholder?: string
142
+ filter?: boolean
143
+ }
144
+ }
145
+
146
+ const props = defineProps<AgentSelectorProps>()
147
+ const { t, locale } = useI18n()
148
+ const { tenantId } = useTenant()
149
+
150
+ // Get custom props from context (FormKit passes them there, not as direct props)
151
+ const startEvent = computed(() => props.context.startEvent)
152
+ const classPlaceholder = computed(() => props.context.classPlaceholder)
153
+ const idPlaceholder = computed(() => props.context.idPlaceholder)
154
+ const filter = computed(() => props.context.filter ?? true)
155
+
156
+ // State
157
+ const agentClasses = ref<AgentClassDto[]>([])
158
+ const agentInstances = ref<FullAgentInstanceDto[]>([])
159
+ const isLoading = ref(false)
160
+ const isLoadingInstances = ref(false)
161
+
162
+ // Get current value from context
163
+ const currentValue = computed(() => props.context.value ?? null)
164
+
165
+ // Selected class (computed property that syncs with the form value)
166
+ const selectedClass = computed({
167
+ get: () => currentValue.value?.agent_class ?? null,
168
+ set: (value: string | null) => {
169
+ if (value) {
170
+ // When class changes, reset agent ID and fetch instances
171
+ emitValue(value, '')
172
+ fetchInstances(value)
173
+ }
174
+ else {
175
+ props.context.node.input(null)
176
+ agentInstances.value = []
177
+ }
178
+ },
179
+ })
180
+
181
+ // Selected agent ID (computed property that syncs with the form value)
182
+ const selectedId = computed({
183
+ get: () => currentValue.value?.agent_id ?? null,
184
+ set: (value: string | null) => {
185
+ if (selectedClass.value && value) {
186
+ emitValue(selectedClass.value, value)
187
+ }
188
+ },
189
+ })
190
+
191
+ // Emit complete value object
192
+ function emitValue(agentClass: string, agentId: string) {
193
+ props.context.node.input({
194
+ agent_class: agentClass,
195
+ agent_id: agentId,
196
+ })
197
+ }
198
+
199
+ // Class options for select
200
+ const classOptions = computed<ClassOption[]>(() =>
201
+ agentClasses.value.map(cls => ({
202
+ name: cls.agent_class,
203
+ displayName: getLocalizedValue(cls.name, locale.value) || useChangeCase(cls.agent_class, 'capitalCase'),
204
+ icon: cls.icon || 'mage:robot',
205
+ })),
206
+ )
207
+
208
+ // Filtered class options based on startEvent
209
+ const filteredClassOptions = computed<ClassOption[]>(() => {
210
+ if (!startEvent.value) return classOptions.value // No filter = show all
211
+
212
+ return classOptions.value.filter((classOption) => {
213
+ const agentClass = agentClasses.value.find(c => c.agent_class === classOption.name)
214
+ if (!agentClass) return false
215
+
216
+ // Check if any start_event matches the filter
217
+ return agentClass.start_events.some(event =>
218
+ event.event_name === startEvent.value
219
+ || event.event_parents.includes(startEvent.value!),
220
+ )
221
+ })
222
+ })
223
+
224
+ // ID options based on selected class
225
+ const idOptions = computed<IdOption[]>(() => {
226
+ return agentInstances.value.map(instance => ({
227
+ id: instance.agent_config.agent_id,
228
+ displayName: instance.agent_config.name || instance.agent_config.agent_id,
229
+ icon: instance.agent_config.icon || 'mage:user',
230
+ }))
231
+ })
232
+
233
+ function getClassIcon(name: string): string {
234
+ const option = classOptions.value.find(opt => opt.name === name)
235
+ return option?.icon ?? 'mage:robot'
236
+ }
237
+
238
+ function getClassDisplayName(name: string): string {
239
+ const option = classOptions.value.find(opt => opt.name === name)
240
+ return option?.displayName ?? name
241
+ }
242
+
243
+ function getIdIcon(id: string): string {
244
+ const option = idOptions.value.find(opt => opt.id === id)
245
+ return option?.icon ?? 'mage:user'
246
+ }
247
+
248
+ function getIdDisplayName(id: string): string {
249
+ const option = idOptions.value.find(opt => opt.id === id)
250
+ return option?.displayName ?? id
251
+ }
252
+
253
+ async function fetchClasses() {
254
+ isLoading.value = true
255
+ try {
256
+ const response = await getAgentClasses({
257
+ composable: '$fetch',
258
+ path: { tenant_id: tenantId.value! },
259
+ })
260
+ agentClasses.value = response
261
+ }
262
+ catch (error) {
263
+ console.error('Failed to fetch agent classes:', error)
264
+ agentClasses.value = []
265
+ }
266
+ finally {
267
+ isLoading.value = false
268
+ }
269
+ }
270
+
271
+ async function fetchInstances(agentClass: string) {
272
+ isLoadingInstances.value = true
273
+ try {
274
+ const response = await getAgentClassInstances({
275
+ composable: '$fetch',
276
+ path: { tenant_id: tenantId.value!, agent_class: agentClass },
277
+ })
278
+ agentInstances.value = response
279
+ }
280
+ catch (error) {
281
+ console.error(`Failed to fetch instances for class "${agentClass}":`, error)
282
+ agentInstances.value = []
283
+ }
284
+ finally {
285
+ isLoadingInstances.value = false
286
+ }
287
+ }
288
+
289
+ // Fetch classes on mount
290
+ onMounted(() => {
291
+ fetchClasses()
292
+
293
+ // If there's already a selected class, fetch its instances
294
+ if (currentValue.value?.agent_class) {
295
+ fetchInstances(currentValue.value.agent_class)
296
+ }
297
+ })
298
+
299
+ // Refetch if startEvent changes
300
+ watch(startEvent, () => {
301
+ // Clear selection if current class no longer matches filter
302
+ if (selectedClass.value && !filteredClassOptions.value.some(opt => opt.name === selectedClass.value)) {
303
+ props.context.node.input(null)
304
+ agentInstances.value = []
305
+ }
306
+ })
307
+ </script>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <div class="flex flex-col gap-2">
3
+ <InputText
4
+ v-model="draft"
5
+ :input-id="inputId"
6
+ :placeholder="placeholder"
7
+ class="w-full"
8
+ @keydown.enter.stop.prevent="commitDraft"
9
+ @keyup.enter.stop.prevent
10
+ @keypress.enter.stop.prevent
11
+ @blur="commitDraft"
12
+ />
13
+ <div
14
+ v-if="chips.length > 0"
15
+ class="flex flex-wrap gap-2"
16
+ >
17
+ <Chip
18
+ v-for="value in chips"
19
+ :key="value"
20
+ :label="value"
21
+ removable
22
+ @remove="removeChip(value)"
23
+ />
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ interface ChipsInputProps {
30
+ context: {
31
+ node: { input: (value: string[]) => void }
32
+ value?: string[] | null
33
+ placeholder?: string
34
+ inputId?: string
35
+ }
36
+ }
37
+
38
+ const props = defineProps<ChipsInputProps>()
39
+
40
+ const placeholder = computed(() => props.context.placeholder)
41
+ const inputId = computed(() => props.context.inputId)
42
+ const draft = ref('')
43
+
44
+ const chips = computed<string[]>({
45
+ get: () => props.context.value ?? [],
46
+ set: (value: string[]) => props.context.node.input(value),
47
+ })
48
+
49
+ function commitDraft() {
50
+ const trimmed = draft.value.trim()
51
+ draft.value = ''
52
+ if (!trimmed)
53
+ return
54
+ if (chips.value.includes(trimmed))
55
+ return
56
+ chips.value = [...chips.value, trimmed]
57
+ }
58
+
59
+ function removeChip(value: string) {
60
+ chips.value = chips.value.filter(v => v !== value)
61
+ }
62
+ </script>
@@ -0,0 +1,155 @@
1
+ <template>
2
+ <div class="content">
3
+ <FormKit
4
+ id="form"
5
+ v-model="data"
6
+ type="form"
7
+ :submit-label="t('common.actions.save')"
8
+ :submit-attrs="{
9
+ inputClass: 'p-button p-component w-full',
10
+ }"
11
+ :config="{
12
+ validationVisibility: 'blur',
13
+ }"
14
+ @submit="submitHandler"
15
+ >
16
+ <FormKitSchema
17
+ :schema="schema"
18
+ :data="{ ...data }"
19
+ />
20
+
21
+ <!-- Render repeaters separately (not supported by FormKit standard) -->
22
+ <FormKitRepeater
23
+ v-for="rep in repeaterElements"
24
+ :key="rep.path"
25
+ :model-value="getRepeaterData(rep.path)"
26
+ :name="rep.name"
27
+ :label="rep.label"
28
+ :add-label="rep.addLabel"
29
+ :children-schema="rep.childrenSchema"
30
+ :min="rep.min"
31
+ :max="rep.max"
32
+ @update:model-value="setRepeaterData(rep.path, $event)"
33
+ />
34
+ </FormKit>
35
+ </div>
36
+ </template>
37
+
38
+ <script setup lang="ts">
39
+ import {
40
+ buildFormKitSchema,
41
+ coerceNullableToggles,
42
+ extractRepeaterConfigs,
43
+ getNestedValue,
44
+ normalizeFormLocaleStrings,
45
+ seedFormDefaults,
46
+ seedNullableToggles,
47
+ setNestedValue,
48
+ type FormElement,
49
+ type RepeaterConfig,
50
+ } from '@core/composables/form/useFormKitTransform'
51
+ import { merge } from 'lodash-es'
52
+
53
+ import type { FormkitElement } from '@core/sdk/client'
54
+ import type { FormKitSchemaDefinition } from '@formkit/core'
55
+
56
+ const { t } = useI18n()
57
+
58
+ const props = defineProps<{
59
+ form: FormkitElement[]
60
+ initialData?: Record<string, unknown>
61
+ }>()
62
+
63
+ function hydrate(raw: Record<string, unknown>): Record<string, unknown> {
64
+ const seeded = seedNullableToggles(raw, props.form as FormElement[])
65
+ return seedFormDefaults(seeded, props.form as FormElement[])
66
+ }
67
+
68
+ const data = ref<Record<string, unknown>>(hydrate(props.initialData || {}))
69
+
70
+ watch(() => props.initialData, (newData) => {
71
+ if (newData && Object.keys(newData).length > 0) {
72
+ data.value = merge({}, data.value, hydrate(newData))
73
+ }
74
+ }, { deep: true })
75
+
76
+ const emit = defineEmits<{
77
+ submit: [Record<string, unknown>]
78
+ }>()
79
+
80
+ function createLabelPattern(): RegExp {
81
+ const keys = Object.keys(data.value)
82
+ if (keys.length === 0) return /(?!)/ // Never matches
83
+ return new RegExp(keys.map(key => `\\$${key}`).join('|'), 'g')
84
+ }
85
+
86
+ function replaceLabelVariables(label: string): string {
87
+ const pattern = createLabelPattern()
88
+ return label.replace(pattern, (match: string) => {
89
+ const key = match.substring(1)
90
+ return (data.value[key] as string) || match
91
+ })
92
+ }
93
+
94
+ const schema = computed<FormKitSchemaDefinition>(() => {
95
+ return buildFormKitSchema(props.form as FormElement[], {
96
+ labelTransform: replaceLabelVariables,
97
+ })
98
+ })
99
+
100
+ const repeaterElements = computed<RepeaterConfig[]>(() => {
101
+ return extractRepeaterConfigs(props.form as FormElement[])
102
+ })
103
+
104
+ function getRepeaterData(path: string): Record<string, unknown>[] {
105
+ return getNestedValue(data.value, path)
106
+ }
107
+
108
+ function setRepeaterData(path: string, value: Record<string, unknown>[]): void {
109
+ setNestedValue(data.value, path, value)
110
+ }
111
+
112
+ async function submitHandler() {
113
+ const coerced = coerceNullableToggles(data.value, props.form as FormElement[])
114
+ const normalizedData = normalizeFormLocaleStrings(coerced)
115
+ emit('submit', normalizedData)
116
+ }
117
+ </script>
118
+
119
+ <style scoped>
120
+ .content {
121
+ @apply font-light text-xs
122
+ }
123
+
124
+ .content :deep(form) {
125
+ @apply gap-6;
126
+ }
127
+
128
+ .content :deep(.formkit-help) {
129
+ @apply text-xs font-light text-surface-500 dark:text-surface-400;
130
+ }
131
+
132
+ .content :deep(.formkit-outer) {
133
+ @apply pt-3 pb-1;
134
+ }
135
+
136
+ .content :deep(.formkit-group-fieldset) {
137
+ @apply border border-surface-300 dark:border-surface-600 rounded-lg p-4 mb-4;
138
+ }
139
+
140
+ .content :deep(.formkit-group-fieldset legend) {
141
+ @apply text-sm font-semibold px-2 text-surface-700 dark:text-surface-300;
142
+ }
143
+
144
+ .content :deep(.formkit-group-fieldset .formkit-group-fieldset) {
145
+ @apply ml-2 mt-2;
146
+ }
147
+
148
+ .content :deep(.formkit-slider-value-input) {
149
+ @apply w-20;
150
+ }
151
+
152
+ .content :deep(.formkit-slider-value-input .p-inputnumber-input) {
153
+ @apply text-center text-sm;
154
+ }
155
+ </style>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="flex items-center gap-3">
3
+ <!-- Icon preview (fixed width to prevent layout shift) -->
4
+ <div class="flex w-8 shrink-0 items-center justify-center">
5
+ <Icon
6
+ v-if="selectedIcon"
7
+ :name="selectedIcon"
8
+ class="text-2xl text-surface-700 dark:text-surface-200"
9
+ />
10
+ <Icon
11
+ v-else
12
+ name="mage:image"
13
+ class="text-2xl text-surface-300 dark:text-surface-600"
14
+ />
15
+ </div>
16
+
17
+ <!-- Editable Select -->
18
+ <Select
19
+ v-model="selectedIcon"
20
+ :options="iconOptions"
21
+ :editable="true"
22
+ :placeholder="placeholder"
23
+ option-label="name"
24
+ option-value="name"
25
+ class="grow"
26
+ >
27
+ <!-- Option template - shows icon + name for each option -->
28
+ <template #option="{ option }">
29
+ <div class="flex items-center gap-2">
30
+ <Icon
31
+ :name="option.name"
32
+ class="shrink-0 text-lg"
33
+ />
34
+ <span>{{ option.name }}</span>
35
+ </div>
36
+ </template>
37
+ </Select>
38
+ </div>
39
+ </template>
40
+
41
+ <script setup lang="ts">
42
+ interface IconSelectorProps {
43
+ context: {
44
+ node: {
45
+ input: (value: string) => void
46
+ }
47
+ value?: string
48
+ attrs: Record<string, unknown>
49
+ options?: string[]
50
+ placeholder?: string
51
+ }
52
+ }
53
+
54
+ const props = defineProps<IconSelectorProps>()
55
+
56
+ // Get options from context (passed from backend)
57
+ const options = computed(() => props.context.options ?? [])
58
+ const placeholder = computed(() => props.context.placeholder ?? 'Select or enter an icon...')
59
+
60
+ // Convert string options to objects for Select component
61
+ const iconOptions = computed(() =>
62
+ options.value.map(name => ({ name })),
63
+ )
64
+
65
+ // Current selected icon value
66
+ const selectedIcon = computed({
67
+ get: () => props.context.value ?? '',
68
+ set: (newVal: string) => {
69
+ props.context.node.input(newVal || '')
70
+ },
71
+ })
72
+ </script>
@@ -0,0 +1,92 @@
1
+ <template>
2
+ <div>
3
+ <MultiSelect
4
+ v-model="selectedDatabases"
5
+ :options="databaseOptions"
6
+ option-label="displayName"
7
+ option-value="name"
8
+ :placeholder="placeholder ?? t('common.selectDatabases')"
9
+ :filter="filter"
10
+ display="chip"
11
+ class="w-full"
12
+ :loading="isLoading"
13
+ >
14
+ <template #option="{ option }">
15
+ <div class="flex items-center gap-2">
16
+ <Icon
17
+ name="mage:database"
18
+ size="1.2em"
19
+ />
20
+ <span>{{ option.displayName }}</span>
21
+ </div>
22
+ </template>
23
+ </MultiSelect>
24
+ </div>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { getDatabases } from '@core/sdk/client'
29
+ import { useChangeCase } from '@vueuse/integrations/useChangeCase'
30
+
31
+ import type { DatabaseDto } from '@core/sdk/client'
32
+
33
+ interface DatabaseOption {
34
+ name: string
35
+ displayName: string
36
+ }
37
+
38
+ interface KnowledgeDatabaseSelectorProps {
39
+ context: {
40
+ node: { input: (value: string[] | null) => void }
41
+ value?: string[] | null
42
+ placeholder?: string
43
+ filter?: boolean
44
+ }
45
+ }
46
+
47
+ const props = defineProps<KnowledgeDatabaseSelectorProps>()
48
+ const { t } = useI18n()
49
+ const { tenantId } = useTenant()
50
+
51
+ const placeholder = computed(() => props.context.placeholder)
52
+ const filter = computed(() => props.context.filter ?? true)
53
+
54
+ const databases = ref<DatabaseDto[]>([])
55
+ const isLoading = ref(false)
56
+
57
+ const selectedDatabases = computed({
58
+ get: () => props.context.value ?? [],
59
+ set: (value: string[]) => {
60
+ props.context.node.input(value.length > 0 ? value : null)
61
+ },
62
+ })
63
+
64
+ const databaseOptions = computed<DatabaseOption[]>(() =>
65
+ databases.value.map(db => ({
66
+ name: db.name,
67
+ displayName: db.display_name || useChangeCase(db.name, 'capitalCase').value,
68
+ })),
69
+ )
70
+
71
+ async function fetchDatabases() {
72
+ isLoading.value = true
73
+ try {
74
+ const response = await getDatabases({
75
+ composable: '$fetch',
76
+ path: { tenant_id: tenantId.value! },
77
+ })
78
+ databases.value = response
79
+ }
80
+ catch (error) {
81
+ console.error('Failed to fetch databases:', error)
82
+ databases.value = []
83
+ }
84
+ finally {
85
+ isLoading.value = false
86
+ }
87
+ }
88
+
89
+ onMounted(() => {
90
+ fetchDatabases()
91
+ })
92
+ </script>