@konneal/engine 0.2.43 → 0.2.44
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/certificates.d.ts
CHANGED
|
@@ -16,6 +16,18 @@ export declare function isRegisterShaped(query: string): boolean;
|
|
|
16
16
|
* numbers ("190", "HM14H1"). Upper-cased tokens match case-insensitively
|
|
17
17
|
* in SQL LIKE. */
|
|
18
18
|
export declare function registerTokens(query: string): string[];
|
|
19
|
+
/** The register query for a token set. Numeric tokens (a model number
|
|
20
|
+
* like "190") must match as a STANDALONE value — `LIKE '%190%'` also
|
|
21
|
+
* catches "XK3190", which the live Utilcell probe demonstrated — so a
|
|
22
|
+
* number matches the exact model, or as a delimiter-separated word
|
|
23
|
+
* (hyphens and punctuation normalize to spaces). Word tokens keep the
|
|
24
|
+
* substring LIKE (names and model words do not overmatch the way
|
|
25
|
+
* numbers do). Each token takes its own numbered placeholder,
|
|
26
|
+
* referenced three times (holder, model, number). */
|
|
27
|
+
export declare function buildRegisterQuery(tokens: string[]): {
|
|
28
|
+
sql: string;
|
|
29
|
+
params: string[];
|
|
30
|
+
};
|
|
19
31
|
export declare function searchRegister(db: any, query: string): Promise<{
|
|
20
32
|
rows: RegisterRow[];
|
|
21
33
|
tokens: string[];
|
|
@@ -1810,17 +1810,32 @@ function registerTokens(query) {
|
|
|
1810
1810
|
}
|
|
1811
1811
|
return tokens2.slice(0, 6);
|
|
1812
1812
|
}
|
|
1813
|
+
function buildRegisterQuery(tokens2) {
|
|
1814
|
+
const params = [];
|
|
1815
|
+
const clauses = tokens2.map((t) => {
|
|
1816
|
+
if (/^\d+$/.test(t)) {
|
|
1817
|
+
const padded = `% ${t.toLowerCase()} %`;
|
|
1818
|
+
params.push(t, t, padded);
|
|
1819
|
+
const n1 = params.length - 2;
|
|
1820
|
+
const n2 = params.length;
|
|
1821
|
+
return `(model = ?${n1} OR num = ?${n1} OR (' ' || REPLACE(REPLACE(REPLACE(LOWER(model), '-', ' '), ',', ' '), '.', ' ') || ' ') LIKE ?${n2})`;
|
|
1822
|
+
}
|
|
1823
|
+
params.push(`%${t}%`);
|
|
1824
|
+
const n = params.length;
|
|
1825
|
+
return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
|
|
1826
|
+
});
|
|
1827
|
+
return {
|
|
1828
|
+
sql: `SELECT num, family, holder, model, year, status FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
|
|
1829
|
+
params
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1813
1832
|
async function searchRegister(db, query) {
|
|
1814
1833
|
if (!isRegisterShaped(query)) return null;
|
|
1815
1834
|
const tokens2 = registerTokens(query);
|
|
1816
1835
|
if (!tokens2.length) return null;
|
|
1817
|
-
const
|
|
1818
|
-
const n = i + 1;
|
|
1819
|
-
return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
|
|
1820
|
-
}).join(" OR ");
|
|
1821
|
-
const params = tokens2.map((t) => `%${t}%`);
|
|
1836
|
+
const { sql, params } = buildRegisterQuery(tokens2);
|
|
1822
1837
|
try {
|
|
1823
|
-
const res = await db.prepare(
|
|
1838
|
+
const res = await db.prepare(sql).bind(...params).all();
|
|
1824
1839
|
return { rows: res.results ?? [], tokens: tokens2 };
|
|
1825
1840
|
} catch {
|
|
1826
1841
|
return { rows: [], tokens: tokens2 };
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
modelGroundingBlock,
|
|
10
10
|
scoreJudge,
|
|
11
11
|
standardForDocNumber
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-HDUSO5S5.js";
|
|
13
13
|
import {
|
|
14
14
|
buildMessages,
|
|
15
15
|
citations,
|
|
@@ -999,7 +999,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
999
999
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
1000
1000
|
body: JSON.stringify({ ...args, stream: false })
|
|
1001
1001
|
});
|
|
1002
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
1002
|
+
const res = name === "ask" ? await (await import("../../ask-JOX2D7KH.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-QZDQVB57.js")).handleSearch(env, ctx, inner, tier, key);
|
|
1003
1003
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
1004
1004
|
});
|
|
1005
1005
|
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.44",
|
|
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",
|
|
@@ -48,23 +48,45 @@ export function registerTokens(query: string): string[] {
|
|
|
48
48
|
return tokens.slice(0, 6);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/** The register query for a token set. Numeric tokens (a model number
|
|
52
|
+
* like "190") must match as a STANDALONE value — `LIKE '%190%'` also
|
|
53
|
+
* catches "XK3190", which the live Utilcell probe demonstrated — so a
|
|
54
|
+
* number matches the exact model, or as a delimiter-separated word
|
|
55
|
+
* (hyphens and punctuation normalize to spaces). Word tokens keep the
|
|
56
|
+
* substring LIKE (names and model words do not overmatch the way
|
|
57
|
+
* numbers do). Each token takes its own numbered placeholder,
|
|
58
|
+
* referenced three times (holder, model, number). */
|
|
59
|
+
export function buildRegisterQuery(tokens: string[]): { sql: string; params: string[] } {
|
|
60
|
+
const params: string[] = [];
|
|
61
|
+
const clauses = tokens.map((t) => {
|
|
62
|
+
if (/^\d+$/.test(t)) {
|
|
63
|
+
// a number matches as a STANDALONE value: the exact model or
|
|
64
|
+
// certificate number, or a delimiter-separated word (hyphens and
|
|
65
|
+
// punctuation normalize to spaces) — never a substring ("190"
|
|
66
|
+
// must not catch "XK3190")
|
|
67
|
+
const padded = `% ${t.toLowerCase()} %`;
|
|
68
|
+
params.push(t, t, padded);
|
|
69
|
+
const n1 = params.length - 2;
|
|
70
|
+
const n2 = params.length;
|
|
71
|
+
return `(model = ?${n1} OR num = ?${n1} OR (' ' || REPLACE(REPLACE(REPLACE(LOWER(model), '-', ' '), ',', ' '), '.', ' ') || ' ') LIKE ?${n2})`;
|
|
72
|
+
}
|
|
73
|
+
params.push(`%${t}%`);
|
|
74
|
+
const n = params.length;
|
|
75
|
+
return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
sql: `SELECT num, family, holder, model, year, status FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
|
|
79
|
+
params,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
51
83
|
export async function searchRegister(db: any, query: string): Promise<{ rows: RegisterRow[]; tokens: string[] } | null> {
|
|
52
84
|
if (!isRegisterShaped(query)) return null;
|
|
53
85
|
const tokens = registerTokens(query);
|
|
54
86
|
if (!tokens.length) return null;
|
|
55
|
-
|
|
56
|
-
// times (holder, model, number) — a shared ?1 would silently search
|
|
57
|
-
// the first token only
|
|
58
|
-
const clauses = tokens.map((_, i) => {
|
|
59
|
-
const n = i + 1;
|
|
60
|
-
return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
|
|
61
|
-
}).join(" OR ");
|
|
62
|
-
const params = tokens.map((t) => `%${t}%`);
|
|
87
|
+
const { sql, params } = buildRegisterQuery(tokens);
|
|
63
88
|
try {
|
|
64
|
-
const res = await db
|
|
65
|
-
.prepare(`SELECT num, family, holder, model, year, status FROM certificates WHERE ${clauses} LIMIT 6`)
|
|
66
|
-
.bind(...params)
|
|
67
|
-
.all();
|
|
89
|
+
const res = await db.prepare(sql).bind(...params).all();
|
|
68
90
|
return { rows: (res.results ?? []) as RegisterRow[], tokens };
|
|
69
91
|
} catch {
|
|
70
92
|
// a missing table or a D1 hiccup degrades to no-note honestly
|