@konneal/engine 0.2.150 → 0.2.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ask-KVGDQTF7.js → ask-UIIE5LD2.js} +1 -1
- package/dist/{chunk-CPPIKASJ.js → chunk-I6HU3EM6.js} +910 -874
- package/dist/mcp-proto.d.ts +3 -0
- package/dist/worker_public/src/index.js +31 -3
- package/docs/AGENT-MODE-STREAM-FIRST.md +84 -0
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +229 -163
- package/workers/worker_public/src/mcp-proto.ts +39 -1
|
@@ -1642,6 +1642,13 @@ function toolNarration(t) {
|
|
|
1642
1642
|
return /^(?:the\s+)?[a-z][a-z_.]*\.[a-z_]+ tool returned\b/i.test(t.slice(0, 200)) || /tool returned,? for the query\b/i.test(t.slice(0, 300));
|
|
1643
1643
|
}
|
|
1644
1644
|
var TOOL_NARRATION_NOTICE = "Correction notice: your draft narrated an internal tool call ('the \u2026 tool returned \u2026') instead of answering. Rewrite: answer the question directly from the retrieved passages, cite the clauses, and never mention tools, queries, wire formats, or JSON.";
|
|
1645
|
+
function intentPreamble(t) {
|
|
1646
|
+
const s = (t ?? "").trim();
|
|
1647
|
+
if (s.length > 240) return false;
|
|
1648
|
+
if (!/^(?:i'll|i will|let me|let's|i'm going to|i am going to)\b/i.test(s)) return false;
|
|
1649
|
+
return !/\[\[u:|\[\^?\d+\]|\b\d+\.\d+\b/.test(s);
|
|
1650
|
+
}
|
|
1651
|
+
var INTENT_PREAMBLE_NOTICE = "Correction notice: your draft announced a plan ('I'll look up \u2026') instead of answering. Do not narrate intent \u2014 answer the question NOW from the retrieved passages: give the values, clause references and citations the question asks for.";
|
|
1645
1652
|
function userImageDataUrl(body) {
|
|
1646
1653
|
const img = body?.image;
|
|
1647
1654
|
if (img == null) return null;
|
|
@@ -1837,14 +1844,6 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
1837
1844
|
const telemetryMeta = () => ({ durationMs: Date.now() - tStart, keyId: key?.id ?? null, retries: generateRetries });
|
|
1838
1845
|
const stageTiming = {};
|
|
1839
1846
|
let generateRetries = 0;
|
|
1840
|
-
const readAs = () => understanding ? {
|
|
1841
|
-
intent: understanding.intent,
|
|
1842
|
-
doc: understanding.docidentifier,
|
|
1843
|
-
edition: understanding.edition ?? null,
|
|
1844
|
-
term: understanding.term,
|
|
1845
|
-
terms: (understanding.defined_terms ?? []).slice(0, 4),
|
|
1846
|
-
lang: q?.lang ?? null
|
|
1847
|
-
} : void 0;
|
|
1848
1847
|
const serverTiming = () => Object.entries(stageTiming).map(([k, v]) => `${k};dur=${v}`).concat([`generate-retries;desc=count;dur=${generateRetries ?? 0}`, `total;dur=${Date.now() - tStart}`]).join(", ");
|
|
1849
1848
|
const body = await readJson(req);
|
|
1850
1849
|
const q = validateQuery(body);
|
|
@@ -1891,10 +1890,40 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
1891
1890
|
return err(503, "generation_disabled", "Generation is temporarily paused; search remains available.");
|
|
1892
1891
|
}
|
|
1893
1892
|
const agentSteps = [];
|
|
1893
|
+
let live = null;
|
|
1894
|
+
let liveResponse = null;
|
|
1894
1895
|
const mark = (step) => {
|
|
1895
|
-
|
|
1896
|
+
if (live) live.send({ type: "agent", step });
|
|
1897
|
+
else agentSteps.push(step);
|
|
1896
1898
|
console.log(`agent-step: ${step}`);
|
|
1897
1899
|
};
|
|
1900
|
+
const wantsStream = body?.stream === true || tier === "anon" && body?.stream !== false;
|
|
1901
|
+
if (wantsStream) {
|
|
1902
|
+
const encoder = new TextEncoder();
|
|
1903
|
+
let ctrl = null;
|
|
1904
|
+
const sse = new ReadableStream({
|
|
1905
|
+
start(c) {
|
|
1906
|
+
ctrl = c;
|
|
1907
|
+
}
|
|
1908
|
+
});
|
|
1909
|
+
live = {
|
|
1910
|
+
send: (ev) => {
|
|
1911
|
+
try {
|
|
1912
|
+
ctrl.enqueue(encoder.encode(`data: ${JSON.stringify(ev)}
|
|
1913
|
+
|
|
1914
|
+
`));
|
|
1915
|
+
} catch {
|
|
1916
|
+
}
|
|
1917
|
+
},
|
|
1918
|
+
close: () => {
|
|
1919
|
+
try {
|
|
1920
|
+
ctrl.close();
|
|
1921
|
+
} catch {
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
};
|
|
1925
|
+
liveResponse = new Response(sse, { headers: { "content-type": "text/event-stream", "cache-control": "no-cache", "x-accel-buffering": "no", ...corsHeaders(req) } });
|
|
1926
|
+
}
|
|
1898
1927
|
const service = env.INTERNAL_SERVICE;
|
|
1899
1928
|
const fedAuth = {
|
|
1900
1929
|
cookie: req.headers.get("cookie") ?? "",
|
|
@@ -1953,941 +1982,948 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
1953
1982
|
const gen = await corpusGen(env.CACHE);
|
|
1954
1983
|
const withImage = effectiveImage || storedImage;
|
|
1955
1984
|
const cached = fresh || contextual || declaredCtx || draftAct || apiCallIntent || withImage || ablate ? null : await cacheGet(env, gen, ns, q.query, q.lang, salt);
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
{ type: "
|
|
1963
|
-
{ type: "
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
+
let probeTokensUsed = 0;
|
|
1986
|
+
const pipeline = async (channel, qq) => {
|
|
1987
|
+
const live2 = channel;
|
|
1988
|
+
const q2 = qq;
|
|
1989
|
+
const finishLine = (message) => {
|
|
1990
|
+
if (live2) {
|
|
1991
|
+
live2.send({ type: "token", v: message });
|
|
1992
|
+
live2.send({ type: "done", model: MODELS.member, query_hash: "", context_applied: NO_CONTEXT });
|
|
1993
|
+
live2.close();
|
|
1994
|
+
return null;
|
|
1995
|
+
}
|
|
1996
|
+
return err(503, "serving_busy", message);
|
|
1997
|
+
};
|
|
1998
|
+
const readAs = () => understanding ? {
|
|
1999
|
+
intent: understanding.intent,
|
|
2000
|
+
doc: understanding.docidentifier,
|
|
2001
|
+
edition: understanding.edition ?? null,
|
|
2002
|
+
term: understanding.term,
|
|
2003
|
+
terms: (understanding.defined_terms ?? []).slice(0, 4),
|
|
2004
|
+
lang: q2?.lang ?? null
|
|
2005
|
+
} : void 0;
|
|
2006
|
+
if (cached) {
|
|
2007
|
+
telemetry(env, ctx, tier, "ask", null, true, (cached.value.answer ?? "").length, cached.value.query_hash, q2.lang, "exact", telemetryMeta());
|
|
2008
|
+
const cctx = cached.value.context_applied ?? NO_CONTEXT;
|
|
2009
|
+
if (live2) {
|
|
2010
|
+
live2.send({ type: "citations", citations: cached.value.citations ?? [], quota, context_applied: cctx, ...cached.value.source_quality ? { source_quality: cached.value.source_quality, confidence_note: cached.value.confidence_note ?? null, ...cached.value.experimental_sources ? { experimental_sources: cached.value.experimental_sources } : {}, ...cached.value.entailment ? { entailment: cached.value.entailment } : {} } : {} });
|
|
2011
|
+
live2.send({ type: "token", v: cached.value.answer ?? "" });
|
|
2012
|
+
live2.send({ type: "done", model: cached.value.model ?? MODELS.member, query_hash: cached.value.query_hash, served_from: "cache", context_applied: cctx });
|
|
2013
|
+
live2.close();
|
|
2014
|
+
return null;
|
|
1985
2015
|
}
|
|
2016
|
+
return json({ ...cached.value, cached: true, quota, context_applied: cctx });
|
|
1986
2017
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
if (conversationId) {
|
|
2018
|
+
const warmQuery = retrievalQuery(q2.query, prev);
|
|
2019
|
+
const warmEmbed = embedWarm(env, warmQuery);
|
|
2020
|
+
const conversationId = typeof body?.conversation_id === "string" && /^[A-Za-z0-9_-]{8,64}$/.test(body.conversation_id) ? body.conversation_id : null;
|
|
1991
2021
|
try {
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2022
|
+
if (!effectiveImage && !attachIds.length && conversationId && env.DB && member) {
|
|
2023
|
+
const prior = await env.DB.prepare(
|
|
2024
|
+
"SELECT m.attachment_id AS aid, a.mime, a.r2_key FROM messages m JOIN attachments a ON a.id = m.attachment_id JOIN conversations c ON c.id = m.conversation_id AND c.sub = ?2 WHERE m.conversation_id = ?1 AND m.role = 'user' AND m.attachment_id IS NOT NULL ORDER BY m.created_at DESC LIMIT 1"
|
|
2025
|
+
).bind(conversationId, member.sub).first();
|
|
2026
|
+
if (prior) {
|
|
2027
|
+
const obj = await env.CHAT_UPLOADS.get(prior.r2_key);
|
|
2028
|
+
if (obj) {
|
|
2029
|
+
const bytes = new Uint8Array(await obj.arrayBuffer());
|
|
2030
|
+
let bin = "";
|
|
2031
|
+
for (let i = 0; i < bytes.length; i += 32768) bin += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
2032
|
+
storedImage = `data:${prior.mime};base64,${btoa(bin)}`;
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
1995
2036
|
} catch {
|
|
1996
2037
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
if (!cached) {
|
|
2005
|
-
const understandingP = understandQuery(portModelRunner(env), roleModel(env, "understand"), q.query, history, convEntities);
|
|
2006
|
-
try {
|
|
2007
|
-
optimisticVec = await warmEmbed ?? null;
|
|
2008
|
-
if (optimisticVec) {
|
|
2009
|
-
const ores = await env.VECTORIZE.query(optimisticVec, { topK: LIMITS.retrieveK, returnMetadata: "all" });
|
|
2010
|
-
optimisticHits = (ores.matches ?? []).map((m) => ({
|
|
2011
|
-
id: m.id,
|
|
2012
|
-
score: m.score,
|
|
2013
|
-
metadata: m.metadata,
|
|
2014
|
-
text: m.metadata?.chunk_text ?? ""
|
|
2015
|
-
}));
|
|
2038
|
+
let convEntities = [];
|
|
2039
|
+
if (conversationId) {
|
|
2040
|
+
try {
|
|
2041
|
+
const rows = await env.DB.prepare("SELECT entity, kind FROM conversation_entities WHERE conversation_id = ?1 LIMIT 12").bind(conversationId).all();
|
|
2042
|
+
convEntities = rows.results ?? [];
|
|
2043
|
+
if (convEntities.length) console.log("entity map:", convEntities.length, "entries");
|
|
2044
|
+
} catch {
|
|
2016
2045
|
}
|
|
2017
|
-
} catch {
|
|
2018
2046
|
}
|
|
2019
|
-
understanding =
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2047
|
+
let understanding = null;
|
|
2048
|
+
const answerCites = (t) => /\[[^\]]+\]/.test(t);
|
|
2049
|
+
const refusalScope = (cited) => ({ cited, conversational: understanding?.intent === "conversational" });
|
|
2050
|
+
let optimisticVec = null;
|
|
2051
|
+
let optimisticHits = [];
|
|
2052
|
+
const t0 = Date.now();
|
|
2053
|
+
if (!cached) {
|
|
2054
|
+
const understandingP = understandQuery(portModelRunner(env), roleModel(env, "understand"), q2.query, history, convEntities);
|
|
2055
|
+
try {
|
|
2056
|
+
optimisticVec = await warmEmbed ?? null;
|
|
2057
|
+
if (optimisticVec) {
|
|
2058
|
+
const ores = await env.VECTORIZE.query(optimisticVec, { topK: LIMITS.retrieveK, returnMetadata: "all" });
|
|
2059
|
+
optimisticHits = (ores.matches ?? []).map((m) => ({
|
|
2060
|
+
id: m.id,
|
|
2061
|
+
score: m.score,
|
|
2062
|
+
metadata: m.metadata,
|
|
2063
|
+
text: m.metadata?.chunk_text ?? ""
|
|
2064
|
+
}));
|
|
2065
|
+
}
|
|
2066
|
+
} catch {
|
|
2067
|
+
}
|
|
2068
|
+
understanding = await understandingP;
|
|
2069
|
+
stageTiming.understand = Date.now() - t0;
|
|
2070
|
+
console.log("stage: understand+optimistic", Date.now() - t0, "ms");
|
|
2071
|
+
}
|
|
2072
|
+
const docScope = declaredCtx && declaredCtx.kind !== "account" ? await resolveDocScope(env, declaredCtx) : null;
|
|
2073
|
+
const named = declaredCtx && declaredCtx.kind !== "account" ? namedDocumentIn(q2.query) : null;
|
|
2074
|
+
let ctxApplied;
|
|
2075
|
+
let declaredScoped = false;
|
|
2076
|
+
if (!declaredCtx) {
|
|
2077
|
+
ctxApplied = NO_CONTEXT;
|
|
2078
|
+
const bare = understanding?.process_intent ? null : namedDocumentIn(q2.query);
|
|
2079
|
+
if (bare && understanding?.doc_number !== bare.doc_number) {
|
|
2080
|
+
understanding = {
|
|
2081
|
+
...understanding ?? syntheticUnderstanding(bare),
|
|
2082
|
+
docidentifier: bare.label,
|
|
2083
|
+
doc_number: bare.doc_number,
|
|
2084
|
+
edition: bare.edition ?? understanding?.edition ?? null
|
|
2085
|
+
};
|
|
2086
|
+
console.log("question names", bare.label, "\u2014 scoping retrieval from the text");
|
|
2087
|
+
}
|
|
2088
|
+
} else if (declaredCtx.kind === "account") {
|
|
2089
|
+
ctxApplied = appliedContext(declaredCtx, null);
|
|
2090
|
+
} else if (docScope && (!named || named.doc_number === docScope.doc_number)) {
|
|
2091
|
+
if (understanding?.doc_number && understanding.doc_number !== docScope.doc_number) {
|
|
2092
|
+
console.log("context scope: understand's doc#" + understanding.doc_number, "is inferred, not named in the question \u2014 the declared", docScope.label, "scopes");
|
|
2093
|
+
}
|
|
2056
2094
|
understanding = {
|
|
2057
|
-
...understanding ?? syntheticUnderstanding(
|
|
2058
|
-
docidentifier:
|
|
2059
|
-
doc_number:
|
|
2060
|
-
edition:
|
|
2095
|
+
...understanding ?? syntheticUnderstanding(docScope),
|
|
2096
|
+
docidentifier: docScope.label,
|
|
2097
|
+
doc_number: docScope.doc_number,
|
|
2098
|
+
edition: docScope.edition ?? understanding?.edition ?? null
|
|
2061
2099
|
};
|
|
2100
|
+
ctxApplied = appliedContext(declaredCtx, docScope);
|
|
2101
|
+
declaredScoped = true;
|
|
2102
|
+
console.log("context scope:", docScope.label, `(${declaredCtx.kind})`);
|
|
2103
|
+
} else if (docScope && named) {
|
|
2104
|
+
if (understanding?.doc_number !== named.doc_number) {
|
|
2105
|
+
understanding = {
|
|
2106
|
+
...understanding ?? syntheticUnderstanding(named),
|
|
2107
|
+
docidentifier: named.label,
|
|
2108
|
+
doc_number: named.doc_number,
|
|
2109
|
+
edition: named.edition ?? null
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
ctxApplied = appliedContext(declaredCtx, null, "question-document-wins");
|
|
2113
|
+
console.log("context scope: the question names", named.label, "\u2014 it wins over the declared", docScope.label);
|
|
2114
|
+
} else if (declaredCtx.doc) {
|
|
2115
|
+
ctxApplied = appliedContext(declaredCtx, null, "document-not-in-corpus");
|
|
2116
|
+
console.log("context scope:", declaredCtx.doc, "not in the corpus \u2014 the general corpus answers");
|
|
2117
|
+
} else {
|
|
2118
|
+
ctxApplied = appliedContext(declaredCtx, null);
|
|
2119
|
+
}
|
|
2120
|
+
if (conversationId && understanding) {
|
|
2121
|
+
const now = Date.now();
|
|
2122
|
+
const ents = [];
|
|
2123
|
+
if (understanding.docidentifier) ents.push([understanding.docidentifier, "document"]);
|
|
2124
|
+
for (const t of understanding.defined_terms) ents.push([t, "term"]);
|
|
2125
|
+
if (ents.length) {
|
|
2126
|
+
const upsert = (e, k) => env.DB.prepare("INSERT OR REPLACE INTO conversation_entities (conversation_id, entity, kind, ts) VALUES (?1, ?2, ?3, ?4)").bind(conversationId, e, k, now).run();
|
|
2127
|
+
ctx.waitUntil(Promise.allSettled(ents.map(([e, k]) => upsert(e, k))));
|
|
2128
|
+
}
|
|
2062
2129
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
console.log("nameplate-bridge:", nameplate.manufacturer, nameplate.model ?? "", "\u2192", bridged.rows.length, "register rows");
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
console.log("register-search:", JSON.stringify({ shaped: !!register, tokens: register?.tokens ?? null, rows: register?.rows?.length ?? null, first: register?.rows?.[0]?.num ?? null }));
|
|
2093
|
-
function queryFamilyForAggregate(query) {
|
|
2094
|
-
return queryFamily(query);
|
|
2095
|
-
}
|
|
2096
|
-
let registerBlock = null;
|
|
2097
|
-
let aggregateNoteText;
|
|
2098
|
-
const aggIntent = registerAggregateIntent(q.query);
|
|
2099
|
-
if (aggIntent) {
|
|
2100
|
-
const fam = queryFamilyForAggregate(q.query);
|
|
2101
|
-
if (fam) {
|
|
2102
|
-
const agg = await registerAggregate(env.DB, fam);
|
|
2103
|
-
if (agg) {
|
|
2104
|
-
const latestLine = agg.latest ? `The latest certificate in the snapshot is ${agg.latest.num} \u2014 holder ${agg.latest.holder}, model "${agg.latest.model}"${agg.latest.year ? `, issued ${agg.latest.year}` : ""}, status ${agg.latest.status}.` : "No certificate rows are present in the snapshot.";
|
|
2105
|
-
const linkLine = agg.latest?.pdf_key ? `
|
|
2130
|
+
console.log("understand:", understanding?.intent ?? "null", understanding?.doc_number ? `doc#${understanding.doc_number}${understanding.edition ? "@" + understanding.edition : ""}` : "nodoc", "|", q2.query.slice(0, 50));
|
|
2131
|
+
const graphDocNumbers = await graphExpand(env, understanding);
|
|
2132
|
+
const eNote = await editionNote(env, understanding);
|
|
2133
|
+
let register = await searchRegister(env.DB, q2.query);
|
|
2134
|
+
if (nameplate?.manufacturer) {
|
|
2135
|
+
mark(`certificates.search \u2014 ${nameplate.manufacturer}${nameplate.model ? ` ${nameplate.model}` : ""}`.slice(0, 140));
|
|
2136
|
+
const bridged = await searchRegister(env.DB, nameplateRegisterQuery(nameplate, q2.query), true);
|
|
2137
|
+
if (bridged?.rows?.length) {
|
|
2138
|
+
register = bridged;
|
|
2139
|
+
console.log("nameplate-bridge:", nameplate.manufacturer, nameplate.model ?? "", "\u2192", bridged.rows.length, "register rows");
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
console.log("register-search:", JSON.stringify({ shaped: !!register, tokens: register?.tokens ?? null, rows: register?.rows?.length ?? null, first: register?.rows?.[0]?.num ?? null }));
|
|
2143
|
+
function queryFamilyForAggregate(query) {
|
|
2144
|
+
return queryFamily(query);
|
|
2145
|
+
}
|
|
2146
|
+
let registerBlock = null;
|
|
2147
|
+
let aggregateNoteText;
|
|
2148
|
+
const aggIntent = registerAggregateIntent(q2.query);
|
|
2149
|
+
if (aggIntent) {
|
|
2150
|
+
const fam = queryFamilyForAggregate(q2.query);
|
|
2151
|
+
if (fam) {
|
|
2152
|
+
const agg = await registerAggregate(env.DB, fam);
|
|
2153
|
+
if (agg) {
|
|
2154
|
+
const latestLine = agg.latest ? `The latest certificate in the snapshot is ${agg.latest.num} \u2014 holder ${agg.latest.holder}, model "${agg.latest.model}"${agg.latest.year ? `, issued ${agg.latest.year}` : ""}, status ${agg.latest.status}.` : "No certificate rows are present in the snapshot.";
|
|
2155
|
+
const linkLine = agg.latest?.pdf_key ? `
|
|
2106
2156
|
|
|
2107
2157
|
[The latest certificate's document](${`/cert-pdf/${agg.latest.pdf_key}`}) is on file.` : "";
|
|
2108
|
-
|
|
2109
|
-
|
|
2158
|
+
const series = agg.latest?.num?.match(/^[A-Za-z]+/)?.[0] ?? "R";
|
|
2159
|
+
const answer2 = aggIntent === "count" ? `The ${P().publisher.name} ${series} ${agg.family} family holds **${agg.count} certificate${agg.count === 1 ? "" : "s"}** in the ${P().publisher.name}-CS register snapshot (${agg.valid} valid${agg.suspended ? `, ${agg.suspended} suspended` : ""}).
|
|
2110
2160
|
|
|
2111
2161
|
Certificates are issued per recommendation family \u2014 the register carries no edition dimension, so the 2021 you named does not narrow the count. The register is a snapshot rather than live certification status.` : `${latestLine}${linkLine}
|
|
2112
2162
|
|
|
2113
2163
|
Certificates are issued per recommendation family \u2014 the register carries no edition dimension. The register is a snapshot rather than live certification status.`;
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2164
|
+
const block = aggregateBlock(agg);
|
|
2165
|
+
registerBlock = block;
|
|
2166
|
+
aggregateNoteText = aggregateNote(agg);
|
|
2167
|
+
const queryHash2 = await sha256Hex(q2.query);
|
|
2168
|
+
telemetry(env, ctx, tier, "ask", MODELS.member, true, answer2.length, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2169
|
+
const tq2 = await chargeAnswerTokens(env, bucketId, void 0, q2.query.length, answer2.length);
|
|
2170
|
+
const payload = {
|
|
2171
|
+
answer: answer2,
|
|
2172
|
+
citations: [{ docidentifier: `${P().publisher.name}-CS certificate register (family ${agg.family})`, corpus: "register" }],
|
|
2173
|
+
model: MODELS.member,
|
|
2174
|
+
query_hash: queryHash2,
|
|
2175
|
+
follow_ups: [],
|
|
2176
|
+
blocks: [block],
|
|
2177
|
+
context_applied: NO_CONTEXT,
|
|
2178
|
+
read: readAs(),
|
|
2179
|
+
...ablate ? { ablate } : {},
|
|
2180
|
+
quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview }
|
|
2181
|
+
};
|
|
2182
|
+
if (live2) {
|
|
2183
|
+
live2.send({ type: "citations", citations: payload.citations, quota: payload.quota, context_applied: NO_CONTEXT });
|
|
2184
|
+
live2.send({ type: "token", v: answer2 });
|
|
2185
|
+
live2.send({ type: "done", model: MODELS.member, query_hash: queryHash2, blocks: [block], follow_ups: [], context_applied: NO_CONTEXT, read: readAs() });
|
|
2186
|
+
live2.send({ type: "quota", quota: payload.quota });
|
|
2187
|
+
live2.close();
|
|
2188
|
+
return null;
|
|
2189
|
+
}
|
|
2190
|
+
return json(payload);
|
|
2191
|
+
}
|
|
2132
2192
|
}
|
|
2133
2193
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
...summary ? [{ role: "system", content: `Earlier in this conversation (summarized for continuity):
|
|
2194
|
+
const regNote = aggregateNoteText ?? (register ? [registerNote(register.rows), certificateLinks(register.rows)].filter(Boolean).join("\n") : void 0);
|
|
2195
|
+
const ops = await operationsLane(env.DB, q2.query);
|
|
2196
|
+
if (understanding?.intent === "conversational") {
|
|
2197
|
+
const queryHash2 = await sha256Hex(q2.query);
|
|
2198
|
+
const messages2 = [
|
|
2199
|
+
{ role: "system", content: identityNote(!!member) },
|
|
2200
|
+
...summary ? [{ role: "system", content: `Earlier in this conversation (summarized for continuity):
|
|
2142
2201
|
${summary}` }] : [],
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
const
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
const stats = {};
|
|
2158
|
-
let full = "";
|
|
2159
|
-
try {
|
|
2160
|
-
for await (const tok of sseTokens(stream, stats)) {
|
|
2161
|
-
full += tok;
|
|
2162
|
-
send({ type: "token", v: tok });
|
|
2163
|
-
}
|
|
2164
|
-
} catch {
|
|
2202
|
+
...keptHistory.slice(-6),
|
|
2203
|
+
{ role: "user", content: q2.query }
|
|
2204
|
+
];
|
|
2205
|
+
if (live2) {
|
|
2206
|
+
if (readAs()) live2.send({ type: "read", read: readAs() });
|
|
2207
|
+
live2.send({ type: "citations", citations: [], context_applied: NO_CONTEXT, quota });
|
|
2208
|
+
const stats = {};
|
|
2209
|
+
let full = "";
|
|
2210
|
+
const stream = await generateStream(env, model, messages2, effort);
|
|
2211
|
+
try {
|
|
2212
|
+
if (stream) {
|
|
2213
|
+
for await (const tok of sseTokens(stream, stats)) {
|
|
2214
|
+
full += tok;
|
|
2215
|
+
live2.send({ type: "token", v: tok });
|
|
2165
2216
|
}
|
|
2166
|
-
|
|
2167
|
-
send({ type: "
|
|
2168
|
-
send({ type: "done", model, query_hash: queryHash2, context_applied: NO_CONTEXT, read: readAs() });
|
|
2169
|
-
telemetry(env, ctx, tier, "ask", model, true, full.length, queryHash2, q.lang, void 0, telemetryMeta());
|
|
2170
|
-
controller.close();
|
|
2217
|
+
} else {
|
|
2218
|
+
live2.send({ type: "token", v: "The generation model is unavailable; please retry." });
|
|
2171
2219
|
}
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
});
|
|
2220
|
+
} catch {
|
|
2221
|
+
}
|
|
2222
|
+
const tq2 = await chargeAnswerTokens(env, bucketId, stats, messageChars(messages2), full.length, probeTokensUsed);
|
|
2223
|
+
live2.send({ type: "quota", quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
|
|
2224
|
+
live2.send({ type: "done", model, query_hash: queryHash2, context_applied: NO_CONTEXT, read: readAs() });
|
|
2225
|
+
telemetry(env, ctx, tier, "ask", model, true, full.length, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2226
|
+
live2.close();
|
|
2227
|
+
return null;
|
|
2176
2228
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
`SELECT lower(coalesce(json_extract(symbols, '$.ascii'), json_extract(symbols, '$.unicode'))) AS sym, dimension_ascii FROM units_db WHERE lower(coalesce(json_extract(symbols, '$.ascii'), json_extract(symbols, '$.unicode'))) IN (${marks})`
|
|
2276
|
-
).bind(...unitTokens).all().catch(() => ({ results: [] }));
|
|
2277
|
-
const dimensions = {};
|
|
2278
|
-
for (const r of rows.results ?? []) dimensions[String(r.sym)] = String(r.dimension_ascii ?? "");
|
|
2279
|
-
machineVerdict = evaluate(boundModel.content, q.query, { dimensions });
|
|
2229
|
+
let answer2 = await generateOnce(env, model, messages2, effort);
|
|
2230
|
+
if (answer2 === null) answer2 = await generateOnce(env, MODELS.fallback, messages2, effort);
|
|
2231
|
+
if (answer2 === null) {
|
|
2232
|
+
telemetry(env, ctx, tier, "ask", model, false, 0, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2233
|
+
return err(502, "generation_failed", "The generation model is unavailable; please retry.");
|
|
2234
|
+
}
|
|
2235
|
+
telemetry(env, ctx, tier, "ask", model, true, answer2.length, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2236
|
+
return json({ answer: answer2, citations: [], model, query_hash: queryHash2, follow_ups: [], context_applied: NO_CONTEXT, read: readAs(), quota });
|
|
2237
|
+
}
|
|
2238
|
+
if (draftAct) {
|
|
2239
|
+
const draftCtxApplied = declaredCtx ? appliedContext(declaredCtx, null) : NO_CONTEXT;
|
|
2240
|
+
const queryHash2 = await sha256Hex(q2.query);
|
|
2241
|
+
const liveCfg = liveDataConfig(env);
|
|
2242
|
+
const sessionRaw = rawSessionToken(req);
|
|
2243
|
+
let delegation;
|
|
2244
|
+
if (!member || !sessionRaw) delegation = { status: "unsigned" };
|
|
2245
|
+
else if (!liveCfg) delegation = { status: "not_configured" };
|
|
2246
|
+
else {
|
|
2247
|
+
const exchanged = await liveTokenFor(env, sessionRaw, member);
|
|
2248
|
+
delegation = exchanged.ok ? { status: "ok", token: exchanged.token } : { status: exchanged.reason };
|
|
2249
|
+
}
|
|
2250
|
+
const verdict = await prepareDraft(env, {
|
|
2251
|
+
act: draftAct,
|
|
2252
|
+
query: q2.query,
|
|
2253
|
+
history: keptHistory,
|
|
2254
|
+
member,
|
|
2255
|
+
delegation,
|
|
2256
|
+
platformClientId: liveCfg?.platformClientId,
|
|
2257
|
+
model: roleModel(env, "understand")
|
|
2258
|
+
});
|
|
2259
|
+
console.log("draft act:", draftAct, "\u2192", verdict.status === "draft" ? `draft (${Object.keys(verdict.draft.fields).length} fields)` : `refused (${verdict.reason})`);
|
|
2260
|
+
const citations2 = verdict.citation ? [{ ...verdict.citation, corpus: P().publisher.id }] : [];
|
|
2261
|
+
const draftPayload = verdict.status === "draft" ? verdict.draft : void 0;
|
|
2262
|
+
telemetry(env, ctx, tier, "ask", model, true, verdict.answer.length, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2263
|
+
if (live2) {
|
|
2264
|
+
if (readAs()) live2.send({ type: "read", read: readAs() });
|
|
2265
|
+
live2.send({ type: "citations", citations: citations2, context_applied: draftCtxApplied, ...draftPayload ? { draft: draftPayload } : {}, quota });
|
|
2266
|
+
live2.send({ type: "token", v: verdict.answer });
|
|
2267
|
+
live2.send({ type: "done", model, query_hash: queryHash2, context_applied: draftCtxApplied, read: readAs(), ...ablate ? { ablate } : {} });
|
|
2268
|
+
live2.close();
|
|
2269
|
+
return null;
|
|
2270
|
+
}
|
|
2271
|
+
const tq2 = await chargeAnswerTokens(env, bucketId, void 0, q2.query.length, verdict.answer.length);
|
|
2272
|
+
return json({ answer: verdict.answer, citations: citations2, model, query_hash: queryHash2, follow_ups: [], context_applied: draftCtxApplied, read: readAs(), ...draftPayload ? { draft: draftPayload } : {}, ...ablate ? { ablate } : {}, quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
|
|
2273
|
+
}
|
|
2274
|
+
if (apiCallIntent) {
|
|
2275
|
+
const callCtxApplied = declaredCtx ? appliedContext(declaredCtx, null) : NO_CONTEXT;
|
|
2276
|
+
const queryHash2 = await sha256Hex(q2.query);
|
|
2277
|
+
const verdict = await prepareApiCall(env, {
|
|
2278
|
+
intent: apiCallIntent,
|
|
2279
|
+
query: q2.query,
|
|
2280
|
+
history: keptHistory,
|
|
2281
|
+
member,
|
|
2282
|
+
declared: declaredCtx,
|
|
2283
|
+
model: roleModel(env, "acts")
|
|
2284
|
+
});
|
|
2285
|
+
console.log("api_call draft:", apiCallIntent, "\u2192", verdict.status === "draft" ? `draft (${verdict.draft.call.method} ${verdict.draft.call.path})` : `refused (${verdict.reason})`);
|
|
2286
|
+
const draftPayload = verdict.status === "draft" ? verdict.draft : void 0;
|
|
2287
|
+
telemetry(env, ctx, tier, "ask", model, true, verdict.answer.length, queryHash2, q2.lang, void 0, telemetryMeta());
|
|
2288
|
+
if (live2) {
|
|
2289
|
+
if (readAs()) live2.send({ type: "read", read: readAs() });
|
|
2290
|
+
live2.send({ type: "citations", citations: [], context_applied: callCtxApplied, ...draftPayload ? { draft: draftPayload } : {}, quota });
|
|
2291
|
+
live2.send({ type: "token", v: verdict.answer });
|
|
2292
|
+
live2.send({ type: "done", model, query_hash: queryHash2, context_applied: callCtxApplied, read: readAs(), ...ablate ? { ablate } : {} });
|
|
2293
|
+
live2.close();
|
|
2294
|
+
return null;
|
|
2295
|
+
}
|
|
2296
|
+
const tq2 = await chargeAnswerTokens(env, bucketId, void 0, q2.query.length, verdict.answer.length);
|
|
2297
|
+
return json({ answer: verdict.answer, citations: [], model, query_hash: queryHash2, follow_ups: [], context_applied: callCtxApplied, read: readAs(), ...draftPayload ? { draft: draftPayload } : {}, ...ablate ? { ablate } : {}, quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
|
|
2298
|
+
}
|
|
2299
|
+
let liveRecords;
|
|
2300
|
+
let accountNote;
|
|
2301
|
+
const modelDocHint = named ?? docScope ?? namedDocumentIn(q2.query);
|
|
2302
|
+
const boundModel = P().publisher.features?.model_plane ? await bindModelNode(env, {
|
|
2303
|
+
label: declaredCtx?.label,
|
|
2304
|
+
query: q2.query,
|
|
2305
|
+
standard: standardForDocNumber(modelDocHint?.doc_number),
|
|
2306
|
+
standardKeys
|
|
2307
|
+
}) ?? await bindConstraintByQuantities(env, q2.query, standardKeys) : null;
|
|
2308
|
+
if (boundModel) {
|
|
2309
|
+
ctxApplied = { ...ctxApplied, model: modelEcho(boundModel) };
|
|
2310
|
+
console.log("model plane: bound", boundModel.node_id, `[${boundModel.standard}]`, boundModel.clause?.urn ?? "no-clause", boundModel.gated ? "(gated: license)" : "");
|
|
2311
|
+
}
|
|
2312
|
+
const modelNote = boundModel && !boundModel.gated ? modelGroundingBlock(boundModel) : void 0;
|
|
2313
|
+
let machineVerdict = boundModel && !boundModel.gated && !ablate?.noVerdict ? evaluate(boundModel.content, q2.query) : null;
|
|
2314
|
+
if (machineVerdict === null && boundModel && !boundModel.gated) {
|
|
2315
|
+
try {
|
|
2316
|
+
const unitTokens = [...new Set(Object.values(extractParamsWithUnits(q2.query, symbolsIn(extractChecks(boundModel.content))).units).map((u) => u.toLowerCase()))];
|
|
2317
|
+
if (unitTokens.length) {
|
|
2318
|
+
const marks = unitTokens.map(() => "?").join(",");
|
|
2319
|
+
const rows = await env.DB.prepare(
|
|
2320
|
+
`SELECT lower(coalesce(json_extract(symbols, '$.ascii'), json_extract(symbols, '$.unicode'))) AS sym, dimension_ascii FROM units_db WHERE lower(coalesce(json_extract(symbols, '$.ascii'), json_extract(symbols, '$.unicode'))) IN (${marks})`
|
|
2321
|
+
).bind(...unitTokens).all().catch(() => ({ results: [] }));
|
|
2322
|
+
const dimensions = {};
|
|
2323
|
+
for (const r of rows.results ?? []) dimensions[String(r.sym)] = String(r.dimension_ascii ?? "");
|
|
2324
|
+
machineVerdict = evaluate(boundModel.content, q2.query, { dimensions });
|
|
2325
|
+
}
|
|
2326
|
+
} catch {
|
|
2280
2327
|
}
|
|
2281
|
-
} catch {
|
|
2282
2328
|
}
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2329
|
+
const machineNote = machineVerdict && boundModel ? verdictNote(machineVerdict, boundModel) : void 0;
|
|
2330
|
+
const modelNodeRows = async (kind, docNum) => {
|
|
2331
|
+
const attempt = (num3) => {
|
|
2332
|
+
const sql = num3 ? `SELECT standard, node_id, content FROM model_nodes WHERE kind = '${kind}' AND standard LIKE '%' || ?1` : `SELECT standard, node_id, content FROM model_nodes WHERE kind = '${kind}'`;
|
|
2333
|
+
return num3 ? env.DB.prepare(sql).bind(num3) : env.DB.prepare(sql);
|
|
2334
|
+
};
|
|
2335
|
+
let rows = await attempt(docNum).all().catch(() => ({ results: [] }));
|
|
2336
|
+
if (!(rows.results ?? []).length && docNum && docNum.includes("-")) {
|
|
2337
|
+
rows = await attempt(docNum.replace(/-\d+$/, "")).all().catch(() => ({ results: [] }));
|
|
2338
|
+
}
|
|
2339
|
+
return rows;
|
|
2289
2340
|
};
|
|
2290
|
-
let
|
|
2291
|
-
|
|
2292
|
-
|
|
2341
|
+
let conditionVerdict = null;
|
|
2342
|
+
let conditionStandard = null;
|
|
2343
|
+
if (!machineVerdict && !boundModel && !ablate?.noVerdict && P().publisher.features?.model_plane) {
|
|
2344
|
+
const ql = q2.query.toLowerCase();
|
|
2345
|
+
const severityWord = /\b(severity|test|valid|tolerance|condition|within)\b/.test(ql);
|
|
2346
|
+
const stated = quantitiesIn(q2.query);
|
|
2347
|
+
if (severityWord && Object.keys(stated).length >= 1) {
|
|
2348
|
+
const docNum = modelDocHint?.doc_number;
|
|
2349
|
+
const rows = await modelNodeRows("condition_set", docNum);
|
|
2350
|
+
const candidates = (rows.results ?? []).filter((r) => {
|
|
2351
|
+
const entry = licensedEntryForPackage(String(r.standard));
|
|
2352
|
+
return !entry || (standardKeys?.has(entry.key) ?? false);
|
|
2353
|
+
});
|
|
2354
|
+
const v = evaluateConditionSets(
|
|
2355
|
+
candidates.map((r) => ({ node_id: String(r.node_id), content: JSON.parse(String(r.content ?? "{}")) })),
|
|
2356
|
+
q2.query
|
|
2357
|
+
);
|
|
2358
|
+
if (v) {
|
|
2359
|
+
conditionVerdict = v;
|
|
2360
|
+
conditionStandard = String(rows.results?.[0]?.standard ?? "");
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2293
2363
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2364
|
+
const conditionNote = conditionVerdict && conditionStandard ? `${conditionVerdict.note} (computed from the ${conditionStandard} condition sets \u2014 machine evaluation, cite the package's clause.)` : void 0;
|
|
2365
|
+
const verdictBlock = machineVerdict ? {
|
|
2366
|
+
unit_id: boundModel.node_id,
|
|
2367
|
+
type: "verdict",
|
|
2368
|
+
docidentifier: `${P().publisher.name} model (${boundModel.standard})`,
|
|
2369
|
+
payload: {
|
|
2370
|
+
verdict: machineVerdict.verdict,
|
|
2371
|
+
on_violation: machineVerdict.on_violation,
|
|
2372
|
+
violation_meaning: machineVerdict.violation_meaning,
|
|
2373
|
+
missing: machineVerdict.missing,
|
|
2374
|
+
checks: machineVerdict.checks
|
|
2375
|
+
}
|
|
2376
|
+
} : null;
|
|
2377
|
+
if (machineVerdict) console.log("verdict engine:", boundModel.node_id, "\u2192", machineVerdict.verdict.toUpperCase(), machineVerdict.missing.length ? `(missing ${machineVerdict.missing.join(",")})` : "");
|
|
2378
|
+
const conditionBlock = conditionVerdict ? {
|
|
2379
|
+
unit_id: conditionVerdict.matched[0] ?? conditionVerdict.nearest.node_id,
|
|
2380
|
+
type: "verdict",
|
|
2381
|
+
docidentifier: `${P().publisher.name} model (${conditionStandard})`,
|
|
2382
|
+
payload: {
|
|
2383
|
+
verdict: conditionVerdict.verdict,
|
|
2384
|
+
missing: [],
|
|
2385
|
+
checks: conditionVerdict.checks.map((c) => ({
|
|
2386
|
+
expression: `${c.quantity_kind} within ${c.band}`,
|
|
2387
|
+
values: { stated: c.stated },
|
|
2388
|
+
result: c.in_band
|
|
2389
|
+
})),
|
|
2390
|
+
...conditionVerdict.nearest ? { nearest: conditionVerdict.nearest } : { matched: conditionVerdict.matched }
|
|
2391
|
+
}
|
|
2392
|
+
} : null;
|
|
2393
|
+
if (conditionVerdict) console.log("condition engine:", conditionVerdict.matched.join("|") || conditionVerdict.nearest.node_id, "\u2192", conditionVerdict.verdict.toUpperCase());
|
|
2394
|
+
let aggregationVerdict = null;
|
|
2395
|
+
let aggregationStandard = null;
|
|
2396
|
+
if (!machineVerdict && !boundModel && !conditionVerdict && P().publisher.features?.model_plane) {
|
|
2303
2397
|
const docNum = modelDocHint?.doc_number;
|
|
2304
|
-
const rows = await modelNodeRows("
|
|
2398
|
+
const rows = await modelNodeRows("table", docNum);
|
|
2305
2399
|
const candidates = (rows.results ?? []).filter((r) => {
|
|
2306
2400
|
const entry = licensedEntryForPackage(String(r.standard));
|
|
2307
2401
|
return !entry || (standardKeys?.has(entry.key) ?? false);
|
|
2308
2402
|
});
|
|
2309
|
-
const v =
|
|
2403
|
+
const v = evaluateAggregation(
|
|
2310
2404
|
candidates.map((r) => ({ node_id: String(r.node_id), content: JSON.parse(String(r.content ?? "{}")) })),
|
|
2311
|
-
|
|
2405
|
+
q2.query
|
|
2312
2406
|
);
|
|
2313
2407
|
if (v) {
|
|
2314
|
-
|
|
2315
|
-
|
|
2408
|
+
aggregationVerdict = v;
|
|
2409
|
+
aggregationStandard = String(rows.results?.[0]?.standard ?? "");
|
|
2316
2410
|
}
|
|
2317
2411
|
}
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
})),
|
|
2345
|
-
...conditionVerdict.nearest ? { nearest: conditionVerdict.nearest } : { matched: conditionVerdict.matched }
|
|
2346
|
-
}
|
|
2347
|
-
} : null;
|
|
2348
|
-
if (conditionVerdict) console.log("condition engine:", conditionVerdict.matched.join("|") || conditionVerdict.nearest.node_id, "\u2192", conditionVerdict.verdict.toUpperCase());
|
|
2349
|
-
let aggregationVerdict = null;
|
|
2350
|
-
let aggregationStandard = null;
|
|
2351
|
-
if (!machineVerdict && !boundModel && !conditionVerdict && P().publisher.features?.model_plane) {
|
|
2352
|
-
const docNum = modelDocHint?.doc_number;
|
|
2353
|
-
const rows = await modelNodeRows("table", docNum);
|
|
2354
|
-
const candidates = (rows.results ?? []).filter((r) => {
|
|
2355
|
-
const entry = licensedEntryForPackage(String(r.standard));
|
|
2356
|
-
return !entry || (standardKeys?.has(entry.key) ?? false);
|
|
2357
|
-
});
|
|
2358
|
-
const v = evaluateAggregation(
|
|
2359
|
-
candidates.map((r) => ({ node_id: String(r.node_id), content: JSON.parse(String(r.content ?? "{}")) })),
|
|
2360
|
-
q.query
|
|
2361
|
-
);
|
|
2362
|
-
if (v) {
|
|
2363
|
-
aggregationVerdict = v;
|
|
2364
|
-
aggregationStandard = String(rows.results?.[0]?.standard ?? "");
|
|
2365
|
-
}
|
|
2366
|
-
}
|
|
2367
|
-
const aggregationNote = aggregationVerdict ? `${aggregationVerdict.note}${aggregationStandard ? ` (standard ${aggregationStandard}.)` : ""}` : void 0;
|
|
2368
|
-
const aggregationBlock = aggregationVerdict ? {
|
|
2369
|
-
unit_id: aggregationVerdict.table,
|
|
2370
|
-
type: "verdict",
|
|
2371
|
-
docidentifier: `${P().publisher.name} model table${aggregationStandard ? ` (${aggregationStandard})` : ""}`,
|
|
2372
|
-
payload: {
|
|
2373
|
-
check: `${aggregationVerdict.operation}: ${aggregationVerdict.column ?? aggregationVerdict.table_title ?? aggregationVerdict.table} = ${aggregationVerdict.value}${aggregationVerdict.unit ? ` ${aggregationVerdict.unit}` : ""}`,
|
|
2374
|
-
meaning: aggregationVerdict.table_title,
|
|
2375
|
-
operation: aggregationVerdict.operation,
|
|
2376
|
-
value: aggregationVerdict.value,
|
|
2377
|
-
unit: aggregationVerdict.unit,
|
|
2378
|
-
row: aggregationVerdict.row
|
|
2379
|
-
}
|
|
2380
|
-
} : null;
|
|
2381
|
-
if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "\u2192", aggregationVerdict.value);
|
|
2382
|
-
let boundaryNote = null;
|
|
2383
|
-
let boundaryBoost;
|
|
2384
|
-
let licensedDocNumbers;
|
|
2385
|
-
let editionBoost;
|
|
2386
|
-
try {
|
|
2387
|
-
const fam = understanding?.doc ? refCodec().familyOf(understanding.doc) : null;
|
|
2388
|
-
if (fam) {
|
|
2389
|
-
const row = await env.DB.prepare("SELECT edition FROM documents WHERE family = ?1 AND active = 1 ORDER BY edition DESC LIMIT 1").bind(fam).first().catch(() => null);
|
|
2390
|
-
if (row?.edition) editionBoost = String(row.edition);
|
|
2412
|
+
const aggregationNote = aggregationVerdict ? `${aggregationVerdict.note}${aggregationStandard ? ` (standard ${aggregationStandard}.)` : ""}` : void 0;
|
|
2413
|
+
const aggregationBlock = aggregationVerdict ? {
|
|
2414
|
+
unit_id: aggregationVerdict.table,
|
|
2415
|
+
type: "verdict",
|
|
2416
|
+
docidentifier: `${P().publisher.name} model table${aggregationStandard ? ` (${aggregationStandard})` : ""}`,
|
|
2417
|
+
payload: {
|
|
2418
|
+
check: `${aggregationVerdict.operation}: ${aggregationVerdict.column ?? aggregationVerdict.table_title ?? aggregationVerdict.table} = ${aggregationVerdict.value}${aggregationVerdict.unit ? ` ${aggregationVerdict.unit}` : ""}`,
|
|
2419
|
+
meaning: aggregationVerdict.table_title,
|
|
2420
|
+
operation: aggregationVerdict.operation,
|
|
2421
|
+
value: aggregationVerdict.value,
|
|
2422
|
+
unit: aggregationVerdict.unit,
|
|
2423
|
+
row: aggregationVerdict.row
|
|
2424
|
+
}
|
|
2425
|
+
} : null;
|
|
2426
|
+
if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "\u2192", aggregationVerdict.value);
|
|
2427
|
+
let boundaryNote = null;
|
|
2428
|
+
let boundaryBoost;
|
|
2429
|
+
let licensedDocNumbers;
|
|
2430
|
+
let editionBoost;
|
|
2431
|
+
try {
|
|
2432
|
+
const fam = understanding?.doc ? refCodec().familyOf(understanding.doc) : null;
|
|
2433
|
+
if (fam) {
|
|
2434
|
+
const row = await env.DB.prepare("SELECT edition FROM documents WHERE family = ?1 AND active = 1 ORDER BY edition DESC LIMIT 1").bind(fam).first().catch(() => null);
|
|
2435
|
+
if (row?.edition) editionBoost = String(row.edition);
|
|
2436
|
+
}
|
|
2437
|
+
} catch {
|
|
2391
2438
|
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2439
|
+
const lexicalBoost = [boundaryBoost, editionBoost].filter(Boolean).join(" ") || void 0;
|
|
2440
|
+
if (P().sources?.licensed?.length) {
|
|
2441
|
+
const match = matchLicensedTopic(q2.query, P().sources.licensed);
|
|
2442
|
+
if (match && (standardKeys?.has(match.entry.key) ?? false)) {
|
|
2443
|
+
licensedDocNumbers = match.entry.package ? [match.entry.package] : void 0;
|
|
2444
|
+
} else if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
|
|
2445
|
+
const docNum = match.entry.doc_number ?? "";
|
|
2446
|
+
boundaryBoost = docNum || void 0;
|
|
2447
|
+
let citing = [];
|
|
2448
|
+
if (docNum) {
|
|
2449
|
+
const rows = await env.DB.prepare(
|
|
2450
|
+
"SELECT n.label AS label FROM graph_edges e JOIN graph_nodes n ON e.src = n.id WHERE e.kind = 'cites' AND e.dst LIKE ?1 LIMIT 4"
|
|
2451
|
+
).bind(`%${docNum}%`).all().catch(() => ({ results: [] }));
|
|
2452
|
+
citing = (rows.results ?? []).map((r) => String(r.label ?? "").replace(/^doc:/, ""));
|
|
2453
|
+
}
|
|
2454
|
+
boundaryNote = boundaryNoteText(match, citing);
|
|
2408
2455
|
}
|
|
2409
|
-
boundaryNote = boundaryNoteText(match, citing);
|
|
2410
2456
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
accountNote = `Live account data (read ${live.readAt} from ${P().prompts.vars.account_note_source ?? `the user's own ${P().publisher.product_name} account`} \u2014 exactly what they may see, never more):
|
|
2457
|
+
const routeMode = ablate?.route ?? "adaptive";
|
|
2458
|
+
const routed = routeMode === "adaptive" ? routeFor(understanding, q2.query) : { route: routeMode, features: [`forced-${routeMode}`] };
|
|
2459
|
+
const routeSubset = ablate?.stages ?? (routed.route === "fast" ? fastRouteStages(STAGE_NAMES) : null);
|
|
2460
|
+
if (routeSubset) console.log("route:", routed.route, routed.features.join("+"), "\u2014", STAGE_NAMES.length - routeSubset.length, "lanes dropped");
|
|
2461
|
+
try {
|
|
2462
|
+
const tR = Date.now();
|
|
2463
|
+
if (declaredCtx?.kind === "account") {
|
|
2464
|
+
const live3 = await resolveLiveAccount(env, rawSessionToken(req), member);
|
|
2465
|
+
if (live3.status === "ok") {
|
|
2466
|
+
liveRecords = live3.records;
|
|
2467
|
+
ctxApplied = appliedContext(declaredCtx, null, void 0, {
|
|
2468
|
+
read_at: live3.readAt,
|
|
2469
|
+
stores: live3.stores,
|
|
2470
|
+
records: live3.records.length
|
|
2471
|
+
});
|
|
2472
|
+
const lines = live3.records.map(
|
|
2473
|
+
(r) => `- ${r.label} [${[r.status, r.detail].filter(Boolean).join("; ")}] ${r.url}`
|
|
2474
|
+
);
|
|
2475
|
+
accountNote = `Live account data (read ${live3.readAt} from ${P().prompts.vars.account_note_source ?? `the user's own ${P().publisher.product_name} account`} \u2014 exactly what they may see, never more):
|
|
2431
2476
|
` + (lines.length ? lines.join("\n") : "(the account surfaces answered empty)") + `
|
|
2432
2477
|
Answer account questions from these records ONLY: name the record when you use it, never invent one, and say honestly when they do not hold the answer. The corpus passages still ground the regulatory claims (the requirements, the procedures); the records are the user's own work.`;
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2478
|
+
console.log("live data:", live3.records.length, "records from", live3.stores.join("+") || "none");
|
|
2479
|
+
} else {
|
|
2480
|
+
const note = live3.reason === "sign_in_required" ? "sign-in-required" : live3.reason === "window_expired" ? "live-window-expired" : "live-unavailable";
|
|
2481
|
+
ctxApplied = appliedContext(declaredCtx, null, note);
|
|
2482
|
+
accountNote = live3.reason === "sign_in_required" ? "Context note: the user asked with the 'my account' context but is not signed in \u2014 the account data was NOT read; answer from the corpus and say so." : live3.reason === "window_expired" ? "Context note: the user's live access window lapsed \u2014 the account data was NOT read; answer from the corpus, say the live read did not happen, and suggest signing in again to refresh it." : "Context note: the live account read was refused or unreachable \u2014 the account data was NOT read; answer from the corpus and say so honestly.";
|
|
2483
|
+
console.log("live data: not read \u2014", live3.reason);
|
|
2484
|
+
}
|
|
2439
2485
|
}
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2486
|
+
retrieved = await retrieve(env, q2.query, {
|
|
2487
|
+
prev,
|
|
2488
|
+
understanding,
|
|
2489
|
+
federate,
|
|
2490
|
+
warmEmbed,
|
|
2491
|
+
graphDocNumbers,
|
|
2492
|
+
sealScope: declaredScoped ? docScope : null,
|
|
2493
|
+
optimisticHits,
|
|
2494
|
+
optimisticVec,
|
|
2495
|
+
datasetScope: narrowed ? corpora : null,
|
|
2496
|
+
standardKeys,
|
|
2497
|
+
lexicalBoost,
|
|
2498
|
+
licensedDocNumbers,
|
|
2499
|
+
...routeSubset ? { stageSubset: routeSubset } : {}
|
|
2500
|
+
});
|
|
2501
|
+
stageTiming["retrieve-core"] = Date.now() - tR;
|
|
2502
|
+
console.log("stage: retrieve", Date.now() - tR, "ms");
|
|
2503
|
+
const docScoped = !!understanding?.doc_number;
|
|
2504
|
+
const gradePromise = docScoped ? Promise.resolve("skipped-doc-scoped") : (() => {
|
|
2505
|
+
const tg = Date.now();
|
|
2506
|
+
return gradeRetrieval(env.AI, roleModel(env, "grader"), q2.query, retrieved.hits.map((h) => h.text)).catch(() => null).finally(() => stageTiming["grade"] = Date.now() - tg);
|
|
2507
|
+
})();
|
|
2508
|
+
if (retrieved.hits.length >= 4 && (member || understanding?.complexity === "complex")) {
|
|
2509
|
+
const tl = Date.now();
|
|
2510
|
+
const reordered = await listwiseRerank(env, MODELS.listwise, understanding?.standalone_query || q2.query, retrieved.hits);
|
|
2511
|
+
stageTiming.listwise = Date.now() - tl;
|
|
2512
|
+
if (reordered) {
|
|
2513
|
+
console.log("listwise: reordered", reordered[0]?.metadata?.docidentifier ?? "?", "to top");
|
|
2514
|
+
retrieved = { ...retrieved, hits: reordered };
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
const grade = await gradePromise;
|
|
2518
|
+
stageTiming.retrieve = Date.now() - tR;
|
|
2519
|
+
console.log("stage: grade+listwise", Date.now() - tR, "ms since retrieve start | grade:", grade);
|
|
2520
|
+
if (grade === "weak" && understanding?.docidentifier) {
|
|
2521
|
+
const broaden = `${understanding.standalone_query || q2.query} ${understanding.docidentifier}`.trim();
|
|
2522
|
+
const tc = Date.now();
|
|
2523
|
+
const second = await retrieve(env, q2.query, { prev, understanding, queryOverride: broaden, federate, datasetScope: narrowed ? corpora : null, standardKeys, sealScope: declaredScoped ? docScope : null, lexicalBoost, ...routeSubset ? { stageSubset: routeSubset } : {} });
|
|
2524
|
+
const grade2 = await gradeRetrieval(env.AI, roleModel(env, "grader"), q2.query, second.hits.map((h) => h.text));
|
|
2525
|
+
stageTiming.corrective = Date.now() - tc;
|
|
2526
|
+
if (grade2 === "good") retrieved = second;
|
|
2527
|
+
}
|
|
2528
|
+
} catch (e) {
|
|
2529
|
+
console.log("ask: retrieval failed:", String(e).slice(0, 300));
|
|
2530
|
+
telemetry(env, ctx, tier, "ask", MODELS.embed, false, 0, await sha256Hex(q2.query), q2.lang, void 0, telemetryMeta());
|
|
2531
|
+
return finishLine("Search is briefly busy \u2014 please retry in a moment.");
|
|
2532
|
+
}
|
|
2533
|
+
const { hits } = retrieved;
|
|
2534
|
+
if (hits.length === 0 && !liveRecords?.length && (!boundModel || boundModel.gated)) {
|
|
2535
|
+
const answer2 = licenseBoundaryRefusal(modelDocHint?.doc_number ?? understanding?.doc_number ?? null, standardKeys) ?? refusalAnswer();
|
|
2536
|
+
const out2 = { answer: answer2, citations: [], model, query_hash: await sha256Hex(q2.query), context_applied: ctxApplied, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
|
|
2537
|
+
telemetry(env, ctx, tier, "ask", model, true, answer2.length, out2.query_hash, q2.lang, void 0, telemetryMeta());
|
|
2538
|
+
return json({ ...out2, quota });
|
|
2539
|
+
}
|
|
2540
|
+
const processNote = understanding?.process_intent ? P().retrieval.process_note : void 0;
|
|
2541
|
+
const licenseNote = licenseBoundaryNote(modelDocHint?.doc_number ?? understanding?.doc_number ?? null, standardKeys);
|
|
2542
|
+
const glossaryForNote = (() => {
|
|
2543
|
+
const g = retrieved.glossary ?? [];
|
|
2544
|
+
if (!g.length) return g;
|
|
2545
|
+
const dt = (understanding?.defined_terms ?? []).map((s) => s.toLowerCase());
|
|
2546
|
+
if (!dt.length) return g;
|
|
2547
|
+
const matched = g.filter((x) => dt.some((d) => x.term.toLowerCase().includes(d.split(" ")[0]) || d.includes(x.term.toLowerCase().split(" ")[0])));
|
|
2548
|
+
return matched.length ? matched : g;
|
|
2462
2549
|
})();
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2550
|
+
const vocabNote = glossaryForNote.length ? "Vocabulary binding \u2014 defined terms in the indexed corpus that may name this question's subject:\n" + glossaryForNote.map((g) => `- ${g.term} (${g.docidentifier}): ${g.definition}`).join("\n") + "\nIf the question describes a symptom or behavior in everyday words, OPEN the answer by naming the matching defined term, quote its definition, and cite its defining publication; keep using that term throughout. Match TIME SCALE carefully: change under a constant load over minutes/hours is creep; change over months/years of use is span stability or durability \u2014 do not call long-term drift creep." : void 0;
|
|
2551
|
+
const opsHits = ops.matched.map((m) => ({
|
|
2552
|
+
id: `ops:${m.anchor}`,
|
|
2553
|
+
score: 0.999,
|
|
2554
|
+
metadata: {
|
|
2555
|
+
doc_id: "smart-ops:catalog",
|
|
2556
|
+
docidentifier: m.docidentifier ?? "Platform API",
|
|
2557
|
+
doctype: "api-operation",
|
|
2558
|
+
doc_number: "",
|
|
2559
|
+
edition: "",
|
|
2560
|
+
language: "en",
|
|
2561
|
+
clause_anchor: m.anchor,
|
|
2562
|
+
clause_title: `Platform operation ${m.anchor}`,
|
|
2563
|
+
tier: "curated",
|
|
2564
|
+
corpus: "smart-ops",
|
|
2565
|
+
text_ref: ""
|
|
2566
|
+
},
|
|
2567
|
+
text: `${m.anchor} \u2014 ${m.text}`
|
|
2568
|
+
}));
|
|
2569
|
+
const { messages, usedHits } = buildMessages(
|
|
2570
|
+
q2.query,
|
|
2571
|
+
[...opsHits, ...hits],
|
|
2572
|
+
q2.lang,
|
|
2573
|
+
keptHistory,
|
|
2574
|
+
// stage-extracted graph facts (GraphRAG) ride the same note channel
|
|
2575
|
+
[ops.note, processNote, eNote, regNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, boundaryNote, licenseNote, ...retrieved.notes ?? []].filter(Boolean).join("\n") || void 0,
|
|
2576
|
+
summary,
|
|
2577
|
+
budget
|
|
2578
|
+
);
|
|
2579
|
+
await attachFigureImages(env, messages, usedHits, q2.query);
|
|
2580
|
+
const pendingTools = [];
|
|
2581
|
+
if (multiTurn && env.DB && !nameplate?.manufacturer) {
|
|
2582
|
+
try {
|
|
2583
|
+
const imageTurn = typeof withImage === "string";
|
|
2584
|
+
if (imageTurn) mark("Reading the photograph to identify the instrument");
|
|
2585
|
+
for (let round = 0; round < 3; round++) {
|
|
2586
|
+
const imageNote = imageTurn && round === 0 ? "A photograph of the instrument is attached after this message. Transcribe the maker, model and any printed certificate number you can read FROM THE PHOTOGRAPH ITSELF, then emit the TOOL line with those tokens as the query \u2014 never invented, and never tokens taken from any register content elsewhere in the context (a register row's holder is not the plate's maker; observed live 2026-10-04)." : "";
|
|
2587
|
+
const continueNote = round > 0 ? "The tool results above are in hand. Answer now without a TOOL line, or issue exactly one more TOOL line if one more query is genuinely needed." : "";
|
|
2588
|
+
const probeMessages = [...messages.slice(0, -1), { role: "user", content: [TOOL_DECLARATION, imageNote, continueNote, q2.query].filter(Boolean).join("\n\n") }];
|
|
2589
|
+
if (imageTurn && round === 0) probeMessages.push({ role: "user", content: [{ type: "image_url", image_url: { url: withImage } }] });
|
|
2590
|
+
const probe = await env.AI.run(model, {
|
|
2591
|
+
messages: probeMessages,
|
|
2592
|
+
max_tokens: 700,
|
|
2593
|
+
reasoning_effort: imageTurn && round === 0 ? "high" : "low"
|
|
2594
|
+
});
|
|
2595
|
+
const probeText = typeof probe?.response === "string" ? probe?.response : probe?.choices?.[0]?.message?.content ?? "";
|
|
2596
|
+
probeTokensUsed += usageTotal(probe?.usage) ?? 0;
|
|
2597
|
+
const nativeCall = Array.isArray(probe?.tool_calls) ? probe.tool_calls[0]?.function : null;
|
|
2598
|
+
const call = nativeCall ? {
|
|
2599
|
+
name: String(nativeCall.name ?? ""),
|
|
2600
|
+
args: (() => {
|
|
2601
|
+
try {
|
|
2602
|
+
return typeof nativeCall.arguments === "string" ? JSON.parse(nativeCall.arguments) : nativeCall.arguments ?? {};
|
|
2603
|
+
} catch {
|
|
2604
|
+
return {};
|
|
2605
|
+
}
|
|
2606
|
+
})()
|
|
2607
|
+
} : parseToolCall(probeText);
|
|
2608
|
+
if (!call || !call.name) break;
|
|
2609
|
+
const result = await runTool(env, call);
|
|
2610
|
+
if (!result) break;
|
|
2611
|
+
mark(`${result.name} \u2014 ${result.query}`.slice(0, 140));
|
|
2612
|
+
messages.push({ role: "system", content: toolNote(result) });
|
|
2613
|
+
pendingTools.push(result);
|
|
2614
|
+
console.log("agent-tool:", result.name, JSON.stringify(result.query), "->", result.output.slice(0, 80));
|
|
2615
|
+
}
|
|
2616
|
+
} catch {
|
|
2470
2617
|
}
|
|
2471
2618
|
}
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
if (grade2 === "good") retrieved = second;
|
|
2482
|
-
}
|
|
2483
|
-
} catch (e) {
|
|
2484
|
-
console.log("ask: retrieval failed:", String(e).slice(0, 300));
|
|
2485
|
-
telemetry(env, ctx, tier, "ask", MODELS.embed, false, 0, await sha256Hex(q.query), q.lang, void 0, telemetryMeta());
|
|
2486
|
-
return err(503, "retrieval_unavailable", "Search is briefly busy \u2014 please retry in a moment.");
|
|
2487
|
-
}
|
|
2488
|
-
const { hits } = retrieved;
|
|
2489
|
-
if (hits.length === 0 && !liveRecords?.length && (!boundModel || boundModel.gated)) {
|
|
2490
|
-
const answer2 = licenseBoundaryRefusal(modelDocHint?.doc_number ?? understanding?.doc_number ?? null, standardKeys) ?? refusalAnswer();
|
|
2491
|
-
const out2 = { answer: answer2, citations: [], model, query_hash: await sha256Hex(q.query), context_applied: ctxApplied, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
|
|
2492
|
-
telemetry(env, ctx, tier, "ask", model, true, answer2.length, out2.query_hash, q.lang, void 0, telemetryMeta());
|
|
2493
|
-
return json({ ...out2, quota });
|
|
2494
|
-
}
|
|
2495
|
-
const processNote = understanding?.process_intent ? P().retrieval.process_note : void 0;
|
|
2496
|
-
const licenseNote = licenseBoundaryNote(modelDocHint?.doc_number ?? understanding?.doc_number ?? null, standardKeys);
|
|
2497
|
-
const glossaryForNote = (() => {
|
|
2498
|
-
const g = retrieved.glossary ?? [];
|
|
2499
|
-
if (!g.length) return g;
|
|
2500
|
-
const dt = (understanding?.defined_terms ?? []).map((s) => s.toLowerCase());
|
|
2501
|
-
if (!dt.length) return g;
|
|
2502
|
-
const matched = g.filter((x) => dt.some((d) => x.term.toLowerCase().includes(d.split(" ")[0]) || d.includes(x.term.toLowerCase().split(" ")[0])));
|
|
2503
|
-
return matched.length ? matched : g;
|
|
2504
|
-
})();
|
|
2505
|
-
const vocabNote = glossaryForNote.length ? "Vocabulary binding \u2014 defined terms in the indexed corpus that may name this question's subject:\n" + glossaryForNote.map((g) => `- ${g.term} (${g.docidentifier}): ${g.definition}`).join("\n") + "\nIf the question describes a symptom or behavior in everyday words, OPEN the answer by naming the matching defined term, quote its definition, and cite its defining publication; keep using that term throughout. Match TIME SCALE carefully: change under a constant load over minutes/hours is creep; change over months/years of use is span stability or durability \u2014 do not call long-term drift creep." : void 0;
|
|
2506
|
-
const opsHits = ops.matched.map((m) => ({
|
|
2507
|
-
id: `ops:${m.anchor}`,
|
|
2508
|
-
score: 0.999,
|
|
2509
|
-
metadata: {
|
|
2510
|
-
doc_id: "smart-ops:catalog",
|
|
2511
|
-
docidentifier: m.docidentifier ?? "Platform API",
|
|
2512
|
-
doctype: "api-operation",
|
|
2513
|
-
doc_number: "",
|
|
2514
|
-
edition: "",
|
|
2515
|
-
language: "en",
|
|
2516
|
-
clause_anchor: m.anchor,
|
|
2517
|
-
clause_title: `Platform operation ${m.anchor}`,
|
|
2518
|
-
tier: "curated",
|
|
2519
|
-
corpus: "smart-ops",
|
|
2520
|
-
text_ref: ""
|
|
2521
|
-
},
|
|
2522
|
-
text: `${m.anchor} \u2014 ${m.text}`
|
|
2523
|
-
}));
|
|
2524
|
-
const { messages, usedHits } = buildMessages(
|
|
2525
|
-
q.query,
|
|
2526
|
-
[...opsHits, ...hits],
|
|
2527
|
-
q.lang,
|
|
2528
|
-
keptHistory,
|
|
2529
|
-
// stage-extracted graph facts (GraphRAG) ride the same note channel
|
|
2530
|
-
[ops.note, processNote, eNote, regNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, boundaryNote, licenseNote, ...retrieved.notes ?? []].filter(Boolean).join("\n") || void 0,
|
|
2531
|
-
summary,
|
|
2532
|
-
budget
|
|
2533
|
-
);
|
|
2534
|
-
await attachFigureImages(env, messages, usedHits, q.query);
|
|
2535
|
-
const pendingTools = [];
|
|
2536
|
-
let probeTokensUsed = 0;
|
|
2537
|
-
if (multiTurn && env.DB) {
|
|
2538
|
-
try {
|
|
2539
|
-
const imageTurn = typeof withImage === "string";
|
|
2540
|
-
if (imageTurn) mark("Reading the photograph to identify the instrument");
|
|
2541
|
-
for (let round = 0; round < 3; round++) {
|
|
2542
|
-
const imageNote = imageTurn && round === 0 ? "A photograph of the instrument is attached after this message. Transcribe the maker, model and any printed certificate number you can read FROM THE PHOTOGRAPH ITSELF, then emit the TOOL line with those tokens as the query \u2014 never invented, and never tokens taken from any register content elsewhere in the context (a register row's holder is not the plate's maker; observed live 2026-10-04)." : "";
|
|
2543
|
-
const continueNote = round > 0 ? "The tool results above are in hand. Answer now without a TOOL line, or issue exactly one more TOOL line if one more query is genuinely needed." : "";
|
|
2544
|
-
const probeMessages = [...messages.slice(0, -1), { role: "user", content: [TOOL_DECLARATION, imageNote, continueNote, q.query].filter(Boolean).join("\n\n") }];
|
|
2545
|
-
if (imageTurn && round === 0) probeMessages.push({ role: "user", content: [{ type: "image_url", image_url: { url: withImage } }] });
|
|
2546
|
-
const probe = await env.AI.run(model, {
|
|
2547
|
-
messages: probeMessages,
|
|
2548
|
-
max_tokens: 700,
|
|
2549
|
-
reasoning_effort: imageTurn && round === 0 ? "high" : "low"
|
|
2550
|
-
});
|
|
2551
|
-
const probeText = typeof probe?.response === "string" ? probe?.response : probe?.choices?.[0]?.message?.content ?? "";
|
|
2552
|
-
probeTokensUsed += usageTotal(probe?.usage) ?? 0;
|
|
2553
|
-
const nativeCall = Array.isArray(probe?.tool_calls) ? probe.tool_calls[0]?.function : null;
|
|
2554
|
-
const call = nativeCall ? {
|
|
2555
|
-
name: String(nativeCall.name ?? ""),
|
|
2556
|
-
args: (() => {
|
|
2557
|
-
try {
|
|
2558
|
-
return typeof nativeCall.arguments === "string" ? JSON.parse(nativeCall.arguments) : nativeCall.arguments ?? {};
|
|
2559
|
-
} catch {
|
|
2560
|
-
return {};
|
|
2561
|
-
}
|
|
2562
|
-
})()
|
|
2563
|
-
} : parseToolCall(probeText);
|
|
2564
|
-
if (!call || !call.name) break;
|
|
2565
|
-
const result = await runTool(env, call);
|
|
2566
|
-
if (!result) break;
|
|
2567
|
-
mark(`${result.name} \u2014 ${result.query}`.slice(0, 140));
|
|
2568
|
-
messages.push({ role: "system", content: toolNote(result) });
|
|
2569
|
-
pendingTools.push(result);
|
|
2570
|
-
console.log("agent-tool:", result.name, JSON.stringify(result.query), "->", result.output.slice(0, 80));
|
|
2619
|
+
if (withImage) {
|
|
2620
|
+
const wantsMarkings = /\b(mark(ing|ings)?|nameplate|label|inscription|engrav|sticker|plate)\b|certificat/i.test(q2.query);
|
|
2621
|
+
const last = messages[messages.length - 1];
|
|
2622
|
+
const note = wantsMarkings ? "\n\n(The user attached a photo with this question. First transcribe every inscription you can actually read in the image \u2014 names, model references, accuracy classes, numeric values with their units, certificate or approval numbers \u2014 quoting them verbatim. Then answer the question from the numbered passages, citing the requirement each interpretation rests on. If an inscription is unreadable, say so; never invent a marking.)" : "\n\n(The user attached an image with this question; interpret it directly when answering.)";
|
|
2623
|
+
if (typeof last.content === "string") {
|
|
2624
|
+
last.content = last.content + note;
|
|
2625
|
+
} else {
|
|
2626
|
+
const textPart = last.content.find((p) => p.type === "text");
|
|
2627
|
+
if (textPart) textPart.text += note;
|
|
2571
2628
|
}
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
}
|
|
2575
|
-
if (withImage) {
|
|
2576
|
-
const wantsMarkings = /\b(mark(ing|ings)?|nameplate|label|inscription|engrav|sticker|plate)\b|certificat/i.test(q.query);
|
|
2577
|
-
const last = messages[messages.length - 1];
|
|
2578
|
-
const note = wantsMarkings ? "\n\n(The user attached a photo with this question. First transcribe every inscription you can actually read in the image \u2014 names, model references, accuracy classes, numeric values with their units, certificate or approval numbers \u2014 quoting them verbatim. Then answer the question from the numbered passages, citing the requirement each interpretation rests on. If an inscription is unreadable, say so; never invent a marking.)" : "\n\n(The user attached an image with this question; interpret it directly when answering.)";
|
|
2579
|
-
if (typeof last.content === "string") {
|
|
2580
|
-
last.content = last.content + note;
|
|
2581
|
-
} else {
|
|
2582
|
-
const textPart = last.content.find((p) => p.type === "text");
|
|
2583
|
-
if (textPart) textPart.text += note;
|
|
2629
|
+
messages.push({ role: "user", content: [{ type: "image_url", image_url: { url: withImage } }] });
|
|
2630
|
+
console.log("user image attached to generation");
|
|
2584
2631
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
async start(controller) {
|
|
2596
|
-
const send = (obj) => controller.enqueue(encoder.encode(`data: ${JSON.stringify(obj)}
|
|
2597
|
-
|
|
2598
|
-
`));
|
|
2599
|
-
for (const step of agentSteps) {
|
|
2600
|
-
try {
|
|
2601
|
-
send({ type: "agent", step });
|
|
2602
|
-
} catch {
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
for (const t of pendingTools) {
|
|
2606
|
-
try {
|
|
2607
|
-
send({ type: "tool", name: t.name, query: t.query });
|
|
2608
|
-
} catch {
|
|
2609
|
-
}
|
|
2632
|
+
const queryHash = await sha256Hex(q2.query);
|
|
2633
|
+
const cites = boundModel ? [modelCitation(boundModel), ...citations(usedHits)] : citations(usedHits);
|
|
2634
|
+
if (live2) {
|
|
2635
|
+
const stream = await generateStream(env, model, messages, routeEffort(routed.route));
|
|
2636
|
+
if (stream) {
|
|
2637
|
+
const send = (obj) => live2.send(obj);
|
|
2638
|
+
for (const step of agentSteps) {
|
|
2639
|
+
try {
|
|
2640
|
+
send({ type: "agent", step });
|
|
2641
|
+
} catch {
|
|
2610
2642
|
}
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
send({ type: "citations", citations: cites, context_applied: ctxApplied, ...sourceQuality ? { source_quality: sourceQuality, confidence_note: qualityNote(sourceQuality), ...sourceQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(cites) } : {} } : {}, ...liveRecords ? { records: liveRecords } : {}, quota });
|
|
2614
|
-
const stats = {};
|
|
2615
|
-
let full = "";
|
|
2643
|
+
}
|
|
2644
|
+
for (const t of pendingTools) {
|
|
2616
2645
|
try {
|
|
2617
|
-
|
|
2618
|
-
for await (const tok of sseTokens(stream, stats)) {
|
|
2619
|
-
full += tok;
|
|
2620
|
-
if (headSettled) {
|
|
2621
|
-
send({ type: "token", v: tok });
|
|
2622
|
-
continue;
|
|
2623
|
-
}
|
|
2624
|
-
if (full.length < 80) continue;
|
|
2625
|
-
headSettled = true;
|
|
2626
|
-
if (toolNarration(full)) {
|
|
2627
|
-
console.log("tool-narration(stream): regenerating once");
|
|
2628
|
-
send({ type: "retry" });
|
|
2629
|
-
const regen = await generateStream(env, model, [
|
|
2630
|
-
...messages,
|
|
2631
|
-
{ role: "system", content: TOOL_NARRATION_NOTICE }
|
|
2632
|
-
], routeEffort(routed.route));
|
|
2633
|
-
if (regen) {
|
|
2634
|
-
full = "";
|
|
2635
|
-
for await (const tok2 of sseTokens(regen, stats)) {
|
|
2636
|
-
full += tok2;
|
|
2637
|
-
send({ type: "token", v: tok2 });
|
|
2638
|
-
}
|
|
2639
|
-
} else {
|
|
2640
|
-
send({ type: "token", v: full });
|
|
2641
|
-
}
|
|
2642
|
-
break;
|
|
2643
|
-
}
|
|
2644
|
-
send({ type: "token", v: full });
|
|
2645
|
-
}
|
|
2646
|
-
if (!headSettled) {
|
|
2647
|
-
headSettled = true;
|
|
2648
|
-
if (!toolNarration(full)) send({ type: "token", v: full });
|
|
2649
|
-
}
|
|
2646
|
+
send({ type: "tool", name: t.name, query: t.query });
|
|
2650
2647
|
} catch {
|
|
2651
2648
|
}
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2649
|
+
}
|
|
2650
|
+
send({ type: "read", read: readAs() });
|
|
2651
|
+
const sourceQuality = answerQuality(cites.map((c) => c.quality));
|
|
2652
|
+
send({ type: "citations", citations: cites, context_applied: ctxApplied, ...sourceQuality ? { source_quality: sourceQuality, confidence_note: qualityNote(sourceQuality), ...sourceQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(cites) } : {} } : {}, ...liveRecords ? { records: liveRecords } : {}, quota });
|
|
2653
|
+
const stats = {};
|
|
2654
|
+
let full = "";
|
|
2655
|
+
try {
|
|
2656
|
+
let headSettled = false;
|
|
2657
|
+
for await (const tok of sseTokens(stream, stats)) {
|
|
2658
|
+
full += tok;
|
|
2659
|
+
if (headSettled) {
|
|
2660
|
+
send({ type: "token", v: tok });
|
|
2661
|
+
continue;
|
|
2662
|
+
}
|
|
2663
|
+
if (full.length < 80) continue;
|
|
2664
|
+
headSettled = true;
|
|
2665
|
+
if (toolNarration(full) || intentPreamble(full)) {
|
|
2666
|
+
console.log(toolNarration(full) ? "tool-narration(stream): regenerating once" : "intent-preamble(stream): regenerating once");
|
|
2667
|
+
send({ type: "retry" });
|
|
2668
|
+
const regen = await generateStream(env, model, [
|
|
2669
|
+
...messages,
|
|
2670
|
+
{ role: "system", content: toolNarration(full) ? TOOL_NARRATION_NOTICE : INTENT_PREAMBLE_NOTICE }
|
|
2671
|
+
], routeEffort(routed.route));
|
|
2672
|
+
if (regen) {
|
|
2673
|
+
full = "";
|
|
2674
|
+
for await (const tok2 of sseTokens(regen, stats)) {
|
|
2675
|
+
full += tok2;
|
|
2676
|
+
send({ type: "token", v: tok2 });
|
|
2669
2677
|
}
|
|
2670
|
-
}
|
|
2678
|
+
} else {
|
|
2679
|
+
send({ type: "token", v: full });
|
|
2671
2680
|
}
|
|
2681
|
+
break;
|
|
2672
2682
|
}
|
|
2683
|
+
send({ type: "token", v: full });
|
|
2673
2684
|
}
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
type: "done",
|
|
2678
|
-
model,
|
|
2679
|
-
query_hash: queryHash,
|
|
2680
|
-
follow_ups: refusalShaped(canonical0, refusalScope(answerCites(full))) ? [] : understanding?.follow_ups ?? [],
|
|
2681
|
-
blocks: [...c2.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : []],
|
|
2682
|
-
context_applied: ctxApplied,
|
|
2683
|
-
read: readAs(),
|
|
2684
|
-
// the evidence view's ground truth: the exact passages this
|
|
2685
|
-
// answer was built from, compact — cache hits carry none,
|
|
2686
|
-
// because the cache stores the answer and never the passages
|
|
2687
|
-
passages: usedHits.slice(0, 8).map((h) => ({ d: h.metadata.docidentifier ?? "", a: h.metadata.clause_anchor ?? "", t: (h.text ?? "").slice(0, h.metadata.block === "table" ? 1400 : 600), b: h.metadata.block === "table" || void 0, ...h.metadata.table_selection ? { s: h.metadata.table_selection } : {} }))
|
|
2688
|
-
});
|
|
2689
|
-
telemetry(env, ctx, tier, "ask", model, true, c2.text.length, queryHash, q.lang, void 0, telemetryMeta());
|
|
2690
|
-
const canonical = c2.text;
|
|
2691
|
-
let streamedEntailment = null;
|
|
2692
|
-
let streamedNote = "";
|
|
2693
|
-
if (THRESHOLDS.entailmentGate && sourceQuality && usedHits.length && !canonical.includes(refusalAnswer())) {
|
|
2694
|
-
const raced = await Promise.race([
|
|
2695
|
-
scoreFaithfulness(env.AI, roleModel(env, "grader"), canonical, usedHits.map((h) => h.text)),
|
|
2696
|
-
new Promise((r) => setTimeout(() => r(null), THRESHOLDS.entailmentBudgetMs))
|
|
2697
|
-
]);
|
|
2698
|
-
if (raced) {
|
|
2699
|
-
const v = entailmentVerdict(raced.score, THRESHOLDS.entailmentSupportedFloor, THRESHOLDS.entailmentPartialFloor);
|
|
2700
|
-
streamedEntailment = { support: v.support, score: Math.round(raced.score * 100) / 100, ...raced.ungrounded_claims?.length ? { ungrounded: raced.ungrounded_claims.slice(0, 3) } : {} };
|
|
2701
|
-
streamedNote = v.note;
|
|
2702
|
-
if (v.support !== "supported") console.log("entailment(stream):", v.support, raced.score);
|
|
2703
|
-
send({ type: "confidence", source_quality: sourceQuality, confidence_note: streamedNote || qualityNote(sourceQuality), ...streamedEntailment ? { entailment: streamedEntailment } : {} });
|
|
2704
|
-
}
|
|
2685
|
+
if (!headSettled) {
|
|
2686
|
+
headSettled = true;
|
|
2687
|
+
if (!toolNarration(full) && !intentPreamble(full)) send({ type: "token", v: full });
|
|
2705
2688
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2689
|
+
} catch {
|
|
2690
|
+
}
|
|
2691
|
+
const tq2 = await chargeAnswerTokens(env, bucketId, stats, messageChars(messages), full.length, probeTokensUsed);
|
|
2692
|
+
send({ type: "quota", quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
|
|
2693
|
+
if (withImage && register?.rows?.length && full.includes(refusalAnswer())) {
|
|
2694
|
+
console.log("blind-answer(stream): regenerating once");
|
|
2695
|
+
mark("Re-answering from the register results");
|
|
2696
|
+
send({ type: "retry" });
|
|
2697
|
+
const regen = await generateStream(env, model, [
|
|
2698
|
+
...messages.slice(0, -1),
|
|
2699
|
+
{ role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
|
|
2700
|
+
messages[messages.length - 1]
|
|
2701
|
+
], routeEffort(routed.route));
|
|
2702
|
+
if (regen) {
|
|
2703
|
+
full = "";
|
|
2704
|
+
try {
|
|
2705
|
+
for await (const tok of sseTokens(regen)) {
|
|
2706
|
+
full += tok;
|
|
2707
|
+
send({ type: "token", v: tok });
|
|
2708
|
+
}
|
|
2709
|
+
} catch {
|
|
2710
|
+
}
|
|
2711
2711
|
}
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2712
|
+
}
|
|
2713
|
+
const canonical0 = exciseMisplacedPin(canonicalRefusal(full.replace(/^TOOL [a-z_.]+.*$\n?/gm, "").replace(/^\n+/, ""), refusalScope(answerCites(full))), answerCites(full));
|
|
2714
|
+
const c2 = canonical0.includes(refusalAnswer()) ? { text: canonical0, blocks: [], dropped: [] } : await contractV2(env.DB, canonical0, usedHits);
|
|
2715
|
+
send({
|
|
2716
|
+
type: "done",
|
|
2717
|
+
model,
|
|
2718
|
+
query_hash: queryHash,
|
|
2719
|
+
follow_ups: refusalShaped(canonical0, refusalScope(answerCites(full))) ? [] : understanding?.follow_ups ?? [],
|
|
2720
|
+
blocks: [...c2.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : []],
|
|
2721
|
+
context_applied: ctxApplied,
|
|
2722
|
+
read: readAs(),
|
|
2723
|
+
// the evidence view's ground truth: the exact passages this
|
|
2724
|
+
// answer was built from, compact — cache hits carry none,
|
|
2725
|
+
// because the cache stores the answer and never the passages
|
|
2726
|
+
passages: usedHits.slice(0, 8).map((h) => ({ d: h.metadata.docidentifier ?? "", a: h.metadata.clause_anchor ?? "", t: (h.text ?? "").slice(0, h.metadata.block === "table" ? 1400 : 600), b: h.metadata.block === "table" || void 0, ...h.metadata.table_selection ? { s: h.metadata.table_selection } : {} }))
|
|
2727
|
+
});
|
|
2728
|
+
telemetry(env, ctx, tier, "ask", model, true, c2.text.length, queryHash, q2.lang, void 0, telemetryMeta());
|
|
2729
|
+
const canonical = c2.text;
|
|
2730
|
+
let streamedEntailment = null;
|
|
2731
|
+
let streamedNote = "";
|
|
2732
|
+
if (THRESHOLDS.entailmentGate && sourceQuality && usedHits.length && !canonical.includes(refusalAnswer())) {
|
|
2733
|
+
const raced = await Promise.race([
|
|
2734
|
+
scoreFaithfulness(env.AI, roleModel(env, "grader"), canonical, usedHits.map((h) => h.text)),
|
|
2735
|
+
new Promise((r) => setTimeout(() => r(null), THRESHOLDS.entailmentBudgetMs))
|
|
2736
|
+
]);
|
|
2737
|
+
if (raced) {
|
|
2738
|
+
const v = entailmentVerdict(raced.score, THRESHOLDS.entailmentSupportedFloor, THRESHOLDS.entailmentPartialFloor);
|
|
2739
|
+
streamedEntailment = { support: v.support, score: Math.round(raced.score * 100) / 100, ...raced.ungrounded_claims?.length ? { ungrounded: raced.ungrounded_claims.slice(0, 3) } : {} };
|
|
2740
|
+
streamedNote = v.note;
|
|
2741
|
+
if (v.support !== "supported") console.log("entailment(stream):", v.support, raced.score);
|
|
2742
|
+
send({ type: "confidence", source_quality: sourceQuality, confidence_note: streamedNote || qualityNote(sourceQuality), ...streamedEntailment ? { entailment: streamedEntailment } : {} });
|
|
2716
2743
|
}
|
|
2717
|
-
controller.close();
|
|
2718
2744
|
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
"
|
|
2724
|
-
"x-accel-buffering": "no",
|
|
2725
|
-
...corsHeaders(req)
|
|
2745
|
+
const streamedAnchors = checkQuoteAnchors(canonical, usedHits.map((h) => h.text));
|
|
2746
|
+
const streamedRetyped = tableRetyped(canonical, usedHits.some((h) => h.metadata.unit_id && h.metadata.block === "table"));
|
|
2747
|
+
const streamed = { total: streamedAnchors.total, violations: streamedRetyped ? ["table-retyped"] : streamedAnchors.violations };
|
|
2748
|
+
if (streamed.violations.length > 0) {
|
|
2749
|
+
console.log("anchors:", streamed.violations.length, "of", streamed.total, "unverified \u2014 not caching");
|
|
2726
2750
|
}
|
|
2751
|
+
if (streamed.violations.length === 0 && canonical.length > 0 && !contextual && !declaredCtx && cacheableAnswer(canonical, refusalScope(answerCites(canonical))) && !ablate) {
|
|
2752
|
+
ctx.waitUntil(
|
|
2753
|
+
env.CACHE.put(exactCacheKey(env.INDEX_VERSION, gen, ns, await sha256Hex(cacheKeyMaterial(q2.query, q2.lang, salt))), JSON.stringify({ answer: canonical, citations: cites, model, query_hash: queryHash, ...sourceQuality ? { source_quality: sourceQuality, confidence_note: streamedNote || qualityNote(sourceQuality) } : {}, ...streamedEntailment ? { entailment: streamedEntailment } : {} }), { expirationTtl: LIMITS.cacheTtlSec })
|
|
2754
|
+
);
|
|
2755
|
+
}
|
|
2756
|
+
live2.close();
|
|
2757
|
+
} else {
|
|
2758
|
+
live2.send({ type: "token", v: "The generation model is unavailable; please retry." });
|
|
2759
|
+
live2.send({ type: "done", model: MODELS.member, query_hash: "", context_applied: NO_CONTEXT });
|
|
2760
|
+
live2.close();
|
|
2761
|
+
return null;
|
|
2762
|
+
}
|
|
2763
|
+
return null;
|
|
2764
|
+
}
|
|
2765
|
+
const tGen = Date.now();
|
|
2766
|
+
let answer = null;
|
|
2767
|
+
if (ablate?.speculative) {
|
|
2768
|
+
const spec = await speculativeDraftVerify(env, {
|
|
2769
|
+
query: q2.query,
|
|
2770
|
+
hits: usedHits,
|
|
2771
|
+
lang: q2.lang,
|
|
2772
|
+
draftModel: MODELS.member,
|
|
2773
|
+
verifierModel: roleModel(env, "verifier")
|
|
2774
|
+
}).catch((e) => {
|
|
2775
|
+
console.log("speculative: failed, falling through \u2014", String(e).slice(0, 120));
|
|
2776
|
+
return null;
|
|
2727
2777
|
});
|
|
2778
|
+
if (spec) {
|
|
2779
|
+
answer = spec.answer;
|
|
2780
|
+
stageTiming.speculative = Date.now() - tGen;
|
|
2781
|
+
console.log("speculative:", spec.nDrafts, "drafts,", spec.chosen, "viable \u2014 verified");
|
|
2782
|
+
}
|
|
2728
2783
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
let answer = null;
|
|
2732
|
-
if (ablate?.speculative) {
|
|
2733
|
-
const spec = await speculativeDraftVerify(env, {
|
|
2734
|
-
query: q.query,
|
|
2735
|
-
hits: usedHits,
|
|
2736
|
-
lang: q.lang,
|
|
2737
|
-
draftModel: MODELS.member,
|
|
2738
|
-
verifierModel: roleModel(env, "verifier")
|
|
2739
|
-
}).catch((e) => {
|
|
2740
|
-
console.log("speculative: failed, falling through \u2014", String(e).slice(0, 120));
|
|
2741
|
-
return null;
|
|
2742
|
-
});
|
|
2743
|
-
if (spec) {
|
|
2744
|
-
answer = spec.answer;
|
|
2745
|
-
stageTiming.speculative = Date.now() - tGen;
|
|
2746
|
-
console.log("speculative:", spec.nDrafts, "drafts,", spec.chosen, "viable \u2014 verified");
|
|
2747
|
-
}
|
|
2748
|
-
}
|
|
2749
|
-
if (!answer) answer = await generateOnce(env, model, messages, routeEffort(routed.route));
|
|
2750
|
-
if (answer === null) {
|
|
2751
|
-
generateRetries += 1;
|
|
2752
|
-
const isFigureAttachMessage = (m) => Array.isArray(m.content) && m.content.some((part) => part?.type === "text" && /^The original image of figure unit /.test(part.text ?? ""));
|
|
2753
|
-
const flat = messages.filter((m) => !isFigureAttachMessage(m)).map(
|
|
2754
|
-
(m) => typeof m.content === "string" ? m : { ...m, content: m.content.filter((p) => p?.type === "text").map((p) => (p?.text ?? "").replace(/\n?\(The user attached an image with this question; interpret it directly when answering\.\)/, "")).join("\n") }
|
|
2755
|
-
);
|
|
2756
|
-
answer = await generateOnce(env, MODELS.fallback, flat, routeEffort(routed.route));
|
|
2757
|
-
}
|
|
2758
|
-
const scrubToolLines = (t) => t.replace(/^TOOL [a-z_.]+.*$\n?/gm, "").replace(/^\n+/, "");
|
|
2759
|
-
if (answer) answer = scrubToolLines(answer);
|
|
2760
|
-
if (answer) answer = canonicalRefusal(answer, refusalScope(answerCites(answer)));
|
|
2761
|
-
if (answer) answer = scrubToolLines(answer);
|
|
2762
|
-
if (answer) answer = exciseMisplacedPin(answer, answerCites(answer));
|
|
2763
|
-
stageTiming.generate = Date.now() - tGen;
|
|
2764
|
-
let used = usedHits;
|
|
2765
|
-
if (answer && !answer.includes(refusalAnswer())) {
|
|
2766
|
-
const anchors = checkQuoteAnchors(answer, used.map((h) => h.text));
|
|
2767
|
-
const hasTableUnit = used.some((h) => h.metadata.unit_id && h.metadata.block === "table");
|
|
2768
|
-
const retyped = tableRetyped(answer, hasTableUnit);
|
|
2769
|
-
const unreferenced = (() => {
|
|
2770
|
-
if (!hasTableUnit || answer.includes("[[u:")) return false;
|
|
2771
|
-
const norm2 = (s) => (s.match(/\d[\d ,.]{1,8}\d/g) ?? []).map((x) => x.replace(/[ ,.]/g, ""));
|
|
2772
|
-
const nums = norm2(answer);
|
|
2773
|
-
if (nums.length < 2) return false;
|
|
2774
|
-
const tableNums = new Set(
|
|
2775
|
-
norm2(used.filter((h) => h.metadata.unit_id && h.metadata.block === "table").map((h) => h.text).join(" "))
|
|
2776
|
-
);
|
|
2777
|
-
return nums.filter((n) => tableNums.has(n)).length >= 2;
|
|
2778
|
-
})();
|
|
2779
|
-
if (anchors.violations.length > 0 || retyped || unreferenced || toolNarration(answer)) {
|
|
2780
|
-
console.log("contract check:", anchors.violations.length, "anchor violations; tableRetyped:", retyped, "; tableDataUnreferenced:", unreferenced, "; toolNarration:", toolNarration(answer), "\u2014 regenerating");
|
|
2781
|
-
const tableUnitId = unreferenced ? used.find((h) => h.metadata.unit_id && h.metadata.block === "table")?.metadata.unit_id : void 0;
|
|
2782
|
-
const note = toolNarration(answer) ? TOOL_NARRATION_NOTICE : retyped || unreferenced ? `Correction notice: your draft reproduced a table as markdown or presented a served table's data without its reference. Rewrite the answer: describe the table in prose, cite the clause, and write the reference token [[u:${tableUnitId ?? "<unit id>"}]] exactly where the table belongs. Do not render any table as markdown.` : ANCHOR_CORRECTION_NOTE;
|
|
2784
|
+
if (!answer) answer = await generateOnce(env, model, messages, routeEffort(routed.route));
|
|
2785
|
+
if (answer === null) {
|
|
2783
2786
|
generateRetries += 1;
|
|
2784
|
-
const
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2787
|
+
const isFigureAttachMessage = (m) => Array.isArray(m.content) && m.content.some((part) => part?.type === "text" && /^The original image of figure unit /.test(part.text ?? ""));
|
|
2788
|
+
const flat = messages.filter((m) => !isFigureAttachMessage(m)).map(
|
|
2789
|
+
(m) => typeof m.content === "string" ? m : { ...m, content: m.content.filter((p) => p?.type === "text").map((p) => (p?.text ?? "").replace(/\n?\(The user attached an image with this question; interpret it directly when answering\.\)/, "")).join("\n") }
|
|
2790
|
+
);
|
|
2791
|
+
answer = await generateOnce(env, MODELS.fallback, flat, routeEffort(routed.route));
|
|
2792
|
+
}
|
|
2793
|
+
if (answer === null) {
|
|
2794
|
+
telemetry(env, ctx, tier, "ask", model, false, 0, queryHash, q2.lang, void 0, telemetryMeta());
|
|
2795
|
+
return err(502, "generation_failed", "The generation model is unavailable; please retry.");
|
|
2796
|
+
}
|
|
2797
|
+
const scrubToolLines = (t) => t.replace(/^TOOL [a-z_.]+.*$\n?/gm, "").replace(/^\n+/, "");
|
|
2798
|
+
if (answer) answer = scrubToolLines(answer);
|
|
2799
|
+
if (answer) answer = canonicalRefusal(answer, refusalScope(answerCites(answer)));
|
|
2800
|
+
if (answer) answer = scrubToolLines(answer);
|
|
2801
|
+
if (answer) answer = exciseMisplacedPin(answer, answerCites(answer));
|
|
2802
|
+
stageTiming.generate = Date.now() - tGen;
|
|
2803
|
+
let used = usedHits;
|
|
2804
|
+
if (answer && !answer.includes(refusalAnswer())) {
|
|
2805
|
+
const anchors = checkQuoteAnchors(answer, used.map((h) => h.text));
|
|
2806
|
+
const hasTableUnit = used.some((h) => h.metadata.unit_id && h.metadata.block === "table");
|
|
2807
|
+
const retyped = tableRetyped(answer, hasTableUnit);
|
|
2808
|
+
const unreferenced = (() => {
|
|
2809
|
+
if (!hasTableUnit || answer.includes("[[u:")) return false;
|
|
2810
|
+
const norm2 = (s) => (s.match(/\d[\d ,.]{1,8}\d/g) ?? []).map((x) => x.replace(/[ ,.]/g, ""));
|
|
2811
|
+
const nums = norm2(answer);
|
|
2812
|
+
if (nums.length < 2) return false;
|
|
2813
|
+
const tableNums = new Set(
|
|
2814
|
+
norm2(used.filter((h) => h.metadata.unit_id && h.metadata.block === "table").map((h) => h.text).join(" "))
|
|
2815
|
+
);
|
|
2816
|
+
return nums.filter((n) => tableNums.has(n)).length >= 2;
|
|
2817
|
+
})();
|
|
2818
|
+
if (anchors.violations.length > 0 || retyped || unreferenced || toolNarration(answer) || intentPreamble(answer)) {
|
|
2819
|
+
console.log("contract check:", anchors.violations.length, "anchor violations; tableRetyped:", retyped, "; tableDataUnreferenced:", unreferenced, "; toolNarration:", toolNarration(answer), "; intentPreamble:", intentPreamble(answer), "\u2014 regenerating");
|
|
2820
|
+
const tableUnitId = unreferenced ? used.find((h) => h.metadata.unit_id && h.metadata.block === "table")?.metadata.unit_id : void 0;
|
|
2821
|
+
const note = toolNarration(answer) ? TOOL_NARRATION_NOTICE : intentPreamble(answer) ? INTENT_PREAMBLE_NOTICE : retyped || unreferenced ? `Correction notice: your draft reproduced a table as markdown or presented a served table's data without its reference. Rewrite the answer: describe the table in prose, cite the clause, and write the reference token [[u:${tableUnitId ?? "<unit id>"}]] exactly where the table belongs. Do not render any table as markdown.` : ANCHOR_CORRECTION_NOTE;
|
|
2822
|
+
generateRetries += 1;
|
|
2823
|
+
const corrected = await generateOnce(env, model, [...messages, { role: "system", content: note }], routeEffort(routed.route));
|
|
2824
|
+
if (corrected) {
|
|
2825
|
+
const correctedAnswer = canonicalRefusal(corrected, refusalScope(answerCites(corrected)));
|
|
2826
|
+
const retryAnchors = checkQuoteAnchors(correctedAnswer, used.map((h) => h.text));
|
|
2827
|
+
const retryRetyped = tableRetyped(correctedAnswer, hasTableUnit);
|
|
2828
|
+
if (retryAnchors.violations.length < anchors.violations.length || !retryRetyped && retyped || unreferenced && correctedAnswer.includes("[[u:") || !toolNarration(correctedAnswer) || !intentPreamble(correctedAnswer)) {
|
|
2829
|
+
answer = correctedAnswer;
|
|
2830
|
+
}
|
|
2791
2831
|
}
|
|
2792
2832
|
}
|
|
2793
2833
|
}
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2834
|
+
if (answer && !answer.includes(refusalAnswer())) {
|
|
2835
|
+
const reflection = await reflect(env.AI, MODELS.grader, q2.query, answer, hits.map((h) => h.text));
|
|
2836
|
+
console.log("reflection:", reflection ? reflection.grounded ? "grounded" : "ungrounded" : "null");
|
|
2837
|
+
if (reflection && !reflection.grounded && reflection.missing_info) {
|
|
2838
|
+
const retryRetrieve = await retrieve(env, q2.query, {
|
|
2839
|
+
prev,
|
|
2840
|
+
understanding: { ...understanding, standalone_query: `${understanding?.standalone_query || q2.query} ${reflection.missing_info}` },
|
|
2841
|
+
sealScope: declaredScoped ? docScope : null,
|
|
2842
|
+
datasetScope: narrowed ? corpora : null,
|
|
2843
|
+
standardKeys,
|
|
2844
|
+
...routeSubset ? { stageSubset: routeSubset ?? void 0 } : {}
|
|
2845
|
+
});
|
|
2846
|
+
if (retryRetrieve.hits.length > 0) {
|
|
2847
|
+
const { messages: retryMessages, usedHits: retryUsed } = buildMessages(q2.query, retryRetrieve.hits, q2.lang, keptHistory, void 0, summary, budget);
|
|
2848
|
+
const retryAnswer = await generateOnce(env, model, retryMessages, routeEffort(routed.route));
|
|
2849
|
+
if (retryAnswer) {
|
|
2850
|
+
answer = canonicalRefusal(retryAnswer, refusalScope(answerCites(retryAnswer)));
|
|
2851
|
+
used = retryUsed;
|
|
2852
|
+
}
|
|
2813
2853
|
}
|
|
2814
2854
|
}
|
|
2815
2855
|
}
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
return err(502, "generation_failed", "The generation model is unavailable; please retry.");
|
|
2820
|
-
}
|
|
2821
|
-
const finalCites = boundModel ? [modelCitation(boundModel), ...citations(used)] : citations(used);
|
|
2822
|
-
const c2ns = answer.includes(refusalAnswer()) ? { text: answer, blocks: [], dropped: [] } : await contractV2(env.DB, answer, used);
|
|
2823
|
-
answer = c2ns.text;
|
|
2824
|
-
const finalAnchors = answer.includes(refusalAnswer()) ? { total: 0, violations: [] } : checkQuoteAnchors(answer, used.map((h) => h.text));
|
|
2825
|
-
if (finalAnchors.violations.length > 0) {
|
|
2826
|
-
console.log("anchors:", finalAnchors.violations.length, "of", finalAnchors.total, "unverified \u2014 not caching");
|
|
2827
|
-
}
|
|
2828
|
-
let completionBlocks = [];
|
|
2829
|
-
if (!answer.includes(refusalAnswer()) && !c2ns.blocks.some((b) => b.type === "table")) {
|
|
2830
|
-
completionBlocks = await completeTables(env.DB, answer, used);
|
|
2831
|
-
if (completionBlocks.length) console.log("contract completion:", completionBlocks.length, "table block(s) attached server-side");
|
|
2832
|
-
}
|
|
2833
|
-
completionBlocks.push(...await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used));
|
|
2834
|
-
if (withImage && register?.rows?.length && answer.includes(refusalAnswer())) {
|
|
2835
|
-
console.log("blind-answer: the register note carried rows but the answer refused \u2014 regenerating once");
|
|
2836
|
-
mark("Re-answering from the register results");
|
|
2837
|
-
const regen = await generateOnce(env, model, [
|
|
2838
|
-
...messages.slice(0, -1),
|
|
2839
|
-
{ role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
|
|
2840
|
-
messages[messages.length - 1]
|
|
2841
|
-
], effort);
|
|
2842
|
-
if (regen && !regen.includes(refusalAnswer())) {
|
|
2843
|
-
answer = canonicalRefusal(regen, refusalScope(answerCites(regen)));
|
|
2844
|
-
console.log("blind-answer: regeneration grounded");
|
|
2845
|
-
}
|
|
2846
|
-
}
|
|
2847
|
-
const jsonQuality = answerQuality(finalCites.map((c) => c.quality));
|
|
2848
|
-
let entailment = null;
|
|
2849
|
-
let entailmentNote = "";
|
|
2850
|
-
if (THRESHOLDS.entailmentGate && jsonQuality && used.length && !answer.includes(refusalAnswer())) {
|
|
2851
|
-
const raced = await Promise.race([
|
|
2852
|
-
scoreFaithfulness(env.AI, roleModel(env, "grader"), answer, used.map((h) => h.text)),
|
|
2853
|
-
new Promise((r) => setTimeout(() => r(null), THRESHOLDS.entailmentBudgetMs))
|
|
2854
|
-
]);
|
|
2855
|
-
if (raced) {
|
|
2856
|
-
const v = entailmentVerdict(raced.score, THRESHOLDS.entailmentSupportedFloor, THRESHOLDS.entailmentPartialFloor);
|
|
2857
|
-
entailment = { support: v.support, score: Math.round(raced.score * 100) / 100, ...raced.ungrounded_claims?.length ? { ungrounded: raced.ungrounded_claims.slice(0, 3) } : {} };
|
|
2858
|
-
entailmentNote = v.note;
|
|
2859
|
-
if (v.support !== "supported") console.log("entailment:", v.support, raced.score, raced.ungrounded_claims?.slice(0, 2));
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
const out = { answer, citations: finalCites, ...jsonQuality ? { source_quality: jsonQuality, confidence_note: entailmentNote || qualityNote(jsonQuality), ...entailment ? { entailment } : {}, ...jsonQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(finalCites) } : {} } : {}, model: MODELS.member, query_hash: queryHash, follow_ups: refusalShaped(answer, refusalScope(answerCites(answer))) ? [] : understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...registerBlock ? [registerBlock] : [], ...completionBlocks], context_applied: ctxApplied, ...liveRecords ? { records: liveRecords } : {}, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
|
|
2863
|
-
const cacheable = !contextual && !declaredCtx && !ablate && cacheableAnswer(answer, refusalScope(answerCites(answer))) && finalAnchors.violations.length === 0;
|
|
2864
|
-
if (cacheable) {
|
|
2865
|
-
const ck = exactCacheKey(env.INDEX_VERSION, gen, ns, await sha256Hex(cacheKeyMaterial(q.query, q.lang, salt)));
|
|
2866
|
-
ctx.waitUntil(env.CACHE.put(ck, JSON.stringify(out), { expirationTtl: LIMITS.cacheTtlSec }));
|
|
2867
|
-
}
|
|
2868
|
-
telemetry(env, ctx, tier, "ask", model, true, answer.length, queryHash, q.lang, void 0, telemetryMeta());
|
|
2869
|
-
const contextOut = used.map((h) => ({
|
|
2870
|
-
doc_id: h.metadata.doc_id,
|
|
2871
|
-
clause_anchor: h.metadata.clause_anchor,
|
|
2872
|
-
text: h.text.slice(0, 1200),
|
|
2873
|
-
...h.metadata.table_selection ? { sel: h.metadata.table_selection } : {}
|
|
2874
|
-
}));
|
|
2875
|
-
const tq = await chargeAnswerTokens(env, bucketId, void 0, messageChars(messages), answer.length, probeTokensUsed);
|
|
2876
|
-
return json({ ...out, context: contextOut, read: readAs(), quota: { ...quota, ...tq, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } }, 200, { ...corsHeaders(req), "server-timing": serverTiming() });
|
|
2877
|
-
}
|
|
2878
|
-
function sseResponse(events, cors) {
|
|
2879
|
-
const encoder = new TextEncoder();
|
|
2880
|
-
const body = events.map((e) => `data: ${JSON.stringify(e)}
|
|
2881
|
-
|
|
2882
|
-
`).join("");
|
|
2883
|
-
return new Response(encoder.encode(body), {
|
|
2884
|
-
headers: {
|
|
2885
|
-
"content-type": "text/event-stream",
|
|
2886
|
-
"cache-control": "no-cache",
|
|
2887
|
-
"x-accel-buffering": "no",
|
|
2888
|
-
...cors
|
|
2856
|
+
if (answer === null) {
|
|
2857
|
+
telemetry(env, ctx, tier, "ask", model, false, 0, queryHash, q2.lang, void 0, telemetryMeta());
|
|
2858
|
+
return err(502, "generation_failed", "The generation model is unavailable; please retry.");
|
|
2889
2859
|
}
|
|
2890
|
-
|
|
2860
|
+
const finalCites = boundModel ? [modelCitation(boundModel), ...citations(used)] : citations(used);
|
|
2861
|
+
const c2ns = answer.includes(refusalAnswer()) ? { text: answer, blocks: [], dropped: [] } : await contractV2(env.DB, answer, used);
|
|
2862
|
+
answer = c2ns.text;
|
|
2863
|
+
const finalAnchors = answer.includes(refusalAnswer()) ? { total: 0, violations: [] } : checkQuoteAnchors(answer, used.map((h) => h.text));
|
|
2864
|
+
if (finalAnchors.violations.length > 0) {
|
|
2865
|
+
console.log("anchors:", finalAnchors.violations.length, "of", finalAnchors.total, "unverified \u2014 not caching");
|
|
2866
|
+
}
|
|
2867
|
+
let completionBlocks = [];
|
|
2868
|
+
if (!answer.includes(refusalAnswer()) && !c2ns.blocks.some((b) => b.type === "table")) {
|
|
2869
|
+
completionBlocks = await completeTables(env.DB, answer, used);
|
|
2870
|
+
if (completionBlocks.length) console.log("contract completion:", completionBlocks.length, "table block(s) attached server-side");
|
|
2871
|
+
}
|
|
2872
|
+
completionBlocks.push(...await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used));
|
|
2873
|
+
if (withImage && register?.rows?.length && answer.includes(refusalAnswer())) {
|
|
2874
|
+
console.log("blind-answer: the register note carried rows but the answer refused \u2014 regenerating once");
|
|
2875
|
+
mark("Re-answering from the register results");
|
|
2876
|
+
const regen = await generateOnce(env, model, [
|
|
2877
|
+
...messages.slice(0, -1),
|
|
2878
|
+
{ role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
|
|
2879
|
+
messages[messages.length - 1]
|
|
2880
|
+
], effort);
|
|
2881
|
+
if (regen && !regen.includes(refusalAnswer())) {
|
|
2882
|
+
answer = canonicalRefusal(regen, refusalScope(answerCites(regen)));
|
|
2883
|
+
console.log("blind-answer: regeneration grounded");
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
const jsonQuality = answerQuality(finalCites.map((c) => c.quality));
|
|
2887
|
+
let entailment = null;
|
|
2888
|
+
let entailmentNote = "";
|
|
2889
|
+
if (THRESHOLDS.entailmentGate && jsonQuality && used.length && !answer.includes(refusalAnswer())) {
|
|
2890
|
+
const raced = await Promise.race([
|
|
2891
|
+
scoreFaithfulness(env.AI, roleModel(env, "grader"), answer, used.map((h) => h.text)),
|
|
2892
|
+
new Promise((r) => setTimeout(() => r(null), THRESHOLDS.entailmentBudgetMs))
|
|
2893
|
+
]);
|
|
2894
|
+
if (raced) {
|
|
2895
|
+
const v = entailmentVerdict(raced.score, THRESHOLDS.entailmentSupportedFloor, THRESHOLDS.entailmentPartialFloor);
|
|
2896
|
+
entailment = { support: v.support, score: Math.round(raced.score * 100) / 100, ...raced.ungrounded_claims?.length ? { ungrounded: raced.ungrounded_claims.slice(0, 3) } : {} };
|
|
2897
|
+
entailmentNote = v.note;
|
|
2898
|
+
if (v.support !== "supported") console.log("entailment:", v.support, raced.score, raced.ungrounded_claims?.slice(0, 2));
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
const out = { answer, citations: finalCites, ...jsonQuality ? { source_quality: jsonQuality, confidence_note: entailmentNote || qualityNote(jsonQuality), ...entailment ? { entailment } : {}, ...jsonQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(finalCites) } : {} } : {}, model: MODELS.member, query_hash: queryHash, follow_ups: refusalShaped(answer, refusalScope(answerCites(answer))) ? [] : understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...registerBlock ? [registerBlock] : [], ...completionBlocks], context_applied: ctxApplied, ...liveRecords ? { records: liveRecords } : {}, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
|
|
2902
|
+
const cacheable = !contextual && !declaredCtx && !ablate && cacheableAnswer(answer, refusalScope(answerCites(answer))) && finalAnchors.violations.length === 0;
|
|
2903
|
+
if (cacheable) {
|
|
2904
|
+
const ck = exactCacheKey(env.INDEX_VERSION, gen, ns, await sha256Hex(cacheKeyMaterial(q2.query, q2.lang, salt)));
|
|
2905
|
+
ctx.waitUntil(env.CACHE.put(ck, JSON.stringify(out), { expirationTtl: LIMITS.cacheTtlSec }));
|
|
2906
|
+
}
|
|
2907
|
+
telemetry(env, ctx, tier, "ask", model, true, answer.length, queryHash, q2.lang, void 0, telemetryMeta());
|
|
2908
|
+
const contextOut = used.map((h) => ({
|
|
2909
|
+
doc_id: h.metadata.doc_id,
|
|
2910
|
+
clause_anchor: h.metadata.clause_anchor,
|
|
2911
|
+
text: h.text.slice(0, 1200),
|
|
2912
|
+
...h.metadata.table_selection ? { sel: h.metadata.table_selection } : {}
|
|
2913
|
+
}));
|
|
2914
|
+
const tq = await chargeAnswerTokens(env, bucketId, void 0, messageChars(messages), answer.length, probeTokensUsed);
|
|
2915
|
+
return json({ ...out, context: contextOut, read: readAs(), quota: { ...quota, ...tq, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } }, 200, { ...corsHeaders(req), "server-timing": serverTiming() });
|
|
2916
|
+
};
|
|
2917
|
+
if (liveResponse) {
|
|
2918
|
+
void pipeline(live, q).catch(() => {
|
|
2919
|
+
try {
|
|
2920
|
+
live.close();
|
|
2921
|
+
} catch {
|
|
2922
|
+
}
|
|
2923
|
+
});
|
|
2924
|
+
return liveResponse;
|
|
2925
|
+
}
|
|
2926
|
+
return await pipeline(null, q);
|
|
2891
2927
|
}
|
|
2892
2928
|
|
|
2893
2929
|
export {
|