mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-09-03 05:41:07 +00:00
refactor(ai): extract assistant into an official module (#749)
* feat(modules): expose host data boundaries * feat(modules): add frontend extension surfaces * refactor(ai): remove assistant from core * chore(ai): prepare the module extraction * fix(modules): load extension styles after the host bundle * chore(modules): lock SDK 3.3.0
This commit is contained in:
@@ -9,7 +9,6 @@ const AdminUsersView = () => import('./views/AdminUsersView.vue')
|
||||
const AdminUserEditView = () => import('./views/AdminUserEditView.vue')
|
||||
const AdminSettingsView = () => import('./views/AdminSettingsView.vue')
|
||||
const AdminMailConfigView = () => import('./views/settings/AdminMailConfigView.vue')
|
||||
const AdminAiConfigView = () => import('./views/settings/AdminAiConfigView.vue')
|
||||
const AdminPdfGenerationView = () => import('./views/settings/AdminPdfGenerationView.vue')
|
||||
const AdminBackupView = () => import('./views/settings/AdminBackupView.vue')
|
||||
const AdminFileDiskView = () => import('./views/settings/AdminFileDiskView.vue')
|
||||
@@ -88,14 +87,6 @@ export const adminRoutes: RouteRecordRaw[] = [
|
||||
},
|
||||
component: AdminMailConfigView,
|
||||
},
|
||||
{
|
||||
path: 'ai-configuration',
|
||||
name: 'admin.settings.ai',
|
||||
meta: {
|
||||
isSuperAdmin: true,
|
||||
},
|
||||
component: AdminAiConfigView,
|
||||
},
|
||||
{
|
||||
path: 'pdf-generation',
|
||||
name: 'admin.settings.pdf',
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
import { ref, computed, watchEffect } from 'vue'
|
||||
import { useRoute, useRouter, RouterView } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { extensionItems, extensionRegistry } from '@/scripts/extensions/runtime'
|
||||
|
||||
interface SettingsMenuItem {
|
||||
title: string
|
||||
@@ -73,11 +74,6 @@ const menuItems = computed<SettingsMenuItem[]>(() => [
|
||||
link: '/admin/administration/settings/mail-configuration',
|
||||
icon: 'EnvelopeIcon',
|
||||
},
|
||||
{
|
||||
title: t('settings.menu_title.ai_configuration'),
|
||||
link: '/admin/administration/settings/ai-configuration',
|
||||
icon: 'SparklesIcon',
|
||||
},
|
||||
{
|
||||
title: t('settings.menu_title.pdf_generation'),
|
||||
link: '/admin/administration/settings/pdf-generation',
|
||||
@@ -108,6 +104,11 @@ const menuItems = computed<SettingsMenuItem[]>(() => [
|
||||
link: '/admin/administration/settings/appearance',
|
||||
icon: 'PaintBrushIcon',
|
||||
},
|
||||
...extensionItems(extensionRegistry.adminSettingsNavigation.value).map((item) => ({
|
||||
title: t(item.title),
|
||||
link: router.resolve(item.to).fullPath,
|
||||
icon: item.icon,
|
||||
})),
|
||||
])
|
||||
|
||||
watchEffect(() => {
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useNotificationStore } from '@/scripts/stores/notification.store'
|
||||
import { aiService } from '@/scripts/api/services/ai.service'
|
||||
import type { AiConfig, AiDriverOption, AiTestPayload } from '@/scripts/types/ai-config'
|
||||
import { getErrorTranslationKey, handleApiError } from '@/scripts/utils/error-handling'
|
||||
import AiConfigurationForm from '@/scripts/features/company/settings/components/AiConfigurationForm.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const notificationStore = useNotificationStore()
|
||||
|
||||
const isSaving = ref(false)
|
||||
const isTesting = ref(false)
|
||||
const isFetchingInitialData = ref(false)
|
||||
const configData = ref<AiConfig | null>(null)
|
||||
const drivers = ref<AiDriverOption[]>([])
|
||||
|
||||
loadData()
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
isFetchingInitialData.value = true
|
||||
try {
|
||||
const [driversResponse, configResponse] = await Promise.all([
|
||||
aiService.getDrivers(),
|
||||
aiService.getGlobalConfig(),
|
||||
])
|
||||
drivers.value = driversResponse.ai_drivers
|
||||
configData.value = configResponse
|
||||
} catch (error: unknown) {
|
||||
const normalizedError = handleApiError(error)
|
||||
notificationStore.showNotification({
|
||||
type: 'error',
|
||||
message: getErrorTranslationKey(normalizedError.message) ?? normalizedError.message,
|
||||
})
|
||||
} finally {
|
||||
isFetchingInitialData.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function saveConfig(value: AiConfig): Promise<void> {
|
||||
isSaving.value = true
|
||||
try {
|
||||
const response = await aiService.saveGlobalConfig(value)
|
||||
if (response.success) {
|
||||
notificationStore.showNotification({
|
||||
type: 'success',
|
||||
message: 'settings.ai.saved',
|
||||
})
|
||||
configData.value = { ...value }
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
const normalizedError = handleApiError(error)
|
||||
notificationStore.showNotification({
|
||||
type: 'error',
|
||||
message: getErrorTranslationKey(normalizedError.message) ?? normalizedError.message,
|
||||
})
|
||||
} finally {
|
||||
isSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function testConnection(payload: AiTestPayload): Promise<void> {
|
||||
isTesting.value = true
|
||||
try {
|
||||
const response = await aiService.testGlobalConnection(payload)
|
||||
if (response.success) {
|
||||
notificationStore.showNotification({
|
||||
type: 'success',
|
||||
message: 'settings.ai.test_success',
|
||||
})
|
||||
} else if (response.error) {
|
||||
notificationStore.showNotification({
|
||||
type: 'error',
|
||||
message: t('settings.ai.errors.' + response.error, { error: response.message ?? '' }),
|
||||
})
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
const normalizedError = handleApiError(error)
|
||||
notificationStore.showNotification({
|
||||
type: 'error',
|
||||
message: getErrorTranslationKey(normalizedError.message) ?? normalizedError.message,
|
||||
})
|
||||
} finally {
|
||||
isTesting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseSettingCard
|
||||
:title="$t('settings.ai.title')"
|
||||
:description="$t('settings.ai.description')"
|
||||
>
|
||||
<div v-if="configData" class="mt-14">
|
||||
<AiConfigurationForm
|
||||
:config-data="configData"
|
||||
:drivers="drivers"
|
||||
:is-saving="isSaving"
|
||||
:is-testing="isTesting"
|
||||
:is-fetching-initial-data="isFetchingInitialData"
|
||||
@submit-data="saveConfig"
|
||||
@test-connection="testConnection"
|
||||
/>
|
||||
</div>
|
||||
</BaseSettingCard>
|
||||
</template>
|
||||
Reference in New Issue
Block a user