@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,310 @@
1
+ import { canonicalJson } from "@loomwork/core";
2
+ import { MCP_INVOKE_TOOL_ID } from "@loomwork/plugin-mcp";
3
+ // ── Invoker wrappers: a call cap, an owner's lifetime signal, an in-pass step memo ─
4
+ // All are TransientInvokers wrapping a TransientInvoker, so they compose with each other and
5
+ // with loom's EffectRuntime without either knowing the other exists. The in-process controller
6
+ // builds ONE `limitInvoker` (the cap is controller-wide: it bounds every call it makes), ONE
7
+ // `signalInvoker` over it bound to its own lifetime (so `dispose` cancels every upstream call at
8
+ // once), and one `memoInvoker` PER PASS in front of both (a memo hit takes no slot). The split
9
+ // server (`serveHandles`, split.ts) composes a memo over a cap the same way, once per batch.
10
+ // None ever returns a promise it did not get from the inner invoker except to wait for a slot,
11
+ // so they add no settle latency on a free slot.
12
+ /**
13
+ * The rejection for a call abandoned because its signal aborted. Named `AbortError` (the
14
+ * platform's own name for a cancelled operation) so a consumer classifies it by `name` — a
15
+ * planner's decider must propagate a cancellation, never retry it or record it as a failed
16
+ * plan. A plain `Error("aborted")` is indistinguishable from a provider failure. Message kept.
17
+ */
18
+ function abortError() {
19
+ const e = new Error("aborted");
20
+ e.name = "AbortError";
21
+ return e;
22
+ }
23
+ /**
24
+ * At most `max` calls in flight through this invoker, across every caller. A queued call whose
25
+ * signal aborts leaves the queue and rejects `"aborted"` without ever reaching `inner`. FIFO: a
26
+ * finished call hands its slot straight to the oldest waiter.
27
+ */
28
+ export function limitInvoker(inner, max) {
29
+ if (!Number.isInteger(max) || max < 1)
30
+ throw new RangeError(`limitInvoker: the cap must be a positive integer, got ${String(max)}`);
31
+ let active = 0;
32
+ // Insertion-ordered: the first entry is the oldest waiter; add/delete are O(1).
33
+ const waiting = new Set();
34
+ const release = () => {
35
+ const next = waiting.values().next();
36
+ if (next.done === true) {
37
+ active -= 1;
38
+ return;
39
+ }
40
+ waiting.delete(next.value);
41
+ next.value(); // the slot passes to the waiter: `active` is unchanged
42
+ };
43
+ const acquire = (signal) => {
44
+ // Checked before capacity: an already-aborted caller must never take a slot (or reach
45
+ // `inner`) just because one happened to be free — that slot belongs to the next live caller.
46
+ if (signal?.aborted === true)
47
+ return Promise.reject(abortError());
48
+ if (active < max) {
49
+ active += 1;
50
+ return undefined;
51
+ }
52
+ return new Promise((resolve, reject) => {
53
+ const onAbort = () => {
54
+ waiting.delete(grant);
55
+ reject(abortError());
56
+ };
57
+ const grant = () => {
58
+ signal?.removeEventListener("abort", onAbort);
59
+ resolve();
60
+ };
61
+ waiting.add(grant);
62
+ signal?.addEventListener("abort", onAbort, { once: true });
63
+ });
64
+ };
65
+ const run = (call) => {
66
+ let p;
67
+ try {
68
+ p = call();
69
+ }
70
+ catch (e) {
71
+ release();
72
+ return Promise.reject(e);
73
+ }
74
+ p.then(release, release);
75
+ return p;
76
+ };
77
+ return {
78
+ invokeTransient(toolId, input, opts) {
79
+ const call = () => inner.invokeTransient(toolId, input, opts);
80
+ const slot = acquire(opts?.signal);
81
+ return slot === undefined ? run(call) : slot.then(() => run(call));
82
+ },
83
+ };
84
+ }
85
+ /** `call()`, with a synchronous throw turned into the rejected promise the contract promises. */
86
+ function callSafely(call) {
87
+ try {
88
+ return call();
89
+ }
90
+ catch (e) {
91
+ return Promise.reject(e);
92
+ }
93
+ }
94
+ /**
95
+ * Every call through this invoker is ALSO cancelled, synchronously, when `signal` aborts — the
96
+ * owner's lifetime (a controller's `dispose`), independent of any caller's own signal, which still
97
+ * reaches `inner` too. Once `signal` has aborted, new calls reject `"aborted"` without reaching
98
+ * `inner`. Leak-free on a long-lived `signal`: a call holds its listener only until it settles.
99
+ */
100
+ export function signalInvoker(inner, signal) {
101
+ return {
102
+ invokeTransient(toolId, input, opts) {
103
+ const own = opts?.signal;
104
+ if (signal.aborted || own?.aborted === true)
105
+ return Promise.reject(abortError());
106
+ const ac = new AbortController();
107
+ const abort = () => ac.abort();
108
+ signal.addEventListener("abort", abort, { once: true });
109
+ own?.addEventListener("abort", abort, { once: true });
110
+ const release = () => {
111
+ signal.removeEventListener("abort", abort);
112
+ own?.removeEventListener("abort", abort);
113
+ };
114
+ const p = callSafely(() => inner.invokeTransient(toolId, input, { ...opts, signal: ac.signal }));
115
+ p.then(release, release);
116
+ return p;
117
+ },
118
+ };
119
+ }
120
+ /**
121
+ * The shape `canonicalJson` actually understands — null/string/finite-number/boolean, and arrays
122
+ * or plain objects (`Object.prototype` or `null` as the prototype) built from those, recursively.
123
+ * `canonicalJson` does not THROW on a `Date`, `Map`, `Set` or a class instance — it silently reads
124
+ * `Object.keys()` on it, which for most of those is `[]`, so two calls with DIFFERENT such
125
+ * arguments would canonicalize to the same `"{}"` and collide on one memo key. Reject those before
126
+ * a key is ever computed, not after: `memoInvoker` must never be the reason a value collapses.
127
+ *
128
+ * `seen` makes this cycle-safe: a hostile or accidental circular reference is walked at most once
129
+ * per object (the second visit reports "not plain" rather than recursing forever), so a cyclic
130
+ * argument bypasses the memo instead of throwing `RangeError: Maximum call stack size exceeded`
131
+ * out of `invokeTransient`. Sharing one `seen` set across a whole call's plainness check is
132
+ * deliberately conservative: a repeated (non-cyclic) reference is also flagged "not plain" and
133
+ * bypasses sharing rather than being memoized — safe, since bypass just means no caching, never a
134
+ * wrong answer.
135
+ */
136
+ function isPlainJsonValue(value, seen = new WeakSet()) {
137
+ if (value === null || value === undefined)
138
+ return true;
139
+ const t = typeof value;
140
+ if (t === "string" || t === "boolean")
141
+ return true;
142
+ if (t === "number")
143
+ return Number.isFinite(value);
144
+ if (t !== "object")
145
+ return false; // function, bigint, symbol
146
+ const obj = value;
147
+ if (seen.has(obj))
148
+ return false;
149
+ seen.add(obj);
150
+ if (Array.isArray(value))
151
+ return value.every((v) => isPlainJsonValue(v, seen));
152
+ const proto = Object.getPrototypeOf(obj);
153
+ if (proto !== Object.prototype && proto !== null)
154
+ return false;
155
+ return Object.values(value).every((v) => isPlainJsonValue(v, seen));
156
+ }
157
+ /**
158
+ * One call per identical MCP step for this invoker's lifetime (a PASS): same tool, same resolved
159
+ * arguments, same schema pin, same call options — the canonical JSON of `[principal, every other
160
+ * option except signal, mcp.invoke's input]`, so key order does not matter. A joiner is
161
+ * served straight from the shared promise — it never calls `inner` itself, so it never passes
162
+ * through whatever per-call authorizer `inner` enforces. That is safe ONLY because every
163
+ * authorization input is part of the key: the principal, and also the stamped execution identity
164
+ * (`as` — an authorizer may grant by workflow), the `label` (which names the transient
165
+ * execution when `as` is absent) and anything else in the options. Every joiner
166
+ * sharing one entry was, by construction, asking with the exact inputs the leader's own (sole)
167
+ * call to `inner` was authorized for; an option that is not plain JSON passes through, uncached. Settled results stay (a step in a later wave is still
168
+ * served) and failures are shared. Other effects (a sandbox reshape) always run, uncached.
169
+ *
170
+ * Cancellation is ref-counted, not leader-owned: `inner` is called once, through an internal
171
+ * `AbortController` this function owns — never a caller's own signal directly — so any ONE
172
+ * caller's abort only ever settles that caller's OWN returned promise (a race against the shared
173
+ * promise). The upstream call itself is cancelled, and the entry forgotten, only once every live
174
+ * caller has aborted AND the call had not already settled; a caller that arrives after a real
175
+ * cancellation finds no entry and starts a fresh call.
176
+ */
177
+ export function memoInvoker(inner) {
178
+ const memo = new Map();
179
+ const onCallerAbort = (key, hit) => {
180
+ hit.live -= 1;
181
+ if (hit.live > 0)
182
+ return;
183
+ // Deferred one microtask: `hit.settled` is set by a handler attached at entry-creation time,
184
+ // which — because it was attached first — runs before this check for any settlement the memo
185
+ // can observe, even when the abort lands in the very same synchronous turn as `hit.promise`
186
+ // settling. Checking `hit.settled` synchronously right here would miss exactly that race.
187
+ // "The memo can observe" is `hit.promise` — `inner`'s promise — not the raw upstream: behind
188
+ // a queued `limitInvoker` (or any wrapper that settles a few hops after its own inner call),
189
+ // an all-abort landing after the RAW upstream settled but before `hit.promise` does still
190
+ // cancels and evicts, so a later caller re-fetches. A wasted call, never a wrong answer.
191
+ //
192
+ // Both conditions below are RE-READ at that later point, not captured now, because either can
193
+ // change in the gap between "live just dropped to 0" and "the microtask actually runs": a
194
+ // fresh caller with no signal of its own can join in the very same synchronous turn (bumping
195
+ // `live` back above 0 before this ever executes), and the upstream can settle in that same
196
+ // window (flipping `settled` true). A snapshot taken at decrement time would race both ways —
197
+ // this is why the check happens here, once, right before the one place that acts on it.
198
+ //
199
+ // Invariant: the controller is aborted, and the entry deleted, AT MOST ONCE per entry — and
200
+ // only when, at the moment this specific check runs, `settled` is still false AND `live` is
201
+ // still <= 0 (no one re-joined). Either condition failing means someone still needs this call
202
+ // to keep going (or already has its answer), so it is left alone.
203
+ queueMicrotask(() => {
204
+ if (hit.settled || hit.live > 0)
205
+ return;
206
+ // Forget the entry BEFORE aborting: `abort()` runs `inner`'s listeners synchronously, and a
207
+ // caller re-entering with the same key from one of them must start a fresh call, not join
208
+ // this dying one.
209
+ if (memo.get(key) === hit)
210
+ memo.delete(key);
211
+ hit.controller.abort();
212
+ });
213
+ };
214
+ const join = (key, hit, signal) => {
215
+ if (signal?.aborted === true) {
216
+ onCallerAbort(key, hit);
217
+ return Promise.reject(abortError());
218
+ }
219
+ return new Promise((resolve, reject) => {
220
+ let settled = false;
221
+ const onAbort = () => {
222
+ if (settled)
223
+ return;
224
+ settled = true;
225
+ onCallerAbort(key, hit);
226
+ reject(abortError());
227
+ };
228
+ signal?.addEventListener("abort", onAbort, { once: true });
229
+ hit.promise.then((v) => {
230
+ if (settled)
231
+ return;
232
+ settled = true;
233
+ signal?.removeEventListener("abort", onAbort);
234
+ resolve(v);
235
+ }, (e) => {
236
+ if (settled)
237
+ return;
238
+ settled = true;
239
+ signal?.removeEventListener("abort", onAbort);
240
+ reject(e);
241
+ });
242
+ });
243
+ };
244
+ return {
245
+ invokeTransient(toolId, input, opts) {
246
+ // Every pass-through is guarded like the leader's call: a synchronous throw from `inner`
247
+ // must come back as a rejected promise, never escape `invokeTransient`.
248
+ const passThrough = () => callSafely(() => inner.invokeTransient(toolId, input, opts));
249
+ if (toolId !== MCP_INVOKE_TOOL_ID)
250
+ return passThrough();
251
+ // Everything in `opts` except the one field that cannot change the answer (`signal`) is
252
+ // part of the key: the principal, the stamped identity (`as`, which an authorizer may key
253
+ // grants on), the `label` (without `as`, the transient executionId is `transient:<label>`,
254
+ // and an authorizer may grant per execution), the budget snapshot, and any option added
255
+ // later. Keying on the remainder rather than a list of known fields is what keeps a joiner
256
+ // from being served a result authorized for a different input this function has never
257
+ // heard of.
258
+ const { signal: _signal, principal = null, ...rest } = opts ?? {};
259
+ let key;
260
+ try {
261
+ const seen = new WeakSet();
262
+ if (!isPlainJsonValue(principal, seen) ||
263
+ !isPlainJsonValue(rest, seen) ||
264
+ !isPlainJsonValue(input, seen))
265
+ return passThrough();
266
+ key = canonicalJson([principal, rest, input]);
267
+ }
268
+ catch {
269
+ return passThrough();
270
+ }
271
+ const hit = memo.get(key);
272
+ if (hit !== undefined) {
273
+ hit.live += 1;
274
+ return join(key, hit, opts?.signal);
275
+ }
276
+ // Mirrors limitInvoker's fast path: an already-aborted caller must never become the leader
277
+ // — that would call `inner`, create an entry nobody asked to keep, and (since nothing here
278
+ // would yet be subscribed to the resulting promise) risk an unhandled rejection.
279
+ if (opts?.signal?.aborted === true)
280
+ return Promise.reject(abortError());
281
+ const controller = new AbortController();
282
+ let promise;
283
+ try {
284
+ // `inner.invokeTransient` is typed to return a Promise, but a misbehaving implementation
285
+ // can still throw synchronously; the interface contract (and every caller of THIS
286
+ // function) requires a rejected promise instead, never a thrown exception. No entry is
287
+ // created for a call that never actually started.
288
+ promise = inner.invokeTransient(toolId, input, {
289
+ ...opts,
290
+ signal: controller.signal,
291
+ });
292
+ }
293
+ catch (e) {
294
+ return Promise.reject(e);
295
+ }
296
+ const entry = { promise, controller, live: 1, settled: false };
297
+ const onSettle = () => {
298
+ entry.settled = true;
299
+ };
300
+ // Attached at entry-creation time — before any joiner's own `.then` — so `entry.settled`
301
+ // is set before `onCallerAbort`'s deferred check can run (see there). Also the
302
+ // backstop: attaching a rejection handler here means NO path can ever leave `promise`
303
+ // unhandled, even if a future caller subscribes late or never at all.
304
+ promise.then(onSettle, onSettle);
305
+ memo.set(key, entry);
306
+ return join(key, entry, opts?.signal);
307
+ },
308
+ };
309
+ }
310
+ //# sourceMappingURL=invokers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invokers.js","sourceRoot":"","sources":["../../src/invokers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { toolInputJsonSchema } from "@loomwork/agent";
2
+ import { TypedFailure, jsonSchemaHash } from "@loomwork/core";
3
+ import { MCP_INVOKE_TOOL_ID } from "@loomwork/plugin-mcp";
4
+ import { SANDBOX_TOOL_ID } from "@loomwork/plugin-sandbox";
5
+ /** The kind id of a step whose target is a registered loom effect. */
6
+ export const LOOM_EFFECT_KIND = "loom-effect";
7
+ /**
8
+ * The failure channel for a target the host did not declare. Served to a client as the fixed
9
+ * `tool-targetUnregistered` code — never the target id or any text of the effect's own.
10
+ */
11
+ export const TARGET_UNREGISTERED = "targetUnregistered";
12
+ /**
13
+ * The failure channel for an effect that itself raised `schemaDrift` (e.g. a target wrapping
14
+ * `mcp.invoke`). Only the provider's OWN pin check may emit `schemaDrift`: a target's drift
15
+ * would otherwise be read as this kind's pin drift, and a repair would re-pin to the inner
16
+ * hash and flip forever. Served as the `tool-targetFailed` code (`tool-failed` to a client).
17
+ */
18
+ export const TARGET_FAILED = "targetFailed";
19
+ /**
20
+ * The pin of an effect's input contract: `jsonSchemaHash` (the one canonical hash MCP pins use)
21
+ * of the schema's JSON-Schema form. Use it BOTH when the host builds a planner `CapabilityRef`
22
+ * (`toolSchemaHash`) and when it lists the effect for {@link loomEffectProvider} (via
23
+ * `{ inputSchema }`) so the two come from one source: editing the effect's zod schema moves
24
+ * the pin, and every stored step drifts.
25
+ */
26
+ export function effectPin(schema) {
27
+ return jsonSchemaHash(toolInputJsonSchema(schema));
28
+ }
29
+ /** The effect kinds a data read can never reach: a person's answer, a model call. */
30
+ const REFUSED_KINDS = new Set(["human", "llm"]);
31
+ /**
32
+ * Effects hydration already reaches through a dedicated plane (the MCP kind, the sandbox
33
+ * reshaper). Exposing them as a data TARGET would let a stored step bypass the pin and the
34
+ * reshaping boundary, so a host cannot list them.
35
+ */
36
+ const RESERVED_TARGETS = new Set([MCP_INVOKE_TOOL_ID, SANDBOX_TOOL_ID]);
37
+ /**
38
+ * The `loom-effect` kind: a step whose `toolName` is the id of an effect registered with the
39
+ * loom effect runtime (a `tool$`, a read-model query effect, an A2A call…), invoked through the
40
+ * SAME transient invoker and therefore the same authoriser, budget and principal as the MCP
41
+ * kind. Construction refuses an effect that is unregistered, not explicitly `ambient`, or a
42
+ * `human` / `llm` kind.
43
+ *
44
+ * An effect's call is not memoised across a pass (the in-pass memo coalesces `mcp.invoke` only:
45
+ * an arbitrary effect is not known to be a pure read), so two steps naming one effect with equal
46
+ * arguments call it twice. (Memoising `ambient` effects is a possible follow-up.)
47
+ *
48
+ * A persisted experience crosses a version boundary only through the log: an older in-memory
49
+ * `executeProvider` / `seal` that predates kinds would run a kinded step as an MCP call.
50
+ */
51
+ export function loomEffectProvider(options) {
52
+ const { runtime } = options;
53
+ const pins = new Map();
54
+ for (const [id, entry] of Object.entries(options.effects)) {
55
+ if (id === "")
56
+ throw new TypeError("loomEffectProvider: an effect id is empty");
57
+ if (RESERVED_TARGETS.has(id))
58
+ throw new TypeError(`loomEffectProvider: "${id}" is reached through its own plane (the MCP kind / the sandbox) and cannot be a data target`);
59
+ if (!runtime.has(id))
60
+ throw new TypeError(`loomEffectProvider: effect "${id}" is not registered with the runtime`);
61
+ if (runtime.modeOf(id) !== "ambient")
62
+ throw new TypeError(`loomEffectProvider: effect "${id}" is not declared mode "ambient" (ADR 0073); a data read may not run an undeclared or journaled effect`);
63
+ const kind = runtime.kindOf(id);
64
+ if (kind !== undefined && REFUSED_KINDS.has(kind))
65
+ throw new TypeError(`loomEffectProvider: effect "${id}" is a ${kind} effect, not a data read`);
66
+ const pin = entry !== null && typeof entry === "object" && "inputSchema" in entry
67
+ ? effectPin(entry.inputSchema)
68
+ : entry?.pin;
69
+ if (typeof pin !== "string" || pin === "")
70
+ throw new TypeError(`loomEffectProvider: effect "${id}" needs a non-empty pin`);
71
+ pins.set(id, pin);
72
+ }
73
+ return Object.freeze({
74
+ kind: LOOM_EFFECT_KIND,
75
+ async invoke(call, invoker, opts) {
76
+ const current = pins.get(call.target);
77
+ if (current === undefined)
78
+ throw new TypedFailure(TARGET_UNREGISTERED, { target: call.target });
79
+ if (current !== call.expectedPin)
80
+ throw new TypedFailure("schemaDrift", {
81
+ toolName: call.target,
82
+ expectedSchemaHash: call.expectedPin,
83
+ observedHash: current,
84
+ });
85
+ try {
86
+ return await invoker.invokeTransient(call.target, call.args, opts);
87
+ }
88
+ catch (e) {
89
+ if (e instanceof TypedFailure && e.channel === "schemaDrift")
90
+ throw new TypedFailure(TARGET_FAILED, { target: call.target });
91
+ throw e;
92
+ }
93
+ },
94
+ });
95
+ }
96
+ //# sourceMappingURL=loomEffectProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loomEffectProvider.js","sourceRoot":"","sources":["../../src/loomEffectProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ import { canonicalJson, fnv1a64 } from "@loomwork/core";
2
+ import { resolveArguments } from "./plan";
3
+ /** A time-range default a host may pass as `ControllerOptions.defaultParams`: the last 24 hours, relative to each pass. */
4
+ export const DEFAULT_TIME_RANGE = Object.freeze({ from: "$now-24h", to: "$now" });
5
+ /** Token-shaped: `$now` not followed by a word character. `$nowcast` is an ordinary string. */
6
+ const TOKEN_LIKE = /^\$now(?![A-Za-z0-9_])/;
7
+ const TIME_TOKEN = /^\$now(?:([+-])(\d{1,9})([smhdw]))?$/;
8
+ const UNIT_MS = {
9
+ s: 1_000,
10
+ m: 60_000,
11
+ h: 3_600_000,
12
+ d: 86_400_000,
13
+ w: 604_800_000,
14
+ };
15
+ const bad = (code, message) => ({ code, severity: "error", message });
16
+ const note = (code, message) => ({ code, severity: "warn", message });
17
+ /** An async argument hook returns one of these: `prepareArguments` never awaits it. */
18
+ function isThenable(v) {
19
+ return (v !== null && typeof v === "object" && typeof v.then === "function");
20
+ }
21
+ /** `$now`, `$now-7d`, `$now+1h` (units s m h d w) as an ISO-8601 instant; `undefined` otherwise. */
22
+ export function resolveTimeToken(token, now) {
23
+ const m = TIME_TOKEN.exec(token);
24
+ if (!m)
25
+ return undefined;
26
+ const offset = m[1] === undefined
27
+ ? 0
28
+ : (m[1] === "-" ? -1 : 1) * Number(m[2]) * UNIT_MS[m[3]];
29
+ const at = new Date(now + offset);
30
+ // Past ±8.64e15 ms a Date is invalid and `toISOString` would throw: refuse instead.
31
+ return Number.isNaN(at.getTime()) ? undefined : at.toISOString();
32
+ }
33
+ /** Every token-shaped string leaf is resolved, or the whole value is refused. Other leaves pass. */
34
+ export function resolveTimeTokens(value, now, where) {
35
+ let failure;
36
+ const visit = (v) => {
37
+ if (failure)
38
+ return v;
39
+ if (typeof v === "string") {
40
+ if (!TOKEN_LIKE.test(v))
41
+ return v;
42
+ const iso = resolveTimeToken(v, now);
43
+ if (iso !== undefined)
44
+ return iso;
45
+ failure = bad("invalid-time-token", `${where}: "${v.slice(0, 64)}" is not a relative-time token ($now, $now-7d, $now+1h; units s m h d w)`);
46
+ return v;
47
+ }
48
+ if (Array.isArray(v))
49
+ return v.map(visit);
50
+ if (v !== null && typeof v === "object")
51
+ return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, visit(x)]));
52
+ return v;
53
+ };
54
+ const out = visit(value);
55
+ return failure ? { ok: false, finding: failure } : { ok: true, value: out };
56
+ }
57
+ const STEP_REF = /\{\{\s*steps\./;
58
+ function containsStepTemplate(v) {
59
+ if (typeof v === "string")
60
+ return STEP_REF.test(v);
61
+ if (Array.isArray(v))
62
+ return v.some(containsStepTemplate);
63
+ if (v !== null && typeof v === "object")
64
+ return Object.values(v).some(containsStepTemplate);
65
+ return false;
66
+ }
67
+ /** A plain object `canonicalJson` can represent (no NaN/±Infinity, bigint, function, over-deep nest). */
68
+ export function checkParams(params) {
69
+ if (params === null || typeof params !== "object" || Array.isArray(params))
70
+ return bad("invalid-params", "params must be a plain object");
71
+ try {
72
+ canonicalJson(params);
73
+ return undefined;
74
+ }
75
+ catch (e) {
76
+ return bad("invalid-params", `params cannot be represented as JSON: ${e instanceof Error ? e.message : String(e)}`);
77
+ }
78
+ }
79
+ /** Canonical identity of a param set (key order irrelevant); `""` for none. Throws only on what `checkParams` refuses. */
80
+ export function paramsKey(params) {
81
+ return Object.keys(params).length === 0 ? "" : fnv1a64(canonicalJson(params));
82
+ }
83
+ /** Every argument name any step of the provider declares overridable, sorted. */
84
+ export function providerParams(spec) {
85
+ const names = new Set();
86
+ for (const step of spec.executionGraph)
87
+ for (const n of step.overridable ?? [])
88
+ names.add(n);
89
+ return [...names].sort();
90
+ }
91
+ /**
92
+ * The named params the set actually holds (own keys only), as a fresh, FROZEN object — this is
93
+ * the object every step's `prepareArguments` call (and its argument hook) receives as `ctx.params`
94
+ * for the whole load, so a hook mutating it would leak into every other step's view of the load.
95
+ * Reads `params[n]` once per name: on params that crossed a trust boundary, snapshot them first
96
+ * (`snapshotParams`) — a live accessor that answered safely for an earlier, separate check (e.g.
97
+ * `checkParams` alone) is free to answer differently by the time THIS read runs.
98
+ */
99
+ export function pickParams(params, names) {
100
+ return Object.freeze(Object.fromEntries(names.filter((n) => Object.hasOwn(params, n)).map((n) => [n, params[n]])));
101
+ }
102
+ /**
103
+ * ONE plain, detached copy of untrusted params — a JSON round-trip through `canonicalJson`, so a
104
+ * value it refuses (a function, bigint, non-finite number, a cycle, past the depth cap) is caught
105
+ * HERE, and `JSON.parse` builds the result from that already-captured string alone: nothing
106
+ * downstream (`checkParams`, `pickParams`, `relevantParams`) ever reads a property of the SOURCE
107
+ * object again. Required wherever params cross a trust boundary (`serveHandle(s)`) — validating a
108
+ * live accessor and then separately picking named keys off it re-reads it, and a hostile getter is
109
+ * free to answer only the validating read safely and answer a later, picking read with something
110
+ * else entirely (observed: a plain value for the first two reads, a function for the third).
111
+ */
112
+ export function snapshotParams(params) {
113
+ if (params === null || typeof params !== "object" || Array.isArray(params))
114
+ return { ok: false, finding: bad("invalid-params", "params must be a plain object") };
115
+ try {
116
+ return { ok: true, params: JSON.parse(canonicalJson(params)) };
117
+ }
118
+ catch (e) {
119
+ return {
120
+ ok: false,
121
+ finding: bad("invalid-params", `params cannot be represented as JSON: ${e instanceof Error ? e.message : String(e)}`),
122
+ };
123
+ }
124
+ }
125
+ /** The params this provider can use: everything else cannot change its answer. */
126
+ export function relevantParams(spec, params) {
127
+ return pickParams(params, providerParams(spec));
128
+ }
129
+ export function applyParams(node, params) {
130
+ const { args, findings } = applyParamsDetailed(node, params);
131
+ return { args, findings };
132
+ }
133
+ /** {@link applyParams}, plus which top-level arguments a param actually replaced (U9b needs them). */
134
+ export function applyParamsDetailed(node, params) {
135
+ const names = node.overridable ?? [];
136
+ const findings = [];
137
+ const replaced = [];
138
+ if (names.length === 0)
139
+ return { args: node.arguments, findings, replaced };
140
+ // A Map, then `Object.fromEntries`: every write is CreateDataProperty, so an argument named
141
+ // `__proto__` lands as an own key instead of setting a prototype.
142
+ const args = new Map(Object.entries(node.arguments));
143
+ for (const name of names) {
144
+ if (!Object.hasOwn(params, name))
145
+ continue;
146
+ if (containsStepTemplate(args.get(name))) {
147
+ findings.push(note("param-templated", `step "${node.stepId}": argument "${name}" is a {{steps.…}} template — another step's output — so no param replaces it`));
148
+ continue;
149
+ }
150
+ const value = params[name];
151
+ if (containsStepTemplate(value)) {
152
+ findings.push(note("param-template-refused", `step "${node.stepId}": the param for "${name}" contains a {{steps.…}} template; a param is a literal, so it is not applied`));
153
+ continue;
154
+ }
155
+ args.set(name, value);
156
+ replaced.push(name);
157
+ }
158
+ return { args: Object.fromEntries(args), findings, replaced };
159
+ }
160
+ export function prepareArguments(node, outputs, ctx) {
161
+ const applied = applyParamsDetailed(node, ctx.params);
162
+ const refused = ctx.guard?.(node, applied);
163
+ if (refused !== undefined)
164
+ return { ok: false, finding: refused };
165
+ const timed = resolveTimeTokens(applied.args, ctx.now, `step "${node.stepId}"`);
166
+ if (!timed.ok)
167
+ return timed;
168
+ const templated = resolveArguments({ ...node, arguments: timed.value }, outputs);
169
+ if (!templated.ok)
170
+ return templated;
171
+ const finished = ctx.finish ? ctx.finish(templated.args) : templated.args;
172
+ if (ctx.hook === undefined)
173
+ return { ok: true, args: finished, findings: applied.findings };
174
+ let hooked;
175
+ try {
176
+ hooked = ctx.hook(finished, {
177
+ handle: ctx.handle,
178
+ stepId: node.stepId,
179
+ toolName: node.toolName,
180
+ ...(node.kind !== undefined && { kind: node.kind }),
181
+ params: ctx.params,
182
+ now: ctx.now,
183
+ });
184
+ }
185
+ catch (e) {
186
+ return {
187
+ ok: false,
188
+ finding: bad("argument-hook-failed", `step "${node.stepId}": the argument hook threw: ${e instanceof Error ? e.message : String(e)}`),
189
+ };
190
+ }
191
+ if (isThenable(hooked)) {
192
+ // The step callback never awaits a hook (it is documented as synchronous): swallow whatever
193
+ // this thenable eventually does, so an async hook never surfaces as an unhandled rejection.
194
+ hooked.then(() => { }, () => { });
195
+ return {
196
+ ok: false,
197
+ finding: bad("argument-hook-failed", `step "${node.stepId}": the argument hook returned a thenable — hooks must return the arguments object synchronously, not a Promise`),
198
+ };
199
+ }
200
+ if (hooked === null || typeof hooked !== "object" || Array.isArray(hooked))
201
+ return {
202
+ ok: false,
203
+ finding: bad("argument-hook-failed", `step "${node.stepId}": the argument hook returned ${hooked === null ? "null" : Array.isArray(hooked) ? "an array" : typeof hooked}, not an arguments object`),
204
+ };
205
+ return { ok: true, args: hooked, findings: applied.findings };
206
+ }
207
+ //# sourceMappingURL=params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/params.ts"],"names":[],"mappings":"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"}