diff --git a/src/lib/review.js b/src/lib/review.js index 3c5139a..20e13b2 100644 --- a/src/lib/review.js +++ b/src/lib/review.js @@ -55,18 +55,22 @@ export async function runReview({ cfg, gitea, db, job, withGlobal, log }) { const messages = buildReviewPrompt({ repo: fullRepo, ref: job.ref, sha, prTitle: job.prTitle, conventions, diff, truncated }); - let review = null, llmError = null; + let review = null, llmError = null, servedModel = null; await withGlobal(async () => { for (let attempt = 1; attempt <= 2; attempt++) { try { - const content = await chat({ + const out = await chat({ routerUrl: cfg.routerUrl, model: cfg.model, messages, agentId: 'code-reviewer', - sessionId: `review-${owner}-${repo}-${sha.slice(0, 12)}`, + sessionId: `review-${owner}-${repo}-${sha.slice(0, 12)}-a${attempt}`, tenantId: cfg.tenantId, timeoutMs: cfg.routerTimeoutMs }); - const raw = extractJson(content); - if (!raw) throw new Error(`no JSON object in model output (attempt ${attempt})`); + servedModel = out.servedModel; + const raw = extractJson(out.content); + if (!raw) { + log(`[${fullRepo}@${sha.slice(0, 8)}] unparseable model output (served=${servedModel}): ${JSON.stringify(out.content.slice(0, 400))}`); + throw new Error(`no JSON object in model output (attempt ${attempt})`); + } review = normalizeReview(raw); if (!review) throw new Error('normalization failed'); llmError = null; @@ -111,7 +115,7 @@ export async function runReview({ cfg, gitea, db, job, withGlobal, log }) { axes: review.axes, overall: review.overall, grade: review.grade, verdict: review.verdict, findings: review.findings, statusState: state, error: null, diffBytes, truncated, - model: cfg.model, durationMs: Date.now() - t0 + model: servedModel || cfg.model, durationMs: Date.now() - t0 }); log(`[${fullRepo}@${sha.slice(0, 8)}] reviewed: ${review.verdict} grade=${review.grade} overall=${review.overall} findings=${review.findings.length} in ${Date.now() - t0}ms`); return { ok: true, verdict: review.verdict }; diff --git a/src/lib/router.js b/src/lib/router.js index f9d0ee8..dda0a6b 100644 --- a/src/lib/router.js +++ b/src/lib/router.js @@ -14,9 +14,14 @@ export async function chat({ routerUrl, model, messages, agentId, sessionId, ten throw new Error(`router -> ${res.status}: ${text.slice(0, 300)}`); } const data = await res.json(); - const content = data?.message?.content ?? data?.content; + // Response shape varies by upstream: prefer .message.content, then + // OpenAI-style choices, then top-level .content (which can carry an + // upstream-down apology — hence last). + const content = data?.message?.content + ?? data?.choices?.[0]?.message?.content + ?? data?.content; if (typeof content !== 'string' || !content.trim()) { throw new Error('router returned empty content'); } - return content; + return { content, servedModel: data?._shre?.model ?? null }; }