@konneal/engine 0.2.92 → 0.2.94
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-UG5UYRJV.js → ask-HCKUKBPB.js} +2 -2
- package/dist/{chunk-EHABW23I.js → chunk-2JC7GXRV.js} +1 -1
- package/dist/{chunk-QBWZ6HVP.js → chunk-64IG3ZLT.js} +72 -5
- package/dist/{tools-PI7IXAL4.js → tools-O7OGW54R.js} +1 -1
- package/dist/tools-content.d.ts +1 -0
- package/dist/worker_public/src/index.js +4 -4
- package/package.json +1 -1
- package/workers/worker_public/src/tools-content.ts +95 -6
- package/workers/worker_public/src/tools.ts +2 -2
|
@@ -754,17 +754,17 @@ var verdictEvaluate = {
|
|
|
754
754
|
description: "Deterministically evaluate a model-plane node's machine checks (OCL boolean expressions, threshold limits) against the quantities a question states. Returns pass/fail with every check's expression and values, or void with the missing parameter names when the question does not state enough. The machine computes; cite the node's clause.",
|
|
755
755
|
params: [
|
|
756
756
|
{ key: "node_id", required: true, description: "the model-plane node id, e.g. /req/metrological/repeatability (node ids appear in answers' verdict blocks)" },
|
|
757
|
-
{ key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" }
|
|
757
|
+
{ key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" },
|
|
758
|
+
{ key: "standard", required: false, description: "the package id when the node id indexes under several standards, as the ambiguity message names it" }
|
|
758
759
|
],
|
|
759
760
|
audiences: ["mcp"],
|
|
760
761
|
handler: async (env, args) => {
|
|
761
762
|
const node_id = String(args?.node_id ?? "").trim();
|
|
762
763
|
const question = String(args?.question ?? "").trim();
|
|
764
|
+
const standard = args?.standard ? String(args.standard).trim() : null;
|
|
763
765
|
if (!node_id.startsWith("/") || question.length < 4) return null;
|
|
764
766
|
try {
|
|
765
|
-
const rows = await env.DB.prepare(
|
|
766
|
-
"SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2"
|
|
767
|
-
).bind(node_id).all();
|
|
767
|
+
const rows = standard ? await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 AND standard = ?2 LIMIT 2").bind(node_id, standard).all() : await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(node_id).all();
|
|
768
768
|
const found = rows.results ?? [];
|
|
769
769
|
if (found.length !== 1) {
|
|
770
770
|
return {
|
|
@@ -851,6 +851,73 @@ var conditionsCheck = {
|
|
|
851
851
|
}
|
|
852
852
|
}
|
|
853
853
|
};
|
|
854
|
+
var bibEntry = {
|
|
855
|
+
name: "bib.entry",
|
|
856
|
+
description: "Fetch the bibliographic registry record for a citation label: every edition document under it with derived status (in-force/superseded, the ACTIVE flag), the relation edges (successor, amends, variant), and its outgoing citations. Use after graph.cites to resolve a cited label to its own record.",
|
|
857
|
+
params: [
|
|
858
|
+
{ key: "label", required: true, description: "the citation label exactly as graph.cites returns it, e.g. ISO 8601" }
|
|
859
|
+
],
|
|
860
|
+
audiences: ["mcp"],
|
|
861
|
+
handler: async (env, args) => {
|
|
862
|
+
const label = String(args?.label ?? "").trim();
|
|
863
|
+
if (label.length < 2) return null;
|
|
864
|
+
try {
|
|
865
|
+
const rows = await env.DB.prepare(
|
|
866
|
+
"SELECT id, kind, label FROM graph_nodes WHERE label = ?1 COLLATE NOCASE LIMIT 5"
|
|
867
|
+
).bind(label).all();
|
|
868
|
+
let nodes = rows.results ?? [];
|
|
869
|
+
if (!nodes.length) {
|
|
870
|
+
const d = await env.DB.prepare(
|
|
871
|
+
"SELECT canonical_id, docidentifier FROM documents WHERE docidentifier = ?1 COLLATE NOCASE LIMIT 5"
|
|
872
|
+
).bind(label).all();
|
|
873
|
+
nodes = (d.results ?? []).map((r) => ({
|
|
874
|
+
id: r.canonical_id,
|
|
875
|
+
kind: "doc",
|
|
876
|
+
label: r.docidentifier
|
|
877
|
+
}));
|
|
878
|
+
}
|
|
879
|
+
if (!nodes.length) {
|
|
880
|
+
return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
|
|
881
|
+
}
|
|
882
|
+
const out = [];
|
|
883
|
+
for (const n of nodes) {
|
|
884
|
+
const entry = { label: n.label, kind: n.kind };
|
|
885
|
+
if (n.kind === "doc") {
|
|
886
|
+
const d = await env.DB.prepare(
|
|
887
|
+
"SELECT docidentifier, family, part, edition, derived_status, active, superseded_by, title FROM documents WHERE canonical_id = ?1"
|
|
888
|
+
).bind(n.id).all();
|
|
889
|
+
const doc = (d.results ?? [])[0];
|
|
890
|
+
if (doc) {
|
|
891
|
+
entry.document = {
|
|
892
|
+
docidentifier: doc.docidentifier,
|
|
893
|
+
family: doc.family,
|
|
894
|
+
part: doc.part,
|
|
895
|
+
edition: doc.edition,
|
|
896
|
+
status: doc.derived_status,
|
|
897
|
+
active: !!doc.active,
|
|
898
|
+
superseded_by: doc.superseded_by,
|
|
899
|
+
title: doc.title
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
const rel = await env.DB.prepare(
|
|
904
|
+
"SELECT e.kind, n.label AS target FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 LIMIT 25"
|
|
905
|
+
).bind(n.id).all();
|
|
906
|
+
const relations = rel.results ?? [];
|
|
907
|
+
if (relations.length) entry.relations = relations;
|
|
908
|
+
const cites = await env.DB.prepare(
|
|
909
|
+
"SELECT n.label AS cited FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 AND e.kind = 'cites' LIMIT 40"
|
|
910
|
+
).bind(n.id).all();
|
|
911
|
+
const cited = (cites.results ?? []).map((r) => r.cited).filter(Boolean);
|
|
912
|
+
if (cited.length) entry.cites = cited;
|
|
913
|
+
out.push(entry);
|
|
914
|
+
}
|
|
915
|
+
return { name: "bib.entry", query: label, output: JSON.stringify(out) };
|
|
916
|
+
} catch {
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
};
|
|
854
921
|
var glossaryLookup = {
|
|
855
922
|
name: "glossary.lookup",
|
|
856
923
|
description: "Look up a defined term in the terminology datasets \u2014 the concept's definition and its defining publication. Bind everyday words to the defined term before interpreting a question.",
|
|
@@ -919,7 +986,7 @@ var certificatesSearch = {
|
|
|
919
986
|
return { name: "certificates.search", query, output };
|
|
920
987
|
}
|
|
921
988
|
};
|
|
922
|
-
var TOOLS_REGISTRY = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck];
|
|
989
|
+
var TOOLS_REGISTRY = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry];
|
|
923
990
|
var TOOL_DECLARATION = [
|
|
924
991
|
"You may use one tool before answering, by writing a single line:",
|
|
925
992
|
...TOOLS_REGISTRY.filter((t) => t.audiences.includes("agent")).map((t) => {
|
package/dist/tools-content.d.ts
CHANGED
|
@@ -6,4 +6,5 @@ export declare const documentsFamily: ToolSpec;
|
|
|
6
6
|
export declare const licensedSection: ToolSpec;
|
|
7
7
|
export declare const verdictEvaluate: ToolSpec;
|
|
8
8
|
export declare const conditionsCheck: ToolSpec;
|
|
9
|
+
export declare const bibEntry: ToolSpec;
|
|
9
10
|
export declare const glossaryLookup: ToolSpec;
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
handleMemories,
|
|
5
5
|
scoreFaithfulness,
|
|
6
6
|
scoreJudge
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-2JC7GXRV.js";
|
|
8
8
|
import {
|
|
9
9
|
TOOLS_REGISTRY,
|
|
10
10
|
bindModelNode,
|
|
11
11
|
modelGroundingBlock
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-64IG3ZLT.js";
|
|
13
13
|
import {
|
|
14
14
|
handleSearch
|
|
15
15
|
} from "../../chunk-TJTEBS4S.js";
|
|
@@ -973,12 +973,12 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
973
973
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
974
974
|
body: JSON.stringify({ ...args, stream: false })
|
|
975
975
|
});
|
|
976
|
-
const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-
|
|
976
|
+
const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-O7OGW54R.js");
|
|
977
977
|
if (TOOLS_REGISTRY2.some((t) => t.name === name && t.audiences.includes("mcp"))) {
|
|
978
978
|
const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
|
|
979
979
|
return r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
|
|
980
980
|
}
|
|
981
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
981
|
+
const res = name === "ask" ? await (await import("../../ask-HCKUKBPB.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-G76DK4AF.js")).handleSearch(env, ctx, inner, tier, key);
|
|
982
982
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
983
983
|
});
|
|
984
984
|
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.94",
|
|
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",
|
|
@@ -236,21 +236,22 @@ export const verdictEvaluate: ToolSpec = {
|
|
|
236
236
|
params: [
|
|
237
237
|
{ key: "node_id", required: true, description: "the model-plane node id, e.g. /req/metrological/repeatability (node ids appear in answers' verdict blocks)" },
|
|
238
238
|
{ key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" },
|
|
239
|
+
{ key: "standard", required: false, description: "the package id when the node id indexes under several standards, as the ambiguity message names it" },
|
|
239
240
|
],
|
|
240
241
|
audiences: ["mcp"],
|
|
241
242
|
handler: async (env, args) => {
|
|
242
243
|
const node_id = String(args?.node_id ?? "").trim();
|
|
243
244
|
const question = String(args?.question ?? "").trim();
|
|
245
|
+
const standard = args?.standard ? String(args.standard).trim() : null;
|
|
244
246
|
if (!node_id.startsWith("/") || question.length < 4) return null;
|
|
245
247
|
try {
|
|
246
248
|
// the same zero-or-ambiguous rule bindModelNode applies: a node
|
|
247
249
|
// id that indexes under exactly one standard resolves; several
|
|
248
|
-
// or none resolve to nothing — no silent pick
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
.bind(node_id)
|
|
253
|
-
.all();
|
|
250
|
+
// or none resolve to nothing — no silent pick (the standard
|
|
251
|
+
// param is the caller's disambiguator)
|
|
252
|
+
const rows = standard
|
|
253
|
+
? await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 AND standard = ?2 LIMIT 2").bind(node_id, standard).all()
|
|
254
|
+
: await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(node_id).all();
|
|
254
255
|
const found = (rows.results ?? []) as { standard: string; kind: string; name: string | null; content: string }[];
|
|
255
256
|
if (found.length !== 1) {
|
|
256
257
|
return {
|
|
@@ -339,6 +340,94 @@ export const conditionsCheck: ToolSpec = {
|
|
|
339
340
|
},
|
|
340
341
|
};
|
|
341
342
|
|
|
343
|
+
|
|
344
|
+
// The bibliography record (the owner's 2026-10-04 direction): the full
|
|
345
|
+
// registry entry for one citation label — what documents exist under
|
|
346
|
+
// it, their derived status, the successor/amends/variant edges, and
|
|
347
|
+
// what it cites and is cited by. graph.cites names the labels; this is
|
|
348
|
+
// the record behind the label, for agents that cite properly.
|
|
349
|
+
export const bibEntry: ToolSpec = {
|
|
350
|
+
name: "bib.entry",
|
|
351
|
+
description:
|
|
352
|
+
"Fetch the bibliographic registry record for a citation label: every edition document under it with derived status (in-force/superseded, the ACTIVE flag), the relation edges (successor, amends, variant), and its outgoing citations. Use after graph.cites to resolve a cited label to its own record.",
|
|
353
|
+
params: [
|
|
354
|
+
{ key: "label", required: true, description: "the citation label exactly as graph.cites returns it, e.g. ISO 8601" },
|
|
355
|
+
],
|
|
356
|
+
audiences: ["mcp"],
|
|
357
|
+
handler: async (env, args) => {
|
|
358
|
+
const label = String(args?.label ?? "").trim();
|
|
359
|
+
if (label.length < 2) return null;
|
|
360
|
+
try {
|
|
361
|
+
const rows = await env.DB.prepare(
|
|
362
|
+
"SELECT id, kind, label FROM graph_nodes WHERE label = ?1 COLLATE NOCASE LIMIT 5",
|
|
363
|
+
)
|
|
364
|
+
.bind(label)
|
|
365
|
+
.all();
|
|
366
|
+
let nodes = ((rows.results ?? []) as { id: string; kind: string; label: string }[]);
|
|
367
|
+
if (!nodes.length) {
|
|
368
|
+
// the docidentifier form ("OIML R 60:2017") is a documents-
|
|
369
|
+
// registry key, not a graph label (labels are titles) — resolve
|
|
370
|
+
// it through the registry and synthesize the node rows
|
|
371
|
+
const d = await env.DB.prepare(
|
|
372
|
+
"SELECT canonical_id, docidentifier FROM documents WHERE docidentifier = ?1 COLLATE NOCASE LIMIT 5",
|
|
373
|
+
)
|
|
374
|
+
.bind(label)
|
|
375
|
+
.all();
|
|
376
|
+
nodes = ((d.results ?? []) as { canonical_id: string; docidentifier: string }[]).map((r) => ({
|
|
377
|
+
id: r.canonical_id,
|
|
378
|
+
kind: "doc",
|
|
379
|
+
label: r.docidentifier,
|
|
380
|
+
}));
|
|
381
|
+
}
|
|
382
|
+
if (!nodes.length) {
|
|
383
|
+
return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
|
|
384
|
+
}
|
|
385
|
+
const out: unknown[] = [];
|
|
386
|
+
for (const n of nodes) {
|
|
387
|
+
const entry: Record<string, unknown> = { label: n.label, kind: n.kind };
|
|
388
|
+
if (n.kind === "doc") {
|
|
389
|
+
const d = await env.DB.prepare(
|
|
390
|
+
"SELECT docidentifier, family, part, edition, derived_status, active, superseded_by, title FROM documents WHERE canonical_id = ?1",
|
|
391
|
+
)
|
|
392
|
+
.bind(n.id)
|
|
393
|
+
.all();
|
|
394
|
+
const doc = (d.results ?? [])[0] as Record<string, unknown> | undefined;
|
|
395
|
+
if (doc) {
|
|
396
|
+
entry.document = {
|
|
397
|
+
docidentifier: doc.docidentifier,
|
|
398
|
+
family: doc.family,
|
|
399
|
+
part: doc.part,
|
|
400
|
+
edition: doc.edition,
|
|
401
|
+
status: doc.derived_status,
|
|
402
|
+
active: !!doc.active,
|
|
403
|
+
superseded_by: doc.superseded_by,
|
|
404
|
+
title: doc.title,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const rel = await env.DB.prepare(
|
|
409
|
+
"SELECT e.kind, n.label AS target FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 LIMIT 25",
|
|
410
|
+
)
|
|
411
|
+
.bind(n.id)
|
|
412
|
+
.all();
|
|
413
|
+
const relations = ((rel.results ?? []) as { kind: string; target: string }[]);
|
|
414
|
+
if (relations.length) entry.relations = relations;
|
|
415
|
+
const cites = await env.DB.prepare(
|
|
416
|
+
"SELECT n.label AS cited FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 AND e.kind = 'cites' LIMIT 40",
|
|
417
|
+
)
|
|
418
|
+
.bind(n.id)
|
|
419
|
+
.all();
|
|
420
|
+
const cited = ((cites.results ?? []) as { cited: string }[]).map((r) => r.cited).filter(Boolean);
|
|
421
|
+
if (cited.length) entry.cites = cited;
|
|
422
|
+
out.push(entry);
|
|
423
|
+
}
|
|
424
|
+
return { name: "bib.entry", query: label, output: JSON.stringify(out) };
|
|
425
|
+
} catch {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
|
|
342
431
|
export const glossaryLookup: ToolSpec = {
|
|
343
432
|
name: "glossary.lookup",
|
|
344
433
|
description:
|
|
@@ -64,9 +64,9 @@ const certificatesSearch: ToolSpec = {
|
|
|
64
64
|
},
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
import { unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck } from "./tools-content.ts";
|
|
67
|
+
import { unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry } from "./tools-content.ts";
|
|
68
68
|
|
|
69
|
-
export const TOOLS_REGISTRY: ToolSpec[] = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck];
|
|
69
|
+
export const TOOLS_REGISTRY: ToolSpec[] = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry];
|
|
70
70
|
|
|
71
71
|
/** The agent loop's protocol declaration, GENERATED from the registry —
|
|
72
72
|
* the model's tool vocabulary is always the registry's, never a
|