@konneal/engine 0.2.16 → 0.2.17
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.
|
@@ -931,12 +931,31 @@ function cellValue(row, cols, col) {
|
|
|
931
931
|
const raw = row[idx] ?? "";
|
|
932
932
|
return num2(raw) ?? String(raw).trim();
|
|
933
933
|
}
|
|
934
|
-
function
|
|
934
|
+
function classValueExists(rows, cols, token) {
|
|
935
|
+
const cc = classColumn(cols);
|
|
936
|
+
if (!cc) return false;
|
|
937
|
+
const idx = cols.indexOf(cc);
|
|
938
|
+
return rows.some((r) => String(r[idx] ?? "").trim().toLowerCase() === token);
|
|
939
|
+
}
|
|
940
|
+
function statedUnits(query) {
|
|
941
|
+
const out = /* @__PURE__ */ new Set();
|
|
942
|
+
const re = new RegExp(`(${NUM2})\\s*([%\xB0a-zA-Z][a-zA-Z/.%\xB0]*\\b)`, "g");
|
|
943
|
+
for (const m of query.matchAll(re)) {
|
|
944
|
+
if (m[2]) out.add(m[2].replace("\u2062", "").trim());
|
|
945
|
+
}
|
|
946
|
+
return out;
|
|
947
|
+
}
|
|
948
|
+
function pickTable(nodes, query) {
|
|
949
|
+
const queryLower = query.toLowerCase();
|
|
950
|
+
const stated = statedUnits(query);
|
|
951
|
+
const cToken = classToken(query);
|
|
935
952
|
let best = null;
|
|
936
953
|
for (const n of nodes) {
|
|
937
954
|
const c = n.content ?? {};
|
|
938
955
|
const payload = c.payload ?? {};
|
|
939
956
|
if (!Array.isArray(payload.rows) || !payload.rows.length) continue;
|
|
957
|
+
const cols = Array.isArray(payload.columns) ? payload.columns : [];
|
|
958
|
+
const rows = (Array.isArray(payload.rows) ? payload.rows : []).filter((r) => Array.isArray(r));
|
|
940
959
|
let score = 0;
|
|
941
960
|
for (const t of tokens(n.node_id.replace("/table/", ""))) {
|
|
942
961
|
if (t.length >= 3 && queryLower.includes(t)) score += 2;
|
|
@@ -944,6 +963,8 @@ function pickTable(nodes, queryLower) {
|
|
|
944
963
|
for (const w of String(c.name ?? "").toLowerCase().split(/[^a-z0-9.]+/)) {
|
|
945
964
|
if (w.length >= 4 && queryLower.includes(w)) score += 1;
|
|
946
965
|
}
|
|
966
|
+
if (intervalPairs(cols).some((p) => p.low.unit && stated.has(p.low.unit))) score += 3;
|
|
967
|
+
if (cToken && (classAsColumn(cols, cToken) || classValueExists(rows, cols, cToken))) score += 2;
|
|
947
968
|
if (!best || score > best.score) best = { node: n, score };
|
|
948
969
|
}
|
|
949
970
|
if (best && best.score > 0) return best.node;
|
|
@@ -953,7 +974,7 @@ function evaluateAggregation(nodes, query) {
|
|
|
953
974
|
const qLower = query.toLowerCase();
|
|
954
975
|
const operation = /\bhow many\b|\bnumber of\b/.test(qLower) ? "count" : /\b(minimum|smallest|shortest|lowest|least)\b/.test(qLower) ? "min" : /\b(maximum|largest|longest|highest|greatest)\b/.test(qLower) ? "max" : "lookup";
|
|
955
976
|
if (!nodes.length) return null;
|
|
956
|
-
const node = pickTable(nodes,
|
|
977
|
+
const node = pickTable(nodes, query);
|
|
957
978
|
if (!node) return null;
|
|
958
979
|
const content = node.content && typeof node.content === "object" ? node.content : {};
|
|
959
980
|
const payload = content.payload ?? {};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
handleMemories,
|
|
8
8
|
scoreJudge,
|
|
9
9
|
standardForDocNumber
|
|
10
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-DRQ37UGZ.js";
|
|
11
11
|
import {
|
|
12
12
|
buildMessages,
|
|
13
13
|
citations,
|
|
@@ -979,7 +979,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
979
979
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
980
980
|
body: JSON.stringify({ ...args, stream: false })
|
|
981
981
|
});
|
|
982
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
982
|
+
const res = name === "ask" ? await (await import("../../ask-PKKNMLLM.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-RFKT7ZZY.js")).handleSearch(env, ctx, inner, tier, key);
|
|
983
983
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
984
984
|
});
|
|
985
985
|
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@oimlsmart/oiml-pubid": "^1.2.1"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {},
|
|
37
|
-
"version": "0.2.
|
|
37
|
+
"version": "0.2.17",
|
|
38
38
|
"description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
|
|
39
39
|
"license": "BSD-3-Clause",
|
|
40
40
|
"type": "module",
|
|
@@ -140,12 +140,35 @@ function cellValue(row: string[], cols: Column[], col: Column): number | string
|
|
|
140
140
|
return num(raw) ?? String(raw).trim();
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
/** The named class exists as a row VALUE of the table's class column
|
|
144
|
+
* (mpe_tiers' accuracy_class A/B/C/D rows). */
|
|
145
|
+
function classValueExists(rows: string[][], cols: Column[], token: string): boolean {
|
|
146
|
+
const cc = classColumn(cols);
|
|
147
|
+
if (!cc) return false;
|
|
148
|
+
const idx = cols.indexOf(cc);
|
|
149
|
+
return rows.some((r) => String(r[idx] ?? "").trim().toLowerCase() === token);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function statedUnits(query: string): Set<string> {
|
|
153
|
+
const out = new Set<string>();
|
|
154
|
+
const re = new RegExp(`(${NUM})\\s*([%°a-zA-Z][a-zA-Z/.%°]*\\b)`,"g");
|
|
155
|
+
for (const m of query.matchAll(re)) {
|
|
156
|
+
if (m[2]) out.add(m[2].replace("\u2062", "").trim());
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function pickTable(nodes: { node_id: string; content: any }[], query: string): { node_id: string; content: any } | null {
|
|
162
|
+
const queryLower = query.toLowerCase();
|
|
163
|
+
const stated = statedUnits(query);
|
|
164
|
+
const cToken = classToken(query);
|
|
144
165
|
let best: { node: { node_id: string; content: any }; score: number } | null = null;
|
|
145
166
|
for (const n of nodes) {
|
|
146
167
|
const c = n.content ?? {};
|
|
147
168
|
const payload = (c.payload ?? {}) as { columns?: Column[]; rows?: unknown[] };
|
|
148
169
|
if (!Array.isArray(payload.rows) || !payload.rows.length) continue;
|
|
170
|
+
const cols = (Array.isArray(payload.columns) ? payload.columns : []) as Column[];
|
|
171
|
+
const rows = (Array.isArray(payload.rows) ? payload.rows : []).filter((r) => Array.isArray(r)) as string[][];
|
|
149
172
|
let score = 0;
|
|
150
173
|
for (const t of tokens(n.node_id.replace("/table/", ""))) {
|
|
151
174
|
if (t.length >= 3 && queryLower.includes(t)) score += 2;
|
|
@@ -153,6 +176,11 @@ function pickTable(nodes: { node_id: string; content: any }[], queryLower: strin
|
|
|
153
176
|
for (const w of String(c.name ?? "").toLowerCase().split(/[^a-z0-9.]+/)) {
|
|
154
177
|
if (w.length >= 4 && queryLower.includes(w)) score += 1;
|
|
155
178
|
}
|
|
179
|
+
// the question's stated unit existing as this table's interval unit,
|
|
180
|
+
// and the named class resolving here, are the strongest signals —
|
|
181
|
+
// a table without either cannot hold the lookup
|
|
182
|
+
if (intervalPairs(cols).some((p) => p.low.unit && stated.has(p.low.unit))) score += 3;
|
|
183
|
+
if (cToken && (classAsColumn(cols, cToken) || classValueExists(rows, cols, cToken))) score += 2;
|
|
156
184
|
if (!best || score > best.score) best = { node: n, score };
|
|
157
185
|
}
|
|
158
186
|
// an un-scored pick across several tables would be a guess: refuse
|
|
@@ -177,7 +205,7 @@ export function evaluateAggregation(
|
|
|
177
205
|
? "max"
|
|
178
206
|
: "lookup";
|
|
179
207
|
if (!nodes.length) return null;
|
|
180
|
-
const node = pickTable(nodes,
|
|
208
|
+
const node = pickTable(nodes, query);
|
|
181
209
|
if (!node) return null;
|
|
182
210
|
const content = (node.content && typeof node.content === "object" ? node.content : {}) as Record<string, any>;
|
|
183
211
|
const payload = (content.payload ?? {}) as { columns?: Column[]; rows?: unknown[] };
|