@loomwork/ui-hydration 0.0.0-stage → 0.1.0

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 +259 -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 +254 -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 +309 -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 +132 -0
  139. package/dist/split/client.d.ts.map +1 -0
  140. package/dist/split/client.js +313 -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 +374 -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 +449 -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,454 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HydrationController = void 0;
4
+ exports.loadFingerprint = loadFingerprint;
5
+ const ui_core_1 = require("@loomwork/ui-core");
6
+ const cache_1 = require("./cache");
7
+ const contentRefs_1 = require("./contentRefs");
8
+ const invokers_1 = require("./invokers");
9
+ const params_1 = require("./params");
10
+ const projection_1 = require("./projection");
11
+ const provider_1 = require("./provider");
12
+ const restricted_1 = require("./restricted");
13
+ const scheduler_1 = require("./scheduler");
14
+ /**
15
+ * The question a load asks: the spec, and — for a `outputCheck: "contract"` provider only — the
16
+ * kinds it is checked against. A `"shape"` (or unset) provider's fingerprint must NEVER fold in
17
+ * kinds: its bound nodes' resolved kinds can change (a catalogue edit, a widened binding) without
18
+ * the provider itself changing, and that must not abort an in-flight load or force a re-run.
19
+ */
20
+ /**
21
+ * A kind whose value is a STRUCTURED contract the data boundary always enforces: a media display
22
+ * widget (a MediaRef, U9) or a chat transcript (a ChatValue, U8). Neither may ever be a streamed
23
+ * string, and neither may rely on a provider that declared only a shape.
24
+ */
25
+ const isStrictValueKind = (kind) => (0, ui_core_1.isMediaKind)(kind) || (0, ui_core_1.isChatKind)(kind);
26
+ /** Does a handle feed a media display widget or a chat transcript (so its value must meet that contract, always)? */
27
+ const feedsMedia = (kinds) => kinds.some(isStrictValueKind);
28
+ function loadFingerprint(spec, kinds) {
29
+ if (spec.outputCheck !== "contract" || kinds.length === 0)
30
+ return (0, cache_1.specFingerprint)(spec);
31
+ // Normalised exactly as the cache key normalises them: a reordered or repeated kinds list is
32
+ // the same question, and must not abort an in-flight load or force a re-run.
33
+ return `${(0, cache_1.specFingerprint)(spec)}${scheduler_1.KEY_SEP}${(0, cache_1.normaliseKinds)(kinds).join(",")}`;
34
+ }
35
+ class HydrationController {
36
+ opts;
37
+ cache;
38
+ clock;
39
+ sched;
40
+ current;
41
+ kinds = new Map();
42
+ globalParams = {};
43
+ scopedParams = new Map();
44
+ lifetime = new AbortController();
45
+ /**
46
+ * Throws `RangeError` for a `maxConcurrentCalls` that is not a positive integer, or
47
+ * `defaultParams` that `checkParams` refuses.
48
+ */
49
+ /** The viewer, copied once at construction so a live mutation of the caller's object is inert. */
50
+ viewer;
51
+ /**
52
+ * Handles that may take token chunks RIGHT NOW: bound by the current experience, cleared for the
53
+ * viewer, and (when output kinds are known) resolving to `StreamingText`. Rebuilt on every bind.
54
+ */
55
+ streamable = new Set();
56
+ bound = new Set();
57
+ policy;
58
+ broadcast;
59
+ audience;
60
+ constructor(opts) {
61
+ this.opts = opts;
62
+ (0, contentRefs_1.assertContentRefConfig)(opts.contentRefArgs, "HydrationController");
63
+ // Snapshotted ONCE: later mutation of `opts` must not lift the ceiling (see `setViewer`).
64
+ this.broadcast = (0, ui_core_1.isBroadcast)(opts.audience);
65
+ this.audience = this.broadcast ? "broadcast" : "viewer";
66
+ if (this.broadcast !== (0, ui_core_1.isBroadcast)(opts.store.scope.audience))
67
+ throw new projection_1.HydrationAudienceMismatchError(this.broadcast);
68
+ this.policy = (0, ui_core_1.mergeReadPolicy)(opts.readPolicy, {
69
+ ...(opts.declaredToolClasses !== undefined && {
70
+ declaredToolClasses: opts.declaredToolClasses,
71
+ }),
72
+ ...(opts.undeclared !== undefined && { undeclared: opts.undeclared }),
73
+ });
74
+ this.viewer = (0, restricted_1.snapshotViewer)(opts.viewer, this.audience);
75
+ opts.store.guardAppend((handle) => this.appendRefusal(handle));
76
+ this.clock = opts.clock ?? Date.now;
77
+ this.cache = opts.cache ?? new cache_1.HydrationCache(this.clock);
78
+ if (opts.defaultParams !== undefined) {
79
+ const bad = (0, params_1.checkParams)(opts.defaultParams);
80
+ if (bad)
81
+ throw new RangeError(bad.message);
82
+ }
83
+ // ONE cap and ONE lifetime for the whole controller; a fresh memo per pass in front of them.
84
+ const calls = (0, invokers_1.signalInvoker)(opts.maxConcurrentCalls === undefined
85
+ ? opts.invoker
86
+ : (0, invokers_1.limitInvoker)(opts.invoker, opts.maxConcurrentCalls), this.lifetime.signal);
87
+ const principalId = opts.principal?.id;
88
+ const contracts = opts.outputKinds?.catalog.valueContracts;
89
+ const variant = (job) => job.kinds === undefined
90
+ ? { params: job.params }
91
+ : {
92
+ params: job.params,
93
+ kinds: job.kinds,
94
+ ...(contracts !== undefined && { contracts }),
95
+ };
96
+ this.sched = new scheduler_1.HandleScheduler(opts.store, {
97
+ newGroup: () => ({ now: this.clock(), invoker: (0, invokers_1.memoInvoker)(calls) }),
98
+ run: (job, signal, pass) => this.run(job, signal, pass),
99
+ // U9b: the content-reference guard (gate included) runs BEFORE the cache is read: a cached value
100
+ // was produced for an argument some principal's gate accepted once; serving it to another
101
+ // principal, or after the host revoked it, would skip the gate. A refusal is a miss (the load
102
+ // refuses it); a param that fills a guarded argument is cached per principal only.
103
+ cached: (job) => {
104
+ const verdict = this.refsVerdict(job);
105
+ return verdict?.refusal !== undefined
106
+ ? undefined
107
+ : this.cache.get(verdict?.paramFilled ? (0, contentRefs_1.principalScoped)(job.spec) : job.spec, principalId, variant(job));
108
+ },
109
+ commit: (job, r) => {
110
+ // Only `ready` is cached — an `empty` answer has no value (loom ADR 0100), so nothing
111
+ // is stored. The scheduler still treats it as ANSWERED for the same question: it is
112
+ // re-asked only when the question changes, on `invalidate`, or on a new bind (and then
113
+ // never served from the cache). A result that proceeded past an input drift (`report-and-proceed`) is never cached:
114
+ // the key does not carry the drift mode, so a controller sharing the cache under the
115
+ // default (`report`) would be served it as a clean `ready` — no stale, no `onDrift`.
116
+ if (r.state === "ready" && r.drift.length === 0) {
117
+ const verdict = this.refsVerdict(job);
118
+ if (verdict?.refusal === undefined)
119
+ this.cache.set(verdict?.paramFilled ? (0, contentRefs_1.principalScoped)(job.spec) : job.spec, principalId, r.value, variant(job));
120
+ }
121
+ },
122
+ published: (job, r) => {
123
+ if (r.drift.length === 0)
124
+ return;
125
+ this.opts.onDrift?.({
126
+ experienceId: job.experienceId,
127
+ versionHash: job.versionHash,
128
+ handle: job.handle,
129
+ spec: job.spec,
130
+ drift: r.drift,
131
+ findings: r.findings,
132
+ // A proceeded input drift can sit beside an `empty` answer (the retried upstream had
133
+ // no rows): still proceeded. `empty` itself never adds drift, so it alone never lands here.
134
+ proceeded: r.state === "ready" || r.state === "empty",
135
+ });
136
+ },
137
+ }, opts.setTimer ?? scheduler_1.defaultTimer, opts.batchWindowMs ?? 50);
138
+ }
139
+ /**
140
+ * Bind an experience: schedule every handle it binds. Findings for handles that cannot load.
141
+ * A second `load` while one experience is already bound IS a recompose — the previous
142
+ * experience's handles are aborted and dropped rather than left published forever.
143
+ */
144
+ load(exp) {
145
+ if (this.sched.isDisposed)
146
+ return { findings: [(0, scheduler_1.disposedFinding)("load")] };
147
+ if (this.current !== undefined)
148
+ return this.recompose(exp);
149
+ return this.bind(exp);
150
+ }
151
+ /**
152
+ * Replace the viewer and re-plan the bound experience: a handle the new viewer may not see is
153
+ * aborted and dropped (an in-flight result is discarded, a loaded value removed), one it newly
154
+ * may see is scheduled. Before any `load` it only records the viewer.
155
+ */
156
+ setViewer(viewer) {
157
+ if (this.sched.isDisposed)
158
+ return { findings: [(0, scheduler_1.disposedFinding)("setViewer")] };
159
+ this.viewer = (0, restricted_1.snapshotViewer)(viewer, this.audience);
160
+ return this.current === undefined ? { findings: [] } : this.recompose(this.current);
161
+ }
162
+ /**
163
+ * Append one token chunk to a `StreamingText` handle, through the same viewer gate as `load`:
164
+ * refused (a finding, nothing written) for a handle that is not bound by the current
165
+ * experience (`stream-unbound`), is restricted for the viewer (`restricted`, the fixed text that
166
+ * names nothing), or — when `outputKinds` is configured — does not resolve to `StreamingText`
167
+ * (`stream-kind-mismatch`). Without `outputKinds` the kind is unknown and is not checked. The
168
+ * store's own `append` is gated by the same rule once a controller fronts it.
169
+ */
170
+ append(handle, chunk) {
171
+ return this.opts.store.append(handle, chunk);
172
+ }
173
+ /**
174
+ * Publish a value for a handle that is NOT loaded by a provider (a live transcript a browser
175
+ * connection folds, ...), through the same gates as a load: the handle must be bound by the current
176
+ * experience, must not be restricted for the viewer (`restricted`, the fixed text that names
177
+ * nothing), must resolve to the kind the caller names (when it names one), and the value must pass
178
+ * EVERY bound kind's contract (a kind with none is refused: nothing is published unchecked).
179
+ * Refused = a finding and nothing written.
180
+ */
181
+ publishValue(handle, value, options = {}) {
182
+ const refuse = (code, message) => ({
183
+ ok: false,
184
+ finding: { code, severity: "error", message },
185
+ });
186
+ if (this.sched.isDisposed || (0, projection_1.isReservedHandle)(handle) || !this.bound.has(handle))
187
+ return refuse("publish-unbound", "the handle is not bound by the current experience; the value was refused");
188
+ if (this.restrictedHandles.has(handle))
189
+ return { ok: false, finding: (0, restricted_1.restrictedFinding)() };
190
+ const kinds = this.kinds.get(handle) ?? [];
191
+ if (kinds.length === 0 || (options.kind !== undefined && !kinds.includes(options.kind)))
192
+ return refuse("publish-kind-mismatch", "the handle's widget does not take this value; refused");
193
+ const contracts = this.opts.outputKinds?.catalog.valueContracts;
194
+ for (const kind of kinds) {
195
+ if (!(0, ui_core_1.hasKindContract)(kind, contracts))
196
+ return refuse("publish-uncontracted", "the handle's widget has no value contract; refused");
197
+ const check = (0, ui_core_1.checkKindValue)(kind, value, contracts);
198
+ if (!check.ok)
199
+ return { ok: false, finding: check.finding };
200
+ }
201
+ this.opts.store.setValue(handle, value, { state: options.state ?? "ready" });
202
+ return { ok: true };
203
+ }
204
+ appendRefusal(handle) {
205
+ if (this.sched.isDisposed || !this.bound.has(handle))
206
+ return {
207
+ code: "stream-unbound",
208
+ severity: "error",
209
+ message: "the handle is not bound by the current experience; the chunk was refused",
210
+ };
211
+ if (this.streamable.has(handle))
212
+ return undefined;
213
+ // Bound but not streamable: restricted for the viewer, or the wrong widget kind.
214
+ return this.restrictedHandles.has(handle)
215
+ ? (0, restricted_1.restrictedFinding)()
216
+ : {
217
+ code: "stream-kind-mismatch",
218
+ severity: "error",
219
+ message: "the handle's widget does not take a token stream (StreamingText); refused",
220
+ };
221
+ }
222
+ restrictedHandles = new Set();
223
+ /** The surface reports a lazy (P2) widget entered the viewport. */
224
+ markVisible(handle) {
225
+ this.sched.markVisible(handle);
226
+ }
227
+ /** A new artifact replaces the current one: abort and drop unbound handles, keep the rest, load new ones. */
228
+ recompose(next) {
229
+ if (this.sched.isDisposed)
230
+ return { findings: [(0, scheduler_1.disposedFinding)("recompose")] };
231
+ // Before anything is aborted or dropped: a tree we refuse to bind must leave the CURRENT
232
+ // one exactly as it was, not half-torn-down between two experiences.
233
+ if ((0, ui_core_1.treeDepth)(next.root) > ui_core_1.MAX_TREE_DEPTH)
234
+ return { findings: [(0, scheduler_1.tooDeep)(next.experienceId, ui_core_1.MAX_TREE_DEPTH)] };
235
+ this.sched.retain(new Set((0, restricted_1.partitionByViewer)((0, ui_core_1.experienceHandles)(next, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer).allowed.map((h) => h.handle)));
236
+ return this.bind(next);
237
+ }
238
+ /**
239
+ * Replace the global params (no `scope.handle`) or one handle's scoped params, then re-ask
240
+ * every bound handle whose question changed — only those, so a handle that ended on `error`
241
+ * with an unchanged question is NOT retried here (`invalidate` retries it). `{}` clears.
242
+ * Refused, with nothing changed, for params `checkParams` refuses or a reserved handle. A lazy
243
+ * (P2) handle whose question changed waits for its next `markVisible`. Params scoped to a handle
244
+ * the experience does not bind are kept only until the next bind, which forgets them.
245
+ */
246
+ setParams(params, scope = {}) {
247
+ if (this.sched.isDisposed)
248
+ return { findings: [(0, scheduler_1.disposedFinding)("setParams")] };
249
+ const bad = (0, params_1.checkParams)(params);
250
+ if (bad)
251
+ return { findings: [bad] };
252
+ if (scope.handle !== undefined && (0, projection_1.isReservedHandle)(scope.handle))
253
+ return {
254
+ findings: [
255
+ {
256
+ code: "invalid-handle",
257
+ severity: "error",
258
+ message: `handle "${scope.handle}" is reserved`,
259
+ },
260
+ ],
261
+ };
262
+ const before = this.current === undefined
263
+ ? new Map()
264
+ : new Map(this.plan(this.current).jobs.map((j) => [j.handle, j.fingerprint]));
265
+ // A copy (own enumerable keys only): a caller mutating its object later changes nothing.
266
+ const copy = Object.fromEntries(Object.entries(params));
267
+ if (scope.handle === undefined)
268
+ this.globalParams = copy;
269
+ else
270
+ this.scopedParams.set(scope.handle, copy);
271
+ if (this.current !== undefined)
272
+ this.sched.schedule(this.plan(this.current).jobs.filter((j) => before.get(j.handle) !== j.fingerprint));
273
+ return { findings: [] };
274
+ }
275
+ /**
276
+ * Drop cached results (one handle or all) and reload the affected bound handles. An in-flight
277
+ * load answering the invalidated question is superseded; a lazy (P2) widget stays lazy.
278
+ */
279
+ invalidate(handle) {
280
+ if (this.sched.isDisposed)
281
+ return { findings: [(0, scheduler_1.disposedFinding)("invalidate")] };
282
+ this.cache.invalidate(handle);
283
+ if (this.current === undefined)
284
+ return { findings: [] };
285
+ const jobs = this.plan(this.current).jobs;
286
+ this.sched.reload(handle === undefined ? jobs : jobs.filter((j) => j.handle === handle));
287
+ return { findings: [] };
288
+ }
289
+ inFlight() {
290
+ return this.sched.inFlight();
291
+ }
292
+ /** Terminal: every in-flight load is aborted and reported, and nothing schedules again. */
293
+ dispose() {
294
+ this.sched.dispose();
295
+ this.lifetime.abort();
296
+ this.current = undefined;
297
+ this.bound = new Set();
298
+ this.streamable = new Set();
299
+ this.restrictedHandles = new Set();
300
+ this.globalParams = {};
301
+ this.scopedParams.clear();
302
+ }
303
+ bind(exp) {
304
+ if ((0, ui_core_1.treeDepth)(exp.root) > ui_core_1.MAX_TREE_DEPTH)
305
+ return { findings: [(0, scheduler_1.tooDeep)(exp.experienceId, ui_core_1.MAX_TREE_DEPTH)] };
306
+ this.current = exp;
307
+ // U9: media-typed nodes mark their handle as media even with NO `outputKinds` (fail closed).
308
+ this.kinds = (0, ui_core_1.handleKindsWithMedia)(exp, this.opts.outputKinds?.catalog, this.opts.outputKinds?.surface);
309
+ // Scoped params outlive a bind only for handles it binds (set before a load, or kept across
310
+ // a recompose); the rest are forgotten, so they never resurface on a later experience.
311
+ // Handle-id collection only (which handles are bound at all): no class is read, so the declared
312
+ // table is deliberately not passed. The viewer-gated partition below does take it.
313
+ const bound = new Set((0, ui_core_1.experienceHandles)(exp).map((h) => h.handle));
314
+ for (const handle of [...this.scopedParams.keys()])
315
+ if (!bound.has(handle))
316
+ this.scopedParams.delete(handle);
317
+ const { jobs, findings, missing } = this.plan(exp);
318
+ for (const m of missing)
319
+ this.opts.store.setStatus(m.handle, { state: "error", finding: m.finding });
320
+ // Refused handles: their status says so (and nothing else), and no job exists for them.
321
+ const { allowed, restricted, advisory } = (0, restricted_1.partitionByViewer)((0, ui_core_1.experienceHandles)(exp, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer);
322
+ this.bound = new Set(bound);
323
+ this.restrictedHandles = new Set(restricted.map((r) => r.handle));
324
+ this.streamable = new Set(allowed
325
+ .map((a) => a.handle)
326
+ .filter((h) =>
327
+ // A media- or chat-bound handle is never streamable: a text chunk must not overwrite a MediaRef or a transcript,
328
+ // and with no `outputKinds` the kinds known here are the node-type media ones only.
329
+ !(this.kinds.get(h) ?? []).some(isStrictValueKind) &&
330
+ (this.opts.outputKinds === undefined ||
331
+ (this.kinds.get(h) ?? []).includes("StreamingText"))));
332
+ for (const r of restricted) {
333
+ if ((0, projection_1.isReservedHandle)(r.handle))
334
+ continue;
335
+ // NOTHING is written for it: no value and no status, because a store projected to a client
336
+ // would reveal the handle's name (and that it is restricted) through its status key.
337
+ this.opts.store.remove(r.handle);
338
+ }
339
+ this.sched.schedule(jobs);
340
+ const mediaAdvice = this.opts.outputKinds === undefined && (0, ui_core_1.hasMediaTypeNodes)(exp)
341
+ ? [
342
+ {
343
+ code: "media-output-kinds-missing",
344
+ severity: "warn",
345
+ 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",
346
+ },
347
+ ]
348
+ : [];
349
+ const refsAdvice = this.opts.contentRefArgs === "none" && (0, ui_core_1.hasMediaTypeNodes)(exp)
350
+ ? [
351
+ {
352
+ code: "media-content-refs-unguarded",
353
+ severity: "warn",
354
+ 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)',
355
+ },
356
+ ]
357
+ : [];
358
+ return { findings: [...findings, ...advisory, ...mediaAdvice, ...refsAdvice] };
359
+ }
360
+ /** Pure: the jobs `exp` asks for right now, and the handles that cannot load (with why). */
361
+ plan(exp) {
362
+ const jobs = [];
363
+ const findings = [];
364
+ const missing = [];
365
+ // A restricted handle is not a job: it never reaches the scheduler, the cache or a provider.
366
+ for (const use of (0, restricted_1.partitionByViewer)((0, ui_core_1.experienceHandles)(exp, this.policy.declaredToolClasses, this.policy.undeclared), this.viewer).allowed) {
367
+ if ((0, projection_1.isReservedHandle)(use.handle)) {
368
+ findings.push({
369
+ code: "invalid-handle",
370
+ severity: "error",
371
+ message: `handle "${use.handle}" is reserved`,
372
+ });
373
+ continue;
374
+ }
375
+ const declared = Object.hasOwn(exp.providers, use.handle)
376
+ ? exp.providers[use.handle]
377
+ : undefined;
378
+ if (declared === undefined) {
379
+ const f = {
380
+ code: "unknown-handle",
381
+ severity: "error",
382
+ message: `nodes ${use.nodeIds.join(", ")} bind "${use.handle}", which has no provider`,
383
+ };
384
+ findings.push(f);
385
+ missing.push({ handle: use.handle, finding: f });
386
+ continue;
387
+ }
388
+ const kinds = this.kinds.get(use.handle) ?? [];
389
+ // U9: a handle feeding a media widget is ALWAYS contract-checked (the MediaRef contract), whatever
390
+ // the provider declared. A shape pin passes any value of the pinned shape — inline bytes or a
391
+ // locator included — and what is published here reaches the store, a seen log and a client.
392
+ const spec = feedsMedia(kinds) && declared.outputCheck !== "contract"
393
+ ? { ...declared, outputCheck: "contract" }
394
+ : declared;
395
+ // Keyed on the params the provider can USE, never the raw bag: an unrelated param must
396
+ // neither re-run the load nor split its cache entry.
397
+ const params = (0, params_1.relevantParams)(spec, {
398
+ ...this.opts.defaultParams,
399
+ ...this.globalParams,
400
+ ...this.scopedParams.get(use.handle),
401
+ });
402
+ jobs.push({
403
+ handle: use.handle,
404
+ priority: use.priority,
405
+ spec,
406
+ params,
407
+ // Only a contract provider's checked value is answerable to a kind; the cache key and
408
+ // `executeProvider` ignore kinds for any other provider anyway.
409
+ kinds: spec.outputCheck === "contract" ? kinds : undefined,
410
+ experienceId: exp.experienceId,
411
+ versionHash: exp.versionHash,
412
+ fingerprint: `${(0, params_1.paramsKey)(params)}${scheduler_1.KEY_SEP}${loadFingerprint(spec, kinds)}`,
413
+ });
414
+ }
415
+ return { jobs, findings, missing };
416
+ }
417
+ /** The content-reference guard over a whole job (asks the host's gate now); `undefined` when nothing is guarded. */
418
+ refsVerdict(job) {
419
+ const table = this.opts.contentRefArgs;
420
+ if (table === "none")
421
+ return undefined;
422
+ return (0, contentRefs_1.inspectContentRefs)(job.spec, job.params, (0, contentRefs_1.contentRefEnv)(table, job.spec, this.opts.acceptContentRefParam, {
423
+ principalId: this.opts.principal?.id,
424
+ principal: this.opts.principal?.chain,
425
+ }));
426
+ }
427
+ async run(job, signal, pass) {
428
+ const outcome = await (0, provider_1.executeProvider)(job.spec, {
429
+ invoker: pass.invoker,
430
+ signal,
431
+ now: pass.now,
432
+ params: job.params,
433
+ ...(job.kinds !== undefined && { kinds: job.kinds }),
434
+ ...(this.opts.outputKinds?.catalog.valueContracts !== undefined && {
435
+ contracts: this.opts.outputKinds.catalog.valueContracts,
436
+ }),
437
+ ...(this.opts.principal?.chain && { principal: this.opts.principal.chain }),
438
+ ...(this.opts.concurrency !== undefined && { concurrency: this.opts.concurrency }),
439
+ ...(this.opts.inputDrift !== undefined && { inputDrift: this.opts.inputDrift }),
440
+ ...(this.opts.argumentHook !== undefined && { argumentHook: this.opts.argumentHook }),
441
+ ...(this.opts.contentRefArgs !== "none" && { contentRefArgs: this.opts.contentRefArgs }),
442
+ ...(this.opts.principal?.id !== undefined && { principalId: this.opts.principal.id }),
443
+ ...(this.opts.acceptContentRefParam !== undefined && {
444
+ acceptContentRefParam: this.opts.acceptContentRefParam,
445
+ }),
446
+ ...(this.opts.reshapers !== undefined && { reshapers: this.opts.reshapers }),
447
+ ...(this.opts.providers !== undefined && { providers: this.opts.providers }),
448
+ ...(this.opts.captureSample !== undefined && { captureSample: this.opts.captureSample }),
449
+ });
450
+ return { ...(0, provider_1.outcomeResult)(outcome), drift: outcome.drift ?? [], findings: outcome.findings };
451
+ }
452
+ }
453
+ exports.HydrationController = HydrationController;
454
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":";;;AAoMA,0CAKC;AAxMD,+CAuB2B;AAC3B,mCAA0E;AAC1E,+CAMuB;AAGvB,yCAAsE;AACtE,qCAMkB;AAClB,6CAIsB;AACtB,yCAAmG;AAEnG,6CAAoF;AACpF,2CAQqB;AA0HrB;;;;;GAKG;AACH;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,IAAA,qBAAW,EAAC,IAAI,CAAC,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC,CAAC;AAC3F,qHAAqH;AACrH,MAAM,UAAU,GAAG,CAAC,KAAwB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAExF,SAAgB,eAAe,CAAC,IAAkB,EAAE,KAAwB;IAC1E,IAAI,IAAI,CAAC,WAAW,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAA,uBAAe,EAAC,IAAI,CAAC,CAAC;IACxF,6FAA6F;IAC7F,6EAA6E;IAC7E,OAAO,GAAG,IAAA,uBAAe,EAAC,IAAI,CAAC,GAAG,mBAAO,GAAG,IAAA,sBAAc,EAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAChF,CAAC;AAuBD,MAAa,mBAAmB;IA2BD;IA1BZ,KAAK,CAAiB;IACtB,KAAK,CAAe;IACpB,KAAK,CAAqD;IACnE,OAAO,CAAyB;IAChC,KAAK,GAA2C,IAAI,GAAG,EAAE,CAAC;IAC1D,YAAY,GAAe,EAAE,CAAC;IACrB,YAAY,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IAElD;;;OAGG;IACH,kGAAkG;IAC1F,MAAM,CAAqB;IACnC;;;OAGG;IACK,UAAU,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC5C,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IAE9B,MAAM,CAAa;IACnB,SAAS,CAAU;IACnB,QAAQ,CAAW;IAEpC,YAA6B,IAAuB;QAAvB,SAAI,GAAJ,IAAI,CAAmB;QAClD,IAAA,oCAAsB,EAAC,IAAI,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;QACnE,0FAA0F;QAC1F,IAAI,CAAC,SAAS,GAAG,IAAA,qBAAW,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxD,IAAI,IAAI,CAAC,SAAS,KAAK,IAAA,qBAAW,EAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC3D,MAAM,IAAI,2CAA8B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,IAAA,yBAAe,EAAC,IAAI,CAAC,UAAU,EAAE;YAC7C,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,SAAS,IAAI;gBAC5C,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;aAC9C,CAAC;YACF,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;SACtE,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,IAAA,2BAAc,EAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,sBAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAA,oBAAW,EAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5C,IAAI,GAAG;gBAAE,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;QACD,6FAA6F;QAC7F,MAAM,KAAK,GAAG,IAAA,wBAAa,EACzB,IAAI,CAAC,kBAAkB,KAAK,SAAS;YACnC,CAAC,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC,IAAA,uBAAY,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAC,EACvD,IAAI,CAAC,QAAQ,CAAC,MAAM,CACrB,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC;QAC3D,MAAM,OAAO,GAAG,CAAC,GAAgB,EAAE,EAAE,CACnC,GAAG,CAAC,KAAK,KAAK,SAAS;YACrB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;YACxB,CAAC,CAAC;gBACE,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;aAC9C,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,IAAI,2BAAe,CAC9B,IAAI,CAAC,KAAK,EACV;YACE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAA,sBAAW,EAAC,KAAK,CAAC,EAAE,CAAC;YACpE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC;YACvD,iGAAiG;YACjG,0FAA0F;YAC1F,8FAA8F;YAC9F,mFAAmF;YACnF,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;gBACd,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;gBACtC,OAAO,OAAO,EAAE,OAAO,KAAK,SAAS;oBACnC,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CACZ,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,IAAA,6BAAe,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAC3D,WAAW,EACX,OAAO,CAAC,GAAG,CAAC,CACb,CAAC;YACR,CAAC;YACD,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;gBACjB,sFAAsF;gBACtF,oFAAoF;gBACpF,uFAAuF;gBACvF,oHAAoH;gBACpH,qFAAqF;gBACrF,qFAAqF;gBACrF,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAChD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;oBACtC,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS;wBAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CACZ,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,IAAA,6BAAe,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAC3D,WAAW,EACX,CAAC,CAAC,KAAK,EACP,OAAO,CAAC,GAAG,CAAC,CACb,CAAC;gBACN,CAAC;YACH,CAAC;YACD,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;gBACpB,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBACjC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClB,YAAY,EAAE,GAAG,CAAC,YAAY;oBAC9B,WAAW,EAAE,GAAG,CAAC,WAAW;oBAC5B,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,qFAAqF;oBACrF,4FAA4F;oBAC5F,SAAS,EAAE,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;iBACtD,CAAC,CAAC;YACL,CAAC;SACF,EACD,IAAI,CAAC,QAAQ,IAAI,wBAAY,EAC7B,IAAI,CAAC,aAAa,IAAI,EAAE,CACzB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,GAAe;QAClB,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,2BAAe,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC1E,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,MAA0B;QAClC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,2BAAe,EAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/E,IAAI,CAAC,MAAM,GAAG,IAAA,2BAAc,EAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtF,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CACJ,MAAc,EACd,KAAc;QAEd,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;OAOG;IACH,YAAY,CACV,MAAc,EACd,KAAc,EACd,UAA4E,EAAE;QAE9E,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,OAAe,EAAmC,EAAE,CAAC,CAAC;YAClF,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,IAAA,6BAAgB,EAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;YAC9E,OAAO,MAAM,CACX,iBAAiB,EACjB,0EAA0E,CAC3E,CAAC;QACJ,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAA,8BAAiB,GAAE,EAAE,CAAC;QAC3F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrF,OAAO,MAAM,CACX,uBAAuB,EACvB,uDAAuD,CACxD,CAAC;QACJ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC;QAChE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAA,yBAAe,EAAC,IAAI,EAAE,SAAS,CAAC;gBACnC,OAAO,MAAM,CAAC,sBAAsB,EAAE,oDAAoD,CAAC,CAAC;YAC9F,MAAM,KAAK,GAAG,IAAA,wBAAc,EAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,KAAK,CAAC,EAAE;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;QAC7E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAEO,aAAa,CAAC,MAAc;QAClC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;YAClD,OAAO;gBACL,IAAI,EAAE,gBAAgB;gBACtB,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,0EAA0E;aACpF,CAAC;QACJ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QAClD,iFAAiF;QACjF,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;YACvC,CAAC,CAAC,IAAA,8BAAiB,GAAE;YACrB,CAAC,CAAC;gBACE,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,2EAA2E;aACrF,CAAC;IACR,CAAC;IACO,iBAAiB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAE3D,mEAAmE;IACnE,WAAW,CAAC,MAAc;QACxB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,6GAA6G;IAC7G,SAAS,CAAC,IAAgB;QACxB,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,2BAAe,EAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/E,yFAAyF;QACzF,qEAAqE;QACrE,IAAI,IAAA,mBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,wBAAc;YACvC,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,mBAAO,EAAC,IAAI,CAAC,YAAY,EAAE,wBAAc,CAAC,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,KAAK,CAAC,MAAM,CACf,IAAI,GAAG,CACL,IAAA,8BAAiB,EACf,IAAA,2BAAiB,EAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAChF,IAAI,CAAC,MAAM,CACZ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAC/B,CACF,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,MAAkB,EAAE,QAAsC,EAAE;QACpE,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,2BAAe,EAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,GAAG,GAAG,IAAA,oBAAW,EAAC,MAAM,CAAC,CAAC;QAChC,IAAI,GAAG;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,IAAA,6BAAgB,EAAC,KAAK,CAAC,MAAM,CAAC;YAC9D,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,gBAAgB;wBACtB,QAAQ,EAAE,OAAO;wBACjB,OAAO,EAAE,WAAW,KAAK,CAAC,MAAM,eAAe;qBAChD;iBACF;aACF,CAAC;QACJ,MAAM,MAAM,GACV,IAAI,CAAC,OAAO,KAAK,SAAS;YACxB,CAAC,CAAC,IAAI,GAAG,EAAkB;YAC3B,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAClF,yFAAyF;QACzF,MAAM,IAAI,GAAe,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;;YACpD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,CACjB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CACnF,CAAC;QACJ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,MAAe;QACxB,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,2BAAe,EAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC;QACzF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED,2FAA2F;IAC3F,OAAO;QACL,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,EAAE,CAAC;QACnC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAEO,IAAI,CAAC,GAAe;QAC1B,IAAI,IAAA,mBAAS,EAAC,GAAG,CAAC,IAAI,CAAC,GAAG,wBAAc;YACtC,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAA,mBAAO,EAAC,GAAG,CAAC,YAAY,EAAE,wBAAc,CAAC,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,6FAA6F;QAC7F,IAAI,CAAC,KAAK,GAAG,IAAA,8BAAoB,EAC/B,GAAG,EACH,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAC/B,CAAC;QACF,4FAA4F;QAC5F,uFAAuF;QACvF,gGAAgG;QAChG,mFAAmF;QACnF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAA,2BAAiB,EAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAChD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnD,KAAK,MAAM,CAAC,IAAI,OAAO;YACrB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9E,wFAAwF;QACxF,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAA,8BAAiB,EACzD,IAAA,2BAAiB,EAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/E,IAAI,CAAC,MAAM,CACZ,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,iBAAiB,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CACvB,OAAO;aACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;aACpB,MAAM,CACL,CAAC,CAAC,EAAE,EAAE;QACJ,iHAAiH;QACjH,oFAAoF;QACpF,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC;YAClD,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS;gBAClC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CACzD,CACJ,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,IAAA,6BAAgB,EAAC,CAAC,CAAC,MAAM,CAAC;gBAAE,SAAS;YACzC,2FAA2F;YAC3F,qFAAqF;YACrF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,WAAW,GACf,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAA,2BAAiB,EAAC,GAAG,CAAC;YAC3D,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,4BAA4B;oBAClC,QAAQ,EAAE,MAAM;oBAChB,OAAO,EACL,oLAAoL;iBACvL;aACF;YACH,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,UAAU,GACd,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,MAAM,IAAI,IAAA,2BAAiB,EAAC,GAAG,CAAC;YAC3D,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,8BAA8B;oBACpC,QAAQ,EAAE,MAAM;oBAChB,OAAO,EACL,8LAA8L;iBACjM;aACF;YACH,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,WAAW,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,4FAA4F;IACpF,IAAI,CAAC,GAAe;QAK1B,MAAM,IAAI,GAAkB,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAgD,EAAE,CAAC;QAChE,6FAA6F;QAC7F,KAAK,MAAM,GAAG,IAAI,IAAA,8BAAiB,EACjC,IAAA,2BAAiB,EAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/E,IAAI,CAAC,MAAM,CACZ,CAAC,OAAO,EAAE,CAAC;YACV,IAAI,IAAA,6BAAgB,EAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,gBAAgB;oBACtB,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,WAAW,GAAG,CAAC,MAAM,eAAe;iBAC9C,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC;gBACvD,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC3B,CAAC,CAAC,SAAS,CAAC;YACd,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAY;oBACjB,IAAI,EAAE,gBAAgB;oBACtB,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,SAAS,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,MAAM,0BAA0B;iBACvF,CAAC;gBACF,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;gBACjD,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAC/C,mGAAmG;YACnG,8FAA8F;YAC9F,4FAA4F;YAC5F,MAAM,IAAI,GACR,UAAU,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,WAAW,KAAK,UAAU;gBACtD,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,UAAmB,EAAE;gBACnD,CAAC,CAAC,QAAQ,CAAC;YACf,uFAAuF;YACvF,qDAAqD;YACrD,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,IAAI,EAAE;gBAClC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;gBAC1B,GAAG,IAAI,CAAC,YAAY;gBACpB,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;aACrC,CAAC,CAAC;YACH,IAAI,CAAC,IAAI,CAAC;gBACR,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,IAAI;gBACJ,MAAM;gBACN,sFAAsF;gBACtF,gEAAgE;gBAChE,KAAK,EAAE,IAAI,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBAC1D,YAAY,EAAE,GAAG,CAAC,YAAY;gBAC9B,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,WAAW,EAAE,GAAG,IAAA,kBAAS,EAAC,MAAM,CAAC,GAAG,mBAAO,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;aAC7E,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACrC,CAAC;IAED,oHAAoH;IAC5G,WAAW,CAAC,GAAgB;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QACvC,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;QACvC,OAAO,IAAA,gCAAkB,EACvB,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,EACV,IAAA,2BAAa,EAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAC9D,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;YACpC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK;SACtC,CAAC,CACH,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,GAAgB,EAAE,MAAmB,EAAE,IAAU;QACjE,MAAM,OAAO,GAAG,MAAM,IAAA,0BAAe,EAAC,GAAG,CAAC,IAAI,EAAE;YAC9C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM;YACN,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;YACpD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,KAAK,SAAS,IAAI;gBACjE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc;aACxD,CAAC;YACF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC3E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAClF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACrF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,MAAM,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACxF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YACrF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,KAAK,SAAS,IAAI;gBACnD,qBAAqB,EAAE,IAAI,CAAC,IAAI,CAAC,qBAAqB;aACvD,CAAC;YACF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;SACzF,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,IAAA,wBAAa,EAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC/F,CAAC;CACF;AAneD,kDAmeC"}
@@ -0,0 +1,53 @@
1
+ import type { TransientInvokeOptions } from "@loomwork/effect-runtime";
2
+ import type { TransientInvoker } from "./invoker";
3
+ /** One call a kind is asked to make. */
4
+ export interface DataProviderCall {
5
+ readonly stepId: string;
6
+ /** The step's `toolName`: the target's id WITHIN this kind. */
7
+ readonly target: string;
8
+ /** The step's arguments, after params, time tokens, templates and the host's hook. */
9
+ readonly args: Record<string, unknown>;
10
+ /** The step's `toolSchemaHash`, or the observed pin on the one drift retry. */
11
+ readonly expectedPin: string;
12
+ }
13
+ export interface DataProvider {
14
+ /** The kind id steps name. Lower-case/digits/`-`; never `"mcp"` unless it IS the MCP provider. */
15
+ readonly kind: string;
16
+ /**
17
+ * Run the call and return the raw output. Contract: throw `TypedFailure("schemaDrift",
18
+ * { observedHash })` when `expectedPin` is not the target's current pin, before running it; any
19
+ * other `TypedFailure` becomes a `tool-<channel>` finding, anything else `tool-failed`. All
20
+ * calls MUST go through `invoker` with `opts` (it carries the signal and the principal).
21
+ */
22
+ invoke(call: DataProviderCall, invoker: TransientInvoker, opts: TransientInvokeOptions): Promise<unknown>;
23
+ }
24
+ /** The kinds a host composed, by id. Immutable once built. */
25
+ export interface DataProviderRegistry {
26
+ has(kind: string): boolean;
27
+ get(kind: string): DataProvider | undefined;
28
+ /** Registered kind ids, sorted. */
29
+ kinds(): readonly string[];
30
+ }
31
+ /**
32
+ * Build a registry. Refuses a malformed or duplicate kind id: two providers for one kind would
33
+ * make what a stored experience means depend on registration order.
34
+ */
35
+ export declare function defineDataProviders(providers: readonly DataProvider[]): DataProviderRegistry;
36
+ /** The MCP kind: `mcp.invoke` with the pin as `expectedSchemaHash` (the plugin verifies it per call). */
37
+ export declare const mcpProvider: DataProvider;
38
+ /** What `executeProvider` uses when the host registers nothing: MCP only — the behaviour before kinds. */
39
+ export declare const DEFAULT_DATA_PROVIDERS: DataProviderRegistry;
40
+ /**
41
+ * Assert the one rule every kind must keep: a wrong pin is `schemaDrift` carrying the observed
42
+ * pin, and the right pin runs the target. Run it in a kind's own test suite against a target the
43
+ * kind serves (`target`, with its current `pin`) and a recording invoker. Returns a list of
44
+ * violations (empty = conformant); never throws for a violation. A wrong pin must ALSO not reach
45
+ * the target (a direct call to `target` through the invoker is counted). This is a TEST HELPER: `defineDataProviders`
46
+ * cannot enforce the rule at registration, so a kind that skips this suite is unchecked.
47
+ */
48
+ export declare function checkDataProviderConformance(provider: DataProvider, fixture: {
49
+ target: string;
50
+ pin: string;
51
+ invoker: TransientInvoker;
52
+ }): Promise<string[]>;
53
+ //# sourceMappingURL=dataProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataProvider.d.ts","sourceRoot":"","sources":["../src/dataProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AA2BlD,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CACJ,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC5C,mCAAmC;IACnC,KAAK,IAAI,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,GAAG,oBAAoB,CAe5F;AAED,yGAAyG;AACzG,eAAO,MAAM,WAAW,EAAE,YAQxB,CAAC;AAEH,0GAA0G;AAC1G,eAAO,MAAM,sBAAsB,EAAE,oBAAyD,CAAC;AAE/F;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAClE,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_DATA_PROVIDERS = exports.mcpProvider = void 0;
4
+ exports.defineDataProviders = defineDataProviders;
5
+ exports.checkDataProviderConformance = checkDataProviderConformance;
6
+ const core_1 = require("@loomwork/core");
7
+ const plugin_mcp_1 = require("@loomwork/plugin-mcp");
8
+ const ui_core_1 = require("@loomwork/ui-core");
9
+ /**
10
+ * Build a registry. Refuses a malformed or duplicate kind id: two providers for one kind would
11
+ * make what a stored experience means depend on registration order.
12
+ */
13
+ function defineDataProviders(providers) {
14
+ const byKind = new Map();
15
+ for (const p of providers) {
16
+ if (typeof p.kind !== "string" || !ui_core_1.STEP_KIND_PATTERN.test(p.kind))
17
+ throw new TypeError(`defineDataProviders: "${String(p.kind)}" is not a valid kind id`);
18
+ if (byKind.has(p.kind))
19
+ throw new TypeError(`defineDataProviders: kind "${p.kind}" is registered twice`);
20
+ byKind.set(p.kind, p);
21
+ }
22
+ const sorted = Object.freeze([...byKind.keys()].sort());
23
+ return {
24
+ has: (kind) => byKind.has(kind),
25
+ get: (kind) => byKind.get(kind),
26
+ kinds: () => sorted,
27
+ };
28
+ }
29
+ /** The MCP kind: `mcp.invoke` with the pin as `expectedSchemaHash` (the plugin verifies it per call). */
30
+ exports.mcpProvider = Object.freeze({
31
+ kind: ui_core_1.DEFAULT_STEP_KIND,
32
+ invoke: (call, invoker, opts) => invoker.invokeTransient(plugin_mcp_1.MCP_INVOKE_TOOL_ID, { toolName: call.target, args: call.args, expectedSchemaHash: call.expectedPin }, opts),
33
+ });
34
+ /** What `executeProvider` uses when the host registers nothing: MCP only — the behaviour before kinds. */
35
+ exports.DEFAULT_DATA_PROVIDERS = defineDataProviders([exports.mcpProvider]);
36
+ /**
37
+ * Assert the one rule every kind must keep: a wrong pin is `schemaDrift` carrying the observed
38
+ * pin, and the right pin runs the target. Run it in a kind's own test suite against a target the
39
+ * kind serves (`target`, with its current `pin`) and a recording invoker. Returns a list of
40
+ * violations (empty = conformant); never throws for a violation. A wrong pin must ALSO not reach
41
+ * the target (a direct call to `target` through the invoker is counted). This is a TEST HELPER: `defineDataProviders`
42
+ * cannot enforce the rule at registration, so a kind that skips this suite is unchecked.
43
+ */
44
+ async function checkDataProviderConformance(provider, fixture) {
45
+ const problems = [];
46
+ let reached = 0;
47
+ const counting = {
48
+ invokeTransient: (...a) => {
49
+ // Only a call to the target's OWN id counts: the MCP kind reaches `mcp.invoke`, whose pin
50
+ // check lives inside that effect (and is MCP's own conformance, not this kit's).
51
+ if (a[0] === fixture.target)
52
+ reached++;
53
+ return fixture.invoker.invokeTransient(...a);
54
+ },
55
+ };
56
+ const base = { stepId: "conformance", target: fixture.target, args: {} };
57
+ try {
58
+ await provider.invoke({ ...base, expectedPin: `${fixture.pin}-stale` }, counting, {});
59
+ problems.push("a stale pin did not fail");
60
+ }
61
+ catch (e) {
62
+ if (!(e instanceof core_1.TypedFailure && e.channel === "schemaDrift"))
63
+ problems.push("a stale pin failed, but not as TypedFailure(schemaDrift)");
64
+ else if (e.payload?.observedHash !== fixture.pin)
65
+ problems.push("schemaDrift did not carry the target's current pin as observedHash");
66
+ }
67
+ if (reached > 0)
68
+ problems.push("a stale pin reached the target before failing");
69
+ try {
70
+ await provider.invoke({ ...base, expectedPin: fixture.pin }, fixture.invoker, {});
71
+ }
72
+ catch (e) {
73
+ problems.push(`the current pin did not run the target: ${e instanceof Error ? e.message : e}`);
74
+ }
75
+ return problems;
76
+ }
77
+ //# sourceMappingURL=dataProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataProvider.js","sourceRoot":"","sources":["../src/dataProvider.ts"],"names":[],"mappings":"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"}