@konneal/engine 0.2.82 → 0.2.84
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-QLY2CODU.js → ask-GVU5PYC4.js} +2 -2
- package/dist/{certificates-YFL4K7O3.js → certificates-CO7KX2S2.js} +1 -1
- package/dist/{chunk-DH3WDTZX.js → chunk-D24PQPDK.js} +18 -3
- package/dist/{chunk-7AQM3GSO.js → chunk-JZFXSTYX.js} +7 -2
- package/dist/worker_public/src/index.js +3 -3
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +21 -3
- package/workers/worker_public/src/certificates.ts +8 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleAsk
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D24PQPDK.js";
|
|
4
4
|
import "./chunk-7HWJOFTQ.js";
|
|
5
5
|
import "./chunk-SPKPH54J.js";
|
|
6
6
|
import "./chunk-A3QHHUN5.js";
|
|
7
7
|
import "./chunk-LVZTWUVJ.js";
|
|
8
8
|
import "./chunk-2PCUAJJO.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-JZFXSTYX.js";
|
|
10
10
|
import "./chunk-3FYJM7LH.js";
|
|
11
11
|
export {
|
|
12
12
|
handleAsk
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
certificateLinks,
|
|
73
73
|
registerNote,
|
|
74
74
|
searchRegister
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-JZFXSTYX.js";
|
|
76
76
|
import {
|
|
77
77
|
P
|
|
78
78
|
} from "./chunk-3FYJM7LH.js";
|
|
@@ -1896,7 +1896,7 @@ async function runTool(db, call) {
|
|
|
1896
1896
|
if (call.name !== "register_search") return null;
|
|
1897
1897
|
const query = String(call.args?.query ?? "").trim().slice(0, 160);
|
|
1898
1898
|
if (!query) return null;
|
|
1899
|
-
const { searchRegister: searchRegister2, registerNote: registerNote2 } = await import("./certificates-
|
|
1899
|
+
const { searchRegister: searchRegister2, registerNote: registerNote2 } = await import("./certificates-CO7KX2S2.js");
|
|
1900
1900
|
const reg = await searchRegister2(db, query, true);
|
|
1901
1901
|
const output = reg?.rows?.length ? registerNote2(reg.rows) : `No certificate was found for "${query}" in the certificates database (the register snapshot). State this as the search's result, with the searched string visible.`;
|
|
1902
1902
|
return { name: call.name, query, output };
|
|
@@ -2310,6 +2310,11 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
2310
2310
|
if (await env.CACHE.get("sys:generation") === "off") {
|
|
2311
2311
|
return err(503, "generation_disabled", "Generation is temporarily paused; search remains available.");
|
|
2312
2312
|
}
|
|
2313
|
+
const agentSteps = [];
|
|
2314
|
+
const mark = (step) => {
|
|
2315
|
+
agentSteps.push(step);
|
|
2316
|
+
console.log(`agent-step: ${step}`);
|
|
2317
|
+
};
|
|
2313
2318
|
const service = env.INTERNAL_SERVICE;
|
|
2314
2319
|
const fedAuth = {
|
|
2315
2320
|
cookie: req.headers.get("cookie") ?? "",
|
|
@@ -2488,6 +2493,7 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
2488
2493
|
let register = await searchRegister(env.DB, q.query);
|
|
2489
2494
|
const bridgeImage = userImage ?? storedImage;
|
|
2490
2495
|
if (bridgeImage && /certificate|certified|certification/i.test(q.query)) {
|
|
2496
|
+
mark("Reading the nameplate photograph");
|
|
2491
2497
|
const np = await extractNameplate(env.AI, MODELS.member, bridgeImage);
|
|
2492
2498
|
if (np?.manufacturer) {
|
|
2493
2499
|
const bridged = await searchRegister(env.DB, nameplateRegisterQuery(np, q.query), true);
|
|
@@ -2878,9 +2884,10 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2878
2884
|
if (/certificate|certified|certification/i.test(q.query) && env.DB) {
|
|
2879
2885
|
try {
|
|
2880
2886
|
const imageTurn = typeof withImage === "string";
|
|
2887
|
+
if (imageTurn) mark("Reading the photograph to identify the instrument");
|
|
2881
2888
|
const probeMessages = [...messages.slice(0, -1), { role: "user", content: `${TOOL_DECLARATION}
|
|
2882
2889
|
|
|
2883
|
-
${imageTurn ? "A photograph of the instrument is attached after this message. Transcribe the maker, model and any printed certificate number you can read, then emit the TOOL line with those tokens as the query \u2014 never invented." : ""}
|
|
2890
|
+
${imageTurn ? "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)." : ""}
|
|
2884
2891
|
|
|
2885
2892
|
${q.query}`.replace("\n\n\n\n", "\n\n") }];
|
|
2886
2893
|
if (imageTurn) probeMessages.push({ role: "user", content: [{ type: "image_url", image_url: { url: withImage } }] });
|
|
@@ -2892,6 +2899,7 @@ ${q.query}`.replace("\n\n\n\n", "\n\n") }];
|
|
|
2892
2899
|
const probeText = typeof probe?.response === "string" ? probe.response : probe?.choices?.[0]?.message?.content ?? "";
|
|
2893
2900
|
const call = parseToolCall(probeText);
|
|
2894
2901
|
if (call) {
|
|
2902
|
+
mark(`Searching the certificate register for \u201C${String(call.args?.query ?? "")}\u201D`);
|
|
2895
2903
|
const result = await runTool(env.DB, call);
|
|
2896
2904
|
if (result) {
|
|
2897
2905
|
messages.push({ role: "system", content: toolNote(result) });
|
|
@@ -2926,6 +2934,12 @@ ${q.query}`.replace("\n\n\n\n", "\n\n") }];
|
|
|
2926
2934
|
const send = (obj) => controller.enqueue(encoder.encode(`data: ${JSON.stringify(obj)}
|
|
2927
2935
|
|
|
2928
2936
|
`));
|
|
2937
|
+
for (const step of agentSteps) {
|
|
2938
|
+
try {
|
|
2939
|
+
send({ type: "agent", step });
|
|
2940
|
+
} catch {
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2929
2943
|
for (const t of pendingTools) {
|
|
2930
2944
|
try {
|
|
2931
2945
|
send({ type: "tool", name: t.name, query: t.query });
|
|
@@ -3085,6 +3099,7 @@ ${q.query}`.replace("\n\n\n\n", "\n\n") }];
|
|
|
3085
3099
|
completionBlocks.push(...await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used));
|
|
3086
3100
|
if (withImage && register?.rows?.length && answer.includes(refusalAnswer())) {
|
|
3087
3101
|
console.log("blind-answer: the register note carried rows but the answer refused \u2014 regenerating once");
|
|
3102
|
+
mark("Re-answering from the register results");
|
|
3088
3103
|
const regen = await generateOnce(env, model, [
|
|
3089
3104
|
...messages.slice(0, -1),
|
|
3090
3105
|
{ 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." },
|
|
@@ -139,8 +139,13 @@ function registerNote(rows) {
|
|
|
139
139
|
}
|
|
140
140
|
function certificateLinks(rows) {
|
|
141
141
|
const links = rows.filter((r) => r.pdf_key).map((r) => `- ${r.num}: https://www.oimlsmart.org/cert-pdf/${r.pdf_key}`);
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
const absent = rows.filter((r) => !r.pdf_key && r.num).slice(0, 6).map((r) => `- ${r.num}: no document on file in this snapshot`);
|
|
143
|
+
const parts = [];
|
|
144
|
+
if (links.length) parts.push(`Documents on file:
|
|
145
|
+
${links.join("\n")}`);
|
|
146
|
+
if (absent.length) parts.push(`No document on file (do NOT construct a link for these):
|
|
147
|
+
${absent.join("\n")}`);
|
|
148
|
+
return parts.join("\n");
|
|
144
149
|
}
|
|
145
150
|
|
|
146
151
|
export {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
modelGroundingBlock,
|
|
7
7
|
scoreFaithfulness,
|
|
8
8
|
scoreJudge
|
|
9
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-D24PQPDK.js";
|
|
10
10
|
import {
|
|
11
11
|
handleSearch
|
|
12
12
|
} from "../../chunk-KO6DRI7C.js";
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
sha256Hex,
|
|
64
64
|
today
|
|
65
65
|
} from "../../chunk-2PCUAJJO.js";
|
|
66
|
-
import "../../chunk-
|
|
66
|
+
import "../../chunk-JZFXSTYX.js";
|
|
67
67
|
import {
|
|
68
68
|
P,
|
|
69
69
|
setProfile
|
|
@@ -959,7 +959,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
959
959
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
960
960
|
body: JSON.stringify({ ...args, stream: false })
|
|
961
961
|
});
|
|
962
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
962
|
+
const res = name === "ask" ? await (await import("../../ask-GVU5PYC4.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-LVUQLA3C.js")).handleSearch(env, ctx, inner, tier, key);
|
|
963
963
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
964
964
|
});
|
|
965
965
|
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"playwright": "^1.62.1",
|
|
28
28
|
"yaml": "^2.9.1"
|
|
29
29
|
},
|
|
30
|
-
"version": "0.2.
|
|
30
|
+
"version": "0.2.84",
|
|
31
31
|
"description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
|
|
32
32
|
"license": "BSD-3-Clause",
|
|
33
33
|
"type": "module",
|
|
@@ -364,6 +364,16 @@ async function handleAsk(
|
|
|
364
364
|
return err(503, "generation_disabled", "Generation is temporarily paused; search remains available.");
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
// the agent's rounds, visible to the user as they happen: each step the
|
|
368
|
+
// assistant takes before and during the answer streams as an event (the
|
|
369
|
+
// owner's 2026-10-04 direction — the user must see the system-to-model
|
|
370
|
+
// questioning sessions, not stare at a spinner)
|
|
371
|
+
const agentSteps: string[] = [];
|
|
372
|
+
const mark = (step: string) => {
|
|
373
|
+
agentSteps.push(step);
|
|
374
|
+
console.log(`agent-step: ${step}`);
|
|
375
|
+
};
|
|
376
|
+
|
|
367
377
|
// Members get federated retrieval (OIML + ISO/IEC) merged into the same
|
|
368
378
|
// pipeline via the service binding; rag-public never touches the
|
|
369
379
|
// internal index itself, and generation/rerank stay in ONE pipeline.
|
|
@@ -666,6 +676,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
666
676
|
// holder, and the photograph's own reading is authoritative over them.
|
|
667
677
|
const bridgeImage = userImage ?? storedImage;
|
|
668
678
|
if (bridgeImage && /certificate|certified|certification/i.test(q.query)) {
|
|
679
|
+
mark("Reading the nameplate photograph");
|
|
669
680
|
const np = await extractNameplate((env as any).AI, MODELS.member, bridgeImage);
|
|
670
681
|
if (np?.manufacturer) {
|
|
671
682
|
const bridged = await searchRegister(env.DB, nameplateRegisterQuery(np, q.query), true);
|
|
@@ -1230,7 +1241,8 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1230
1241
|
if (/certificate|certified|certification/i.test(q.query) && env.DB) {
|
|
1231
1242
|
try {
|
|
1232
1243
|
const imageTurn = typeof withImage === "string";
|
|
1233
|
-
|
|
1244
|
+
if (imageTurn) mark("Reading the photograph to identify the instrument");
|
|
1245
|
+
const probeMessages: any[] = [...messages.slice(0, -1), { role: "user", content: `${TOOL_DECLARATION}\n\n${imageTurn ? "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 — 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)." : ""}\n\n${q.query}`.replace("\n\n\n\n", "\n\n") }];
|
|
1234
1246
|
if (imageTurn) probeMessages.push({ role: "user", content: [{ type: "image_url", image_url: { url: withImage } }] });
|
|
1235
1247
|
const probe = await (env as any).AI.run(model, {
|
|
1236
1248
|
messages: probeMessages,
|
|
@@ -1240,6 +1252,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1240
1252
|
const probeText = typeof probe?.response === "string" ? probe.response : probe?.choices?.[0]?.message?.content ?? "";
|
|
1241
1253
|
const call = parseToolCall(probeText);
|
|
1242
1254
|
if (call) {
|
|
1255
|
+
mark(`Searching the certificate register for “${String(call.args?.query ?? "")}”`);
|
|
1243
1256
|
const result = await runTool(env.DB, call);
|
|
1244
1257
|
if (result) {
|
|
1245
1258
|
messages.push({ role: "system", content: toolNote(result) });
|
|
@@ -1292,8 +1305,12 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1292
1305
|
const sse = new ReadableStream({
|
|
1293
1306
|
async start(controller) {
|
|
1294
1307
|
const send = (obj: unknown) => controller.enqueue(encoder.encode(`data: ${JSON.stringify(obj)}\n\n`));
|
|
1295
|
-
// the
|
|
1296
|
-
//
|
|
1308
|
+
// the agent trace arrives first: every questioning round the
|
|
1309
|
+
// assistant ran — the photograph read, the register search, any
|
|
1310
|
+
// re-answer — so the user watched what happened, not a spinner
|
|
1311
|
+
for (const step of agentSteps) {
|
|
1312
|
+
try { send({ type: "agent", step }); } catch { /* never block the answer */ }
|
|
1313
|
+
}
|
|
1297
1314
|
for (const t of pendingTools) {
|
|
1298
1315
|
try { send({ type: "tool", name: t.name, query: t.query }); } catch { /* never block the answer */ }
|
|
1299
1316
|
}
|
|
@@ -1522,6 +1539,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1522
1539
|
// that exact signature; the retry carries a sterner ground instruction.
|
|
1523
1540
|
if (withImage && register?.rows?.length && answer.includes(refusalAnswer())) {
|
|
1524
1541
|
console.log("blind-answer: the register note carried rows but the answer refused — regenerating once");
|
|
1542
|
+
mark("Re-answering from the register results");
|
|
1525
1543
|
const regen = await generateOnce(env, model, [
|
|
1526
1544
|
...messages.slice(0, -1),
|
|
1527
1545
|
{ role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows — number, holder, model, status, and every document link — as the answer. Do not claim that nothing was provided." },
|
|
@@ -163,6 +163,13 @@ export function registerNote(rows: RegisterRow[]): string {
|
|
|
163
163
|
* the fact. */
|
|
164
164
|
export function certificateLinks(rows: RegisterRow[]): string {
|
|
165
165
|
const links = rows.filter((r) => r.pdf_key).map((r) => `- ${r.num}: https://www.oimlsmart.org/cert-pdf/${r.pdf_key}`);
|
|
166
|
-
|
|
166
|
+
// absence is stated per row: an unmarked gap invited the model to
|
|
167
|
+
// generalize the URL pattern to a document-less row (a fabricated 404
|
|
168
|
+
// link, observed live 2026-10-04)
|
|
169
|
+
const absent = rows.filter((r) => !r.pdf_key && r.num).slice(0, 6).map((r) => `- ${r.num}: no document on file in this snapshot`);
|
|
170
|
+
const parts: string[] = [];
|
|
171
|
+
if (links.length) parts.push(`Documents on file:\n${links.join("\n")}`);
|
|
172
|
+
if (absent.length) parts.push(`No document on file (do NOT construct a link for these):\n${absent.join("\n")}`);
|
|
173
|
+
return parts.join("\n");
|
|
167
174
|
}
|
|
168
175
|
|