granthi-review v1: estate-wide AI code review service
Webhook-driven central review service for Granthi forges: HMAC-verified push/pull_request webhooks, per-repo serialization with global LLM concurrency 1, shre-router powered rubric review (8 axes, strict JSON, tolerant extractor + retry), commit statuses + PR scorecard comments, sqlite attribution ledger with Co-Authored-By trailer parsing, per-repo HTML history dashboard, nightly per-agent digests, fail-open-with- visibility when the router is unavailable. Posture: BLOCK on confirmed critical/high correctness+security findings; admin merge is the human override. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
// shre-router client. POST /v1/chat with stream:false.
|
||||
// Real model answer lives in .message.content; top-level .content can carry an
|
||||
// upstream-down apology — always prefer .message.content.
|
||||
|
||||
export async function chat({ routerUrl, model, messages, agentId, sessionId, tenantId, timeoutMs }) {
|
||||
const res = await fetch(`${routerUrl.replace(/\/$/, '')}/v1/chat`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ model, messages, agentId, sessionId, tenantId, stream: false }),
|
||||
signal: AbortSignal.timeout(timeoutMs)
|
||||
});
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '');
|
||||
throw new Error(`router -> ${res.status}: ${text.slice(0, 300)}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
const content = data?.message?.content ?? data?.content;
|
||||
if (typeof content !== 'string' || !content.trim()) {
|
||||
throw new Error('router returned empty content');
|
||||
}
|
||||
return content;
|
||||
}
|
||||
Reference in New Issue
Block a user