@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,83 @@
|
|
|
1
|
+
import type { EventChartInput } from '@core/types/EventChartInput'
|
|
2
|
+
|
|
3
|
+
import { useI18n } from '#imports'
|
|
4
|
+
|
|
5
|
+
export const useBasicEventStatistics = () => {
|
|
6
|
+
const { t } = useI18n()
|
|
7
|
+
|
|
8
|
+
const router = useRouter()
|
|
9
|
+
const route = useRoute()
|
|
10
|
+
const timeRange = useRouteQuery<'1h' | '24h' | '30d' | '365d'>('range', '30d', { route, router })
|
|
11
|
+
|
|
12
|
+
const { timeseries: startSeries, timeseriesIsLoading: startIsLoading } = useEventTimeseries({
|
|
13
|
+
eventName: 'StartEvent',
|
|
14
|
+
timeRange,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const { timeseries: allSeries, timeseriesIsLoading: allIsLoading } = useEventTimeseries({
|
|
18
|
+
timeRange,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const { timeseries: stopSeries, timeseriesIsLoading: stopIsLoading } = useEventTimeseries({
|
|
22
|
+
eventName: 'StopEvent',
|
|
23
|
+
timeRange,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const { timeseries: hitlSeries, timeseriesIsLoading: hitlIsLoading } = useEventTimeseries({
|
|
27
|
+
eventName: 'HumanInTheLoopRequestEvent',
|
|
28
|
+
timeRange,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const { timeseries: bitlSeries, timeseriesIsLoading: bitlIsLoading } = useEventTimeseries({
|
|
32
|
+
eventName: 'BotInTheLoopRequestEvent',
|
|
33
|
+
timeRange,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const { timeseries: aitlSeries, timeseriesIsLoading: aitlIsLoading } = useEventTimeseries({
|
|
37
|
+
eventName: 'AgentInTheLoopRequestEvent',
|
|
38
|
+
timeRange,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const { timeseries: exceptionSeries, timeseriesIsLoading: exstepsionIsLoading } = useEventTimeseries({
|
|
42
|
+
eventName: 'ExceptionEvent',
|
|
43
|
+
timeRange,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const charts = computed<EventChartInput[]>(() => [
|
|
47
|
+
{
|
|
48
|
+
title: t('event.statistics.charts.agentInvocations'),
|
|
49
|
+
isLoading: startIsLoading.value,
|
|
50
|
+
timeseriesInputs: [
|
|
51
|
+
{ name: t('event.statistics.charts.agentStart'), color: 'var(--p-surface-600)', timeseries: startSeries.value },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
title: t('event.statistics.charts.endEvents'),
|
|
56
|
+
isLoading: stopIsLoading.value || exstepsionIsLoading.value || hitlIsLoading.value || bitlIsLoading.value,
|
|
57
|
+
timeseriesInputs: [
|
|
58
|
+
{ name: t('event.statistics.charts.success'), color: 'var(--p-green-600)', timeseries: stopSeries.value },
|
|
59
|
+
{ name: t('event.statistics.charts.openHumanInTheLoop'), color: 'var(--p-yellow-500)', timeseries: hitlSeries.value },
|
|
60
|
+
{ name: t('event.statistics.charts.openBotInTheLoop'), color: 'var(--p-yellow-600)', timeseries: bitlSeries.value },
|
|
61
|
+
{ name: t('event.statistics.charts.error'), color: 'var(--p-red-600)', timeseries: exceptionSeries.value },
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: t('event.statistics.charts.delegations'),
|
|
66
|
+
isLoading: aitlIsLoading.value,
|
|
67
|
+
timeseriesInputs: [
|
|
68
|
+
{ name: t('event.statistics.charts.delegatedTaskAgentInTheLoop'), color: 'var(--p-blue-600)', timeseries: aitlSeries.value },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: t('event.statistics.charts.allEvents'),
|
|
73
|
+
isLoading: allIsLoading.value,
|
|
74
|
+
timeseriesInputs: [
|
|
75
|
+
{ name: t('event.statistics.charts.allEvents'), color: 'var(--p-surface-600)', timeseries: allSeries.value },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
])
|
|
79
|
+
return {
|
|
80
|
+
timeRange,
|
|
81
|
+
charts,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const EVENT_COLOR_PALETTE = [
|
|
2
|
+
'#34d399', '#fbbf24', '#60a5fa', '#c084fc', '#f87171',
|
|
3
|
+
'#fb923c', '#2dd4bf', '#a78bfa', '#f472b6', '#facc15',
|
|
4
|
+
'#4ade80', '#38bdf8', '#e879f9', '#a3e635', '#818cf8',
|
|
5
|
+
]
|
|
6
|
+
|
|
7
|
+
const FALLBACK_COLOR = '#94a3b8'
|
|
8
|
+
|
|
9
|
+
const hashString = (str: string): number => {
|
|
10
|
+
let hash = 0
|
|
11
|
+
for (let i = 0; i < str.length; i++) {
|
|
12
|
+
hash = ((hash << 5) - hash) + str.charCodeAt(i)
|
|
13
|
+
hash = hash & hash
|
|
14
|
+
}
|
|
15
|
+
return Math.abs(hash)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const useEventColor = () => {
|
|
19
|
+
const getEventColor = (eventName: string): string => {
|
|
20
|
+
if (!eventName) return FALLBACK_COLOR
|
|
21
|
+
return EVENT_COLOR_PALETTE[hashString(eventName) % EVENT_COLOR_PALETTE.length]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { getEventColor }
|
|
25
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ContextualizedAgentEvent } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
EventDisplayAgentInTheLoopRequestEvent,
|
|
5
|
+
EventDisplayAgentInTheLoopResponseEvent,
|
|
6
|
+
EventDisplayChunkEvent,
|
|
7
|
+
EventDisplayEmbeddingEvent,
|
|
8
|
+
EventDisplayHumanInTheLoopRequestEvent,
|
|
9
|
+
EventDisplayHumanInTheLoopResponseEvent,
|
|
10
|
+
EventDisplayLLMCostEvent,
|
|
11
|
+
EventDisplayLLMEvent,
|
|
12
|
+
EventDisplayLimitChatHistoryEvent,
|
|
13
|
+
EventDisplayRerankerEvent,
|
|
14
|
+
EventDisplayRetrieverEvent,
|
|
15
|
+
EventDisplayStandaloneQuestionCondenserEvent,
|
|
16
|
+
EventDisplayRAGSuccessStopEvent,
|
|
17
|
+
EventDisplayRAGFailureStopEvent,
|
|
18
|
+
EventDisplayStopEvent,
|
|
19
|
+
EventDisplayThoughtEvent,
|
|
20
|
+
EventDisplayToolEvent,
|
|
21
|
+
EventDisplayUnknownEvent,
|
|
22
|
+
EventDisplayUserMessageEvent,
|
|
23
|
+
EventDisplayRAGStartEvent,
|
|
24
|
+
EventDisplayGuardEvent,
|
|
25
|
+
EventDisplayGuardAcceptEvent,
|
|
26
|
+
EventDisplayGuardRejectionEvent,
|
|
27
|
+
EventDisplayRouterEvent,
|
|
28
|
+
EventDisplayExceptionEvent,
|
|
29
|
+
EventDisplayBaseRetrieveMemoryEvent,
|
|
30
|
+
EventDisplayBaseStoreMemoryEvent,
|
|
31
|
+
EventDisplayAddMemoryToChatHistoryEvent,
|
|
32
|
+
} from '#components'
|
|
33
|
+
|
|
34
|
+
export const useEventComponent = () => {
|
|
35
|
+
const resolveComponentForEvent = (event: ContextualizedAgentEvent) => {
|
|
36
|
+
const mapping = {
|
|
37
|
+
UserMessageEvent: EventDisplayUserMessageEvent,
|
|
38
|
+
RAGStartEvent: EventDisplayRAGStartEvent,
|
|
39
|
+
ChunkEvent: EventDisplayChunkEvent,
|
|
40
|
+
LLMEvent: EventDisplayLLMEvent,
|
|
41
|
+
LLMCostEvent: EventDisplayLLMCostEvent,
|
|
42
|
+
LimitChatHistoryEvent: EventDisplayLimitChatHistoryEvent,
|
|
43
|
+
ThoughtEvent: EventDisplayThoughtEvent,
|
|
44
|
+
EmbeddingEvent: EventDisplayEmbeddingEvent,
|
|
45
|
+
RerankerEvent: EventDisplayRerankerEvent,
|
|
46
|
+
RetrieverEvent: EventDisplayRetrieverEvent,
|
|
47
|
+
StandaloneQuestionCondenserEvent: EventDisplayStandaloneQuestionCondenserEvent,
|
|
48
|
+
ToolEvent: EventDisplayToolEvent,
|
|
49
|
+
AgentInTheLoopRequestEvent: EventDisplayAgentInTheLoopRequestEvent,
|
|
50
|
+
AgentInTheLoopResponseEvent: EventDisplayAgentInTheLoopResponseEvent,
|
|
51
|
+
HumanInTheLoopRequestEvent: EventDisplayHumanInTheLoopRequestEvent,
|
|
52
|
+
HumanInTheLoopResponseEvent: EventDisplayHumanInTheLoopResponseEvent,
|
|
53
|
+
GuardEvent: EventDisplayGuardEvent,
|
|
54
|
+
GuardAcceptEvent: EventDisplayGuardAcceptEvent,
|
|
55
|
+
GuardRejectionEvent: EventDisplayGuardRejectionEvent,
|
|
56
|
+
AgentSuitabilityAcceptEvent: EventDisplayGuardAcceptEvent,
|
|
57
|
+
AgentSuitabilityRejectEvent: EventDisplayGuardRejectionEvent,
|
|
58
|
+
ContextSufficientAcceptEvent: EventDisplayGuardAcceptEvent,
|
|
59
|
+
ContextInsufficientRejectEvent: EventDisplayGuardRejectionEvent,
|
|
60
|
+
FewShotAcceptEvent: EventDisplayGuardAcceptEvent,
|
|
61
|
+
FewShotRejectEvent: EventDisplayGuardRejectionEvent,
|
|
62
|
+
SensitiveInfoAcceptEvent: EventDisplayGuardAcceptEvent,
|
|
63
|
+
SensitiveInfoRejectEvent: EventDisplayGuardRejectionEvent,
|
|
64
|
+
RAGSuccessStopEvent: EventDisplayRAGSuccessStopEvent,
|
|
65
|
+
RAGFailureStopEvent: EventDisplayRAGFailureStopEvent,
|
|
66
|
+
StopEvent: EventDisplayStopEvent,
|
|
67
|
+
RouterEvent: EventDisplayRouterEvent,
|
|
68
|
+
ExceptionEvent: EventDisplayExceptionEvent,
|
|
69
|
+
BaseRetrieveMemoryEvent: EventDisplayBaseRetrieveMemoryEvent,
|
|
70
|
+
BaseStoreMemoryEvent: EventDisplayBaseStoreMemoryEvent,
|
|
71
|
+
AddMemoryToChatHistoryEvent: EventDisplayAddMemoryToChatHistoryEvent,
|
|
72
|
+
}
|
|
73
|
+
const exact_match = mapping[event.event._event_name]
|
|
74
|
+
if (exact_match) {
|
|
75
|
+
return exact_match
|
|
76
|
+
}
|
|
77
|
+
for (const eventName in mapping) {
|
|
78
|
+
if (event.event._parent_event_names.includes(eventName)) {
|
|
79
|
+
return mapping[eventName]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return EventDisplayUnknownEvent
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
resolveComponentForEvent,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type EventTimeseries,
|
|
3
|
+
getAgentEventTimeseries,
|
|
4
|
+
} from '@core/sdk/client'
|
|
5
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
6
|
+
import { useRoute } from 'vue-router'
|
|
7
|
+
|
|
8
|
+
export const useEventTimeseries = ({ eventName, timeRange, agentClass, agentId }: { eventName?: string, timeRange: Ref<string>, agentClass?: string, agentId?: string }) => {
|
|
9
|
+
const route = useRoute()
|
|
10
|
+
const { tenantId } = useTenant()
|
|
11
|
+
|
|
12
|
+
const query = {
|
|
13
|
+
agent_class: agentClass ?? route?.params?.agent_class,
|
|
14
|
+
agent_id: agentId ?? route?.params?.agent_id,
|
|
15
|
+
thread_id: route?.params?.thread_id,
|
|
16
|
+
event_name: eventName,
|
|
17
|
+
}
|
|
18
|
+
const { data: timeseries, isPending: timeseriesIsLoading } = useQuery<EventTimeseries>({
|
|
19
|
+
key: () => ['tenant', tenantId.value, 'events', 'agents', 'timeseries', timeRange.value, query],
|
|
20
|
+
staleTime: minutesToMilliseconds(5),
|
|
21
|
+
enabled: useTenantReady(),
|
|
22
|
+
query: async () => {
|
|
23
|
+
return await getAgentEventTimeseries({
|
|
24
|
+
composable: '$fetch',
|
|
25
|
+
path: {
|
|
26
|
+
tenant_id: tenantId.value!,
|
|
27
|
+
time_range: timeRange.value,
|
|
28
|
+
},
|
|
29
|
+
query,
|
|
30
|
+
})
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
timeseries,
|
|
36
|
+
timeseriesIsLoading,
|
|
37
|
+
timeRange,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EventBucket, EventTimeseries } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useEventTimeseriesStats = (timeseries: EventTimeseries) => {
|
|
4
|
+
const sum = computed(() => {
|
|
5
|
+
return timeseries.buckets.reduce((sum, bucket: EventBucket) => sum + bucket.total_events, 0)
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const isTrendingUp = computed<boolean>(() => {
|
|
9
|
+
const localBuckets = timeseries.buckets
|
|
10
|
+
if (!localBuckets || localBuckets.length < 2) return false
|
|
11
|
+
|
|
12
|
+
const halfwayIndex = Math.floor(localBuckets.length / 2)
|
|
13
|
+
const firstHalfBuckets = localBuckets.slice(0, halfwayIndex)
|
|
14
|
+
const secondHalfBuckets = localBuckets.slice(halfwayIndex)
|
|
15
|
+
|
|
16
|
+
const sum1 = firstHalfBuckets.reduce((sum, bucket: EventBucket) => sum + (bucket.total_events || 0), 0)
|
|
17
|
+
const sum2 = secondHalfBuckets.reduce((sum, bucket: EventBucket) => sum + (bucket.total_events || 0), 0)
|
|
18
|
+
|
|
19
|
+
return sum2 > sum1
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
sum,
|
|
24
|
+
isTrendingUp,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
initiateDocumentUpload,
|
|
3
|
+
validateDocumentUpload,
|
|
4
|
+
type DocumentUploadRequest,
|
|
5
|
+
type DocumentUploadValidationRequest,
|
|
6
|
+
} from '@core/sdk/client'
|
|
7
|
+
|
|
8
|
+
export interface UploadFileOptions {
|
|
9
|
+
filename: string
|
|
10
|
+
file: File
|
|
11
|
+
namespace: string
|
|
12
|
+
database: string
|
|
13
|
+
tenantId: string
|
|
14
|
+
onProgress?: () => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Map extensions to MIME types for files where browser fails
|
|
18
|
+
const MIME_TYPE_OVERRIDES: Record<string, string> = {
|
|
19
|
+
'.md': 'text/markdown',
|
|
20
|
+
'.markdown': 'text/markdown',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const getMimeType = (file: File): string => {
|
|
24
|
+
if (file.type) {
|
|
25
|
+
return file.type
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ext = '.' + (file.name.split('.').pop()?.toLowerCase() ?? '')
|
|
29
|
+
return MIME_TYPE_OVERRIDES[ext] || 'application/octet-stream'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const useFileUpload = defineMutation(() => {
|
|
33
|
+
const queryCache = useQueryCache()
|
|
34
|
+
|
|
35
|
+
const { mutateAsync: uploadFileMutation } = useMutation({
|
|
36
|
+
mutation: async (options: UploadFileOptions) => {
|
|
37
|
+
const { filename, file, namespace, database, tenantId } = options
|
|
38
|
+
|
|
39
|
+
const contentType = getMimeType(file)
|
|
40
|
+
|
|
41
|
+
const initiateRequest: DocumentUploadRequest = {
|
|
42
|
+
filename,
|
|
43
|
+
content_type: contentType,
|
|
44
|
+
content_length: file.size,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const initiateResponse = await initiateDocumentUpload({
|
|
48
|
+
composable: '$fetch',
|
|
49
|
+
body: initiateRequest,
|
|
50
|
+
path: {
|
|
51
|
+
tenant_id: tenantId,
|
|
52
|
+
database,
|
|
53
|
+
namespace,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
await fetch(initiateResponse.upload_url, {
|
|
58
|
+
method: 'PUT',
|
|
59
|
+
body: file,
|
|
60
|
+
headers: {
|
|
61
|
+
'Content-Type': contentType,
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const validationRequest: DocumentUploadValidationRequest = {
|
|
66
|
+
file_path: initiateResponse.object_key,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await validateDocumentUpload({
|
|
70
|
+
composable: '$fetch',
|
|
71
|
+
body: validationRequest,
|
|
72
|
+
path: {
|
|
73
|
+
tenant_id: tenantId,
|
|
74
|
+
database,
|
|
75
|
+
namespace,
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
return initiateResponse.upload_id
|
|
80
|
+
},
|
|
81
|
+
onSuccess: (data, variables) => {
|
|
82
|
+
queryCache.invalidateQueries({
|
|
83
|
+
key: ['tenant', variables.tenantId, 'knowledge'],
|
|
84
|
+
})
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
uploadFile: uploadFileMutation,
|
|
90
|
+
}
|
|
91
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getSupportedFileTypes } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
export const useSupportedFileTypes = defineQuery(() => {
|
|
5
|
+
const { tenantId } = useTenant()
|
|
6
|
+
|
|
7
|
+
const { data: supportedFileTypes } = useQuery<string[]>({
|
|
8
|
+
key: () => ['tenant', tenantId.value, 'supportedFileTypes'],
|
|
9
|
+
staleTime: minutesToMilliseconds(60),
|
|
10
|
+
enabled: useTenantReady(),
|
|
11
|
+
query: async () => {
|
|
12
|
+
return await getSupportedFileTypes({
|
|
13
|
+
composable: '$fetch',
|
|
14
|
+
path: { tenant_id: tenantId.value! },
|
|
15
|
+
})
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
supportedFileTypes,
|
|
21
|
+
}
|
|
22
|
+
})
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { merge } from 'lodash-es'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type FormElement,
|
|
5
|
+
type GroupConfig,
|
|
6
|
+
type RepeaterConfig,
|
|
7
|
+
buildFormKitSchema,
|
|
8
|
+
categorizeFormElements,
|
|
9
|
+
coerceNullableToggles,
|
|
10
|
+
extractGroupConfigs,
|
|
11
|
+
extractRepeaterConfigs,
|
|
12
|
+
getFormkitType,
|
|
13
|
+
getNestedValue,
|
|
14
|
+
seedFormDefaults,
|
|
15
|
+
seedNullableToggles,
|
|
16
|
+
setNestedValue,
|
|
17
|
+
} from './useFormKitTransform'
|
|
18
|
+
|
|
19
|
+
import type { FormKitSchemaNode } from '@formkit/core'
|
|
20
|
+
import type { Ref } from 'vue'
|
|
21
|
+
|
|
22
|
+
export interface ClassDataLike {
|
|
23
|
+
form: unknown[]
|
|
24
|
+
templates?: Array<Record<string, unknown>>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Drops keys whose matching form-schema node is a group/repeater and whose incoming
|
|
29
|
+
* value is `null`. FormKit rejects `null` for group values (must be an object) and for
|
|
30
|
+
* repeater values (must be an array), so template payloads that serialise optional
|
|
31
|
+
* nested configs as `null` (Pydantic `Form | None = None`) would otherwise throw during
|
|
32
|
+
* hydration.
|
|
33
|
+
*/
|
|
34
|
+
export function stripNullsForGroups(
|
|
35
|
+
data: Record<string, unknown>,
|
|
36
|
+
elements: FormElement[],
|
|
37
|
+
): Record<string, unknown> {
|
|
38
|
+
const result: Record<string, unknown> = {}
|
|
39
|
+
|
|
40
|
+
for (const [key, value] of Object.entries(data)) {
|
|
41
|
+
const element = elements.find(el => el.name === key)
|
|
42
|
+
if (!element) {
|
|
43
|
+
result[key] = value
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
const formkitType = getFormkitType(element)
|
|
47
|
+
|
|
48
|
+
if ((formkitType === 'group' || formkitType === 'repeater') && value === null) {
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const children = (element.children as FormElement[] | undefined) ?? []
|
|
53
|
+
|
|
54
|
+
if (formkitType === 'group' && value && typeof value === 'object' && !Array.isArray(value)) {
|
|
55
|
+
result[key] = stripNullsForGroups(value as Record<string, unknown>, children)
|
|
56
|
+
}
|
|
57
|
+
else if (formkitType === 'repeater' && Array.isArray(value)) {
|
|
58
|
+
result[key] = value.map(item =>
|
|
59
|
+
item && typeof item === 'object' && !Array.isArray(item)
|
|
60
|
+
? stripNullsForGroups(item as Record<string, unknown>, children)
|
|
61
|
+
: item,
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
result[key] = value
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return result
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface CreateInstanceFormOptions<T extends ClassDataLike> {
|
|
73
|
+
/** Reactive list of available class definitions (agent classes, process classes, etc.) */
|
|
74
|
+
classes: Ref<T[] | undefined>
|
|
75
|
+
/** Property name used to identify a class (e.g. 'agent_class', 'process_class') */
|
|
76
|
+
classField: string
|
|
77
|
+
/** Property name used as fallback label in templates (e.g. 'agent_id', 'process_id') */
|
|
78
|
+
idField: string
|
|
79
|
+
/** Getter for the initial class selection (from component props) */
|
|
80
|
+
initialClass: () => string
|
|
81
|
+
/** Current locale ref for i18n-aware form rendering */
|
|
82
|
+
locale: Ref<string>
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Shared form logic for creating agent/process instances from class definitions.
|
|
87
|
+
*
|
|
88
|
+
* Handles class selection, FormKit schema generation, stepper navigation,
|
|
89
|
+
* and form data lifecycle. Template/clone pre-filling is done via applyInitialData().
|
|
90
|
+
* Domain-specific submission logic stays in the calling component.
|
|
91
|
+
*/
|
|
92
|
+
export function useCreateInstanceForm<T extends ClassDataLike>(options: CreateInstanceFormOptions<T>) {
|
|
93
|
+
const { classes, classField, initialClass, locale } = options
|
|
94
|
+
|
|
95
|
+
const selectedClass = ref<string>(initialClass())
|
|
96
|
+
const formData = ref<Record<string, unknown>>({})
|
|
97
|
+
const activeStep = ref(0)
|
|
98
|
+
|
|
99
|
+
watch(initialClass, (newClass) => {
|
|
100
|
+
if (newClass) {
|
|
101
|
+
selectedClass.value = newClass
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const selectedClassData = computed<T | undefined>(() => {
|
|
106
|
+
if (!selectedClass.value || !classes.value) return undefined
|
|
107
|
+
return classes.value.find(c => c[classField as keyof T] === selectedClass.value)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const configForm = computed(() => selectedClassData.value?.form ?? [])
|
|
111
|
+
|
|
112
|
+
const categorizedElements = computed(() => {
|
|
113
|
+
return categorizeFormElements(configForm.value as FormElement[])
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const simpleElementsSchema = computed<FormKitSchemaNode[]>(() => {
|
|
117
|
+
return buildFormKitSchema(categorizedElements.value.simpleElements, { locale: locale.value })
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const groupConfigs = computed<GroupConfig[]>(() => {
|
|
121
|
+
return extractGroupConfigs(configForm.value as FormElement[], locale.value)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
const repeaterConfigs = computed<RepeaterConfig[]>(() => {
|
|
125
|
+
return extractRepeaterConfigs(configForm.value as FormElement[], locale.value)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const hasSimpleElements = computed(() => simpleElementsSchema.value.length > 0)
|
|
129
|
+
|
|
130
|
+
function getGroupStepIndex(groupIndex: number): number {
|
|
131
|
+
return (hasSimpleElements.value ? 1 : 0) + groupIndex
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getRepeaterStepIndex(repeaterIndex: number): number {
|
|
135
|
+
return (hasSimpleElements.value ? 1 : 0) + groupConfigs.value.length + repeaterIndex
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getRepeaterData(path: string): Record<string, unknown>[] {
|
|
139
|
+
return getNestedValue(formData.value, path)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function setRepeaterData(path: string, value: Record<string, unknown>[]): void {
|
|
143
|
+
setNestedValue(formData.value, path, value)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
watch(selectedClassData, (newClass) => {
|
|
147
|
+
if (newClass?.form && newClass.form.length > 0) {
|
|
148
|
+
const base = initializeGroupData(configForm.value as FormElement[], {})
|
|
149
|
+
formData.value = seedFormDefaults(base, configForm.value as FormElement[])
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
formData.value = {}
|
|
153
|
+
}
|
|
154
|
+
}, { immediate: true })
|
|
155
|
+
|
|
156
|
+
function initializeElementData(
|
|
157
|
+
element: FormElement,
|
|
158
|
+
result: Record<string, unknown>,
|
|
159
|
+
recursiveFn: (elements: FormElement[], data: Record<string, unknown>) => Record<string, unknown>,
|
|
160
|
+
): void {
|
|
161
|
+
const formkitType = getFormkitType(element)
|
|
162
|
+
const name = element.name as string
|
|
163
|
+
const children = element.children as FormElement[] | undefined
|
|
164
|
+
const hasChildren = children && Array.isArray(children)
|
|
165
|
+
|
|
166
|
+
if (formkitType === 'group') {
|
|
167
|
+
result[name] = result[name] ?? {}
|
|
168
|
+
if (hasChildren) {
|
|
169
|
+
result[name] = recursiveFn(children, result[name] as Record<string, unknown>)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (formkitType === 'repeater') {
|
|
173
|
+
result[name] = result[name] ?? []
|
|
174
|
+
if (Array.isArray(result[name]) && hasChildren) {
|
|
175
|
+
result[name] = (result[name] as Record<string, unknown>[]).map(item => recursiveFn(children, item))
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function initializeGroupData(
|
|
181
|
+
formElements: FormElement[],
|
|
182
|
+
data: Record<string, unknown>,
|
|
183
|
+
): Record<string, unknown> {
|
|
184
|
+
const result = { ...data }
|
|
185
|
+
for (const element of formElements) {
|
|
186
|
+
initializeElementData(element, result, initializeGroupData)
|
|
187
|
+
}
|
|
188
|
+
return result
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function cleanFormData(data: Record<string, unknown>): Record<string, unknown> {
|
|
192
|
+
const result: Record<string, unknown> = {}
|
|
193
|
+
// FormKit artifacts that should be stripped from submissions
|
|
194
|
+
const formkitArtifacts = new Set(['slots'])
|
|
195
|
+
|
|
196
|
+
for (const [key, value] of Object.entries(data)) {
|
|
197
|
+
if (formkitArtifacts.has(key)) continue
|
|
198
|
+
// Strip the internal repeater validation mirror written by FormKit/Repeater.vue.
|
|
199
|
+
if (key.startsWith('__validate__')) continue
|
|
200
|
+
|
|
201
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
202
|
+
result[key] = cleanFormData(value as Record<string, unknown>)
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
result[key] = value
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return result
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function applyInitialData(data: Record<string, unknown>) {
|
|
213
|
+
// Seed toggles from the raw data so that `field: null` in a template becomes
|
|
214
|
+
// `__field__enabled: false`. If we seeded after stripping nulls and merging
|
|
215
|
+
// against the `{}` placeholder from initializeGroupData, every nullable group
|
|
216
|
+
// would look truthy and the toggle would come up enabled.
|
|
217
|
+
const seeded = seedNullableToggles(data, configForm.value as FormElement[])
|
|
218
|
+
const base = initializeGroupData(configForm.value as FormElement[], {})
|
|
219
|
+
const withDefaults = seedFormDefaults(base, configForm.value as FormElement[])
|
|
220
|
+
const sanitized = stripNullsForGroups(seeded, configForm.value as FormElement[])
|
|
221
|
+
formData.value = merge(withDefaults, sanitized)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function resetForm() {
|
|
225
|
+
selectedClass.value = initialClass()
|
|
226
|
+
formData.value = {}
|
|
227
|
+
activeStep.value = 0
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
selectedClass,
|
|
232
|
+
formData,
|
|
233
|
+
activeStep,
|
|
234
|
+
selectedClassData,
|
|
235
|
+
configForm,
|
|
236
|
+
categorizedElements,
|
|
237
|
+
simpleElementsSchema,
|
|
238
|
+
groupConfigs,
|
|
239
|
+
repeaterConfigs,
|
|
240
|
+
hasSimpleElements,
|
|
241
|
+
getGroupStepIndex,
|
|
242
|
+
getRepeaterStepIndex,
|
|
243
|
+
getRepeaterData,
|
|
244
|
+
setRepeaterData,
|
|
245
|
+
initializeGroupData,
|
|
246
|
+
cleanFormData,
|
|
247
|
+
coerceNullableToggles,
|
|
248
|
+
applyInitialData,
|
|
249
|
+
resetForm,
|
|
250
|
+
}
|
|
251
|
+
}
|