Refactor backend and frontend cleanup paths

This commit is contained in:
curo1305
2026-06-16 11:50:17 +02:00
parent 6b56763689
commit e97ca164d7
29 changed files with 1106 additions and 2280 deletions
+15 -24
View File
@@ -61,7 +61,7 @@
<input
v-model="formByProvider[prov.provider_id].base_url"
type="text"
:placeholder="providerDefaultBaseUrl(prov.provider_id) || '(default)'"
:placeholder="providerDefaultBaseUrl(prov) || '(default)'"
class="block w-full rounded-lg px-3 py-2 text-sm border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors"
/>
</div>
@@ -71,7 +71,7 @@
<SearchableModelSelect
v-model="formByProvider[prov.provider_id].model_name"
:provider-id="prov.provider_id"
:placeholder="providerDefaultModel(prov.provider_id)"
:placeholder="providerDefaultModel(prov)"
/>
</div>
@@ -80,7 +80,7 @@
<input
v-model.number="formByProvider[prov.provider_id].context_chars"
type="number"
:placeholder="String(providerDefaultContextChars(prov.provider_id))"
:placeholder="String(providerDefaultContextChars(prov))"
min="1000"
max="2000000"
class="block w-full rounded-lg px-3 py-2 text-sm border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors"
@@ -131,8 +131,6 @@
</div>
</section>
<!-- Per-user AI provider assignment (existing DO NOT MODIFY) -->
<div v-if="loading" class="bg-white rounded-xl border border-gray-200 p-8 text-center">
<div class="flex items-center justify-center gap-2 text-gray-400 text-sm">
<span class="animate-spin rounded-full border-2 border-current border-t-transparent w-4 h-4"></span>
@@ -210,25 +208,6 @@ import AppIcon from '../../components/ui/AppIcon.vue'
import SearchableModelSelect from '../../components/ui/SearchableModelSelect.vue'
import BreadcrumbBar from '../../components/ui/BreadcrumbBar.vue'
const _PROVIDER_DEFAULTS = {
openai: { base_url: null, model: 'gpt-4o', context_chars: 120000 },
anthropic: { base_url: null, model: 'claude-sonnet-4-6', context_chars: 180000 },
gemini: { base_url: 'https://generativelanguage.googleapis.com/v1beta/openai/', model: 'gemini-2.0-flash', context_chars: 800000 },
groq: { base_url: 'https://api.groq.com/openai/v1', model: 'llama-3.3-70b-versatile', context_chars: 128000 },
xai: { base_url: 'https://api.x.ai/v1', model: 'grok-3-mini', context_chars: 128000 },
deepseek: { base_url: 'https://api.deepseek.com', model: 'deepseek-chat', context_chars: 60000 },
openrouter: { base_url: 'https://openrouter.ai/api/v1', model: 'anthropic/claude-3.5-sonnet', context_chars: 180000 },
mistral: { base_url: 'https://api.mistral.ai/v1', model: 'mistral-large-latest', context_chars: 128000 },
ollama: { base_url: 'http://host.docker.internal:11434/v1', model: 'llama3.2', context_chars: 8000 },
lmstudio: { base_url: 'http://host.docker.internal:1234/v1', model: 'gemma-4-e4b-it', context_chars: 8000 },
}
function providerDefaultBaseUrl(pid) { return _PROVIDER_DEFAULTS[pid]?.base_url || '' }
function providerDefaultModel(pid) { return _PROVIDER_DEFAULTS[pid]?.model || '' }
function providerDefaultContextChars(pid) { return _PROVIDER_DEFAULTS[pid]?.context_chars || 8000 }
const systemProviders = ref([])
const loadingSystem = ref(false)
const systemError = ref(null)
@@ -238,6 +217,18 @@ const testResults = reactive({})
const savingProvider = ref(null)
const testingProvider = ref(null)
function providerDefaultBaseUrl(provider) {
return provider?.base_url || ''
}
function providerDefaultModel(provider) {
return provider?.model_name || ''
}
function providerDefaultContextChars(provider) {
return provider?.context_chars || 8000
}
function toggleProvider(pid) {
openProviderId.value = openProviderId.value === pid ? null : pid
}
+31 -33
View File
@@ -291,7 +291,7 @@ function generateRandomPassword() {
const lower = 'abcdefghijkmnpqrstuvwxyz'
const digits = '23456789'
const special = '!@#$%^&*'
const charset = upper + lower + digits + special // 64 chars — 256 % 64 === 0, no modulo bias
const charset = upper + lower + digits + special
const arr = new Uint8Array(16)
crypto.getRandomValues(arr)
@@ -396,62 +396,60 @@ function cancelDelete() {
}
async function confirmDoDelete(id) {
pendingAction[id] = true
deleteError.value = null
try {
await runUserAction(id, async () => {
await api.adminDeleteUser(id, deletePassword.value)
users.value = users.value.filter(u => u.id !== id)
cancelDelete()
} catch (e) {
}, (e) => {
deleteError.value = e.message
} finally {
delete pendingAction[id]
}
})
}
async function confirmDoDeactivate(id) {
pendingAction[id] = true
actionError.value = null
try {
await runUserAction(id, async () => {
await api.adminDeactivateUser(id)
const idx = users.value.findIndex(u => u.id === id)
if (idx !== -1) {
users.value[idx] = { ...users.value[idx], is_active: false }
}
updateUser(id, { is_active: false })
confirmDeactivate.value = null
} catch (e) {
}, (e) => {
actionError.value = e.message
confirmDeactivate.value = null
} finally {
delete pendingAction[id]
}
})
}
async function reactivate(id) {
pendingAction[id] = true
actionError.value = null
try {
await runUserAction(id, async () => {
await api.adminReactivateUser(id)
const idx = users.value.findIndex(u => u.id === id)
if (idx !== -1) {
users.value[idx] = { ...users.value[idx], is_active: true }
}
} catch (e) {
updateUser(id, { is_active: true })
}, (e) => {
actionError.value = e.message
})
}
async function resetPassword(id) {
actionError.value = null
await runUserAction(id, () => api.adminResetUserPassword(id), (e) => {
actionError.value = e.message
})
}
async function runUserAction(id, action, onError) {
pendingAction[id] = true
try {
await action()
} catch (e) {
onError(e)
} finally {
delete pendingAction[id]
}
}
async function resetPassword(id) {
pendingAction[id] = true
actionError.value = null
try {
await api.adminResetUserPassword(id)
} catch (e) {
actionError.value = e.message
} finally {
delete pendingAction[id]
function updateUser(id, patch) {
const idx = users.value.findIndex(u => u.id === id)
if (idx !== -1) {
users.value[idx] = { ...users.value[idx], ...patch }
}
}