@loomwork/ui-hydration 0.0.0-stage → 0.1.1

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 (179) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +398 -2
  4. package/dist/cache.d.ts +71 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/cache.js +157 -0
  7. package/dist/cache.js.map +1 -0
  8. package/dist/chatSource.d.ts +105 -0
  9. package/dist/chatSource.d.ts.map +1 -0
  10. package/dist/chatSource.js +264 -0
  11. package/dist/chatSource.js.map +1 -0
  12. package/dist/client.d.ts +17 -0
  13. package/dist/client.d.ts.map +1 -0
  14. package/dist/client.js +36 -0
  15. package/dist/client.js.map +1 -0
  16. package/dist/contentRefs.d.ts +78 -0
  17. package/dist/contentRefs.d.ts.map +1 -0
  18. package/dist/contentRefs.js +129 -0
  19. package/dist/contentRefs.js.map +1 -0
  20. package/dist/controller.d.ts +228 -0
  21. package/dist/controller.d.ts.map +1 -0
  22. package/dist/controller.js +454 -0
  23. package/dist/controller.js.map +1 -0
  24. package/dist/dataProvider.d.ts +53 -0
  25. package/dist/dataProvider.d.ts.map +1 -0
  26. package/dist/dataProvider.js +77 -0
  27. package/dist/dataProvider.js.map +1 -0
  28. package/dist/esm/cache.js +151 -0
  29. package/dist/esm/cache.js.map +1 -0
  30. package/dist/esm/chatSource.js +259 -0
  31. package/dist/esm/chatSource.js.map +1 -0
  32. package/dist/esm/client.js +15 -0
  33. package/dist/esm/client.js.map +1 -0
  34. package/dist/esm/contentRefs.js +119 -0
  35. package/dist/esm/contentRefs.js.map +1 -0
  36. package/dist/esm/controller.js +449 -0
  37. package/dist/esm/controller.js.map +1 -0
  38. package/dist/esm/dataProvider.js +72 -0
  39. package/dist/esm/dataProvider.js.map +1 -0
  40. package/dist/esm/index.js +15 -0
  41. package/dist/esm/index.js.map +1 -0
  42. package/dist/esm/invoker.js +2 -0
  43. package/dist/esm/invoker.js.map +1 -0
  44. package/dist/esm/invokers.js +310 -0
  45. package/dist/esm/invokers.js.map +1 -0
  46. package/dist/esm/loomEffectProvider.js +96 -0
  47. package/dist/esm/loomEffectProvider.js.map +1 -0
  48. package/dist/esm/params.js +207 -0
  49. package/dist/esm/params.js.map +1 -0
  50. package/dist/esm/path.js +24 -0
  51. package/dist/esm/path.js.map +1 -0
  52. package/dist/esm/plan.js +190 -0
  53. package/dist/esm/plan.js.map +1 -0
  54. package/dist/esm/projection.js +230 -0
  55. package/dist/esm/projection.js.map +1 -0
  56. package/dist/esm/provider.js +416 -0
  57. package/dist/esm/provider.js.map +1 -0
  58. package/dist/esm/repair.js +53 -0
  59. package/dist/esm/repair.js.map +1 -0
  60. package/dist/esm/reshape.js +156 -0
  61. package/dist/esm/reshape.js.map +1 -0
  62. package/dist/esm/restricted.js +54 -0
  63. package/dist/esm/restricted.js.map +1 -0
  64. package/dist/esm/scheduler.js +247 -0
  65. package/dist/esm/scheduler.js.map +1 -0
  66. package/dist/esm/select.js +18 -0
  67. package/dist/esm/select.js.map +1 -0
  68. package/dist/esm/shape.js +34 -0
  69. package/dist/esm/shape.js.map +1 -0
  70. package/dist/esm/split/client.js +312 -0
  71. package/dist/esm/split/client.js.map +1 -0
  72. package/dist/esm/split/index.js +3 -0
  73. package/dist/esm/split/index.js.map +1 -0
  74. package/dist/esm/split/server.js +488 -0
  75. package/dist/esm/split/server.js.map +1 -0
  76. package/dist/esm/split/shared.js +13 -0
  77. package/dist/esm/split/shared.js.map +1 -0
  78. package/dist/index.d.ts +29 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +63 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/invoker.d.ts +10 -0
  83. package/dist/invoker.d.ts.map +1 -0
  84. package/dist/invoker.js +3 -0
  85. package/dist/invoker.js.map +1 -0
  86. package/dist/invokers.d.ts +36 -0
  87. package/dist/invokers.d.ts.map +1 -0
  88. package/dist/invokers.js +315 -0
  89. package/dist/invokers.js.map +1 -0
  90. package/dist/loomEffectProvider.d.ts +67 -0
  91. package/dist/loomEffectProvider.d.ts.map +1 -0
  92. package/dist/loomEffectProvider.js +101 -0
  93. package/dist/loomEffectProvider.js.map +1 -0
  94. package/dist/params.d.ts +103 -0
  95. package/dist/params.d.ts.map +1 -0
  96. package/dist/params.js +221 -0
  97. package/dist/params.js.map +1 -0
  98. package/dist/path.d.ts +12 -0
  99. package/dist/path.d.ts.map +1 -0
  100. package/dist/path.js +28 -0
  101. package/dist/path.js.map +1 -0
  102. package/dist/plan.d.ts +56 -0
  103. package/dist/plan.d.ts.map +1 -0
  104. package/dist/plan.js +199 -0
  105. package/dist/plan.js.map +1 -0
  106. package/dist/projection.d.ts +122 -0
  107. package/dist/projection.d.ts.map +1 -0
  108. package/dist/projection.js +238 -0
  109. package/dist/projection.js.map +1 -0
  110. package/dist/provider.d.ts +152 -0
  111. package/dist/provider.d.ts.map +1 -0
  112. package/dist/provider.js +421 -0
  113. package/dist/provider.js.map +1 -0
  114. package/dist/repair.d.ts +18 -0
  115. package/dist/repair.d.ts.map +1 -0
  116. package/dist/repair.js +57 -0
  117. package/dist/repair.js.map +1 -0
  118. package/dist/reshape.d.ts +32 -0
  119. package/dist/reshape.d.ts.map +1 -0
  120. package/dist/reshape.js +164 -0
  121. package/dist/reshape.js.map +1 -0
  122. package/dist/restricted.d.ts +21 -0
  123. package/dist/restricted.d.ts.map +1 -0
  124. package/dist/restricted.js +61 -0
  125. package/dist/restricted.js.map +1 -0
  126. package/dist/scheduler.d.ts +82 -0
  127. package/dist/scheduler.d.ts.map +1 -0
  128. package/dist/scheduler.js +254 -0
  129. package/dist/scheduler.js.map +1 -0
  130. package/dist/select.d.ts +34 -0
  131. package/dist/select.d.ts.map +1 -0
  132. package/dist/select.js +21 -0
  133. package/dist/select.js.map +1 -0
  134. package/dist/shape.d.ts +3 -0
  135. package/dist/shape.d.ts.map +1 -0
  136. package/dist/shape.js +37 -0
  137. package/dist/shape.js.map +1 -0
  138. package/dist/split/client.d.ts +135 -0
  139. package/dist/split/client.d.ts.map +1 -0
  140. package/dist/split/client.js +316 -0
  141. package/dist/split/client.js.map +1 -0
  142. package/dist/split/index.d.ts +5 -0
  143. package/dist/split/index.d.ts.map +1 -0
  144. package/dist/split/index.js +14 -0
  145. package/dist/split/index.js.map +1 -0
  146. package/dist/split/server.d.ts +160 -0
  147. package/dist/split/server.d.ts.map +1 -0
  148. package/dist/split/server.js +496 -0
  149. package/dist/split/server.js.map +1 -0
  150. package/dist/split/shared.d.ts +6 -0
  151. package/dist/split/shared.d.ts.map +1 -0
  152. package/dist/split/shared.js +19 -0
  153. package/dist/split/shared.js.map +1 -0
  154. package/package.json +77 -3
  155. package/src/cache.ts +211 -0
  156. package/src/chatSource.ts +378 -0
  157. package/src/client.ts +46 -0
  158. package/src/contentRefs.ts +195 -0
  159. package/src/controller.ts +708 -0
  160. package/src/dataProvider.ts +141 -0
  161. package/src/index.ts +86 -0
  162. package/src/invoker.ts +14 -0
  163. package/src/invokers.ts +348 -0
  164. package/src/loomEffectProvider.ts +136 -0
  165. package/src/params.ts +314 -0
  166. package/src/path.ts +26 -0
  167. package/src/plan.ts +197 -0
  168. package/src/projection.ts +297 -0
  169. package/src/provider.ts +657 -0
  170. package/src/repair.ts +70 -0
  171. package/src/reshape.ts +193 -0
  172. package/src/restricted.ts +69 -0
  173. package/src/scheduler.ts +284 -0
  174. package/src/select.ts +59 -0
  175. package/src/shape.ts +39 -0
  176. package/src/split/client.ts +452 -0
  177. package/src/split/index.ts +18 -0
  178. package/src/split/server.ts +746 -0
  179. package/src/split/shared.ts +18 -0
@@ -0,0 +1,449 @@
1
+ import { MAX_TREE_DEPTH, checkKindValue, experienceHandles, handleKindsWithMedia, hasKindContract, hasMediaTypeNodes, isBroadcast, isChatKind, isMediaKind, mergeReadPolicy, treeDepth, } from "@loomwork/ui-core";
2
+ import { HydrationCache, normaliseKinds, specFingerprint } from "./cache";
3
+ import { assertContentRefConfig, contentRefEnv, inspectContentRefs, principalScoped, } from "./contentRefs";
4
+ import { limitInvoker, memoInvoker, signalInvoker } from "./invokers";
5
+ import { checkParams, paramsKey, relevantParams, } from "./params";
6
+ import { HydrationAudienceMismatchError, isReservedHandle, } from "./projection";
7
+ import { executeProvider, outcomeResult } from "./provider";
8
+ import { partitionByViewer, restrictedFinding, snapshotViewer } from "./restricted";
9
+ import { HandleScheduler, KEY_SEP, defaultTimer, disposedFinding, tooDeep, } from "./scheduler";
10
+ /**
11
+ * The question a load asks: the spec, and — for a `outputCheck: "contract"` provider only — the
12
+ * kinds it is checked against. A `"shape"` (or unset) provider's fingerprint must NEVER fold in
13
+ * kinds: its bound nodes' resolved kinds can change (a catalogue edit, a widened binding) without
14
+ * the provider itself changing, and that must not abort an in-flight load or force a re-run.
15
+ */
16
+ /**
17
+ * A kind whose value is a STRUCTURED contract the data boundary always enforces: a media display
18
+ * widget (a MediaRef, U9) or a chat transcript (a ChatValue, U8). Neither may ever be a streamed
19
+ * string, and neither may rely on a provider that declared only a shape.
20
+ */
21
+ const isStrictValueKind = (kind) => isMediaKind(kind) || isChatKind(kind);
22
+ /** Does a handle feed a media display widget or a chat transcript (so its value must meet that contract, always)? */
23
+ const feedsMedia = (kinds) => kinds.some(isStrictValueKind);
24
+ export function loadFingerprint(spec, kinds) {
25
+ if (spec.outputCheck !== "contract" || kinds.length === 0)
26
+ return specFingerprint(spec);
27
+ // Normalised exactly as the cache key normalises them: a reordered or repeated kinds list is
28
+ // the same question, and must not abort an in-flight load or force a re-run.
29
+ return `${specFingerprint(spec)}${KEY_SEP}${normaliseKinds(kinds).join(",")}`;
30
+ }
31
+ export class HydrationController {
32
+ opts;
33
+ cache;
34
+ clock;
35
+ sched;
36
+ current;
37
+ kinds = new Map();
38
+ globalParams = {};
39
+ scopedParams = new Map();
40
+ lifetime = new AbortController();
41
+ /**
42
+ * Throws `RangeError` for a `maxConcurrentCalls` that is not a positive integer, or
43
+ * `defaultParams` that `checkParams` refuses.
44
+ */
45
+ /** The viewer, copied once at construction so a live mutation of the caller's object is inert. */
46
+ viewer;
47
+ /**
48
+ * Handles that may take token chunks RIGHT NOW: bound by the current experience, cleared for the
49
+ * viewer, and (when output kinds are known) resolving to `StreamingText`. Rebuilt on every bind.
50
+ */
51
+ streamable = new Set();
52
+ bound = new Set();
53
+ policy;
54
+ broadcast;
55
+ audience;
56
+ constructor(opts) {
57
+ this.opts = opts;
58
+ assertContentRefConfig(opts.contentRefArgs, "HydrationController");
59
+ // Snapshotted ONCE: later mutation of `opts` must not lift the ceiling (see `setViewer`).
60
+ this.broadcast = isBroadcast(opts.audience);
61
+ this.audience = this.broadcast ? "broadcast" : "viewer";
62
+ if (this.broadcast !== isBroadcast(opts.store.scope.audience))
63
+ throw new HydrationAudienceMismatchError(this.broadcast);
64
+ this.policy = mergeReadPolicy(opts.readPolicy, {
65
+ ...(opts.declaredToolClasses !== undefined && {
66
+ declaredToolClasses: opts.declaredToolClasses,
67
+ }),
68
+ ...(opts.undeclared !== undefined && { undeclared: opts.undeclared }),
69
+ });
70
+ this.viewer = snapshotViewer(opts.viewer, this.audience);
71
+ opts.store.guardAppend((handle) => this.appendRefusal(handle));
72
+ this.clock = opts.clock ?? Date.now;
73
+ this.cache = opts.cache ?? new HydrationCache(this.clock);
74
+ if (opts.defaultParams !== undefined) {
75
+ const bad = checkParams(opts.defaultParams);
76
+ if (bad)
77
+ throw new RangeError(bad.message);
78
+ }
79
+ // ONE cap and ONE lifetime for the whole controller; a fresh memo per pass in front of them.
80
+ const calls = signalInvoker(opts.maxConcurrentCalls === undefined
81
+ ? opts.invoker
82
+ : limitInvoker(opts.invoker, opts.maxConcurrentCalls), this.lifetime.signal);
83
+ const principalId = opts.principal?.id;
84
+ const contracts = opts.outputKinds?.catalog.valueContracts;
85
+ const variant = (job) => job.kinds === undefined
86
+ ? { params: job.params }
87
+ : {
88
+ params: job.params,
89
+ kinds: job.kinds,
90
+ ...(contracts !== undefined && { contracts }),
91
+ };
92
+ this.sched = new HandleScheduler(opts.store, {
93
+ newGroup: () => ({ now: this.clock(), invoker: memoInvoker(calls) }),
94
+ run: (job, signal, pass) => this.run(job, signal, pass),
95
+ // U9b: the content-reference guard (gate included) runs BEFORE the cache is read: a cached value
96
+ // was produced for an argument some principal's gate accepted once; serving it to another
97
+ // principal, or after the host revoked it, would skip the gate. A refusal is a miss (the load
98
+ // refuses it); a param that fills a guarded argument is cached per principal only.
99
+ cached: (job) => {
100
+ const verdict = this.refsVerdict(job);
101
+ return verdict?.refusal !== undefined
102
+ ? undefined
103
+ : this.cache.get(verdict?.paramFilled ? principalScoped(job.spec) : job.spec, principalId, variant(job));
104
+ },
105
+ commit: (job, r) => {
106
+ // Only `ready` is cached — an `empty` answer has no value (loom ADR 0100), so nothing
107
+ // is stored. The scheduler still treats it as ANSWERED for the same question: it is
108
+ // re-asked only when the question changes, on `invalidate`, or on a new bind (and then
109
+ // never served from the cache). A result that proceeded past an input drift (`report-and-proceed`) is never cached:
110
+ // the key does not carry the drift mode, so a controller sharing the cache under the
111
+ // default (`report`) would be served it as a clean `ready` — no stale, no `onDrift`.
112
+ if (r.state === "ready" && r.drift.length === 0) {
113
+ const verdict = this.refsVerdict(job);
114
+ if (verdict?.refusal === undefined)
115
+ this.cache.set(verdict?.paramFilled ? principalScoped(job.spec) : job.spec, principalId, r.value, variant(job));
116
+ }
117
+ },
118
+ published: (job, r) => {
119
+ if (r.drift.length === 0)
120
+ return;
121
+ this.opts.onDrift?.({
122
+ experienceId: job.experienceId,
123
+ versionHash: job.versionHash,
124
+ handle: job.handle,
125
+ spec: job.spec,
126
+ drift: r.drift,
127
+ findings: r.findings,
128
+ // A proceeded input drift can sit beside an `empty` answer (the retried upstream had
129
+ // no rows): still proceeded. `empty` itself never adds drift, so it alone never lands here.
130
+ proceeded: r.state === "ready" || r.state === "empty",
131
+ });
132
+ },
133
+ }, opts.setTimer ?? defaultTimer, opts.batchWindowMs ?? 50);
134
+ }
135
+ /**
136
+ * Bind an experience: schedule every handle it binds. Findings for handles that cannot load.
137
+ * A second `load` while one experience is already bound IS a recompose — the previous
138
+ * experience's handles are aborted and dropped rather than left published forever.
139
+ */
140
+ load(exp) {
141
+ if (this.sched.isDisposed)
142
+ return { findings: [disposedFinding("load")] };
143
+ if (this.current !== undefined)
144
+ return this.recompose(exp);
145
+ return this.bind(exp);
146
+ }
147
+ /**
148
+ * Replace the viewer and re-plan the bound experience: a handle the new viewer may not see is
149
+ * aborted and dropped (an in-flight result is discarded, a loaded value removed), one it newly
150
+ * may see is scheduled. Before any `load` it only records the viewer.
151
+ */
152
+ setViewer(viewer) {
153
+ if (this.sched.isDisposed)
154
+ return { findings: [disposedFinding("setViewer")] };
155
+ this.viewer = snapshotViewer(viewer, this.audience);
156
+ return this.current === undefined ? { findings: [] } : this.recompose(this.current);
157
+ }
158
+ /**
159
+ * Append one token chunk to a `StreamingText` handle, through the same viewer gate as `load`:
160
+ * refused (a finding, nothing written) for a handle that is not bound by the current
161
+ * experience (`stream-unbound`), is restricted for the viewer (`restricted`, the fixed text that
162
+ * names nothing), or — when `outputKinds` is configured — does not resolve to `StreamingText`
163
+ * (`stream-kind-mismatch`). Without `outputKinds` the kind is unknown and is not checked. The
164
+ * store's own `append` is gated by the same rule once a controller fronts it.
165
+ */
166
+ append(handle, chunk) {
167
+ return this.opts.store.append(handle, chunk);
168
+ }
169
+ /**
170
+ * Publish a value for a handle that is NOT loaded by a provider (a live transcript a browser
171
+ * connection folds, ...), through the same gates as a load: the handle must be bound by the current
172
+ * experience, must not be restricted for the viewer (`restricted`, the fixed text that names
173
+ * nothing), must resolve to the kind the caller names (when it names one), and the value must pass
174
+ * EVERY bound kind's contract (a kind with none is refused: nothing is published unchecked).
175
+ * Refused = a finding and nothing written.
176
+ */
177
+ publishValue(handle, value, options = {}) {
178
+ const refuse = (code, message) => ({
179
+ ok: false,
180
+ finding: { code, severity: "error", message },
181
+ });
182
+ if (this.sched.isDisposed || isReservedHandle(handle) || !this.bound.has(handle))
183
+ return refuse("publish-unbound", "the handle is not bound by the current experience; the value was refused");
184
+ if (this.restrictedHandles.has(handle))
185
+ return { ok: false, finding: restrictedFinding() };
186
+ const kinds = this.kinds.get(handle) ?? [];
187
+ if (kinds.length === 0 || (options.kind !== undefined && !kinds.includes(options.kind)))
188
+ return refuse("publish-kind-mismatch", "the handle's widget does not take this value; refused");
189
+ const contracts = this.opts.outputKinds?.catalog.valueContracts;
190
+ for (const kind of kinds) {
191
+ if (!hasKindContract(kind, contracts))
192
+ return refuse("publish-uncontracted", "the handle's widget has no value contract; refused");
193
+ const check = checkKindValue(kind, value, contracts);
194
+ if (!check.ok)
195
+ return { ok: false, finding: check.finding };
196
+ }
197
+ this.opts.store.setValue(handle, value, { state: options.state ?? "ready" });
198
+ return { ok: true };
199
+ }
200
+ appendRefusal(handle) {
201
+ if (this.sched.isDisposed || !this.bound.has(handle))
202
+ return {
203
+ code: "stream-unbound",
204
+ severity: "error",
205
+ message: "the handle is not bound by the current experience; the chunk was refused",
206
+ };
207
+ if (this.streamable.has(handle))
208
+ return undefined;
209
+ // Bound but not streamable: restricted for the viewer, or the wrong widget kind.
210
+ return this.restrictedHandles.has(handle)
211
+ ? restrictedFinding()
212
+ : {
213
+ code: "stream-kind-mismatch",
214
+ severity: "error",
215
+ message: "the handle's widget does not take a token stream (StreamingText); refused",
216
+ };
217
+ }
218
+ restrictedHandles = new Set();
219
+ /** The surface reports a lazy (P2) widget entered the viewport. */
220
+ markVisible(handle) {
221
+ this.sched.markVisible(handle);
222
+ }
223
+ /** A new artifact replaces the current one: abort and drop unbound handles, keep the rest, load new ones. */
224
+ recompose(next) {
225
+ if (this.sched.isDisposed)
226
+ return { findings: [disposedFinding("recompose")] };
227
+ // Before anything is aborted or dropped: a tree we refuse to bind must leave the CURRENT
228
+ // one exactly as it was, not half-torn-down between two experiences.
229
+ if (treeDepth(next.root) > MAX_TREE_DEPTH)
230
+ return { findings: [tooDeep(next.experienceId, MAX_TREE_DEPTH)] };
231
+ this.sched.retain(new Set(partitionByViewer(experienceHandles(next, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer).allowed.map((h) => h.handle)));
232
+ return this.bind(next);
233
+ }
234
+ /**
235
+ * Replace the global params (no `scope.handle`) or one handle's scoped params, then re-ask
236
+ * every bound handle whose question changed — only those, so a handle that ended on `error`
237
+ * with an unchanged question is NOT retried here (`invalidate` retries it). `{}` clears.
238
+ * Refused, with nothing changed, for params `checkParams` refuses or a reserved handle. A lazy
239
+ * (P2) handle whose question changed waits for its next `markVisible`. Params scoped to a handle
240
+ * the experience does not bind are kept only until the next bind, which forgets them.
241
+ */
242
+ setParams(params, scope = {}) {
243
+ if (this.sched.isDisposed)
244
+ return { findings: [disposedFinding("setParams")] };
245
+ const bad = checkParams(params);
246
+ if (bad)
247
+ return { findings: [bad] };
248
+ if (scope.handle !== undefined && isReservedHandle(scope.handle))
249
+ return {
250
+ findings: [
251
+ {
252
+ code: "invalid-handle",
253
+ severity: "error",
254
+ message: `handle "${scope.handle}" is reserved`,
255
+ },
256
+ ],
257
+ };
258
+ const before = this.current === undefined
259
+ ? new Map()
260
+ : new Map(this.plan(this.current).jobs.map((j) => [j.handle, j.fingerprint]));
261
+ // A copy (own enumerable keys only): a caller mutating its object later changes nothing.
262
+ const copy = Object.fromEntries(Object.entries(params));
263
+ if (scope.handle === undefined)
264
+ this.globalParams = copy;
265
+ else
266
+ this.scopedParams.set(scope.handle, copy);
267
+ if (this.current !== undefined)
268
+ this.sched.schedule(this.plan(this.current).jobs.filter((j) => before.get(j.handle) !== j.fingerprint));
269
+ return { findings: [] };
270
+ }
271
+ /**
272
+ * Drop cached results (one handle or all) and reload the affected bound handles. An in-flight
273
+ * load answering the invalidated question is superseded; a lazy (P2) widget stays lazy.
274
+ */
275
+ invalidate(handle) {
276
+ if (this.sched.isDisposed)
277
+ return { findings: [disposedFinding("invalidate")] };
278
+ this.cache.invalidate(handle);
279
+ if (this.current === undefined)
280
+ return { findings: [] };
281
+ const jobs = this.plan(this.current).jobs;
282
+ this.sched.reload(handle === undefined ? jobs : jobs.filter((j) => j.handle === handle));
283
+ return { findings: [] };
284
+ }
285
+ inFlight() {
286
+ return this.sched.inFlight();
287
+ }
288
+ /** Terminal: every in-flight load is aborted and reported, and nothing schedules again. */
289
+ dispose() {
290
+ this.sched.dispose();
291
+ this.lifetime.abort();
292
+ this.current = undefined;
293
+ this.bound = new Set();
294
+ this.streamable = new Set();
295
+ this.restrictedHandles = new Set();
296
+ this.globalParams = {};
297
+ this.scopedParams.clear();
298
+ }
299
+ bind(exp) {
300
+ if (treeDepth(exp.root) > MAX_TREE_DEPTH)
301
+ return { findings: [tooDeep(exp.experienceId, MAX_TREE_DEPTH)] };
302
+ this.current = exp;
303
+ // U9: media-typed nodes mark their handle as media even with NO `outputKinds` (fail closed).
304
+ this.kinds = handleKindsWithMedia(exp, this.opts.outputKinds?.catalog, this.opts.outputKinds?.surface);
305
+ // Scoped params outlive a bind only for handles it binds (set before a load, or kept across
306
+ // a recompose); the rest are forgotten, so they never resurface on a later experience.
307
+ // Handle-id collection only (which handles are bound at all): no class is read, so the declared
308
+ // table is deliberately not passed. The viewer-gated partition below does take it.
309
+ const bound = new Set(experienceHandles(exp).map((h) => h.handle));
310
+ for (const handle of [...this.scopedParams.keys()])
311
+ if (!bound.has(handle))
312
+ this.scopedParams.delete(handle);
313
+ const { jobs, findings, missing } = this.plan(exp);
314
+ for (const m of missing)
315
+ this.opts.store.setStatus(m.handle, { state: "error", finding: m.finding });
316
+ // Refused handles: their status says so (and nothing else), and no job exists for them.
317
+ const { allowed, restricted, advisory } = partitionByViewer(experienceHandles(exp, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer);
318
+ this.bound = new Set(bound);
319
+ this.restrictedHandles = new Set(restricted.map((r) => r.handle));
320
+ this.streamable = new Set(allowed
321
+ .map((a) => a.handle)
322
+ .filter((h) =>
323
+ // A media- or chat-bound handle is never streamable: a text chunk must not overwrite a MediaRef or a transcript,
324
+ // and with no `outputKinds` the kinds known here are the node-type media ones only.
325
+ !(this.kinds.get(h) ?? []).some(isStrictValueKind) &&
326
+ (this.opts.outputKinds === undefined ||
327
+ (this.kinds.get(h) ?? []).includes("StreamingText"))));
328
+ for (const r of restricted) {
329
+ if (isReservedHandle(r.handle))
330
+ continue;
331
+ // NOTHING is written for it: no value and no status, because a store projected to a client
332
+ // would reveal the handle's name (and that it is restricted) through its status key.
333
+ this.opts.store.remove(r.handle);
334
+ }
335
+ this.sched.schedule(jobs);
336
+ const mediaAdvice = this.opts.outputKinds === undefined && hasMediaTypeNodes(exp)
337
+ ? [
338
+ {
339
+ code: "media-output-kinds-missing",
340
+ severity: "warn",
341
+ message: "the experience has media nodes and the controller has no outputKinds: media handles are contract-checked by node type, but pass outputKinds so kinds resolve through the catalogue",
342
+ },
343
+ ]
344
+ : [];
345
+ const refsAdvice = this.opts.contentRefArgs === "none" && hasMediaTypeNodes(exp)
346
+ ? [
347
+ {
348
+ code: "media-content-refs-unguarded",
349
+ severity: "warn",
350
+ message: 'the experience has media nodes and the controller runs with contentRefArgs: "none": a content-reference tool argument is not checked; derive the table with contentRefArgsFrom(capabilities)',
351
+ },
352
+ ]
353
+ : [];
354
+ return { findings: [...findings, ...advisory, ...mediaAdvice, ...refsAdvice] };
355
+ }
356
+ /** Pure: the jobs `exp` asks for right now, and the handles that cannot load (with why). */
357
+ plan(exp) {
358
+ const jobs = [];
359
+ const findings = [];
360
+ const missing = [];
361
+ // A restricted handle is not a job: it never reaches the scheduler, the cache or a provider.
362
+ for (const use of partitionByViewer(experienceHandles(exp, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer).allowed) {
363
+ if (isReservedHandle(use.handle)) {
364
+ findings.push({
365
+ code: "invalid-handle",
366
+ severity: "error",
367
+ message: `handle "${use.handle}" is reserved`,
368
+ });
369
+ continue;
370
+ }
371
+ const declared = Object.hasOwn(exp.providers, use.handle)
372
+ ? exp.providers[use.handle]
373
+ : undefined;
374
+ if (declared === undefined) {
375
+ const f = {
376
+ code: "unknown-handle",
377
+ severity: "error",
378
+ message: `nodes ${use.nodeIds.join(", ")} bind "${use.handle}", which has no provider`,
379
+ };
380
+ findings.push(f);
381
+ missing.push({ handle: use.handle, finding: f });
382
+ continue;
383
+ }
384
+ const kinds = this.kinds.get(use.handle) ?? [];
385
+ // U9: a handle feeding a media widget is ALWAYS contract-checked (the MediaRef contract), whatever
386
+ // the provider declared. A shape pin passes any value of the pinned shape — inline bytes or a
387
+ // locator included — and what is published here reaches the store, a seen log and a client.
388
+ const spec = feedsMedia(kinds) && declared.outputCheck !== "contract"
389
+ ? { ...declared, outputCheck: "contract" }
390
+ : declared;
391
+ // Keyed on the params the provider can USE, never the raw bag: an unrelated param must
392
+ // neither re-run the load nor split its cache entry.
393
+ const params = relevantParams(spec, {
394
+ ...this.opts.defaultParams,
395
+ ...this.globalParams,
396
+ ...this.scopedParams.get(use.handle),
397
+ });
398
+ jobs.push({
399
+ handle: use.handle,
400
+ priority: use.priority,
401
+ spec,
402
+ params,
403
+ // Only a contract provider's checked value is answerable to a kind; the cache key and
404
+ // `executeProvider` ignore kinds for any other provider anyway.
405
+ kinds: spec.outputCheck === "contract" ? kinds : undefined,
406
+ experienceId: exp.experienceId,
407
+ versionHash: exp.versionHash,
408
+ fingerprint: `${paramsKey(params)}${KEY_SEP}${loadFingerprint(spec, kinds)}`,
409
+ });
410
+ }
411
+ return { jobs, findings, missing };
412
+ }
413
+ /** The content-reference guard over a whole job (asks the host's gate now); `undefined` when nothing is guarded. */
414
+ refsVerdict(job) {
415
+ const table = this.opts.contentRefArgs;
416
+ if (table === "none")
417
+ return undefined;
418
+ return inspectContentRefs(job.spec, job.params, contentRefEnv(table, job.spec, this.opts.acceptContentRefParam, {
419
+ principalId: this.opts.principal?.id,
420
+ principal: this.opts.principal?.chain,
421
+ }));
422
+ }
423
+ async run(job, signal, pass) {
424
+ const outcome = await executeProvider(job.spec, {
425
+ invoker: pass.invoker,
426
+ signal,
427
+ now: pass.now,
428
+ params: job.params,
429
+ ...(job.kinds !== undefined && { kinds: job.kinds }),
430
+ ...(this.opts.outputKinds?.catalog.valueContracts !== undefined && {
431
+ contracts: this.opts.outputKinds.catalog.valueContracts,
432
+ }),
433
+ ...(this.opts.principal?.chain && { principal: this.opts.principal.chain }),
434
+ ...(this.opts.concurrency !== undefined && { concurrency: this.opts.concurrency }),
435
+ ...(this.opts.inputDrift !== undefined && { inputDrift: this.opts.inputDrift }),
436
+ ...(this.opts.argumentHook !== undefined && { argumentHook: this.opts.argumentHook }),
437
+ ...(this.opts.contentRefArgs !== "none" && { contentRefArgs: this.opts.contentRefArgs }),
438
+ ...(this.opts.principal?.id !== undefined && { principalId: this.opts.principal.id }),
439
+ ...(this.opts.acceptContentRefParam !== undefined && {
440
+ acceptContentRefParam: this.opts.acceptContentRefParam,
441
+ }),
442
+ ...(this.opts.reshapers !== undefined && { reshapers: this.opts.reshapers }),
443
+ ...(this.opts.providers !== undefined && { providers: this.opts.providers }),
444
+ ...(this.opts.captureSample !== undefined && { captureSample: this.opts.captureSample }),
445
+ });
446
+ return { ...outcomeResult(outcome), drift: outcome.drift ?? [], findings: outcome.findings };
447
+ }
448
+ }
449
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { TypedFailure } from "@loomwork/core";
2
+ import { MCP_INVOKE_TOOL_ID } from "@loomwork/plugin-mcp";
3
+ import { DEFAULT_STEP_KIND, STEP_KIND_PATTERN } from "@loomwork/ui-core";
4
+ /**
5
+ * Build a registry. Refuses a malformed or duplicate kind id: two providers for one kind would
6
+ * make what a stored experience means depend on registration order.
7
+ */
8
+ export function defineDataProviders(providers) {
9
+ const byKind = new Map();
10
+ for (const p of providers) {
11
+ if (typeof p.kind !== "string" || !STEP_KIND_PATTERN.test(p.kind))
12
+ throw new TypeError(`defineDataProviders: "${String(p.kind)}" is not a valid kind id`);
13
+ if (byKind.has(p.kind))
14
+ throw new TypeError(`defineDataProviders: kind "${p.kind}" is registered twice`);
15
+ byKind.set(p.kind, p);
16
+ }
17
+ const sorted = Object.freeze([...byKind.keys()].sort());
18
+ return {
19
+ has: (kind) => byKind.has(kind),
20
+ get: (kind) => byKind.get(kind),
21
+ kinds: () => sorted,
22
+ };
23
+ }
24
+ /** The MCP kind: `mcp.invoke` with the pin as `expectedSchemaHash` (the plugin verifies it per call). */
25
+ export const mcpProvider = Object.freeze({
26
+ kind: DEFAULT_STEP_KIND,
27
+ invoke: (call, invoker, opts) => invoker.invokeTransient(MCP_INVOKE_TOOL_ID, { toolName: call.target, args: call.args, expectedSchemaHash: call.expectedPin }, opts),
28
+ });
29
+ /** What `executeProvider` uses when the host registers nothing: MCP only — the behaviour before kinds. */
30
+ export const DEFAULT_DATA_PROVIDERS = defineDataProviders([mcpProvider]);
31
+ /**
32
+ * Assert the one rule every kind must keep: a wrong pin is `schemaDrift` carrying the observed
33
+ * pin, and the right pin runs the target. Run it in a kind's own test suite against a target the
34
+ * kind serves (`target`, with its current `pin`) and a recording invoker. Returns a list of
35
+ * violations (empty = conformant); never throws for a violation. A wrong pin must ALSO not reach
36
+ * the target (a direct call to `target` through the invoker is counted). This is a TEST HELPER: `defineDataProviders`
37
+ * cannot enforce the rule at registration, so a kind that skips this suite is unchecked.
38
+ */
39
+ export async function checkDataProviderConformance(provider, fixture) {
40
+ const problems = [];
41
+ let reached = 0;
42
+ const counting = {
43
+ invokeTransient: (...a) => {
44
+ // Only a call to the target's OWN id counts: the MCP kind reaches `mcp.invoke`, whose pin
45
+ // check lives inside that effect (and is MCP's own conformance, not this kit's).
46
+ if (a[0] === fixture.target)
47
+ reached++;
48
+ return fixture.invoker.invokeTransient(...a);
49
+ },
50
+ };
51
+ const base = { stepId: "conformance", target: fixture.target, args: {} };
52
+ try {
53
+ await provider.invoke({ ...base, expectedPin: `${fixture.pin}-stale` }, counting, {});
54
+ problems.push("a stale pin did not fail");
55
+ }
56
+ catch (e) {
57
+ if (!(e instanceof TypedFailure && e.channel === "schemaDrift"))
58
+ problems.push("a stale pin failed, but not as TypedFailure(schemaDrift)");
59
+ else if (e.payload?.observedHash !== fixture.pin)
60
+ problems.push("schemaDrift did not carry the target's current pin as observedHash");
61
+ }
62
+ if (reached > 0)
63
+ problems.push("a stale pin reached the target before failing");
64
+ try {
65
+ await provider.invoke({ ...base, expectedPin: fixture.pin }, fixture.invoker, {});
66
+ }
67
+ catch (e) {
68
+ problems.push(`the current pin did not run the target: ${e instanceof Error ? e.message : e}`);
69
+ }
70
+ return problems;
71
+ }
72
+ //# sourceMappingURL=dataProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataProvider.js","sourceRoot":"","sources":["../../src/dataProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export { HYDRATION_PROJECTION_ID, HYDRATION_PROJECTION_VERSION, HYDRATION_SET_EVENT, HydrationAudienceMismatchError, HydrationScopeError, HydrationStore, hydrationProjection, isReservedHandle, } from "./projection";
2
+ export { limitInvoker, memoInvoker, signalInvoker } from "./invokers";
3
+ export { defineReshapers, jsonPathSelect, outputShapeHashOf } from "./reshape";
4
+ export { DEFAULT_TIME_RANGE, checkParams } from "./params";
5
+ export { ContentRefConfigError } from "./contentRefs";
6
+ export { DEFAULT_DATA_PROVIDERS, checkDataProviderConformance, defineDataProviders, mcpProvider, } from "./dataProvider";
7
+ export { LOOM_EFFECT_KIND, TARGET_FAILED, TARGET_UNREGISTERED, effectPin, loomEffectProvider, } from "./loomEffectProvider";
8
+ export { executeProvider } from "./provider";
9
+ export { stepReferences, terminalSteps, topoWaves } from "./plan";
10
+ export { DEFAULT_CACHE_MAX_ENTRIES, HydrationCache } from "./cache";
11
+ export { HydrationController } from "./controller";
12
+ export { DEFAULT_MAX_BATCH, DEFAULT_MAX_CONCURRENT_CALLS, SplitHydrationController, createServeSurface, handleInventory, publicFinding, serveHandle, serveHandles, } from "./split/index";
13
+ export { SCHEMA_REPAIRED, remapOperation } from "./repair";
14
+ export { connectConversation, publishChat } from "./chatSource";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,mBAAmB,EACnB,8BAA8B,EAC9B,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE/E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAOtD,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,mBAAmB,EACnB,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAElE,OAAO,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,WAAW,EACX,YAAY,GACb,MAAM,eAAe,CAAC;AAYvB,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE3D,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=invoker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoker.js","sourceRoot":"","sources":["../../src/invoker.ts"],"names":[],"mappings":""}