@konneal/engine 0.2.57 → 0.2.60

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.
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  handleAsk
3
- } from "./chunk-MNEUEHO7.js";
3
+ } from "./chunk-OEXJFPNO.js";
4
4
  import "./chunk-TPV5GPY2.js";
5
5
  import "./chunk-SPKPH54J.js";
6
6
  import "./chunk-A3QHHUN5.js";
7
7
  import "./chunk-LVZTWUVJ.js";
8
8
  import "./chunk-2PCUAJJO.js";
9
- import "./chunk-Z6JAGZAM.js";
9
+ import "./chunk-PCP4AQQQ.js";
10
10
  import "./chunk-3FYJM7LH.js";
11
11
  export {
12
12
  handleAsk
@@ -1,14 +1,16 @@
1
1
  import {
2
2
  buildRegisterQuery,
3
+ certificateLinks,
3
4
  isRegisterShaped,
4
5
  queryFamily,
5
6
  registerNote,
6
7
  registerTokens,
7
8
  searchRegister
8
- } from "./chunk-Z6JAGZAM.js";
9
+ } from "./chunk-PCP4AQQQ.js";
9
10
  import "./chunk-3FYJM7LH.js";
10
11
  export {
11
12
  buildRegisterQuery,
13
+ certificateLinks,
12
14
  isRegisterShaped,
13
15
  queryFamily,
14
16
  registerNote,
@@ -5,6 +5,7 @@ export interface RegisterRow {
5
5
  model: string;
6
6
  year: string;
7
7
  status: string;
8
+ pdf_key?: string | null;
8
9
  }
9
10
  /** A question is register-shaped when it asks about certification
10
11
  * standing of an identifiable model or holder — the deterministic
@@ -37,3 +38,7 @@ export declare function searchRegister(db: any, query: string): Promise<{
37
38
  tokens: string[];
38
39
  } | null>;
39
40
  export declare function registerNote(rows: RegisterRow[]): string;
41
+ /** Each certificate's location rides the note as a link when its PDF
42
+ * is in the R2 plane (TODO 7) — the user gets the document, not just
43
+ * the fact. */
44
+ export declare function certificateLinks(rows: RegisterRow[]): string;
@@ -65,9 +65,10 @@ import {
65
65
  sha256Hex
66
66
  } from "./chunk-2PCUAJJO.js";
67
67
  import {
68
+ certificateLinks,
68
69
  registerNote,
69
70
  searchRegister
70
- } from "./chunk-Z6JAGZAM.js";
71
+ } from "./chunk-PCP4AQQQ.js";
71
72
  import {
72
73
  P
73
74
  } from "./chunk-3FYJM7LH.js";
@@ -1891,7 +1892,7 @@ async function runTool(db, call) {
1891
1892
  if (call.name !== "register_search") return null;
1892
1893
  const query = String(call.args?.query ?? "").trim().slice(0, 160);
1893
1894
  if (!query) return null;
1894
- const { searchRegister: searchRegister2, registerNote: registerNote2 } = await import("./certificates-DZJJLRGU.js");
1895
+ const { searchRegister: searchRegister2, registerNote: registerNote2 } = await import("./certificates-7HZZBOPW.js");
1895
1896
  const reg = await searchRegister2(db, query);
1896
1897
  const output = reg?.rows?.length ? registerNote2(reg.rows) : `No certificate was found for "${query}" in the certificates database (the register snapshot). State this as the search's result, with the searched string visible.`;
1897
1898
  return { name: call.name, query, output };
@@ -2313,7 +2314,7 @@ async function handleAsk(env, ctx, req, tier, key) {
2313
2314
  }
2314
2315
  }
2315
2316
  console.log("register-search:", JSON.stringify({ shaped: !!register, tokens: register?.tokens ?? null, rows: register?.rows?.length ?? null, first: register?.rows?.[0]?.num ?? null }));
2316
- const regNote = register ? registerNote(register.rows) : void 0;
2317
+ const regNote = register ? [registerNote(register.rows), certificateLinks(register.rows)].filter(Boolean).join("\n") : void 0;
2317
2318
  if (understanding?.intent === "conversational") {
2318
2319
  const queryHash2 = await sha256Hex(q.query);
2319
2320
  const messages2 = [
@@ -84,7 +84,7 @@ function buildRegisterQuery(tokens) {
84
84
  return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
85
85
  });
86
86
  return {
87
- sql: `SELECT num, family, holder, model, year, status FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
87
+ sql: `SELECT num, family, holder, model, year, status, pdf_key FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
88
88
  params
89
89
  };
90
90
  }
@@ -96,8 +96,9 @@ async function searchRegister(db, query) {
96
96
  let { sql, params } = built;
97
97
  const family = queryFamily(query);
98
98
  if (family) {
99
- sql = sql.replace(" WHERE ", " WHERE family = ?0 AND ");
100
- params.unshift(family);
99
+ sql = sql.replace(/\?(\d+)/g, (_, n) => `?${Number(n) + 1}`);
100
+ sql = sql.replace(" WHERE ", " WHERE family = ?1 AND ");
101
+ params.unshift(family.replace(/^[A-Za-z]+/, ""));
101
102
  }
102
103
  try {
103
104
  const res = await db.prepare(sql).bind(...params).all();
@@ -116,6 +117,11 @@ function registerNote(rows) {
116
117
  ...lines
117
118
  ].join("\n");
118
119
  }
120
+ function certificateLinks(rows) {
121
+ const links = rows.filter((r) => r.pdf_key).map((r) => `- ${r.num}: https://www.oimlsmart.org/cert-pdf/${r.pdf_key}`);
122
+ return links.length ? `The certificates' documents:
123
+ ${links.join("\n")}` : "";
124
+ }
119
125
 
120
126
  export {
121
127
  isRegisterShaped,
@@ -123,5 +129,6 @@ export {
123
129
  registerTokens,
124
130
  buildRegisterQuery,
125
131
  searchRegister,
126
- registerNote
132
+ registerNote,
133
+ certificateLinks
127
134
  };
@@ -6,7 +6,7 @@ import {
6
6
  modelGroundingBlock,
7
7
  scoreFaithfulness,
8
8
  scoreJudge
9
- } from "../../chunk-MNEUEHO7.js";
9
+ } from "../../chunk-OEXJFPNO.js";
10
10
  import {
11
11
  handleSearch
12
12
  } from "../../chunk-FLNX4O7C.js";
@@ -63,7 +63,7 @@ import {
63
63
  sha256Hex,
64
64
  today
65
65
  } from "../../chunk-2PCUAJJO.js";
66
- import "../../chunk-Z6JAGZAM.js";
66
+ import "../../chunk-PCP4AQQQ.js";
67
67
  import {
68
68
  P,
69
69
  setProfile
@@ -959,7 +959,7 @@ async function handleMcp(env, ctx, req, tier, key) {
959
959
  // stream:false forces the JSON lane (anon defaults to SSE)
960
960
  body: JSON.stringify({ ...args, stream: false })
961
961
  });
962
- const res = name === "ask" ? await (await import("../../ask-26DGSVFW.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-PBOODCMQ.js")).handleSearch(env, ctx, inner, tier, key);
962
+ const res = name === "ask" ? await (await import("../../ask-I6DJFZKL.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-PBOODCMQ.js")).handleSearch(env, ctx, inner, tier, key);
963
963
  return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
964
964
  });
965
965
  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.57",
30
+ "version": "0.2.60",
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",
@@ -39,7 +39,7 @@ export type { Env };
39
39
  import { json, err, corsHeaders, readJson, validateQuery, type ApiKey } from "./lib/http";
40
40
  import { clientIp, checkQuota, telemetry } from "./quota";
41
41
  import { graphExpand, editionNote } from "./graph";
42
- import { registerNote, searchRegister } from "./certificates";
42
+ import { registerNote, searchRegister, certificateLinks } from "./certificates";
43
43
  import { TOOL_DECLARATION, parseToolCall, runTool, toolNote } from "./tools";
44
44
  import { extractNameplate, nameplateRegisterQuery } from "./nameplate.ts";
45
45
  import { P } from "./profile.ts";
@@ -637,7 +637,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
637
637
  }
638
638
  }
639
639
  console.log("register-search:", JSON.stringify({ shaped: !!register, tokens: register?.tokens ?? null, rows: register?.rows?.length ?? null, first: register?.rows?.[0]?.num ?? null }));
640
- const regNote = register ? registerNote(register.rows) : undefined;
640
+ const regNote = register ? [registerNote(register.rows), certificateLinks(register.rows)].filter(Boolean).join("\n") : undefined;
641
641
 
642
642
  // Conversational route, decided by query UNDERSTANDING (any language, any
643
643
  // phrasing) — not string matching. No retrieval: nothing in the corpus
@@ -15,6 +15,7 @@ export interface RegisterRow {
15
15
  model: string;
16
16
  year: string;
17
17
  status: string;
18
+ pdf_key?: string | null;
18
19
  }
19
20
 
20
21
  /** A question is register-shaped when it asks about certification
@@ -83,7 +84,7 @@ export function buildRegisterQuery(tokens: string[]): { sql: string; params: str
83
84
  return `(holder LIKE ?${n} OR model LIKE ?${n} OR num LIKE ?${n})`;
84
85
  });
85
86
  return {
86
- sql: `SELECT num, family, holder, model, year, status FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
87
+ sql: `SELECT num, family, holder, model, year, status, pdf_key FROM certificates WHERE ${clauses.join(" OR ")} LIMIT 6`,
87
88
  params,
88
89
  };
89
90
  }
@@ -96,8 +97,13 @@ export async function searchRegister(db: any, query: string): Promise<{ rows: Re
96
97
  let { sql, params } = built;
97
98
  const family = queryFamily(query);
98
99
  if (family) {
99
- sql = sql.replace(" WHERE ", " WHERE family = ?0 AND ");
100
- params.unshift(family);
100
+ // the register's family column is the DIGITS ONLY ("60", "105") —
101
+ // the letter+padding form ("R60") never matched a single row
102
+ // the prepend shifts every token placeholder by one: renumber them,
103
+ // or each token binds the family string and nothing matches
104
+ sql = sql.replace(/\?(\d+)/g, (_, n) => `?${Number(n) + 1}`);
105
+ sql = sql.replace(" WHERE ", " WHERE family = ?1 AND ");
106
+ params.unshift(family.replace(/^[A-Za-z]+/, ""));
101
107
  }
102
108
  try {
103
109
  const res = await db.prepare(sql).bind(...params).all();
@@ -118,3 +124,11 @@ export function registerNote(rows: RegisterRow[]): string {
118
124
  ...lines,
119
125
  ].join("\n");
120
126
  }
127
+ /** Each certificate's location rides the note as a link when its PDF
128
+ * is in the R2 plane (TODO 7) — the user gets the document, not just
129
+ * the fact. */
130
+ export function certificateLinks(rows: RegisterRow[]): string {
131
+ const links = rows.filter((r) => r.pdf_key).map((r) => `- ${r.num}: https://www.oimlsmart.org/cert-pdf/${r.pdf_key}`);
132
+ return links.length ? `The certificates' documents:\n${links.join("\n")}` : "";
133
+ }
134
+