@konneal/engine 0.1.1 → 0.1.3
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/README.md
CHANGED
|
@@ -6,8 +6,109 @@ typed tables/formulas/figures, conformance checking by execution, and
|
|
|
6
6
|
the measurement gates that keep it honest. Konneal builds the databases
|
|
7
7
|
and serves the API; publishers own their content, profile and frontend.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
```
|
|
10
|
+
npm install @konneal/engine
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
BSD-3-Clause. The reference deployment is
|
|
14
|
+
[OIML SMART AI](https://ai.oimlsmart.org).
|
|
15
|
+
|
|
16
|
+
## What a deployment looks like
|
|
17
|
+
|
|
18
|
+
A publisher's worker is ten lines:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
// workers/worker_public/src/index.ts — the deployment entry
|
|
22
|
+
import worker, { setProfile } from "@konneal/engine";
|
|
23
|
+
import { PROFILE } from "./profile.gen.ts";
|
|
24
|
+
|
|
25
|
+
setProfile(PROFILE);
|
|
26
|
+
|
|
27
|
+
export default worker;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Everything the publisher owns lives in `profile/*.yaml` — identity,
|
|
31
|
+
datasets, corpora, prompts, thresholds, eval cases. The codegen
|
|
32
|
+
(`gen_profile.mjs`, included) turns the YAML into a committed
|
|
33
|
+
TypeScript module; a drift test keeps both sides honest. The engine
|
|
34
|
+
reads the profile at request time; no publisher fact is hardcoded.
|
|
35
|
+
|
|
36
|
+
The engine also ships the ingest CLI (Python): parse → embed → upsert,
|
|
37
|
+
reading the same profile for its corpora declarations.
|
|
38
|
+
|
|
39
|
+
## The three packages
|
|
40
|
+
|
|
41
|
+
| Package | What it is |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `@konneal/engine` | The serving Worker + the ingest CLI (this package) |
|
|
44
|
+
| `@konneal/client` | The publisher-site contract: wire types, SSE client, citation chips, typed blocks |
|
|
45
|
+
| `@konneal/create-publisher` | `npm create @konneal/publisher` — scaffolds the whole deployment |
|
|
46
|
+
|
|
47
|
+
Start with the scaffolder: `npm create @konneal/publisher my-sdo
|
|
48
|
+
-- --with-site` writes the profile, the worker entry, the Cloudflare
|
|
49
|
+
wiring, the profile codegen, and (with `--with-site`) a minimal
|
|
50
|
+
Astro+Vue frontend consuming `@konneal/client`.
|
|
51
|
+
|
|
52
|
+
## The profile (the publisher's single edit surface)
|
|
53
|
+
|
|
54
|
+
| File | Declares |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `publisher.yaml` | id, name, domains, identity issuer, codec, session cookie, features |
|
|
57
|
+
| `datasets.yaml` | what users can scope to (public vs session-gated), per-corpus prompt notes |
|
|
58
|
+
| `corpora.yaml` | the corpus registry — which corpora exist, which indexes serve them |
|
|
59
|
+
| `sources.yaml` | upstream repos the tooling reads (clean corpus, bibliography, terminology, models) |
|
|
60
|
+
| `ui.yaml` | suggestions, model disclosure, smoke probes |
|
|
61
|
+
| `retrieval.yaml` | steering vocabulary, process-intent notes |
|
|
62
|
+
| `prompts.yaml` | the publisher's prompt voice (identity, refusal, examples) |
|
|
63
|
+
| `evals/` | golden cases, annealment probes, ladder — the promotion-gate data |
|
|
64
|
+
|
|
65
|
+
## Serving architecture
|
|
66
|
+
|
|
67
|
+
- **Retrieval** is a stage registry; the ask path owns composition only
|
|
68
|
+
- **HTTP** is a route table dispatched by both workers
|
|
69
|
+
- Every steering number lives in `THRESHOLDS`; the chunk wire type is
|
|
70
|
+
shared with the Python producer by a contract test
|
|
71
|
+
- **Ports** (`ports/`): ModelRunner, VectorIndex, Kv, Blobs, Runtime —
|
|
72
|
+
the Cloudflare adapters are the only provider-typed module; a purity
|
|
73
|
+
lint enforces it in CI
|
|
74
|
+
- **Publisher purity**: a CI lint fails any publisher string in
|
|
75
|
+
`workers/` outside the codec registry (the identifier grammars)
|
|
76
|
+
- **Feature gates**: `drafts` and `model_plane` are profile-declared,
|
|
77
|
+
off by default
|
|
78
|
+
|
|
79
|
+
## The ingest CLI
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install git+https://github.com/konneal/engine.git
|
|
83
|
+
python -m ingest.cli parse # corpora → chunks.jsonl + manifest
|
|
84
|
+
python -m ingest.cli embed # embed via the binding's model
|
|
85
|
+
python -m ingest.cli upsert # push vectors + metadata to Vectorize
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## MCP server
|
|
89
|
+
|
|
90
|
+
The package exports `./mcp` — a ten-line entry per deployment serves
|
|
91
|
+
the publisher's public corpus to MCP clients (agent ecosystems).
|
|
92
|
+
Auth is required: the MCP client presents one of the deployment's API
|
|
93
|
+
keys; the same token rides outbound so spend and quota charge that
|
|
94
|
+
key.
|
|
95
|
+
|
|
96
|
+
## Promotion gates
|
|
97
|
+
|
|
98
|
+
The engine ships the gate harness: a deployment's golden cases and
|
|
99
|
+
annealment probes live in `profile/evals/`; the gate runs them against
|
|
100
|
+
production before any promotion. Answers are witness-checked (the
|
|
101
|
+
answer must contain the expected span, not just score well).
|
|
102
|
+
|
|
103
|
+
## Repository
|
|
104
|
+
|
|
105
|
+
- `workers/worker_public/` — the public-facing Worker
|
|
106
|
+
- `workers/worker_mcp/` — the MCP server Worker
|
|
107
|
+
- `workers/shared/` — the router, chunk wire type, session
|
|
108
|
+
- `ports/` — the provider seam (interfaces + Cloudflare adapters)
|
|
109
|
+
- `profile/` — the engine's fixture profile (a real deployment carries
|
|
110
|
+
its own; this one exists so tests run against declared data)
|
|
111
|
+
- `profile2/` — the reference matrix's second fixture (a different
|
|
112
|
+
publisher shape; CI proves the engine serves declared profiles)
|
|
113
|
+
- `ingest/` — the Python ingest CLI
|
|
114
|
+
- `tests/` — unit suites (plain node, no network)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { setProfile } from "../../worker_public/src/profile.ts";
|
|
1
2
|
export interface Env {
|
|
2
3
|
RAG_BASE: string;
|
|
3
4
|
/** the deployment's shared D1 (API keys + the derived documents
|
|
@@ -8,3 +9,4 @@ declare const _default: {
|
|
|
8
9
|
fetch(req: Request, env: Env): Promise<Response>;
|
|
9
10
|
};
|
|
10
11
|
export default _default;
|
|
12
|
+
export { setProfile };
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
} from "../../chunk-ROF3Q7UC.js";
|
|
4
4
|
import "../../chunk-OCNLV7Q7.js";
|
|
5
5
|
import {
|
|
6
|
-
P
|
|
6
|
+
P,
|
|
7
|
+
setProfile
|
|
7
8
|
} from "../../chunk-35ODH64W.js";
|
|
8
9
|
|
|
9
10
|
// workers/worker_mcp/src/index.ts
|
|
@@ -17,7 +18,7 @@ var rpcError = (id, code, message) => json({ jsonrpc: "2.0", id, error: { code,
|
|
|
17
18
|
var publisherId = () => P().publisher.id;
|
|
18
19
|
var bearer = (req) => (req.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
|
|
19
20
|
var publisherName = () => P().publisher.name;
|
|
20
|
-
var
|
|
21
|
+
var tools = () => [
|
|
21
22
|
{
|
|
22
23
|
name: `${publisherId()}_search`,
|
|
23
24
|
description: `Search the ${publisherName()} publications corpus. Returns ranked passages with publication identifier, edition, clause and snippet.`,
|
|
@@ -107,7 +108,7 @@ var src_default = {
|
|
|
107
108
|
server: "rag-mcp",
|
|
108
109
|
transport: "streamable-http",
|
|
109
110
|
endpoint: "/mcp",
|
|
110
|
-
tools:
|
|
111
|
+
tools: tools().map((t) => t.name)
|
|
111
112
|
});
|
|
112
113
|
}
|
|
113
114
|
if (url.pathname !== "/mcp") return json({ error: "not_found" }, 404);
|
|
@@ -130,7 +131,7 @@ var src_default = {
|
|
|
130
131
|
serverInfo: { name: "rag-mcp", version: "1.0.0", title: `${P().publisher.product_name} \u2014 public corpus` }
|
|
131
132
|
});
|
|
132
133
|
case "tools/list":
|
|
133
|
-
return rpcResult(msg.id, { tools:
|
|
134
|
+
return rpcResult(msg.id, { tools: tools() });
|
|
134
135
|
case "tools/call": {
|
|
135
136
|
const out = await callTool(env, bearer(req), String(msg.params?.name ?? ""), msg.params?.arguments ?? {});
|
|
136
137
|
return rpcResult(msg.id, out);
|
|
@@ -149,5 +150,6 @@ var src_default = {
|
|
|
149
150
|
}
|
|
150
151
|
};
|
|
151
152
|
export {
|
|
152
|
-
src_default as default
|
|
153
|
+
src_default as default,
|
|
154
|
+
setProfile
|
|
153
155
|
};
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@astrojs/markdown-satteri": "^0.4.1",
|
|
32
32
|
"@astrojs/mdx": "^4.3.14"
|
|
33
33
|
},
|
|
34
|
-
"version": "0.1.
|
|
34
|
+
"version": "0.1.3",
|
|
35
35
|
"description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
|
|
36
36
|
"license": "BSD-3-Clause",
|
|
37
37
|
"type": "module",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// server — each request is answered in one JSON response; no sessions.
|
|
15
15
|
// https://modelcontextprotocol.io spec (2025-06 streamable HTTP).
|
|
16
16
|
|
|
17
|
-
import { P } from "../../worker_public/src/profile.ts";
|
|
17
|
+
import { P, setProfile } from "../../worker_public/src/profile.ts";
|
|
18
18
|
import { authenticate } from "../../worker_public/src/lib/http";
|
|
19
19
|
|
|
20
20
|
export interface Env {
|
|
@@ -39,7 +39,7 @@ const rpcError = (id: unknown, code: number, message: string) =>
|
|
|
39
39
|
const publisherId = () => P().publisher.id;
|
|
40
40
|
const bearer = (req: Request) => (req.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
|
|
41
41
|
const publisherName = () => P().publisher.name;
|
|
42
|
-
const
|
|
42
|
+
const tools = () => [
|
|
43
43
|
{
|
|
44
44
|
name: `${publisherId()}_search`,
|
|
45
45
|
description:
|
|
@@ -138,7 +138,7 @@ export default {
|
|
|
138
138
|
server: "rag-mcp",
|
|
139
139
|
transport: "streamable-http",
|
|
140
140
|
endpoint: "/mcp",
|
|
141
|
-
tools:
|
|
141
|
+
tools: tools().map((t) => t.name),
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -168,7 +168,7 @@ export default {
|
|
|
168
168
|
serverInfo: { name: "rag-mcp", version: "1.0.0", title: `${P().publisher.product_name} — public corpus` },
|
|
169
169
|
});
|
|
170
170
|
case "tools/list":
|
|
171
|
-
return rpcResult(msg.id, { tools:
|
|
171
|
+
return rpcResult(msg.id, { tools: tools() });
|
|
172
172
|
case "tools/call": {
|
|
173
173
|
const out = await callTool(env, bearer(req), String(msg.params?.name ?? ""), msg.params?.arguments ?? {});
|
|
174
174
|
return rpcResult(msg.id, out);
|
|
@@ -186,3 +186,4 @@ export default {
|
|
|
186
186
|
}
|
|
187
187
|
},
|
|
188
188
|
};
|
|
189
|
+
export { setProfile };
|