Wire new routes; identity, summarize-url, dashboard, admin

This commit is contained in:
Keysat
2026-06-13 13:36:30 -05:00
parent 04dcf86fa4
commit 318c6c4b81
20 changed files with 12407 additions and 499 deletions
+118 -57
View File
@@ -28,8 +28,13 @@
import express from "express";
import multer from "multer";
import { resolveLicense } from "../keysat-client.js";
import { getOrCreateRow, planBackend, commitCredit } from "../credits.js";
import { resolveIdentity, identityTier } from "../identity.js";
import {
getOrCreateRow,
planBackend,
commitCredit,
licenseFingerprint,
} from "../credits.js";
import { lookupJob, markJobCharged, refundJob } from "../job-credits.js";
import { getConfigSnapshot, getTierQuotas } from "../config.js";
import { createGeminiBackend } from "../backends/gemini.js";
@@ -37,6 +42,9 @@ import { createHardwareBackend } from "../backends/hardware.js";
import { envelope, errorEnvelope } from "./envelope.js";
import { recordCall } from "../audit-log.js";
import { calcGeminiCost } from "../pricing.js";
import { getAudioDurationSecondsFromBuffer } from "../audio-meta.js";
import { resolveHardwareConfig } from "../hardware-config.js";
import { reportHealthEvent } from "../spark-control-events.js";
const upload = multer({
storage: multer.memoryStorage(),
@@ -48,67 +56,93 @@ export function transcribeRouter() {
router.post("/transcribe", upload.single("audio"), async (req, res) => {
const t0 = Date.now();
const installId = req.header("X-Recap-Install-Id");
const jobId = req.header("X-Recap-Job-Id") || null;
const auth = req.header("Authorization");
if (!installId) {
let identity;
try {
identity = await resolveIdentity(req);
} catch (err) {
const e = await errorEnvelope({
error: err?.message || "auth_error",
statusHint: err?.status || 401,
});
return res.status(e.statusHint || 401).json(e.body);
}
if (identity.kind === "license" && !identity.installId) {
const e = await errorEnvelope({
error: "missing X-Recap-Install-Id header",
statusHint: 400,
});
return res.status(400).json(e.body);
}
const { creditKey, installId, license } = identity;
if (!req.file) {
const e = await errorEnvelope({ error: "missing audio file", installId, statusHint: 400 });
const e = await errorEnvelope({ error: "missing audio file", creditKey, installId, statusHint: 400 });
return res.status(400).json(e.body);
}
const license = await resolveLicense(auth);
const tier = license.tier;
const row = await getOrCreateRow(installId);
const row = await getOrCreateRow({ creditKey, installId, license });
const tier = identityTier(identity, row);
row.tier_snapshot = tier;
const licenseFp = identity.kind === "cloud" ? null : licenseFingerprint(license);
const auditInstall = installId || identity.userId || null;
let reusedJob = false;
let chosenBackend = null;
const existingJob = lookupJob(installId, jobId);
if (existingJob) {
reusedJob = true;
chosenBackend = existingJob.backend;
} else {
const cfg = await getConfigSnapshot();
const hasHardware = !!cfg.relay_parakeet_base_url;
const quota = await getTierQuotas();
const preference =
cfg.relay_transcribe_backend_preference || "gemini_first";
const plan = planBackend(row, quota, { hasHardware, preference });
if (!plan.allowed) {
await recordCall({
install_id: installId,
tier,
pipeline: "transcribe",
backend: null,
model: null,
status: "refused",
credit_charged: 0,
duration_ms: Date.now() - t0,
cost_usd: 0,
job_id: jobId,
error: plan.reason,
});
const e = await errorEnvelope({
error: plan.reason,
installId,
tier,
statusHint: 402,
});
return res.status(402).json(e.body);
}
chosenBackend = plan.backend;
}
// Probe audio duration BEFORE the backend call so we can record
// it on every audit row (success and error alike). Used by the
// dashboard to normalize wall-clock time to "ms per minute of
// audio" — a backend-agnostic speed benchmark.
const audioSeconds = await getAudioDurationSecondsFromBuffer(
req.file?.buffer
);
// Billing vs. routing are decoupled — see analyze.js for the
// full reasoning. Look up job to decide whether to charge a
// credit, but always run planBackend fresh so transcribe's
// routing decision respects relay_transcribe_backend_preference.
const reusedJob = !!lookupJob({ creditKey, installId, license, jobId });
const cfg = await getConfigSnapshot();
const hw = await resolveHardwareConfig(cfg);
// Operator-only diagnostic — see the matching comment in
// summarize-url.js for the full reasoning. We don't 503 here on
// blocked_reason because doing so pre-empts planBackend and
// surfaces operator-internal wording to clients even when
// Gemini was the configured preference.
if (hw.transcribe.blocked_reason) {
console.warn(
`[transcribe] hardware transcribe currently blocked (planBackend will route to Gemini if available): ${hw.transcribe.blocked_reason}`,
);
}
const hasHardware = !!hw.transcribe.url;
const quota = await getTierQuotas();
const preference =
cfg.relay_transcribe_backend_preference || "gemini_first";
const plan = planBackend(row, quota, { hasHardware, preference });
if (!plan.allowed) {
await recordCall({
install_id: auditInstall,
license_fingerprint: licenseFp,
tier,
pipeline: "transcribe",
backend: null,
model: null,
status: "refused",
credit_charged: 0,
duration_ms: Date.now() - t0,
audio_seconds: audioSeconds,
cost_usd: 0,
job_id: jobId,
error: plan.reason,
});
const e = await errorEnvelope({
error: plan.reason,
creditKey,
installId,
tier,
statusHint: 402,
});
return res.status(402).json(e.body);
}
const chosenBackend = plan.backend;
let result;
try {
if (chosenBackend === "gemini") {
@@ -116,6 +150,8 @@ export function transcribeRouter() {
apiKey: cfg.relay_gemini_api_key,
transcriptionModel: cfg.relay_gemini_transcription_model,
analysisModel: cfg.relay_gemini_analysis_model,
txChunkSeconds: (cfg.relay_gemini_tx_chunk_minutes || 30) * 60,
txConcurrency: cfg.relay_gemini_tx_concurrency || 12,
});
result = await backend.transcribeAudio({
audio: req.file.buffer,
@@ -128,10 +164,19 @@ export function transcribeRouter() {
});
} else {
const backend = createHardwareBackend({
parakeetBaseURL: cfg.relay_parakeet_base_url,
gemmaBaseURL: cfg.relay_gemma_base_url,
parakeetModel: cfg.relay_parakeet_model,
gemmaModel: cfg.relay_gemma_model,
parakeetBaseURL: hw.transcribe.url || "",
gemmaBaseURL: hw.analyze.url || "",
sparkControlBaseURL: hw.sparkBase || "",
parakeetModel: hw.transcribe.model || "",
gemmaModel: hw.analyze.model || "",
txChunkSeconds: (cfg.relay_hardware_tx_chunk_minutes || 5) * 60,
txChunkOverlapSeconds: cfg.relay_hardware_tx_chunk_overlap_seconds ?? 30,
diarizationEnabled: !!cfg.relay_hardware_diarization_enabled,
clusterThresholdPct: cfg.relay_hardware_voice_clustering_threshold ?? 70,
anchorMinSpeakingSec: cfg.relay_hardware_anchor_min_speaking_sec ?? 30,
smallClusterMaxSpeakingSec: cfg.relay_hardware_small_cluster_max_speaking_sec ?? 15,
uncertainMarginPct: cfg.relay_hardware_uncertain_margin_pct ?? 10,
txConcurrency: cfg.relay_hardware_tx_concurrency || 4,
});
result = await backend.transcribeAudio({
audio: req.file.buffer,
@@ -140,25 +185,38 @@ export function transcribeRouter() {
});
}
} catch (err) {
if (reusedJob) refundJob(installId, jobId);
if (reusedJob) await refundJob({ creditKey, installId, license, jobId });
console.error(`[relay/transcribe] backend error: ${err?.message}`);
// Fire-and-forget health report for hardware-served calls;
// Gemini failures are a separate observability surface.
if (chosenBackend === "hardware") {
reportHealthEvent({
service: "parakeet",
ok: false,
error: (err?.message || String(err)).slice(0, 280),
ms: Date.now() - t0,
});
}
await recordCall({
install_id: installId,
install_id: auditInstall,
license_fingerprint: licenseFp,
tier,
pipeline: "transcribe",
backend: chosenBackend,
model: chosenBackend === "gemini"
? cfg.relay_gemini_transcription_model
: cfg.relay_parakeet_model,
: hw.transcribe.model || "(auto)",
status: "error",
credit_charged: 0,
duration_ms: Date.now() - t0,
audio_seconds: audioSeconds,
cost_usd: 0,
job_id: jobId,
error: (err?.message || String(err)).slice(0, 200),
});
const e = await errorEnvelope({
error: err?.message || "backend_error",
creditKey,
installId,
tier,
statusHint: err?.status || 502,
@@ -168,8 +226,8 @@ export function transcribeRouter() {
let creditCharged = 0;
if (!reusedJob) {
await commitCredit(installId, { backend: chosenBackend, tier });
markJobCharged(installId, jobId, { backend: chosenBackend, tier });
await commitCredit({ creditKey, installId, license, backend: chosenBackend, tier });
await markJobCharged({ creditKey, installId, license, jobId, backend: chosenBackend, tier });
creditCharged = 1;
}
@@ -188,6 +246,7 @@ export function transcribeRouter() {
};
await recordCall({
install_id: installId,
license_fingerprint: licenseFp,
tier,
pipeline: "transcribe",
backend: chosenBackend,
@@ -195,11 +254,13 @@ export function transcribeRouter() {
status: "success",
credit_charged: creditCharged,
duration_ms: Date.now() - t0,
audio_seconds: audioSeconds,
job_id: jobId,
attempts: result?.attempts || null,
...costDetails,
});
const body = await envelope({ result, installId, tier, creditCharged });
const body = await envelope({ result, creditKey, installId, license, tier, creditCharged });
res.json(body);
});