@konneal/engine 0.2.94 → 0.2.96
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-HCKUKBPB.js → ask-KKOQH7HK.js} +3 -3
- package/dist/{chunk-64IG3ZLT.js → chunk-AJU6LMY3.js} +5 -3
- package/dist/{chunk-2JC7GXRV.js → chunk-CX3OVN3V.js} +8 -4
- package/dist/{chunk-3BL223VD.js → chunk-PTCDEFI3.js} +28 -0
- package/dist/{chunk-TJTEBS4S.js → chunk-ZLQMRQOV.js} +1 -1
- package/dist/{search-G76DK4AF.js → search-CGQFGYTR.js} +2 -2
- package/dist/{tools-O7OGW54R.js → tools-Z4HQH3QU.js} +1 -1
- package/dist/worker_public/src/index.js +29 -14
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +7 -2
- package/workers/worker_public/src/mcp.ts +42 -12
- package/workers/worker_public/src/modelplane.ts +16 -4
- package/workers/worker_public/src/stages/index.ts +2 -0
- package/workers/worker_public/src/stages/licensedLane.ts +38 -0
- package/workers/worker_public/src/stages/types.ts +4 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleAsk
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-CX3OVN3V.js";
|
|
4
|
+
import "./chunk-AJU6LMY3.js";
|
|
5
|
+
import "./chunk-PTCDEFI3.js";
|
|
6
6
|
import "./chunk-LOBYXEVD.js";
|
|
7
7
|
import "./chunk-SPKPH54J.js";
|
|
8
8
|
import "./chunk-A3QHHUN5.js";
|
|
@@ -148,9 +148,11 @@ async function bindModelNode(env, opts) {
|
|
|
148
148
|
};
|
|
149
149
|
if (opts.standard) return gate(await fetchNode(env, opts.standard, nodeId));
|
|
150
150
|
try {
|
|
151
|
-
const rows = await env.DB.prepare(
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
const rows = await env.DB.prepare(
|
|
152
|
+
"SELECT n.standard AS standard FROM model_nodes n LEFT JOIN model_plane_meta m ON m.standard = n.standard WHERE n.node_id = ?1 ORDER BY m.indexed_at DESC, n.standard DESC LIMIT 1"
|
|
153
|
+
).bind(nodeId).all();
|
|
154
|
+
const standard = (rows?.results ?? []).map((r) => String(r.standard))[0];
|
|
155
|
+
if (standard) return gate(await fetchNode(env, standard, nodeId));
|
|
154
156
|
return null;
|
|
155
157
|
} catch {
|
|
156
158
|
return null;
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
tableRetyped,
|
|
19
19
|
toolNote,
|
|
20
20
|
verdictNote
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-AJU6LMY3.js";
|
|
22
22
|
import {
|
|
23
23
|
NO_CONTEXT,
|
|
24
24
|
answerQuality,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
tokenBudget,
|
|
57
57
|
understandQuery,
|
|
58
58
|
usageTotal
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-PTCDEFI3.js";
|
|
60
60
|
import {
|
|
61
61
|
embed,
|
|
62
62
|
generateOnce,
|
|
@@ -2166,6 +2166,7 @@ ${summary}` }] : [],
|
|
|
2166
2166
|
if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "\u2192", aggregationVerdict.value);
|
|
2167
2167
|
let boundaryNote = null;
|
|
2168
2168
|
let boundaryBoost;
|
|
2169
|
+
let licensedDocNumbers;
|
|
2169
2170
|
let editionBoost;
|
|
2170
2171
|
try {
|
|
2171
2172
|
const fam = understanding?.doc ? refCodec().familyOf(understanding.doc) : null;
|
|
@@ -2178,7 +2179,9 @@ ${summary}` }] : [],
|
|
|
2178
2179
|
const lexicalBoost = [boundaryBoost, editionBoost].filter(Boolean).join(" ") || void 0;
|
|
2179
2180
|
if (P().sources?.licensed?.length) {
|
|
2180
2181
|
const match = matchLicensedTopic(q.query, P().sources.licensed);
|
|
2181
|
-
if (match &&
|
|
2182
|
+
if (match && (standardKeys?.has(match.entry.key) ?? false)) {
|
|
2183
|
+
licensedDocNumbers = match.entry.package ? [match.entry.package] : void 0;
|
|
2184
|
+
} else if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
|
|
2182
2185
|
const docNum = match.entry.doc_number ?? "";
|
|
2183
2186
|
boundaryBoost = docNum || void 0;
|
|
2184
2187
|
let citing = [];
|
|
@@ -2227,7 +2230,8 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2227
2230
|
optimisticVec,
|
|
2228
2231
|
datasetScope: narrowed ? corpora : null,
|
|
2229
2232
|
standardKeys,
|
|
2230
|
-
lexicalBoost
|
|
2233
|
+
lexicalBoost,
|
|
2234
|
+
licensedDocNumbers
|
|
2231
2235
|
});
|
|
2232
2236
|
stageTiming["retrieve-core"] = Date.now() - tR;
|
|
2233
2237
|
console.log("stage: retrieve", Date.now() - tR, "ms");
|
|
@@ -22522,6 +22522,33 @@ var graphLane = {
|
|
|
22522
22522
|
}
|
|
22523
22523
|
};
|
|
22524
22524
|
|
|
22525
|
+
// workers/worker_public/src/stages/licensedLane.ts
|
|
22526
|
+
var licensedLane = {
|
|
22527
|
+
name: "licensed-lane",
|
|
22528
|
+
failure: "additive",
|
|
22529
|
+
when: (c) => !!c.opts.licensedDocNumbers?.length && c.vector.length > 0,
|
|
22530
|
+
prefetch: (c) => {
|
|
22531
|
+
c.lane["licensed-lane"] = portIndex(c.env, "public").query({
|
|
22532
|
+
vector: c.vector,
|
|
22533
|
+
topK: 12,
|
|
22534
|
+
filter: { standard: { $in: c.opts.licensedDocNumbers } }
|
|
22535
|
+
});
|
|
22536
|
+
},
|
|
22537
|
+
run: async (c) => {
|
|
22538
|
+
const g = await c.lane["licensed-lane"];
|
|
22539
|
+
const seenIds = new Set(c.matches.map((m) => m.id));
|
|
22540
|
+
let merged = 0;
|
|
22541
|
+
for (const m of (g ?? []).slice(0, 10)) {
|
|
22542
|
+
if (!seenIds.has(m.id)) {
|
|
22543
|
+
c.matches.push({ id: m.id, score: m.score * THRESHOLDS.graphLaneDiscount, metadata: m.metadata });
|
|
22544
|
+
seenIds.add(m.id);
|
|
22545
|
+
merged++;
|
|
22546
|
+
}
|
|
22547
|
+
}
|
|
22548
|
+
console.log("licensed lane:", g?.length ?? 0, "hits,", merged, "merged");
|
|
22549
|
+
}
|
|
22550
|
+
};
|
|
22551
|
+
|
|
22525
22552
|
// workers/worker_public/src/stages/multiQuery.ts
|
|
22526
22553
|
var RRF_K = 60;
|
|
22527
22554
|
var multiQuery = {
|
|
@@ -23133,6 +23160,7 @@ var STAGES = [
|
|
|
23133
23160
|
glossary,
|
|
23134
23161
|
conceptGraph,
|
|
23135
23162
|
graphLane,
|
|
23163
|
+
licensedLane,
|
|
23136
23164
|
multiQuery,
|
|
23137
23165
|
subQuery,
|
|
23138
23166
|
poolOpen,
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
handleMemories,
|
|
5
5
|
scoreFaithfulness,
|
|
6
6
|
scoreJudge
|
|
7
|
-
} from "../../chunk-
|
|
7
|
+
} from "../../chunk-CX3OVN3V.js";
|
|
8
8
|
import {
|
|
9
9
|
TOOLS_REGISTRY,
|
|
10
10
|
bindModelNode,
|
|
11
11
|
modelGroundingBlock
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-AJU6LMY3.js";
|
|
13
13
|
import {
|
|
14
14
|
handleSearch
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-ZLQMRQOV.js";
|
|
16
16
|
import {
|
|
17
17
|
buildMessages,
|
|
18
18
|
citations,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
sessionFrom,
|
|
35
35
|
telemetry,
|
|
36
36
|
understandQuery
|
|
37
|
-
} from "../../chunk-
|
|
37
|
+
} from "../../chunk-PTCDEFI3.js";
|
|
38
38
|
import {
|
|
39
39
|
cfBlobs,
|
|
40
40
|
embed,
|
|
@@ -967,26 +967,41 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
967
967
|
const method = typeof body?.method === "string" ? body.method : null;
|
|
968
968
|
const id = body?.id ?? null;
|
|
969
969
|
const out = await dispatch(method, body?.params, async (name, args) => {
|
|
970
|
+
const t0 = Date.now();
|
|
971
|
+
try {
|
|
972
|
+
return await callToolOnce(env, ctx, req, tier, key, name, args, t0);
|
|
973
|
+
} catch (e) {
|
|
974
|
+
telemetry(env, ctx, tier, `mcp:${name}`, null, false, 0, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), void 0, void 0, { durationMs: Date.now() - t0 });
|
|
975
|
+
throw e;
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
|
979
|
+
if (out.ok) {
|
|
980
|
+
if (out.result?.serverInfo) out.result.serverInfo.name = `${P().publisher.id}-rag`;
|
|
981
|
+
return json({ jsonrpc: "2.0", id, result: out.result });
|
|
982
|
+
}
|
|
983
|
+
return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
|
|
984
|
+
}
|
|
985
|
+
async function callToolOnce(env, ctx, _req, tier, key, name, args, t0) {
|
|
986
|
+
{
|
|
970
987
|
const inner = new Request("https://internal/mcp", {
|
|
971
988
|
method: "POST",
|
|
972
989
|
headers: { "content-type": "application/json" },
|
|
973
990
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
974
991
|
body: JSON.stringify({ ...args, stream: false })
|
|
975
992
|
});
|
|
976
|
-
const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-
|
|
993
|
+
const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-Z4HQH3QU.js");
|
|
994
|
+
let payload;
|
|
977
995
|
if (TOOLS_REGISTRY2.some((t) => t.name === name && t.audiences.includes("mcp"))) {
|
|
978
996
|
const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
|
|
979
|
-
|
|
997
|
+
payload = r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
|
|
998
|
+
} else {
|
|
999
|
+
const res = name === "ask" ? await (await import("../../ask-KKOQH7HK.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-CGQFGYTR.js")).handleSearch(env, ctx, inner, tier, key);
|
|
1000
|
+
payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
980
1001
|
}
|
|
981
|
-
|
|
982
|
-
return
|
|
983
|
-
});
|
|
984
|
-
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
|
985
|
-
if (out.ok) {
|
|
986
|
-
if (out.result?.serverInfo) out.result.serverInfo.name = `${P().publisher.id}-rag`;
|
|
987
|
-
return json({ jsonrpc: "2.0", id, result: out.result });
|
|
1002
|
+
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 });
|
|
1003
|
+
return payload;
|
|
988
1004
|
}
|
|
989
|
-
return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
|
|
990
1005
|
}
|
|
991
1006
|
|
|
992
1007
|
// workers/shared/router.ts
|
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.96",
|
|
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",
|
|
@@ -1017,6 +1017,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1017
1017
|
// publication's own clause — surface for a question the document's
|
|
1018
1018
|
// vocabulary alone would miss
|
|
1019
1019
|
let boundaryBoost: string | undefined;
|
|
1020
|
+
let licensedDocNumbers: string[] | undefined;
|
|
1020
1021
|
// the EDITION boost: the grounding pool tilts to the publication's
|
|
1021
1022
|
// ACTIVE edition (the graph's own registry) — the dirty corpus's
|
|
1022
1023
|
// superseded editions otherwise outrank the current ones on shared
|
|
@@ -1037,7 +1038,11 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1037
1038
|
const lexicalBoost = [boundaryBoost, editionBoost].filter(Boolean).join(" ") || undefined;
|
|
1038
1039
|
if (P().sources?.licensed?.length) {
|
|
1039
1040
|
const match = matchLicensedTopic(q.query, P().sources.licensed);
|
|
1040
|
-
if (match &&
|
|
1041
|
+
if (match && (standardKeys?.has(match.entry.key) ?? false)) {
|
|
1042
|
+
// the entitled caller: the licensed lane pulls the package's own
|
|
1043
|
+
// units so they compete with (and outrank) the public restatements
|
|
1044
|
+
licensedDocNumbers = match.entry.package ? [match.entry.package] : undefined;
|
|
1045
|
+
} else if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
|
|
1041
1046
|
const docNum = match.entry.doc_number ?? "";
|
|
1042
1047
|
boundaryBoost = docNum || undefined;
|
|
1043
1048
|
let citing: string[] = [];
|
|
@@ -1106,7 +1111,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
|
1106
1111
|
// publications there).
|
|
1107
1112
|
retrieved = await retrieve(env, q.query, { prev, understanding, federate, warmEmbed, graphDocNumbers,
|
|
1108
1113
|
sealScope: declaredScoped ? docScope : null, optimisticHits, optimisticVec,
|
|
1109
|
-
datasetScope: narrowed ? corpora : null, standardKeys, lexicalBoost });
|
|
1114
|
+
datasetScope: narrowed ? corpora : null, standardKeys, lexicalBoost, licensedDocNumbers });
|
|
1110
1115
|
stageTiming["retrieve-core"] = Date.now() - tR;
|
|
1111
1116
|
console.log("stage: retrieve", Date.now() - tR, "ms");
|
|
1112
1117
|
// ── TTFT surgery: the two post-retrieval LLM calls run IN PARALLEL —
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
// mcp-proto.ts (dependency-free, unit-tested). The internal-audience
|
|
7
7
|
// server federates both indexes and lives in its own worker, never here.
|
|
8
8
|
import { json, readJson, type ApiKey } from "./lib/http";
|
|
9
|
+
import { sha256Hex } from "./config.ts";
|
|
10
|
+
import { telemetry } from "./quota.ts";
|
|
9
11
|
import { P } from "./profile.ts";
|
|
10
12
|
import { dispatch } from "./mcp-proto.ts";
|
|
11
13
|
import type { Env } from "./env.ts";
|
|
@@ -24,6 +26,37 @@ export async function handleMcp(
|
|
|
24
26
|
const id = body?.id ?? null;
|
|
25
27
|
|
|
26
28
|
const out = await dispatch(method, body?.params, async (name, args) => {
|
|
29
|
+
const t0 = Date.now();
|
|
30
|
+
try {
|
|
31
|
+
return await callToolOnce(env, ctx, req, tier, key, name, args, t0);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
telemetry(env, ctx, tier, `mcp:${name}`, null, false, 0, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), undefined, undefined, { durationMs: Date.now() - t0 });
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
|
39
|
+
if (out.ok) {
|
|
40
|
+
if ((out.result as any)?.serverInfo) (out.result as any).serverInfo.name = `${P().publisher.id}-rag`;
|
|
41
|
+
return json({ jsonrpc: "2.0", id, result: out.result });
|
|
42
|
+
}
|
|
43
|
+
return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** One tools/call dispatch, measured: every MCP surface's tool usage
|
|
47
|
+
* lands in the queries table under the mcp:<tool> route — which tools
|
|
48
|
+
* agents actually call becomes countable, per tier, per key. */
|
|
49
|
+
async function callToolOnce(
|
|
50
|
+
env: Env,
|
|
51
|
+
ctx: Background,
|
|
52
|
+
_req: Request,
|
|
53
|
+
tier: "anon" | "key" | "member",
|
|
54
|
+
key: ApiKey | null,
|
|
55
|
+
name: string,
|
|
56
|
+
args: Record<string, unknown>,
|
|
57
|
+
t0: number,
|
|
58
|
+
) {
|
|
59
|
+
{
|
|
27
60
|
const inner = new Request("https://internal/mcp", {
|
|
28
61
|
method: "POST",
|
|
29
62
|
headers: { "content-type": "application/json" },
|
|
@@ -35,20 +68,17 @@ export async function handleMcp(
|
|
|
35
68
|
// registry tools (certificates.search, units.get, …) dispatch through
|
|
36
69
|
// the SAME handlers the API would — the no-drift rule, now structural
|
|
37
70
|
const { runTool, TOOLS_REGISTRY } = await import("./tools.ts");
|
|
71
|
+
let payload: any;
|
|
38
72
|
if (TOOLS_REGISTRY.some((t) => t.name === name && t.audiences.includes("mcp"))) {
|
|
39
73
|
const r = await runTool({ ...env, DB: (env as any).DB }, { name, args }, "mcp");
|
|
40
|
-
|
|
74
|
+
payload = r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
|
|
75
|
+
} else {
|
|
76
|
+
const res = name === "ask"
|
|
77
|
+
? await (await import("./ask")).handleAsk(env, ctx as any, inner, tier, key)
|
|
78
|
+
: await (await import("./search")).handleSearch(env, ctx as any, inner, tier, key);
|
|
79
|
+
payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
41
80
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
: await (await import("./search")).handleSearch(env, ctx as any, inner, tier, key);
|
|
45
|
-
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
|
49
|
-
if (out.ok) {
|
|
50
|
-
if ((out.result as any)?.serverInfo) (out.result as any).serverInfo.name = `${P().publisher.id}-rag`;
|
|
51
|
-
return json({ jsonrpc: "2.0", id, result: out.result });
|
|
81
|
+
telemetry(env, ctx, tier, `mcp:${name}`, null, !payload?.error, JSON.stringify(payload).length, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), undefined, undefined, { durationMs: Date.now() - t0 });
|
|
82
|
+
return payload;
|
|
52
83
|
}
|
|
53
|
-
return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
|
|
54
84
|
}
|
|
@@ -196,10 +196,22 @@ export async function bindModelNode(
|
|
|
196
196
|
};
|
|
197
197
|
if (opts.standard) return gate(await fetchNode(env, opts.standard, nodeId));
|
|
198
198
|
try {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
// The MECE flip left the retired standards' nodes beside their
|
|
200
|
+
// successors' (the same node id under oiml-r60 and oiml-r60-lml),
|
|
201
|
+
// so ambiguity is the COMMON case now. The plane's own registry
|
|
202
|
+
// breaks the tie: the standard loaded most recently is the
|
|
203
|
+
// canonical layer for that id (the flip's law — the layer owns its
|
|
204
|
+
// units), standard name descending as the deterministic second key;
|
|
205
|
+
// a standard with no meta row (orphaned) sorts last. An id under
|
|
206
|
+
// zero standards still binds to nothing.
|
|
207
|
+
const rows = await env.DB.prepare(
|
|
208
|
+
"SELECT n.standard AS standard FROM model_nodes n LEFT JOIN model_plane_meta m ON m.standard = n.standard WHERE n.node_id = ?1 ORDER BY m.indexed_at DESC, n.standard DESC LIMIT 1",
|
|
209
|
+
)
|
|
210
|
+
.bind(nodeId)
|
|
211
|
+
.all();
|
|
212
|
+
const standard = (rows?.results ?? []).map((r: any) => String(r.standard))[0];
|
|
213
|
+
if (standard) return gate(await fetchNode(env, standard, nodeId));
|
|
214
|
+
return null; // not indexed
|
|
203
215
|
} catch {
|
|
204
216
|
return null;
|
|
205
217
|
}
|
|
@@ -17,6 +17,7 @@ import { hyde } from "./hyde.ts";
|
|
|
17
17
|
import { glossary } from "./glossary.ts";
|
|
18
18
|
import { conceptGraph } from "./conceptGraph.ts";
|
|
19
19
|
import { graphLane } from "./graphLane.ts";
|
|
20
|
+
import { licensedLane } from "./licensedLane.ts";
|
|
20
21
|
import { multiQuery } from "./multiQuery.ts";
|
|
21
22
|
import { subQuery } from "./subQuery.ts";
|
|
22
23
|
import { poolOpen } from "./poolOpen.ts";
|
|
@@ -46,6 +47,7 @@ export const STAGES: Stage[] = [
|
|
|
46
47
|
glossary,
|
|
47
48
|
conceptGraph,
|
|
48
49
|
graphLane,
|
|
50
|
+
licensedLane,
|
|
49
51
|
multiQuery,
|
|
50
52
|
subQuery,
|
|
51
53
|
poolOpen,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Licensed lane (additive): an entitled caller whose question is
|
|
2
|
+
// topically about a licensed standard gets that standard's typed units
|
|
3
|
+
// merged into the pool at the graph lane's discount — the public
|
|
4
|
+
// restatements (the Recommendations' own annexes citing the standard)
|
|
5
|
+
// stop out-ranking the licensed package's own units, the rank-order
|
|
6
|
+
// gap the quality ledger has documented on every damp-heat run since
|
|
7
|
+
// the eleven-standard wave. Unentitled callers never see this lane
|
|
8
|
+
// (license-scope would strip the units anyway — the lane simply does
|
|
9
|
+
// not fire).
|
|
10
|
+
import { THRESHOLDS } from "../config.ts";
|
|
11
|
+
import { portIndex } from "../env.ts";
|
|
12
|
+
import type { Stage } from "./types.ts";
|
|
13
|
+
|
|
14
|
+
export const licensedLane: Stage = {
|
|
15
|
+
name: "licensed-lane",
|
|
16
|
+
failure: "additive",
|
|
17
|
+
when: (c) => !!c.opts.licensedDocNumbers?.length && c.vector.length > 0,
|
|
18
|
+
prefetch: (c) => {
|
|
19
|
+
c.lane["licensed-lane"] = portIndex(c.env, "public").query({
|
|
20
|
+
vector: c.vector,
|
|
21
|
+
topK: 12,
|
|
22
|
+
filter: { standard: { $in: c.opts.licensedDocNumbers } },
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
run: async (c) => {
|
|
26
|
+
const g = (await c.lane["licensed-lane"]!) as any;
|
|
27
|
+
const seenIds = new Set(c.matches.map((m: any) => m.id));
|
|
28
|
+
let merged = 0;
|
|
29
|
+
for (const m of (g ?? []).slice(0, 10)) {
|
|
30
|
+
if (!seenIds.has(m.id)) {
|
|
31
|
+
c.matches.push({ id: m.id, score: m.score * THRESHOLDS.graphLaneDiscount, metadata: m.metadata });
|
|
32
|
+
seenIds.add(m.id);
|
|
33
|
+
merged++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
console.log("licensed lane:", g?.length ?? 0, "hits,", merged, "merged");
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -20,6 +20,10 @@ export interface RetrieveOptions {
|
|
|
20
20
|
federate?: (query: string) => Promise<Hit[]>;
|
|
21
21
|
warmEmbed?: Promise<number[] | null>;
|
|
22
22
|
graphDocNumbers?: string[];
|
|
23
|
+
/** The licensed standards the entitled, topically-matched question
|
|
24
|
+
* pulls (the licensed lane's metadata filter — the package ids, e.g.
|
|
25
|
+
* iec-60068-2-30). Empty/absent for everyone else. */
|
|
26
|
+
licensedDocNumbers?: string[];
|
|
23
27
|
/** The declared context's HARD seal (TODO.ai-platform/02): when the
|
|
24
28
|
* panel's chip declares a document scope, the CANDIDATE POOL is cut
|
|
25
29
|
* to the publication family before rerank + the top-N cut — the
|