@contractspec/lib.surface-runtime 0.2.3 → 0.3.2
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/dist/adapters/ai-sdk-stub.js +1 -6
- package/dist/adapters/blocknote-stub.js +3 -8
- package/dist/adapters/dnd-kit-adapter.js +6 -11
- package/dist/adapters/dnd-kit-stub.js +1 -6
- package/dist/adapters/floating-ui-stub.js +4 -9
- package/dist/adapters/index.js +7 -176
- package/dist/adapters/interfaces.js +0 -1
- package/dist/adapters/motion-stub.js +2 -7
- package/dist/adapters/resizable-panels-stub.js +7 -12
- package/dist/browser/adapters/ai-sdk-stub.js +1 -5
- package/dist/browser/adapters/blocknote-stub.js +3 -7
- package/dist/browser/adapters/dnd-kit-adapter.js +6 -10
- package/dist/browser/adapters/dnd-kit-stub.js +1 -5
- package/dist/browser/adapters/floating-ui-stub.js +4 -8
- package/dist/browser/adapters/index.js +7 -175
- package/dist/browser/adapters/motion-stub.js +2 -6
- package/dist/browser/adapters/resizable-panels-stub.js +5 -9
- package/dist/browser/evals/golden-harness.js +4 -825
- package/dist/browser/examples/pm-workbench.bundle.js +2 -316
- package/dist/browser/i18n/catalogs/en.js +1 -5
- package/dist/browser/i18n/catalogs/es.js +1 -5
- package/dist/browser/i18n/catalogs/fr.js +1 -5
- package/dist/browser/i18n/catalogs/index.js +3 -133
- package/dist/browser/i18n/index.js +3 -168
- package/dist/browser/i18n/keys.js +1 -5
- package/dist/browser/i18n/messages.js +6 -137
- package/dist/browser/index.js +4 -2466
- package/dist/browser/react/BundleProvider.js +12 -19
- package/dist/browser/react/BundleRenderer.js +19 -662
- package/dist/browser/react/OverlayConflictResolver.js +12 -180
- package/dist/browser/react/PatchProposalCard.js +9 -177
- package/dist/browser/react/RegionRenderer.js +14 -60
- package/dist/browser/react/SlotRenderer.js +15 -58
- package/dist/browser/react/WidgetPalette.js +6 -10
- package/dist/browser/react/index.js +14 -790
- package/dist/browser/runtime/apply-surface-patch.js +3 -208
- package/dist/browser/runtime/audit-events.js +8 -19
- package/dist/browser/runtime/build-context.js +2 -6
- package/dist/browser/runtime/extension-registry.js +3 -9
- package/dist/browser/runtime/field-renderer-registry.js +5 -11
- package/dist/browser/runtime/index.js +54 -1487
- package/dist/browser/runtime/overlay-alignment.js +8 -19
- package/dist/browser/runtime/overlay-signer.js +2 -7
- package/dist/browser/runtime/override-store.js +3 -9
- package/dist/browser/runtime/planner-prompt.js +2 -6
- package/dist/browser/runtime/planner-tools.js +3 -9
- package/dist/browser/runtime/policy-eval.js +3 -135
- package/dist/browser/runtime/preference-adapter.js +2 -62
- package/dist/browser/runtime/resolve-bundle.js +10 -447
- package/dist/browser/runtime/resolve-preferences.js +3 -7
- package/dist/browser/runtime/rollback.js +2 -325
- package/dist/browser/runtime/widget-registry.js +1 -5
- package/dist/browser/spec/define-module-bundle.js +2 -67
- package/dist/browser/spec/index.js +9 -317
- package/dist/browser/spec/validate-bundle.js +3 -8
- package/dist/browser/spec/validate-surface-patch.js +5 -11
- package/dist/browser/telemetry/index.js +4 -16
- package/dist/browser/telemetry/surface-metrics.js +7 -16
- package/dist/evals/golden-context.js +0 -1
- package/dist/evals/golden-harness.js +4 -826
- package/dist/examples/pm-workbench.bundle.js +2 -317
- package/dist/i18n/catalogs/en.js +1 -6
- package/dist/i18n/catalogs/es.js +1 -6
- package/dist/i18n/catalogs/fr.js +1 -6
- package/dist/i18n/catalogs/index.js +3 -134
- package/dist/i18n/index.js +3 -169
- package/dist/i18n/keys.js +1 -6
- package/dist/i18n/messages.js +6 -138
- package/dist/index.js +4 -2467
- package/dist/node/adapters/ai-sdk-stub.js +1 -5
- package/dist/node/adapters/blocknote-stub.js +3 -7
- package/dist/node/adapters/dnd-kit-adapter.js +6 -10
- package/dist/node/adapters/dnd-kit-stub.js +1 -5
- package/dist/node/adapters/floating-ui-stub.js +4 -8
- package/dist/node/adapters/index.js +7 -175
- package/dist/node/adapters/motion-stub.js +2 -6
- package/dist/node/adapters/resizable-panels-stub.js +5 -9
- package/dist/node/evals/golden-harness.js +4 -825
- package/dist/node/examples/pm-workbench.bundle.js +2 -316
- package/dist/node/i18n/catalogs/en.js +1 -5
- package/dist/node/i18n/catalogs/es.js +1 -5
- package/dist/node/i18n/catalogs/fr.js +1 -5
- package/dist/node/i18n/catalogs/index.js +3 -133
- package/dist/node/i18n/index.js +3 -168
- package/dist/node/i18n/keys.js +1 -5
- package/dist/node/i18n/messages.js +6 -137
- package/dist/node/index.js +4 -2466
- package/dist/node/react/BundleProvider.js +12 -19
- package/dist/node/react/BundleRenderer.js +19 -662
- package/dist/node/react/OverlayConflictResolver.js +12 -180
- package/dist/node/react/PatchProposalCard.js +9 -177
- package/dist/node/react/RegionRenderer.js +14 -60
- package/dist/node/react/SlotRenderer.js +15 -58
- package/dist/node/react/WidgetPalette.js +6 -10
- package/dist/node/react/index.js +14 -790
- package/dist/node/runtime/apply-surface-patch.js +3 -208
- package/dist/node/runtime/audit-events.js +8 -19
- package/dist/node/runtime/build-context.js +2 -6
- package/dist/node/runtime/extension-registry.js +3 -9
- package/dist/node/runtime/field-renderer-registry.js +5 -11
- package/dist/node/runtime/index.js +54 -1487
- package/dist/node/runtime/overlay-alignment.js +8 -19
- package/dist/node/runtime/overlay-signer.js +2 -7
- package/dist/node/runtime/override-store.js +3 -9
- package/dist/node/runtime/planner-prompt.js +2 -6
- package/dist/node/runtime/planner-tools.js +3 -9
- package/dist/node/runtime/policy-eval.js +3 -135
- package/dist/node/runtime/preference-adapter.js +2 -62
- package/dist/node/runtime/resolve-bundle.js +10 -447
- package/dist/node/runtime/resolve-preferences.js +3 -7
- package/dist/node/runtime/rollback.js +2 -325
- package/dist/node/runtime/widget-registry.js +1 -5
- package/dist/node/spec/define-module-bundle.js +2 -67
- package/dist/node/spec/index.js +9 -317
- package/dist/node/spec/validate-bundle.js +3 -8
- package/dist/node/spec/validate-surface-patch.js +5 -11
- package/dist/node/telemetry/index.js +4 -16
- package/dist/node/telemetry/surface-metrics.js +7 -16
- package/dist/react/BundleProvider.js +12 -20
- package/dist/react/BundleRenderer.d.ts +3 -1
- package/dist/react/BundleRenderer.js +19 -663
- package/dist/react/OverlayConflictResolver.js +12 -181
- package/dist/react/PatchProposalCard.js +9 -178
- package/dist/react/RegionRenderer.js +14 -61
- package/dist/react/SlotRenderer.js +15 -59
- package/dist/react/WidgetPalette.js +6 -11
- package/dist/react/index.js +14 -791
- package/dist/runtime/apply-surface-patch.js +3 -209
- package/dist/runtime/audit-events.js +8 -20
- package/dist/runtime/build-context.js +2 -7
- package/dist/runtime/extension-registry.js +3 -10
- package/dist/runtime/field-renderer-registry.js +9 -16
- package/dist/runtime/index.js +54 -1488
- package/dist/runtime/overlay-alignment.js +8 -20
- package/dist/runtime/overlay-signer.js +2 -8
- package/dist/runtime/override-store.js +3 -10
- package/dist/runtime/planner-prompt.js +11 -9
- package/dist/runtime/planner-tools.js +4 -11
- package/dist/runtime/policy-eval.js +3 -136
- package/dist/runtime/preference-adapter.js +2 -63
- package/dist/runtime/resolve-bundle.js +10 -448
- package/dist/runtime/resolve-preferences.js +3 -8
- package/dist/runtime/rollback.js +2 -326
- package/dist/runtime/widget-registry.js +1 -6
- package/dist/spec/define-module-bundle.js +2 -68
- package/dist/spec/index.js +9 -318
- package/dist/spec/types.js +0 -1
- package/dist/spec/validate-bundle.js +3 -9
- package/dist/spec/validate-surface-patch.js +5 -12
- package/dist/spec/verification-snapshot-types.js +0 -1
- package/dist/telemetry/index.js +4 -17
- package/dist/telemetry/surface-metrics.js +7 -17
- package/package.json +7 -7
package/dist/node/spec/index.js
CHANGED
|
@@ -1,319 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
"insert-node",
|
|
4
|
-
"replace-node",
|
|
5
|
-
"remove-node",
|
|
6
|
-
"move-node",
|
|
7
|
-
"resize-panel",
|
|
8
|
-
"set-layout",
|
|
9
|
-
"reveal-field",
|
|
10
|
-
"hide-field",
|
|
11
|
-
"promote-action",
|
|
12
|
-
"set-focus"
|
|
13
|
-
];
|
|
14
|
-
var VALID_NODE_KINDS = [
|
|
15
|
-
"metric-strip",
|
|
16
|
-
"data-view",
|
|
17
|
-
"entity-card",
|
|
18
|
-
"entity-header",
|
|
19
|
-
"entity-summary",
|
|
20
|
-
"entity-section",
|
|
21
|
-
"entity-field",
|
|
22
|
-
"entity-activity",
|
|
23
|
-
"entity-relations",
|
|
24
|
-
"entity-timeline",
|
|
25
|
-
"entity-comments",
|
|
26
|
-
"entity-attachments",
|
|
27
|
-
"entity-view-switcher",
|
|
28
|
-
"entity-automation-panel",
|
|
29
|
-
"rich-doc",
|
|
30
|
-
"chat-thread",
|
|
31
|
-
"assistant-panel",
|
|
32
|
-
"action-bar",
|
|
33
|
-
"timeline",
|
|
34
|
-
"board",
|
|
35
|
-
"table",
|
|
36
|
-
"calendar",
|
|
37
|
-
"form",
|
|
38
|
-
"chart",
|
|
39
|
-
"relation-graph",
|
|
40
|
-
"custom-widget"
|
|
41
|
-
];
|
|
42
|
-
function validateSurfaceNode(node, path) {
|
|
43
|
-
if (!node.nodeId || typeof node.nodeId !== "string") {
|
|
44
|
-
throw new Error(`${path}: nodeId must be a non-empty string`);
|
|
45
|
-
}
|
|
46
|
-
if (!node.kind || !VALID_NODE_KINDS.includes(node.kind)) {
|
|
47
|
-
throw new Error(`${path}: kind must be one of ${VALID_NODE_KINDS.join(", ")}`);
|
|
48
|
-
}
|
|
49
|
-
if (node.children) {
|
|
50
|
-
for (let i = 0;i < node.children.length; i++) {
|
|
51
|
-
const child = node.children[i];
|
|
52
|
-
if (child)
|
|
53
|
-
validateSurfaceNode(child, `${path}.children[${i}]`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function validateSurfacePatchOp(op, index) {
|
|
58
|
-
const path = `ops[${index}]`;
|
|
59
|
-
if (!op || typeof op !== "object" || !("op" in op)) {
|
|
60
|
-
throw new Error(`${path}: must be an object with op field`);
|
|
61
|
-
}
|
|
62
|
-
const opType = op.op;
|
|
63
|
-
if (!VALID_OPS.includes(opType)) {
|
|
64
|
-
throw new Error(`${path}: op must be one of ${VALID_OPS.join(", ")}`);
|
|
65
|
-
}
|
|
66
|
-
switch (op.op) {
|
|
67
|
-
case "insert-node":
|
|
68
|
-
if (!op.slotId || typeof op.slotId !== "string") {
|
|
69
|
-
throw new Error(`${path}: insert-node requires slotId string`);
|
|
70
|
-
}
|
|
71
|
-
if (!op.node) {
|
|
72
|
-
throw new Error(`${path}: insert-node requires node`);
|
|
73
|
-
}
|
|
74
|
-
validateSurfaceNode(op.node, `${path}.node`);
|
|
75
|
-
if (op.index !== undefined && typeof op.index !== "number") {
|
|
76
|
-
throw new Error(`${path}: insert-node index must be number if present`);
|
|
77
|
-
}
|
|
78
|
-
break;
|
|
79
|
-
case "replace-node":
|
|
80
|
-
if (!op.nodeId || typeof op.nodeId !== "string") {
|
|
81
|
-
throw new Error(`${path}: replace-node requires nodeId string`);
|
|
82
|
-
}
|
|
83
|
-
if (!op.node) {
|
|
84
|
-
throw new Error(`${path}: replace-node requires node`);
|
|
85
|
-
}
|
|
86
|
-
validateSurfaceNode(op.node, `${path}.node`);
|
|
87
|
-
break;
|
|
88
|
-
case "remove-node":
|
|
89
|
-
if (!op.nodeId || typeof op.nodeId !== "string") {
|
|
90
|
-
throw new Error(`${path}: remove-node requires nodeId string`);
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
case "move-node":
|
|
94
|
-
if (!op.nodeId || typeof op.nodeId !== "string") {
|
|
95
|
-
throw new Error(`${path}: move-node requires nodeId string`);
|
|
96
|
-
}
|
|
97
|
-
if (!op.toSlotId || typeof op.toSlotId !== "string") {
|
|
98
|
-
throw new Error(`${path}: move-node requires toSlotId string`);
|
|
99
|
-
}
|
|
100
|
-
if (op.index !== undefined && typeof op.index !== "number") {
|
|
101
|
-
throw new Error(`${path}: move-node index must be number if present`);
|
|
102
|
-
}
|
|
103
|
-
break;
|
|
104
|
-
case "resize-panel":
|
|
105
|
-
if (!op.persistKey || typeof op.persistKey !== "string") {
|
|
106
|
-
throw new Error(`${path}: resize-panel requires persistKey string`);
|
|
107
|
-
}
|
|
108
|
-
if (!Array.isArray(op.sizes) || op.sizes.some((s) => typeof s !== "number")) {
|
|
109
|
-
throw new Error(`${path}: resize-panel requires sizes number[]`);
|
|
110
|
-
}
|
|
111
|
-
break;
|
|
112
|
-
case "set-layout":
|
|
113
|
-
if (!op.layoutId || typeof op.layoutId !== "string") {
|
|
114
|
-
throw new Error(`${path}: set-layout requires layoutId string`);
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
case "reveal-field":
|
|
118
|
-
case "hide-field":
|
|
119
|
-
if (!op.fieldId || typeof op.fieldId !== "string") {
|
|
120
|
-
throw new Error(`${path}: ${op.op} requires fieldId string`);
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
123
|
-
case "promote-action": {
|
|
124
|
-
if (!op.actionId || typeof op.actionId !== "string") {
|
|
125
|
-
throw new Error(`${path}: promote-action requires actionId string`);
|
|
126
|
-
}
|
|
127
|
-
const validPlacements = ["header", "inline", "context", "assistant"];
|
|
128
|
-
if (!op.placement || !validPlacements.includes(op.placement)) {
|
|
129
|
-
throw new Error(`${path}: promote-action placement must be one of ${validPlacements.join(", ")}`);
|
|
130
|
-
}
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
case "set-focus":
|
|
134
|
-
if (!op.targetId || typeof op.targetId !== "string") {
|
|
135
|
-
throw new Error(`${path}: set-focus requires targetId string`);
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
default:
|
|
139
|
-
throw new Error(`${path}: unknown op "${opType}"`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function validateSurfacePatch(ops) {
|
|
143
|
-
if (!Array.isArray(ops)) {
|
|
144
|
-
throw new Error("Patch ops must be an array");
|
|
145
|
-
}
|
|
146
|
-
for (let i = 0;i < ops.length; i++) {
|
|
147
|
-
const op = ops[i];
|
|
148
|
-
if (op)
|
|
149
|
-
validateSurfacePatchOp(op, i);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function validateSurfaceNodeAgainstKinds(node, allowedKinds, path) {
|
|
153
|
-
if (!allowedKinds.includes(node.kind)) {
|
|
154
|
-
throw new Error(`${path}: kind "${node.kind}" not in allowed list [${allowedKinds.join(", ")}]`);
|
|
155
|
-
}
|
|
156
|
-
if (node.children) {
|
|
157
|
-
for (let i = 0;i < node.children.length; i++) {
|
|
158
|
-
const child = node.children[i];
|
|
159
|
-
if (child)
|
|
160
|
-
validateSurfaceNodeAgainstKinds(child, allowedKinds, `${path}.children[${i}]`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
function validatePatchProposal(ops, constraints) {
|
|
165
|
-
if (!Array.isArray(ops)) {
|
|
166
|
-
throw new Error("Patch ops must be an array");
|
|
167
|
-
}
|
|
168
|
-
const { allowedOps, allowedSlots, allowedNodeKinds } = constraints;
|
|
169
|
-
for (let i = 0;i < ops.length; i++) {
|
|
170
|
-
const op = ops[i];
|
|
171
|
-
if (!op)
|
|
172
|
-
continue;
|
|
173
|
-
const path = `ops[${i}]`;
|
|
174
|
-
if (!allowedOps.includes(op.op)) {
|
|
175
|
-
throw new Error(`${path}: op "${op.op}" not in allowed list [${allowedOps.join(", ")}]`);
|
|
176
|
-
}
|
|
177
|
-
switch (op.op) {
|
|
178
|
-
case "insert-node":
|
|
179
|
-
if (!allowedSlots.includes(op.slotId)) {
|
|
180
|
-
throw new Error(`${path}: slotId "${op.slotId}" not in allowed slots [${allowedSlots.join(", ")}]`);
|
|
181
|
-
}
|
|
182
|
-
if (op.node) {
|
|
183
|
-
validateSurfaceNodeAgainstKinds(op.node, allowedNodeKinds, `${path}.node`);
|
|
184
|
-
}
|
|
185
|
-
break;
|
|
186
|
-
case "move-node":
|
|
187
|
-
if (!allowedSlots.includes(op.toSlotId)) {
|
|
188
|
-
throw new Error(`${path}: toSlotId "${op.toSlotId}" not in allowed slots [${allowedSlots.join(", ")}]`);
|
|
189
|
-
}
|
|
190
|
-
break;
|
|
191
|
-
case "replace-node":
|
|
192
|
-
if (op.node) {
|
|
193
|
-
validateSurfaceNodeAgainstKinds(op.node, allowedNodeKinds, `${path}.node`);
|
|
194
|
-
}
|
|
195
|
-
break;
|
|
196
|
-
default:
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
validateSurfacePatch(ops);
|
|
201
|
-
}
|
|
202
|
-
// src/spec/validate-bundle.ts
|
|
203
|
-
var KNOWN_NODE_KIND_RENDERERS = new Set([
|
|
204
|
-
"entity-section",
|
|
205
|
-
"entity-field",
|
|
206
|
-
"action-bar",
|
|
207
|
-
"table",
|
|
208
|
-
"timeline",
|
|
209
|
-
"rich-doc",
|
|
210
|
-
"chat-thread",
|
|
211
|
-
"assistant-panel",
|
|
212
|
-
"entity-card",
|
|
213
|
-
"entity-header",
|
|
214
|
-
"entity-summary",
|
|
215
|
-
"entity-activity",
|
|
216
|
-
"entity-relations",
|
|
217
|
-
"relation-graph",
|
|
218
|
-
"custom-widget"
|
|
219
|
-
]);
|
|
220
|
-
function collectSlotIdsFromRegion(node) {
|
|
221
|
-
const ids = [];
|
|
222
|
-
if (node.type === "slot") {
|
|
223
|
-
ids.push(node.slotId);
|
|
224
|
-
}
|
|
225
|
-
if (node.type === "panel-group" || node.type === "stack") {
|
|
226
|
-
for (const child of node.children) {
|
|
227
|
-
ids.push(...collectSlotIdsFromRegion(child));
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (node.type === "tabs") {
|
|
231
|
-
for (const tab of node.tabs) {
|
|
232
|
-
ids.push(...collectSlotIdsFromRegion(tab.child));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (node.type === "floating") {
|
|
236
|
-
ids.push(node.anchorSlotId);
|
|
237
|
-
ids.push(...collectSlotIdsFromRegion(node.child));
|
|
238
|
-
}
|
|
239
|
-
return ids;
|
|
240
|
-
}
|
|
241
|
-
function validateLayoutSlots(surface) {
|
|
242
|
-
const declaredSlotIds = new Set(surface.slots.map((s) => s.slotId));
|
|
243
|
-
for (const layout of surface.layouts) {
|
|
244
|
-
const layoutSlotIds = collectSlotIdsFromRegion(layout.root);
|
|
245
|
-
for (const slotId of layoutSlotIds) {
|
|
246
|
-
if (!declaredSlotIds.has(slotId)) {
|
|
247
|
-
throw new Error(`Surface "${surface.surfaceId}" layout "${layout.layoutId}" references undeclared slot "${slotId}". Declared slots: ${[...declaredSlotIds].join(", ")}`);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
function validateBundleNodeKinds(surface) {
|
|
253
|
-
const warnings = [];
|
|
254
|
-
for (const slot of surface.slots) {
|
|
255
|
-
for (const kind of slot.accepts) {
|
|
256
|
-
if (!KNOWN_NODE_KIND_RENDERERS.has(kind)) {
|
|
257
|
-
warnings.push(`Surface "${surface.surfaceId}" slot "${slot.slotId}" accepts "${kind}" which has no dedicated renderer (generic fallback used)`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return { warnings };
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// src/spec/define-module-bundle.ts
|
|
265
|
-
function defineModuleBundle(spec) {
|
|
266
|
-
if (!spec.meta?.key || !spec.meta?.version || !spec.meta?.title) {
|
|
267
|
-
throw new Error("ModuleBundleSpec must have meta.key, meta.version, and meta.title");
|
|
268
|
-
}
|
|
269
|
-
if (!spec.routes?.length) {
|
|
270
|
-
throw new Error("ModuleBundleSpec must have at least one route");
|
|
271
|
-
}
|
|
272
|
-
if (!spec.surfaces || Object.keys(spec.surfaces).length === 0) {
|
|
273
|
-
throw new Error("ModuleBundleSpec must have at least one surface");
|
|
274
|
-
}
|
|
275
|
-
if (spec.entities) {
|
|
276
|
-
if (!spec.entities.entityTypes || typeof spec.entities.entityTypes !== "object") {
|
|
277
|
-
throw new Error("ModuleBundleSpec.entities must have entityTypes object when present");
|
|
278
|
-
}
|
|
279
|
-
if (!spec.entities.fieldKinds || typeof spec.entities.fieldKinds !== "object") {
|
|
280
|
-
throw new Error("ModuleBundleSpec.entities must have fieldKinds object when present");
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
const REQUIRED_DIMENSIONS = [
|
|
284
|
-
"guidance",
|
|
285
|
-
"density",
|
|
286
|
-
"dataDepth",
|
|
287
|
-
"control",
|
|
288
|
-
"media",
|
|
289
|
-
"pace",
|
|
290
|
-
"narrative"
|
|
291
|
-
];
|
|
292
|
-
const MIN_DESCRIPTION_LENGTH = 10;
|
|
293
|
-
for (const surface of Object.values(spec.surfaces)) {
|
|
294
|
-
if (!surface.verification?.dimensions) {
|
|
295
|
-
throw new Error(`Surface "${surface.surfaceId}" must have verification.dimensions for all 7 preference dimensions`);
|
|
296
|
-
}
|
|
297
|
-
const dims = surface.verification.dimensions;
|
|
298
|
-
for (const d of REQUIRED_DIMENSIONS) {
|
|
299
|
-
const val = dims[d];
|
|
300
|
-
if (!val || typeof val !== "string") {
|
|
301
|
-
throw new Error(`Surface "${surface.surfaceId}" verification.dimensions.${d} must be a non-empty string`);
|
|
302
|
-
}
|
|
303
|
-
const trimmed = val.trim();
|
|
304
|
-
if (trimmed.length < MIN_DESCRIPTION_LENGTH) {
|
|
305
|
-
throw new Error(`Surface "${surface.surfaceId}" verification.dimensions.${d} must be at least ${MIN_DESCRIPTION_LENGTH} characters (got ${trimmed.length})`);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
validateLayoutSlots(surface);
|
|
309
|
-
}
|
|
310
|
-
return spec;
|
|
311
|
-
}
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export { defineModuleBundle } from "./define-module-bundle";
|
|
312
3
|
export {
|
|
313
|
-
validateSurfacePatchOp,
|
|
314
|
-
validateSurfacePatch,
|
|
315
|
-
validatePatchProposal,
|
|
316
4
|
validateLayoutSlots,
|
|
317
|
-
validateBundleNodeKinds
|
|
318
|
-
|
|
319
|
-
|
|
5
|
+
validateBundleNodeKinds
|
|
6
|
+
} from "./validate-bundle";
|
|
7
|
+
export {
|
|
8
|
+
validateSurfacePatch,
|
|
9
|
+
validateSurfacePatchOp,
|
|
10
|
+
validatePatchProposal
|
|
11
|
+
} from "./validate-surface-patch";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var KNOWN_NODE_KIND_RENDERERS = new Set([
|
|
1
|
+
const KNOWN_NODE_KIND_RENDERERS = new Set([
|
|
3
2
|
"entity-section",
|
|
4
3
|
"entity-field",
|
|
5
4
|
"action-bar",
|
|
@@ -37,7 +36,7 @@ function collectSlotIdsFromRegion(node) {
|
|
|
37
36
|
}
|
|
38
37
|
return ids;
|
|
39
38
|
}
|
|
40
|
-
function validateLayoutSlots(surface) {
|
|
39
|
+
export function validateLayoutSlots(surface) {
|
|
41
40
|
const declaredSlotIds = new Set(surface.slots.map((s) => s.slotId));
|
|
42
41
|
for (const layout of surface.layouts) {
|
|
43
42
|
const layoutSlotIds = collectSlotIdsFromRegion(layout.root);
|
|
@@ -48,7 +47,7 @@ function validateLayoutSlots(surface) {
|
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
function validateBundleNodeKinds(surface) {
|
|
50
|
+
export function validateBundleNodeKinds(surface) {
|
|
52
51
|
const warnings = [];
|
|
53
52
|
for (const slot of surface.slots) {
|
|
54
53
|
for (const kind of slot.accepts) {
|
|
@@ -59,7 +58,3 @@ function validateBundleNodeKinds(surface) {
|
|
|
59
58
|
}
|
|
60
59
|
return { warnings };
|
|
61
60
|
}
|
|
62
|
-
export {
|
|
63
|
-
validateLayoutSlots,
|
|
64
|
-
validateBundleNodeKinds
|
|
65
|
-
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var VALID_OPS = [
|
|
1
|
+
const VALID_OPS = [
|
|
3
2
|
"insert-node",
|
|
4
3
|
"replace-node",
|
|
5
4
|
"remove-node",
|
|
@@ -11,7 +10,7 @@ var VALID_OPS = [
|
|
|
11
10
|
"promote-action",
|
|
12
11
|
"set-focus"
|
|
13
12
|
];
|
|
14
|
-
|
|
13
|
+
const VALID_NODE_KINDS = [
|
|
15
14
|
"metric-strip",
|
|
16
15
|
"data-view",
|
|
17
16
|
"entity-card",
|
|
@@ -54,7 +53,7 @@ function validateSurfaceNode(node, path) {
|
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
|
-
function validateSurfacePatchOp(op, index) {
|
|
56
|
+
export function validateSurfacePatchOp(op, index) {
|
|
58
57
|
const path = `ops[${index}]`;
|
|
59
58
|
if (!op || typeof op !== "object" || !("op" in op)) {
|
|
60
59
|
throw new Error(`${path}: must be an object with op field`);
|
|
@@ -139,7 +138,7 @@ function validateSurfacePatchOp(op, index) {
|
|
|
139
138
|
throw new Error(`${path}: unknown op "${opType}"`);
|
|
140
139
|
}
|
|
141
140
|
}
|
|
142
|
-
function validateSurfacePatch(ops) {
|
|
141
|
+
export function validateSurfacePatch(ops) {
|
|
143
142
|
if (!Array.isArray(ops)) {
|
|
144
143
|
throw new Error("Patch ops must be an array");
|
|
145
144
|
}
|
|
@@ -161,7 +160,7 @@ function validateSurfaceNodeAgainstKinds(node, allowedKinds, path) {
|
|
|
161
160
|
}
|
|
162
161
|
}
|
|
163
162
|
}
|
|
164
|
-
function validatePatchProposal(ops, constraints) {
|
|
163
|
+
export function validatePatchProposal(ops, constraints) {
|
|
165
164
|
if (!Array.isArray(ops)) {
|
|
166
165
|
throw new Error("Patch ops must be an array");
|
|
167
166
|
}
|
|
@@ -199,8 +198,3 @@ function validatePatchProposal(ops, constraints) {
|
|
|
199
198
|
}
|
|
200
199
|
validateSurfacePatch(ops);
|
|
201
200
|
}
|
|
202
|
-
export {
|
|
203
|
-
validateSurfacePatchOp,
|
|
204
|
-
validateSurfacePatch,
|
|
205
|
-
validatePatchProposal
|
|
206
|
-
};
|
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
// src/telemetry/surface-metrics.ts
|
|
2
|
-
import {
|
|
3
|
-
createCounter,
|
|
4
|
-
createHistogram
|
|
5
|
-
} from "@contractspec/lib.observability/metrics";
|
|
6
|
-
var METER_NAME = "@contractspec/lib.surface-runtime";
|
|
7
|
-
var resolutionDurationMs = createHistogram("bundle_surface_resolution_duration_ms", "Time to resolve bundle spec to surface plan in milliseconds", METER_NAME);
|
|
8
|
-
var patchAcceptanceCounter = createCounter("bundle_surface_patch_acceptance_total", "Total AI patch proposals accepted by user", METER_NAME);
|
|
9
|
-
var patchRejectionCounter = createCounter("bundle_surface_patch_rejection_total", "Total AI patch proposals rejected by user", METER_NAME);
|
|
10
|
-
var policyDenialCounter = createCounter("bundle_surface_policy_denial_total", "Total policy denials (actions denied by policy)", METER_NAME);
|
|
11
|
-
var surfaceFallbackCounter = createCounter("bundle_surface_fallback_total", "Total surface or layout fallbacks during resolution", METER_NAME);
|
|
12
|
-
var missingRendererCounter = createCounter("bundle_surface_renderer_missing_total", "Total slots with no renderer for requested node kind", METER_NAME);
|
|
13
1
|
export {
|
|
14
|
-
surfaceFallbackCounter,
|
|
15
2
|
resolutionDurationMs,
|
|
16
|
-
policyDenialCounter,
|
|
17
|
-
patchRejectionCounter,
|
|
18
3
|
patchAcceptanceCounter,
|
|
4
|
+
patchRejectionCounter,
|
|
5
|
+
policyDenialCounter,
|
|
6
|
+
surfaceFallbackCounter,
|
|
19
7
|
missingRendererCounter
|
|
20
|
-
};
|
|
8
|
+
} from "./surface-metrics";
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
// src/telemetry/surface-metrics.ts
|
|
2
1
|
import {
|
|
3
2
|
createCounter,
|
|
4
3
|
createHistogram
|
|
5
4
|
} from "@contractspec/lib.observability/metrics";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
surfaceFallbackCounter,
|
|
15
|
-
resolutionDurationMs,
|
|
16
|
-
policyDenialCounter,
|
|
17
|
-
patchRejectionCounter,
|
|
18
|
-
patchAcceptanceCounter,
|
|
19
|
-
missingRendererCounter
|
|
20
|
-
};
|
|
5
|
+
const METER_NAME = "@contractspec/lib.surface-runtime";
|
|
6
|
+
export const resolutionDurationMs = createHistogram("bundle_surface_resolution_duration_ms", "Time to resolve bundle spec to surface plan in milliseconds", METER_NAME);
|
|
7
|
+
export const patchAcceptanceCounter = createCounter("bundle_surface_patch_acceptance_total", "Total AI patch proposals accepted by user", METER_NAME);
|
|
8
|
+
export const patchRejectionCounter = createCounter("bundle_surface_patch_rejection_total", "Total AI patch proposals rejected by user", METER_NAME);
|
|
9
|
+
export const policyDenialCounter = createCounter("bundle_surface_policy_denial_total", "Total policy denials (actions denied by policy)", METER_NAME);
|
|
10
|
+
export const surfaceFallbackCounter = createCounter("bundle_surface_fallback_total", "Total surface or layout fallbacks during resolution", METER_NAME);
|
|
11
|
+
export const missingRendererCounter = createCounter("bundle_surface_renderer_missing_total", "Total slots with no renderer for requested node kind", METER_NAME);
|
|
@@ -1,48 +1,40 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// src/react/BundleProvider.tsx
|
|
3
|
-
import { createContext, useContext } from "react";
|
|
4
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
5
1
|
"use client";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import { jsxDEV as jsxDEV_7x81h0kn } from "react/jsx-dev-runtime";
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
const BundlePlanContext = createContext(null);
|
|
5
|
+
const PreferencesContext = createContext(null);
|
|
6
|
+
const EditingContext = createContext(false);
|
|
7
|
+
export function BundleProvider({
|
|
10
8
|
plan,
|
|
11
9
|
children,
|
|
12
10
|
isEditing = false
|
|
13
11
|
}) {
|
|
14
12
|
const preferences = plan.adaptation.appliedDimensions;
|
|
15
|
-
return /* @__PURE__ */
|
|
13
|
+
return /* @__PURE__ */ jsxDEV_7x81h0kn(BundlePlanContext.Provider, {
|
|
16
14
|
value: plan,
|
|
17
|
-
children: /* @__PURE__ */
|
|
15
|
+
children: /* @__PURE__ */ jsxDEV_7x81h0kn(PreferencesContext.Provider, {
|
|
18
16
|
value: preferences,
|
|
19
|
-
children: /* @__PURE__ */
|
|
17
|
+
children: /* @__PURE__ */ jsxDEV_7x81h0kn(EditingContext.Provider, {
|
|
20
18
|
value: isEditing,
|
|
21
19
|
children
|
|
22
20
|
}, undefined, false, undefined, this)
|
|
23
21
|
}, undefined, false, undefined, this)
|
|
24
22
|
}, undefined, false, undefined, this);
|
|
25
23
|
}
|
|
26
|
-
function useIsEditing() {
|
|
24
|
+
export function useIsEditing() {
|
|
27
25
|
return useContext(EditingContext);
|
|
28
26
|
}
|
|
29
|
-
function useBundlePlan() {
|
|
27
|
+
export function useBundlePlan() {
|
|
30
28
|
const value = useContext(BundlePlanContext);
|
|
31
29
|
if (!value) {
|
|
32
30
|
throw new Error("useBundlePlan must be used inside BundleProvider.");
|
|
33
31
|
}
|
|
34
32
|
return value;
|
|
35
33
|
}
|
|
36
|
-
function useBundlePreferences() {
|
|
34
|
+
export function useBundlePreferences() {
|
|
37
35
|
const value = useContext(PreferencesContext);
|
|
38
36
|
if (!value) {
|
|
39
37
|
throw new Error("useBundlePreferences must be used inside BundleProvider.");
|
|
40
38
|
}
|
|
41
39
|
return value;
|
|
42
40
|
}
|
|
43
|
-
export {
|
|
44
|
-
useIsEditing,
|
|
45
|
-
useBundlePreferences,
|
|
46
|
-
useBundlePlan,
|
|
47
|
-
BundleProvider
|
|
48
|
-
};
|
|
@@ -4,6 +4,8 @@ export interface BundleRendererProps {
|
|
|
4
4
|
assistantSlotId?: string;
|
|
5
5
|
/** Content for the assistant slot (e.g. ChatContainer with useChat). */
|
|
6
6
|
assistantSlotContent?: React.ReactNode;
|
|
7
|
+
/** Override content for any slot. When provided, renders this instead of SlotRenderer for the given slotId. */
|
|
8
|
+
slotContent?: Partial<Record<string, React.ReactNode>>;
|
|
7
9
|
/** Called when user accepts a patch proposal. Caller should apply patch and update plan. */
|
|
8
10
|
onPatchAccept?: (proposalId: string) => void;
|
|
9
11
|
/** Called when user rejects a patch proposal. Caller should remove from proposals and emit audit. */
|
|
@@ -19,4 +21,4 @@ export interface BundleRendererProps {
|
|
|
19
21
|
* Composes RegionRenderer (layout tree), SlotRenderer, and motion tokens from pace.
|
|
20
22
|
* When assistantSlotId is set and matches a slot, renders assistantSlotContent instead.
|
|
21
23
|
*/
|
|
22
|
-
export declare function BundleRenderer({ assistantSlotId, assistantSlotContent, onPatchAccept, onPatchReject, onOverlayConflictResolve, }?: BundleRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function BundleRenderer({ assistantSlotId, assistantSlotContent, slotContent, onPatchAccept, onPatchReject, onOverlayConflictResolve, }?: BundleRendererProps): import("react/jsx-runtime").JSX.Element;
|