@ixo/editor 3.0.0-beta.27 → 3.0.0-beta.29

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.
@@ -0,0 +1,470 @@
1
+ import {
2
+ getActionByCan
3
+ } from "./chunk-77R3T42S.mjs";
4
+
5
+ // src/core/lib/flowCompiler/blockMapping.ts
6
+ var ICON_DEFAULTS = {
7
+ "bid/submit": "gavel",
8
+ "bid/evaluate": "check-circle",
9
+ "claim/submit": "file-check",
10
+ "claim/evaluate": "clipboard-check",
11
+ "email/send": "mail",
12
+ "notification/push": "bell",
13
+ "matrix/dm": "message-circle",
14
+ "proposal/create": "scroll",
15
+ "proposal/vote": "vote",
16
+ "domain/create": "globe",
17
+ "domain/sign": "feather",
18
+ "credential/store": "shield",
19
+ "payment/execute": "credit-card",
20
+ "http/request": "cloud",
21
+ "protocol/select": "git-branch",
22
+ "human/checkbox": "check-square",
23
+ "human/form": "file-text",
24
+ "form/submit": "file-text",
25
+ "oracle/query": "cpu"
26
+ };
27
+ function compileBlockProps(cap, registryType) {
28
+ return {
29
+ title: cap.title || cap.can,
30
+ description: cap.description || "",
31
+ icon: cap.icon || ICON_DEFAULTS[cap.can] || "bolt",
32
+ actionType: registryType,
33
+ inputs: JSON.stringify(cap.nb || {}),
34
+ requiresConfirmation: "",
35
+ conditions: "",
36
+ // compiled separately by the compiler
37
+ // Authorization props
38
+ parentCapability: cap.actor?.parentCapability || "",
39
+ authorisedActors: cap.actor?.authorisedActors ? JSON.stringify(cap.actor.authorisedActors) : "",
40
+ // TTL props
41
+ ttlAbsoluteDueDate: cap.ttl?.absoluteDueDate || "",
42
+ ttlFromEnablement: cap.ttl?.fromEnablement || "",
43
+ ttlFromCommitment: cap.ttl?.fromCommitment || ""
44
+ };
45
+ }
46
+ var COMPILED_BLOCK_TYPE = "action";
47
+
48
+ // src/core/lib/flowCompiler/compiler.ts
49
+ function compileBaseUcanFlow(plan, registry) {
50
+ if (!Array.isArray(plan.capabilities)) {
51
+ throw new Error("BaseUcanFlow.capabilities must be an array");
52
+ }
53
+ const capabilities = plan.capabilities;
54
+ if (capabilities.length === 0) {
55
+ throw new Error("BaseUcanFlow has no capabilities to compile");
56
+ }
57
+ const actionMap = /* @__PURE__ */ new Map();
58
+ for (const cap of capabilities) {
59
+ const nodeId = cap.id?.trim();
60
+ if (!nodeId) {
61
+ throw new Error("Every capability in BaseUcanFlow.capabilities must include a non-empty id.");
62
+ }
63
+ if (actionMap.has(nodeId)) {
64
+ throw new Error(`Duplicate capability id "${nodeId}" in BaseUcanFlow.capabilities.`);
65
+ }
66
+ const action = registry.getActionByCan(cap.can);
67
+ if (!action) {
68
+ throw new Error(`Unknown capability "${cap.can}" for node "${nodeId}". Not found in action registry.`);
69
+ }
70
+ actionMap.set(nodeId, { action, nodeId, cap });
71
+ }
72
+ const blockIndex = {};
73
+ for (const nodeId of actionMap.keys()) {
74
+ blockIndex[nodeId] = generateBlockId(nodeId);
75
+ }
76
+ const edges = [];
77
+ for (const [nodeId, { cap }] of actionMap) {
78
+ if (!cap.dependsOn) continue;
79
+ for (const depId of cap.dependsOn) {
80
+ if (!actionMap.has(depId)) {
81
+ throw new Error(`Node "${nodeId}" depends on "${depId}" which does not exist in the plan.`);
82
+ }
83
+ edges.push({
84
+ id: `${depId}->${nodeId}`,
85
+ source: depId,
86
+ target: nodeId,
87
+ kind: "dependency",
88
+ condition: cap.condition
89
+ });
90
+ }
91
+ }
92
+ const nodeIds = Array.from(actionMap.keys());
93
+ const order = topologicalSort(nodeIds, edges);
94
+ const blocks = [];
95
+ const nodes = {};
96
+ for (const nodeId of order) {
97
+ const { action, cap } = actionMap.get(nodeId);
98
+ const blockId = blockIndex[nodeId];
99
+ const props = compileBlockProps(cap, action.type);
100
+ if (cap.condition) {
101
+ props.conditions = compileCondition(cap.condition, blockIndex);
102
+ }
103
+ if (cap.dependsOn && cap.dependsOn.length > 0) {
104
+ props.activationUpstreamNodeId = blockIndex[cap.dependsOn[0]];
105
+ props.activationRequiredStatus = "approved";
106
+ }
107
+ blocks.push({
108
+ id: blockId,
109
+ type: COMPILED_BLOCK_TYPE,
110
+ props
111
+ });
112
+ nodes[nodeId] = {
113
+ id: nodeId,
114
+ blockId,
115
+ can: cap.can,
116
+ with: cap.with,
117
+ registryType: action.type,
118
+ title: cap.title || cap.can,
119
+ description: cap.description || "",
120
+ props,
121
+ dependsOn: cap.dependsOn || [],
122
+ phase: cap.phase,
123
+ parallelGroup: cap.parallelGroup,
124
+ actor: cap.actor
125
+ };
126
+ }
127
+ return {
128
+ meta: {
129
+ flowId: plan.flowId,
130
+ title: plan.title,
131
+ goal: plan.goal,
132
+ version: plan.version,
133
+ flowOwnerDid: plan.meta?.rootIssuer || "",
134
+ flowUri: plan.meta?.flowUri,
135
+ compiledAt: (/* @__PURE__ */ new Date()).toISOString(),
136
+ compiledFrom: "BaseUcanFlow"
137
+ },
138
+ blocks,
139
+ nodes,
140
+ edges,
141
+ order,
142
+ blockIndex
143
+ };
144
+ }
145
+ function generateBlockId(nodeId) {
146
+ return `flow_block_${nodeId}`;
147
+ }
148
+ function topologicalSort(nodeIds, edges) {
149
+ const inDegree = /* @__PURE__ */ new Map();
150
+ const adjacency = /* @__PURE__ */ new Map();
151
+ for (const id of nodeIds) {
152
+ inDegree.set(id, 0);
153
+ adjacency.set(id, []);
154
+ }
155
+ for (const edge of edges) {
156
+ adjacency.get(edge.source).push(edge.target);
157
+ inDegree.set(edge.target, (inDegree.get(edge.target) || 0) + 1);
158
+ }
159
+ const queue = nodeIds.filter((id) => inDegree.get(id) === 0);
160
+ const result = [];
161
+ while (queue.length > 0) {
162
+ const node = queue.shift();
163
+ result.push(node);
164
+ for (const neighbor of adjacency.get(node) || []) {
165
+ const newDegree = (inDegree.get(neighbor) || 1) - 1;
166
+ inDegree.set(neighbor, newDegree);
167
+ if (newDegree === 0) queue.push(neighbor);
168
+ }
169
+ }
170
+ if (result.length !== nodeIds.length) {
171
+ const remaining = nodeIds.filter((id) => !result.includes(id));
172
+ throw new Error(`Cycle detected in flow dependencies. Nodes involved: ${remaining.join(", ")}`);
173
+ }
174
+ return result;
175
+ }
176
+ function compileCondition(condition, blockIndex) {
177
+ const sourceBlockId = blockIndex[condition.sourceId];
178
+ if (!sourceBlockId) {
179
+ throw new Error(`Condition references unknown source "${condition.sourceId}".`);
180
+ }
181
+ const conditionConfig = {
182
+ enabled: true,
183
+ mode: "all_must_pass",
184
+ conditions: [
185
+ {
186
+ id: `cond_${condition.sourceId}_${condition.field}`,
187
+ name: `Condition from ${condition.sourceId}`,
188
+ sourceBlockId,
189
+ sourceBlockType: COMPILED_BLOCK_TYPE,
190
+ rule: {
191
+ type: "property_value",
192
+ property: condition.field,
193
+ operator: condition.operator,
194
+ value: condition.value
195
+ },
196
+ effect: condition.effect || { action: "enable" }
197
+ }
198
+ ]
199
+ };
200
+ return JSON.stringify(conditionConfig);
201
+ }
202
+
203
+ // src/core/types/baseUcan.ts
204
+ function isRuntimeRef(value) {
205
+ return typeof value === "object" && value !== null && "$ref" in value && typeof value.$ref === "string";
206
+ }
207
+
208
+ // src/core/lib/flowCompiler/resolveRefs.ts
209
+ function resolveRuntimeRefs(nb, getNodeOutput) {
210
+ return resolveValue(nb, getNodeOutput);
211
+ }
212
+ function resolveValue(value, getNodeOutput) {
213
+ if (isRuntimeRef(value)) {
214
+ return resolveRef(value.$ref, getNodeOutput);
215
+ }
216
+ if (Array.isArray(value)) {
217
+ return value.map((item) => resolveValue(item, getNodeOutput));
218
+ }
219
+ if (typeof value === "object" && value !== null) {
220
+ const result = {};
221
+ for (const [key, val] of Object.entries(value)) {
222
+ result[key] = resolveValue(val, getNodeOutput);
223
+ }
224
+ return result;
225
+ }
226
+ return value;
227
+ }
228
+ function resolveRef(ref, getNodeOutput) {
229
+ const outputIndex = ref.indexOf(".output.");
230
+ if (outputIndex === -1) {
231
+ throw new Error(`Invalid runtime reference "${ref}". Expected format: "nodeId.output.fieldPath"`);
232
+ }
233
+ const nodeId = ref.slice(0, outputIndex);
234
+ const fieldPath = ref.slice(outputIndex + ".output.".length);
235
+ const output = getNodeOutput(nodeId);
236
+ if (!output) {
237
+ return void 0;
238
+ }
239
+ return getNestedValue(output, fieldPath);
240
+ }
241
+ function getNestedValue(obj, path) {
242
+ const parts = path.split(".");
243
+ let current = obj;
244
+ for (const part of parts) {
245
+ if (current == null || typeof current !== "object") {
246
+ return void 0;
247
+ }
248
+ current = current[part];
249
+ }
250
+ return current;
251
+ }
252
+
253
+ // src/core/lib/flowCompiler/setup.ts
254
+ import * as Y3 from "yjs";
255
+ import { MatrixProvider } from "@ixo/matrix-crdt";
256
+
257
+ // src/core/lib/flowCompiler/hydrate.ts
258
+ import * as Y from "yjs";
259
+ function hydrateYDocFromCompiledFlow(yDoc, compiled) {
260
+ yDoc.transact(() => {
261
+ const flowMeta = yDoc.getMap("qi.flow.meta");
262
+ for (const [key, value] of Object.entries(compiled.meta)) {
263
+ if (value !== void 0) {
264
+ flowMeta.set(key, value);
265
+ }
266
+ }
267
+ const flowNodes = yDoc.getMap("qi.flow.nodes");
268
+ for (const [nodeId, node] of Object.entries(compiled.nodes)) {
269
+ const yNode = new Y.Map();
270
+ yNode.set("id", node.id);
271
+ yNode.set("blockId", node.blockId);
272
+ yNode.set("can", node.can);
273
+ yNode.set("with", node.with);
274
+ yNode.set("registryType", node.registryType);
275
+ yNode.set("title", node.title);
276
+ yNode.set("description", node.description);
277
+ yNode.set("dependsOn", node.dependsOn);
278
+ if (node.phase) yNode.set("phase", node.phase);
279
+ if (node.parallelGroup) yNode.set("parallelGroup", node.parallelGroup);
280
+ if (node.actor) yNode.set("actor", node.actor);
281
+ flowNodes.set(nodeId, yNode);
282
+ }
283
+ const flowEdges = yDoc.getMap("qi.flow.edges");
284
+ for (const edge of compiled.edges) {
285
+ const yEdge = new Y.Map();
286
+ yEdge.set("id", edge.id);
287
+ yEdge.set("source", edge.source);
288
+ yEdge.set("target", edge.target);
289
+ yEdge.set("kind", edge.kind);
290
+ if (edge.condition) yEdge.set("condition", edge.condition);
291
+ flowEdges.set(edge.id, yEdge);
292
+ }
293
+ const flowOrder = yDoc.getArray("qi.flow.order");
294
+ for (const nodeId of compiled.order) {
295
+ flowOrder.push([nodeId]);
296
+ }
297
+ const flowBlockIndex = yDoc.getMap("qi.flow.blockIndex");
298
+ for (const [nodeId, blockId] of Object.entries(compiled.blockIndex)) {
299
+ flowBlockIndex.set(nodeId, blockId);
300
+ }
301
+ });
302
+ }
303
+ function initializeRuntime(runtimeMap, compiled) {
304
+ for (const nodeId of compiled.order) {
305
+ runtimeMap.set(compiled.blockIndex[nodeId], { state: "idle" });
306
+ }
307
+ }
308
+
309
+ // src/core/lib/flowCompiler/documentFragment.ts
310
+ import * as Y2 from "yjs";
311
+ function writeCompiledBlocksToFragment(fragment, blocks) {
312
+ const documentBlockGroup = getOrCreateDocumentBlockGroup(fragment);
313
+ for (const block of blocks) {
314
+ const blockContainer = new Y2.XmlElement("blockContainer");
315
+ const { backgroundColor: rawBackgroundColor, textColor: rawTextColor, ...contentProps } = block.props;
316
+ blockContainer.setAttribute("id", block.id);
317
+ blockContainer.setAttribute("textColor", rawTextColor || "default");
318
+ blockContainer.setAttribute("backgroundColor", rawBackgroundColor || "default");
319
+ const blockContent = new Y2.XmlElement(block.type);
320
+ for (const [key, value] of Object.entries(contentProps)) {
321
+ if (value !== "") {
322
+ blockContent.setAttribute(key, value);
323
+ }
324
+ }
325
+ blockContainer.insert(0, [blockContent]);
326
+ documentBlockGroup.insert(documentBlockGroup.length, [blockContainer]);
327
+ }
328
+ }
329
+ function getOrCreateDocumentBlockGroup(fragment) {
330
+ if (fragment.length === 0) {
331
+ const blockGroup = new Y2.XmlElement("blockGroup");
332
+ fragment.insert(0, [blockGroup]);
333
+ return blockGroup;
334
+ }
335
+ if (fragment.length === 1) {
336
+ const rootNode = fragment.get(0);
337
+ if (rootNode instanceof Y2.XmlElement && rootNode.nodeName === "blockGroup") {
338
+ return rootNode;
339
+ }
340
+ }
341
+ throw new Error("Unexpected BlockNote document shape in XmlFragment. Expected a single top-level blockGroup node.");
342
+ }
343
+
344
+ // src/core/lib/flowCompiler/setup.ts
345
+ async function setupFlowFromBaseUcan(options) {
346
+ const { plan, roomId, matrixClient, creatorDid, docId } = options;
347
+ const compiled = compileBaseUcanFlow(plan, { getActionByCan });
348
+ const yDoc = new Y3.Doc();
349
+ const client = matrixClient;
350
+ client.canSupportVoip = false;
351
+ client.clientOpts = { lazyLoadMembers: true };
352
+ const provider = new MatrixProvider(
353
+ yDoc,
354
+ client,
355
+ { type: "id", id: roomId },
356
+ {
357
+ translator: {
358
+ updateEventType: "matrix-crdt.doc_update",
359
+ snapshotEventType: "matrix-crdt.doc_snapshot"
360
+ },
361
+ enableExperimentalWebrtcSync: false,
362
+ // no need for setup
363
+ enableAwareness: false,
364
+ // no need for setup
365
+ reader: { snapshotInterval: 10 },
366
+ writer: { flushInterval: 300, retryIfForbiddenInterval: 3e4 }
367
+ }
368
+ );
369
+ await new Promise((resolve, reject) => {
370
+ const timeout = setTimeout(() => {
371
+ reject(new Error(`Timed out connecting to room ${roomId}`));
372
+ }, 3e4);
373
+ provider.onDocumentAvailable(() => {
374
+ clearTimeout(timeout);
375
+ resolve();
376
+ });
377
+ provider.onDocumentUnavailable(() => {
378
+ clearTimeout(timeout);
379
+ reject(new Error(`Room ${roomId} is unavailable`));
380
+ });
381
+ provider.initialize().catch((err) => {
382
+ clearTimeout(timeout);
383
+ reject(err);
384
+ });
385
+ });
386
+ try {
387
+ const root = yDoc.getMap("root");
388
+ const fragment = yDoc.getXmlFragment("document");
389
+ if (hasFlowBlocks(fragment)) {
390
+ throw new Error(`Room ${roomId} already contains flow blocks. Use a new room or clear the existing one first.`);
391
+ }
392
+ yDoc.transact(() => {
393
+ if (!root.get("@context")) root.set("@context", "https://ixo.world/flow/0.3");
394
+ if (!root.get("_type")) root.set("_type", "ixo.flow.crdt");
395
+ if (!root.get("schema_version")) root.set("schema_version", "0.3");
396
+ if (!root.get("doc_id")) root.set("doc_id", docId || plan.flowId);
397
+ if (!root.get("createdAt")) root.set("createdAt", (/* @__PURE__ */ new Date()).toISOString());
398
+ if (!root.get("createdBy")) root.set("createdBy", creatorDid);
399
+ root.set("flowOwnerDid", creatorDid);
400
+ const titleText = yDoc.getText("title");
401
+ if (titleText.length === 0 && plan.title) {
402
+ titleText.insert(0, plan.title);
403
+ }
404
+ });
405
+ hydrateYDocFromCompiledFlow(yDoc, compiled);
406
+ const runtimeMap = yDoc.getMap("runtime");
407
+ initializeRuntime(runtimeMap, compiled);
408
+ yDoc.transact(() => {
409
+ writeCompiledBlocksToFragment(fragment, compiled.blocks);
410
+ });
411
+ await provider.waitForFlush();
412
+ } finally {
413
+ provider.dispose();
414
+ yDoc.destroy();
415
+ }
416
+ return {
417
+ compiled,
418
+ roomId,
419
+ flowId: plan.flowId
420
+ };
421
+ }
422
+ var FLOW_BLOCK_TYPES = /* @__PURE__ */ new Set([
423
+ "checkbox",
424
+ "list",
425
+ "enumChecklist",
426
+ "overview",
427
+ "proposal",
428
+ "apiRequest",
429
+ "notify",
430
+ "claim",
431
+ "evaluator",
432
+ "domainCreator",
433
+ "email",
434
+ "visualization",
435
+ "dynamicList",
436
+ "protocolSelector",
437
+ "form",
438
+ "domainCreatorSign",
439
+ "domainCardViewer",
440
+ "governanceGroup",
441
+ "flowLink",
442
+ "action",
443
+ "location",
444
+ "embed"
445
+ ]);
446
+ function hasFlowBlocks(fragment) {
447
+ for (let i = 0; i < fragment.length; i++) {
448
+ const blockGroup = fragment.get(i);
449
+ if (!(blockGroup instanceof Y3.XmlElement)) continue;
450
+ for (let j = 0; j < blockGroup.length; j++) {
451
+ const blockContainer = blockGroup.get(j);
452
+ if (!(blockContainer instanceof Y3.XmlElement)) continue;
453
+ for (let k = 0; k < blockContainer.length; k++) {
454
+ const blockContent = blockContainer.get(k);
455
+ if (blockContent instanceof Y3.XmlElement && FLOW_BLOCK_TYPES.has(blockContent.nodeName)) {
456
+ return true;
457
+ }
458
+ }
459
+ }
460
+ }
461
+ return false;
462
+ }
463
+
464
+ export {
465
+ compileBaseUcanFlow,
466
+ isRuntimeRef,
467
+ resolveRuntimeRefs,
468
+ setupFlowFromBaseUcan
469
+ };
470
+ //# sourceMappingURL=chunk-5PHI3WWK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/lib/flowCompiler/blockMapping.ts","../src/core/lib/flowCompiler/compiler.ts","../src/core/types/baseUcan.ts","../src/core/lib/flowCompiler/resolveRefs.ts","../src/core/lib/flowCompiler/setup.ts","../src/core/lib/flowCompiler/hydrate.ts","../src/core/lib/flowCompiler/documentFragment.ts"],"sourcesContent":["import type { FlowCapability } from '../../types/baseUcan';\n\n/** Default icon per `can` statement. */\nconst ICON_DEFAULTS: Record<string, string> = {\n 'bid/submit': 'gavel',\n 'bid/evaluate': 'check-circle',\n 'claim/submit': 'file-check',\n 'claim/evaluate': 'clipboard-check',\n 'email/send': 'mail',\n 'notification/push': 'bell',\n 'matrix/dm': 'message-circle',\n 'proposal/create': 'scroll',\n 'proposal/vote': 'vote',\n 'domain/create': 'globe',\n 'domain/sign': 'feather',\n 'credential/store': 'shield',\n 'payment/execute': 'credit-card',\n 'http/request': 'cloud',\n 'protocol/select': 'git-branch',\n 'human/checkbox': 'check-square',\n 'human/form': 'file-text',\n 'form/submit': 'file-text',\n 'oracle/query': 'cpu',\n};\n\n/**\n * Compile a FlowCapability into block props for the `action` block type.\n *\n * All capabilities map to the `action` block type — the `actionType` prop\n * routes to the correct registry action at runtime. This is consistent with\n * how the slash menu creates action blocks today.\n *\n * All returned values are strings per BlockNote convention.\n */\nexport function compileBlockProps(cap: FlowCapability, registryType: string): Record<string, string> {\n return {\n title: cap.title || cap.can,\n description: cap.description || '',\n icon: cap.icon || ICON_DEFAULTS[cap.can] || 'bolt',\n actionType: registryType,\n inputs: JSON.stringify(cap.nb || {}),\n requiresConfirmation: '',\n conditions: '', // compiled separately by the compiler\n // Authorization props\n parentCapability: cap.actor?.parentCapability || '',\n authorisedActors: cap.actor?.authorisedActors ? JSON.stringify(cap.actor.authorisedActors) : '',\n // TTL props\n ttlAbsoluteDueDate: cap.ttl?.absoluteDueDate || '',\n ttlFromEnablement: cap.ttl?.fromEnablement || '',\n ttlFromCommitment: cap.ttl?.fromCommitment || '',\n };\n}\n\n/** The BlockNote block type that all capabilities compile to. */\nexport const COMPILED_BLOCK_TYPE = 'action' as const;\n\n/** Get the default icon for a `can` statement. */\nexport function getDefaultIcon(can: string): string {\n return ICON_DEFAULTS[can] || 'bolt';\n}\n","import type { BaseUcanFlow, FlowCapability, CompiledFlow, CompiledBlock, CompiledEdge, CompiledFlowNode, ConditionRef } from '../../types/baseUcan';\nimport type { ActionDefinition } from '../actionRegistry/types';\nimport { compileBlockProps, COMPILED_BLOCK_TYPE } from './blockMapping';\n\n// ─── Public API ─────────────────────────────────────────────────────────────\n\n/** Registry interface expected by the compiler (keeps it pure / testable). */\nexport interface CompilerRegistry {\n getActionByCan(can: string): ActionDefinition | undefined;\n}\n\n/**\n * Compile a Base UCAN flow plan into blocks, graph state, and metadata.\n *\n * This is a **pure function** — no React, no Yjs, no side effects.\n * The output is consumed by `hydrateFlowFromPlan()`.\n */\nexport function compileBaseUcanFlow(plan: BaseUcanFlow, registry: CompilerRegistry): CompiledFlow {\n if (!Array.isArray(plan.capabilities)) {\n throw new Error('BaseUcanFlow.capabilities must be an array');\n }\n\n const capabilities = plan.capabilities;\n if (capabilities.length === 0) {\n throw new Error('BaseUcanFlow has no capabilities to compile');\n }\n\n // 1. Validate every `can` against the registry\n const actionMap = new Map<string, { action: ActionDefinition; nodeId: string; cap: FlowCapability }>();\n for (const cap of capabilities) {\n const nodeId = cap.id?.trim();\n if (!nodeId) {\n throw new Error('Every capability in BaseUcanFlow.capabilities must include a non-empty id.');\n }\n if (actionMap.has(nodeId)) {\n throw new Error(`Duplicate capability id \"${nodeId}\" in BaseUcanFlow.capabilities.`);\n }\n\n const action = registry.getActionByCan(cap.can);\n if (!action) {\n throw new Error(`Unknown capability \"${cap.can}\" for node \"${nodeId}\". Not found in action registry.`);\n }\n actionMap.set(nodeId, { action, nodeId, cap });\n }\n\n // 2. Pre-generate deterministic block IDs (stable for testing)\n const blockIndex: Record<string, string> = {};\n for (const nodeId of actionMap.keys()) {\n blockIndex[nodeId] = generateBlockId(nodeId);\n }\n\n // 3. Build edges from dependsOn\n const edges: CompiledEdge[] = [];\n for (const [nodeId, { cap }] of actionMap) {\n if (!cap.dependsOn) continue;\n for (const depId of cap.dependsOn) {\n if (!actionMap.has(depId)) {\n throw new Error(`Node \"${nodeId}\" depends on \"${depId}\" which does not exist in the plan.`);\n }\n edges.push({\n id: `${depId}->${nodeId}`,\n source: depId,\n target: nodeId,\n kind: 'dependency',\n condition: cap.condition,\n });\n }\n }\n\n // 4. Topological sort\n const nodeIds = Array.from(actionMap.keys());\n const order = topologicalSort(nodeIds, edges);\n\n // 5. Compile each block (in topological order)\n const blocks: CompiledBlock[] = [];\n const nodes: Record<string, CompiledFlowNode> = {};\n\n for (const nodeId of order) {\n const { action, cap } = actionMap.get(nodeId)!;\n const blockId = blockIndex[nodeId];\n\n // Compile base props from the capability\n const props = compileBlockProps(cap, action.type);\n\n // Compile conditions into the block's conditions prop\n if (cap.condition) {\n props.conditions = compileCondition(cap.condition, blockIndex);\n }\n\n // Compile activation condition from first dependency\n if (cap.dependsOn && cap.dependsOn.length > 0) {\n props.activationUpstreamNodeId = blockIndex[cap.dependsOn[0]];\n props.activationRequiredStatus = 'approved';\n }\n\n blocks.push({\n id: blockId,\n type: COMPILED_BLOCK_TYPE,\n props,\n });\n\n nodes[nodeId] = {\n id: nodeId,\n blockId,\n can: cap.can,\n with: cap.with,\n registryType: action.type,\n title: cap.title || cap.can,\n description: cap.description || '',\n props,\n dependsOn: cap.dependsOn || [],\n phase: cap.phase,\n parallelGroup: cap.parallelGroup,\n actor: cap.actor,\n };\n }\n\n return {\n meta: {\n flowId: plan.flowId,\n title: plan.title,\n goal: plan.goal,\n version: plan.version,\n flowOwnerDid: plan.meta?.rootIssuer || '',\n flowUri: plan.meta?.flowUri,\n compiledAt: new Date().toISOString(),\n compiledFrom: 'BaseUcanFlow',\n },\n blocks,\n nodes,\n edges,\n order,\n blockIndex,\n };\n}\n\n// ─── Internal Helpers ───────────────────────────────────────────────────────\n\n/** Generate a deterministic block ID from a node ID. */\nfunction generateBlockId(nodeId: string): string {\n // Use a prefix to clearly identify compiler-generated blocks\n return `flow_block_${nodeId}`;\n}\n\n/**\n * Topological sort using Kahn's algorithm.\n * Throws on cycles.\n */\nfunction topologicalSort(nodeIds: string[], edges: CompiledEdge[]): string[] {\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>();\n\n for (const id of nodeIds) {\n inDegree.set(id, 0);\n adjacency.set(id, []);\n }\n\n for (const edge of edges) {\n adjacency.get(edge.source)!.push(edge.target);\n inDegree.set(edge.target, (inDegree.get(edge.target) || 0) + 1);\n }\n\n const queue = nodeIds.filter((id) => inDegree.get(id) === 0);\n const result: string[] = [];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n result.push(node);\n for (const neighbor of adjacency.get(node) || []) {\n const newDegree = (inDegree.get(neighbor) || 1) - 1;\n inDegree.set(neighbor, newDegree);\n if (newDegree === 0) queue.push(neighbor);\n }\n }\n\n if (result.length !== nodeIds.length) {\n const remaining = nodeIds.filter((id) => !result.includes(id));\n throw new Error(`Cycle detected in flow dependencies. Nodes involved: ${remaining.join(', ')}`);\n }\n\n return result;\n}\n\n/**\n * Compile a ConditionRef into the JSON string format expected by block conditions.\n * Matches the shape used by the existing block conditions system.\n */\nfunction compileCondition(condition: ConditionRef, blockIndex: Record<string, string>): string {\n const sourceBlockId = blockIndex[condition.sourceId];\n if (!sourceBlockId) {\n throw new Error(`Condition references unknown source \"${condition.sourceId}\".`);\n }\n\n const conditionConfig = {\n enabled: true,\n mode: 'all_must_pass',\n conditions: [\n {\n id: `cond_${condition.sourceId}_${condition.field}`,\n name: `Condition from ${condition.sourceId}`,\n sourceBlockId,\n sourceBlockType: COMPILED_BLOCK_TYPE,\n rule: {\n type: 'property_value',\n property: condition.field,\n operator: condition.operator,\n value: condition.value,\n },\n effect: condition.effect || { action: 'enable' },\n },\n ],\n };\n\n return JSON.stringify(conditionConfig);\n}\n","// ─── Base UCAN Flow Plan ────────────────────────────────────────────────────\n// A structured, capability-shaped planning document that borrows UCAN semantics.\n// The AI generates this plan; the compiler turns it into blocks + graph + Yjs state.\n\n/** Condition that gates when a capability activates. */\nexport interface ConditionRef {\n /** ID of the upstream capability whose output is checked. */\n sourceId: string;\n /** Output field path to inspect, e.g., \"decision\". */\n field: string;\n /** Comparison operator. */\n operator: 'eq' | 'neq' | 'gt' | 'lt' | 'in' | 'exists';\n /** Value to compare against (omit for 'exists'). */\n value?: unknown;\n /** What happens when the condition is (not) met. */\n effect?: {\n action: 'enable' | 'disable' | 'hide' | 'show';\n message?: string;\n };\n}\n\n/** Authorization constraint for a capability. */\nexport interface ActorConstraint {\n /** Whitelisted actor DIDs. */\n authorisedActors?: string[];\n /** Parent capability URI for delegation chain. */\n parentCapability?: string;\n}\n\n/** Time-to-live constraint for a capability. */\nexport interface TTLConstraint {\n /** Hard deadline (ISO 8601 date string). */\n absoluteDueDate?: string;\n /** Duration from when the block becomes enabled (ISO 8601 duration, e.g., \"P7D\"). */\n fromEnablement?: string;\n /** Duration from when an actor commits (ISO 8601 duration, e.g., \"PT2H\"). */\n fromCommitment?: string;\n}\n\n/**\n * A single capability in a Base UCAN flow plan.\n *\n * UCAN semantics:\n * can = the action\n * with = the resource or scope\n * nb = typed caveats, inputs, parameters\n *\n * Workflow semantics (kept separate from nb):\n * dependsOn, condition, parallelGroup, phase\n */\nexport interface FlowCapability {\n /** Stable node identifier for this step. */\n id: string;\n /** UCAN-style ability string, e.g., \"bid/submit\", \"email/send\". */\n can: string;\n /** Resource URI, e.g., \"ixo:flow:{flowId}\" or \"ixo:flow:{flowId}:{nodeId}\". */\n with: string;\n /** Typed caveats / input parameters. Shape is dictated by the action registry. */\n nb?: Record<string, unknown>;\n\n // ── Workflow topology ──\n /** IDs of upstream capabilities this depends on. */\n dependsOn?: string[];\n /** Condition that must be met for this capability to activate. */\n condition?: ConditionRef;\n /** Capabilities sharing a parallelGroup run concurrently. */\n parallelGroup?: string;\n /** Semantic grouping for layout lanes. */\n phase?: string;\n\n // ── Authorization ──\n /** Who can execute this step. */\n actor?: ActorConstraint;\n\n // ── TTL ──\n /** Time-to-live constraints. */\n ttl?: TTLConstraint;\n\n // ── Human-facing metadata ──\n /** Display title (falls back to can statement). */\n title?: string;\n /** Description of what this step does. */\n description?: string;\n /** Icon identifier. */\n icon?: string;\n}\n\n/**\n * The Base UCAN flow plan — the intermediate representation between\n * user intent and the compiled flow graph.\n *\n * capabilities is an ordered list. Each capability carries its own stable `id`.\n */\nexport interface BaseUcanFlow {\n kind: 'qi.flow.base-ucan';\n version: '1.0';\n flowId: string;\n title: string;\n goal?: string;\n meta?: {\n entityDid?: string;\n flowUri?: string;\n rootIssuer?: string;\n };\n /** Ordered capabilities, each with its own stable node ID. */\n capabilities: FlowCapability[];\n}\n\n// ─── Runtime References ─────────────────────────────────────────────────────\n// Used in nb values to reference outputs from upstream capabilities.\n// Resolved at execution time, serialized as-is at compile time.\n\n/** A reference to an upstream node's output field. Format: \"nodeId.output.fieldPath\" */\nexport interface RuntimeRef {\n $ref: string;\n}\n\nexport function isRuntimeRef(value: unknown): value is RuntimeRef {\n return typeof value === 'object' && value !== null && '$ref' in value && typeof (value as Record<string, unknown>).$ref === 'string';\n}\n\n// ─── Compiled Flow Output ───────────────────────────────────────────────────\n// Produced by the compiler, consumed by hydration.\n\n/** A single block ready for insertion into BlockNote. */\nexport interface CompiledBlock {\n /** Pre-generated stable block ID. */\n id: string;\n /** BlockNote block type (e.g., \"action\"). */\n type: string;\n /** Block props — all values are strings per BlockNote convention. */\n props: Record<string, string>;\n}\n\n/** A dependency edge in the flow graph. */\nexport interface CompiledEdge {\n id: string;\n source: string;\n target: string;\n kind: 'dependency';\n condition?: ConditionRef;\n}\n\n/** A compiled flow node stored in qi.flow.nodes. */\nexport interface CompiledFlowNode {\n id: string;\n blockId: string;\n can: string;\n with: string;\n registryType: string;\n title: string;\n description: string;\n props: Record<string, string>;\n dependsOn: string[];\n phase?: string;\n parallelGroup?: string;\n actor?: ActorConstraint;\n}\n\n/** The complete compiled output from the Base UCAN compiler. */\nexport interface CompiledFlow {\n /** Flow metadata for qi.flow.meta and Y.Map('root'). */\n meta: {\n flowId: string;\n title: string;\n goal?: string;\n version: string;\n flowOwnerDid: string;\n flowUri?: string;\n compiledAt: string;\n compiledFrom: 'BaseUcanFlow';\n };\n /** Blocks to insert into BlockNote, in topological order. */\n blocks: CompiledBlock[];\n /** Flow graph nodes, keyed by node ID. */\n nodes: Record<string, CompiledFlowNode>;\n /** Dependency edges. */\n edges: CompiledEdge[];\n /** Topological order of node IDs. */\n order: string[];\n /** nodeId → blockId mapping. */\n blockIndex: Record<string, string>;\n}\n","import { isRuntimeRef } from '../../types/baseUcan';\n\n/**\n * Resolve runtime references in an nb (caveats) object.\n *\n * At compile time, `{ \"$ref\": \"nodeId.output.fieldPath\" }` values are serialized\n * as-is into the block's `inputs` JSON string. At execution time, this function\n * replaces them with actual output values from upstream nodes.\n *\n * @param nb - The caveats object (may contain nested RuntimeRef values)\n * @param getNodeOutput - Lookup function for upstream node outputs\n * @returns A new object with all $ref values resolved\n */\nexport function resolveRuntimeRefs(nb: Record<string, unknown>, getNodeOutput: (nodeId: string) => Record<string, unknown> | undefined): Record<string, unknown> {\n return resolveValue(nb, getNodeOutput) as Record<string, unknown>;\n}\n\nfunction resolveValue(value: unknown, getNodeOutput: (nodeId: string) => Record<string, unknown> | undefined): unknown {\n if (isRuntimeRef(value)) {\n return resolveRef(value.$ref, getNodeOutput);\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => resolveValue(item, getNodeOutput));\n }\n\n if (typeof value === 'object' && value !== null) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = resolveValue(val, getNodeOutput);\n }\n return result;\n }\n\n return value;\n}\n\n/**\n * Resolve a single $ref string.\n * Format: \"nodeId.output.fieldPath\" where fieldPath supports dot notation.\n */\nfunction resolveRef(ref: string, getNodeOutput: (nodeId: string) => Record<string, unknown> | undefined): unknown {\n // Parse \"nodeId.output.fieldPath\"\n const outputIndex = ref.indexOf('.output.');\n if (outputIndex === -1) {\n throw new Error(`Invalid runtime reference \"${ref}\". Expected format: \"nodeId.output.fieldPath\"`);\n }\n\n const nodeId = ref.slice(0, outputIndex);\n const fieldPath = ref.slice(outputIndex + '.output.'.length);\n\n const output = getNodeOutput(nodeId);\n if (!output) {\n return undefined;\n }\n\n // Traverse the field path (supports dot notation)\n return getNestedValue(output, fieldPath);\n}\n\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current == null || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n","import * as Y from 'yjs';\nimport { MatrixProvider } from '@ixo/matrix-crdt';\nimport type { MatrixClient } from 'matrix-js-sdk';\nimport type { BaseUcanFlow, CompiledFlow } from '../../types/baseUcan';\nimport { compileBaseUcanFlow } from './compiler';\nimport { hydrateYDocFromCompiledFlow, initializeRuntime } from './hydrate';\nimport { getActionByCan } from '../actionRegistry';\nimport { writeCompiledBlocksToFragment } from './documentFragment';\n\nexport interface SetupFlowOptions {\n /** The Base UCAN flow plan to compile. */\n plan: BaseUcanFlow;\n /** Matrix room ID to hydrate the flow into. */\n roomId: string;\n /** Authenticated Matrix client. */\n matrixClient: MatrixClient;\n /** DID of the user setting up the flow. */\n creatorDid: string;\n /** Optional doc ID override (defaults to plan.flowId). */\n docId?: string;\n}\n\nexport interface SetupFlowResult {\n /** The compiled flow artifacts. */\n compiled: CompiledFlow;\n /** The room ID (same as input, for convenience). */\n roomId: string;\n /** The flow ID from the plan. */\n flowId: string;\n}\n\n/**\n * One-shot function that compiles a Base UCAN flow plan and writes it\n * into a Matrix room's Y.Doc. After this completes, the room is a\n * normal flow that anyone can open via `useCreateCollaborativeIxoEditor`.\n *\n * Usage:\n * ```ts\n * const result = await setupFlowFromBaseUcan({\n * plan: myBaseUcanFlow,\n * roomId: '!abc:matrix.org',\n * matrixClient,\n * creatorDid: 'did:ixo:abc123',\n * });\n *\n * // Now open the flow through normal channels:\n * // useCreateCollaborativeIxoEditor({ roomId: result.roomId, ... })\n * ```\n */\nexport async function setupFlowFromBaseUcan(options: SetupFlowOptions): Promise<SetupFlowResult> {\n const { plan, roomId, matrixClient, creatorDid, docId } = options;\n\n // 1. Compile the plan (pure, synchronous)\n const compiled = compileBaseUcanFlow(plan, { getActionByCan });\n\n // 2. Create a temporary Y.Doc\n const yDoc = new Y.Doc();\n\n // 3. Connect to the Matrix room\n const client = matrixClient;\n (client as any).canSupportVoip = false;\n (client as any).clientOpts = { lazyLoadMembers: true };\n\n const provider = new MatrixProvider(\n yDoc,\n client,\n { type: 'id', id: roomId },\n {\n translator: {\n updateEventType: 'matrix-crdt.doc_update',\n snapshotEventType: 'matrix-crdt.doc_snapshot',\n },\n enableExperimentalWebrtcSync: false, // no need for setup\n enableAwareness: false, // no need for setup\n reader: { snapshotInterval: 10 },\n writer: { flushInterval: 300, retryIfForbiddenInterval: 30000 },\n }\n );\n\n // Wait for the provider to connect and sync\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Timed out connecting to room ${roomId}`));\n }, 30000);\n\n provider.onDocumentAvailable(() => {\n clearTimeout(timeout);\n resolve();\n });\n\n provider.onDocumentUnavailable(() => {\n clearTimeout(timeout);\n reject(new Error(`Room ${roomId} is unavailable`));\n });\n\n provider.initialize().catch((err: Error) => {\n clearTimeout(timeout);\n reject(err);\n });\n });\n\n try {\n // 4. Check if the doc already has flow blocks (don't overwrite)\n const root = yDoc.getMap('root');\n const fragment = yDoc.getXmlFragment('document');\n if (hasFlowBlocks(fragment)) {\n throw new Error(`Room ${roomId} already contains flow blocks. ` + `Use a new room or clear the existing one first.`);\n }\n\n // 5. Set metadata (additive — don't overwrite what the editor already set)\n yDoc.transact(() => {\n if (!root.get('@context')) root.set('@context', 'https://ixo.world/flow/0.3');\n if (!root.get('_type')) root.set('_type', 'ixo.flow.crdt');\n if (!root.get('schema_version')) root.set('schema_version', '0.3');\n if (!root.get('doc_id')) root.set('doc_id', docId || plan.flowId);\n if (!root.get('createdAt')) root.set('createdAt', new Date().toISOString());\n if (!root.get('createdBy')) root.set('createdBy', creatorDid);\n root.set('flowOwnerDid', creatorDid);\n\n // Title — only set if empty\n const titleText = yDoc.getText('title');\n if (titleText.length === 0 && plan.title) {\n titleText.insert(0, plan.title);\n }\n });\n\n // 6. Hydrate graph state into qi.flow.* maps\n hydrateYDocFromCompiledFlow(yDoc, compiled);\n\n // 7. Initialize runtime\n const runtimeMap = yDoc.getMap('runtime');\n initializeRuntime(runtimeMap, compiled);\n\n // 8. Write blocks into the document fragment.\n // BlockNote uses an XmlFragment named 'document' whose ProseMirror\n // document shape is:\n // doc > blockGroup > blockContainer > <block type>\n // Important: the collaborative Yjs tree stores ProseMirror node names\n // and attrs directly. The DOM-only `data-*` attributes are added later\n // by BlockNote when rendering node views.\n yDoc.transact(() => {\n writeCompiledBlocksToFragment(fragment, compiled.blocks);\n });\n\n // 9. Wait for the provider to flush all writes to Matrix\n await provider.waitForFlush();\n } finally {\n // 10. Disconnect — room is now a self-contained flow\n provider.dispose();\n yDoc.destroy();\n }\n\n return {\n compiled,\n roomId,\n flowId: plan.flowId,\n };\n}\n\n// ─── Internal Helpers ─────────────────────────────────────────────────────\n\n/** Custom block types that constitute \"flow blocks\" (not default BlockNote blocks). */\nconst FLOW_BLOCK_TYPES = new Set([\n 'checkbox',\n 'list',\n 'enumChecklist',\n 'overview',\n 'proposal',\n 'apiRequest',\n 'notify',\n 'claim',\n 'evaluator',\n 'domainCreator',\n 'email',\n 'visualization',\n 'dynamicList',\n 'protocolSelector',\n 'form',\n 'domainCreatorSign',\n 'domainCardViewer',\n 'governanceGroup',\n 'flowLink',\n 'action',\n 'location',\n 'embed',\n]);\n\n/**\n * Walk the XmlFragment and check if any block content element is a flow block type.\n * Structure: fragment > blockGroup > blockContainer > <block type>.\n */\nfunction hasFlowBlocks(fragment: Y.XmlFragment): boolean {\n for (let i = 0; i < fragment.length; i++) {\n const blockGroup = fragment.get(i);\n if (!(blockGroup instanceof Y.XmlElement)) continue;\n\n for (let j = 0; j < blockGroup.length; j++) {\n const blockContainer = blockGroup.get(j);\n if (!(blockContainer instanceof Y.XmlElement)) continue;\n\n for (let k = 0; k < blockContainer.length; k++) {\n const blockContent = blockContainer.get(k);\n if (blockContent instanceof Y.XmlElement && FLOW_BLOCK_TYPES.has(blockContent.nodeName)) {\n return true;\n }\n }\n }\n }\n return false;\n}\n","import type { Map as YMap, Doc as YDoc } from 'yjs';\nimport * as Y from 'yjs';\nimport type { CompiledFlow } from '../../types/baseUcan';\n\n/**\n * Insert compiled flow artifacts into a live collaborative editor's Y.Doc.\n *\n * This function:\n * 1. Populates qi.flow.* Yjs maps with graph state\n * 2. Returns the compiled blocks for insertion into BlockNote\n *\n * Should be called ONCE when the editor connects to an empty document.\n *\n * Note: Block insertion into BlockNote must be done by the caller via\n * `editor.insertBlocks()` because BlockNote's API is not accessible here\n * without pulling in React dependencies.\n */\nexport function hydrateYDocFromCompiledFlow(yDoc: YDoc, compiled: CompiledFlow): void {\n yDoc.transact(() => {\n // ── qi.flow.meta ──\n const flowMeta = yDoc.getMap('qi.flow.meta');\n for (const [key, value] of Object.entries(compiled.meta)) {\n if (value !== undefined) {\n flowMeta.set(key, value);\n }\n }\n\n // ── qi.flow.nodes ──\n const flowNodes = yDoc.getMap('qi.flow.nodes');\n for (const [nodeId, node] of Object.entries(compiled.nodes)) {\n const yNode = new Y.Map();\n yNode.set('id', node.id);\n yNode.set('blockId', node.blockId);\n yNode.set('can', node.can);\n yNode.set('with', node.with);\n yNode.set('registryType', node.registryType);\n yNode.set('title', node.title);\n yNode.set('description', node.description);\n yNode.set('dependsOn', node.dependsOn);\n if (node.phase) yNode.set('phase', node.phase);\n if (node.parallelGroup) yNode.set('parallelGroup', node.parallelGroup);\n if (node.actor) yNode.set('actor', node.actor);\n flowNodes.set(nodeId, yNode);\n }\n\n // ── qi.flow.edges ──\n const flowEdges = yDoc.getMap('qi.flow.edges');\n for (const edge of compiled.edges) {\n const yEdge = new Y.Map();\n yEdge.set('id', edge.id);\n yEdge.set('source', edge.source);\n yEdge.set('target', edge.target);\n yEdge.set('kind', edge.kind);\n if (edge.condition) yEdge.set('condition', edge.condition);\n flowEdges.set(edge.id, yEdge);\n }\n\n // ── qi.flow.order ──\n const flowOrder = yDoc.getArray('qi.flow.order');\n for (const nodeId of compiled.order) {\n flowOrder.push([nodeId]);\n }\n\n // ── qi.flow.blockIndex ──\n const flowBlockIndex = yDoc.getMap('qi.flow.blockIndex');\n for (const [nodeId, blockId] of Object.entries(compiled.blockIndex)) {\n flowBlockIndex.set(nodeId, blockId);\n }\n });\n}\n\n/**\n * Initialize runtime state for all compiled nodes.\n * Sets each node to 'idle' state in the runtime Y.Map.\n */\nexport function initializeRuntime(runtimeMap: YMap<unknown>, compiled: CompiledFlow): void {\n for (const nodeId of compiled.order) {\n runtimeMap.set(compiled.blockIndex[nodeId], { state: 'idle' });\n }\n}\n","import * as Y from 'yjs';\nimport type { CompiledBlock } from '../../types/baseUcan';\n\n/**\n * Writes compiled blocks into BlockNote's collaborative XmlFragment using the\n * ProseMirror/Yjs structure that BlockNote reads from collaboration.\n */\nexport function writeCompiledBlocksToFragment(fragment: Y.XmlFragment, blocks: CompiledBlock[]): void {\n const documentBlockGroup = getOrCreateDocumentBlockGroup(fragment);\n\n for (const block of blocks) {\n const blockContainer = new Y.XmlElement('blockContainer');\n const { backgroundColor: rawBackgroundColor, textColor: rawTextColor, ...contentProps } = block.props;\n\n blockContainer.setAttribute('id', block.id);\n blockContainer.setAttribute('textColor', rawTextColor || 'default');\n blockContainer.setAttribute('backgroundColor', rawBackgroundColor || 'default');\n\n const blockContent = new Y.XmlElement(block.type);\n for (const [key, value] of Object.entries(contentProps)) {\n if (value !== '') {\n blockContent.setAttribute(key, value);\n }\n }\n\n blockContainer.insert(0, [blockContent]);\n documentBlockGroup.insert(documentBlockGroup.length, [blockContainer]);\n }\n}\n\nfunction getOrCreateDocumentBlockGroup(fragment: Y.XmlFragment): Y.XmlElement {\n if (fragment.length === 0) {\n const blockGroup = new Y.XmlElement('blockGroup');\n fragment.insert(0, [blockGroup]);\n return blockGroup;\n }\n\n if (fragment.length === 1) {\n const rootNode = fragment.get(0);\n if (rootNode instanceof Y.XmlElement && rootNode.nodeName === 'blockGroup') {\n return rootNode;\n }\n }\n\n throw new Error('Unexpected BlockNote document shape in XmlFragment. ' + 'Expected a single top-level blockGroup node.');\n}\n"],"mappings":"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","names":["Y","Y"]}