@loomwork/ui-hydration 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +398 -2
- package/dist/cache.d.ts +71 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +157 -0
- package/dist/cache.js.map +1 -0
- package/dist/chatSource.d.ts +105 -0
- package/dist/chatSource.d.ts.map +1 -0
- package/dist/chatSource.js +264 -0
- package/dist/chatSource.js.map +1 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +36 -0
- package/dist/client.js.map +1 -0
- package/dist/contentRefs.d.ts +78 -0
- package/dist/contentRefs.d.ts.map +1 -0
- package/dist/contentRefs.js +129 -0
- package/dist/contentRefs.js.map +1 -0
- package/dist/controller.d.ts +228 -0
- package/dist/controller.d.ts.map +1 -0
- package/dist/controller.js +454 -0
- package/dist/controller.js.map +1 -0
- package/dist/dataProvider.d.ts +53 -0
- package/dist/dataProvider.d.ts.map +1 -0
- package/dist/dataProvider.js +77 -0
- package/dist/dataProvider.js.map +1 -0
- package/dist/esm/cache.js +151 -0
- package/dist/esm/cache.js.map +1 -0
- package/dist/esm/chatSource.js +259 -0
- package/dist/esm/chatSource.js.map +1 -0
- package/dist/esm/client.js +15 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/contentRefs.js +119 -0
- package/dist/esm/contentRefs.js.map +1 -0
- package/dist/esm/controller.js +449 -0
- package/dist/esm/controller.js.map +1 -0
- package/dist/esm/dataProvider.js +72 -0
- package/dist/esm/dataProvider.js.map +1 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/invoker.js +2 -0
- package/dist/esm/invoker.js.map +1 -0
- package/dist/esm/invokers.js +310 -0
- package/dist/esm/invokers.js.map +1 -0
- package/dist/esm/loomEffectProvider.js +96 -0
- package/dist/esm/loomEffectProvider.js.map +1 -0
- package/dist/esm/params.js +207 -0
- package/dist/esm/params.js.map +1 -0
- package/dist/esm/path.js +24 -0
- package/dist/esm/path.js.map +1 -0
- package/dist/esm/plan.js +190 -0
- package/dist/esm/plan.js.map +1 -0
- package/dist/esm/projection.js +230 -0
- package/dist/esm/projection.js.map +1 -0
- package/dist/esm/provider.js +416 -0
- package/dist/esm/provider.js.map +1 -0
- package/dist/esm/repair.js +53 -0
- package/dist/esm/repair.js.map +1 -0
- package/dist/esm/reshape.js +156 -0
- package/dist/esm/reshape.js.map +1 -0
- package/dist/esm/restricted.js +54 -0
- package/dist/esm/restricted.js.map +1 -0
- package/dist/esm/scheduler.js +247 -0
- package/dist/esm/scheduler.js.map +1 -0
- package/dist/esm/select.js +18 -0
- package/dist/esm/select.js.map +1 -0
- package/dist/esm/shape.js +34 -0
- package/dist/esm/shape.js.map +1 -0
- package/dist/esm/split/client.js +312 -0
- package/dist/esm/split/client.js.map +1 -0
- package/dist/esm/split/index.js +3 -0
- package/dist/esm/split/index.js.map +1 -0
- package/dist/esm/split/server.js +488 -0
- package/dist/esm/split/server.js.map +1 -0
- package/dist/esm/split/shared.js +13 -0
- package/dist/esm/split/shared.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/invoker.d.ts +10 -0
- package/dist/invoker.d.ts.map +1 -0
- package/dist/invoker.js +3 -0
- package/dist/invoker.js.map +1 -0
- package/dist/invokers.d.ts +36 -0
- package/dist/invokers.d.ts.map +1 -0
- package/dist/invokers.js +315 -0
- package/dist/invokers.js.map +1 -0
- package/dist/loomEffectProvider.d.ts +67 -0
- package/dist/loomEffectProvider.d.ts.map +1 -0
- package/dist/loomEffectProvider.js +101 -0
- package/dist/loomEffectProvider.js.map +1 -0
- package/dist/params.d.ts +103 -0
- package/dist/params.d.ts.map +1 -0
- package/dist/params.js +221 -0
- package/dist/params.js.map +1 -0
- package/dist/path.d.ts +12 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +28 -0
- package/dist/path.js.map +1 -0
- package/dist/plan.d.ts +56 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +199 -0
- package/dist/plan.js.map +1 -0
- package/dist/projection.d.ts +122 -0
- package/dist/projection.d.ts.map +1 -0
- package/dist/projection.js +238 -0
- package/dist/projection.js.map +1 -0
- package/dist/provider.d.ts +152 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +421 -0
- package/dist/provider.js.map +1 -0
- package/dist/repair.d.ts +18 -0
- package/dist/repair.d.ts.map +1 -0
- package/dist/repair.js +57 -0
- package/dist/repair.js.map +1 -0
- package/dist/reshape.d.ts +32 -0
- package/dist/reshape.d.ts.map +1 -0
- package/dist/reshape.js +164 -0
- package/dist/reshape.js.map +1 -0
- package/dist/restricted.d.ts +21 -0
- package/dist/restricted.d.ts.map +1 -0
- package/dist/restricted.js +61 -0
- package/dist/restricted.js.map +1 -0
- package/dist/scheduler.d.ts +82 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +254 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/select.d.ts +34 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +21 -0
- package/dist/select.js.map +1 -0
- package/dist/shape.d.ts +3 -0
- package/dist/shape.d.ts.map +1 -0
- package/dist/shape.js +37 -0
- package/dist/shape.js.map +1 -0
- package/dist/split/client.d.ts +135 -0
- package/dist/split/client.d.ts.map +1 -0
- package/dist/split/client.js +316 -0
- package/dist/split/client.js.map +1 -0
- package/dist/split/index.d.ts +5 -0
- package/dist/split/index.d.ts.map +1 -0
- package/dist/split/index.js +14 -0
- package/dist/split/index.js.map +1 -0
- package/dist/split/server.d.ts +160 -0
- package/dist/split/server.d.ts.map +1 -0
- package/dist/split/server.js +496 -0
- package/dist/split/server.js.map +1 -0
- package/dist/split/shared.d.ts +6 -0
- package/dist/split/shared.d.ts.map +1 -0
- package/dist/split/shared.js +19 -0
- package/dist/split/shared.js.map +1 -0
- package/package.json +77 -3
- package/src/cache.ts +211 -0
- package/src/chatSource.ts +378 -0
- package/src/client.ts +46 -0
- package/src/contentRefs.ts +195 -0
- package/src/controller.ts +708 -0
- package/src/dataProvider.ts +141 -0
- package/src/index.ts +86 -0
- package/src/invoker.ts +14 -0
- package/src/invokers.ts +348 -0
- package/src/loomEffectProvider.ts +136 -0
- package/src/params.ts +314 -0
- package/src/path.ts +26 -0
- package/src/plan.ts +197 -0
- package/src/projection.ts +297 -0
- package/src/provider.ts +657 -0
- package/src/repair.ts +70 -0
- package/src/reshape.ts +193 -0
- package/src/restricted.ts +69 -0
- package/src/scheduler.ts +284 -0
- package/src/select.ts +59 -0
- package/src/shape.ts +39 -0
- package/src/split/client.ts +452 -0
- package/src/split/index.ts +18 -0
- package/src/split/server.ts +746 -0
- package/src/split/shared.ts +18 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publishChat = exports.connectConversation = exports.SplitHydrationController = exports.outputShapeHashOf = exports.jsonPathSelect = exports.topoWaves = exports.terminalSteps = exports.stepReferences = exports.checkParams = exports.DEFAULT_TIME_RANGE = exports.handleOfPath = exports.HYDRATION_VALUES_PREFIX = exports.isReservedHandle = exports.hydrationProjection = exports.HydrationStore = exports.HYDRATION_SET_EVENT = exports.HYDRATION_PROJECTION_VERSION = exports.HYDRATION_PROJECTION_ID = void 0;
|
|
4
|
+
// ── @loomwork/ui-hydration/client: the browser entry ─────────────────────────────────
|
|
5
|
+
// Everything a browser needs for SPLIT hydration and nothing that executes a provider: the split
|
|
6
|
+
// controller, the loader contract it calls, the store it publishes to, and param checks. The
|
|
7
|
+
// server half (`handleInventory`, `serveHandles`, `executeProvider`, the invokers and reshapers)
|
|
8
|
+
// stays on the root entry, `@loomwork/ui-hydration`, which imports the sandbox and the MCP plugin.
|
|
9
|
+
// `clientEntry.test.ts` fails the build if this entry's module graph ever reaches them.
|
|
10
|
+
var projection_1 = require("./projection");
|
|
11
|
+
Object.defineProperty(exports, "HYDRATION_PROJECTION_ID", { enumerable: true, get: function () { return projection_1.HYDRATION_PROJECTION_ID; } });
|
|
12
|
+
Object.defineProperty(exports, "HYDRATION_PROJECTION_VERSION", { enumerable: true, get: function () { return projection_1.HYDRATION_PROJECTION_VERSION; } });
|
|
13
|
+
Object.defineProperty(exports, "HYDRATION_SET_EVENT", { enumerable: true, get: function () { return projection_1.HYDRATION_SET_EVENT; } });
|
|
14
|
+
Object.defineProperty(exports, "HydrationStore", { enumerable: true, get: function () { return projection_1.HydrationStore; } });
|
|
15
|
+
Object.defineProperty(exports, "hydrationProjection", { enumerable: true, get: function () { return projection_1.hydrationProjection; } });
|
|
16
|
+
Object.defineProperty(exports, "isReservedHandle", { enumerable: true, get: function () { return projection_1.isReservedHandle; } });
|
|
17
|
+
var path_1 = require("./path");
|
|
18
|
+
Object.defineProperty(exports, "HYDRATION_VALUES_PREFIX", { enumerable: true, get: function () { return path_1.HYDRATION_VALUES_PREFIX; } });
|
|
19
|
+
Object.defineProperty(exports, "handleOfPath", { enumerable: true, get: function () { return path_1.handleOfPath; } });
|
|
20
|
+
var params_1 = require("./params");
|
|
21
|
+
Object.defineProperty(exports, "DEFAULT_TIME_RANGE", { enumerable: true, get: function () { return params_1.DEFAULT_TIME_RANGE; } });
|
|
22
|
+
Object.defineProperty(exports, "checkParams", { enumerable: true, get: function () { return params_1.checkParams; } });
|
|
23
|
+
var plan_1 = require("./plan");
|
|
24
|
+
Object.defineProperty(exports, "stepReferences", { enumerable: true, get: function () { return plan_1.stepReferences; } });
|
|
25
|
+
Object.defineProperty(exports, "terminalSteps", { enumerable: true, get: function () { return plan_1.terminalSteps; } });
|
|
26
|
+
Object.defineProperty(exports, "topoWaves", { enumerable: true, get: function () { return plan_1.topoWaves; } });
|
|
27
|
+
var select_1 = require("./select");
|
|
28
|
+
Object.defineProperty(exports, "jsonPathSelect", { enumerable: true, get: function () { return select_1.jsonPathSelect; } });
|
|
29
|
+
var shape_1 = require("./shape");
|
|
30
|
+
Object.defineProperty(exports, "outputShapeHashOf", { enumerable: true, get: function () { return shape_1.outputShapeHashOf; } });
|
|
31
|
+
var client_1 = require("./split/client");
|
|
32
|
+
Object.defineProperty(exports, "SplitHydrationController", { enumerable: true, get: function () { return client_1.SplitHydrationController; } });
|
|
33
|
+
var chatSource_1 = require("./chatSource");
|
|
34
|
+
Object.defineProperty(exports, "connectConversation", { enumerable: true, get: function () { return chatSource_1.connectConversation; } });
|
|
35
|
+
Object.defineProperty(exports, "publishChat", { enumerable: true, get: function () { return chatSource_1.publishChat; } });
|
|
36
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,wFAAwF;AACxF,iGAAiG;AACjG,6FAA6F;AAC7F,iGAAiG;AACjG,mGAAmG;AACnG,wFAAwF;AACxF,2CAOsB;AANpB,qHAAA,uBAAuB,OAAA;AACvB,0HAAA,4BAA4B,OAAA;AAC5B,iHAAA,mBAAmB,OAAA;AACnB,4GAAA,cAAc,OAAA;AACd,iHAAA,mBAAmB,OAAA;AACnB,8GAAA,gBAAgB,OAAA;AASlB,+BAA+D;AAAtD,+GAAA,uBAAuB,OAAA;AAAE,oGAAA,YAAY,OAAA;AAC9C,mCAA2D;AAAlD,4GAAA,kBAAkB,OAAA;AAAE,qGAAA,WAAW,OAAA;AAGxC,+BAAkE;AAAzD,sGAAA,cAAc,OAAA;AAAE,qGAAA,aAAa,OAAA;AAAE,iGAAA,SAAS,OAAA;AACjD,mCAA0C;AAAjC,wGAAA,cAAc,OAAA;AAEvB,iCAA4C;AAAnC,0GAAA,iBAAiB,OAAA;AAG1B,yCAA0D;AAAjD,kHAAA,wBAAwB,OAAA;AAQjC,2CAAgE;AAAvD,iHAAA,mBAAmB,OAAA;AAAE,yGAAA,WAAW,OAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { TransientInvokeOptions } from "@loomwork/effect-runtime";
|
|
2
|
+
import { type ContentRefTable, type Finding, type MCPToolNode, type ProviderSpec } from "@loomwork/ui-core";
|
|
3
|
+
import { type LoadParams } from "./params";
|
|
4
|
+
export type ContentRefPrincipal = TransientInvokeOptions["principal"];
|
|
5
|
+
/** What the host's gate is told about a param that would fill a content-reference argument. */
|
|
6
|
+
export interface ContentRefParamContext {
|
|
7
|
+
readonly handle: string;
|
|
8
|
+
readonly stepId: string;
|
|
9
|
+
readonly toolName: string;
|
|
10
|
+
readonly kind?: string;
|
|
11
|
+
readonly param: string;
|
|
12
|
+
readonly value: unknown;
|
|
13
|
+
/** The viewer the load runs for (the controller's `principal.id` / serve's `principalId`). */
|
|
14
|
+
readonly principalId?: string;
|
|
15
|
+
/** The full principal chain, when the load has one. */
|
|
16
|
+
readonly principal?: ContentRefPrincipal;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The host's gate on a PARAM that would fill a content-reference argument (U9b). Called once per
|
|
20
|
+
* replaced top-level argument that holds a marked path (for a tool whose schema is `"unknown"`, once
|
|
21
|
+
* per replaced param), EVERY time the answer is wanted: before a cache lookup as well as before a call.
|
|
22
|
+
* Return `true` only for a reference the host itself vouches for: one that `acceptMediaAttach`
|
|
23
|
+
* accepted, was ISSUED TO `ctx.principalId` (check issuance to THIS principal, not merely "some
|
|
24
|
+
* principal"), and is still current (a revoked share must answer `false`). Synchronous; a throw or a
|
|
25
|
+
* non-`true` answer refuses the step. With no gate configured, EVERY such param is refused: a param is
|
|
26
|
+
* a client-reachable value and a content address is a capability.
|
|
27
|
+
*/
|
|
28
|
+
export type ContentRefParamGate = (ctx: ContentRefParamContext) => boolean;
|
|
29
|
+
/** Everything the guard needs about the load; built once per provider load. */
|
|
30
|
+
export interface ContentRefEnv {
|
|
31
|
+
readonly table: ContentRefTable;
|
|
32
|
+
readonly handle: string;
|
|
33
|
+
readonly steps: ReadonlyMap<string, MCPToolNode>;
|
|
34
|
+
readonly acceptContentRefParam?: ContentRefParamGate;
|
|
35
|
+
readonly principalId?: string;
|
|
36
|
+
readonly principal?: ContentRefPrincipal;
|
|
37
|
+
}
|
|
38
|
+
export declare const contentRefEnv: (table: ContentRefTable, spec: ProviderSpec, gate: ContentRefParamGate | undefined, who: {
|
|
39
|
+
principalId?: string | undefined;
|
|
40
|
+
principal?: ContentRefPrincipal | undefined;
|
|
41
|
+
}) => ContentRefEnv;
|
|
42
|
+
/**
|
|
43
|
+
* U9b, defence in depth behind composition: after params are applied and BEFORE anything resolves,
|
|
44
|
+
* a marked content-reference argument must be absent / null, a step reference to an output its tool
|
|
45
|
+
* declares to be a content reference, or a param the host's gate accepted. A model-authored literal,
|
|
46
|
+
* an echo / concat reference, or an ungated param refuses the step, so the call is never made.
|
|
47
|
+
* `paramFilled` says a param filled a guarded argument (the caller then caches per principal only).
|
|
48
|
+
*/
|
|
49
|
+
export declare function checkContentRefs(node: MCPToolNode, applied: {
|
|
50
|
+
readonly args: Record<string, unknown>;
|
|
51
|
+
readonly replaced: readonly string[];
|
|
52
|
+
}, env: ContentRefEnv): {
|
|
53
|
+
readonly finding?: Finding;
|
|
54
|
+
readonly paramFilled: boolean;
|
|
55
|
+
};
|
|
56
|
+
/** `args` without JSON null at the step's marked paths (a tool never sees `null` where a reference belongs). */
|
|
57
|
+
export declare function finishContentRefArgs(node: MCPToolNode, args: Record<string, unknown>, table: ContentRefTable): Record<string, unknown>;
|
|
58
|
+
/**
|
|
59
|
+
* Judge a whole provider BEFORE a cache lookup: the same guard `executeProvider` runs per step, over
|
|
60
|
+
* every step, with the gate asked now. A cached value was produced for an argument the gate accepted
|
|
61
|
+
* once; serving it to another principal, or after the host revoked it, would skip the gate. A
|
|
62
|
+
* refusal means: do not serve from the cache (the load itself will refuse). `paramFilled` means the
|
|
63
|
+
* answer depends on who is asking: cache it per principal, never globally.
|
|
64
|
+
*/
|
|
65
|
+
export declare function inspectContentRefs(spec: ProviderSpec, params: LoadParams, env: ContentRefEnv): {
|
|
66
|
+
readonly refusal?: Finding;
|
|
67
|
+
readonly paramFilled: boolean;
|
|
68
|
+
};
|
|
69
|
+
/** `spec` with `cachePolicy.scope: "principal"` (memoised per spec object, so its fingerprint is computed once). */
|
|
70
|
+
export declare function principalScoped(spec: ProviderSpec): ProviderSpec;
|
|
71
|
+
/** `contentRefArgs` is missing or malformed: a configuration error, never read as "nothing is guarded". */
|
|
72
|
+
export declare class ContentRefConfigError extends Error {
|
|
73
|
+
readonly code = "content-ref-config";
|
|
74
|
+
constructor(where: string);
|
|
75
|
+
}
|
|
76
|
+
/** Throws {@link ContentRefConfigError} unless `value` is `"none"` or exactly a well-formed table. */
|
|
77
|
+
export declare function assertContentRefConfig(value: unknown, where: string): void;
|
|
78
|
+
//# sourceMappingURL=contentRefs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentRefs.d.ts","sourceRoot":"","sources":["../src/contentRefs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentRefConfigError = exports.contentRefEnv = void 0;
|
|
4
|
+
exports.checkContentRefs = checkContentRefs;
|
|
5
|
+
exports.finishContentRefArgs = finishContentRefArgs;
|
|
6
|
+
exports.inspectContentRefs = inspectContentRefs;
|
|
7
|
+
exports.principalScoped = principalScoped;
|
|
8
|
+
exports.assertContentRefConfig = assertContentRefConfig;
|
|
9
|
+
const ui_core_1 = require("@loomwork/ui-core");
|
|
10
|
+
const params_1 = require("./params");
|
|
11
|
+
// U9b, the SERVER half: a module of its own so that the browser entry (which imports params.ts) never
|
|
12
|
+
// reaches `@loomwork/ui-core`'s root, which pulls in node:crypto.
|
|
13
|
+
const bad = (code, message) => ({ code, severity: "error", message });
|
|
14
|
+
const contentRefEnv = (table, spec, gate, who) => ({
|
|
15
|
+
table,
|
|
16
|
+
handle: spec.handle,
|
|
17
|
+
steps: new Map(spec.executionGraph.map((s) => [s.stepId, s])),
|
|
18
|
+
...(gate !== undefined && { acceptContentRefParam: gate }),
|
|
19
|
+
...(who.principalId !== undefined && { principalId: who.principalId }),
|
|
20
|
+
...(who.principal !== undefined && { principal: who.principal }),
|
|
21
|
+
});
|
|
22
|
+
exports.contentRefEnv = contentRefEnv;
|
|
23
|
+
/**
|
|
24
|
+
* U9b, defence in depth behind composition: after params are applied and BEFORE anything resolves,
|
|
25
|
+
* a marked content-reference argument must be absent / null, a step reference to an output its tool
|
|
26
|
+
* declares to be a content reference, or a param the host's gate accepted. A model-authored literal,
|
|
27
|
+
* an echo / concat reference, or an ungated param refuses the step, so the call is never made.
|
|
28
|
+
* `paramFilled` says a param filled a guarded argument (the caller then caches per principal only).
|
|
29
|
+
*/
|
|
30
|
+
function checkContentRefs(node, applied, env) {
|
|
31
|
+
const entry = (0, ui_core_1.contentRefEntry)(env.table, (0, ui_core_1.toolKey)(node));
|
|
32
|
+
if (entry === undefined)
|
|
33
|
+
return { paramFilled: false };
|
|
34
|
+
const skip = new Set();
|
|
35
|
+
// A tool whose schema mentions the marker but cannot be read: every replaced param is gated.
|
|
36
|
+
const guarded = entry === "unknown"
|
|
37
|
+
? new Set(applied.replaced)
|
|
38
|
+
: typeof entry === "string"
|
|
39
|
+
? new Set()
|
|
40
|
+
: (0, ui_core_1.markedTopLevelKeys)(entry);
|
|
41
|
+
let paramFilled = false;
|
|
42
|
+
for (const name of applied.replaced) {
|
|
43
|
+
if (!guarded.has(name))
|
|
44
|
+
continue;
|
|
45
|
+
paramFilled = true;
|
|
46
|
+
let ok = false;
|
|
47
|
+
try {
|
|
48
|
+
ok =
|
|
49
|
+
env.acceptContentRefParam?.({
|
|
50
|
+
handle: env.handle,
|
|
51
|
+
stepId: node.stepId,
|
|
52
|
+
toolName: node.toolName,
|
|
53
|
+
...(node.kind !== undefined && { kind: node.kind }),
|
|
54
|
+
param: name,
|
|
55
|
+
value: applied.args[name],
|
|
56
|
+
...(env.principalId !== undefined && { principalId: env.principalId }),
|
|
57
|
+
...(env.principal !== undefined && { principal: env.principal }),
|
|
58
|
+
}) === true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
ok = false;
|
|
62
|
+
}
|
|
63
|
+
if (!ok)
|
|
64
|
+
return {
|
|
65
|
+
paramFilled,
|
|
66
|
+
finding: bad("media-arg-param-refused", `step "${node.stepId}": the param for "${name}" fills a content-reference argument and the host did not accept it`),
|
|
67
|
+
};
|
|
68
|
+
skip.add(name);
|
|
69
|
+
}
|
|
70
|
+
const found = (0, ui_core_1.contentRefArgFindings)(applied.args, entry, `step "${node.stepId}"`, {
|
|
71
|
+
skipKeys: skip,
|
|
72
|
+
proven: (0, ui_core_1.provenIn)(env.table, env.steps, node.stepId, ui_core_1.toolKey),
|
|
73
|
+
}).find((f) => f.severity === "error");
|
|
74
|
+
return { paramFilled, ...(found !== undefined && { finding: found }) };
|
|
75
|
+
}
|
|
76
|
+
/** `args` without JSON null at the step's marked paths (a tool never sees `null` where a reference belongs). */
|
|
77
|
+
function finishContentRefArgs(node, args, table) {
|
|
78
|
+
const entry = (0, ui_core_1.contentRefEntry)(table, (0, ui_core_1.toolKey)(node));
|
|
79
|
+
return entry === undefined || typeof entry === "string"
|
|
80
|
+
? args
|
|
81
|
+
: (0, ui_core_1.stripNullContentRefs)(args, entry);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Judge a whole provider BEFORE a cache lookup: the same guard `executeProvider` runs per step, over
|
|
85
|
+
* every step, with the gate asked now. A cached value was produced for an argument the gate accepted
|
|
86
|
+
* once; serving it to another principal, or after the host revoked it, would skip the gate. A
|
|
87
|
+
* refusal means: do not serve from the cache (the load itself will refuse). `paramFilled` means the
|
|
88
|
+
* answer depends on who is asking: cache it per principal, never globally.
|
|
89
|
+
*/
|
|
90
|
+
function inspectContentRefs(spec, params, env) {
|
|
91
|
+
let paramFilled = false;
|
|
92
|
+
for (const step of spec.executionGraph) {
|
|
93
|
+
const applied = (0, params_1.applyParamsDetailed)(step, params);
|
|
94
|
+
const r = checkContentRefs(step, applied, env);
|
|
95
|
+
paramFilled ||= r.paramFilled;
|
|
96
|
+
if (r.finding !== undefined)
|
|
97
|
+
return { refusal: r.finding, paramFilled };
|
|
98
|
+
}
|
|
99
|
+
return { paramFilled };
|
|
100
|
+
}
|
|
101
|
+
const PRINCIPAL_SCOPED = new WeakMap();
|
|
102
|
+
/** `spec` with `cachePolicy.scope: "principal"` (memoised per spec object, so its fingerprint is computed once). */
|
|
103
|
+
function principalScoped(spec) {
|
|
104
|
+
if (spec.cachePolicy.scope === "principal")
|
|
105
|
+
return spec;
|
|
106
|
+
let s = PRINCIPAL_SCOPED.get(spec);
|
|
107
|
+
if (s === undefined) {
|
|
108
|
+
s = { ...spec, cachePolicy: { ...spec.cachePolicy, scope: "principal" } };
|
|
109
|
+
PRINCIPAL_SCOPED.set(spec, s);
|
|
110
|
+
}
|
|
111
|
+
return s;
|
|
112
|
+
}
|
|
113
|
+
/** `contentRefArgs` is missing or malformed: a configuration error, never read as "nothing is guarded". */
|
|
114
|
+
class ContentRefConfigError extends Error {
|
|
115
|
+
code = "content-ref-config";
|
|
116
|
+
constructor(where) {
|
|
117
|
+
super(`${where}: contentRefArgs is required: pass the table contentRefArgsFrom(capabilities) builds (a malformed or missing one is refused, never read as "none"), or the explicit opt-out "none"`);
|
|
118
|
+
this.name = "ContentRefConfigError";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.ContentRefConfigError = ContentRefConfigError;
|
|
122
|
+
/** Throws {@link ContentRefConfigError} unless `value` is `"none"` or exactly a well-formed table. */
|
|
123
|
+
function assertContentRefConfig(value, where) {
|
|
124
|
+
if (value === "none")
|
|
125
|
+
return;
|
|
126
|
+
if ((0, ui_core_1.parseContentRefTable)(value) === undefined)
|
|
127
|
+
throw new ContentRefConfigError(where);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=contentRefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contentRefs.js","sourceRoot":"","sources":["../src/contentRefs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type { TransientInvokeOptions } from "@loomwork/effect-runtime";
|
|
2
|
+
import { type Audience, type ContentRefTable, type DeclaredToolClasses, type Experience, type Finding, type ProviderSpec, type ReadPolicy, type SemanticCatalog, type Surface, type UndeclaredToolPolicy, type Viewer } from "@loomwork/ui-core";
|
|
3
|
+
import { HydrationCache } from "./cache";
|
|
4
|
+
import { type ContentRefParamGate } from "./contentRefs";
|
|
5
|
+
import type { DataProviderRegistry } from "./dataProvider";
|
|
6
|
+
import type { TransientInvoker } from "./invoker";
|
|
7
|
+
import { type ArgumentHook, type LoadParams } from "./params";
|
|
8
|
+
import { type HydrationStore } from "./projection";
|
|
9
|
+
import { type DriftRecord, type InputDriftMode } from "./provider";
|
|
10
|
+
import type { ReshaperRegistry } from "./reshape";
|
|
11
|
+
export interface DriftReport {
|
|
12
|
+
readonly experienceId: string;
|
|
13
|
+
readonly versionHash: string;
|
|
14
|
+
readonly handle: string;
|
|
15
|
+
readonly spec: ProviderSpec;
|
|
16
|
+
readonly drift: readonly DriftRecord[];
|
|
17
|
+
readonly findings: readonly Finding[];
|
|
18
|
+
/** `true` when the load retried with the observed pin and published (`inputDrift: "report-and-proceed"`). */
|
|
19
|
+
readonly proceeded: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ControllerOptions {
|
|
22
|
+
readonly invoker: TransientInvoker;
|
|
23
|
+
readonly store: HydrationStore;
|
|
24
|
+
/** Cache TTLs AND relative-time tokens run on this clock (read once per pass). Default `Date.now`. */
|
|
25
|
+
readonly clock?: () => number;
|
|
26
|
+
/** Schedule `fn` after `ms`; returns a cancel. Default: setTimeout/clearTimeout. */
|
|
27
|
+
readonly setTimer?: (fn: () => void, ms: number) => () => void;
|
|
28
|
+
readonly batchWindowMs?: number;
|
|
29
|
+
/** Parallel steps per wave within ONE provider. Default 4. */
|
|
30
|
+
readonly concurrency?: number;
|
|
31
|
+
/** At most this many transient calls in flight across the WHOLE controller. Default: unbounded. */
|
|
32
|
+
readonly maxConcurrentCalls?: number;
|
|
33
|
+
readonly principal?: {
|
|
34
|
+
readonly id: string;
|
|
35
|
+
readonly chain?: TransientInvokeOptions["principal"];
|
|
36
|
+
};
|
|
37
|
+
readonly cache?: HydrationCache;
|
|
38
|
+
/**
|
|
39
|
+
* Who the data is for (`@loomwork/ui-core`'s `Viewer`). A handle bound by any node classified above
|
|
40
|
+
* the viewer's clearance is never loaded: its provider is not invoked, nothing is cached for it,
|
|
41
|
+
* and NOTHING is written to the store for it (no value, no status: a store projected to a client
|
|
42
|
+
* must not even name it). SNAPSHOT at construction: later mutation of this object changes
|
|
43
|
+
* nothing; a different viewer needs {@link HydrationController.setViewer} (or a new
|
|
44
|
+
* controller). FAIL-CLOSED: absent = a viewer
|
|
45
|
+
* with no clearance (and `load` reports one `viewer-not-supplied` warn if anything is
|
|
46
|
+
* classified); unclassified handles are unaffected. Pass `{ clearance: "secret" }` for full access.
|
|
47
|
+
*/
|
|
48
|
+
readonly viewer?: Viewer;
|
|
49
|
+
/**
|
|
50
|
+
* Who the surface is for, the SAME value `compile` takes (`@loomwork/ui-core` `Audience`). `"broadcast"`
|
|
51
|
+
* clamps the viewer to the audience's ceiling (unclassified data only): every handle `compile`
|
|
52
|
+
* withheld for the audience is never loaded, cached or written to the store, and `appendStream`
|
|
53
|
+
* and friends refuse it, whoever the `viewer` is. Absent / `"viewer"` = the viewer as given.
|
|
54
|
+
*/
|
|
55
|
+
readonly audience?: Audience;
|
|
56
|
+
/**
|
|
57
|
+
* The host's DECLARED class per tool (`toolKey`), a read-time floor under every handle calling
|
|
58
|
+
* that tool (`@loomwork/ui-core` `DeclaredToolClasses`): a handle whose stored nodes carry no class
|
|
59
|
+
* is still gated as strictly as its tool is declared. Absent = only the experience's own classes.
|
|
60
|
+
*/
|
|
61
|
+
readonly declaredToolClasses?: DeclaredToolClasses;
|
|
62
|
+
/**
|
|
63
|
+
* The host's whole {@link ReadPolicy}, the SAME value `createServeSurface` takes, so one policy
|
|
64
|
+
* serves both. Bound first; the separate `declaredToolClasses` / `undeclared` options join it
|
|
65
|
+
* raise-only (`mergeReadPolicy`), so neither can lower the other.
|
|
66
|
+
*/
|
|
67
|
+
readonly readPolicy?: ReadPolicy;
|
|
68
|
+
/**
|
|
69
|
+
* What a tool the `declaredToolClasses` table does not list reads as: `"allow"` (default) = as the
|
|
70
|
+
* experience itself says; `"deny"` = no viewer may read it (only with a table present).
|
|
71
|
+
*/
|
|
72
|
+
readonly undeclared?: UndeclaredToolPolicy;
|
|
73
|
+
readonly onDrift?: (report: DriftReport) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Where `outputCheck: "contract"` providers get their kinds: every bound node resolved on this
|
|
76
|
+
* surface through this catalogue (`handleKinds`). Without it a contract provider is an error.
|
|
77
|
+
*/
|
|
78
|
+
readonly outputKinds?: {
|
|
79
|
+
readonly catalog: SemanticCatalog;
|
|
80
|
+
readonly surface: Surface;
|
|
81
|
+
};
|
|
82
|
+
/** Params every load starts from (e.g. `DEFAULT_TIME_RANGE`); `setParams` layers over them. */
|
|
83
|
+
readonly defaultParams?: LoadParams;
|
|
84
|
+
/** On an input-schema drift: `"report"` (default) goes stale; `"report-and-proceed"` publishes. */
|
|
85
|
+
readonly inputDrift?: InputDriftMode;
|
|
86
|
+
/** The host's last word on each step's arguments (after params, time tokens, templates). */
|
|
87
|
+
readonly argumentHook?: ArgumentHook;
|
|
88
|
+
/**
|
|
89
|
+
* REQUIRED (U9b): the marked content-reference argument paths per tool, derived from the offered
|
|
90
|
+
* capabilities with the planner's `contentRefArgsFrom(capabilities)` (persist it with the capability
|
|
91
|
+
* set; `parseContentRefTable` re-reads it). A step whose marked argument holds a literal, or a
|
|
92
|
+
* reference to an output its tool does not declare to be one, is refused (`media-arg-literal` /
|
|
93
|
+
* `media-arg-unproven-ref`) and its call is NOT made, whatever validation did or did not run. `"none"`
|
|
94
|
+
* is the explicit opt-out: nothing is guarded, and loading an experience with media nodes then returns
|
|
95
|
+
* a `media-content-refs-unguarded` warning.
|
|
96
|
+
*/
|
|
97
|
+
readonly contentRefArgs: ContentRefTable | "none";
|
|
98
|
+
/**
|
|
99
|
+
* U9b: the host's gate on a PARAM that fills a marked argument. Return `true` only for a reference
|
|
100
|
+
* the host vouches for, i.e. one that `acceptMediaAttach` accepted for this principal. Absent =
|
|
101
|
+
* every such param is refused.
|
|
102
|
+
*/
|
|
103
|
+
readonly acceptContentRefParam?: ContentRefParamGate;
|
|
104
|
+
/** Where `Named` reshaping looks its reshapers up. */
|
|
105
|
+
readonly reshapers?: ReshaperRegistry;
|
|
106
|
+
/** The data-provider kinds composed for this controller (default: MCP only). */
|
|
107
|
+
readonly providers?: DataProviderRegistry;
|
|
108
|
+
/**
|
|
109
|
+
* Attach the RAW terminal output to each output-drift record `onDrift` reports, as a tainted
|
|
110
|
+
* sample (`DriftRecord.observedSample`) — what a planner repair pins against. Default false.
|
|
111
|
+
* The same option `serveHandle` takes, so in-process and split drift reports carry the same.
|
|
112
|
+
*/
|
|
113
|
+
readonly captureSample?: boolean;
|
|
114
|
+
}
|
|
115
|
+
export declare function loadFingerprint(spec: ProviderSpec, kinds: readonly string[]): string;
|
|
116
|
+
export declare class HydrationController {
|
|
117
|
+
private readonly opts;
|
|
118
|
+
private readonly cache;
|
|
119
|
+
private readonly clock;
|
|
120
|
+
private readonly sched;
|
|
121
|
+
private current;
|
|
122
|
+
private kinds;
|
|
123
|
+
private globalParams;
|
|
124
|
+
private readonly scopedParams;
|
|
125
|
+
private readonly lifetime;
|
|
126
|
+
/**
|
|
127
|
+
* Throws `RangeError` for a `maxConcurrentCalls` that is not a positive integer, or
|
|
128
|
+
* `defaultParams` that `checkParams` refuses.
|
|
129
|
+
*/
|
|
130
|
+
/** The viewer, copied once at construction so a live mutation of the caller's object is inert. */
|
|
131
|
+
private viewer;
|
|
132
|
+
/**
|
|
133
|
+
* Handles that may take token chunks RIGHT NOW: bound by the current experience, cleared for the
|
|
134
|
+
* viewer, and (when output kinds are known) resolving to `StreamingText`. Rebuilt on every bind.
|
|
135
|
+
*/
|
|
136
|
+
private streamable;
|
|
137
|
+
private bound;
|
|
138
|
+
private readonly policy;
|
|
139
|
+
private readonly broadcast;
|
|
140
|
+
private readonly audience;
|
|
141
|
+
constructor(opts: ControllerOptions);
|
|
142
|
+
/**
|
|
143
|
+
* Bind an experience: schedule every handle it binds. Findings for handles that cannot load.
|
|
144
|
+
* A second `load` while one experience is already bound IS a recompose — the previous
|
|
145
|
+
* experience's handles are aborted and dropped rather than left published forever.
|
|
146
|
+
*/
|
|
147
|
+
load(exp: Experience): {
|
|
148
|
+
findings: Finding[];
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Replace the viewer and re-plan the bound experience: a handle the new viewer may not see is
|
|
152
|
+
* aborted and dropped (an in-flight result is discarded, a loaded value removed), one it newly
|
|
153
|
+
* may see is scheduled. Before any `load` it only records the viewer.
|
|
154
|
+
*/
|
|
155
|
+
setViewer(viewer: Viewer | undefined): {
|
|
156
|
+
findings: Finding[];
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Append one token chunk to a `StreamingText` handle, through the same viewer gate as `load`:
|
|
160
|
+
* refused (a finding, nothing written) for a handle that is not bound by the current
|
|
161
|
+
* experience (`stream-unbound`), is restricted for the viewer (`restricted`, the fixed text that
|
|
162
|
+
* names nothing), or — when `outputKinds` is configured — does not resolve to `StreamingText`
|
|
163
|
+
* (`stream-kind-mismatch`). Without `outputKinds` the kind is unknown and is not checked. The
|
|
164
|
+
* store's own `append` is gated by the same rule once a controller fronts it.
|
|
165
|
+
*/
|
|
166
|
+
append(handle: string, chunk: unknown): {
|
|
167
|
+
ok: true;
|
|
168
|
+
applied: boolean;
|
|
169
|
+
} | {
|
|
170
|
+
ok: false;
|
|
171
|
+
finding: Finding;
|
|
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: string, value: unknown, options?: {
|
|
182
|
+
readonly state?: "ready" | "pending";
|
|
183
|
+
readonly kind?: string;
|
|
184
|
+
}): {
|
|
185
|
+
ok: true;
|
|
186
|
+
} | {
|
|
187
|
+
ok: false;
|
|
188
|
+
finding: Finding;
|
|
189
|
+
};
|
|
190
|
+
private appendRefusal;
|
|
191
|
+
private restrictedHandles;
|
|
192
|
+
/** The surface reports a lazy (P2) widget entered the viewport. */
|
|
193
|
+
markVisible(handle: string): void;
|
|
194
|
+
/** A new artifact replaces the current one: abort and drop unbound handles, keep the rest, load new ones. */
|
|
195
|
+
recompose(next: Experience): {
|
|
196
|
+
findings: Finding[];
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Replace the global params (no `scope.handle`) or one handle's scoped params, then re-ask
|
|
200
|
+
* every bound handle whose question changed — only those, so a handle that ended on `error`
|
|
201
|
+
* with an unchanged question is NOT retried here (`invalidate` retries it). `{}` clears.
|
|
202
|
+
* Refused, with nothing changed, for params `checkParams` refuses or a reserved handle. A lazy
|
|
203
|
+
* (P2) handle whose question changed waits for its next `markVisible`. Params scoped to a handle
|
|
204
|
+
* the experience does not bind are kept only until the next bind, which forgets them.
|
|
205
|
+
*/
|
|
206
|
+
setParams(params: LoadParams, scope?: {
|
|
207
|
+
readonly handle?: string;
|
|
208
|
+
}): {
|
|
209
|
+
findings: Finding[];
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Drop cached results (one handle or all) and reload the affected bound handles. An in-flight
|
|
213
|
+
* load answering the invalidated question is superseded; a lazy (P2) widget stays lazy.
|
|
214
|
+
*/
|
|
215
|
+
invalidate(handle?: string): {
|
|
216
|
+
findings: Finding[];
|
|
217
|
+
};
|
|
218
|
+
inFlight(): string[];
|
|
219
|
+
/** Terminal: every in-flight load is aborted and reported, and nothing schedules again. */
|
|
220
|
+
dispose(): void;
|
|
221
|
+
private bind;
|
|
222
|
+
/** Pure: the jobs `exp` asks for right now, and the handles that cannot load (with why). */
|
|
223
|
+
private plan;
|
|
224
|
+
/** The content-reference guard over a whole job (asks the host's gate now); `undefined` when nothing is guarded. */
|
|
225
|
+
private refsVerdict;
|
|
226
|
+
private run;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
|