Keep the selected LLM profile visible while activating it.
The dropdown was bound to the previous server value, so a profile without a model snapped back to OpenRouter before the error was obvious. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
bef422a429
commit
59921fc5b5
|
|
@ -104,14 +104,19 @@ def seed_provider_settings(conn) -> None:
|
|||
|
||||
def seed_llm_profiles(conn) -> None:
|
||||
"""Named presets. Existing rows are not overwritten. Keys never stored."""
|
||||
ollama = conn.execute("SELECT id FROM llm_profiles WHERE id = ?", (OLLAMA_LAN_ID,)).fetchone()
|
||||
ollama = conn.execute("SELECT * FROM llm_profiles WHERE id = ?", (OLLAMA_LAN_ID,)).fetchone()
|
||||
if not ollama:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO llm_profiles (id, title, name, url, model, zdr, no_train)
|
||||
VALUES (?, ?, ?, ?, ?, 1, 1)
|
||||
""",
|
||||
(OLLAMA_LAN_ID, "Ollama (LAN)", "ollama", OLLAMA_LAN_URL, ""),
|
||||
(OLLAMA_LAN_ID, "Ollama (LAN)", "ollama", OLLAMA_LAN_URL, "phi3:mini"),
|
||||
)
|
||||
elif not (dict(ollama).get("model") or "").strip():
|
||||
conn.execute(
|
||||
"UPDATE llm_profiles SET model = ?, updated = datetime('now') WHERE id = ?",
|
||||
("phi3:mini", OLLAMA_LAN_ID),
|
||||
)
|
||||
for role in ROLES:
|
||||
row = conn.execute("SELECT * FROM provider_settings WHERE role = ?", (role,)).fetchone()
|
||||
|
|
|
|||
|
|
@ -113,8 +113,29 @@ export default function AdminProvidersPage() {
|
|||
}
|
||||
|
||||
const applyRole = async (role, profileId) => {
|
||||
const profile = profiles.find((item) => item.id === profileId)
|
||||
if (!profile) return
|
||||
setError('')
|
||||
setNotice('')
|
||||
setForms((prev) => ({
|
||||
...prev,
|
||||
[role]: {
|
||||
...(prev[role] || emptyRole()),
|
||||
role,
|
||||
name: profile.name || '',
|
||||
url: profile.url || '',
|
||||
model: profile.model || '',
|
||||
zdr: Boolean(profile.zdr),
|
||||
no_train: Boolean(profile.no_train),
|
||||
profile_id: profile.id,
|
||||
key: '',
|
||||
saveAsTitle: ''
|
||||
}
|
||||
}))
|
||||
if (!profile.model) {
|
||||
setError('Das Profil braucht ein Modell, bevor es einer Stufe zugeordnet werden kann.')
|
||||
return
|
||||
}
|
||||
setSaving(`activate-${role}`)
|
||||
try {
|
||||
const payload = await api(`/api/admin/providers/${role}/activate`, {
|
||||
|
|
@ -123,7 +144,7 @@ export default function AdminProvidersPage() {
|
|||
body: { profile_id: profileId }
|
||||
})
|
||||
applyPayload(payload)
|
||||
setNotice(`${role === 'detect' ? 'Maskierung' : 'Sprachmodell'}: Profil übernommen.`)
|
||||
setNotice(`${role === 'detect' ? 'Maskierung' : 'Sprachmodell'}: ${profile.title} ist aktiv.`)
|
||||
} catch (err) {
|
||||
setError(err.message)
|
||||
} finally {
|
||||
|
|
@ -226,21 +247,21 @@ export default function AdminProvidersPage() {
|
|||
<>
|
||||
{data.roles.map((role) => {
|
||||
const form = forms[role.role] || emptyRole()
|
||||
const selected = profiles.find((item) => item.id === form.profile_id)
|
||||
const view = selected
|
||||
? { ...role, ...form, local: selected.local, ready: selected.local ? Boolean(form.url && form.model) : role.ready }
|
||||
: role
|
||||
return (
|
||||
<form
|
||||
key={role.role}
|
||||
className="stack"
|
||||
onSubmit={(e) => { e.preventDefault(); saveRole(role.role) }}
|
||||
>
|
||||
<div key={role.role} className="stack">
|
||||
<h2>{role.title || role.role}</h2>
|
||||
{role.task && <p className="muted">{role.task}</p>}
|
||||
<dl className="meta">
|
||||
<dt>Status</dt>
|
||||
<dd>{statusLabel(role)}</dd>
|
||||
<dd>{statusLabel(view)}</dd>
|
||||
<dt>Key</dt>
|
||||
<dd>{role.key_present ? (role.key_source === 'generate' ? 'über Sprachmodell' : 'gesetzt') : (role.local ? 'nicht nötig (lokal)' : 'fehlt')}</dd>
|
||||
<dd>{view.key_present ? (view.key_source === 'generate' ? 'über Sprachmodell' : 'gesetzt') : (view.local ? 'nicht nötig (lokal)' : 'fehlt')}</dd>
|
||||
<dt>Modus</dt>
|
||||
<dd>{role.local ? 'lokal' : 'extern'} · {role.mode}</dd>
|
||||
<dd>{view.local ? 'lokal' : 'extern'} · {view.mode}</dd>
|
||||
</dl>
|
||||
<label>
|
||||
Aktives Profil
|
||||
|
|
@ -260,6 +281,10 @@ export default function AdminProvidersPage() {
|
|||
))}
|
||||
</select>
|
||||
</label>
|
||||
<form
|
||||
className="stack"
|
||||
onSubmit={(e) => { e.preventDefault(); saveRole(role.role) }}
|
||||
>
|
||||
<label>
|
||||
Name
|
||||
<input value={form.name} onChange={(e) => updateRole(role.role, 'name', e.target.value)} />
|
||||
|
|
@ -293,19 +318,20 @@ export default function AdminProvidersPage() {
|
|||
kein Provider-Training
|
||||
</label>
|
||||
<label>
|
||||
API-Key {role.key_present ? '(leer lassen, um den bestehenden zu behalten)' : '(für externe URL)'}
|
||||
API-Key {view.key_present ? '(leer lassen, um den bestehenden zu behalten)' : '(für externe URL)'}
|
||||
<input
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
value={form.key}
|
||||
onChange={(e) => updateRole(role.role, 'key', e.target.value)}
|
||||
placeholder={role.local ? 'lokal ohne Key' : (role.role === 'detect' ? 'leer = Key des Sprachmodells' : '')}
|
||||
placeholder={view.local ? 'lokal ohne Key' : (role.role === 'detect' ? 'leer = Key des Sprachmodells' : '')}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit" disabled={saving === role.role}>
|
||||
{saving === role.role ? 'Speichert …' : 'Stufe speichern'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user