mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-09 02:56:02 +08:00
feat(pm): LLM routing endpoint, usage capture, and admin review view
Backend counterpart to the Python engine's semantic router. - POST /api/decision/route: service-secret-guarded endpoint the Python backend calls on regex-miss. Calls gpt-5-mini (ROUTER_LLM_MODEL), validates the chosen id against the candidate set, and writes both a UsageEvent (central cost ledger) and a routing-review record — including timeouts, with timeoutMs + actual latencyMs — so the budget can be tuned - LlmRoutingDecision model + GET /api/admin/llm-routing (paginated, status-filtered, per-status counts) - admin "LLM Routing" tab: transcript vs expected phrase, candidate chips with the chosen one highlighted, latency/budget chip, model reason - serviceAuth util (mirrors CRON_SECRET pattern) - .env.example: ROUTER_LLM_MODEL, SERVICE_SECRET Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
32
server/utils/serviceAuth.ts
Normal file
32
server/utils/serviceAuth.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { H3Event } from 'h3'
|
||||
import { createError, getHeader } from 'h3'
|
||||
|
||||
let warnedMissingSecret = false
|
||||
|
||||
/**
|
||||
* Guards internal server-to-server endpoints (e.g. the Python decision backend
|
||||
* calling back into Nuxt). The secret is read from SERVICE_SECRET and must be
|
||||
* supplied via the `x-service-secret` header.
|
||||
*
|
||||
* Fail closed: if no secret is configured the endpoint refuses to run (503)
|
||||
* rather than being publicly callable.
|
||||
*/
|
||||
export function requireServiceSecret(event: H3Event) {
|
||||
const secret = (process.env.SERVICE_SECRET || '').trim()
|
||||
|
||||
if (!secret) {
|
||||
if (!warnedMissingSecret) {
|
||||
console.error(
|
||||
'[service] SERVICE_SECRET is not set — internal endpoints are disabled (503). ' +
|
||||
'Set SERVICE_SECRET and pass it via the x-service-secret header.',
|
||||
)
|
||||
warnedMissingSecret = true
|
||||
}
|
||||
throw createError({ statusCode: 503, statusMessage: 'Service endpoint is not configured.' })
|
||||
}
|
||||
|
||||
const provided = (getHeader(event, 'x-service-secret') || '').trim()
|
||||
if (provided !== secret) {
|
||||
throw createError({ statusCode: 401, statusMessage: 'Invalid service secret.' })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user