@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.
- package/LICENSE +661 -0
- package/README.md +479 -0
- package/app.config.ts +1 -0
- package/app.vue +52 -0
- package/assets/css/main.css +4 -0
- package/assets/images/logo.png +0 -0
- package/components/Agent/Avatar.vue +40 -0
- package/components/Agent/Card.vue +139 -0
- package/components/Agent/Configuration.vue +20 -0
- package/components/Agent/CreateModal.vue +287 -0
- package/components/Agent/EmptyCard.vue +35 -0
- package/components/Agent/List.vue +85 -0
- package/components/Agent/TemplateCard.vue +58 -0
- package/components/AppLoader.vue +55 -0
- package/components/Chat/Message.vue +90 -0
- package/components/Chat/SourceNodes.vue +120 -0
- package/components/Chat/Thread.vue +134 -0
- package/components/Costs/Table.vue +56 -0
- package/components/Dashboard/Component/BarChart.vue +46 -0
- package/components/Dashboard/Component/LineChart.vue +138 -0
- package/components/Dashboard/Component/Number.vue +31 -0
- package/components/Dashboard/Grid.vue +214 -0
- package/components/Dashboard/Item.vue +75 -0
- package/components/Dashboard/Trend.vue +34 -0
- package/components/Display/List/DisplayList.vue +93 -0
- package/components/Evaluation/Dataset/Card.vue +70 -0
- package/components/Evaluation/Dataset/Create.vue +81 -0
- package/components/Evaluation/Dataset/Edit.vue +132 -0
- package/components/Event/Display/AddMemoryToChatHistoryEvent.vue +60 -0
- package/components/Event/Display/AgentInTheLoopRequestEvent.vue +56 -0
- package/components/Event/Display/AgentInTheLoopResponseEvent.vue +17 -0
- package/components/Event/Display/Base.vue +125 -0
- package/components/Event/Display/BaseRetrieveMemoryEvent.vue +101 -0
- package/components/Event/Display/BaseStoreMemoryEvent.vue +182 -0
- package/components/Event/Display/ChunkEvent.vue +40 -0
- package/components/Event/Display/EmbeddingEvent.vue +25 -0
- package/components/Event/Display/ExceptionEvent.vue +21 -0
- package/components/Event/Display/GuardAcceptEvent.vue +25 -0
- package/components/Event/Display/GuardEvent.vue +17 -0
- package/components/Event/Display/GuardRejectionEvent.vue +25 -0
- package/components/Event/Display/HumanInTheLoopRequestEvent.vue +53 -0
- package/components/Event/Display/HumanInTheLoopResponseEvent.vue +40 -0
- package/components/Event/Display/LLMCostEvent.vue +25 -0
- package/components/Event/Display/LLMEvent.vue +92 -0
- package/components/Event/Display/LimitChatHistoryEvent.vue +60 -0
- package/components/Event/Display/RAGFailureStopEvent.vue +28 -0
- package/components/Event/Display/RAGStartEvent.vue +77 -0
- package/components/Event/Display/RAGSuccessStopEvent.vue +16 -0
- package/components/Event/Display/RawDataContent.vue +69 -0
- package/components/Event/Display/RerankerEvent.vue +39 -0
- package/components/Event/Display/RetrieverEvent.vue +22 -0
- package/components/Event/Display/RouterEvent.vue +54 -0
- package/components/Event/Display/StandaloneQuestionCondenserEvent.vue +38 -0
- package/components/Event/Display/StopEvent.vue +16 -0
- package/components/Event/Display/ThoughtEvent.vue +20 -0
- package/components/Event/Display/ToolEvent.vue +38 -0
- package/components/Event/Display/UnknownEvent.vue +17 -0
- package/components/Event/Display/UserMessageEvent.vue +35 -0
- package/components/Event/List/EventList.vue +249 -0
- package/components/Event/Statistics.vue +49 -0
- package/components/Event/Timeseries.vue +224 -0
- package/components/FormKit/AgentSelector.vue +307 -0
- package/components/FormKit/ChipsInput.vue +62 -0
- package/components/FormKit/DynamicConfiguration.vue +155 -0
- package/components/FormKit/IconSelector.vue +72 -0
- package/components/FormKit/KnowledgeDatabaseSelector.vue +92 -0
- package/components/FormKit/LocaleInput.vue +150 -0
- package/components/FormKit/ModelSelect.vue +110 -0
- package/components/FormKit/Repeater.vue +93 -0
- package/components/FormKit/VectorStoreInput.vue +247 -0
- package/components/Knowledge/Document/List.vue +140 -0
- package/components/Knowledge/Document/Overview.vue +28 -0
- package/components/Knowledge/Document/UploadModal.vue +298 -0
- package/components/Knowledge/Document/WithNodes.vue +105 -0
- package/components/Knowledge/Namespace/Card.vue +108 -0
- package/components/Knowledge/Namespace/CreateModal.vue +203 -0
- package/components/Knowledge/Namespace/EditModal.vue +134 -0
- package/components/Knowledge/Namespace/EmptyCard.vue +35 -0
- package/components/Knowledge/Node/Content.vue +71 -0
- package/components/Markdown/Renderer.vue +87 -0
- package/components/Memory/DetailPage.vue +48 -0
- package/components/Memory/Edit.vue +241 -0
- package/components/Memory/Graph.vue +318 -0
- package/components/Memory/List.vue +155 -0
- package/components/Memory/MemoryManagementPage.vue +178 -0
- package/components/Memory/OpenWebUIContent.vue +96 -0
- package/components/Memory/PageLayout.vue +72 -0
- package/components/Models/ModelDetailsPanel.vue +250 -0
- package/components/Models/NamespaceCard.vue +79 -0
- package/components/Navigation/Left.vue +85 -0
- package/components/Navigation/Top.vue +31 -0
- package/components/Notification/Item.vue +88 -0
- package/components/Notification/NotificationsOverlay.vue +164 -0
- package/components/Process/Card.vue +119 -0
- package/components/Process/Configuration.vue +20 -0
- package/components/Process/CreateModal.vue +276 -0
- package/components/Process/EmptyCard.vue +35 -0
- package/components/Process/Form.vue +153 -0
- package/components/Process/Starts.vue +44 -0
- package/components/Process/Walkthrough/List.vue +162 -0
- package/components/Role/AccessRulesEditor.vue +132 -0
- package/components/Role/Card.vue +68 -0
- package/components/Role/Create.vue +55 -0
- package/components/Role/Edit.vue +82 -0
- package/components/Role/UsageLimitsEditor.vue +225 -0
- package/components/Service/Selection.vue +148 -0
- package/components/Structural/Column.vue +74 -0
- package/components/Structural/Screen.vue +10 -0
- package/components/Structural/Substructure.vue +5 -0
- package/components/Tenant/Switcher.vue +102 -0
- package/components/Thread/Details.vue +135 -0
- package/components/Thread/Hierarchy.vue +136 -0
- package/components/Thread/Info.vue +41 -0
- package/components/Thread/List.vue +136 -0
- package/components/User/Bar.vue +74 -0
- package/components/User/List.vue +86 -0
- package/components/User/RoleChips.vue +83 -0
- package/components/User/Settings.vue +79 -0
- package/components/Workflow/Modal.vue +39 -0
- package/components/Workflow/NodeCard.vue +41 -0
- package/components/Workflow/StartNode.vue +24 -0
- package/components/Workflow/StepNode.vue +27 -0
- package/components/Workflow/StopNode.vue +24 -0
- package/components/Workflow/Visualization.vue +265 -0
- package/components/mdc/MarkdownFigure.vue +9 -0
- package/components/mdc/MarkdownTable.vue +9 -0
- package/components/mdc/ResolveImageComponent.vue +58 -0
- package/composables/agent/useAgentClass.ts +27 -0
- package/composables/agent/useAgentClassInstances.ts +27 -0
- package/composables/agent/useAgentClasses.ts +27 -0
- package/composables/agent/useAgentIconFromThread.ts +8 -0
- package/composables/agent/useAgentInstance.ts +28 -0
- package/composables/agent/useAgentInstanceThreads.ts +76 -0
- package/composables/agent/useAgentInstances.ts +25 -0
- package/composables/agent/useAgentNavigation.ts +35 -0
- package/composables/agent/useCreateAgentInstance.ts +33 -0
- package/composables/agent/useDeleteAgentInstance.ts +31 -0
- package/composables/agent/useUpdateAgentInstance.ts +40 -0
- package/composables/auth/useAuth.ts +54 -0
- package/composables/auth/useAuthProviders.ts +14 -0
- package/composables/chat/useChatCompletions.ts +30 -0
- package/composables/dashboard/useAgentNameFromDashboardWidget.ts +27 -0
- package/composables/dashboard/useDashboardComponent.ts +27 -0
- package/composables/dashboard/useSaveDashboard.ts +21 -0
- package/composables/document/useCreateNamespace.ts +26 -0
- package/composables/document/useDatabases.ts +23 -0
- package/composables/document/useDocument.ts +29 -0
- package/composables/document/useDocumentUrl.ts +20 -0
- package/composables/document/useDocuments.ts +107 -0
- package/composables/document/useNodes.ts +29 -0
- package/composables/document/useSummaryNodes.ts +32 -0
- package/composables/document/useUpdateNamespace.ts +22 -0
- package/composables/evaluation/useCreateDataset.ts +19 -0
- package/composables/evaluation/useDataset.ts +26 -0
- package/composables/evaluation/useDatasets.ts +25 -0
- package/composables/evaluation/useUpdateDataset.ts +23 -0
- package/composables/event/useBasicEventStatistics.ts +83 -0
- package/composables/event/useEventColor.ts +25 -0
- package/composables/event/useEventComponent.ts +87 -0
- package/composables/event/useEventTimeseries.ts +39 -0
- package/composables/event/useEventTimeseriesStats.ts +26 -0
- package/composables/file/useFileUpload.ts +91 -0
- package/composables/file/useSupportedFileTypes.ts +22 -0
- package/composables/form/useCreateInstanceForm.ts +251 -0
- package/composables/form/useFormKitTransform.ts +753 -0
- package/composables/memory/useMemoryCRUD.ts +88 -0
- package/composables/memory/useMemoryFactory.ts +319 -0
- package/composables/memory/useMemorySearchFilter.ts +74 -0
- package/composables/models/useModelsList.ts +24 -0
- package/composables/models/useSingleModel.ts +30 -0
- package/composables/notification/useNotificationPoller.ts +58 -0
- package/composables/notification/useNotifications.ts +57 -0
- package/composables/notification/useUpdateMultipleNotifications.ts +17 -0
- package/composables/notification/useUpdateNotification.ts +17 -0
- package/composables/process/useCreateProcessInstance.ts +32 -0
- package/composables/process/useDeleteProcessInstance.ts +31 -0
- package/composables/process/useProcessClasses.ts +27 -0
- package/composables/process/useProcessInstance.ts +28 -0
- package/composables/process/useProcessInstances.ts +27 -0
- package/composables/process/useProcessWalkthroughs.ts +73 -0
- package/composables/process/useSendProcessStartForm.ts +43 -0
- package/composables/process/useUpdateProcessInstance.ts +40 -0
- package/composables/role/useCreateRole.ts +19 -0
- package/composables/role/useDeleteRole.ts +21 -0
- package/composables/role/useRole.ts +30 -0
- package/composables/role/useRoles.ts +25 -0
- package/composables/role/useUpdateRole.ts +22 -0
- package/composables/suite/useApps.ts +31 -0
- package/composables/suite/useSuite.ts +26 -0
- package/composables/tenant/useActiveTenant.ts +27 -0
- package/composables/tenant/useSysadminNavigation.ts +19 -0
- package/composables/tenant/useTenant.ts +38 -0
- package/composables/tenant/useTenantMemberships.ts +15 -0
- package/composables/tenant/useTenantPath.ts +20 -0
- package/composables/tenant/useTenantPolling.ts +30 -0
- package/composables/tenant/useTenantReady.ts +12 -0
- package/composables/theme/useDarkMode.ts +5 -0
- package/composables/thread/useThread.ts +27 -0
- package/composables/thread/useThreadEvents.ts +91 -0
- package/composables/thread/useThreadUtils.ts +49 -0
- package/composables/thread/useThreads.ts +64 -0
- package/composables/thread/useThreadsInfinite.ts +56 -0
- package/composables/translation/useTranslate.ts +20 -0
- package/composables/useRouteReady.ts +21 -0
- package/composables/useTimeAgo.ts +40 -0
- package/composables/user/useAssignRoleToUser.ts +22 -0
- package/composables/user/useMyUser.ts +25 -0
- package/composables/user/useRevokeRoleFromUser.ts +21 -0
- package/composables/user/useUser.ts +30 -0
- package/composables/user/useUsers.ts +63 -0
- package/composables/utils/useJsonTree.ts +138 -0
- package/formkit.config.ts +44 -0
- package/i18n/locales/de.yaml +815 -0
- package/i18n/locales/en.yaml +804 -0
- package/i18n/locales/fr.yaml +812 -0
- package/i18n/locales/it.yaml +808 -0
- package/layouts/anonymous.vue +8 -0
- package/layouts/default.vue +116 -0
- package/middleware/auth.global.ts +62 -0
- package/nuxt.config.ts +145 -0
- package/package.json +114 -0
- package/pages/[tenant]/index.vue +31 -0
- package/pages/[tenant]/notifications/index.vue +235 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/chat.vue +67 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/configuration.vue +122 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories/[memory_id].vue +3 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories.vue +20 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/overview.vue +72 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/threads.vue +52 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/workflow.vue +19 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id].vue +63 -0
- package/pages/[tenant]/service/agents/templates.vue +102 -0
- package/pages/[tenant]/service/agents.vue +185 -0
- package/pages/[tenant]/service/datasets/[dataset_id].vue +81 -0
- package/pages/[tenant]/service/datasets.vue +53 -0
- package/pages/[tenant]/service/health/index.vue +3 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/nodes.vue +20 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/overview.vue +40 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/summary.vue +88 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id].vue +48 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace].vue +144 -0
- package/pages/[tenant]/service/knowledge.vue +126 -0
- package/pages/[tenant]/service/models/[model_name].vue +84 -0
- package/pages/[tenant]/service/models.vue +61 -0
- package/pages/[tenant]/service/my-account.vue +117 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/memories.vue +66 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/sources.vue +100 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/tracing.vue +49 -0
- package/pages/[tenant]/service/openai.vue +101 -0
- package/pages/[tenant]/service/organization-memories/graph.vue +97 -0
- package/pages/[tenant]/service/organization-memories/list/[memory_id].vue +3 -0
- package/pages/[tenant]/service/organization-memories/list.vue +150 -0
- package/pages/[tenant]/service/organization-memories.vue +3 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/[process_walkthrough_id].vue +7 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/configuration.vue +106 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/overview.vue +67 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/start.vue +26 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs/[process_walkthrough_id]/overview.vue +14 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs.vue +54 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id].vue +60 -0
- package/pages/[tenant]/service/processes.vue +129 -0
- package/pages/[tenant]/service/roles/[role_id].vue +54 -0
- package/pages/[tenant]/service/roles.vue +84 -0
- package/pages/[tenant]/service/threads/[thread_id]/chat.vue +51 -0
- package/pages/[tenant]/service/threads/[thread_id]/display/[display_id].vue +21 -0
- package/pages/[tenant]/service/threads/[thread_id]/display.vue +29 -0
- package/pages/[tenant]/service/threads/[thread_id]/hierarchy.vue +14 -0
- package/pages/[tenant]/service/threads/[thread_id]/memories/[memory_id].vue +3 -0
- package/pages/[tenant]/service/threads/[thread_id]/memories.vue +19 -0
- package/pages/[tenant]/service/threads/[thread_id]/overview.vue +100 -0
- package/pages/[tenant]/service/threads/[thread_id].vue +54 -0
- package/pages/[tenant]/service/threads.vue +52 -0
- package/pages/[tenant]/service/user-memories/graph.vue +97 -0
- package/pages/[tenant]/service/user-memories/list/[memory_id].vue +3 -0
- package/pages/[tenant]/service/user-memories/list.vue +150 -0
- package/pages/[tenant]/service/user-memories.vue +3 -0
- package/pages/[tenant]/service/users/[user_id].vue +117 -0
- package/pages/[tenant]/service/users.vue +88 -0
- package/pages/auth/callback.vue +52 -0
- package/pages/auth/login.vue +80 -0
- package/pages/auth/renew.vue +24 -0
- package/pages/index.vue +59 -0
- package/pages/select-tenant.vue +76 -0
- package/plugins/0.runtime-config.client.ts +55 -0
- package/plugins/apexcharts.client.ts +5 -0
- package/plugins/api-client.client.ts +38 -0
- package/plugins/dark-mode.client.ts +12 -0
- package/plugins/keycloak-client.ts +41 -0
- package/plugins/oidc-client.ts +78 -0
- package/sdk/client/client/client.gen.ts +237 -0
- package/sdk/client/client/index.ts +24 -0
- package/sdk/client/client/types.gen.ts +213 -0
- package/sdk/client/client/utils.gen.ts +407 -0
- package/sdk/client/client.gen.ts +25 -0
- package/sdk/client/core/auth.gen.ts +42 -0
- package/sdk/client/core/bodySerializer.gen.ts +96 -0
- package/sdk/client/core/params.gen.ts +181 -0
- package/sdk/client/core/pathSerializer.gen.ts +180 -0
- package/sdk/client/core/queryKeySerializer.gen.ts +136 -0
- package/sdk/client/core/serverSentEvents.gen.ts +265 -0
- package/sdk/client/core/types.gen.ts +118 -0
- package/sdk/client/core/utils.gen.ts +143 -0
- package/sdk/client/index.ts +1013 -0
- package/sdk/client/schemas.gen.ts +35395 -0
- package/sdk/client/sdk.gen.ts +3438 -0
- package/sdk/client/transformers.gen.ts +143 -0
- package/sdk/client/types.gen.ts +27567 -0
- package/tailwind.config.mjs +27 -0
- package/themes/aihub-theme.ts +125 -0
- package/types/DashboardWidget.ts +13 -0
- package/types/EventChartInput.ts +7 -0
- package/types/NavItem.ts +6 -0
- package/types/TimeseriesInput.ts +7 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VueFlow
|
|
3
|
+
:nodes="nodes"
|
|
4
|
+
:edges="edges"
|
|
5
|
+
:min-zoom="0.2"
|
|
6
|
+
:max-zoom="4"
|
|
7
|
+
:nodes-connectable="false"
|
|
8
|
+
fit-view-on-init
|
|
9
|
+
class="size-full"
|
|
10
|
+
>
|
|
11
|
+
<Background />
|
|
12
|
+
|
|
13
|
+
<template #node-start="{ id, data }">
|
|
14
|
+
<WorkflowStartNode
|
|
15
|
+
:id="id"
|
|
16
|
+
:data="data"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<template #node-step="{ id, data }">
|
|
21
|
+
<WorkflowStepNode
|
|
22
|
+
:id="id"
|
|
23
|
+
:data="data"
|
|
24
|
+
/>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<template #node-stop="{ id, data }">
|
|
28
|
+
<WorkflowStopNode
|
|
29
|
+
:id="id"
|
|
30
|
+
:data="data"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
</VueFlow>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { Background } from '@vue-flow/background'
|
|
38
|
+
import { VueFlow, MarkerType, Position, useVueFlow } from '@vue-flow/core'
|
|
39
|
+
import { computed, onBeforeUnmount, onMounted } from 'vue'
|
|
40
|
+
|
|
41
|
+
import '@vue-flow/core/dist/style.css'
|
|
42
|
+
import '@vue-flow/core/dist/theme-default.css'
|
|
43
|
+
|
|
44
|
+
import type { WorkflowGraph } from '@core/sdk/client'
|
|
45
|
+
|
|
46
|
+
const NODE_WIDTH = 298
|
|
47
|
+
const NODE_HEIGHT = 100
|
|
48
|
+
const ROW_GAP = 80
|
|
49
|
+
const COL_GAP = 80
|
|
50
|
+
|
|
51
|
+
const props = defineProps<{
|
|
52
|
+
graphData: WorkflowGraph
|
|
53
|
+
}>()
|
|
54
|
+
|
|
55
|
+
const { updateNodeInternals, fitView } = useVueFlow()
|
|
56
|
+
|
|
57
|
+
// Re-measure handle positions after the modal's open animation has settled.
|
|
58
|
+
// Without this, vue-flow's initial handleBounds are taken mid-animation and end
|
|
59
|
+
// up ~10px off-center, shifting edge endpoints sideways from the actual handles.
|
|
60
|
+
// The handle is cleared on unmount so a quick close-during-animation won't call
|
|
61
|
+
// updateNodeInternals/fitView on a disposed VueFlow instance.
|
|
62
|
+
let settleTimer: ReturnType<typeof setTimeout> | null = null
|
|
63
|
+
onMounted(() => {
|
|
64
|
+
settleTimer = setTimeout(() => {
|
|
65
|
+
updateNodeInternals(props.graphData.nodes.map(n => n.id))
|
|
66
|
+
fitView({ padding: 0.15 })
|
|
67
|
+
settleTimer = null
|
|
68
|
+
}, 350)
|
|
69
|
+
})
|
|
70
|
+
onBeforeUnmount(() => {
|
|
71
|
+
if (settleTimer !== null) {
|
|
72
|
+
clearTimeout(settleTimer)
|
|
73
|
+
settleTimer = null
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const COL_PITCH = NODE_WIDTH + COL_GAP
|
|
78
|
+
const ROW_PITCH = NODE_HEIGHT + ROW_GAP
|
|
79
|
+
|
|
80
|
+
type Adjacency = Map<string, string[]>
|
|
81
|
+
type GridSlot = { row: number, col: number }
|
|
82
|
+
type ColumnCount = 1 | 2 | 3
|
|
83
|
+
|
|
84
|
+
const chooseColumnCount = (middleCount: number): ColumnCount => {
|
|
85
|
+
if (middleCount >= 12) return 3
|
|
86
|
+
if (middleCount >= 6) return 2
|
|
87
|
+
return 1
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const FILL_ORDERS: Record<ColumnCount, [number[], number[]]> = {
|
|
91
|
+
1: [[0], [0]],
|
|
92
|
+
2: [[1, 0], [0, 1]],
|
|
93
|
+
3: [[1, 0, 2], [1, 2, 0]],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const fillOrderForRow = (colCount: ColumnCount, row: number): number[] =>
|
|
97
|
+
FILL_ORDERS[colCount][row % 2]
|
|
98
|
+
|
|
99
|
+
const buildAdjacency = (links: { source: string, target: string }[]): { children: Adjacency, parents: Adjacency } => {
|
|
100
|
+
const children: Adjacency = new Map()
|
|
101
|
+
const parents: Adjacency = new Map()
|
|
102
|
+
for (const { source, target } of links) {
|
|
103
|
+
const kids = children.get(source) ?? []
|
|
104
|
+
kids.push(target)
|
|
105
|
+
children.set(source, kids)
|
|
106
|
+
const pars = parents.get(target) ?? []
|
|
107
|
+
pars.push(source)
|
|
108
|
+
parents.set(target, pars)
|
|
109
|
+
}
|
|
110
|
+
return { children, parents }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** BFS from start nodes, yielding middle-node ids in visit order. */
|
|
114
|
+
const bfsMiddleOrder = (startIds: string[], middleIds: Set<string>, children: Adjacency): string[] => {
|
|
115
|
+
const visited = new Set<string>(startIds)
|
|
116
|
+
const order: string[] = []
|
|
117
|
+
const queue = [...startIds]
|
|
118
|
+
while (queue.length) {
|
|
119
|
+
const current = queue.shift()!
|
|
120
|
+
for (const child of children.get(current) ?? []) {
|
|
121
|
+
if (visited.has(child)) continue
|
|
122
|
+
visited.add(child)
|
|
123
|
+
if (middleIds.has(child)) order.push(child)
|
|
124
|
+
queue.push(child)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return order
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const requiredRowFor = (nodeId: string, parents: Adjacency, rowOf: Map<string, number>): number => {
|
|
131
|
+
let required = 0
|
|
132
|
+
for (const pid of parents.get(nodeId) ?? []) {
|
|
133
|
+
const pr = rowOf.get(pid)
|
|
134
|
+
if (pr !== undefined && pr + 1 > required) required = pr + 1
|
|
135
|
+
}
|
|
136
|
+
return required
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const findFreeSlot = (
|
|
140
|
+
fromRow: number,
|
|
141
|
+
colCount: ColumnCount,
|
|
142
|
+
taken: Set<string>,
|
|
143
|
+
): GridSlot => {
|
|
144
|
+
// Upper bound: in the worst case every already-taken slot forces us to the
|
|
145
|
+
// next row. `taken.size` rows is always enough to find a fresh one since we
|
|
146
|
+
// place at most one node per call. +2 keeps the bound loose for safety.
|
|
147
|
+
const maxRows = taken.size + 2
|
|
148
|
+
for (let row = fromRow; row < fromRow + maxRows; row++) {
|
|
149
|
+
for (const col of fillOrderForRow(colCount, row)) {
|
|
150
|
+
if (!taken.has(`${row}:${col}`)) return { row, col }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
throw new Error(`findFreeSlot: no free slot found within ${maxRows} rows from ${fromRow}`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Assign (row, col) slots to each middle node in BFS order. */
|
|
157
|
+
const assignSlots = (bfsOrder: string[], parents: Adjacency, colCount: ColumnCount): Map<string, GridSlot> => {
|
|
158
|
+
const slotOf = new Map<string, GridSlot>()
|
|
159
|
+
const taken = new Set<string>()
|
|
160
|
+
const rowOf = new Map<string, number>()
|
|
161
|
+
for (const nodeId of bfsOrder) {
|
|
162
|
+
const slot = findFreeSlot(requiredRowFor(nodeId, parents, rowOf), colCount, taken)
|
|
163
|
+
slotOf.set(nodeId, slot)
|
|
164
|
+
rowOf.set(nodeId, slot.row)
|
|
165
|
+
taken.add(`${slot.row}:${slot.col}`)
|
|
166
|
+
}
|
|
167
|
+
return slotOf
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Column index → horizontal pixel offset. Column 1 (center in 3-col) is at x=0. */
|
|
171
|
+
const columnX = (colCount: ColumnCount, col: number): number => {
|
|
172
|
+
if (colCount === 1) return 0
|
|
173
|
+
if (colCount === 2) return (col - 0.5) * COL_PITCH
|
|
174
|
+
return (col - 1) * COL_PITCH
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Distribute `total` nodes horizontally around x=0. */
|
|
178
|
+
const centeredGroupX = (index: number, total: number): number =>
|
|
179
|
+
(index - (total - 1) / 2) * COL_PITCH
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Custom layout algorithm:
|
|
183
|
+
* - Start and stop nodes are centered as groups on their own rows; their x
|
|
184
|
+
* positions are independent of the column grid.
|
|
185
|
+
* - Middle nodes fill 1/2/3 columns depending on middle-node count
|
|
186
|
+
* (<6 → 1 col, 6–11 → 2, 12+ → 3).
|
|
187
|
+
* - Processing order: BFS from start nodes.
|
|
188
|
+
* - Each node's row = min row such that all its already-placed parents have
|
|
189
|
+
* lower rows (cycles back to earlier rows are ignored).
|
|
190
|
+
* - Column fill order per row: center first, then alternate sides by row parity.
|
|
191
|
+
* - If a row has no free columns at the required row, bump to the next row.
|
|
192
|
+
*/
|
|
193
|
+
const layout = computed(() => {
|
|
194
|
+
const { nodes: graphNodes, links } = props.graphData
|
|
195
|
+
|
|
196
|
+
const startNodes = graphNodes.filter(n => n.type === 'start')
|
|
197
|
+
const stopNodes = graphNodes.filter(n => n.type === 'stop')
|
|
198
|
+
const middleNodes = graphNodes.filter(n => n.type === 'step')
|
|
199
|
+
const middleIds = new Set(middleNodes.map(n => n.id))
|
|
200
|
+
const colCount = chooseColumnCount(middleNodes.length)
|
|
201
|
+
|
|
202
|
+
const { children, parents } = buildAdjacency(links)
|
|
203
|
+
|
|
204
|
+
const bfsOrder = bfsMiddleOrder(startNodes.map(n => n.id), middleIds, children)
|
|
205
|
+
// Include any middle nodes unreachable from start (defensive).
|
|
206
|
+
for (const n of middleNodes) {
|
|
207
|
+
if (!bfsOrder.includes(n.id)) bfsOrder.push(n.id)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const slotOf = assignSlots(bfsOrder, parents, colCount)
|
|
211
|
+
|
|
212
|
+
const layoutMap = new Map<string, { x: number, y: number }>()
|
|
213
|
+
startNodes.forEach((node, i) => {
|
|
214
|
+
layoutMap.set(node.id, { x: centeredGroupX(i, startNodes.length), y: 0 })
|
|
215
|
+
})
|
|
216
|
+
let maxRow = -1
|
|
217
|
+
middleNodes.forEach((node) => {
|
|
218
|
+
const { row, col } = slotOf.get(node.id)!
|
|
219
|
+
if (row > maxRow) maxRow = row
|
|
220
|
+
layoutMap.set(node.id, { x: columnX(colCount, col), y: (row + 1) * ROW_PITCH })
|
|
221
|
+
})
|
|
222
|
+
const stopRow = maxRow + 2
|
|
223
|
+
stopNodes.forEach((node, i) => {
|
|
224
|
+
layoutMap.set(node.id, { x: centeredGroupX(i, stopNodes.length), y: stopRow * ROW_PITCH })
|
|
225
|
+
})
|
|
226
|
+
return layoutMap
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
const nodes = computed(() => props.graphData.nodes.map((node) => {
|
|
230
|
+
const pos = layout.value.get(node.id)!
|
|
231
|
+
return {
|
|
232
|
+
id: node.id,
|
|
233
|
+
type: node.type,
|
|
234
|
+
position: pos,
|
|
235
|
+
data: node,
|
|
236
|
+
sourcePosition: Position.Bottom,
|
|
237
|
+
targetPosition: Position.Top,
|
|
238
|
+
}
|
|
239
|
+
}))
|
|
240
|
+
|
|
241
|
+
const edges = computed(() => props.graphData.links.map(link => ({
|
|
242
|
+
id: `${link.source}->${link.target}`,
|
|
243
|
+
source: link.source,
|
|
244
|
+
target: link.target,
|
|
245
|
+
animated: true,
|
|
246
|
+
markerEnd: { type: MarkerType.ArrowClosed, width: 24, height: 24 },
|
|
247
|
+
})))
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
<style scoped>
|
|
251
|
+
/* Selected nodes: bolder red border + red tint so even start/end nodes
|
|
252
|
+
* (already red) stand out clearly. Scoped + :deep keeps these rules from
|
|
253
|
+
* leaking into any sibling component that also uses vue-flow. */
|
|
254
|
+
:deep(.vue-flow__node.selected > *) {
|
|
255
|
+
border-color: rgb(239 68 68) !important; /* red-500 */
|
|
256
|
+
background-color: oklch(88.5% 0.062 18.334) !important; /* red-100 */
|
|
257
|
+
}
|
|
258
|
+
:deep(.dark .vue-flow__node.selected > *) {
|
|
259
|
+
background-color: oklch(25.8% 0.092 26.042) !important;
|
|
260
|
+
}
|
|
261
|
+
:deep(.vue-flow__edge.selected .vue-flow__edge-path) {
|
|
262
|
+
stroke: rgb(239 68 68) !important;
|
|
263
|
+
stroke-width: 2 !important;
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<img
|
|
4
|
+
:src="imageUrl"
|
|
5
|
+
:alt="alt"
|
|
6
|
+
:width="width"
|
|
7
|
+
:height="height"
|
|
8
|
+
>
|
|
9
|
+
<p
|
|
10
|
+
v-if="alt"
|
|
11
|
+
class="text-[10px] italic leading-3 text-surface-500"
|
|
12
|
+
>
|
|
13
|
+
{{ alt }}
|
|
14
|
+
</p>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { getFileUrl } from '@core/sdk/client'
|
|
20
|
+
|
|
21
|
+
const props = defineProps<{
|
|
22
|
+
src: string
|
|
23
|
+
alt?: string
|
|
24
|
+
width?: string | number
|
|
25
|
+
height?: string | number
|
|
26
|
+
}>()
|
|
27
|
+
|
|
28
|
+
const { tenantId } = useTenant()
|
|
29
|
+
const imageUrl = ref<string | null>(props.src)
|
|
30
|
+
|
|
31
|
+
const fetchAndSetImageUrl = async () => {
|
|
32
|
+
if (props.src.startsWith('http')) {
|
|
33
|
+
return props.src
|
|
34
|
+
}
|
|
35
|
+
if (!tenantId.value) return
|
|
36
|
+
|
|
37
|
+
let src = props.src
|
|
38
|
+
if (src.includes('://')) {
|
|
39
|
+
src = src.split('://')[1]
|
|
40
|
+
}
|
|
41
|
+
const parts = src.split('/')
|
|
42
|
+
const [container, file_path] = [parts[0], parts.slice(1).join('/')]
|
|
43
|
+
|
|
44
|
+
const { url } = await getFileUrl({
|
|
45
|
+
composable: '$fetch',
|
|
46
|
+
path: {
|
|
47
|
+
tenant_id: tenantId.value!,
|
|
48
|
+
container,
|
|
49
|
+
file_path,
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
imageUrl.value = url
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onMounted(() => {
|
|
56
|
+
fetchAndSetImageUrl()
|
|
57
|
+
})
|
|
58
|
+
</script>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AgentClassDtoReadable, getAgentClass } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
|
|
5
|
+
export const useAgentClass = defineQuery(() => {
|
|
6
|
+
const route = useRoute()
|
|
7
|
+
const { tenantId } = useTenant()
|
|
8
|
+
|
|
9
|
+
const { data: agentClass, isPending: agentClassIsLoading } = useQuery<AgentClassDtoReadable>({
|
|
10
|
+
key: () => ['tenant', tenantId.value, 'agent-classes', route.params.agent_class as string],
|
|
11
|
+
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
enabled: useTenantReady('agent_class'),
|
|
13
|
+
query: async () => {
|
|
14
|
+
return await getAgentClass({
|
|
15
|
+
composable: '$fetch',
|
|
16
|
+
path: {
|
|
17
|
+
tenant_id: tenantId.value!,
|
|
18
|
+
agent_class: route.params.agent_class as string,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
return {
|
|
24
|
+
agentClass,
|
|
25
|
+
agentClassIsLoading,
|
|
26
|
+
}
|
|
27
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type FullAgentInstanceDto, getAgentClassInstances } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
|
|
5
|
+
export const useAgentClassInstances = defineQuery(() => {
|
|
6
|
+
const route = useRoute()
|
|
7
|
+
const { tenantId } = useTenant()
|
|
8
|
+
|
|
9
|
+
const { data: agentClassInstances, isPending: agentClassInstancesAreLoading } = useQuery<FullAgentInstanceDto[]>({
|
|
10
|
+
key: () => ['tenant', tenantId.value, 'agent-class-instances', route.params.agent_class as string],
|
|
11
|
+
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
enabled: useTenantReady('agent_class'),
|
|
13
|
+
query: async () => {
|
|
14
|
+
return await getAgentClassInstances({
|
|
15
|
+
composable: '$fetch',
|
|
16
|
+
path: {
|
|
17
|
+
tenant_id: tenantId.value!,
|
|
18
|
+
agent_class: route.params.agent_class as string,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
return {
|
|
24
|
+
agentClassInstances,
|
|
25
|
+
agentClassInstancesAreLoading,
|
|
26
|
+
}
|
|
27
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type AgentClassDtoReadable, getAgentClasses } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
export type AgentClassDto = AgentClassDtoReadable
|
|
5
|
+
|
|
6
|
+
export const useAgentClasses = defineQuery((options?: { online?: boolean }) => {
|
|
7
|
+
const { tenantId } = useTenant()
|
|
8
|
+
|
|
9
|
+
const { data: agentClasses, isPending: agentClassesAreLoading } = useQuery<AgentClassDto[]>({
|
|
10
|
+
key: () => ['tenant', tenantId.value, 'agent-classes', options?.online],
|
|
11
|
+
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
enabled: useTenantReady(),
|
|
13
|
+
query: async () => {
|
|
14
|
+
return await getAgentClasses({
|
|
15
|
+
composable: '$fetch',
|
|
16
|
+
path: { tenant_id: tenantId.value! },
|
|
17
|
+
query: {
|
|
18
|
+
online: options?.online,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
return {
|
|
24
|
+
agentClasses,
|
|
25
|
+
agentClassesAreLoading,
|
|
26
|
+
}
|
|
27
|
+
})
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MinimalAgentInstanceDto, ThreadDto, ContextualizedAgentEvent } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export default (event: ContextualizedAgentEvent, thread: ThreadDto) => {
|
|
4
|
+
return computed<string | undefined>(() => thread.participating_agents
|
|
5
|
+
?.find((agent: MinimalAgentInstanceDto) => agent.agent_id == event.agent_id && agent.agent_class == event.agent_class)
|
|
6
|
+
?.agent_config?.icon,
|
|
7
|
+
)
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type FullAgentInstanceDto, getAgentInstance } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
|
|
5
|
+
export const useAgentInstance = defineQuery(() => {
|
|
6
|
+
const route = useRoute()
|
|
7
|
+
const { tenantId } = useTenant()
|
|
8
|
+
|
|
9
|
+
const { data: agentInstance, isPending: agentInstanceIsLoading } = useQuery<FullAgentInstanceDto>({
|
|
10
|
+
key: () => ['tenant', tenantId.value, 'agent-instances', route.params.agent_class as string, route.params.agent_id as string],
|
|
11
|
+
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
enabled: useTenantReady('agent_id', 'agent_class'),
|
|
13
|
+
query: async () => {
|
|
14
|
+
return await getAgentInstance({
|
|
15
|
+
composable: '$fetch',
|
|
16
|
+
path: {
|
|
17
|
+
tenant_id: tenantId.value!,
|
|
18
|
+
agent_id: route.params.agent_id as string,
|
|
19
|
+
agent_class: route.params.agent_class as string,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
return {
|
|
25
|
+
agentInstance,
|
|
26
|
+
agentInstanceIsLoading,
|
|
27
|
+
}
|
|
28
|
+
})
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getAgentInstanceThreads } from '@core/sdk/client'
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
|
|
5
|
+
export const useAgentInstanceThreads = defineQuery(() => {
|
|
6
|
+
const route = useRoute()
|
|
7
|
+
const { tenantId } = useTenant()
|
|
8
|
+
|
|
9
|
+
// Pagination state
|
|
10
|
+
const currentPage = ref(1)
|
|
11
|
+
const pageSize = ref(10)
|
|
12
|
+
|
|
13
|
+
// Query to fetch paginated threads
|
|
14
|
+
const threadQuery = useQuery({
|
|
15
|
+
key: () => [
|
|
16
|
+
'tenant',
|
|
17
|
+
tenantId.value,
|
|
18
|
+
'agent-instance-threads',
|
|
19
|
+
route.params.agent_id as string,
|
|
20
|
+
route.params.agent_class as string,
|
|
21
|
+
currentPage.value,
|
|
22
|
+
pageSize.value,
|
|
23
|
+
],
|
|
24
|
+
enabled: useTenantReady('agent_id', 'agent_class'),
|
|
25
|
+
query: async () => {
|
|
26
|
+
return await getAgentInstanceThreads({
|
|
27
|
+
composable: '$fetch',
|
|
28
|
+
path: {
|
|
29
|
+
tenant_id: tenantId.value!,
|
|
30
|
+
agent_id: route.params.agent_id as string,
|
|
31
|
+
agent_class: route.params.agent_class as string,
|
|
32
|
+
},
|
|
33
|
+
query: {
|
|
34
|
+
page: currentPage.value,
|
|
35
|
+
page_size: pageSize.value,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
placeholderData: previousData => previousData, // Keep previous data while fetching
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Update page size and refetch
|
|
43
|
+
const setPageSize = (newSize: number) => {
|
|
44
|
+
pageSize.value = newSize
|
|
45
|
+
// When changing page size, reset to first page to avoid out-of-range issues
|
|
46
|
+
currentPage.value = 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Update current page and refetch
|
|
50
|
+
const setPage = (newPage: number) => {
|
|
51
|
+
currentPage.value = newPage
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Extract pagination metadata
|
|
55
|
+
const paginationMeta = computed(() => {
|
|
56
|
+
const data = threadQuery.state.value?.data
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
total: data?.total ?? 0,
|
|
60
|
+
currentPage: data?.page ?? 1,
|
|
61
|
+
pageSize: data?.page_size ?? 10,
|
|
62
|
+
totalPages: data?.total_pages ?? 1,
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
threads: computed(() => threadQuery.state.value?.data?.threads ?? []),
|
|
68
|
+
isLoading: computed(() => threadQuery.asyncStatus.value === 'loading'),
|
|
69
|
+
pagination: paginationMeta,
|
|
70
|
+
currentPage,
|
|
71
|
+
pageSize,
|
|
72
|
+
setPage,
|
|
73
|
+
setPageSize,
|
|
74
|
+
refetch: threadQuery.refetch,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type FullAgentInstanceDto, getAllAgentInstances } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
export const useAgentInstances = defineQuery((options?: { online?: boolean }) => {
|
|
5
|
+
const { tenantId } = useTenant()
|
|
6
|
+
|
|
7
|
+
const { data: agentInstances, isPending: agentInstancesAreLoading } = useQuery<FullAgentInstanceDto[]>({
|
|
8
|
+
key: () => ['tenant', tenantId.value, 'agent-instances', options?.online],
|
|
9
|
+
staleTime: minutesToMilliseconds(5),
|
|
10
|
+
enabled: useTenantReady(),
|
|
11
|
+
query: async () => {
|
|
12
|
+
return await getAllAgentInstances({
|
|
13
|
+
composable: '$fetch',
|
|
14
|
+
path: { tenant_id: tenantId.value! },
|
|
15
|
+
query: {
|
|
16
|
+
online: options?.online,
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
return {
|
|
22
|
+
agentInstances,
|
|
23
|
+
agentInstancesAreLoading,
|
|
24
|
+
}
|
|
25
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { NavItem } from '@core/types/NavItem'
|
|
2
|
+
|
|
3
|
+
export function useAgentNavigation() {
|
|
4
|
+
const router = useRouter()
|
|
5
|
+
const route = useRoute()
|
|
6
|
+
const tenantPath = useTenantPath()
|
|
7
|
+
const { t } = useI18n()
|
|
8
|
+
|
|
9
|
+
const navItems = computed<NavItem[]>(() => [
|
|
10
|
+
{
|
|
11
|
+
name: t('agent.tabs.myAgents'),
|
|
12
|
+
key: 'agents',
|
|
13
|
+
path: '/service/agents',
|
|
14
|
+
isActive: () => route.path.startsWith(tenantPath('/service/agents')) && !route.path.includes('/service/agents/templates'),
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: t('agent.tabs.templates'),
|
|
18
|
+
key: 'templates',
|
|
19
|
+
path: '/service/agents/templates',
|
|
20
|
+
isActive: () => route.path.includes('/service/agents/templates'),
|
|
21
|
+
},
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
const activeNavItem = computed<NavItem | undefined>(() => {
|
|
25
|
+
return navItems.value.find((navItem: NavItem) => navItem.isActive())
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const toNavItem = (navItem: NavItem | null) => {
|
|
29
|
+
if (navItem) {
|
|
30
|
+
router.push(tenantPath(navItem.path))
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { navItems, activeNavItem, toNavItem }
|
|
35
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createAgentInstance, type CreateAgentInstanceRequest } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useCreateAgentInstance = defineMutation(() => {
|
|
4
|
+
const queryCache = useQueryCache()
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
mutateAsync: createAgentInstanceMutation,
|
|
8
|
+
isPending: isCreating,
|
|
9
|
+
error: createError,
|
|
10
|
+
} = useMutation({
|
|
11
|
+
mutation: async ({ agentClass, request, tenantId }: { agentClass: string, request: CreateAgentInstanceRequest, tenantId: string }) => {
|
|
12
|
+
const result = await createAgentInstance({
|
|
13
|
+
composable: '$fetch',
|
|
14
|
+
path: {
|
|
15
|
+
tenant_id: tenantId,
|
|
16
|
+
agent_class: agentClass,
|
|
17
|
+
},
|
|
18
|
+
body: request,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
// Invalidate agent instances cache to refresh the list
|
|
22
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId, 'agent-instances'] })
|
|
23
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId, 'agent-class-instances', agentClass] })
|
|
24
|
+
return result
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
createAgentInstance: createAgentInstanceMutation,
|
|
30
|
+
isCreating,
|
|
31
|
+
createError,
|
|
32
|
+
}
|
|
33
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { deleteAgentInstance } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useDeleteAgentInstance = defineMutation(() => {
|
|
4
|
+
const queryCache = useQueryCache()
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
mutateAsync: deleteAgentInstanceMutation,
|
|
8
|
+
isPending: isDeleting,
|
|
9
|
+
error: deleteError,
|
|
10
|
+
} = useMutation({
|
|
11
|
+
mutation: async ({ agentClass, agentId, tenantId }: { agentClass: string, agentId: string, tenantId: string }) => {
|
|
12
|
+
await deleteAgentInstance({
|
|
13
|
+
composable: '$fetch',
|
|
14
|
+
path: {
|
|
15
|
+
tenant_id: tenantId,
|
|
16
|
+
agent_class: agentClass,
|
|
17
|
+
agent_id: agentId,
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId, 'agent-instances'] })
|
|
22
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId, 'agent-class-instances', agentClass] })
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
deleteAgentInstance: deleteAgentInstanceMutation,
|
|
28
|
+
isDeleting,
|
|
29
|
+
deleteError,
|
|
30
|
+
}
|
|
31
|
+
})
|