@konneal/engine 0.2.18 → 0.2.20
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-36JS3555.js +12 -0
- package/dist/boundary.d.ts +17 -0
- package/dist/{chunk-EFQALN2Z.js → chunk-BV7IKH3N.js} +2 -2
- package/dist/{chunk-5MBWE7WD.js → chunk-COKARI7O.js} +2 -2
- package/dist/{chunk-7UT76RQO.js → chunk-DGFJUA2C.js} +8 -7
- package/dist/{chunk-PBXE2LFD.js → chunk-EE6V6X6D.js} +82 -18
- package/dist/{chunk-DBBGOOMZ.js → chunk-FNJ457SE.js} +1 -1
- package/dist/{chunk-ADXV2DPK.js → chunk-RESCBSX6.js} +1 -1
- package/dist/{chunk-YFDWKXEB.js → chunk-SLZ4TZNO.js} +4 -4
- package/dist/{chunk-TJRTVJW5.js → chunk-YTWPZE5O.js} +11 -5
- package/dist/drafts.d.ts +1 -1
- package/dist/profile.gen.d.ts +7 -5
- package/dist/profile2.gen.d.ts +2 -0
- package/dist/search-YA6TD6QJ.js +12 -0
- package/dist/worker_mcp/src/index.js +3 -3
- package/dist/worker_public/src/config.js +2 -2
- package/dist/worker_public/src/index.js +10 -10
- package/dist/worker_public/src/profile.js +1 -1
- package/dist/worker_public/src/refusal.js +2 -2
- package/dist/worker_public/src/requestScope.js +3 -3
- package/package.json +1 -1
- package/profile/publisher.yaml +4 -0
- package/profile/sources.yaml +1 -1
- package/workers/worker_public/src/aggregation.ts +6 -5
- package/workers/worker_public/src/ask.ts +25 -4
- package/workers/worker_public/src/auth.ts +1 -1
- package/workers/worker_public/src/boundary.ts +73 -0
- package/workers/worker_public/src/drafts.ts +8 -8
- package/workers/worker_public/src/index.ts +1 -1
- package/workers/worker_public/src/livedata.ts +2 -2
- package/workers/worker_public/src/pipeline.ts +2 -1
- package/workers/worker_public/src/profile.gen.ts +11 -5
- package/workers/worker_public/src/profile2.gen.ts +4 -0
- package/dist/ask-4O753Y4T.js +0 -12
- package/dist/search-RFKT7ZZY.js +0 -12
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleAsk
|
|
3
|
+
} from "./chunk-EE6V6X6D.js";
|
|
4
|
+
import "./chunk-DGFJUA2C.js";
|
|
5
|
+
import "./chunk-BV7IKH3N.js";
|
|
6
|
+
import "./chunk-FNJ457SE.js";
|
|
7
|
+
import "./chunk-COKARI7O.js";
|
|
8
|
+
import "./chunk-RESCBSX6.js";
|
|
9
|
+
import "./chunk-YTWPZE5O.js";
|
|
10
|
+
export {
|
|
11
|
+
handleAsk
|
|
12
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface LicensedEntry {
|
|
2
|
+
key: string;
|
|
3
|
+
package?: string;
|
|
4
|
+
doc_number?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface LicensedMatch {
|
|
8
|
+
entry: LicensedEntry;
|
|
9
|
+
matched: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function distinctiveTokens(title: string): string[];
|
|
12
|
+
/** The licensed entry whose distinctive title tokens best match the
|
|
13
|
+
* question. Needs TWO token hits (or one hyphenated-compound hit) —
|
|
14
|
+
* a single shared word is not a topic match. */
|
|
15
|
+
export declare function matchLicensedTopic(query: string, licensed: LicensedEntry[]): LicensedMatch | null;
|
|
16
|
+
/** The note text: the posture instruction for an unentitled match. */
|
|
17
|
+
export declare function boundaryNoteText(match: LicensedMatch, citing: string[]): string;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LIMITS,
|
|
3
3
|
sha256Hex
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RESCBSX6.js";
|
|
5
5
|
import {
|
|
6
6
|
P
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YTWPZE5O.js";
|
|
8
8
|
|
|
9
9
|
// workers/worker_public/src/bubble.ts
|
|
10
10
|
function isAllowedBubbleOrigin(origin) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DATASETS,
|
|
3
3
|
datasetAllowed
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RESCBSX6.js";
|
|
5
5
|
import {
|
|
6
6
|
P
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YTWPZE5O.js";
|
|
8
8
|
|
|
9
9
|
// workers/worker_public/src/requestScope.ts
|
|
10
10
|
function licenseDeclared() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
bubbleConfirmPage,
|
|
3
3
|
isAllowedBubbleOrigin
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BV7IKH3N.js";
|
|
5
5
|
import {
|
|
6
6
|
DATASETS,
|
|
7
7
|
LIMITS,
|
|
@@ -12,12 +12,12 @@ import {
|
|
|
12
12
|
processExpansion,
|
|
13
13
|
sha256Hex,
|
|
14
14
|
today
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RESCBSX6.js";
|
|
16
16
|
import {
|
|
17
17
|
P,
|
|
18
18
|
__commonJS,
|
|
19
19
|
__toESM
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-YTWPZE5O.js";
|
|
21
21
|
|
|
22
22
|
// node_modules/@oimlsmart/oiml-pubid/dist/index.js
|
|
23
23
|
var require_dist = __commonJS({
|
|
@@ -1939,7 +1939,8 @@ ${context}` }
|
|
|
1939
1939
|
};
|
|
1940
1940
|
}
|
|
1941
1941
|
function publicationUrl(meta) {
|
|
1942
|
-
|
|
1942
|
+
const ownCorpora = P().publisher.catalog_corpora;
|
|
1943
|
+
if (meta.corpus && ownCorpora && !ownCorpora.includes(meta.corpus)) return void 0;
|
|
1943
1944
|
const tpl = P().publisher.catalog_url_template;
|
|
1944
1945
|
if (!tpl || !meta.doctype || !meta.doc_number) return void 0;
|
|
1945
1946
|
return tpl.replace("{type}", meta.doctype.toLowerCase()) + meta.doc_number;
|
|
@@ -2032,9 +2033,9 @@ async function sha256Hex2(s) {
|
|
|
2032
2033
|
function liveDataConfig(env) {
|
|
2033
2034
|
const platformApi = (env.SMART_PLATFORM_API ?? "").trim().replace(/\/$/, "");
|
|
2034
2035
|
const platformClientId = (env.SMART_PLATFORM_CLIENT_ID ?? "").trim();
|
|
2035
|
-
const issuer = (env.OIDC_ISSUER ?? "
|
|
2036
|
+
const issuer = (env.OIDC_ISSUER ?? "").trim().replace(/\/$/, "");
|
|
2036
2037
|
const clientId = (env.OIDC_CLIENT_ID ?? "").trim();
|
|
2037
|
-
if (!platformApi || !platformClientId || !clientId) return null;
|
|
2038
|
+
if (!platformApi || !platformClientId || !clientId || !issuer) return null;
|
|
2038
2039
|
return { platformApi, platformClientId, issuer, clientId, clientSecret: env.OIDC_CLIENT_SECRET };
|
|
2039
2040
|
}
|
|
2040
2041
|
var SUBJECT_KEY = (sessionHash) => `opat:${sessionHash}`;
|
|
@@ -2444,7 +2445,7 @@ function authErrorText(reason) {
|
|
|
2444
2445
|
return PLAIN_LANGUAGE[reason] ?? "Sign-in failed. Please try again.";
|
|
2445
2446
|
}
|
|
2446
2447
|
function authConfig(env) {
|
|
2447
|
-
const issuer = env.OIDC_ISSUER ?? "
|
|
2448
|
+
const issuer = (env.OIDC_ISSUER ?? "").trim().replace(/\/$/, "");
|
|
2448
2449
|
const clientId = env.OIDC_CLIENT_ID;
|
|
2449
2450
|
const redirectUri = env.OIDC_REDIRECT_URI ?? "https://ai.oimlsmart.org/auth/callback";
|
|
2450
2451
|
const sessionSecret = env.SESSION_SECRET;
|
|
@@ -27,23 +27,23 @@ import {
|
|
|
27
27
|
syntheticUnderstanding,
|
|
28
28
|
telemetry,
|
|
29
29
|
understandQuery
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-DGFJUA2C.js";
|
|
31
31
|
import {
|
|
32
32
|
corsHeaders,
|
|
33
33
|
err,
|
|
34
34
|
json,
|
|
35
35
|
readJson,
|
|
36
36
|
validateQuery
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-BV7IKH3N.js";
|
|
38
38
|
import {
|
|
39
39
|
canonicalRefusal,
|
|
40
40
|
refusalAnswer
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-FNJ457SE.js";
|
|
42
42
|
import {
|
|
43
43
|
entitlementScope,
|
|
44
44
|
requestSalt,
|
|
45
45
|
resolveRequestScope
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-COKARI7O.js";
|
|
47
47
|
import {
|
|
48
48
|
LIMITS,
|
|
49
49
|
MODELS,
|
|
@@ -53,10 +53,10 @@ import {
|
|
|
53
53
|
requestEffort,
|
|
54
54
|
roleModel,
|
|
55
55
|
sha256Hex
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-RESCBSX6.js";
|
|
57
57
|
import {
|
|
58
58
|
P
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-YTWPZE5O.js";
|
|
60
60
|
|
|
61
61
|
// workers/worker_public/src/internal_gateway.ts
|
|
62
62
|
async function retrieveInternal(service, auth, query) {
|
|
@@ -883,9 +883,10 @@ function classToken(query) {
|
|
|
883
883
|
return m ? m[1].toLowerCase() : null;
|
|
884
884
|
}
|
|
885
885
|
function classAsColumn(cols, token) {
|
|
886
|
-
const
|
|
886
|
+
const classCols = cols.filter((c) => /^class_[a-z0-9.]+$/.test(c.name));
|
|
887
|
+
const exact = classCols.find((c) => c.name.slice(6) === token);
|
|
887
888
|
if (exact) return exact;
|
|
888
|
-
return
|
|
889
|
+
return classCols.find((c) => c.name.slice(6).startsWith(token));
|
|
889
890
|
}
|
|
890
891
|
function numericColumns(cols) {
|
|
891
892
|
return cols.filter((c) => c.type === "number" || c.type === "integer" || /^class_[a-z0-9.]+$/.test(c.name));
|
|
@@ -1074,9 +1075,57 @@ function evaluateAggregation(nodes, query) {
|
|
|
1074
1075
|
return null;
|
|
1075
1076
|
}
|
|
1076
1077
|
|
|
1078
|
+
// workers/worker_public/src/boundary.ts
|
|
1079
|
+
var TITLE_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1080
|
+
"environmental",
|
|
1081
|
+
"testing",
|
|
1082
|
+
"test",
|
|
1083
|
+
"tests",
|
|
1084
|
+
"guidance",
|
|
1085
|
+
"generic",
|
|
1086
|
+
"standards",
|
|
1087
|
+
"standard",
|
|
1088
|
+
"electromagnetic",
|
|
1089
|
+
"compatibility",
|
|
1090
|
+
"environment",
|
|
1091
|
+
"description",
|
|
1092
|
+
"measurement",
|
|
1093
|
+
"techniques",
|
|
1094
|
+
"immunity",
|
|
1095
|
+
"residential",
|
|
1096
|
+
"commercial",
|
|
1097
|
+
"industrial",
|
|
1098
|
+
"environments",
|
|
1099
|
+
"and",
|
|
1100
|
+
"for",
|
|
1101
|
+
"the",
|
|
1102
|
+
"iec",
|
|
1103
|
+
"iso"
|
|
1104
|
+
]);
|
|
1105
|
+
function distinctiveTokens(title) {
|
|
1106
|
+
return title.toLowerCase().split(/[^a-z0-9.]+/).filter((w) => w.length >= 3 && !TITLE_STOPWORDS.has(w) && !/^[0-9:-]+$/.test(w));
|
|
1107
|
+
}
|
|
1108
|
+
function matchLicensedTopic(query, licensed) {
|
|
1109
|
+
const words = new Set(query.toLowerCase().split(/[^a-z0-9.]+/).filter(Boolean));
|
|
1110
|
+
let best = null;
|
|
1111
|
+
for (const entry of licensed) {
|
|
1112
|
+
if (!entry.title) continue;
|
|
1113
|
+
const matched = distinctiveTokens(entry.title).filter((w) => words.has(w));
|
|
1114
|
+
if (matched.length < 2) continue;
|
|
1115
|
+
if (!best || matched.length > best.matched.length) best = { entry, matched };
|
|
1116
|
+
}
|
|
1117
|
+
return best;
|
|
1118
|
+
}
|
|
1119
|
+
function boundaryNoteText(match, citing) {
|
|
1120
|
+
const doc = match.entry.doc_number ?? match.entry.key;
|
|
1121
|
+
const title = match.entry.title ?? doc;
|
|
1122
|
+
const refs = citing.length ? `The public corpus references it from ${citing.join(", ")}.` : "";
|
|
1123
|
+
return `LICENSED BOUNDARY \u2014 ${title} (IEC ${doc}) is licensed content in this deployment; its procedure is NOT part of the public corpus you are grounded in. ${refs} When answering: name the licensed document as the authoritative source of the procedure and say it is available to entitled callers. Do NOT state its conditioning or severity parameters in ANY form \u2014 no temperatures, humidity levels, durations or cycle counts, not even as a single bound or as a value another publication repeats or cites; keep the description structural (expose, condition, recover) and let the licensed document own the numbers. If the grounding passages state parameter values, say only that the publications describe their own requirements and that the procedure's parameters are in the licensed document.`;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1077
1126
|
// workers/worker_public/src/drafts.ts
|
|
1078
1127
|
var ACT_VERB = "(?:draft|prepare|pre-?fill|fill\\s+(?:in|out)|start|submit|file|lodge)";
|
|
1079
|
-
var ACT_TARGET = "(?:new\\s+)?(?:certification\\s+|type[ -]evaluation\\s
|
|
1128
|
+
var ACT_TARGET = "(?:new\\s+)?(?:certification\\s+|type[ -]evaluation\\s+)?application";
|
|
1080
1129
|
var INTENT_RES = [
|
|
1081
1130
|
new RegExp(`\\b${ACT_VERB}\\b[\\s\\S]{0,60}?\\b${ACT_TARGET}\\b`, "i"),
|
|
1082
1131
|
new RegExp(`\\b${ACT_TARGET}\\b[\\s\\S]{0,30}?\\b(?:draft|prepare|pre-?fill|for me)\\b`, "i")
|
|
@@ -1101,18 +1150,18 @@ function roleLabel(role) {
|
|
|
1101
1150
|
if (["cs_admin", "admin"].includes(role)) return "a scheme administrator";
|
|
1102
1151
|
return `the "${role}" role`;
|
|
1103
1152
|
}
|
|
1104
|
-
var EXTRACTION_SYSTEM = `You extract the fields of a new
|
|
1153
|
+
var EXTRACTION_SYSTEM = `You extract the fields of a new certification application from the user's own messages.
|
|
1105
1154
|
|
|
1106
1155
|
Rules:
|
|
1107
1156
|
- Output ONLY a JSON object \u2014 no prose, no code fence.
|
|
1108
1157
|
- Copy every value from the user's own words, and for each field give "source": the exact contiguous span of the user's message you copied it from.
|
|
1109
1158
|
- NEVER infer, complete, normalize away, or guess a value. If the user did not state it, omit the field entirely.
|
|
1110
|
-
- "standard": the
|
|
1159
|
+
- "standard": the publication the user named (e.g. "AB 99" or "ACME AB 99:2019") \u2014 a plain string, or omit when none was named.
|
|
1111
1160
|
- "scheme": only when the user named scheme A or scheme B explicitly.
|
|
1112
1161
|
|
|
1113
1162
|
Schema (every field optional):
|
|
1114
1163
|
{
|
|
1115
|
-
"standard": "
|
|
1164
|
+
"standard": "AB 99",
|
|
1116
1165
|
"family_designation": { "value": "\u2026", "source": "\u2026" },
|
|
1117
1166
|
"group_label": { "value": "\u2026", "source": "\u2026" },
|
|
1118
1167
|
"model_designation": { "value": "\u2026", "source": "\u2026" },
|
|
@@ -1275,14 +1324,14 @@ async function prepareDraft(env, opts) {
|
|
|
1275
1324
|
const untraced = dropped.find((d) => d.field === "standard");
|
|
1276
1325
|
return refusal(
|
|
1277
1326
|
"standard_unresolved",
|
|
1278
|
-
untraced ? `I can't anchor the draft: you haven't named the Recommendation in your own words (the ${untraced.value} reading isn't yours). Name it plainly \u2014 for example
|
|
1327
|
+
untraced ? `I can't anchor the draft: you haven't named the Recommendation in your own words (the ${untraced.value} reading isn't yours). Name it plainly \u2014 for example ACME AB 99 \u2014 and I'll prepare the draft.` : "I can't anchor the draft: you haven't named the publication. Name it plainly \u2014 for example ACME AB 99 \u2014 and I'll prepare it."
|
|
1279
1328
|
);
|
|
1280
1329
|
}
|
|
1281
1330
|
const standard = await resolveStandard(env, kept.standard);
|
|
1282
1331
|
if (!standard) {
|
|
1283
1332
|
return refusal(
|
|
1284
1333
|
"standard_unresolved",
|
|
1285
|
-
`I couldn't resolve ${kept.standard} as a publication in the corpus, so I can't anchor the draft. Name the
|
|
1334
|
+
`I couldn't resolve ${kept.standard} as a publication in the corpus, so I can't anchor the draft. Name the publication plainly \u2014 for example ACME AB 99 \u2014 and I'll prepare it.`
|
|
1286
1335
|
);
|
|
1287
1336
|
}
|
|
1288
1337
|
const fields = {
|
|
@@ -1904,7 +1953,7 @@ ${summary}` }] : [],
|
|
|
1904
1953
|
const verdictBlock = machineVerdict ? {
|
|
1905
1954
|
unit_id: boundModel.node_id,
|
|
1906
1955
|
type: "verdict",
|
|
1907
|
-
docidentifier: `${P().publisher.name}
|
|
1956
|
+
docidentifier: `${P().publisher.name} model (${boundModel.standard})`,
|
|
1908
1957
|
payload: {
|
|
1909
1958
|
verdict: machineVerdict.verdict,
|
|
1910
1959
|
on_violation: machineVerdict.on_violation,
|
|
@@ -1917,7 +1966,7 @@ ${summary}` }] : [],
|
|
|
1917
1966
|
const conditionBlock = conditionVerdict ? {
|
|
1918
1967
|
unit_id: conditionVerdict.matched[0] ?? conditionVerdict.nearest.node_id,
|
|
1919
1968
|
type: "verdict",
|
|
1920
|
-
docidentifier:
|
|
1969
|
+
docidentifier: `${P().publisher.name} model (${conditionStandard})`,
|
|
1921
1970
|
payload: {
|
|
1922
1971
|
verdict: conditionVerdict.verdict,
|
|
1923
1972
|
missing: [],
|
|
@@ -1952,7 +2001,7 @@ ${summary}` }] : [],
|
|
|
1952
2001
|
const aggregationBlock = aggregationVerdict ? {
|
|
1953
2002
|
unit_id: aggregationVerdict.table,
|
|
1954
2003
|
type: "verdict",
|
|
1955
|
-
docidentifier:
|
|
2004
|
+
docidentifier: `${P().publisher.name} model table${aggregationStandard ? ` (${aggregationStandard})` : ""}`,
|
|
1956
2005
|
payload: {
|
|
1957
2006
|
check: `${aggregationVerdict.operation}: ${aggregationVerdict.column ?? aggregationVerdict.table_title ?? aggregationVerdict.table} = ${aggregationVerdict.value}${aggregationVerdict.unit ? ` ${aggregationVerdict.unit}` : ""}`,
|
|
1958
2007
|
meaning: aggregationVerdict.table_title,
|
|
@@ -1963,6 +2012,21 @@ ${summary}` }] : [],
|
|
|
1963
2012
|
}
|
|
1964
2013
|
} : null;
|
|
1965
2014
|
if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "\u2192", aggregationVerdict.value);
|
|
2015
|
+
let boundaryNote = null;
|
|
2016
|
+
if (P().sources?.licensed?.length) {
|
|
2017
|
+
const match = matchLicensedTopic(q.query, P().sources.licensed);
|
|
2018
|
+
if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
|
|
2019
|
+
const docNum = match.entry.doc_number ?? "";
|
|
2020
|
+
let citing = [];
|
|
2021
|
+
if (docNum) {
|
|
2022
|
+
const rows = await env.DB.prepare(
|
|
2023
|
+
"SELECT n.label AS label FROM graph_edges e JOIN graph_nodes n ON e.src = n.id WHERE e.kind = 'cites' AND e.dst LIKE ?1 LIMIT 4"
|
|
2024
|
+
).bind(`%${docNum}%`).all().catch(() => ({ results: [] }));
|
|
2025
|
+
citing = (rows.results ?? []).map((r) => String(r.label ?? "").replace(/^doc:/, ""));
|
|
2026
|
+
}
|
|
2027
|
+
boundaryNote = boundaryNoteText(match, citing);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
1966
2030
|
try {
|
|
1967
2031
|
const tR = Date.now();
|
|
1968
2032
|
if (declaredCtx?.kind === "account") {
|
|
@@ -2056,7 +2120,7 @@ Answer account questions from these records ONLY: name the record when you use i
|
|
|
2056
2120
|
q.lang,
|
|
2057
2121
|
keptHistory,
|
|
2058
2122
|
// stage-extracted graph facts (GraphRAG) ride the same note channel
|
|
2059
|
-
[processNote, eNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, licenseNote, ...retrieved.notes ?? []].filter(Boolean).join("\n") || void 0,
|
|
2123
|
+
[processNote, eNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, boundaryNote, licenseNote, ...retrieved.notes ?? []].filter(Boolean).join("\n") || void 0,
|
|
2060
2124
|
summary,
|
|
2061
2125
|
budget
|
|
2062
2126
|
);
|
|
@@ -7,24 +7,24 @@ import {
|
|
|
7
7
|
sessionFrom,
|
|
8
8
|
telemetry,
|
|
9
9
|
understandQuery
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DGFJUA2C.js";
|
|
11
11
|
import {
|
|
12
12
|
corsHeaders,
|
|
13
13
|
err,
|
|
14
14
|
json,
|
|
15
15
|
readJson,
|
|
16
16
|
validateQuery
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BV7IKH3N.js";
|
|
18
18
|
import {
|
|
19
19
|
entitlementScope,
|
|
20
20
|
standardKeysFrom
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-COKARI7O.js";
|
|
22
22
|
import {
|
|
23
23
|
LIMITS,
|
|
24
24
|
MODELS,
|
|
25
25
|
num,
|
|
26
26
|
sha256Hex
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-RESCBSX6.js";
|
|
28
28
|
|
|
29
29
|
// workers/worker_public/src/search.ts
|
|
30
30
|
async function handleSearch(env, ctx, req, tier, key) {
|
|
@@ -48,6 +48,12 @@ var PROFILE = {
|
|
|
48
48
|
"references": {
|
|
49
49
|
"label_prefix": ""
|
|
50
50
|
},
|
|
51
|
+
"catalog_url_template": "https://catalog.fixture.example.org/{type}",
|
|
52
|
+
"catalog_corpora": [
|
|
53
|
+
"pub",
|
|
54
|
+
"dirty",
|
|
55
|
+
"clean"
|
|
56
|
+
],
|
|
51
57
|
"features": {
|
|
52
58
|
"drafts": false,
|
|
53
59
|
"model_plane": false
|
|
@@ -109,11 +115,11 @@ var PROFILE = {
|
|
|
109
115
|
"models": {},
|
|
110
116
|
"licensed": [
|
|
111
117
|
{
|
|
112
|
-
"key": "std:fixture-
|
|
113
|
-
"package": "fixture-
|
|
114
|
-
"doc_number": "
|
|
115
|
-
"title": "FIXTURE
|
|
116
|
-
"edition": "
|
|
118
|
+
"key": "std:fixture-ab-99",
|
|
119
|
+
"package": "fixture-ab-99",
|
|
120
|
+
"doc_number": "ab-99",
|
|
121
|
+
"title": "FIXTURE climatic conditioning, cyclic humidity",
|
|
122
|
+
"edition": "2019"
|
|
117
123
|
}
|
|
118
124
|
]
|
|
119
125
|
},
|
package/dist/drafts.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface DraftSample {
|
|
|
5
5
|
export interface ApplicationPrefillFields {
|
|
6
6
|
/** the Recommendation, as the estate URN (urn:oiml:pub:r:60:2021) */
|
|
7
7
|
standard_doc: string;
|
|
8
|
-
/** display label ("
|
|
8
|
+
/** display label ("ACME AB 99:2019") */
|
|
9
9
|
standard_label?: string;
|
|
10
10
|
family_designation?: string;
|
|
11
11
|
group_label?: string;
|
package/dist/profile.gen.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export declare const PROFILE: {
|
|
|
17
17
|
readonly references: {
|
|
18
18
|
readonly label_prefix: "";
|
|
19
19
|
};
|
|
20
|
+
readonly catalog_url_template: "https://catalog.fixture.example.org/{type}";
|
|
21
|
+
readonly catalog_corpora: readonly ["pub", "dirty", "clean"];
|
|
20
22
|
readonly features: {
|
|
21
23
|
readonly drafts: false;
|
|
22
24
|
readonly model_plane: false;
|
|
@@ -55,11 +57,11 @@ export declare const PROFILE: {
|
|
|
55
57
|
readonly terminology: {};
|
|
56
58
|
readonly models: {};
|
|
57
59
|
readonly licensed: readonly [{
|
|
58
|
-
readonly key: "std:fixture-
|
|
59
|
-
readonly package: "fixture-
|
|
60
|
-
readonly doc_number: "
|
|
61
|
-
readonly title: "FIXTURE
|
|
62
|
-
readonly edition: "
|
|
60
|
+
readonly key: "std:fixture-ab-99";
|
|
61
|
+
readonly package: "fixture-ab-99";
|
|
62
|
+
readonly doc_number: "ab-99";
|
|
63
|
+
readonly title: "FIXTURE climatic conditioning, cyclic humidity";
|
|
64
|
+
readonly edition: "2019";
|
|
63
65
|
}];
|
|
64
66
|
};
|
|
65
67
|
readonly ui: {
|
package/dist/profile2.gen.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare const PROFILE: {
|
|
|
22
22
|
readonly review: readonly ["review"];
|
|
23
23
|
readonly glossary: readonly ["glossary"];
|
|
24
24
|
};
|
|
25
|
+
readonly catalog_url_template: "https://catalog.atlas.example/{type}";
|
|
26
|
+
readonly catalog_corpora: readonly ["spec"];
|
|
25
27
|
readonly features: {
|
|
26
28
|
readonly drafts: false;
|
|
27
29
|
readonly model_plane: false;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleSearch
|
|
3
|
+
} from "./chunk-SLZ4TZNO.js";
|
|
4
|
+
import "./chunk-DGFJUA2C.js";
|
|
5
|
+
import "./chunk-BV7IKH3N.js";
|
|
6
|
+
import "./chunk-FNJ457SE.js";
|
|
7
|
+
import "./chunk-COKARI7O.js";
|
|
8
|
+
import "./chunk-RESCBSX6.js";
|
|
9
|
+
import "./chunk-YTWPZE5O.js";
|
|
10
|
+
export {
|
|
11
|
+
handleSearch
|
|
12
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
authenticate
|
|
3
|
-
} from "../../chunk-
|
|
4
|
-
import "../../chunk-
|
|
3
|
+
} from "../../chunk-BV7IKH3N.js";
|
|
4
|
+
import "../../chunk-RESCBSX6.js";
|
|
5
5
|
import {
|
|
6
6
|
P,
|
|
7
7
|
setProfile
|
|
8
|
-
} from "../../chunk-
|
|
8
|
+
} from "../../chunk-YTWPZE5O.js";
|
|
9
9
|
|
|
10
10
|
// workers/worker_mcp/src/index.ts
|
|
11
11
|
var PROTOCOL_VERSION = "2025-06-18";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleSearch
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-SLZ4TZNO.js";
|
|
4
4
|
import {
|
|
5
5
|
checkQuoteAnchors,
|
|
6
6
|
handleAsk,
|
|
7
7
|
handleMemories,
|
|
8
8
|
scoreJudge,
|
|
9
9
|
standardForDocNumber
|
|
10
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-EE6V6X6D.js";
|
|
11
11
|
import {
|
|
12
12
|
buildMessages,
|
|
13
13
|
citations,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
sessionFrom,
|
|
30
30
|
telemetry,
|
|
31
31
|
understandQuery
|
|
32
|
-
} from "../../chunk-
|
|
32
|
+
} from "../../chunk-DGFJUA2C.js";
|
|
33
33
|
import {
|
|
34
34
|
authenticate,
|
|
35
35
|
corsHeaders,
|
|
@@ -38,14 +38,14 @@ import {
|
|
|
38
38
|
readJson,
|
|
39
39
|
validateQuery,
|
|
40
40
|
withCors
|
|
41
|
-
} from "../../chunk-
|
|
41
|
+
} from "../../chunk-BV7IKH3N.js";
|
|
42
42
|
import {
|
|
43
43
|
canonicalRefusal
|
|
44
|
-
} from "../../chunk-
|
|
44
|
+
} from "../../chunk-FNJ457SE.js";
|
|
45
45
|
import {
|
|
46
46
|
entitlementScope,
|
|
47
47
|
standardKeysFrom
|
|
48
|
-
} from "../../chunk-
|
|
48
|
+
} from "../../chunk-COKARI7O.js";
|
|
49
49
|
import {
|
|
50
50
|
LIMITS,
|
|
51
51
|
MODELS,
|
|
@@ -56,11 +56,11 @@ import {
|
|
|
56
56
|
roleModel,
|
|
57
57
|
sha256Hex,
|
|
58
58
|
today
|
|
59
|
-
} from "../../chunk-
|
|
59
|
+
} from "../../chunk-RESCBSX6.js";
|
|
60
60
|
import {
|
|
61
61
|
P,
|
|
62
62
|
setProfile
|
|
63
|
-
} from "../../chunk-
|
|
63
|
+
} from "../../chunk-YTWPZE5O.js";
|
|
64
64
|
|
|
65
65
|
// workers/worker_public/src/conversations.ts
|
|
66
66
|
var ID_RE = /^[a-zA-Z0-9_-]{8,64}$/;
|
|
@@ -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-36JS3555.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-YA6TD6QJ.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 });
|
|
@@ -1404,7 +1404,7 @@ async function absenceRoute(c) {
|
|
|
1404
1404
|
const namedStd = namedDocumentIn(String(body?.standard ?? ""));
|
|
1405
1405
|
const standard = standardForDocNumber(namedStd?.doc_number ?? String(body?.standard ?? "").trim());
|
|
1406
1406
|
const topic = String(body?.topic ?? "").trim().toLowerCase();
|
|
1407
|
-
if (!standard || !topic) return err(400, "invalid_input",
|
|
1407
|
+
if (!standard || !topic) return err(400, "invalid_input", "standard and topic are required");
|
|
1408
1408
|
try {
|
|
1409
1409
|
const nodes = (await env.DB.prepare("SELECT node_id, kind, name, content FROM model_nodes WHERE standard = ?1").bind(standard).all()).results ?? [];
|
|
1410
1410
|
const tokens = topic.split(/\s+/).filter((t2) => t2.length > 2);
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
requestSalt,
|
|
5
5
|
resolveRequestScope,
|
|
6
6
|
standardKeysFrom
|
|
7
|
-
} from "../../chunk-
|
|
8
|
-
import "../../chunk-
|
|
9
|
-
import "../../chunk-
|
|
7
|
+
} from "../../chunk-COKARI7O.js";
|
|
8
|
+
import "../../chunk-RESCBSX6.js";
|
|
9
|
+
import "../../chunk-YTWPZE5O.js";
|
|
10
10
|
export {
|
|
11
11
|
entitlementScope,
|
|
12
12
|
licenseDeclared,
|
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.20",
|
|
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",
|
package/profile/publisher.yaml
CHANGED
|
@@ -19,6 +19,10 @@ codec: plain-slug
|
|
|
19
19
|
session_cookie: fixture-session
|
|
20
20
|
references:
|
|
21
21
|
label_prefix: ""
|
|
22
|
+
# the publisher's catalog page ({type} = lowercase doctype) and the
|
|
23
|
+
# corpora the catalog covers (foreign-corpus chunks get no catalog link)
|
|
24
|
+
catalog_url_template: "https://catalog.fixture.example.org/{type}"
|
|
25
|
+
catalog_corpora: [pub, dirty, clean]
|
|
22
26
|
# engine features this deployment switches on (default: off — the
|
|
23
27
|
# engine serves every publisher without them)
|
|
24
28
|
features:
|
package/profile/sources.yaml
CHANGED
|
@@ -11,4 +11,4 @@ models: {}
|
|
|
11
11
|
# Absent or empty = the deployment serves public content only. The
|
|
12
12
|
# fixture declares one so the license scope rides every engine test.
|
|
13
13
|
licensed:
|
|
14
|
-
- { key: "std:fixture-
|
|
14
|
+
- { key: "std:fixture-ab-99", package: "fixture-ab-99", doc_number: "ab-99", title: "FIXTURE climatic conditioning, cyclic humidity", edition: "2019" }
|
|
@@ -73,13 +73,14 @@ function classToken(query: string): string | null {
|
|
|
73
73
|
return m ? m[1]!.toLowerCase() : null;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
/** The class columns shaped `
|
|
77
|
-
*
|
|
76
|
+
/** The class columns shaped `class_<id>` — classes as COLUMNS rather
|
|
77
|
+
* than as row values. Exact id first; a column whose suffix STARTS WITH
|
|
78
|
+
* the token serves compound class ids sharing one column (c → cd). */
|
|
78
79
|
function classAsColumn(cols: Column[], token: string): Column | undefined {
|
|
79
|
-
const
|
|
80
|
+
const classCols = cols.filter((c) => /^class_[a-z0-9.]+$/.test(c.name));
|
|
81
|
+
const exact = classCols.find((c) => c.name.slice(6) === token);
|
|
80
82
|
if (exact) return exact;
|
|
81
|
-
|
|
82
|
-
return cols.find((c) => /^class_[a-z0-9.]+$/.test(c.name) && c.name.slice(6) === "cd" && (token === "c" || token === "d"));
|
|
83
|
+
return classCols.find((c) => c.name.slice(6).startsWith(token));
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
function numericColumns(cols: Column[]): Column[] {
|
|
@@ -23,6 +23,7 @@ import { bindModelNode, licenseBoundaryNote, licenseBoundaryRefusal, licensedEnt
|
|
|
23
23
|
import { evaluate as machineEvaluate, verdictNote } from "./verdict";
|
|
24
24
|
import { evaluateConditionSets, quantitiesIn, type ConditionVerdict } from "./conditions";
|
|
25
25
|
import { evaluateAggregation, type AggregationVerdict } from "./aggregation";
|
|
26
|
+
import { matchLicensedTopic, boundaryNoteText } from "./boundary";
|
|
26
27
|
import { detectDraftIntent, prepareDraft } from "./drafts";
|
|
27
28
|
import { memoryNote } from "./memories";
|
|
28
29
|
import { entitlementScope, resolveRequestScope, requestSalt } from "./requestScope";
|
|
@@ -773,7 +774,7 @@ async function handleAsk(
|
|
|
773
774
|
? {
|
|
774
775
|
unit_id: boundModel!.node_id,
|
|
775
776
|
type: "verdict",
|
|
776
|
-
docidentifier: `${P().publisher.name}
|
|
777
|
+
docidentifier: `${P().publisher.name} model (${boundModel!.standard})`,
|
|
777
778
|
payload: {
|
|
778
779
|
verdict: machineVerdict.verdict,
|
|
779
780
|
on_violation: machineVerdict.on_violation,
|
|
@@ -788,7 +789,7 @@ async function handleAsk(
|
|
|
788
789
|
? {
|
|
789
790
|
unit_id: conditionVerdict.matched[0] ?? conditionVerdict.nearest!.node_id,
|
|
790
791
|
type: "verdict",
|
|
791
|
-
docidentifier:
|
|
792
|
+
docidentifier: `${P().publisher.name} model (${conditionStandard})`,
|
|
792
793
|
payload: {
|
|
793
794
|
verdict: conditionVerdict.verdict,
|
|
794
795
|
missing: [],
|
|
@@ -834,7 +835,7 @@ async function handleAsk(
|
|
|
834
835
|
? {
|
|
835
836
|
unit_id: aggregationVerdict.table,
|
|
836
837
|
type: "verdict",
|
|
837
|
-
docidentifier:
|
|
838
|
+
docidentifier: `${P().publisher.name} model table${aggregationStandard ? ` (${aggregationStandard})` : ""}`,
|
|
838
839
|
payload: {
|
|
839
840
|
check: `${aggregationVerdict.operation}: ${aggregationVerdict.column ?? aggregationVerdict.table_title ?? aggregationVerdict.table} = ${aggregationVerdict.value}${aggregationVerdict.unit ? ` ${aggregationVerdict.unit}` : ""}`,
|
|
840
841
|
meaning: aggregationVerdict.table_title,
|
|
@@ -846,6 +847,26 @@ async function handleAsk(
|
|
|
846
847
|
}
|
|
847
848
|
: null;
|
|
848
849
|
if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "→", aggregationVerdict.value);
|
|
850
|
+
// ── the licensed boundary note (TODO.rag/12): an unentitled question
|
|
851
|
+
// that is topically ABOUT a licensed standard gets the boundary
|
|
852
|
+
// posture — the citation graph names the public publications that
|
|
853
|
+
// reference the licensed document, and the note instructs the model
|
|
854
|
+
// to attribute, never to recite the licensed parameters.
|
|
855
|
+
let boundaryNote: string | null = null;
|
|
856
|
+
if (P().sources?.licensed?.length) {
|
|
857
|
+
const match = matchLicensedTopic(q.query, P().sources.licensed);
|
|
858
|
+
if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
|
|
859
|
+
const docNum = match.entry.doc_number ?? "";
|
|
860
|
+
let citing: string[] = [];
|
|
861
|
+
if (docNum) {
|
|
862
|
+
const rows = await env.DB.prepare(
|
|
863
|
+
"SELECT n.label AS label FROM graph_edges e JOIN graph_nodes n ON e.src = n.id WHERE e.kind = 'cites' AND e.dst LIKE ?1 LIMIT 4",
|
|
864
|
+
).bind(`%${docNum}%`).all().catch(() => ({ results: [] }));
|
|
865
|
+
citing = (rows.results ?? []).map((r: any) => String(r.label ?? "").replace(/^doc:/, ""));
|
|
866
|
+
}
|
|
867
|
+
boundaryNote = boundaryNoteText(match, citing);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
849
870
|
try {
|
|
850
871
|
const tR = Date.now();
|
|
851
872
|
// ── The "my account" live read (TODO.ai-platform/03) — resolved
|
|
@@ -995,7 +1016,7 @@ async function handleAsk(
|
|
|
995
1016
|
q.lang,
|
|
996
1017
|
keptHistory,
|
|
997
1018
|
// stage-extracted graph facts (GraphRAG) ride the same note channel
|
|
998
|
-
[processNote, eNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, licenseNote, ...(retrieved.notes ?? [])].filter(Boolean).join("\n") || undefined,
|
|
1019
|
+
[processNote, eNote, contextNote(declaredCtx, docScope), accountNote, modelNote, vocabNote, memNote, machineNote, conditionNote, aggregationNote, boundaryNote, licenseNote, ...(retrieved.notes ?? [])].filter(Boolean).join("\n") || undefined,
|
|
999
1020
|
summary,
|
|
1000
1021
|
budget,
|
|
1001
1022
|
);
|
|
@@ -48,7 +48,7 @@ export interface AuthConfig {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function authConfig(env: any): AuthConfig | null {
|
|
51
|
-
const issuer = env.OIDC_ISSUER ?? "
|
|
51
|
+
const issuer = (env.OIDC_ISSUER ?? "").trim().replace(/\/$/, "");
|
|
52
52
|
const clientId = env.OIDC_CLIENT_ID;
|
|
53
53
|
const redirectUri = env.OIDC_REDIRECT_URI ?? "https://ai.oimlsmart.org/auth/callback";
|
|
54
54
|
const sessionSecret = env.SESSION_SECRET;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// The licensed boundary note (TODO.rag/12): when a question is about a
|
|
2
|
+
// topic that matches a LICENSED standard the caller is not entitled to,
|
|
3
|
+
// the note gives the answer model the boundary posture — name the
|
|
4
|
+
// licensed document as the authoritative procedure, name the public
|
|
5
|
+
// publications that reference it, and never recite the licensed
|
|
6
|
+
// parameters as if from the source. Pure matching/text lives here; the
|
|
7
|
+
// inverse-cites D1 read lives at the call site.
|
|
8
|
+
|
|
9
|
+
export interface LicensedEntry {
|
|
10
|
+
key: string;
|
|
11
|
+
package?: string;
|
|
12
|
+
doc_number?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface LicensedMatch {
|
|
17
|
+
entry: LicensedEntry;
|
|
18
|
+
matched: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// title words that carry no topical identity — a question about "tests"
|
|
22
|
+
// or "immunity" must not alone light the boundary
|
|
23
|
+
const TITLE_STOPWORDS = new Set([
|
|
24
|
+
"environmental", "testing", "test", "tests", "guidance", "generic",
|
|
25
|
+
"standards", "standard", "electromagnetic", "compatibility",
|
|
26
|
+
"environment", "description", "measurement", "techniques", "immunity",
|
|
27
|
+
"residential", "commercial", "industrial", "environments", "and", "for", "the",
|
|
28
|
+
"iec", "iso",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
export function distinctiveTokens(title: string): string[] {
|
|
32
|
+
return title
|
|
33
|
+
.toLowerCase()
|
|
34
|
+
.split(/[^a-z0-9.]+/)
|
|
35
|
+
.filter((w) => w.length >= 3 && !TITLE_STOPWORDS.has(w) && !/^[0-9:-]+$/.test(w));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The licensed entry whose distinctive title tokens best match the
|
|
39
|
+
* question. Needs TWO token hits (or one hyphenated-compound hit) —
|
|
40
|
+
* a single shared word is not a topic match. */
|
|
41
|
+
export function matchLicensedTopic(query: string, licensed: LicensedEntry[]): LicensedMatch | null {
|
|
42
|
+
const words = new Set(query.toLowerCase().split(/[^a-z0-9.]+/).filter(Boolean));
|
|
43
|
+
let best: { entry: LicensedEntry; matched: string[] } | null = null;
|
|
44
|
+
for (const entry of licensed) {
|
|
45
|
+
if (!entry.title) continue;
|
|
46
|
+
const matched = distinctiveTokens(entry.title).filter((w) => words.has(w));
|
|
47
|
+
if (matched.length < 2) continue;
|
|
48
|
+
if (!best || matched.length > best.matched.length) best = { entry, matched };
|
|
49
|
+
}
|
|
50
|
+
return best;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The note text: the posture instruction for an unentitled match. */
|
|
54
|
+
export function boundaryNoteText(match: LicensedMatch, citing: string[]): string {
|
|
55
|
+
const doc = match.entry.doc_number ?? match.entry.key;
|
|
56
|
+
const title = match.entry.title ?? doc;
|
|
57
|
+
const refs = citing.length
|
|
58
|
+
? `The public corpus references it from ${citing.join(", ")}.`
|
|
59
|
+
: "";
|
|
60
|
+
return (
|
|
61
|
+
`LICENSED BOUNDARY — ${title} (IEC ${doc}) is licensed content in this ` +
|
|
62
|
+
`deployment; its procedure is NOT part of the public corpus you are grounded in. ` +
|
|
63
|
+
`${refs} When answering: name the licensed document as the authoritative source of ` +
|
|
64
|
+
`the procedure and say it is available to entitled callers. Do NOT state its ` +
|
|
65
|
+
`conditioning or severity parameters in ANY form — no temperatures, humidity ` +
|
|
66
|
+
`levels, durations or cycle counts, not even as a single bound or as a value ` +
|
|
67
|
+
`another publication repeats or cites; keep the description structural (expose, ` +
|
|
68
|
+
`condition, recover) and let the licensed document own the numbers. If the ` +
|
|
69
|
+
`grounding passages state parameter values, say only that the publications ` +
|
|
70
|
+
`describe their own requirements and that the procedure's parameters are in the ` +
|
|
71
|
+
`licensed document.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -48,7 +48,7 @@ export interface DraftSample {
|
|
|
48
48
|
export interface ApplicationPrefillFields {
|
|
49
49
|
/** the Recommendation, as the estate URN (urn:oiml:pub:r:60:2021) */
|
|
50
50
|
standard_doc: string;
|
|
51
|
-
/** display label ("
|
|
51
|
+
/** display label ("ACME AB 99:2019") */
|
|
52
52
|
standard_label?: string;
|
|
53
53
|
family_designation?: string;
|
|
54
54
|
group_label?: string;
|
|
@@ -124,7 +124,7 @@ export interface PrepareOpts {
|
|
|
124
124
|
// performs).
|
|
125
125
|
|
|
126
126
|
const ACT_VERB = "(?:draft|prepare|pre-?fill|fill\\s+(?:in|out)|start|submit|file|lodge)";
|
|
127
|
-
const ACT_TARGET = "(?:new\\s+)?(?:certification\\s+|type[ -]evaluation\\s
|
|
127
|
+
const ACT_TARGET = "(?:new\\s+)?(?:certification\\s+|type[ -]evaluation\\s+)?application";
|
|
128
128
|
const INTENT_RES = [
|
|
129
129
|
new RegExp(`\\b${ACT_VERB}\\b[\\s\\S]{0,60}?\\b${ACT_TARGET}\\b`, "i"),
|
|
130
130
|
new RegExp(`\\b${ACT_TARGET}\\b[\\s\\S]{0,30}?\\b(?:draft|prepare|pre-?fill|for me)\\b`, "i"),
|
|
@@ -165,18 +165,18 @@ function roleLabel(role: string): string {
|
|
|
165
165
|
|
|
166
166
|
// ── the extraction (the LLM proposes) ────────────────────────────────
|
|
167
167
|
|
|
168
|
-
const EXTRACTION_SYSTEM = `You extract the fields of a new
|
|
168
|
+
const EXTRACTION_SYSTEM = `You extract the fields of a new certification application from the user's own messages.
|
|
169
169
|
|
|
170
170
|
Rules:
|
|
171
171
|
- Output ONLY a JSON object — no prose, no code fence.
|
|
172
172
|
- Copy every value from the user's own words, and for each field give "source": the exact contiguous span of the user's message you copied it from.
|
|
173
173
|
- NEVER infer, complete, normalize away, or guess a value. If the user did not state it, omit the field entirely.
|
|
174
|
-
- "standard": the
|
|
174
|
+
- "standard": the publication the user named (e.g. "AB 99" or "ACME AB 99:2019") — a plain string, or omit when none was named.
|
|
175
175
|
- "scheme": only when the user named scheme A or scheme B explicitly.
|
|
176
176
|
|
|
177
177
|
Schema (every field optional):
|
|
178
178
|
{
|
|
179
|
-
"standard": "
|
|
179
|
+
"standard": "AB 99",
|
|
180
180
|
"family_designation": { "value": "…", "source": "…" },
|
|
181
181
|
"group_label": { "value": "…", "source": "…" },
|
|
182
182
|
"model_designation": { "value": "…", "source": "…" },
|
|
@@ -428,8 +428,8 @@ export async function prepareDraft(env: any, opts: PrepareOpts): Promise<DraftVe
|
|
|
428
428
|
"standard_unresolved",
|
|
429
429
|
untraced
|
|
430
430
|
? `I can't anchor the draft: you haven't named the Recommendation in your own words (the ${untraced.value} reading isn't yours). ` +
|
|
431
|
-
"Name it plainly — for example
|
|
432
|
-
: "I can't anchor the draft: you haven't named the
|
|
431
|
+
"Name it plainly — for example ACME AB 99 — and I'll prepare the draft."
|
|
432
|
+
: "I can't anchor the draft: you haven't named the publication. Name it plainly — for example ACME AB 99 — and I'll prepare it.",
|
|
433
433
|
);
|
|
434
434
|
}
|
|
435
435
|
const standard = await resolveStandard(env, kept.standard);
|
|
@@ -437,7 +437,7 @@ export async function prepareDraft(env: any, opts: PrepareOpts): Promise<DraftVe
|
|
|
437
437
|
return refusal(
|
|
438
438
|
"standard_unresolved",
|
|
439
439
|
`I couldn't resolve ${kept.standard} as a publication in the corpus, so I can't anchor the draft. ` +
|
|
440
|
-
"Name the
|
|
440
|
+
"Name the publication plainly — for example ACME AB 99 — and I'll prepare it.",
|
|
441
441
|
);
|
|
442
442
|
}
|
|
443
443
|
|
|
@@ -192,7 +192,7 @@ async function absenceRoute(c: RouteContext): Promise<Response> {
|
|
|
192
192
|
const namedStd = namedDocumentIn(String(body?.standard ?? ""));
|
|
193
193
|
const standard = standardForDocNumber(namedStd?.doc_number ?? String(body?.standard ?? "").trim());
|
|
194
194
|
const topic = String(body?.topic ?? "").trim().toLowerCase();
|
|
195
|
-
if (!standard || !topic) return err(400, "invalid_input", "standard
|
|
195
|
+
if (!standard || !topic) return err(400, "invalid_input", "standard and topic are required");
|
|
196
196
|
try {
|
|
197
197
|
const nodes = (await env.DB.prepare("SELECT node_id, kind, name, content FROM model_nodes WHERE standard = ?1").bind(standard).all()).results ?? [];
|
|
198
198
|
const tokens = topic.split(/\s+/).filter((t: string) => t.length > 2);
|
|
@@ -50,9 +50,9 @@ export interface LiveDataConfig {
|
|
|
50
50
|
export function liveDataConfig(env: any): LiveDataConfig | null {
|
|
51
51
|
const platformApi = (env.SMART_PLATFORM_API ?? "").trim().replace(/\/$/, "");
|
|
52
52
|
const platformClientId = (env.SMART_PLATFORM_CLIENT_ID ?? "").trim();
|
|
53
|
-
const issuer = (env.OIDC_ISSUER ?? "
|
|
53
|
+
const issuer = (env.OIDC_ISSUER ?? "").trim().replace(/\/$/, "");
|
|
54
54
|
const clientId = (env.OIDC_CLIENT_ID ?? "").trim();
|
|
55
|
-
if (!platformApi || !platformClientId || !clientId) return null;
|
|
55
|
+
if (!platformApi || !platformClientId || !clientId || !issuer) return null;
|
|
56
56
|
return { platformApi, platformClientId, issuer, clientId, clientSecret: env.OIDC_CLIENT_SECRET };
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -384,7 +384,8 @@ function publicationUrl(meta: ChunkMeta): string | undefined {
|
|
|
384
384
|
// foreign-corpus chunk has no entry in it, and a fabricated url is
|
|
385
385
|
// worse than none (the door for internal renderings is the internal
|
|
386
386
|
// origin, wired by the site's doc-base configuration)
|
|
387
|
-
|
|
387
|
+
const ownCorpora = P().publisher.catalog_corpora;
|
|
388
|
+
if (meta.corpus && ownCorpora && !ownCorpora.includes(meta.corpus)) return undefined;
|
|
388
389
|
const tpl = P().publisher.catalog_url_template;
|
|
389
390
|
if (!tpl || !meta.doctype || !meta.doc_number) return undefined;
|
|
390
391
|
return tpl.replace("{type}", meta.doctype.toLowerCase()) + meta.doc_number;
|
|
@@ -19,6 +19,12 @@ export const PROFILE = {
|
|
|
19
19
|
"references": {
|
|
20
20
|
"label_prefix": ""
|
|
21
21
|
},
|
|
22
|
+
"catalog_url_template": "https://catalog.fixture.example.org/{type}",
|
|
23
|
+
"catalog_corpora": [
|
|
24
|
+
"pub",
|
|
25
|
+
"dirty",
|
|
26
|
+
"clean"
|
|
27
|
+
],
|
|
22
28
|
"features": {
|
|
23
29
|
"drafts": false,
|
|
24
30
|
"model_plane": false
|
|
@@ -80,11 +86,11 @@ export const PROFILE = {
|
|
|
80
86
|
"models": {},
|
|
81
87
|
"licensed": [
|
|
82
88
|
{
|
|
83
|
-
"key": "std:fixture-
|
|
84
|
-
"package": "fixture-
|
|
85
|
-
"doc_number": "
|
|
86
|
-
"title": "FIXTURE
|
|
87
|
-
"edition": "
|
|
89
|
+
"key": "std:fixture-ab-99",
|
|
90
|
+
"package": "fixture-ab-99",
|
|
91
|
+
"doc_number": "ab-99",
|
|
92
|
+
"title": "FIXTURE climatic conditioning, cyclic humidity",
|
|
93
|
+
"edition": "2019"
|
|
88
94
|
}
|
|
89
95
|
]
|
|
90
96
|
},
|
package/dist/ask-4O753Y4T.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
handleAsk
|
|
3
|
-
} from "./chunk-PBXE2LFD.js";
|
|
4
|
-
import "./chunk-7UT76RQO.js";
|
|
5
|
-
import "./chunk-EFQALN2Z.js";
|
|
6
|
-
import "./chunk-DBBGOOMZ.js";
|
|
7
|
-
import "./chunk-5MBWE7WD.js";
|
|
8
|
-
import "./chunk-ADXV2DPK.js";
|
|
9
|
-
import "./chunk-TJRTVJW5.js";
|
|
10
|
-
export {
|
|
11
|
-
handleAsk
|
|
12
|
-
};
|
package/dist/search-RFKT7ZZY.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
handleSearch
|
|
3
|
-
} from "./chunk-YFDWKXEB.js";
|
|
4
|
-
import "./chunk-7UT76RQO.js";
|
|
5
|
-
import "./chunk-EFQALN2Z.js";
|
|
6
|
-
import "./chunk-DBBGOOMZ.js";
|
|
7
|
-
import "./chunk-5MBWE7WD.js";
|
|
8
|
-
import "./chunk-ADXV2DPK.js";
|
|
9
|
-
import "./chunk-TJRTVJW5.js";
|
|
10
|
-
export {
|
|
11
|
-
handleSearch
|
|
12
|
-
};
|