@konneal/engine 0.2.53 → 0.2.55
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-5KXW7WIA.js → ask-PJBGJIXF.js} +1 -1
- package/dist/{chunk-PH7W6HMN.js → chunk-DKQXJN6G.js} +11 -10
- package/dist/openapi-surface.gen.d.ts +1 -1
- package/dist/openapi-types.d.ts +0 -89
- package/dist/worker_public/src/index.js +3 -49
- package/package.json +1 -1
- package/workers/worker_public/openapi.yaml +0 -52
- package/workers/worker_public/src/ask.ts +21 -15
- package/workers/worker_public/src/index.ts +1 -38
- package/workers/worker_public/src/openapi-surface.gen.ts +0 -12
|
@@ -2222,20 +2222,22 @@ async function handleAsk(env, ctx, req, tier, key) {
|
|
|
2222
2222
|
const warmQuery = retrievalQuery(q.query, prev);
|
|
2223
2223
|
const warmEmbed = embedWarm(env, warmQuery);
|
|
2224
2224
|
const conversationId = typeof body?.conversation_id === "string" && /^[A-Za-z0-9_-]{8,64}$/.test(body.conversation_id) ? body.conversation_id : null;
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2225
|
+
try {
|
|
2226
|
+
if (!effectiveImage && !attachIds.length && conversationId && env.DB && member) {
|
|
2227
|
+
const prior = await env.DB.prepare(
|
|
2228
|
+
"SELECT m.attachment_id AS aid, a.mime, a.r2_key FROM messages m JOIN attachments a ON a.id = m.attachment_id JOIN conversations c ON c.id = m.conversation_id AND c.sub = ?2 WHERE m.conversation_id = ?1 AND m.role = 'user' AND m.attachment_id IS NOT NULL ORDER BY m.created_at DESC LIMIT 1"
|
|
2229
|
+
).bind(conversationId, member.sub).first();
|
|
2230
|
+
if (prior) {
|
|
2231
2231
|
const obj = await env.CHAT_UPLOADS.get(prior.r2_key);
|
|
2232
2232
|
if (obj) {
|
|
2233
|
-
const
|
|
2234
|
-
|
|
2233
|
+
const bytes = new Uint8Array(await obj.arrayBuffer());
|
|
2234
|
+
let bin = "";
|
|
2235
|
+
for (let i = 0; i < bytes.length; i += 32768) bin += String.fromCharCode(...bytes.subarray(i, i + 32768));
|
|
2236
|
+
storedImage = `data:${prior.mime};base64,${btoa(bin)}`;
|
|
2235
2237
|
}
|
|
2236
|
-
} catch {
|
|
2237
2238
|
}
|
|
2238
2239
|
}
|
|
2240
|
+
} catch {
|
|
2239
2241
|
}
|
|
2240
2242
|
let convEntities = [];
|
|
2241
2243
|
if (conversationId) {
|
|
@@ -2908,7 +2910,6 @@ export {
|
|
|
2908
2910
|
handleMemories,
|
|
2909
2911
|
scoreFaithfulness,
|
|
2910
2912
|
checkQuoteAnchors,
|
|
2911
|
-
standardForDocNumber,
|
|
2912
2913
|
bindModelNode,
|
|
2913
2914
|
modelGroundingBlock,
|
|
2914
2915
|
scoreJudge,
|
|
@@ -3,7 +3,7 @@ export interface OpenApiRoute {
|
|
|
3
3
|
pattern: string;
|
|
4
4
|
operationId: string;
|
|
5
5
|
}
|
|
6
|
-
export type OpenApiOperationId = "askAnonymous" | "askKeyed" | "search" | "searchKeyed" | "
|
|
6
|
+
export type OpenApiOperationId = "askAnonymous" | "askKeyed" | "search" | "searchKeyed" | "verify" | "verifyKeyed" | "research" | "researchKeyed" | "mcp" | "datasets" | "keyUsage" | "health" | "listConversations" | "createConversation" | "getConversation" | "renameConversation" | "deleteConversation" | "appendMessage" | "shareConversation" | "getShared" | "uploadAttachment" | "listAttachments" | "getAttachment" | "deleteAttachment" | "listMemories" | "createMemory" | "deleteMemory" | "listProjects" | "createProject" | "deleteProject" | "listProjectFiles" | "attachProjectFile" | "detachProjectFile" | "laneQuery" | "laneKeyed" | "feedback" | "adminEnrich" | "adminEnrichAlias" | "adminSection" | "adminSectionAlias" | "adminVectors" | "adminCaption" | "adminJudge" | "adminJudgeAlias" | "adminRevokeKey" | "authMe" | "authLogin" | "authCallback" | "authLogout" | "authLogoutLink" | "adminStats" | "adminListKeys" | "adminCreateKey";
|
|
7
7
|
export declare const OPENAPI_SURFACE: readonly (Omit<OpenApiRoute, "operationId"> & {
|
|
8
8
|
operationId: OpenApiOperationId;
|
|
9
9
|
})[];
|
package/dist/openapi-types.d.ts
CHANGED
|
@@ -86,43 +86,6 @@ export interface paths {
|
|
|
86
86
|
patch?: never;
|
|
87
87
|
trace?: never;
|
|
88
88
|
};
|
|
89
|
-
"/api/absence": {
|
|
90
|
-
parameters: {
|
|
91
|
-
query?: never;
|
|
92
|
-
header?: never;
|
|
93
|
-
path?: never;
|
|
94
|
-
cookie?: never;
|
|
95
|
-
};
|
|
96
|
-
get?: never;
|
|
97
|
-
put?: never;
|
|
98
|
-
/**
|
|
99
|
-
* Request a provable absence certificate
|
|
100
|
-
* @description Enumerates the entire machine-readable model of the named standard and reports how many nodes were examined and whether any matched the topic. A verdict of absent is an enumeration certificate that states its scope, not a statement that a search found nothing.
|
|
101
|
-
*/
|
|
102
|
-
post: operations["absence"];
|
|
103
|
-
delete?: never;
|
|
104
|
-
options?: never;
|
|
105
|
-
head?: never;
|
|
106
|
-
patch?: never;
|
|
107
|
-
trace?: never;
|
|
108
|
-
};
|
|
109
|
-
"/v1/absence": {
|
|
110
|
-
parameters: {
|
|
111
|
-
query?: never;
|
|
112
|
-
header?: never;
|
|
113
|
-
path?: never;
|
|
114
|
-
cookie?: never;
|
|
115
|
-
};
|
|
116
|
-
get?: never;
|
|
117
|
-
put?: never;
|
|
118
|
-
/** Request a provable absence certificate with an API key */
|
|
119
|
-
post: operations["absenceKeyed"];
|
|
120
|
-
delete?: never;
|
|
121
|
-
options?: never;
|
|
122
|
-
head?: never;
|
|
123
|
-
patch?: never;
|
|
124
|
-
trace?: never;
|
|
125
|
-
};
|
|
126
89
|
"/api/verify": {
|
|
127
90
|
parameters: {
|
|
128
91
|
query?: never;
|
|
@@ -1089,58 +1052,6 @@ export interface operations {
|
|
|
1089
1052
|
};
|
|
1090
1053
|
};
|
|
1091
1054
|
};
|
|
1092
|
-
absence: {
|
|
1093
|
-
parameters: {
|
|
1094
|
-
query?: never;
|
|
1095
|
-
header?: never;
|
|
1096
|
-
path?: never;
|
|
1097
|
-
cookie?: never;
|
|
1098
|
-
};
|
|
1099
|
-
requestBody: {
|
|
1100
|
-
content: {
|
|
1101
|
-
"application/json": {
|
|
1102
|
-
/** @description The publication, for example R 60. */
|
|
1103
|
-
standard: string;
|
|
1104
|
-
/** @description The topic whose absence is to be proven. */
|
|
1105
|
-
topic: string;
|
|
1106
|
-
};
|
|
1107
|
-
};
|
|
1108
|
-
};
|
|
1109
|
-
responses: {
|
|
1110
|
-
/** @description The enumeration certificate. */
|
|
1111
|
-
200: {
|
|
1112
|
-
headers: {
|
|
1113
|
-
[name: string]: unknown;
|
|
1114
|
-
};
|
|
1115
|
-
content?: never;
|
|
1116
|
-
};
|
|
1117
|
-
};
|
|
1118
|
-
};
|
|
1119
|
-
absenceKeyed: {
|
|
1120
|
-
parameters: {
|
|
1121
|
-
query?: never;
|
|
1122
|
-
header?: never;
|
|
1123
|
-
path?: never;
|
|
1124
|
-
cookie?: never;
|
|
1125
|
-
};
|
|
1126
|
-
requestBody: {
|
|
1127
|
-
content: {
|
|
1128
|
-
"application/json": {
|
|
1129
|
-
standard: string;
|
|
1130
|
-
topic: string;
|
|
1131
|
-
};
|
|
1132
|
-
};
|
|
1133
|
-
};
|
|
1134
|
-
responses: {
|
|
1135
|
-
/** @description The enumeration certificate. */
|
|
1136
|
-
200: {
|
|
1137
|
-
headers: {
|
|
1138
|
-
[name: string]: unknown;
|
|
1139
|
-
};
|
|
1140
|
-
content?: never;
|
|
1141
|
-
};
|
|
1142
|
-
};
|
|
1143
|
-
};
|
|
1144
1055
|
verify: {
|
|
1145
1056
|
parameters: {
|
|
1146
1057
|
query?: never;
|
|
@@ -8,9 +8,8 @@ import {
|
|
|
8
8
|
handleMemories,
|
|
9
9
|
modelGroundingBlock,
|
|
10
10
|
scoreFaithfulness,
|
|
11
|
-
scoreJudge
|
|
12
|
-
|
|
13
|
-
} from "../../chunk-PH7W6HMN.js";
|
|
11
|
+
scoreJudge
|
|
12
|
+
} from "../../chunk-DKQXJN6G.js";
|
|
14
13
|
import {
|
|
15
14
|
buildMessages,
|
|
16
15
|
cfBlobs,
|
|
@@ -25,7 +24,6 @@ import {
|
|
|
25
24
|
handleLogin,
|
|
26
25
|
handleLogout,
|
|
27
26
|
handleMe,
|
|
28
|
-
namedDocumentIn,
|
|
29
27
|
opCfg,
|
|
30
28
|
opMemberCanWrite,
|
|
31
29
|
opTokenMember,
|
|
@@ -960,7 +958,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
960
958
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
961
959
|
body: JSON.stringify({ ...args, stream: false })
|
|
962
960
|
});
|
|
963
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
961
|
+
const res = name === "ask" ? await (await import("../../ask-PJBGJIXF.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-PBOODCMQ.js")).handleSearch(env, ctx, inner, tier, key);
|
|
964
962
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
965
963
|
});
|
|
966
964
|
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
|
@@ -1020,16 +1018,6 @@ var OPENAPI_SURFACE = [
|
|
|
1020
1018
|
"pattern": "/v1/search",
|
|
1021
1019
|
"operationId": "searchKeyed"
|
|
1022
1020
|
},
|
|
1023
|
-
{
|
|
1024
|
-
"method": "POST",
|
|
1025
|
-
"pattern": "/api/absence",
|
|
1026
|
-
"operationId": "absence"
|
|
1027
|
-
},
|
|
1028
|
-
{
|
|
1029
|
-
"method": "POST",
|
|
1030
|
-
"pattern": "/v1/absence",
|
|
1031
|
-
"operationId": "absenceKeyed"
|
|
1032
|
-
},
|
|
1033
1021
|
{
|
|
1034
1022
|
"method": "POST",
|
|
1035
1023
|
"pattern": "/api/verify",
|
|
@@ -1456,38 +1444,6 @@ async function adminStatsRoute(c) {
|
|
|
1456
1444
|
pruned: "telemetry >90d"
|
|
1457
1445
|
}, 200, corsHeaders(req));
|
|
1458
1446
|
}
|
|
1459
|
-
async function absenceRoute(c) {
|
|
1460
|
-
const { env, req } = c;
|
|
1461
|
-
const t = await tierFor(c);
|
|
1462
|
-
if (t instanceof Response) return t;
|
|
1463
|
-
const body = await readJson(req);
|
|
1464
|
-
const namedStd = namedDocumentIn(String(body?.standard ?? ""));
|
|
1465
|
-
const standard = standardForDocNumber(namedStd?.doc_number ?? String(body?.standard ?? "").trim());
|
|
1466
|
-
const topic = String(body?.topic ?? "").trim().toLowerCase();
|
|
1467
|
-
if (!standard || !topic) return err(400, "invalid_input", "standard and topic are required");
|
|
1468
|
-
try {
|
|
1469
|
-
const nodes = (await env.DB.prepare("SELECT node_id, kind, name, content FROM model_nodes WHERE standard = ?1").bind(standard).all()).results ?? [];
|
|
1470
|
-
const tokens = topic.split(/\s+/).filter((t2) => t2.length > 2);
|
|
1471
|
-
const matches = [];
|
|
1472
|
-
for (const n of nodes) {
|
|
1473
|
-
const hay = `${n.name ?? ""} ${n.content ?? ""}`.toLowerCase();
|
|
1474
|
-
if (tokens.some((tok) => hay.includes(tok))) {
|
|
1475
|
-
matches.push({ node_id: n.node_id, kind: n.kind });
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
const chunks = await env.DB.prepare("SELECT COUNT(*) AS n FROM chunks WHERE corpus = 'smart-model' AND (docidentifier LIKE ?1 OR doc_id LIKE ?2)").bind(`%${body?.standard}%`, `%${body?.standard}%`).first();
|
|
1479
|
-
return json({
|
|
1480
|
-
standard,
|
|
1481
|
-
topic,
|
|
1482
|
-
enumerated: { model_nodes: nodes.length, smart_model_chunks: chunks?.n ?? 0 },
|
|
1483
|
-
matches: matches.slice(0, 20),
|
|
1484
|
-
verdict: matches.length === 0 ? "absent" : "present",
|
|
1485
|
-
scope: `the machine-readable model of ${standard} (all model nodes) \u2014 the enumeration is exhaustive over that scope; prose outside the modeled families is not claimed`
|
|
1486
|
-
});
|
|
1487
|
-
} catch (e) {
|
|
1488
|
-
return err(502, "absence_failed", String(e).slice(0, 200));
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
1447
|
async function verifyRoute(c) {
|
|
1492
1448
|
const { env, req } = c;
|
|
1493
1449
|
const t = await tierFor(c);
|
|
@@ -1727,8 +1683,6 @@ var OPENAPI_HANDLERS = {
|
|
|
1727
1683
|
askKeyed: askRoute,
|
|
1728
1684
|
search: searchRoute,
|
|
1729
1685
|
searchKeyed: searchRoute,
|
|
1730
|
-
absence: absenceRoute,
|
|
1731
|
-
absenceKeyed: absenceRoute,
|
|
1732
1686
|
verify: verifyRoute,
|
|
1733
1687
|
verifyKeyed: verifyRoute,
|
|
1734
1688
|
research: researchRoute,
|
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.55",
|
|
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",
|
|
@@ -178,58 +178,6 @@ paths:
|
|
|
178
178
|
responses:
|
|
179
179
|
'200':
|
|
180
180
|
description: The ranked hits.
|
|
181
|
-
/api/absence:
|
|
182
|
-
post:
|
|
183
|
-
tags: [Evidence]
|
|
184
|
-
summary: Request a provable absence certificate
|
|
185
|
-
description: >-
|
|
186
|
-
Enumerates the entire machine-readable model of the named standard and
|
|
187
|
-
reports how many nodes were examined and whether any matched the
|
|
188
|
-
topic. A verdict of absent is an enumeration certificate that
|
|
189
|
-
states its scope, not a statement that a search found nothing.
|
|
190
|
-
operationId: absence
|
|
191
|
-
requestBody:
|
|
192
|
-
required: true
|
|
193
|
-
content:
|
|
194
|
-
application/json:
|
|
195
|
-
schema:
|
|
196
|
-
type: object
|
|
197
|
-
required: [standard, topic]
|
|
198
|
-
properties:
|
|
199
|
-
standard:
|
|
200
|
-
type: string
|
|
201
|
-
description: The publication, for example R 60.
|
|
202
|
-
topic:
|
|
203
|
-
type: string
|
|
204
|
-
description: The topic whose absence is to be proven.
|
|
205
|
-
examples:
|
|
206
|
-
packaging:
|
|
207
|
-
value:
|
|
208
|
-
standard: R 60
|
|
209
|
-
topic: packaging
|
|
210
|
-
responses:
|
|
211
|
-
'200':
|
|
212
|
-
description: The enumeration certificate.
|
|
213
|
-
/v1/absence:
|
|
214
|
-
post:
|
|
215
|
-
tags: [Evidence]
|
|
216
|
-
summary: Request a provable absence certificate with an API key
|
|
217
|
-
operationId: absenceKeyed
|
|
218
|
-
security:
|
|
219
|
-
- bearerAuth: []
|
|
220
|
-
requestBody:
|
|
221
|
-
required: true
|
|
222
|
-
content:
|
|
223
|
-
application/json:
|
|
224
|
-
schema:
|
|
225
|
-
type: object
|
|
226
|
-
required: [standard, topic]
|
|
227
|
-
properties:
|
|
228
|
-
standard: { type: string }
|
|
229
|
-
topic: { type: string }
|
|
230
|
-
responses:
|
|
231
|
-
'200':
|
|
232
|
-
description: The enumeration certificate.
|
|
233
181
|
/api/verify:
|
|
234
182
|
post:
|
|
235
183
|
tags: [Evidence]
|
|
@@ -452,24 +452,30 @@ async function handleAsk(
|
|
|
452
452
|
const conversationId = typeof body?.conversation_id === "string" && /^[A-Za-z0-9_-]{8,64}$/.test(body.conversation_id) ? body.conversation_id : null;
|
|
453
453
|
|
|
454
454
|
// Tier-2 continuation: no new image, but the conversation carries one —
|
|
455
|
-
// its most recent stored image re-attaches to this question
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if (
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
455
|
+
// its most recent stored image re-attaches to this question. The query
|
|
456
|
+
// scopes by the CONVERSATION'S OWNER (the messages table carries no
|
|
457
|
+
// sub; ownership rides the conversation row) and the whole resolution
|
|
458
|
+
// fails open: an optional feature never takes the ask down.
|
|
459
|
+
try {
|
|
460
|
+
if (!effectiveImage && !attachIds.length && conversationId && env.DB && member) {
|
|
461
|
+
const prior = await env.DB.prepare(
|
|
462
|
+
"SELECT m.attachment_id AS aid, a.mime, a.r2_key FROM messages m JOIN attachments a ON a.id = m.attachment_id JOIN conversations c ON c.id = m.conversation_id AND c.sub = ?2 WHERE m.conversation_id = ?1 AND m.role = 'user' AND m.attachment_id IS NOT NULL ORDER BY m.created_at DESC LIMIT 1",
|
|
463
|
+
).bind(conversationId, member.sub).first<{ aid: string; mime: string; r2_key: string }>();
|
|
464
|
+
if (prior) {
|
|
465
|
+
const obj = await (env as any).CHAT_UPLOADS.get(prior.r2_key);
|
|
466
|
+
if (obj) {
|
|
467
|
+
const bytes = new Uint8Array(await obj.arrayBuffer());
|
|
468
|
+
let bin = "";
|
|
469
|
+
for (let i = 0; i < bytes.length; i += 0x8000) bin += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
470
|
+
storedImage = `data:${prior.mime};base64,${btoa(bin)}`;
|
|
471
|
+
}
|
|
469
472
|
}
|
|
470
473
|
}
|
|
474
|
+
} catch {
|
|
475
|
+
/* the reuse path is optional — the ask answers without the image */
|
|
471
476
|
}
|
|
472
|
-
|
|
477
|
+
|
|
478
|
+
let convEntities: Array<{ entity: string; kind: string }> = [];
|
|
473
479
|
if (conversationId) {
|
|
474
480
|
try {
|
|
475
481
|
const rows = await env.DB.prepare("SELECT entity, kind FROM conversation_entities WHERE conversation_id = ?1 LIMIT 12").bind(conversationId).all();
|
|
@@ -13,8 +13,7 @@ import { embed } from "./ai";
|
|
|
13
13
|
import { ftsMatchQuery } from "./lexical";
|
|
14
14
|
import { scoreFaithfulness } from "./faithfulness";
|
|
15
15
|
import { checkQuoteAnchors } from "./anchors";
|
|
16
|
-
import {
|
|
17
|
-
import { standardForDocNumber, bindModelNode, modelGroundingBlock } from "./modelplane";
|
|
16
|
+
import { bindModelNode, modelGroundingBlock } from "./modelplane";
|
|
18
17
|
import { refCodec } from "./codecs";
|
|
19
18
|
import { entitlementScope, standardKeysFrom } from "./requestScope";
|
|
20
19
|
import type { Env } from "./env";
|
|
@@ -261,40 +260,6 @@ async function adminStatsRoute(c: RouteContext): Promise<Response> {
|
|
|
261
260
|
}, 200, corsHeaders(req));
|
|
262
261
|
}
|
|
263
262
|
|
|
264
|
-
// ── Provable absence (TODO.era3/02): deterministic enumeration proof ──
|
|
265
|
-
async function absenceRoute(c: RouteContext): Promise<Response> {
|
|
266
|
-
const { env, req } = c;
|
|
267
|
-
const t = await tierFor(c);
|
|
268
|
-
if (t instanceof Response) return t;
|
|
269
|
-
const body = await readJson(req);
|
|
270
|
-
const namedStd = namedDocumentIn(String(body?.standard ?? ""));
|
|
271
|
-
const standard = standardForDocNumber(namedStd?.doc_number ?? String(body?.standard ?? "").trim());
|
|
272
|
-
const topic = String(body?.topic ?? "").trim().toLowerCase();
|
|
273
|
-
if (!standard || !topic) return err(400, "invalid_input", "standard and topic are required");
|
|
274
|
-
try {
|
|
275
|
-
const nodes = (await env.DB.prepare("SELECT node_id, kind, name, content FROM model_nodes WHERE standard = ?1").bind(standard).all()).results ?? [];
|
|
276
|
-
const tokens = topic.split(/\s+/).filter((t: string) => t.length > 2);
|
|
277
|
-
const matches: unknown[] = [];
|
|
278
|
-
for (const n of nodes as any[]) {
|
|
279
|
-
const hay = `${n.name ?? ""} ${n.content ?? ""}`.toLowerCase();
|
|
280
|
-
if (tokens.some((tok: string) => hay.includes(tok))) {
|
|
281
|
-
matches.push({ node_id: n.node_id, kind: n.kind });
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
const chunks = (await env.DB.prepare("SELECT COUNT(*) AS n FROM chunks WHERE corpus = 'smart-model' AND (docidentifier LIKE ?1 OR doc_id LIKE ?2)").bind(`%${body?.standard}%`, `%${body?.standard}%`).first()) as any;
|
|
285
|
-
return json({
|
|
286
|
-
standard,
|
|
287
|
-
topic,
|
|
288
|
-
enumerated: { model_nodes: nodes.length, smart_model_chunks: chunks?.n ?? 0 },
|
|
289
|
-
matches: matches.slice(0, 20),
|
|
290
|
-
verdict: matches.length === 0 ? "absent" : "present",
|
|
291
|
-
scope: `the machine-readable model of ${standard} (all model nodes) — the enumeration is exhaustive over that scope; prose outside the modeled families is not claimed`,
|
|
292
|
-
});
|
|
293
|
-
} catch (e) {
|
|
294
|
-
return err(502, "absence_failed", String(e).slice(0, 200));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
263
|
// ── Self-verification (TODO.era3/03): the deterministic battery, exposed ──
|
|
299
264
|
async function verifyRoute(c: RouteContext): Promise<Response> {
|
|
300
265
|
const { env, req } = c;
|
|
@@ -595,8 +560,6 @@ const OPENAPI_HANDLERS: Record<OpenApiOperationId, RouteHandler> = {
|
|
|
595
560
|
askKeyed: askRoute,
|
|
596
561
|
search: searchRoute,
|
|
597
562
|
searchKeyed: searchRoute,
|
|
598
|
-
absence: absenceRoute,
|
|
599
|
-
absenceKeyed: absenceRoute,
|
|
600
563
|
verify: verifyRoute,
|
|
601
564
|
verifyKeyed: verifyRoute,
|
|
602
565
|
research: researchRoute,
|
|
@@ -11,8 +11,6 @@ export type OpenApiOperationId =
|
|
|
11
11
|
| "askKeyed"
|
|
12
12
|
| "search"
|
|
13
13
|
| "searchKeyed"
|
|
14
|
-
| "absence"
|
|
15
|
-
| "absenceKeyed"
|
|
16
14
|
| "verify"
|
|
17
15
|
| "verifyKeyed"
|
|
18
16
|
| "research"
|
|
@@ -84,16 +82,6 @@ export const OPENAPI_SURFACE: readonly (Omit<OpenApiRoute, "operationId"> & { op
|
|
|
84
82
|
"pattern": "/v1/search",
|
|
85
83
|
"operationId": "searchKeyed"
|
|
86
84
|
},
|
|
87
|
-
{
|
|
88
|
-
"method": "POST",
|
|
89
|
-
"pattern": "/api/absence",
|
|
90
|
-
"operationId": "absence"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"method": "POST",
|
|
94
|
-
"pattern": "/v1/absence",
|
|
95
|
-
"operationId": "absenceKeyed"
|
|
96
|
-
},
|
|
97
85
|
{
|
|
98
86
|
"method": "POST",
|
|
99
87
|
"pattern": "/api/verify",
|