Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
216 lines
6.0 KiB
TypeScript
216 lines
6.0 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
|
|
// Backend URL - klausur-service
|
|
const KLAUSUR_SERVICE_URL = process.env.KLAUSUR_SERVICE_URL || 'http://localhost:8086'
|
|
|
|
// Helper to proxy requests to backend
|
|
async function proxyRequest(
|
|
endpoint: string,
|
|
method: string = 'GET',
|
|
body?: any
|
|
): Promise<Response> {
|
|
const url = `${KLAUSUR_SERVICE_URL}${endpoint}`
|
|
const options: RequestInit = {
|
|
method,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
}
|
|
|
|
if (body) {
|
|
options.body = JSON.stringify(body)
|
|
}
|
|
|
|
return fetch(url, options)
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const searchParams = request.nextUrl.searchParams
|
|
const action = searchParams.get('action')
|
|
const jobId = searchParams.get('job_id')
|
|
const versionId = searchParams.get('version_id')
|
|
|
|
try {
|
|
let response: Response
|
|
|
|
switch (action) {
|
|
case 'jobs':
|
|
response = await proxyRequest('/api/v1/admin/training/jobs')
|
|
break
|
|
|
|
case 'job':
|
|
if (!jobId) {
|
|
return NextResponse.json({ error: 'job_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/jobs/${jobId}`)
|
|
break
|
|
|
|
case 'models':
|
|
response = await proxyRequest('/api/v1/admin/training/models')
|
|
break
|
|
|
|
case 'model':
|
|
if (!versionId) {
|
|
return NextResponse.json({ error: 'version_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/models/${versionId}`)
|
|
break
|
|
|
|
case 'dataset-stats':
|
|
response = await proxyRequest('/api/v1/admin/training/dataset/stats')
|
|
break
|
|
|
|
case 'status':
|
|
response = await proxyRequest('/api/v1/admin/training/status')
|
|
break
|
|
|
|
default:
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Unknown action',
|
|
validActions: ['jobs', 'job', 'models', 'model', 'dataset-stats', 'status']
|
|
},
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text()
|
|
console.error(`Backend error: ${response.status} - ${errorText}`)
|
|
return NextResponse.json(
|
|
{ error: 'Backend error', detail: errorText },
|
|
{ status: response.status }
|
|
)
|
|
}
|
|
|
|
const data = await response.json()
|
|
return NextResponse.json(data)
|
|
|
|
} catch (error) {
|
|
console.error('Training API proxy error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to connect to backend', detail: String(error) },
|
|
{ status: 503 }
|
|
)
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
const searchParams = request.nextUrl.searchParams
|
|
const action = searchParams.get('action')
|
|
const jobId = searchParams.get('job_id')
|
|
const versionId = searchParams.get('version_id')
|
|
|
|
try {
|
|
let response: Response
|
|
let body: any = null
|
|
|
|
// Parse body if present
|
|
try {
|
|
const text = await request.text()
|
|
if (text) {
|
|
body = JSON.parse(text)
|
|
}
|
|
} catch {
|
|
// No body or invalid JSON
|
|
}
|
|
|
|
switch (action) {
|
|
case 'create-job':
|
|
if (!body) {
|
|
return NextResponse.json({ error: 'Body required for job creation' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest('/api/v1/admin/training/jobs', 'POST', body)
|
|
break
|
|
|
|
case 'pause':
|
|
if (!jobId) {
|
|
return NextResponse.json({ error: 'job_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/jobs/${jobId}/pause`, 'POST')
|
|
break
|
|
|
|
case 'resume':
|
|
if (!jobId) {
|
|
return NextResponse.json({ error: 'job_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/jobs/${jobId}/resume`, 'POST')
|
|
break
|
|
|
|
case 'cancel':
|
|
if (!jobId) {
|
|
return NextResponse.json({ error: 'job_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/jobs/${jobId}/cancel`, 'POST')
|
|
break
|
|
|
|
case 'activate-model':
|
|
if (!versionId) {
|
|
return NextResponse.json({ error: 'version_id required' }, { status: 400 })
|
|
}
|
|
response = await proxyRequest(`/api/v1/admin/training/models/${versionId}/activate`, 'POST')
|
|
break
|
|
|
|
default:
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Unknown action',
|
|
validActions: ['create-job', 'pause', 'resume', 'cancel', 'activate-model']
|
|
},
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ detail: 'Unknown error' }))
|
|
return NextResponse.json(errorData, { status: response.status })
|
|
}
|
|
|
|
const data = await response.json()
|
|
return NextResponse.json(data)
|
|
|
|
} catch (error) {
|
|
console.error('Training API proxy error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to connect to backend', detail: String(error) },
|
|
{ status: 503 }
|
|
)
|
|
}
|
|
}
|
|
|
|
export async function DELETE(request: NextRequest) {
|
|
const searchParams = request.nextUrl.searchParams
|
|
const jobId = searchParams.get('job_id')
|
|
const versionId = searchParams.get('version_id')
|
|
|
|
try {
|
|
let response: Response
|
|
|
|
if (jobId) {
|
|
response = await proxyRequest(`/api/v1/admin/training/jobs/${jobId}`, 'DELETE')
|
|
} else if (versionId) {
|
|
response = await proxyRequest(`/api/v1/admin/training/models/${versionId}`, 'DELETE')
|
|
} else {
|
|
return NextResponse.json(
|
|
{ error: 'Either job_id or version_id required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ detail: 'Unknown error' }))
|
|
return NextResponse.json(errorData, { status: response.status })
|
|
}
|
|
|
|
const data = await response.json()
|
|
return NextResponse.json(data)
|
|
|
|
} catch (error) {
|
|
console.error('Training API proxy error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to connect to backend', detail: String(error) },
|
|
{ status: 503 }
|
|
)
|
|
}
|
|
}
|