@konneal/engine 0.2.33 → 0.2.35

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.
Files changed (41) hide show
  1. package/dist/apicalls.d.ts +72 -0
  2. package/dist/ask-P6KLPBKL.js +12 -0
  3. package/dist/{chunk-JGKSUSF5.js → chunk-4GJGBGJK.js} +3 -3
  4. package/dist/{chunk-NHHQAGBW.js → chunk-GHDRKT4K.js} +115 -25
  5. package/dist/{chunk-2RKYO3OC.js → chunk-R2V3X6SQ.js} +1 -1
  6. package/dist/{chunk-OMXAE27N.js → chunk-V46XM2GU.js} +4 -0
  7. package/dist/{chunk-WSLADX7O.js → chunk-YSWKFXXG.js} +306 -12
  8. package/dist/{chunk-5LSEBH3J.js → chunk-Z7AQEW6G.js} +4 -4
  9. package/dist/config.d.ts +1 -0
  10. package/dist/context.d.ts +37 -0
  11. package/dist/delegated.d.ts +2 -0
  12. package/dist/drafts.d.ts +5 -0
  13. package/dist/env.d.ts +2 -0
  14. package/dist/livedata.d.ts +14 -0
  15. package/dist/oidc.d.ts +12 -0
  16. package/dist/prompts/system.md +2 -1
  17. package/dist/requestScope.d.ts +10 -2
  18. package/dist/search-IBZ2BK2E.js +12 -0
  19. package/dist/worker_mcp/src/index.js +2 -2
  20. package/dist/worker_public/src/config.js +1 -1
  21. package/dist/worker_public/src/index.js +8 -8
  22. package/dist/worker_public/src/requestScope.js +2 -2
  23. package/docs/API.md +83 -0
  24. package/package.json +1 -1
  25. package/workers/shared/session.ts +10 -0
  26. package/workers/worker_public/prompts/system.md +2 -1
  27. package/workers/worker_public/src/apicalls.ts +447 -0
  28. package/workers/worker_public/src/ask.ts +58 -8
  29. package/workers/worker_public/src/auth.ts +7 -1
  30. package/workers/worker_public/src/config.ts +4 -0
  31. package/workers/worker_public/src/context.ts +89 -4
  32. package/workers/worker_public/src/delegated.ts +83 -0
  33. package/workers/worker_public/src/drafts.ts +10 -0
  34. package/workers/worker_public/src/env.ts +5 -1
  35. package/workers/worker_public/src/index.ts +4 -1
  36. package/workers/worker_public/src/livedata.ts +24 -2
  37. package/workers/worker_public/src/oidc.ts +35 -19
  38. package/workers/worker_public/src/ports/cloudflare/adapters.ts +8 -0
  39. package/workers/worker_public/src/requestScope.ts +9 -3
  40. package/dist/ask-GU554Y45.js +0 -12
  41. package/dist/search-LGDQR43R.js +0 -12
@@ -16,7 +16,7 @@ import {
16
16
  roleModel,
17
17
  sha256Hex,
18
18
  today
19
- } from "../../chunk-OMXAE27N.js";
19
+ } from "../../chunk-V46XM2GU.js";
20
20
  import "../../chunk-3FYJM7LH.js";
21
21
  export {
22
22
  DATASETS,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleSearch
3
- } from "../../chunk-5LSEBH3J.js";
3
+ } from "../../chunk-Z7AQEW6G.js";
4
4
  import {
5
5
  bindModelNode,
6
6
  checkQuoteAnchors,
@@ -9,7 +9,7 @@ import {
9
9
  modelGroundingBlock,
10
10
  scoreJudge,
11
11
  standardForDocNumber
12
- } from "../../chunk-WSLADX7O.js";
12
+ } from "../../chunk-YSWKFXXG.js";
13
13
  import {
14
14
  buildMessages,
15
15
  citations,
@@ -32,7 +32,7 @@ import {
32
32
  sessionFrom,
33
33
  telemetry,
34
34
  understandQuery
35
- } from "../../chunk-NHHQAGBW.js";
35
+ } from "../../chunk-GHDRKT4K.js";
36
36
  import {
37
37
  authenticate,
38
38
  corsHeaders,
@@ -41,14 +41,14 @@ import {
41
41
  readJson,
42
42
  validateQuery,
43
43
  withCors
44
- } from "../../chunk-2RKYO3OC.js";
44
+ } from "../../chunk-R2V3X6SQ.js";
45
45
  import {
46
46
  canonicalRefusal
47
47
  } from "../../chunk-A3QHHUN5.js";
48
48
  import {
49
49
  entitlementScope,
50
50
  standardKeysFrom
51
- } from "../../chunk-JGKSUSF5.js";
51
+ } from "../../chunk-4GJGBGJK.js";
52
52
  import {
53
53
  LIMITS,
54
54
  MODELS,
@@ -59,7 +59,7 @@ import {
59
59
  roleModel,
60
60
  sha256Hex,
61
61
  today
62
- } from "../../chunk-OMXAE27N.js";
62
+ } from "../../chunk-V46XM2GU.js";
63
63
  import {
64
64
  P,
65
65
  setProfile
@@ -996,7 +996,7 @@ async function handleMcp(env, ctx, req, tier, key) {
996
996
  // stream:false forces the JSON lane (anon defaults to SSE)
997
997
  body: JSON.stringify({ ...args, stream: false })
998
998
  });
999
- const res = name === "ask" ? await (await import("../../ask-GU554Y45.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-LGDQR43R.js")).handleSearch(env, ctx, inner, tier, key);
999
+ const res = name === "ask" ? await (await import("../../ask-P6KLPBKL.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-IBZ2BK2E.js")).handleSearch(env, ctx, inner, tier, key);
1000
1000
  return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
1001
1001
  });
1002
1002
  if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
@@ -1359,7 +1359,7 @@ async function tierFor(c) {
1359
1359
  if (!key) return err(401, "unauthorized", `Provide a valid API key: Authorization: Bearer ${P().publisher.id}_...`);
1360
1360
  }
1361
1361
  let tier = isApi ? "key" : "anon";
1362
- if (!isApi && c.env.SESSION_SECRET && await sessionFrom(c.req, c.env)) tier = "member";
1362
+ if (!isApi && await sessionFrom(c.req, c.env)) tier = "member";
1363
1363
  return { tier, key };
1364
1364
  }
1365
1365
  async function mcpRoute(c) {
@@ -4,8 +4,8 @@ import {
4
4
  requestSalt,
5
5
  resolveRequestScope,
6
6
  standardKeysFrom
7
- } from "../../chunk-JGKSUSF5.js";
8
- import "../../chunk-OMXAE27N.js";
7
+ } from "../../chunk-4GJGBGJK.js";
8
+ import "../../chunk-V46XM2GU.js";
9
9
  import "../../chunk-3FYJM7LH.js";
10
10
  export {
11
11
  entitlementScope,
package/docs/API.md CHANGED
@@ -117,6 +117,43 @@ a corpus document. The service applies it honestly:
117
117
  declaration, not just the query) and is never written into them.
118
118
  - Conversational turns (greetings, identity) never ground in a declared
119
119
  context — the echo reports `none`.
120
+ - The entity declaration may carry the affordance channel's `machine`
121
+ facet (TODO.ai-platform/08): the lifecycle machine's current `state`
122
+ (the fact) and the `acts` it offers there for the declaring user's
123
+ role (already role-filtered by the platform). The facet parses bounded
124
+ (state ≤ 60 chars, ≤ 24 acts, each `action`/`to`/`guard` ≤ 60), rides
125
+ the entity kind only, and BOUNDS the proposal grammar: a draft act the
126
+ set does not offer is never proposed, and an empty `acts` array is the
127
+ honest "the user can read but not act" — the answer says so and no
128
+ draft rides. The facet is advisory; the platform re-validates every
129
+ draft act authoritatively on the way back.
130
+
131
+ ```jsonc
132
+ "context": {
133
+ "kind": "entity",
134
+ "label": "this application R60-2026-0042",
135
+ "route": "/app/ia/applications/R60-2026-0042",
136
+ "machine": { // the affordance channel — entity kind only
137
+ "state": "UNDER_REVIEW", // the machine's current state (the fact)
138
+ "acts": [ // offered FOR THE DECLARING USER'S ROLE — may be []
139
+ { "action": "ia_accepts", "to": "ACCEPTED" },
140
+ { "action": "ia_logs_samples", "to": "SAMPLES_RECEIVED", "guard": "receipt_complete" }
141
+ ]
142
+ }
143
+ }
144
+ ```
145
+
146
+ The echo carries the facet's fact + count, so the panel's honest context
147
+ line reads the service's applied truth, never its own copy:
148
+
149
+ ```jsonc
150
+ "context_applied": {
151
+ "kind": "entity",
152
+ "label": "this application R60-2026-0042",
153
+ "scoped_to": "OIML R 60:2021",
154
+ "machine": { "state": "UNDER_REVIEW", "offered": 2 }
155
+ }
156
+ ```
120
157
 
121
158
  Every ask response — the SSE `citations`/`done` events and the JSON body —
122
159
  echoes what was APPLIED, so the panel's context line never invents a
@@ -245,6 +282,52 @@ The honest rules, all eval-gated (the golden suite's `draft-*` legs):
245
282
 
246
283
  **SSE**: the `draft` rides the first (`citations`) frame beside
247
284
  `context_applied`; `token` frames carry the answer; `done` as usual.
285
+
286
+ ##### The api_call act (TODO.ai-platform/09 — the operations deployment)
287
+
288
+ The second draft act proposes ONE platform operation — the operations
289
+ assistant's grammar, feature-flagged (`features.api_call_drafts`; the
290
+ corpus-only deployment leaves it off):
291
+
292
+ ```jsonc
293
+ "draft": {
294
+ "kind": "draft",
295
+ "act": "api_call",
296
+ "version": 1,
297
+ "title": "Save the R 60 filter", // what the act DOES — never the wire shape
298
+ "prepared_at": "2026-09-26T09:00:00Z",
299
+ "requires_confirmation": true, // ALWAYS
300
+ "call": {
301
+ "method": "PUT", // a real operation from the plane —
302
+ "path": "/api/notify/preferences", // an invented path is a service bug
303
+ "body": { } // optional; preference bodies trace
304
+ } // to the user's own words
305
+ }
306
+ ```
307
+
308
+ The honest rules (the module is structurally write-free — it reads the
309
+ operation directory and calls the pick model; there is no platform IO):
310
+
311
+ - **The directory is the closed world**: the call names an operation the
312
+ deployment's `api_ops` directory (loaded from the OpenAPI plane at
313
+ ingest) actually carries. The model proposes an operation id; the
314
+ guard resolves it against the directory AFTER the fact — an invented
315
+ id or path never rides.
316
+ - **The machine facet bounds the machine acts** (§2.1.1): the entity
317
+ write composes only for an act the offered set carries, addressed to
318
+ the declared entity (the profile's route-pattern table maps the
319
+ page's route to the store and id). An empty offered set answers the
320
+ honest "you can read but not act" and proposes nothing.
321
+ - **The never-offer list holds** (profile data, `publisher.acts
322
+ .never_offer`): the auth family (signout is the user's own, forever)
323
+ and the grant's own mint/revoke (delegation is granted by the user's
324
+ hand on the settings page, never by a chat message) are excluded from
325
+ the pick prompt AND refused at the guard.
326
+ - **The act class is the platform's word, not the draft's**: the panel
327
+ pre-flights every api_call draft against the plane and the class
328
+ decides the arc — preference rides the standing grant's seam, record
329
+ confirms per act and executes as the user.
330
+
248
331
  The draft is ephemeral — the conversations API never persists it (a
249
332
  resumed session keeps the honest context line, not a stale draft).
250
333
 
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.33",
30
+ "version": "0.2.35",
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",
@@ -14,6 +14,16 @@ export interface SessionClaims {
14
14
  roles: string[];
15
15
  iat: number;
16
16
  exp: number;
17
+ /** the credential kind: absent = the service session; "delegated" =
18
+ * the OP-minted RFC 8693 bearer (TODO.ai-platform/12 — the session
19
+ * bridge; delegated.ts) */
20
+ via?: "delegated";
21
+ /** the delegating surface (the delegated bearer's act.sub — the
22
+ * platform instance's OP client) */
23
+ delegator?: string;
24
+ /** the delegated bearer's granted scope string (the platform read
25
+ * cone it carries — livedata reads through it directly) */
26
+ scope?: string;
17
27
  }
18
28
 
19
29
  export const SESSION_COOKIE = "rag_session";
@@ -1,4 +1,4 @@
1
- You are the OIML SMART AI assistant at ai.oimlsmart.org, a public service answering questions about OIML legal-metrology publications; be precise, professional and warm — a knowledgeable colleague, not a search box.{{HISTORY_CONTEXT}}
1
+ You are {{ASSISTANT_IDENTITY}}; be precise, professional and warm — a knowledgeable colleague, not a search box.{{HISTORY_CONTEXT}}
2
2
  Conversational turns — greetings, thanks, small talk, or questions about you and this service (who you are, which model you are, what you can do, what you search, how you work) — answer naturally, briefly, in first person, without citations. Never refuse them.
3
3
  Questions about the publisher itself ({{PUBLISHER_NAME}} — what it is, who it is, its role) are the same class: you know your own publisher a priori — {{PUBLISHER_IDENTITY}} — so answer briefly without citations and never refuse them. When context passages about the publisher do appear, prefer grounding the answer in them and cite them like any other passage.
4
4
  When earlier turns are provided, answer the LATEST message; earlier turns are context for resolving pronouns and ellipses.
@@ -15,6 +15,7 @@ MANDATORY: when the question asks how to do something (get certified, apply, com
15
15
  If the passages cover only part of the question, answer the covered part fully, then state precisely what the indexed publications do not cover — do not pad with outside knowledge.
16
16
  Refuse ONLY when no passage relates to the question's topic. Use exactly this sentence: {{REFUSAL_SENTENCE}} Then add one short line naming what you can answer instead, so the refusal redirects rather than dead-ends.
17
17
  {{LICENSE_POSTURE}}
18
+ {{SERVICE_POSTURE}}
18
19
  {{CORPUS_NOTES}}
19
20
  Lead with the direct answer, then supporting detail; no preamble like 'Based on the passages'. Use short paragraphs or bullets for multi-part answers. Be concise and precise. Answer in the question's language{{LANG_CLAUSE}}.
20
21
  - HARD RULE — typed units: passages whose header shows `unit u:xxxx (table)` contain a typed table. If your answer presents that table's data, you MUST write the token `[[u:xxxx]]` where the table belongs and MUST NOT render the table as markdown or reproduce more than ONE of its rows inline. Summarize the pattern in prose ("classes A–D with lower limits from 100 to 50 000"), cite the clause normally, and let `[[u:xxxx]]` stand for the full table — the interface renders it exactly from the source. The same rule applies to `unit u:xxxx (formula|figure|term)` objects.