@konneal/engine 0.2.138 → 0.2.140
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-UL5NL5O7.js → ask-YVGMSXVO.js} +1 -1
- package/dist/{chunk-4GNKOTIK.js → chunk-KAHL4SZU.js} +2 -2
- package/dist/mcp-proto.d.ts +1 -1
- package/dist/worker_public/src/index.js +47 -43
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +2 -2
- package/workers/worker_public/src/mcp-proto.ts +21 -9
|
@@ -2633,7 +2633,7 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2633
2633
|
}
|
|
2634
2634
|
}
|
|
2635
2635
|
}
|
|
2636
|
-
const canonical0 =
|
|
2636
|
+
const canonical0 = exciseMisplacedPin(canonicalRefusal(full, refusalScope(answerCites(full))), answerCites(full));
|
|
2637
2637
|
const c2 = canonical0.includes(refusalAnswer()) ? { text: canonical0, blocks: [], dropped: [] } : await contractV2(env.DB, canonical0, usedHits);
|
|
2638
2638
|
send({
|
|
2639
2639
|
type: "done",
|
|
@@ -2718,7 +2718,7 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2718
2718
|
answer = await generateOnce(env, MODELS.fallback, flat, routeEffort(routed.route));
|
|
2719
2719
|
}
|
|
2720
2720
|
if (answer) answer = canonicalRefusal(answer, refusalScope(answerCites(answer)));
|
|
2721
|
-
if (answer
|
|
2721
|
+
if (answer) answer = exciseMisplacedPin(answer, answerCites(answer));
|
|
2722
2722
|
stageTiming.generate = Date.now() - tGen;
|
|
2723
2723
|
let used = usedHits;
|
|
2724
2724
|
if (answer && !answer.includes(refusalAnswer())) {
|
package/dist/mcp-proto.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleMemories,
|
|
5
5
|
scoreFaithfulness,
|
|
6
6
|
scoreJudge
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-KAHL4SZU.js";
|
|
8
8
|
import "../../chunk-GBGRHXRU.js";
|
|
9
9
|
import {
|
|
10
10
|
TOOLS_REGISTRY,
|
|
@@ -962,19 +962,21 @@ async function deleteAttachment(deps, sub, id) {
|
|
|
962
962
|
// workers/worker_public/src/mcp-proto.ts
|
|
963
963
|
var PROTOCOL_VERSION = "2025-06-18";
|
|
964
964
|
var mcpPrefix = () => `${P().publisher.id}_`;
|
|
965
|
-
var
|
|
965
|
+
var mcpOverrides = () => ({
|
|
966
966
|
retrieve: `${P().publisher.id}_search`,
|
|
967
967
|
// the published retrieval contract
|
|
968
968
|
"documents.family": `${P().publisher.id}_documents`
|
|
969
969
|
// the published registry contract
|
|
970
|
-
};
|
|
970
|
+
});
|
|
971
971
|
function mcpName(registryName2) {
|
|
972
|
-
|
|
972
|
+
const overrides = mcpOverrides();
|
|
973
|
+
return overrides[registryName2] ?? `${mcpPrefix()}${registryName2.replace(/\./g, "_")}`;
|
|
973
974
|
}
|
|
974
975
|
function registryName(presented) {
|
|
975
976
|
const pid = P().publisher.id;
|
|
976
977
|
if (presented === `${pid}_ask`) return "ask";
|
|
977
|
-
|
|
978
|
+
const overrides = mcpOverrides();
|
|
979
|
+
for (const [reg, mc] of Object.entries(overrides)) if (mc === presented) return reg;
|
|
978
980
|
if (presented.startsWith(`${pid}_`)) {
|
|
979
981
|
const rest = presented.slice(pid.length + 1);
|
|
980
982
|
const hit = TOOLS_REGISTRY.find((t) => t.audiences.includes("mcp") && t.name.replace(/\./g, "_") === rest);
|
|
@@ -982,41 +984,43 @@ function registryName(presented) {
|
|
|
982
984
|
}
|
|
983
985
|
return presented;
|
|
984
986
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
987
|
+
function buildTools() {
|
|
988
|
+
return [
|
|
989
|
+
{
|
|
990
|
+
name: mcpName("ask"),
|
|
991
|
+
description: "Ask the corpus a question; returns a citation-grounded answer with the passages it rests on.",
|
|
992
|
+
inputSchema: {
|
|
993
|
+
type: "object",
|
|
994
|
+
properties: {
|
|
995
|
+
query: { type: "string", description: "The question (1-8000 chars)" },
|
|
996
|
+
lang: { type: "string", description: "Answer language hint (e.g. en, fr)" }
|
|
997
|
+
},
|
|
998
|
+
required: ["query"]
|
|
999
|
+
}
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
name: mcpName("retrieve"),
|
|
1003
|
+
description: "Retrieve the top passages for a query (hybrid dense + metadata steering, reranked).",
|
|
1004
|
+
inputSchema: {
|
|
1005
|
+
type: "object",
|
|
1006
|
+
properties: {
|
|
1007
|
+
query: { type: "string" },
|
|
1008
|
+
k: { type: "number", description: "Hits to return (default 5)" }
|
|
1009
|
+
},
|
|
1010
|
+
required: ["query"]
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
...TOOLS_REGISTRY.filter((t) => t.audiences.includes("mcp")).map((t) => ({
|
|
1014
|
+
name: mcpName(t.name),
|
|
1015
|
+
description: t.description,
|
|
1016
|
+
inputSchema: {
|
|
1017
|
+
type: "object",
|
|
1018
|
+
properties: Object.fromEntries(t.params.map((p) => [p.key, { type: "string", description: p.description }])),
|
|
1019
|
+
required: t.params.filter((p) => p.required).map((p) => p.key)
|
|
1020
|
+
}
|
|
1021
|
+
}))
|
|
1022
|
+
];
|
|
1023
|
+
}
|
|
1020
1024
|
function dispatch(method, params, callTool) {
|
|
1021
1025
|
switch (method) {
|
|
1022
1026
|
case "initialize":
|
|
@@ -1025,10 +1029,10 @@ function dispatch(method, params, callTool) {
|
|
|
1025
1029
|
case "ping":
|
|
1026
1030
|
return Promise.resolve({ ok: true, accepted: true });
|
|
1027
1031
|
case "tools/list":
|
|
1028
|
-
return Promise.resolve({ ok: true, result: { tools:
|
|
1032
|
+
return Promise.resolve({ ok: true, result: { tools: buildTools() } });
|
|
1029
1033
|
case "tools/call": {
|
|
1030
1034
|
const name = typeof params?.name === "string" ? params.name : "";
|
|
1031
|
-
if (!
|
|
1035
|
+
if (!buildTools().some((t) => t.name === name)) {
|
|
1032
1036
|
return Promise.resolve({ ok: false, code: -32602, message: `unknown tool: ${name}` });
|
|
1033
1037
|
}
|
|
1034
1038
|
return callTool(registryName(name), params?.arguments ?? {}).then(
|
|
@@ -1075,7 +1079,7 @@ async function callToolOnce(env, ctx, _req, tier, key, name, args, t0) {
|
|
|
1075
1079
|
const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
|
|
1076
1080
|
payload = r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
|
|
1077
1081
|
} else {
|
|
1078
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
1082
|
+
const res = name === "ask" ? await (await import("../../ask-YVGMSXVO.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-VEGQBEFC.js")).handleSearch(env, ctx, inner, tier, key);
|
|
1079
1083
|
payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
1080
1084
|
}
|
|
1081
1085
|
telemetry(env, ctx, tier, `mcp:${name}`, null, !payload?.error, JSON.stringify(payload).length, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), void 0, void 0, { durationMs: Date.now() - t0 });
|
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.140",
|
|
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",
|
|
@@ -1570,7 +1570,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1570
1570
|
}
|
|
1571
1571
|
// the misplaced-pin wall rides the streamed path too: a
|
|
1572
1572
|
// CITED stream is not a refusal
|
|
1573
|
-
const canonical0 =
|
|
1573
|
+
const canonical0 = exciseMisplacedPin(canonicalRefusal(full, refusalScope(answerCites(full))), answerCites(full));
|
|
1574
1574
|
// answer contract v2: validate [[u:]] refs, resolve typed blocks
|
|
1575
1575
|
const c2 = canonical0.includes(refusalAnswer())
|
|
1576
1576
|
? { text: canonical0, blocks: [], dropped: [] as string[] }
|
|
@@ -1679,7 +1679,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1679
1679
|
// the pinned sentence if the model dropped it in as a disclaimer
|
|
1680
1680
|
// (measured on chip-scoped asks: correct cited answers carrying the
|
|
1681
1681
|
// pin mid-text, read by users and graders as total refusals)
|
|
1682
|
-
if (answer
|
|
1682
|
+
if (answer) answer = exciseMisplacedPin(answer, answerCites(answer));
|
|
1683
1683
|
stageTiming.generate = Date.now() - tGen;
|
|
1684
1684
|
|
|
1685
1685
|
// ── Deterministic quote-anchor + table-retyping check ──
|
|
@@ -11,14 +11,18 @@ export const PROTOCOL_VERSION = "2025-06-18";
|
|
|
11
11
|
// across servers. The three names docs/MCP.md already publishes keep
|
|
12
12
|
// their exact spelling; the mechanical transform covers the rest.
|
|
13
13
|
const mcpPrefix = () => `${P().publisher.id}_`;
|
|
14
|
-
|
|
14
|
+
// per call like everything else here — a module-level map froze the
|
|
15
|
+
// fixture prefix into the two published contracts (the freeze test
|
|
16
|
+
// caught this one AFTER catching the TOOLS array)
|
|
17
|
+
const mcpOverrides = (): Record<string, string> => ({
|
|
15
18
|
retrieve: `${P().publisher.id}_search`, // the published retrieval contract
|
|
16
19
|
"documents.family": `${P().publisher.id}_documents`, // the published registry contract
|
|
17
|
-
};
|
|
20
|
+
});
|
|
18
21
|
|
|
19
22
|
/** Registry tool name → the MCP-presented name. */
|
|
20
23
|
export function mcpName(registryName: string): string {
|
|
21
|
-
|
|
24
|
+
const overrides = mcpOverrides();
|
|
25
|
+
return overrides[registryName] ?? `${mcpPrefix()}${registryName.replace(/\./g, "_")}`;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
/** MCP-presented name → the name the handlers dispatch on. Raw
|
|
@@ -27,7 +31,8 @@ export function mcpName(registryName: string): string {
|
|
|
27
31
|
export function registryName(presented: string): string {
|
|
28
32
|
const pid = P().publisher.id;
|
|
29
33
|
if (presented === `${pid}_ask`) return "ask";
|
|
30
|
-
|
|
34
|
+
const overrides = mcpOverrides();
|
|
35
|
+
for (const [reg, mc] of Object.entries(overrides)) if (mc === presented) return reg;
|
|
31
36
|
if (presented.startsWith(`${pid}_`)) {
|
|
32
37
|
const rest = presented.slice(pid.length + 1);
|
|
33
38
|
const hit = TOOLS_REGISTRY.find((t) => t.audiences.includes("mcp") && t.name.replace(/\./g, "_") === rest);
|
|
@@ -43,8 +48,14 @@ export interface McpTool {
|
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
// the registry's MCP-audience tools are GENERATED here (OCP: adding a
|
|
46
|
-
// tool registers it; this list is never hand-extended for them)
|
|
47
|
-
|
|
51
|
+
// tool registers it; this list is never hand-extended for them).
|
|
52
|
+
// BUILT PER CALL, never at module load: the names carry the publisher
|
|
53
|
+
// prefix, and the deployment's setProfile runs AFTER this module's
|
|
54
|
+
// imports evaluate — a module-level array froze the fixture prefix
|
|
55
|
+
// into production's tools/list (caught by the 2026-10-12 deploy smoke's
|
|
56
|
+
// tools/list line, which the "ask" substring grep was too weak to fail).
|
|
57
|
+
export function buildTools(): McpTool[] {
|
|
58
|
+
return [
|
|
48
59
|
{
|
|
49
60
|
name: mcpName("ask"),
|
|
50
61
|
description: "Ask the corpus a question; returns a citation-grounded answer with the passages it rests on.",
|
|
@@ -80,7 +91,8 @@ export const TOOLS: McpTool[] = [
|
|
|
80
91
|
required: t.params.filter((p) => p.required).map((p) => p.key),
|
|
81
92
|
},
|
|
82
93
|
})),
|
|
83
|
-
];
|
|
94
|
+
];
|
|
95
|
+
}
|
|
84
96
|
|
|
85
97
|
export type McpResult =
|
|
86
98
|
| { ok: true; result: unknown }
|
|
@@ -101,10 +113,10 @@ export function dispatch(
|
|
|
101
113
|
case "ping":
|
|
102
114
|
return Promise.resolve({ ok: true, accepted: true });
|
|
103
115
|
case "tools/list":
|
|
104
|
-
return Promise.resolve({ ok: true, result: { tools:
|
|
116
|
+
return Promise.resolve({ ok: true, result: { tools: buildTools() } });
|
|
105
117
|
case "tools/call": {
|
|
106
118
|
const name = typeof params?.name === "string" ? params.name : "";
|
|
107
|
-
if (!
|
|
119
|
+
if (!buildTools().some((t) => t.name === name)) {
|
|
108
120
|
return Promise.resolve({ ok: false, code: -32602, message: `unknown tool: ${name}` });
|
|
109
121
|
}
|
|
110
122
|
return callTool(registryName(name), params?.arguments ?? {}).then(
|