@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,241 @@
1
+ <template>
2
+ <div class="flex h-full flex-col space-y-4">
3
+ <div class="flex-1 space-y-4 overflow-y-auto">
4
+ <div class="space-y-2">
5
+ <label
6
+ for="memory-content-textarea"
7
+ class="text-xs font-medium text-gray-700 dark:text-gray-500"
8
+ >{{ t('memory.edit.memory_content_label') }}</label>
9
+ <Textarea
10
+ v-if="isEditing"
11
+ v-model="editedData"
12
+ input-id="memory-content-textarea"
13
+ auto-resize
14
+ rows="5"
15
+ class="w-full"
16
+ />
17
+ <div
18
+ v-else
19
+ class="rounded border bg-surface-50 p-3 dark:border-surface-800 dark:bg-surface-950"
20
+ >
21
+ {{ memory.memory }}
22
+ </div>
23
+ </div>
24
+
25
+ <div class="space-y-4">
26
+ <!-- Created At - always shown -->
27
+ <div class="space-y-2">
28
+ <p class="text-xs font-medium text-gray-500">
29
+ {{ t('memory.detail.created_at') }}
30
+ </p>
31
+ <div class="text-sm">
32
+ {{ new Date(memory.created_at).toLocaleString() }}
33
+ </div>
34
+ </div>
35
+
36
+ <!-- Agent Link - shown if agent exists -->
37
+ <!-- Follows the AgentAvatar pattern from Thread/Info.vue but simplified -->
38
+ <div
39
+ v-if="canNavigateToAgent"
40
+ class="space-y-2"
41
+ >
42
+ <p class="text-xs font-medium text-gray-500">
43
+ {{ t('memory.detail.agent_link_label') }}
44
+ </p>
45
+ <div
46
+ class="flex cursor-pointer gap-2 rounded border border-surface-200 p-2 hover:bg-surface-100 dark:border-surface-800 hover:dark:bg-surface-800"
47
+ @click="navigateToAgent"
48
+ >
49
+ <Avatar
50
+ size="normal"
51
+ icon="pi pi-verified"
52
+ />
53
+ <div class="mb-1 flex flex-col justify-center">
54
+ <p class="text-xs font-bold">
55
+ {{ parsedAgent.agent_class }}
56
+ </p>
57
+ <p class="text-xs">
58
+ {{ parsedAgent.agent_class }} / {{ parsedAgent.agent_id }}
59
+ </p>
60
+ </div>
61
+ </div>
62
+ </div>
63
+
64
+ <!-- Thread/Display Link - shown if both thread_id and display_id exist -->
65
+ <!-- Similar pattern to agent but with thread/conversation icon -->
66
+ <div
67
+ v-if="canNavigateToThread"
68
+ class="space-y-2"
69
+ >
70
+ <p class="text-xs font-medium text-gray-500">
71
+ {{ t('memory.detail.thread_link_label') }}
72
+ </p>
73
+ <div
74
+ class="flex cursor-pointer gap-2 rounded border border-surface-200 p-2 hover:bg-surface-100 dark:border-surface-800 hover:dark:bg-surface-800"
75
+ @click="navigateToThreadDisplay"
76
+ >
77
+ <Avatar
78
+ size="normal"
79
+ icon="pi pi-comments"
80
+ />
81
+ <div class="mb-1 flex flex-col justify-center">
82
+ <p class="text-xs font-bold">
83
+ {{ t('memory.detail.thread_title') }}
84
+ </p>
85
+ <p class="font-mono text-xs">
86
+ {{ memory.thread_id?.substring(0, 8) }}... / {{ memory.display_id?.substring(0, 8) }}...
87
+ </p>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+
94
+ <div class="flex items-center justify-between border-t pt-4">
95
+ <Button
96
+ v-if="!isEditing"
97
+ :label="t('memory.edit.edit_button')"
98
+ icon="pi pi-pencil"
99
+ @click="isEditing = true"
100
+ />
101
+ <div
102
+ v-else
103
+ class="flex space-x-2"
104
+ >
105
+ <Button
106
+ :label="t('memory.edit.save_button')"
107
+ icon="pi pi-check"
108
+ @click="handleSave"
109
+ />
110
+ <Button
111
+ :label="t('memory.edit.cancel_button')"
112
+ icon="pi pi-times"
113
+ severity="secondary"
114
+ @click="handleCancel"
115
+ />
116
+ </div>
117
+
118
+ <Button
119
+ :label="t('memory.edit.delete_button')"
120
+ icon="pi pi-trash"
121
+ severity="danger"
122
+ @click="handleDelete"
123
+ />
124
+ </div>
125
+ </div>
126
+ </template>
127
+
128
+ <script setup lang="ts">
129
+ import Avatar from 'primevue/avatar'
130
+ import { useConfirm } from 'primevue/useconfirm'
131
+ import { useToast } from 'primevue/usetoast'
132
+ import { computed, ref, watch } from 'vue'
133
+
134
+ import type { MemoryDto } from '@core/sdk/client'
135
+
136
+ interface Props {
137
+ memory: MemoryDto
138
+ }
139
+
140
+ const props = defineProps<Props>()
141
+
142
+ const emit = defineEmits<{
143
+ update: [data: string]
144
+ delete: []
145
+ close: []
146
+ }>()
147
+
148
+ const confirm = useConfirm()
149
+ const toast = useToast()
150
+ const { t } = useI18n()
151
+ const router = useRouter()
152
+ const tenantPath = useTenantPath()
153
+
154
+ const editedData = ref('')
155
+ const isEditing = ref(false)
156
+
157
+ watch(() => props.memory, (newMemory) => {
158
+ editedData.value = newMemory.memory
159
+ isEditing.value = false
160
+ }, { immediate: true })
161
+
162
+ const handleSave = () => {
163
+ if (!editedData.value.trim()) {
164
+ toast.add({
165
+ severity: 'warn',
166
+ summary: t('memory.edit.validation_error'),
167
+ detail: t('memory.edit.validation_empty'),
168
+ life: 3000,
169
+ })
170
+ return
171
+ }
172
+
173
+ emit('update', editedData.value)
174
+ isEditing.value = false
175
+ }
176
+
177
+ const handleCancel = () => {
178
+ editedData.value = props.memory.memory
179
+ isEditing.value = false
180
+ }
181
+
182
+ const handleDelete = () => {
183
+ confirm.require({
184
+ message: t('memory.edit.delete_confirm_message'),
185
+ header: t('memory.edit.delete_confirm_header'),
186
+ icon: 'pi pi-exclamation-triangle',
187
+ rejectProps: {
188
+ label: t('memory.edit.cancel_button'),
189
+ severity: 'secondary',
190
+ outlined: true,
191
+ },
192
+ acceptProps: {
193
+ label: t('memory.edit.delete_button'),
194
+ severity: 'danger',
195
+ },
196
+ accept: () => {
197
+ emit('delete')
198
+ },
199
+ })
200
+ }
201
+
202
+ // Parse agent_id from "agent_class/agent_id" format
203
+ const parsedAgent = computed(() => {
204
+ if (!props.memory.agent_id) return null
205
+ const parts = props.memory.agent_id.split('/')
206
+ if (parts.length !== 2) return null
207
+ return { agent_class: parts[0], agent_id: parts[1] }
208
+ })
209
+
210
+ // Check if we can navigate to agent
211
+ const canNavigateToAgent = computed(() => parsedAgent.value !== null)
212
+
213
+ // Check if we can navigate to thread/display (both must exist)
214
+ const canNavigateToThread = computed(() => {
215
+ return !!props.memory.thread_id && !!props.memory.display_id
216
+ })
217
+
218
+ // Construct agent URL
219
+ const agentUrl = computed(() => {
220
+ if (!parsedAgent.value) return ''
221
+ return `/service/agents/${parsedAgent.value.agent_class}-${parsedAgent.value.agent_id}/overview`
222
+ })
223
+
224
+ // Construct thread/display URL
225
+ const threadDisplayUrl = computed(() => {
226
+ if (!canNavigateToThread.value) return ''
227
+ return `/service/threads/${props.memory.thread_id}/display/${props.memory.display_id}`
228
+ })
229
+
230
+ const navigateToAgent = () => {
231
+ if (canNavigateToAgent.value) {
232
+ router.push(tenantPath(agentUrl.value))
233
+ }
234
+ }
235
+
236
+ const navigateToThreadDisplay = () => {
237
+ if (canNavigateToThread.value) {
238
+ router.push(tenantPath(threadDisplayUrl.value))
239
+ }
240
+ }
241
+ </script>
@@ -0,0 +1,318 @@
1
+ <template>
2
+ <div
3
+ ref="container"
4
+ class="relative size-full overflow-hidden"
5
+ :style="{ minHeight: props.height }"
6
+ />
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { EdgeCurvedArrowProgram } from '@sigma/edge-curve'
11
+ import Graph from 'graphology'
12
+ import forceAtlas2 from 'graphology-layout-forceatlas2'
13
+ import Sigma from 'sigma'
14
+ import { createEdgeArrowProgram } from 'sigma/rendering'
15
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
16
+
17
+ import type { MemoryRelationDto } from '@core/sdk/client'
18
+
19
+ interface Props {
20
+ relations: MemoryRelationDto[]
21
+ selectedMemoryId?: string
22
+ highlightedRelations?: MemoryRelationDto[]
23
+ height?: string
24
+ }
25
+
26
+ interface Colors {
27
+ nodeActive: string
28
+ nodeInactive: string
29
+ nodeSelected: string
30
+ edgeActive: string
31
+ edgeInactive: string
32
+ labelColor: string
33
+ }
34
+
35
+ const props = withDefaults(defineProps<Props>(), {
36
+ height: '800px',
37
+ })
38
+ const emit = defineEmits<{ selectNode: [nodeId: string] }>()
39
+
40
+ const { myUser } = useMyUser()
41
+ const isDark = useDarkMode()
42
+ const container = ref<HTMLDivElement>()
43
+
44
+ let sigma: Sigma | null = null
45
+ let graph: Graph | null = null
46
+ let resizeObserver: ResizeObserver | null = null
47
+ let renderedWithValidSize = false
48
+
49
+ const MIN_NODE_SIZE = 10
50
+ const MAX_NODE_SIZE = 50
51
+ const EDGE_CURVATURE = 0.4
52
+
53
+ const CustomArrowProgram = createEdgeArrowProgram({
54
+ widenessToThicknessRatio: 3,
55
+ lengthToThicknessRatio: 4,
56
+ })
57
+
58
+ const isHighlightActive = computed(() => !!props.highlightedRelations)
59
+
60
+ const relevantRelationKeys = computed(() => {
61
+ if (!props.highlightedRelations) return new Set<string>()
62
+ return new Set(
63
+ props.highlightedRelations.map((r, i) => `${r.source}-${r.relation}-${r.target}-${i}`),
64
+ )
65
+ })
66
+
67
+ const hashString = (str: string): number => {
68
+ let hash = 0
69
+ for (let i = 0; i < str.length; i++) {
70
+ hash = ((hash << 5) - hash) + str.charCodeAt(i)
71
+ hash = hash & hash
72
+ }
73
+ return Math.abs(hash)
74
+ }
75
+
76
+ const getDeterministicPosition = (id: string, seed: string, index: number): number => {
77
+ const hash = hashString(id + seed)
78
+ const offset = (index * 0.001) % 1
79
+ return ((hash % 1000) / 1000 + offset) % 1
80
+ }
81
+
82
+ const getCssVar = (varName: string): string => {
83
+ if (typeof window === 'undefined') return '#000000'
84
+ return getComputedStyle(document.documentElement).getPropertyValue(varName).trim()
85
+ }
86
+
87
+ const getColors = (): Colors => ({
88
+ nodeActive: getCssVar('--p-primary-color'),
89
+ nodeInactive: getCssVar('--p-surface-500'),
90
+ nodeSelected: getCssVar('--p-red-600'),
91
+ edgeActive: getCssVar('--p-surface-600'),
92
+ edgeInactive: getCssVar('--p-surface-400'),
93
+ labelColor: getCssVar('--p-primary-color'),
94
+ })
95
+
96
+ const isNodeRelevant = (nodeId: string): boolean => {
97
+ if (!isHighlightActive.value) return true
98
+ // A node is relevant if it appears in any highlighted relation
99
+ return props.highlightedRelations?.some(r => r.source === nodeId || r.target === nodeId) ?? false
100
+ }
101
+
102
+ const isEdgeRelevant = (edgeKey: string): boolean => {
103
+ return !isHighlightActive.value || relevantRelationKeys.value.has(edgeKey)
104
+ }
105
+
106
+ const lerp = (min: number, max: number, t: number): number => {
107
+ return min + t * (max - min)
108
+ }
109
+
110
+ const calculateNodeSize = (degree: number, minDegree: number, maxDegree: number): number => {
111
+ if (maxDegree === minDegree) return (MIN_NODE_SIZE + MAX_NODE_SIZE) / 2
112
+ const t = (degree - minDegree) / (maxDegree - minDegree)
113
+ return lerp(MIN_NODE_SIZE, MAX_NODE_SIZE, t)
114
+ }
115
+
116
+ /**
117
+ * Creates a canonical key for a pair of nodes (order-independent)
118
+ */
119
+ const getNodePairKey = (source: string, target: string): string => {
120
+ return [source, target].sort().join('::')
121
+ }
122
+
123
+ /**
124
+ * Detects parallel edges and assigns curvature to them
125
+ */
126
+ const assignEdgeCurvatures = (g: Graph): void => {
127
+ const edgesByPair = new Map<string, string[]>()
128
+
129
+ g.forEachEdge((edge, _attrs, source, target) => {
130
+ const pairKey = getNodePairKey(source, target)
131
+ if (!edgesByPair.has(pairKey)) {
132
+ edgesByPair.set(pairKey, [])
133
+ }
134
+ edgesByPair.get(pairKey)!.push(edge)
135
+ })
136
+
137
+ edgesByPair.forEach((edges) => {
138
+ if (edges.length === 1) {
139
+ g.setEdgeAttribute(edges[0], 'curvature', 0)
140
+ g.setEdgeAttribute(edges[0], 'type', 'straight')
141
+ }
142
+ else {
143
+ // Spread all parallel edges evenly
144
+ // For 2 edges: indices 0,1 → offsets -0.5, +0.5
145
+ // For 3 edges: indices 0,1,2 → offsets -1, 0, +1
146
+ edges.forEach((edge, index) => {
147
+ const spreadFactor = index - (edges.length - 1) / 2
148
+ const curvature = spreadFactor * EDGE_CURVATURE
149
+
150
+ g.setEdgeAttribute(edge, 'curvature', curvature)
151
+ g.setEdgeAttribute(edge, 'type', curvature === 0 ? 'straight' : 'curved')
152
+ })
153
+ }
154
+ })
155
+ }
156
+
157
+ const buildGraph = (colors: Colors): Graph => {
158
+ const g = new Graph({ multi: true, type: 'directed' })
159
+
160
+ if (!props.relations?.length) return g
161
+
162
+ const nodeSet = new Set<string>()
163
+ props.relations.forEach((rel) => {
164
+ nodeSet.add(rel.source)
165
+ nodeSet.add(rel.target)
166
+ })
167
+
168
+ Array.from(nodeSet).forEach((node, index) => {
169
+ const isCurrentUser = myUser.value?.id === node
170
+ const label = isCurrentUser ? (myUser.value?.name ?? node) : node
171
+
172
+ g.addNode(node, {
173
+ label,
174
+ x: getDeterministicPosition(node, 'x', index),
175
+ y: getDeterministicPosition(node, 'y', index),
176
+ })
177
+ })
178
+
179
+ props.relations.forEach((rel, index) => {
180
+ const edgeKey = `${rel.source}-${rel.relation}-${rel.target}-${index}`
181
+ const relevant = isEdgeRelevant(edgeKey)
182
+ g.addEdge(rel.source, rel.target, {
183
+ label: rel.relation,
184
+ size: relevant ? 4 : 2,
185
+ color: relevant ? colors.edgeActive : colors.edgeInactive,
186
+ labelColor: colors.labelColor,
187
+ forceLabel: true,
188
+ }, `edge-${index}`)
189
+ })
190
+
191
+ // Assign curvatures to handle parallel/bidirectional edges
192
+ assignEdgeCurvatures(g)
193
+
194
+ const degrees = g.mapNodes(node => g.degree(node))
195
+ const minDegree = Math.min(...degrees)
196
+ const maxDegree = Math.max(...degrees)
197
+
198
+ g.forEachNode((node) => {
199
+ const degree = g.degree(node)
200
+ const size = calculateNodeSize(degree, minDegree, maxDegree)
201
+ const relevant = isNodeRelevant(node)
202
+
203
+ g.setNodeAttribute(node, 'baseSize', size)
204
+ g.setNodeAttribute(node, 'size', size)
205
+ g.setNodeAttribute(node, 'color', relevant ? colors.nodeActive : colors.nodeInactive)
206
+ g.setNodeAttribute(node, 'labelColor', colors.labelColor)
207
+ })
208
+
209
+ return g
210
+ }
211
+
212
+ const applyLayout = (g: Graph): void => {
213
+ if (g.order === 0) return
214
+ forceAtlas2.assign(g, {
215
+ iterations: 300,
216
+ settings: {
217
+ gravity: 0.15, // was 0.3 - lower to give more room
218
+ scalingRatio: 70, // was 50 - slightly more repulsion
219
+ adjustSizes: true,
220
+ barnesHutOptimize: true,
221
+ strongGravityMode: false,
222
+ linLogMode: false,
223
+ outboundAttractionDistribution: true,
224
+ },
225
+ })
226
+ }
227
+
228
+ const highlightSelectedNode = (nodeId: string | undefined, colors: Colors): void => {
229
+ if (!graph || !nodeId || !graph.hasNode(nodeId)) return
230
+ graph.setNodeAttribute(nodeId, 'color', colors.nodeSelected)
231
+ }
232
+
233
+ const renderGraph = (): void => {
234
+ if (!container.value) return
235
+
236
+ const { width } = container.value.getBoundingClientRect()
237
+ if (width > 0) renderedWithValidSize = true
238
+
239
+ sigma?.kill()
240
+ sigma = null
241
+
242
+ const colors = getColors()
243
+ graph = buildGraph(colors)
244
+ applyLayout(graph)
245
+
246
+ sigma = new Sigma(graph, container.value, {
247
+ renderEdgeLabels: true,
248
+ allowInvalidContainer: true,
249
+ labelSize: 12,
250
+ labelWeight: 'bold',
251
+ labelRenderedSizeThreshold: 5,
252
+ labelDensity: 0.5,
253
+ labelGridCellSize: 100,
254
+ edgeLabelSize: 10,
255
+ labelColor: { attribute: 'labelColor', color: colors.labelColor },
256
+ edgeLabelColor: { attribute: 'labelColor', color: colors.labelColor },
257
+ defaultEdgeType: 'straight',
258
+ edgeProgramClasses: {
259
+ straight: CustomArrowProgram,
260
+ curved: EdgeCurvedArrowProgram,
261
+ },
262
+ })
263
+
264
+ sigma.on('clickNode', ({ node }) => emit('selectNode', node))
265
+
266
+ highlightSelectedNode(props.selectedMemoryId, colors)
267
+ sigma.refresh()
268
+ }
269
+
270
+ watch(
271
+ () => [props.relations, props.highlightedRelations],
272
+ () => renderGraph(),
273
+ { deep: true },
274
+ )
275
+
276
+ watch(
277
+ () => props.selectedMemoryId,
278
+ (newId, oldId) => {
279
+ if (!graph || !sigma) return
280
+
281
+ const colors = getColors()
282
+
283
+ if (oldId && graph.hasNode(oldId)) {
284
+ const baseSize = graph.getNodeAttribute(oldId, 'baseSize') as number
285
+ graph.setNodeAttribute(oldId, 'size', baseSize)
286
+ graph.setNodeAttribute(oldId, 'color', isNodeRelevant(oldId) ? colors.nodeActive : colors.nodeInactive)
287
+ }
288
+
289
+ highlightSelectedNode(newId, colors)
290
+ sigma.refresh()
291
+ },
292
+ )
293
+
294
+ watch(isDark, async () => {
295
+ await nextTick()
296
+ renderGraph()
297
+ })
298
+
299
+ onMounted(() => {
300
+ renderGraph()
301
+
302
+ if (container.value) {
303
+ resizeObserver = new ResizeObserver(() => {
304
+ if (!container.value || renderedWithValidSize) return
305
+ const { width } = container.value.getBoundingClientRect()
306
+ if (width > 0) {
307
+ renderGraph()
308
+ }
309
+ })
310
+ resizeObserver.observe(container.value)
311
+ }
312
+ })
313
+
314
+ onUnmounted(() => {
315
+ sigma?.kill()
316
+ resizeObserver?.disconnect()
317
+ })
318
+ </script>
@@ -0,0 +1,155 @@
1
+ <template>
2
+ <div class="flex h-full flex-col">
3
+ <DataTable
4
+ :value="memories"
5
+ :loading="loading"
6
+ :selection="selectedMemory"
7
+ selection-mode="single"
8
+ :meta-key-selection="false"
9
+ data-key="id"
10
+ class="flex-1"
11
+ size="small"
12
+ scrollable
13
+ scroll-height="flex"
14
+ striped-rows
15
+ @update:selection="handleSelection"
16
+ >
17
+ <Column
18
+ field="memory"
19
+ :header="t('memory.table.memory')"
20
+ style="min-width: 300px"
21
+ >
22
+ <template #body="slotProps">
23
+ <div class="line-clamp-2 text-surface-700 dark:text-surface-200">
24
+ {{ slotProps.data.memory }}
25
+ </div>
26
+ </template>
27
+ </Column>
28
+
29
+ <Column
30
+ v-if="!hideAgentColumn"
31
+ field="agent_id"
32
+ :header="t('memory.table.agent')"
33
+ style="width: 200px"
34
+ >
35
+ <template #body="slotProps">
36
+ <Tag
37
+ v-if="slotProps.data.agent_id"
38
+ :value="slotProps.data.agent_id"
39
+ severity="secondary"
40
+ class="font-mono"
41
+ />
42
+ <span
43
+ v-else
44
+ class="text-surface-400 dark:text-surface-500"
45
+ >-</span>
46
+ </template>
47
+ </Column>
48
+ <Column
49
+ field="created"
50
+ :header="t('memory.table.created')"
51
+ style="width: 160px"
52
+ >
53
+ <template #body="slotProps">
54
+ <div class="flex flex-col">
55
+ <span class="text-sm font-medium text-surface-700 dark:text-surface-200">
56
+ {{ useDateFormat(slotProps.data.created, 'DD.MM.YYYY') }}
57
+ </span>
58
+ <span class="text-xs text-surface-500 dark:text-surface-400">
59
+ {{ useDateFormat(slotProps.data.created, 'HH:mm:ss') }}
60
+ </span>
61
+ </div>
62
+ </template>
63
+ </Column>
64
+ <Column
65
+ field="score"
66
+ :header="t('memory.table.score')"
67
+ style="width: 120px"
68
+ >
69
+ <template #body="slotProps">
70
+ <Tag
71
+ v-if="slotProps.data.score != null"
72
+ :value="slotProps.data.score.toFixed(2)"
73
+ :severity="getScoreSeverity(slotProps.data.score)"
74
+ rounded
75
+ />
76
+ <span
77
+ v-else
78
+ class="text-surface-400 dark:text-surface-500"
79
+ >-</span>
80
+ </template>
81
+ </Column>
82
+ </DataTable>
83
+
84
+ <div
85
+ v-if="totalPages > 1"
86
+ class="flex items-center justify-between border-t p-4"
87
+ >
88
+ <Button
89
+ icon="pi pi-chevron-left"
90
+ :disabled="currentPage === 1"
91
+ text
92
+ @click="emit('prevPage')"
93
+ />
94
+ <span class="text-sm text-gray-600">
95
+ {{ t('memory.table.pagination', { currentPage, totalPages }) }}
96
+ </span>
97
+ <Button
98
+ icon="pi pi-chevron-right"
99
+ :disabled="currentPage === totalPages"
100
+ text
101
+ @click="emit('nextPage')"
102
+ />
103
+ </div>
104
+ </div>
105
+ </template>
106
+
107
+ <script setup lang="ts">
108
+ import { computed } from 'vue'
109
+
110
+ import type { MemoryDto } from '@core/sdk/client'
111
+
112
+ interface Props {
113
+ memories: MemoryDto[]
114
+ loading?: boolean
115
+ currentPage: number
116
+ totalPages: number
117
+ selectedMemoryId?: string
118
+ hideAgentColumn?: boolean
119
+ }
120
+
121
+ const props = defineProps<Props>()
122
+
123
+ const emit = defineEmits<{
124
+ selectMemory: [memory: MemoryDto]
125
+ nextPage: []
126
+ prevPage: []
127
+ goToPage: [page: number]
128
+ }>()
129
+
130
+ const selectedMemory = computed(() => {
131
+ return props.memories.find(memory => memory.id === props.selectedMemoryId)
132
+ })
133
+
134
+ const { t } = useI18n()
135
+
136
+ const handleSelection = (memory: MemoryDto) => {
137
+ emit('selectMemory', memory)
138
+ }
139
+
140
+ const getScoreSeverity = (score: number) => {
141
+ if (score >= 0.8) return 'success'
142
+ if (score >= 0.6) return 'info'
143
+ if (score >= 0.4) return 'warn'
144
+ return 'danger'
145
+ }
146
+ </script>
147
+
148
+ <style scoped>
149
+ .line-clamp-2 {
150
+ display: -webkit-box;
151
+ -webkit-line-clamp: 2;
152
+ -webkit-box-orient: vertical;
153
+ overflow: hidden;
154
+ }
155
+ </style>