@swiss-ai-hub/web 0.312.1 → 0.313.0
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.
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const SUPPORTED_SCHEMA_VERSIONS = ['1.0']
|
|
2
|
+
|
|
3
|
+
export type AgentConfig = {
|
|
4
|
+
schemaVersion: string
|
|
5
|
+
agentClass: string
|
|
6
|
+
agentId?: string
|
|
7
|
+
configuration: Record<string, unknown>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type AgentConfigImportReason = 'invalidJson' | 'invalidStructure' | 'missingFields' | 'unsupportedVersion'
|
|
11
|
+
|
|
12
|
+
export class AgentConfigImportError extends Error {
|
|
13
|
+
readonly reason: AgentConfigImportReason
|
|
14
|
+
|
|
15
|
+
constructor(reason: AgentConfigImportReason) {
|
|
16
|
+
super(reason)
|
|
17
|
+
this.name = 'AgentConfigImportError'
|
|
18
|
+
this.reason = reason
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
23
|
+
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
24
|
+
|
|
25
|
+
const parseAgentConfigExport = (text: string): AgentConfig => {
|
|
26
|
+
let parsed: unknown
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(text)
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new AgentConfigImportError('invalidJson')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!isRecord(parsed)) throw new AgentConfigImportError('invalidStructure')
|
|
35
|
+
|
|
36
|
+
const { schemaVersion, agentClass, agentId, configuration } = parsed
|
|
37
|
+
|
|
38
|
+
if (typeof schemaVersion !== 'string' || typeof agentClass !== 'string' || !agentClass || !isRecord(configuration)) {
|
|
39
|
+
throw new AgentConfigImportError('missingFields')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!SUPPORTED_SCHEMA_VERSIONS.includes(schemaVersion)) {
|
|
43
|
+
throw new AgentConfigImportError('unsupportedVersion')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
schemaVersion,
|
|
48
|
+
agentClass,
|
|
49
|
+
agentId: typeof agentId === 'string' ? agentId : undefined,
|
|
50
|
+
configuration,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const useImportAgentInstance = () => {
|
|
55
|
+
const readAgentConfigFile = async (file: File): Promise<AgentConfig> => {
|
|
56
|
+
const text = await file.text()
|
|
57
|
+
return parseAgentConfigExport(text)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { readAgentConfigFile }
|
|
61
|
+
}
|
package/i18n/locales/de.yaml
CHANGED
|
@@ -331,6 +331,17 @@ agent:
|
|
|
331
331
|
status: 'Status:'
|
|
332
332
|
online: Online
|
|
333
333
|
offline: Offline
|
|
334
|
+
import:
|
|
335
|
+
button: Importieren
|
|
336
|
+
error:
|
|
337
|
+
title: Import fehlgeschlagen
|
|
338
|
+
invalidJson: Die ausgewählte Datei ist kein gültiges JSON.
|
|
339
|
+
invalidStructure: Die ausgewählte Datei ist kein gültiger Agenten-Konfigurationsexport.
|
|
340
|
+
missingFields: In der Datei fehlen erforderliche Felder (schemaVersion, agentClass
|
|
341
|
+
oder configuration).
|
|
342
|
+
unsupportedVersion: Die Datei verwendet eine nicht unterstützte Export-Schemaversion.
|
|
343
|
+
blueprintNotFound: Die Agenten-Vorlage "{agentClass}" ist in dieser Umgebung
|
|
344
|
+
nicht verfügbar.
|
|
334
345
|
export:
|
|
335
346
|
button: Exportieren
|
|
336
347
|
configuration:
|
package/i18n/locales/en.yaml
CHANGED
|
@@ -328,6 +328,17 @@ agent:
|
|
|
328
328
|
status: 'Status:'
|
|
329
329
|
online: Online
|
|
330
330
|
offline: Offline
|
|
331
|
+
import:
|
|
332
|
+
button: Import
|
|
333
|
+
error:
|
|
334
|
+
title: Import failed
|
|
335
|
+
invalidJson: The selected file is not valid JSON.
|
|
336
|
+
invalidStructure: The selected file is not a valid agent configuration export.
|
|
337
|
+
missingFields: The file is missing required fields (schemaVersion, agentClass,
|
|
338
|
+
or configuration).
|
|
339
|
+
unsupportedVersion: The file uses an unsupported export schema version.
|
|
340
|
+
blueprintNotFound: The agent blueprint "{agentClass}" is not available in this
|
|
341
|
+
environment.
|
|
331
342
|
export:
|
|
332
343
|
button: Export
|
|
333
344
|
configuration:
|
package/i18n/locales/fr.yaml
CHANGED
|
@@ -329,6 +329,19 @@ agent:
|
|
|
329
329
|
status: 'Statut:'
|
|
330
330
|
online: En ligne
|
|
331
331
|
offline: Hors ligne
|
|
332
|
+
import:
|
|
333
|
+
button: Importer
|
|
334
|
+
error:
|
|
335
|
+
title: Échec de l'import
|
|
336
|
+
invalidJson: Le fichier sélectionné n'est pas un JSON valide.
|
|
337
|
+
invalidStructure: Le fichier sélectionné n'est pas un export de configuration
|
|
338
|
+
d'agent valide.
|
|
339
|
+
missingFields: Il manque des champs obligatoires dans le fichier (schemaVersion,
|
|
340
|
+
agentClass ou configuration).
|
|
341
|
+
unsupportedVersion: Le fichier utilise une version de schéma d'export non prise
|
|
342
|
+
en charge.
|
|
343
|
+
blueprintNotFound: Le modèle d'agent « {agentClass} » n'est pas disponible dans
|
|
344
|
+
cet environnement.
|
|
332
345
|
export:
|
|
333
346
|
button: Exporter
|
|
334
347
|
configuration:
|
package/i18n/locales/it.yaml
CHANGED
|
@@ -329,6 +329,19 @@ agent:
|
|
|
329
329
|
status: 'Stato:'
|
|
330
330
|
online: Online
|
|
331
331
|
offline: Offline
|
|
332
|
+
import:
|
|
333
|
+
button: Importa
|
|
334
|
+
error:
|
|
335
|
+
title: Importazione non riuscita
|
|
336
|
+
invalidJson: Il file selezionato non è un JSON valido.
|
|
337
|
+
invalidStructure: Il file selezionato non è un export di configurazione dell'agente
|
|
338
|
+
valido.
|
|
339
|
+
missingFields: Nel file mancano campi obbligatori (schemaVersion, agentClass
|
|
340
|
+
o configuration).
|
|
341
|
+
unsupportedVersion: Il file utilizza una versione dello schema di export non
|
|
342
|
+
supportata.
|
|
343
|
+
blueprintNotFound: Il modello di agente "{agentClass}" non è disponibile in
|
|
344
|
+
questo ambiente.
|
|
332
345
|
export:
|
|
333
346
|
button: Esporta
|
|
334
347
|
configuration:
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"license": "AGPL-3.0-or-later",
|
|
4
4
|
"author": "bbv Software Services AG (https://www.bbv.ch)",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.313.0",
|
|
7
7
|
"description": "Swiss AI Hub - Admin & Management UI (Nuxt 3 layer)",
|
|
8
8
|
"main": "./nuxt.config.ts",
|
|
9
9
|
"repository": {
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
@update:model-value="toNavItem"
|
|
17
17
|
/>
|
|
18
18
|
<div class="flex items-center gap-4">
|
|
19
|
+
<Button
|
|
20
|
+
icon="pi pi-upload"
|
|
21
|
+
severity="secondary"
|
|
22
|
+
:label="t('agent.import.button')"
|
|
23
|
+
@click="triggerImport"
|
|
24
|
+
/>
|
|
19
25
|
<Select
|
|
20
26
|
v-model="agentClass"
|
|
21
27
|
:options="agentClassOptions"
|
|
@@ -41,6 +47,14 @@
|
|
|
41
47
|
:placeholder="t('agent.list.search_placeholder')"
|
|
42
48
|
class="w-80"
|
|
43
49
|
/>
|
|
50
|
+
<input
|
|
51
|
+
ref="fileInput"
|
|
52
|
+
type="file"
|
|
53
|
+
accept="application/json,.json"
|
|
54
|
+
:aria-label="t('agent.import.button')"
|
|
55
|
+
class="hidden"
|
|
56
|
+
@change="handleFileSelected"
|
|
57
|
+
>
|
|
44
58
|
</div>
|
|
45
59
|
</div>
|
|
46
60
|
<div class="flex flex-col gap-8 pt-4">
|
|
@@ -120,6 +134,8 @@
|
|
|
120
134
|
</template>
|
|
121
135
|
|
|
122
136
|
<script setup lang="ts">
|
|
137
|
+
import { AgentConfigImportError } from '@core/composables/agent/useImportAgentInstance'
|
|
138
|
+
|
|
123
139
|
import type { FullAgentInstanceDto, WorkflowGraph } from '@core/sdk/client'
|
|
124
140
|
|
|
125
141
|
type AgentGroup = {
|
|
@@ -135,11 +151,15 @@ type AgentGroup = {
|
|
|
135
151
|
const router = useRouter()
|
|
136
152
|
const route = useRoute()
|
|
137
153
|
const tenantPath = useTenantPath()
|
|
154
|
+
const { tenantId } = useTenant()
|
|
138
155
|
const { t, locale } = useI18n()
|
|
139
156
|
|
|
157
|
+
const toast = useToast()
|
|
158
|
+
|
|
140
159
|
const { agentInstances, agentInstancesAreLoading, searchQuery, agentClass, status } = useAgentInstances()
|
|
141
160
|
const { agentClasses, agentClassesAreLoading } = useAgentClasses()
|
|
142
161
|
const { navItems, activeNavItem, toNavItem } = useAgentNavigation()
|
|
162
|
+
const { readAgentConfigFile } = useImportAgentInstance()
|
|
143
163
|
|
|
144
164
|
const isLoading = computed(() => agentInstancesAreLoading.value || agentClassesAreLoading.value)
|
|
145
165
|
const isTemplatesRoute = computed(() => route.path.includes('/service/agents/templates'))
|
|
@@ -148,6 +168,8 @@ const createModalOpen = ref(false)
|
|
|
148
168
|
const selectedClassForCreate = ref('')
|
|
149
169
|
const initialDataForCreate = ref<Record<string, unknown> | null>(null)
|
|
150
170
|
|
|
171
|
+
const fileInput = ref<HTMLInputElement | null>(null)
|
|
172
|
+
|
|
151
173
|
const workflowModalOpen = ref(false)
|
|
152
174
|
const selectedGroupForWorkflow = ref<AgentGroup | null>(null)
|
|
153
175
|
|
|
@@ -195,6 +217,50 @@ const handleClone = (agent: FullAgentInstanceDto) => {
|
|
|
195
217
|
createModalOpen.value = true
|
|
196
218
|
}
|
|
197
219
|
|
|
220
|
+
const triggerImport = () => fileInput.value?.click()
|
|
221
|
+
|
|
222
|
+
const handleFileSelected = async () => {
|
|
223
|
+
const input = fileInput.value
|
|
224
|
+
const file = input?.files?.[0]
|
|
225
|
+
if (input) input.value = ''
|
|
226
|
+
if (!file) return
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
const exported = await readAgentConfigFile(file)
|
|
230
|
+
|
|
231
|
+
const blueprintExists = agentClasses.value?.find(c => c.agent_class === exported.agentClass)
|
|
232
|
+
if (!blueprintExists) {
|
|
233
|
+
toast.add({
|
|
234
|
+
severity: 'error',
|
|
235
|
+
summary: t('agent.import.error.title'),
|
|
236
|
+
detail: t('agent.import.error.blueprintNotFound', { agentClass: exported.agentClass }),
|
|
237
|
+
life: 5000,
|
|
238
|
+
})
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const configuration: Record<string, unknown> = { ...exported.configuration, tenant_id: tenantId.value }
|
|
243
|
+
|
|
244
|
+
const orgMemory = configuration.org_memory
|
|
245
|
+
if (orgMemory && typeof orgMemory === 'object' && !Array.isArray(orgMemory)) {
|
|
246
|
+
configuration.org_memory = { ...orgMemory, tenant_id: tenantId.value }
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
selectedClassForCreate.value = exported.agentClass
|
|
250
|
+
initialDataForCreate.value = configuration
|
|
251
|
+
createModalOpen.value = true
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
const reason = error instanceof AgentConfigImportError ? error.reason : 'invalidStructure'
|
|
255
|
+
toast.add({
|
|
256
|
+
severity: 'error',
|
|
257
|
+
summary: t('agent.import.error.title'),
|
|
258
|
+
detail: t(`agent.import.error.${reason}`),
|
|
259
|
+
life: 5000,
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
198
264
|
const groupedAgents = computed<AgentGroup[]>(() => {
|
|
199
265
|
const groups = new Map<string, AgentGroup>()
|
|
200
266
|
|