AI-admin: «Generer + restart gateway»-knapp
Utvider generate-config endepunktet med ?restart=true som finner og restarter ai-gateway docker-containeren etter config-generering. Ny grønn knapp i UI gjør begge operasjoner i ett klikk. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b1a7e55fff
commit
177e4b6b66
2 changed files with 66 additions and 8 deletions
|
|
@ -3,11 +3,13 @@ import type { RequestHandler } from './$types';
|
||||||
import { sql } from '$lib/server/db';
|
import { sql } from '$lib/server/db';
|
||||||
import { writeFileSync } from 'node:fs';
|
import { writeFileSync } from 'node:fs';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
|
import { execSync } from 'node:child_process';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/admin/ai/generate-config — Generer LiteLLM config.yaml fra PG.
|
* POST /api/admin/ai/generate-config — Generer LiteLLM config.yaml fra PG.
|
||||||
|
* Query: ?restart=true — restart ai-gateway etter generering.
|
||||||
*/
|
*/
|
||||||
export const POST: RequestHandler = async ({ locals }) => {
|
export const POST: RequestHandler = async ({ locals, url }) => {
|
||||||
if (!locals.workspace || !locals.user) error(401);
|
if (!locals.workspace || !locals.user) error(401);
|
||||||
|
|
||||||
// Hent aktive aliaser med aktive providers
|
// Hent aktive aliaser med aktive providers
|
||||||
|
|
@ -46,9 +48,38 @@ export const POST: RequestHandler = async ({ locals }) => {
|
||||||
const configPath = join(process.cwd(), 'config', 'litellm', 'config.yaml');
|
const configPath = join(process.cwd(), 'config', 'litellm', 'config.yaml');
|
||||||
writeFileSync(configPath, yaml, 'utf-8');
|
writeFileSync(configPath, yaml, 'utf-8');
|
||||||
|
|
||||||
|
// Restart ai-gateway container hvis forespurt
|
||||||
|
const shouldRestart = url.searchParams.get('restart') === 'true';
|
||||||
|
let restarted = false;
|
||||||
|
let restartError = '';
|
||||||
|
|
||||||
|
if (shouldRestart) {
|
||||||
|
try {
|
||||||
|
// Finn container med "ai-gateway" i navnet
|
||||||
|
const name = execSync('docker ps --format "{{.Names}}" | grep ai-gateway', {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
timeout: 5000
|
||||||
|
}).trim();
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
execSync(`docker restart ${name}`, { timeout: 30000 });
|
||||||
|
restarted = true;
|
||||||
|
} else {
|
||||||
|
restartError = 'ai-gateway container ikke funnet';
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
restartError = e.message || 'Kunne ikke restarte ai-gateway';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
ok: true,
|
ok: true,
|
||||||
message: 'Config generert. Restart ai-gateway for å aktivere.',
|
message: restarted
|
||||||
model_count: rows.length
|
? 'Config generert og ai-gateway restartet.'
|
||||||
|
: restartError
|
||||||
|
? `Config generert, men restart feilet: ${restartError}`
|
||||||
|
: 'Config generert. Restart ai-gateway for å aktivere.',
|
||||||
|
model_count: rows.length,
|
||||||
|
restarted
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -395,16 +395,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateConfig() {
|
let configLoading = $state(false);
|
||||||
|
|
||||||
|
async function generateConfig(restart = false) {
|
||||||
configMsg = '';
|
configMsg = '';
|
||||||
errorMsg = '';
|
errorMsg = '';
|
||||||
|
configLoading = true;
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/admin/ai/generate-config', { method: 'POST' });
|
const url = restart
|
||||||
|
? '/api/admin/ai/generate-config?restart=true'
|
||||||
|
: '/api/admin/ai/generate-config';
|
||||||
|
const res = await fetch(url, { method: 'POST' });
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (!res.ok) throw new Error(data.message ?? 'Feil');
|
if (!res.ok) throw new Error(data.message ?? 'Feil');
|
||||||
configMsg = `${data.message} (${data.model_count} modeller)`;
|
configMsg = `${data.message} (${data.model_count} modeller)`;
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
errorMsg = e.message || 'Feil ved config-generering';
|
errorMsg = e.message || 'Feil ved config-generering';
|
||||||
|
} finally {
|
||||||
|
configLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -761,11 +769,16 @@
|
||||||
<section>
|
<section>
|
||||||
<h3>Konfigurasjon</h3>
|
<h3>Konfigurasjon</h3>
|
||||||
<div class="config-box">
|
<div class="config-box">
|
||||||
<button class="generate-btn" onclick={generateConfig}>Generer config.yaml</button>
|
<button class="generate-btn" onclick={() => generateConfig(false)} disabled={configLoading}>
|
||||||
|
Generer config.yaml
|
||||||
|
</button>
|
||||||
|
<button class="generate-btn generate-btn--restart" onclick={() => generateConfig(true)} disabled={configLoading}>
|
||||||
|
{configLoading ? 'Jobber...' : 'Generer + restart gateway'}
|
||||||
|
</button>
|
||||||
{#if configMsg}
|
{#if configMsg}
|
||||||
<span class="config-msg">{configMsg}</span>
|
<span class="config-msg">{configMsg}</span>
|
||||||
{/if}
|
{/if}
|
||||||
<p class="hint">Genererer LiteLLM config.yaml fra databasen. AI Gateway (LiteLLM) må restartes for å lese ny config.</p>
|
<p class="hint">Genererer LiteLLM config.yaml fra databasen. «Generer + restart» aktiverer endringene umiddelbart.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1216,10 +1229,24 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.generate-btn:hover {
|
.generate-btn:hover:not(:disabled) {
|
||||||
background: #264b7a;
|
background: #264b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.generate-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-btn--restart {
|
||||||
|
background: #1e4f3a;
|
||||||
|
border-color: #22c55e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-btn--restart:hover:not(:disabled) {
|
||||||
|
background: #276b4f;
|
||||||
|
}
|
||||||
|
|
||||||
/* Forms */
|
/* Forms */
|
||||||
.add-form {
|
.add-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue