@ai-matrx/office 0.8.0 → 0.8.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/CHANGELOG.md +16 -0
- package/dist/chunk-47MIGBMH.js +148 -0
- package/dist/chunk-47MIGBMH.js.map +1 -0
- package/dist/{chunk-BWMAYLW4.cjs → chunk-6Z3Y6DUI.cjs} +7 -7
- package/dist/chunk-6Z3Y6DUI.cjs.map +1 -0
- package/dist/chunk-MQB2ZK2F.cjs +148 -0
- package/dist/chunk-MQB2ZK2F.cjs.map +1 -0
- package/dist/chunk-QZE7HBZB.cjs.map +1 -1
- package/dist/{chunk-O6FTSXHE.cjs → chunk-UBLEFLES.cjs} +40 -10
- package/dist/chunk-UBLEFLES.cjs.map +1 -0
- package/dist/{chunk-IDEA5UXK.js → chunk-XMM62UAT.js} +2 -2
- package/dist/{chunk-PI473GES.js → chunk-Z247F527.js} +36 -6
- package/dist/chunk-Z247F527.js.map +1 -0
- package/dist/chunk-ZDZCCOUB.cjs.map +1 -1
- package/dist/docs-io.cjs +9 -10
- package/dist/docs-io.cjs.map +1 -1
- package/dist/docs-io.js +2 -3
- package/dist/docs-io.js.map +1 -1
- package/dist/docs-tools.cjs +40 -129
- package/dist/docs-tools.cjs.map +1 -1
- package/dist/docs-tools.d.cts +21 -14
- package/dist/docs-tools.d.ts +21 -14
- package/dist/docs-tools.js +21 -110
- package/dist/docs-tools.js.map +1 -1
- package/dist/docs.cjs +19 -4
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.d.cts +5 -0
- package/dist/docs.d.ts +5 -0
- package/dist/docs.js +18 -3
- package/dist/docs.js.map +1 -1
- package/dist/matrxImagePorts-JDFYE4QI.cjs.map +1 -1
- package/dist/sheets-xlsx.cjs.map +1 -1
- package/dist/sheets.cjs.map +1 -1
- package/dist/univer-collab.cjs +11 -1
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +7 -1
- package/dist/univer-collab.d.ts +7 -1
- package/dist/univer-collab.js +11 -1
- package/dist/univer-collab.js.map +1 -1
- package/dist/xlsx-to-univer-AQAXU3TC.cjs.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-2UBGQUXW.cjs +0 -37
- package/dist/chunk-2UBGQUXW.cjs.map +0 -1
- package/dist/chunk-BWMAYLW4.cjs.map +0 -1
- package/dist/chunk-MPKXXZZV.js +0 -37
- package/dist/chunk-MPKXXZZV.js.map +0 -1
- package/dist/chunk-O6FTSXHE.cjs.map +0 -1
- package/dist/chunk-PI473GES.js.map +0 -1
- /package/dist/{chunk-IDEA5UXK.js.map → chunk-XMM62UAT.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/univer/collab/index.ts","../src/univer/collab/WorkbookCollabSession.ts","../src/univer/collab/covered.ts","../src/univer/collab/docs-ot/transform.ts","../src/univer/collab/docs-ot/state-hash.ts","../src/univer/collab/docs-ot/room.ts","../src/docs/document-ot-room.ts","../src/docs/document-service.ts","../src/docs/ports.ts"],"sourcesContent":["/**\n * The collab session shared by `/sheets` and `/docs` (was matrx-frontend `features/workbooks/collab`): the\n * Univer <-> Yjs bridge. It owns the Yjs import, so it is loaded on demand (`import()` when a workbook\n * or document goes live). The snapshot-insert subscription hook is its own entry,\n * `@ai-matrx/office/univer/realtime`, so a static import of the hook never carries Yjs into the editor\n * chunk. A transitional subpath, like `./univer`: it goes internal when the editors move.\n */\nexport * from \"./WorkbookCollabSession\";\nexport * from \"./docs-ot\";\nexport * from \"../../docs/document-ot-room\";\n","/**\n * WorkbookCollabSession — the Univer ↔ Yjs bridge.\n *\n * Subscribes to Univer's public `commandService.onMutationExecutedForCollab`\n * hook for local mutations and pushes them onto a `Y.Array<MutationOp>` shared\n * via `SupabaseYjsProvider`. Inbound Yjs updates produce `IMutationInfo` ops\n * that are applied through `commandService.syncExecuteCommand` with the\n * `fromCollab` execution option flagged so the outbound listener short-\n * circuits and we don't echo our own apply.\n *\n * See `FEATURE.md` in this directory for the architecture, the \"do NOT use\n * the Pro preset\" verdict, and the host-election rule. This class is the\n * runtime side of that plan.\n *\n * Lifecycle:\n * - constructor: wire references, no side effects\n * - start(): create Y.Doc + Awareness, instantiate provider, subscribe to\n * command stream, subscribe to Yjs Array observer\n * - stop(): detach all listeners, dispose provider\n *\n * The session is one-shot per workbook open. Reload = stop() + new instance.\n */\n\"use client\";\n\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport { electCollabHost, remoteOriginOf, REMOTE_PARAM_TAG } from \"@ai-matrx/data/realtime/collab\";\n\nexport { COLLAB_COVERED_KEY, stampCovered, takeCovered } from \"./covered\";\n\n/**\n * Structural transport contract. `SupabaseYjsProvider` satisfies it in\n * production; the verification harness injects an in-memory loopback\n * transport through the same seam. Keeping this structural (not the concrete\n * class) is what makes the session testable without network.\n */\nexport type CollabProviderLike = {\n connect(): Promise<void>;\n disconnect(): void;\n ready(): Promise<void>;\n /**\n * True when this is the only holder of its room in this tab allowed to act as\n * host (autosave). Same-tab holders share one client id and one uid, so\n * awareness cannot tell them apart. Absent = a lone holder = leader.\n */\n isTabLeader?(): boolean;\n};\n\n// Univer types are loose at the public hook boundary; we narrow with a\n// structural interface so we don't have to import the full Univer surface.\ntype MutationParams = Record<string, unknown> | unknown[] | null;\n\nexport type CollabMutationInfo = {\n id: string;\n type: number; // CommandType.MUTATION = 2 in Univer's enum\n params: MutationParams;\n /** Who made it (the person's uid), so a peer can tell its own other tab's edit from a stranger's. */\n uid?: string;\n /**\n * The entry's identity in the room (`<clientId>:<seq>`). A saved snapshot names the entries it holds\n * (`stampCovered`), so a seat that boots from that snapshot never replays them a second time.\n */\n eid?: string;\n};\n\n/**\n * What a seat booted from: the saved snapshot's row id and the room entries that snapshot already holds.\n * The session never replays a covered entry, and a seat that booted from an OLDER snapshot than the\n * room's newest checkpoint first reloads (the entries that checkpoint trimmed are only in that snapshot).\n */\nexport type CollabBase = {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (and make it the base). */\n reload: () => Promise<void>;\n};\n\ntype ExecuteOptions = {\n /** Per-Univer convention: when true, the command runs locally only and is\n * NOT broadcast to other plugins. We set this on inbound-apply so the\n * subsequent onMutationExecutedForCollab does NOT re-fire on our peer. */\n onlyLocal?: boolean;\n fromCollab?: boolean;\n};\n\nexport type CommandServiceLike = {\n onMutationExecutedForCollab(\n listener: (info: CollabMutationInfo, options?: ExecuteOptions) => void,\n ): {\n dispose: () => void;\n };\n syncExecuteCommand(\n id: string,\n params: MutationParams,\n options?: ExecuteOptions,\n ): unknown;\n};\n\nexport type WorkbookCollabSessionOptions = {\n workbookId: string;\n uid: string;\n clientId: string;\n commandService: CommandServiceLike;\n /** Factory so this file does not statically depend on the provider. */\n makeProvider: (args: {\n workbookId: string;\n clientId: string;\n doc: Y.Doc;\n awareness: Awareness;\n /** Wire to the provider so a host handover re-runs the election. */\n onLeaderChange: () => void;\n }) => CollabProviderLike;\n /** Called when the awareness set changes (peers join / leave / move cursor). */\n onAwarenessChange?: (awareness: Awareness) => void;\n /**\n * A peer replaced the whole content (history restore, Google update): the\n * newest saved snapshot is the content now. Reload it in place; never\n * re-announce. See `announceReplaced`.\n */\n onReplaced?: (snapshotId: string) => void;\n /**\n * TRUE when the room is bound to a Univer DOCUMENT unit (the Docs editor): there the `doc.mutation.*`\n * stream IS the content, so it must travel. Leave unset for a workbook, where `doc.mutation.*` is the\n * in-cell editor's scratch document and never travels (see `isCellEditorScratch`).\n */\n forwardDocumentMutations?: boolean;\n /**\n * The Univer unit id this seat mounted. Each seat can mount its own unit, so a peer's mutation\n * (addressed to the SENDER's unit) is re-addressed to this one before it is applied.\n */\n unitId?: () => string | null;\n /** A peer's mutation could not be applied here: the seat says so and re-syncs; never only a console line. */\n onApplyFailed?: (mutationId: string, error: unknown) => void;\n /**\n * The saved snapshot this seat booted from. Without it a reloading seat replays every entry still in\n * the room's log on top of a snapshot that already holds them: the text shows twice, and the next save\n * stores it twice (2026-10-16).\n */\n base?: CollabBase;\n};\n\n/** What `checkpoint` writes into the room's control map: the newest saved snapshot whose entries left the log. */\ntype CheckpointSignal = { snapshotId: string; by: string };\n\n/** What `announceReplaced` writes into the room's control map. */\ntype ReplacedSignal = { snapshotId: string; by: string; nonce: string };\n\nconst MUTATIONS_ARRAY_KEY = \"mutations\";\nconst CONTROL_MAP_KEY = \"control\";\nconst REPLACED_KEY = \"replaced\";\nconst CHECKPOINT_KEY = \"checkpoint\";\n\nexport class WorkbookCollabSession {\n private readonly options: WorkbookCollabSessionOptions;\n private doc: Y.Doc | null = null;\n private awareness: Awareness | null = null;\n private provider: CollabProviderLike | null = null;\n private commandDisposer: { dispose: () => void } | null = null;\n private yArrayObserver:\n ((event: Y.YArrayEvent<CollabMutationInfo>) => void) | null = null;\n private awarenessObserver: (() => void) | null = null;\n private controlObserver: ((event: Y.YMapEvent<unknown>) => void) | null = null;\n /** >0 while this client swaps its own content: its mutations are not edits. */\n private muted = 0;\n private started = false;\n private disposed = false;\n /** Room entries this seat holds in its content: applied from a peer, or made here. */\n private readonly applied = new Set<string>();\n /** Entries without an id (a peer on an older build) are applied once, by identity. */\n private readonly appliedRefs = new WeakSet<object>();\n private seq = 0;\n /** False until this seat has seen the room's content once (the join-time check runs then). */\n private joined = false;\n /** The base is being reloaded: entries wait in the log until it is shown. */\n private reloadingBase = false;\n\n constructor(options: WorkbookCollabSessionOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n if (this.started || this.disposed) return;\n this.started = true;\n\n this.doc = new Y.Doc();\n this.awareness = new Awareness(this.doc);\n\n // Seed local awareness with the user identity. Cursor (sheetId/row/col)\n // is set later via setCursor().\n this.awareness.setLocalState({\n uid: this.options.uid,\n clientId: this.options.clientId,\n name: this.options.uid.slice(0, 8),\n color: pickColor(this.options.uid),\n sheetId: null,\n row: null,\n col: null,\n ts: Date.now(),\n });\n\n this.provider = this.options.makeProvider({\n workbookId: this.options.workbookId,\n clientId: this.options.clientId,\n doc: this.doc,\n awareness: this.awareness,\n onLeaderChange: () => {\n if (this.awareness) this.options.onAwarenessChange?.(this.awareness);\n },\n });\n\n // Subscribe to inbound Yjs array changes BEFORE connecting the provider,\n // so the initial-state replay (if any) hits our observer.\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n this.yArrayObserver = (event) => {\n // Local transactions are OUR OWN pushes from handleLocalMutation —\n // Univer already executed those mutations. Re-applying them here would\n // double-apply every local edit on the originator. Only act on\n // transactions that arrived via Y.applyUpdate (origin 'remote').\n if (event.transaction.local) return;\n if (!event.changes.delta.some((change) => Array.isArray(change.insert) && change.insert.length > 0)) return;\n this.drain();\n };\n yArray.observe(this.yArrayObserver as Parameters<typeof yArray.observe>[0]);\n\n // Awareness change passthrough.\n if (this.options.onAwarenessChange) {\n const cb = this.options.onAwarenessChange;\n this.awarenessObserver = () => {\n if (this.awareness) cb(this.awareness);\n };\n this.awareness.on(\"change\", this.awarenessObserver);\n }\n\n // Subscribe to Univer's collab-grain mutation stream.\n this.commandDisposer =\n this.options.commandService.onMutationExecutedForCollab((info, options) =>\n this.handleLocalMutation(info, options),\n );\n\n await this.provider.connect();\n await this.provider.ready();\n this.drain();\n\n // Whole-content replacement from a peer. Bound AFTER the initial sync: a\n // joiner already loaded the newest snapshot, so the signal it finds in\n // the room's state is history, not news (the editor also skips a\n // snapshot it already shows).\n if (this.disposed || !this.doc) return;\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const seen = (control.get(REPLACED_KEY) as ReplacedSignal | undefined)?.nonce ?? null;\n this.controlObserver = (event) => {\n if (event.transaction.local || !event.keysChanged.has(REPLACED_KEY)) return;\n const signal = control.get(REPLACED_KEY) as ReplacedSignal | undefined;\n if (!signal?.snapshotId || signal.nonce === seen) return;\n this.options.onReplaced?.(signal.snapshotId);\n };\n control.observe(this.controlObserver);\n }\n\n stop(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n this.commandDisposer?.dispose();\n this.commandDisposer = null;\n\n if (this.doc && this.yArrayObserver) {\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n yArray.unobserve(\n this.yArrayObserver as Parameters<typeof yArray.unobserve>[0],\n );\n this.yArrayObserver = null;\n }\n\n if (this.doc && this.controlObserver) {\n this.doc.getMap<unknown>(CONTROL_MAP_KEY).unobserve(this.controlObserver);\n this.controlObserver = null;\n }\n\n if (this.awareness && this.awarenessObserver) {\n this.awareness.off(\"change\", this.awarenessObserver);\n this.awarenessObserver = null;\n }\n\n this.provider?.disconnect();\n this.provider = null;\n\n if (this.awareness) {\n this.awareness.destroy();\n this.awareness = null;\n }\n\n if (this.doc) {\n this.doc.destroy();\n this.doc = null;\n }\n }\n\n /** How many mutations the shared log holds right now. */\n logLength(): number {\n return this.doc?.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).length ?? 0;\n }\n\n /**\n * The room entries this seat's content holds RIGHT NOW. Read it in the same synchronous step as the\n * content you are about to save, and save it with that content (`stampCovered`); after the save lands,\n * pass it to `checkpoint`.\n */\n coveredNow(): string[] {\n if (!this.doc) return [];\n const covered = this.options.base?.covered();\n const out: string[] = [];\n for (const op of this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).toArray()) {\n if (op.eid && (this.applied.has(op.eid) || covered?.has(op.eid))) out.push(op.eid);\n }\n return out;\n }\n\n /**\n * The snapshot `snapshotId` was SAVED holding `covered` (from `coveredNow`): those entries leave the\n * shared log, and the room records the snapshot as its newest checkpoint. Removal is by entry id, never\n * by position — an entry that arrived while the save was in flight is not in the snapshot and stays.\n * Only the elected saver calls this; peers receive it as a delete (never replayed).\n */\n checkpoint(snapshotId: string, covered: readonly string[]): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const drop = new Set(covered);\n const signal: CheckpointSignal = { snapshotId, by: this.options.clientId };\n this.doc.transact(() => {\n const entries = yArray.toArray();\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const eid = entries[i]?.eid;\n if (eid && drop.has(eid)) yArray.delete(i, 1);\n }\n control.set(CHECKPOINT_KEY, signal);\n });\n }\n\n /**\n * This client replaced the whole content and SAVED it as `snapshotId`.\n * One transaction empties the shared mutation log (every entry targets the\n * content that is gone — a joiner must never replay them onto the new\n * snapshot) and tells every peer to reload the newest snapshot.\n */\n announceReplaced(snapshotId: string): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const signal: ReplacedSignal = {\n snapshotId,\n by: this.options.clientId,\n nonce: `${this.options.clientId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,\n };\n this.doc.transact(() => {\n if (yArray.length > 0) yArray.delete(0, yArray.length);\n control.set(REPLACED_KEY, signal);\n control.set(CHECKPOINT_KEY, { snapshotId, by: this.options.clientId } satisfies CheckpointSignal);\n });\n }\n\n /**\n * Run `swap` (this client tearing its content down and mounting the new\n * one) without broadcasting what Univer emits while it does: those are not\n * edits, and peers reload the same snapshot themselves.\n */\n muteWhile<T>(swap: () => T): T {\n this.muted += 1;\n try {\n return swap();\n } finally {\n this.muted -= 1;\n }\n }\n\n /**\n * Update the local awareness cursor. Call this from Univer's selection\n * listener (`worksheet.onSelectionChange(...)`). Throttle at the call site\n * (~50ms is plenty); the provider broadcasts on its own debounced cycle.\n */\n setCursor(input: {\n sheetId: string | null;\n row: number | null;\n col: number | null;\n }): void {\n if (!this.awareness) return;\n const current = this.awareness.getLocalState() ?? {};\n this.awareness.setLocalState({\n ...current,\n sheetId: input.sheetId,\n row: input.row,\n col: input.col,\n ts: Date.now(),\n });\n }\n\n /**\n * Returns the deterministic host: the connected peer with the lowest uid\n * (lexicographic). Host is the only client that writes canonical snapshots.\n * No election protocol; recompute whenever awareness changes.\n */\n electHost(opts: { tabTieBreak?: boolean } = {}): { isHost: boolean; hostUid: string | null } {\n if (!this.awareness) return { isHost: false, hostUid: null };\n const states = Array.from(this.awareness.getStates().values()) as Array<\n Record<string, unknown>\n >;\n // Lowest uid wins ACROSS tabs; inside this tab only the room's tab leader\n // may be host, because every same-tab holder carries the same uid.\n const leader = this.provider?.isTabLeader?.() ?? true;\n return electCollabHost(states, this.options.uid, this.options.clientId, leader, opts.tabTieBreak ?? false);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private handleLocalMutation(info: CollabMutationInfo, options?: ExecuteOptions): void {\n if (this.muted > 0) return;\n // Univer marks a mutation `onlyLocal` when every seat derives it itself (formula-engine recalculation,\n // layout results): relaying it turns every recalculation into network traffic and a logged op.\n if (options?.onlyLocal) return;\n if (!this.options.forwardDocumentMutations && isCellEditorScratch(info)) return;\n // Inbound-applied mutations re-fire this listener because Univer's\n // syncExecuteCommand legitimately processes them through the full\n // pipeline. Skip by sniffing the sentinel we stamped on apply.\n if (\n info.params &&\n typeof info.params === \"object\" &&\n !Array.isArray(info.params) &&\n remoteOriginOf(info.params) !== null\n ) {\n return;\n }\n if (!this.doc) return;\n\n // Normalize params through a JSON round-trip BEFORE pushing into Yjs.\n // Yjs (and the Broadcast transport) only carry JSON-encodable values;\n // Univer types its mutation params as \"serializable\" but JS objects can\n // smuggle Date / Map / class instances through that promise. The\n // round-trip makes the failure mode deterministic: a non-encodable\n // mutation is skipped with a warning instead of corrupting the shared\n // doc or desyncing peers mid-session. What we push here is byte-for-byte\n // what remote peers will apply, so local-apply == remote-apply.\n let safeParams: MutationParams;\n try {\n safeParams =\n info.params === undefined || info.params === null\n ? null\n : stripSenderView(JSON.parse(JSON.stringify(info.params)) as MutationParams);\n } catch (err) {\n console.warn(\n `[collab] skipping non-serializable mutation \"${info.id}\" — peers will not receive it`,\n err,\n );\n return;\n }\n\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const eid = `${this.options.clientId}:${++this.seq}`;\n this.applied.add(eid);\n // An edit made here is made on what this seat shows: the join-time check is over.\n this.joined = true;\n yArray.push([{ id: info.id, type: info.type, params: safeParams, uid: this.options.uid, eid }]);\n }\n\n /**\n * Apply every log entry this seat's content does not hold yet, in the log's order. The first time the\n * room shows content, the join-time check runs: a seat that booted from a snapshot OLDER than the\n * room's newest checkpoint reloads first (the entries that checkpoint trimmed exist only in it).\n */\n private drain(): void {\n if (!this.doc || this.disposed || this.reloadingBase) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const entries = yArray.toArray();\n const base = this.options.base;\n if (!this.joined) {\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const checkpoint = control.get(CHECKPOINT_KEY) as CheckpointSignal | undefined;\n if (entries.length === 0 && !checkpoint) return;\n this.joined = true;\n if (base && checkpoint?.snapshotId && checkpoint.snapshotId !== base.snapshotId()) {\n this.reloadingBase = true;\n void base\n .reload()\n .catch((error: unknown) => {\n console.warn(\"[collab] could not load the newest saved version on joining\", error);\n this.options.onApplyFailed?.(\"collab.join\", error);\n })\n .finally(() => {\n this.reloadingBase = false;\n this.drain();\n });\n return;\n }\n }\n const covered = base?.covered();\n for (const op of entries) {\n if (op.eid) {\n if (this.applied.has(op.eid) || covered?.has(op.eid)) continue;\n this.applied.add(op.eid);\n } else {\n if (this.appliedRefs.has(op)) continue;\n this.appliedRefs.add(op);\n }\n this.applyRemoteMutation(op);\n }\n }\n\n private applyRemoteMutation(op: CollabMutationInfo): void {\n // Wrap params with the sentinel so handleLocalMutation knows not to\n // echo the apply back into Yjs.\n const ownUnit = this.options.unitId?.() ?? null;\n const taggedParams: MutationParams =\n op.params && typeof op.params === \"object\" && !Array.isArray(op.params)\n ? {\n ...(op.params as Record<string, unknown>),\n ...(ownUnit && typeof (op.params as { unitId?: unknown }).unitId === \"string\" ? { unitId: ownUnit } : {}),\n [REMOTE_PARAM_TAG]: op.uid ?? true,\n }\n : op.params;\n\n try {\n this.options.commandService.syncExecuteCommand(op.id, taggedParams, {\n onlyLocal: true,\n fromCollab: true,\n });\n } catch (err) {\n // One unappliable op (already baked into the loaded snapshot, or a\n // stale target) must not throw into the realtime channel handler and\n // abort the rest of the catch-up. Said, never swallowed.\n console.warn(\n `[collab] could not apply remote mutation \"${op.id}\" — skipped`,\n err,\n );\n this.options.onApplyFailed?.(op.id, err);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────────────────\n\n/**\n * A workbook holds no Univer DOCUMENT units of its own: the `doc.mutation.*` stream a sheet emits is\n * the in-cell editor's scratch document (typing into a cell). The finished text reaches the sheet as\n * `sheet.mutation.set-range-values`, which does travel. Sending the scratch edits made a joiner replay\n * them against an editor unit it does not have (\"Trying to overwrite value at key\").\n */\nexport const SENDER_VIEW_PARAMS: readonly string[] = [\"layoutState\", \"textRanges\", \"prevTextRanges\"];\n\n/**\n * Remove what describes the SENDER'S view (the editor's layout cache, caret and selection ranges) from a\n * mutation's params before it travels: a receiver would otherwise restore the sender's layout and caret.\n * Everything else (the content-changing `actions`, ids, addresses) is left as is.\n */\nexport function stripSenderView(params: MutationParams): MutationParams {\n if (!params || typeof params !== \"object\" || Array.isArray(params)) return params;\n const out: Record<string, unknown> = { ...params };\n for (const key of SENDER_VIEW_PARAMS) delete out[key];\n return out;\n}\n\nexport function isCellEditorScratch(info: Pick<CollabMutationInfo, \"id\">): boolean {\n return typeof info.id === \"string\" && info.id.startsWith(\"doc.mutation.\");\n}\n\nconst CURSOR_PALETTE = [\n \"#3b82f6\", // blue\n \"#10b981\", // emerald\n \"#f59e0b\", // amber\n \"#ef4444\", // red\n \"#8b5cf6\", // violet\n \"#06b6d4\", // cyan\n \"#ec4899\", // pink\n \"#84cc16\", // lime\n];\n\nfunction pickColor(uid: string): string {\n // Deterministic FNV-1a-ish hash so the same user is always the same color\n // across sessions and across other users' screens.\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? \"#ec4899\";\n}\n","/**\n * A saved snapshot names the collab-room entries it already holds, so a seat that boots from it never\n * replays them (2026-10-16: a reload showed the text twice). Pure — no Yjs — so the editors' model can\n * stamp and read it without loading the room.\n */\n\n/** The key a saved snapshot carries its covered room entries under (`stampCovered` / `takeCovered`). */\nexport const COLLAB_COVERED_KEY = \"__matrxCollabCovered\";\n\n/** The snapshot to SAVE: `snapshot` plus the room entries it holds (`WorkbookCollabSession.coveredNow`). */\nexport function stampCovered<T extends object>(snapshot: T, covered: readonly string[]): T {\n return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered] };\n}\n\n/** A LOADED snapshot split into the content to mount and the room entries it already holds. */\nexport function takeCovered<T>(snapshot: T): { snapshot: T; covered: Set<string> } {\n if (!snapshot || typeof snapshot !== \"object\" || !(COLLAB_COVERED_KEY in (snapshot as object))) {\n return { snapshot, covered: new Set() };\n }\n const { [COLLAB_COVERED_KEY]: list, ...rest } = snapshot as Record<string, unknown>;\n return {\n snapshot: rest as T,\n covered: new Set(Array.isArray(list) ? list.filter((e): e is string => typeof e === \"string\") : []),\n };\n}\n","/**\n * The Docs operational transform (COLLAB-DESIGN §6.4, §6.5; C0b rules R1–R5 plus the C2 retain rule R6).\n *\n * Pure and DOM-free. ot-json1 walks the JSON tree; only the `text-x` edit transform is ours. It is a port of\n * Univer 1.0.4's `TextX._transform` / `transformBody` (Apache-2.0, dream-num/univer, core\n * src/docs/data-model/text-x) with these cases changed or added (evidence: C0-REPORT, C0b):\n *\n * R1 a whole-table delete swallows typing inside it; the typist gets a `lost` entry.\n * R2 a REPLACE (coverType 1) retain keeps a concurrent comment decoration whole.\n * R3 a REPLACE paragraph with no paragraphStyle means \"no style\" ({}), on both sides.\n * R4 style keys are tested for presence (`!== undefined`), never truthiness (a winning `bl: 0`).\n * R5 a non-monotonic op (a negative retain) is rewritten as the composition of its forward segments.\n * R6 a merge (not REPLACE) retain whose style lost every key comes back as a PLAIN retain. Without it `textRuns: [{ts:{}}]` and\n * `textRuns: []` apply differently and two-edit chains diverge (C2: 462 of 20,000; with it 0).\n *\n * Ops carrying `rangeUpdates` go to Univer's `TextX.transform` unchanged (no free 1.0.4 command emits them).\n * `T(x, y, side)` returns x rewritten to apply after y; `side` is x's side and the later-committed op takes\n * `'left'` (§6.4). A transform that throws is a barrier for that pair (the session treats a throw as one).\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- Univer's text-x action shapes are open JSON */\nimport { JSONX, TextX, getBodySliceForSplitTextXAction, normalizeTextRuns, merge as univerMerge } from \"@univerjs/core\";\nimport * as json1 from \"ot-json1\";\n\ntype Act = Record<string, any> & { t: \"i\" | \"r\" | \"d\"; len: number };\ntype Body = Record<string, any>;\ntype Zone = [number, number];\n/** One `lost` entry: what a transform dropped from either side (R1), for the author's notice. */\nexport interface DocsLost {\n rule: string;\n side: \"insert\" | \"delete\";\n len: number;\n text?: string;\n}\n\nconst isTextX = (c: unknown): c is { et: string; e: Act[] } =>\n !!c && typeof c === \"object\" && (c as { et?: unknown }).et === \"text-x\" && Array.isArray((c as { e?: unknown }).e);\nconst clone = <T>(v: T): T => (v == null ? v : structuredClone(v));\n\n// ── normalisation: the travelling shape ──────────────────────────────────────────────────────────────\n\nfunction tableZones(a: Act): Zone[] {\n const out: Zone[] = [];\n for (const t of (a.body?.tables ?? []) as Array<{ startIndex: number; endIndex: number }>) {\n if (t.startIndex >= 0 && t.endIndex <= a.len && t.endIndex > t.startIndex) out.push([t.startIndex, t.endIndex - 1]);\n }\n return out;\n}\n\n/** R5: an op whose cursor goes backwards becomes the composition of its forward-only segments. */\nfunction unrewind(actions: Act[]): Act[] {\n if (!actions.some((a) => a.len < 0)) return actions;\n const segs: Act[][] = [];\n let cur: Act[] = [];\n let cursor = 0;\n for (const a of actions) {\n if (a.len < 0) {\n if (a.t !== \"r\") return actions;\n segs.push(cur);\n cursor += a.len;\n cur = cursor > 0 ? [{ t: \"r\", len: cursor }] : [];\n continue;\n }\n cur.push(a);\n if (a.t !== \"d\") cursor += a.len;\n }\n segs.push(cur);\n const out = segs.reduce((acc, s) => TextX.compose(acc as any, s as any) as unknown as Act[]);\n return out.some((a) => a.len < 0) ? actions : out;\n}\n\nfunction normText(actions: Act[]): Act[] {\n const out: Act[] = [];\n for (const a of unrewind(actions)) {\n if (a.t === \"d\") {\n if (!(a.len > 0)) continue;\n const d: Act = { t: \"d\", len: a.len };\n if (a.valueRangeId !== undefined) d.valueRangeId = a.valueRangeId;\n const tz = (a.tz as Zone[] | undefined) ?? tableZones(a);\n if (tz.length) d.tz = tz;\n out.push(d);\n continue;\n }\n if (a.t === \"r\") {\n const { oldBody: _oldBody, ...rest } = a;\n out.push(rest as Act);\n continue;\n }\n out.push(a);\n }\n return out;\n}\n\n/** The travelling shape of a Docs JSON op: text-x edits normalised (R1 zones, R5, no oldBody). */\nexport function normalizeDocsOp<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) return { ...v, e: normText(v.e) };\n return v;\n };\n return walk(op) as T;\n}\n\n/** R6: a retain whose style lost every key to the other side is a plain retain. */\nexport function dropEmptyStyleRetains<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) {\n return {\n ...v,\n e: v.e.map((a) => {\n const b = a.body as Body | undefined;\n if (a.t !== \"r\" || !b || a.coverType === 1) return a;\n const runs = ((b.textRuns as Array<{ ts?: Record<string, unknown> }>) ?? []).filter((r) => r.ts && Object.keys(r.ts).length);\n const other = Object.keys(b).filter(\n (k) => k !== \"textRuns\" && k !== \"dataStream\" && !(Array.isArray(b[k]) && (b[k] as unknown[]).length === 0),\n );\n if (!runs.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: \"r\", len: a.len };\n if (b.textRuns === undefined || runs.length === (b.textRuns as unknown[]).length) return a;\n return { ...a, body: { ...b, textRuns: runs } };\n }),\n };\n }\n return v;\n };\n return walk(op) as T;\n}\n\n// ── action list helpers (Univer's TextX.push / trimEndUselessRetainAction, plus zone merging) ────────\n\nconst onlyDataStream = (body: Body) => Object.keys(body).length === 1;\nconst shiftZones = (tz: Zone[], by: number): Zone[] => tz.map(([s, e]) => [s + by, e + by]);\nfunction mergeZones(tz: Zone[]): Zone[] {\n const s = [...tz].sort((x, y) => x[0] - y[0]);\n const out: Zone[] = [];\n for (const z of s) {\n const l = out[out.length - 1];\n if (l && l[1] + 1 >= z[0]) l[1] = Math.max(l[1], z[1]);\n else out.push([z[0], z[1]]);\n }\n return out;\n}\nfunction push(list: Act[], action: Act): void {\n let index = list.length;\n let last = list[index - 1];\n const a = clone(action);\n if (a.t === \"r\" && a.len === 0 && a.body == null && !a.rangeUpdates) return;\n if (last) {\n if (last.t === \"d\" && a.t === \"d\" && last.valueRangeId === a.valueRangeId) {\n const tz = [...((last.tz as Zone[]) ?? []), ...shiftZones((a.tz as Zone[]) ?? [], last.len)];\n last.len += a.len;\n if (tz.length) last.tz = mergeZones(tz);\n return;\n }\n if (last.t === \"d\" && a.t === \"i\") {\n index -= 1;\n last = list[index - 1];\n if (last == null) {\n list.unshift(a);\n return;\n }\n }\n if (last.t === \"r\" && a.t === \"r\" && last.body == null && a.body == null && !last.rangeUpdates && !a.rangeUpdates) {\n last.len += a.len;\n return;\n }\n if (last.t === \"i\" && onlyDataStream(last.body) && a.t === \"i\" && onlyDataStream(a.body) && last.valueRangeId === a.valueRangeId) {\n last.len += a.len;\n last.body.dataStream += a.body.dataStream;\n return;\n }\n }\n if (index === list.length) list.push(a);\n else list.splice(index, 0, a);\n}\nconst BODY_FIELDS = [\n \"textRuns\", \"paragraphs\", \"customRanges\", \"customBlocks\", \"docxRawCustomBlocks\", \"docxRawBlocks\",\n \"docxExportExcludedRanges\", \"customDecorations\", \"tables\", \"columnGroups\", \"blockRanges\",\n];\nconst uselessRetain = (a: Act) => !a.rangeUpdates?.length && (a.body == null || BODY_FIELDS.every((k) => a.body[k] == null));\nfunction trimEnd(list: Act[]): Act[] {\n while (list.length && list[list.length - 1]!.t === \"r\" && uselessRetain(list[list.length - 1]!)) list.pop();\n return list;\n}\n\n/** Univer's ActionIterator, plus the offset inside the current action and table zones sliced on split. */\nclass It {\n private i = 0;\n private off = 0;\n constructor(private readonly a: Act[]) {}\n peekType(): Act[\"t\"] {\n return this.a[this.i]?.t ?? \"r\";\n }\n peekLength(): number {\n const x = this.a[this.i];\n return x ? x.len - this.off : Number.POSITIVE_INFINITY;\n }\n hasNext(): boolean {\n return this.peekLength() < Number.POSITIVE_INFINITY;\n }\n /** An insert placed now would land strictly inside a table this delete removes whole. */\n inZone(): boolean {\n const x = this.a[this.i];\n return x?.t === \"d\" && ((x.tz as Zone[]) ?? []).some(([s, e]) => s < this.off && this.off <= e);\n }\n next(length?: number): Act {\n let len = length || Number.POSITIVE_INFINITY;\n const x = this.a[this.i];\n if (!x) return { t: \"r\", len: Number.POSITIVE_INFINITY };\n const offset = this.off;\n if (len >= x.len - offset) {\n len = x.len - offset;\n this.i += 1;\n this.off = 0;\n } else this.off += len;\n if (x.t === \"d\") {\n const piece: Act = { ...clone(x), len };\n delete piece.tz;\n const tz = ((x.tz as Zone[]) ?? [])\n .map(([s, e]): Zone => [Math.max(s, offset) - offset, Math.min(e, offset + len - 1) - offset])\n .filter(([s, e]) => s <= e);\n if (tz.length) piece.tz = tz;\n return piece;\n }\n if (x.t === \"r\" && x.body == null) return { ...clone(x), len };\n return { ...clone(x), len, body: getBodySliceForSplitTextXAction(x.body, offset, offset + len, false) };\n }\n}\n\n// ── body transforms: ported from Univer transform-utils.ts, cases R3/R4 marked ───────────────────────\n\nfunction transformTextRuns(originTextRuns: any[] | undefined, targetTextRuns: any[] | undefined, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (originTextRuns == null || targetTextRuns == null) return targetTextRuns;\n if (originTextRuns.length === 0 || targetTextRuns.length === 0) return [];\n targetTextRuns = clone(targetTextRuns);\n originTextRuns = clone(originTextRuns);\n const out: any[] = [];\n const updateLength = targetTextRuns.length;\n const removeLength = originTextRuns.length;\n let updateIndex = 0;\n let removeIndex = 0;\n let pending: any = null;\n const flush = () => {\n if (pending) {\n out.push(pending);\n pending = null;\n return true;\n }\n return false;\n };\n while (updateIndex < updateLength && removeIndex < removeLength) {\n const { st: updateSt, ed: updateEd, ts: targetStyle } = targetTextRuns[updateIndex];\n const { st: removeSt, ed: removeEd, ts: originStyle, sId } = originTextRuns[removeIndex];\n let newTs: Record<string, unknown> = {};\n if (transformType === 0) {\n newTs = { ...targetStyle };\n if (originCoverType === 0 && targetCoverType === 1 && originStyle) newTs = Object.assign({}, originStyle, newTs);\n } else {\n newTs = { ...targetStyle };\n if (originCoverType === 1) {\n if (targetCoverType === 1) newTs = { ...originStyle };\n else if (targetStyle && originStyle) {\n for (const key of Object.keys(targetStyle)) if (originStyle[key] !== undefined) delete newTs[key]; // R4\n }\n } else if (targetCoverType === 1) {\n if (originStyle) for (const key of Object.keys(originStyle)) if (originStyle[key] !== undefined) newTs[key] = originStyle[key];\n } else if (originStyle) {\n for (const key of Object.keys(originStyle)) if (newTs[key] !== undefined) delete newTs[key];\n }\n }\n if (updateEd < removeSt) {\n if (!flush()) out.push(targetTextRuns[updateIndex]);\n updateIndex++;\n } else if (removeEd < updateSt) {\n if (!flush()) out.push(originTextRuns[removeIndex]);\n removeIndex++;\n } else {\n out.push({ st: Math.max(updateSt, removeSt), ed: Math.min(updateEd, removeEd), ts: newTs, sId });\n if (updateEd < removeEd) {\n updateIndex++;\n originTextRuns[removeIndex].st = updateEd;\n if (originTextRuns[removeIndex].st === originTextRuns[removeIndex].ed) removeIndex++;\n } else {\n removeIndex++;\n targetTextRuns[updateIndex].st = removeEd;\n if (targetTextRuns[updateIndex].st === targetTextRuns[updateIndex].ed) updateIndex++;\n }\n const p = {\n st: Math.min(updateEd, removeEd),\n ed: Math.max(updateEd, removeEd),\n ts: updateEd < removeEd ? { ...originStyle } : { ...targetStyle },\n sId: updateEd < removeEd ? sId : undefined,\n };\n pending = p.ed > p.st ? p : null;\n }\n }\n flush();\n const top = out[out.length - 1];\n const updateLast = targetTextRuns[updateLength - 1];\n const removeLast = originTextRuns[removeLength - 1];\n if (top.ed !== Math.max(updateLast.ed, removeLast.ed)) out.push(updateLast.ed > removeLast.ed ? updateLast : removeLast);\n return normalizeTextRuns(out, true);\n}\n\nfunction transformCustomRanges(o: any[] | undefined, t: any[] | undefined, originCoverType: number, _targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (o == null || t == null) return t;\n if (o.length === 0 || t.length === 0) return [];\n if (o.length > 1 || t.length > 1) throw new Error(\"CustomRanges is only supported transform for length one now.\");\n if (originCoverType === 1) return transformType === 1 ? [clone(o[0])] : [clone(t[0])];\n const r = clone(t[0]);\n if (transformType === 1) Object.assign(r, clone(o[0]));\n return [r];\n}\n\nfunction transformParagraph(origin: any, target: any, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any {\n const paragraph: any = { startIndex: target.startIndex, paragraphId: target.paragraphId };\n // R3: on a REPLACE paragraph, a missing paragraphStyle means \"no style\", which is a value.\n const oStyle = originCoverType === 1 ? origin.paragraphStyle ?? {} : origin.paragraphStyle;\n const tStyle = targetCoverType === 1 ? target.paragraphStyle ?? {} : target.paragraphStyle;\n if (tStyle) {\n paragraph.paragraphStyle = clone(tStyle);\n if (oStyle) {\n const ps = paragraph.paragraphStyle;\n if (originCoverType === 1) {\n if (targetCoverType === 1) {\n if (transformType === 1) paragraph.paragraphStyle = { ...oStyle };\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (targetCoverType === 1) {\n if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (ps[k] !== undefined) delete ps[k]; // R3: presence, not truthiness\n }\n }\n if (targetCoverType !== 1 && Object.keys(paragraph.paragraphStyle).length === 0) delete paragraph.paragraphStyle;\n }\n if (originCoverType === 1 && targetCoverType === 1) paragraph.bullet = transformType === 1 ? clone(origin.bullet) : clone(target.bullet);\n else if (origin.bullet === undefined) paragraph.bullet = clone(target.bullet);\n else if (originCoverType === 1 || targetCoverType === 1) paragraph.bullet = transformType === 0 && target.bullet ? clone(target.bullet) : clone(origin.bullet);\n else if (transformType === 0 && target.bullet !== undefined) paragraph.bullet = clone(target.bullet);\n if (paragraph.bullet === undefined) delete paragraph.bullet;\n if (paragraph.paragraphId === undefined) delete paragraph.paragraphId;\n return paragraph;\n}\n\nfunction transformCustomDecorations(origin: any[] | undefined, target: any[] | undefined): any[] | undefined {\n if (origin == null || target == null) return target;\n if (origin.length === 0 || target.length === 0) return clone(target);\n const out: any[] = [];\n for (const d of target) {\n let pushed = false;\n for (const o of origin) {\n if (o.id === d.id) {\n if (o.type === 9999 || d.type === 9999) {\n pushed = true;\n out.push({ ...d, type: 9999 });\n }\n break;\n }\n }\n if (!pushed) out.push(d);\n }\n return out;\n}\n\nfunction transformBlockRanges(thisBlockRanges: any[], otherBlockRanges: any[], priority: boolean): any[] {\n if (!thisBlockRanges.length) return otherBlockRanges;\n if (!otherBlockRanges.length) return [];\n return otherBlockRanges.map((o) => {\n const t = thisBlockRanges.find((b) => b.blockId === o.blockId);\n return t && priority ? univerMerge(o, t) : o;\n });\n}\n\n/** transformBody(thisAction = the other op's chunk, otherAction = the chunk being transformed, priority = this wins). */\nfunction transformBody(thisAction: Act, otherAction: Act, priority: boolean): { coverType: number; body: Body } {\n const { body: thisBody, coverType: thisCoverType = 0 } = thisAction;\n const { body: otherBody, coverType: otherCoverType = 0 } = otherAction;\n if (thisBody == null || thisBody.dataStream !== \"\" || otherBody == null || otherBody.dataStream !== \"\") {\n throw new Error(\"Data stream is not supported in retain transform.\");\n }\n const ret: Body = { dataStream: \"\" };\n const { textRuns: tr1, paragraphs: p1 = [], blockRanges: b1 = [], customRanges: c1, customDecorations: d1 } = thisBody;\n const { textRuns: tr2, paragraphs: p2 = [], blockRanges: b2 = [], customRanges: c2, customDecorations: d2 } = otherBody;\n const pt: 0 | 1 = priority ? 1 : 0;\n const textRuns = transformTextRuns(tr1, tr2, thisCoverType, otherCoverType, pt);\n if (textRuns) ret.textRuns = textRuns;\n const customRanges = transformCustomRanges(c1, c2, thisCoverType, otherCoverType, pt);\n if (customRanges) ret.customRanges = customRanges;\n const customDecorations = transformCustomDecorations(d1, d2);\n if (customDecorations) ret.customDecorations = customDecorations;\n const paragraphs: any[] = [];\n let i = 0;\n let j = 0;\n while (i < p1.length && j < p2.length) {\n const a = p1[i];\n const b = p2[j];\n if (a.startIndex === b.startIndex) {\n paragraphs.push(transformParagraph(a, b, thisCoverType, otherCoverType, pt));\n i++;\n j++;\n } else if (a.startIndex < b.startIndex) i++;\n else {\n paragraphs.push(clone(b));\n j++;\n }\n }\n if (j < p2.length) paragraphs.push(...p2.slice(j));\n if (paragraphs.length) ret.paragraphs = paragraphs;\n const blockRanges = transformBlockRanges(b1, b2, priority);\n if (blockRanges.length) ret.blockRanges = blockRanges;\n return { coverType: otherCoverType, body: ret };\n}\n\n// ── the text-x transform ──────────────────────────────────────────────────────────────────────────────\n\nconst valueIds = (acts: Act[]) => new Set(acts.flatMap((a) => (a.t !== \"r\" && a.valueRangeId ? [a.valueRangeId as string] : [])));\nfunction withoutValueRangeMetadata(acts: Act[], suppressed: Set<string>): Act[] {\n return acts.map((a) => {\n if (!a.body?.customRanges?.some((r: any) => suppressed.has(r.rangeId))) return a;\n const body = { ...a.body, customRanges: a.body.customRanges.filter((r: any) => !suppressed.has(r.rangeId)) };\n if (!body.customRanges.length) delete body.customRanges;\n return { ...a, body };\n });\n}\n/** Decorations y adds, in the coordinates of the document after y. */\nfunction addedDecorations(y: Act[]): Array<{ id: string; type: number; ds: number; de: number }> {\n const out: Array<{ id: string; type: number; ds: number; de: number }> = [];\n let pos = 0;\n for (const a of y) {\n if (a.t === \"d\") continue;\n if (a.t === \"r\") for (const d of a.body?.customDecorations ?? []) if (d.type !== 9999) out.push({ id: d.id, type: d.type, ds: pos + d.startIndex, de: pos + d.endIndex });\n pos += a.len;\n }\n return out;\n}\nconst hasRangeUpdates = (acts: Act[]) => acts.some((a) => a.t === \"r\" && a.rangeUpdates?.length);\n\n/** x rewritten to apply after y over one text-x body; `side` is x's side. Drops land in `lost` (R1). */\nexport function transformTextX(xIn: Act[], yIn: Act[], side: \"left\" | \"right\", lost: DocsLost[] = []): Act[] {\n if (hasRangeUpdates(xIn) || hasRangeUpdates(yIn)) return TextX.transform(xIn as any, yIn as any, side) as unknown as Act[];\n const x = normText(xIn);\n const y = normText(yIn);\n const xLeft = side === \"left\";\n const yIds = valueIds(y);\n const conflicts = new Set([...valueIds(x)].filter((id) => yIds.has(id)));\n const X = new It(conflicts.size && !xLeft ? withoutValueRangeMetadata(x, conflicts) : x);\n const Y = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);\n const decos = addedDecorations(y).map((d) => ({ ...d, pieces: [] as Zone[] }));\n const out: Act[] = [];\n let inPos = 0;\n let outPos = 0;\n while (X.hasNext() || Y.hasNext()) {\n if (X.peekType() === \"i\" && (xLeft || Y.peekType() !== \"i\")) {\n const a = X.next();\n if (Y.inZone()) {\n lost.push({ rule: \"R1\", side: \"insert\", len: a.len, ...(a.body?.dataStream !== undefined ? { text: a.body.dataStream } : {}) });\n continue;\n }\n if (a.valueRangeId && conflicts.has(a.valueRangeId) && !xLeft) continue;\n push(out, a);\n outPos += a.len;\n } else if (Y.peekType() === \"i\") {\n const b = Y.next();\n if (X.inZone()) {\n push(out, { t: \"d\", len: b.len, tz: [[0, b.len - 1]] });\n lost.push({ rule: \"R1\", side: \"delete\", len: b.len, ...(b.body?.dataStream !== undefined ? { text: b.body.dataStream } : {}) });\n inPos += b.len;\n continue;\n }\n if (b.valueRangeId && conflicts.has(b.valueRangeId) && xLeft) push(out, { t: \"d\", len: b.len, valueRangeId: b.valueRangeId });\n else {\n push(out, { t: \"r\", len: b.len });\n outPos += b.len;\n }\n inPos += b.len;\n } else {\n const len = Math.min(X.peekLength(), Y.peekLength());\n const a = X.next(len);\n const b = Y.next(len);\n if (b.t === \"d\") continue;\n if (a.t === \"d\") {\n push(out, a);\n inPos += len;\n continue;\n }\n for (const d of decos) {\n const s = Math.max(d.ds, inPos);\n const e = Math.min(d.de, inPos + len - 1);\n if (s <= e) d.pieces.push([outPos + s - inPos, outPos + e - inPos]);\n }\n let r: Act = a;\n if (a.body != null && b.body != null) {\n const { coverType, body } = transformBody(b, a, !xLeft);\n r = { ...a, t: \"r\", coverType, body };\n }\n // R2: a REPLACE retain re-asserts, whole, every decoration y added that it overlaps.\n if (r.coverType === 1 && r.body) {\n const keep: any[] = [];\n for (const d of decos) {\n if (!(d.de >= inPos && d.ds < inPos + len)) continue;\n const ahead: Zone[] = d.de >= inPos + len ? [[outPos + len + Math.max(d.ds, inPos + len) - (inPos + len), outPos + d.de - inPos]] : [];\n for (const [s, e] of [...d.pieces, ...ahead]) keep.push({ id: d.id, type: d.type, startIndex: s - outPos, endIndex: e - outPos });\n }\n if (keep.length) r = { ...r, body: { ...r.body, customDecorations: [...(r.body.customDecorations ?? []), ...keep] } };\n }\n push(out, r);\n inPos += len;\n outPos += len;\n }\n }\n return trimEnd(out);\n}\n\n// ── ot-json1 binding ─────────────────────────────────────────────────────────────────────────────────\n\n/** A Docs operation: an ot-json1 op over the whole Univer snapshot (what `rich-text-editing` carries as `actions`). */\nexport type DocsOp = unknown[] | null;\n\nexport interface DocsTransformResult {\n op: DocsOp;\n lost: DocsLost[];\n}\n\nlet sink: DocsLost[] | null = null;\nconst ours = {\n name: \"text-x\",\n uri: (TextX as unknown as { uri: string }).uri,\n apply: (doc: any, actions: any) => TextX.apply(doc, actions),\n compose: (a: any, b: any) => TextX.compose(a, b),\n isNoop: (a: any) => TextX.isNoop(a),\n invert: (a: any) => TextX.invert(a),\n makeInvertible: (a: any, doc: any) => TextX.makeInvertible(a, doc),\n transform: (x: any, y: any, side: \"left\" | \"right\") => transformTextX(x, y, side, sink ?? []),\n};\n\n/**\n * `T(x, y, side)` for Docs: ot-json1 `transformNoConflict` (never throws on DROP_COLLISION / RM_UNEXPECTED_CONTENT /\n * BLACKHOLE, §3) with our text-x transform registered only for the duration of one call, so Univer's own apply is\n * untouched even when the bundler shares one ot-json1 instance with `@univerjs/core`. R6 runs on the result.\n */\nexport function transformDocsOp(x: DocsOp, y: DocsOp, side: \"left\" | \"right\"): DocsTransformResult {\n if (x == null) return { op: null, lost: [] };\n if (y == null) return { op: x, lost: [] };\n const lost: DocsLost[] = [];\n sink = lost;\n json1.type.registerSubtype(ours as any);\n try {\n const op = json1.type.transformNoConflict(normalizeDocsOp(x) as any, normalizeDocsOp(y) as any, side) as DocsOp;\n return { op: dropEmptyStyleRetains(op), lost };\n } finally {\n json1.type.registerSubtype(TextX as any);\n sink = null;\n }\n}\n\n/** `a` then `b` as one op (TextX is the subtype every reader composes with). */\nexport function composeDocsOps(a: DocsOp, b: DocsOp): DocsOp {\n if (a == null) return b;\n if (b == null) return a;\n json1.type.registerSubtype(TextX as any);\n return json1.type.compose(a as any, b as any) as DocsOp;\n}\n\nexport function isNoopDocsOp(op: DocsOp): boolean {\n return op == null || (Array.isArray(op) && op.length === 0) || json1.type.isNoop(op as any);\n}\n\n/** Apply an op to a plain snapshot (tests, the fold). Univer's own JSONX, so TextX applies as the editor applies. */\nexport function applyDocsOp<T>(doc: T, op: DocsOp): T {\n if (isNoopDocsOp(op)) return doc;\n return JSONX.apply(structuredClone(doc) as any, op as any) as T;\n}\n\n/** The inverse of `op` against the state it applied to. JSONX.invertWithDoc MUTATES its op: invert a copy (C0). */\nexport function invertDocsOp(op: DocsOp, preDoc: unknown): DocsOp {\n if (isNoopDocsOp(op)) return null;\n return JSONX.invertWithDoc(structuredClone(op) as any, preDoc as any) as DocsOp;\n}\n\n/** Part of `proto` (§6.4): Univer 1.0.4 + this transformer, rules R1–R6. */\nexport const DOCS_TRANSFORM_VERSION = \"univer-1.0.4+docs-ot-r6\";\n","/**\n * The canonical Docs state hash (COLLAB-DESIGN §7.2; C0 item 6, `spikes/c0-collab/lib.mjs`).\n *\n * SHA-256 of the canonical snapshot: keys sorted, empty values dropped, the unit id and seat-local fields\n * removed (revision counter, collab stamps, layout state, selections), adjacent equal text runs merged, split\n * pieces of one custom range or decoration folded, and `paragraphId` dropped (Univer's TextX.apply mints a\n * random one per seat, C0 surprise 3). Header, footer and note bodies get the same rules.\n *\n * Two seats with equal content hash equal; one character more hashes differently. Browser and Node: the\n * digest is Web Crypto's.\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- snapshot JSON */\n\n/** Never content: the collab stamps, revision counters, seat-local view state. */\nexport const DOC_LOCAL_KEYS = [\"rev\", \"__matrxCollabCovered\", \"__collab\", \"disabled\", \"layoutState\", \"textRanges\", \"selections\"];\n\nfunction sortDeep(v: any): any {\n if (Array.isArray(v)) return v.map(sortDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v).sort()) {\n const x = v[k];\n if (x === undefined || x === null) continue;\n if (Array.isArray(x) && x.length === 0) continue;\n if (x && typeof x === \"object\" && !Array.isArray(x) && Object.keys(x).length === 0) continue;\n out[k] = sortDeep(x);\n }\n return out;\n }\n return v;\n}\n\nconst sameTs = (a: unknown, b: unknown) => JSON.stringify(sortDeep(a ?? {})) === JSON.stringify(sortDeep(b ?? {}));\n\nfunction canonicalRuns(runs: any[] | undefined): any[] {\n const out: any[] = [];\n for (const r of [...(runs ?? [])].sort((x, y) => x.st - y.st)) {\n if (r.ed <= r.st) continue;\n const ts = sortDeep(r.ts ?? {});\n if (Object.keys(ts).length === 0) continue;\n const last = out[out.length - 1];\n if (last && last.ed === r.st && sameTs(last.ts, ts)) last.ed = r.ed;\n else out.push({ st: r.st, ed: r.ed, ts });\n }\n return out;\n}\n\nfunction foldPieces(items: any[] | undefined, keyOf: (it: any) => string): any[] {\n const groups = new Map<string, any[]>();\n for (const it of items ?? []) {\n const k = keyOf(it);\n const g = groups.get(k) ?? [];\n g.push(it);\n groups.set(k, g);\n }\n const out: any[] = [];\n for (const list of groups.values()) {\n list.sort((a, b) => a.startIndex - b.startIndex);\n let cur: any = null;\n for (const it of list) {\n if (cur && cur.endIndex + 1 >= it.startIndex) cur.endIndex = Math.max(cur.endIndex, it.endIndex);\n else {\n if (cur) out.push(cur);\n cur = { ...it };\n }\n }\n if (cur) out.push(cur);\n }\n return out;\n}\nconst rootId = (id: unknown) => String(id).split(\"$\")[0];\n\nfunction canonicalBody(body: any): any {\n if (!body) return body;\n const b = { ...body };\n b.textRuns = canonicalRuns(b.textRuns);\n if (Array.isArray(b.paragraphs)) b.paragraphs = b.paragraphs.map(({ paragraphId: _p, ...p }: any) => p);\n b.customRanges = foldPieces(b.customRanges, (r) => JSON.stringify([rootId(r.rangeId), r.rangeType, sortDeep(r.properties ?? {})])).map((r) => ({\n ...r,\n rangeId: rootId(r.rangeId),\n }));\n b.customDecorations = foldPieces(b.customDecorations, (d) => JSON.stringify([d.id, d.type]));\n for (const k of [\"paragraphs\", \"customRanges\", \"customBlocks\", \"tables\", \"sectionBreaks\", \"customDecorations\"]) {\n if (Array.isArray(b[k])) {\n b[k] = [...b[k]].sort(\n (x: any, y: any) =>\n (x.startIndex ?? 0) - (y.startIndex ?? 0) ||\n String(x.rangeId ?? x.blockId ?? x.tableId ?? \"\").localeCompare(String(y.rangeId ?? y.blockId ?? y.tableId ?? \"\")),\n );\n }\n }\n return b;\n}\n\n/** The canonical Docs snapshot: content only, keys sorted, runs normalised, local fields removed. */\nexport function canonicalDocsSnapshot(snapshot: unknown): unknown {\n const s = structuredClone(snapshot ?? {}) as any;\n delete s.id;\n for (const k of DOC_LOCAL_KEYS) delete s[k];\n s.body = canonicalBody(s.body);\n for (const seg of [\"headers\", \"footers\", \"notes\"]) {\n if (!s[seg]) continue;\n for (const id of Object.keys(s[seg])) s[seg][id] = { ...s[seg][id], body: canonicalBody(s[seg][id].body) };\n }\n return sortDeep(s);\n}\n\n/** The canonical form as the string the hash digests (tests compare these directly). */\nexport const canonicalDocsString = (snapshot: unknown): string => JSON.stringify(canonicalDocsSnapshot(snapshot));\n\n/** SHA-256 hex of the canonical snapshot (§7.2). */\nexport async function docsStateHash(snapshot: unknown): Promise<string> {\n const bytes = new TextEncoder().encode(canonicalDocsString(snapshot));\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * Ids every seat agrees on for a snapshot that lacks them (C0 surprise 5): a raw snapshot (an import, markdown)\n * loaded on two seats would otherwise get two random `sectionId`s / `paragraphId`s. Missing ids become\n * positional ones; ids already present are kept. Applied to every snapshot a room loads.\n */\nexport function stampDeterministicIds<T>(snapshot: T): T {\n const s = structuredClone(snapshot) as any;\n const stamp = (body: any, scope: string) => {\n if (!body) return;\n for (const p of body.paragraphs ?? []) if (!p.paragraphId) p.paragraphId = `p_${scope}${p.startIndex}`;\n for (const sb of body.sectionBreaks ?? []) if (!sb.sectionId) sb.sectionId = `s_${scope}${sb.startIndex}`;\n };\n stamp(s?.body, \"\");\n for (const seg of [\"headers\", \"footers\", \"notes\"]) for (const id of Object.keys(s?.[seg] ?? {})) stamp(s[seg][id]?.body, `${id}_`);\n return s as T;\n}\n","/**\n * The Docs co-editing room on the ordered log (COLLAB-DESIGN §6, unit C3): the `OpDocumentAdapter` for\n * `openOpSession` over a document's editors, plus saves, restore and the saver choice.\n *\n * - CAPTURE (§6.3). The document model hands over every local `doc.mutation.rich-text-editing` with the applied\n * params (the handler's own rewrite, C0 surprise 6), the pre-state cloned in `beforeCommandExecuted`, and the\n * outermost command id. `onlyLocal` / `fromCollab` never arrive here (the model filters them). Only `segmentId`\n * and `actions` travel; the inverse is computed from the APPLIED actions on a COPY (`invertWithDoc` mutates its\n * op). Each mutation goes to the session as it happens, so a remote apply can never land between a local\n * mutation and its hand-over; the command id rides along as the change's label.\n * - APPLY (§6.7). `syncExecuteCommand(id, { unitId: own, segmentId, actions, textRanges: null,\n * noNeedSetTextRange: true }, { onlyLocal: true, fromCollab: true })` through the model (every view of the\n * document in this tab). A throw, `false`, or actions the handler emptied fail the apply: the session rebuilds,\n * never skips. While an IME composition is open, remote applies QUEUE (acks continue); a local op captured\n * meanwhile is rebased over the queue (`L' = T(L, Q, 'left')`, `Q' = T(Q, L, 'right')`), and the queue drains\n * at `compositionend`.\n * - UNDO (§6.9). Each applied remote op rebases every stored undo and redo item of this seat\n * (`T(item, R1, 'left')`); `textRanges` and `layoutState` are stripped from rebased items; an item whose rebase\n * is a barrier, throws or comes back empty is dropped. Undo therefore only ever reverts this person's changes.\n * - SAVES (§7.3). Only a quiet seat whose hash matches every peer at its rev saves, and only the chosen saver\n * (the lowest client id among seats publishing a quiet hash) saves on its own; a manual save always tries.\n * - RESTORE (§20). A whole-document replace goes through `collab_replace`: the snapshot is loaded into this seat's\n * editor first, so the stored snapshot and its hash are the Univer-normalised form every seat will load.\n */\nimport type {\n OpDocumentAdapter,\n OpPresence,\n OpSession,\n OpSessionIncident,\n OpSessionNotice,\n OpSessionStatus,\n OpTransport,\n} from \"@ai-matrx/data/realtime/collab\";\nimport { isOpBarrier, openOpSession } from \"@ai-matrx/data/realtime/collab\";\n\nimport { canonicalDocsString, docsStateHash, stampDeterministicIds } from \"./state-hash\";\nimport {\n composeDocsOps,\n DOCS_TRANSFORM_VERSION,\n invertDocsOp,\n isNoopDocsOp,\n normalizeDocsOp,\n transformDocsOp,\n type DocsOp,\n} from \"./transform\";\n\nexport const RICH_TEXT_EDITING = \"doc.mutation.rich-text-editing\";\n\n/**\n * The room's protocol (§6.4): Univer 1.0.4 + transformer `DOCS_TRANSFORM_VERSION`. Any Univer or transformer\n * change raises it; a room at another proto opens read-only for this build.\n */\nexport const DOCS_COLLAB_PROTO = 1;\n\n/** One local mutation as the document model hands it over. */\nexport interface DocsLocalMutation {\n id: string;\n params: unknown;\n /** The document before this mutation (cloned in `beforeCommandExecuted`), when the view could supply it. */\n pre: unknown | null;\n /** The outermost command this mutation belongs to (the depth tracker with its try/finally guard). */\n cmd: string | null;\n /** Whether the mutation changes what a snapshot stores. */\n content: boolean;\n}\n\n/** What the document model lends the room (implemented by `DocumentModel`). */\nexport interface DocsOtPort {\n onLocal(listener: (m: DocsLocalMutation) => void): () => void;\n /** Apply one committed mutation to every view of the document; throws when any view could not. */\n applyRemote(id: string, params: Record<string, unknown>): void;\n /** The document as the editor holds it now (`doc.save()`), or null when no view is mounted. */\n snapshot(): unknown | null;\n /** Replace the document in every view (and the kept editor). */\n load(snapshot: unknown): void;\n /** Univer's undo/redo service of each mounted view and the unit it holds. */\n undoTargets(): Array<{ service: unknown; unitId: string }>;\n /** Ask for a save (the record's one coalesced save). */\n markDirty(): void;\n}\n\nexport type DocsOtNotice =\n | OpSessionNotice<DocsOp>\n | { kind: \"not_shared\"; mutationId: string }\n | { kind: \"not_live\" };\n\nexport interface OpenDocsOtRoomOptions {\n port: DocsOtPort;\n transport: OpTransport;\n clientId: string;\n presence?: OpPresence;\n /** `collab_replace` for this room (restore, whole import). */\n replace: (req: { snapshot: unknown; stateHash: string; clientId: string }) => Promise<{ rev: number; ref: string }>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n /** Watch IME composition here (default: `document`). */\n compositionTarget?: Pick<Document, \"addEventListener\" | \"removeEventListener\"> | null;\n}\n\nexport interface DocsOtRoom {\n session: OpSession<DocsOp>;\n /** The record's save: a checkpoint at a quiet point (§7.3). False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace` (§20). */\n replace(snapshot: unknown): Promise<void>;\n /** This seat is the one that saves on its own. */\n isSaver(): boolean;\n stop(): void;\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────────────────────────────\n\n/** Top-level keys an op descends into (`[\"body\", …]` or `[[\"body\", …], [\"headers\", …]]`). */\nfunction branches(op: DocsOp): unknown[][] {\n if (!Array.isArray(op) || op.length === 0) return [];\n return Array.isArray(op[0]) ? (op as unknown[][]) : [op as unknown[]];\n}\nconst touchesPageSetup = (op: DocsOp) => branches(op).some((b) => b[0] === \"documentStyle\");\n\n/** The segment a branch edits: `[\"headers\", id, \"body\", …]` → id; the body → \"\". */\nfunction segmentOf(branch: unknown[]): string {\n return (branch[0] === \"headers\" || branch[0] === \"footers\") && typeof branch[1] === \"string\" ? branch[1] : \"\";\n}\n\ninterface UndoItem {\n unitID?: string;\n undoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n redoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n}\ninterface UndoServiceInternals {\n _undoStacks?: Map<string, UndoItem[]>;\n _redoStacks?: Map<string, UndoItem[]>;\n}\n\n/** The Univer 1.0.4 fields the undo rebase reads; a forcing test fails if they move (Univer is pinned). */\nexport function undoStacksOf(service: unknown): { undo: Map<string, UndoItem[]>; redo: Map<string, UndoItem[]> } | null {\n const s = service as UndoServiceInternals | null;\n if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;\n return { undo: s._undoStacks, redo: s._redoStacks };\n}\n\n/** §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped. */\nexport function rebaseUndoStack(items: UndoItem[], remote: DocsOp): number {\n let dropped = 0;\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!;\n let ok = true;\n for (const list of [item.undoMutations, item.redoMutations]) {\n for (const m of list ?? []) {\n if (m.id !== RICH_TEXT_EDITING) continue;\n try {\n if (touchesPageSetup(m.params.actions as DocsOp) && touchesPageSetup(remote)) throw new Error(\"page setup\");\n const r = transformDocsOp(m.params.actions as DocsOp, remote, \"left\");\n if (isNoopDocsOp(r.op)) ok = false;\n else {\n m.params = { ...m.params, actions: r.op };\n delete m.params.textRanges;\n delete m.params.layoutState;\n }\n } catch {\n ok = false;\n }\n }\n }\n if (!ok) {\n items.splice(i, 1);\n dropped++;\n }\n }\n return dropped;\n}\n\n// ── the room ──────────────────────────────────────────────────────────────────────────────────────────\n\nexport function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom {\n const { port } = o;\n let session: OpSession<DocsOp> | null = null;\n let composing = false;\n /** Remote ops held while an IME composition is open, already rebased over local composition ops. */\n let queue: DocsOp[] = [];\n const drainWaiters: Array<() => void> = [];\n\n const notice = (n: DocsOtNotice) => {\n try {\n o.onNotice?.(n);\n } catch (err) {\n console.warn(\"[docs-ot] notice handler failed\", err);\n }\n };\n\n const applyNow = (op: DocsOp) => {\n for (const b of branches(op)) {\n const params: Record<string, unknown> = { segmentId: segmentOf(b), actions: b };\n port.applyRemote(RICH_TEXT_EDITING, params);\n }\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n if (!stacks) continue;\n for (const m of [stacks.undo, stacks.redo]) {\n const items = m.get(t.unitId);\n if (items?.length) rebaseUndoStack(items, op);\n }\n }\n port.markDirty();\n };\n\n const drain = () => {\n const held = queue;\n queue = [];\n try {\n for (const op of held) applyNow(op);\n } catch (err) {\n console.warn(\"[docs-ot] a held remote edit failed after composition; reloading this seat\", err);\n session?.rebuild(\"ime_drain_failed\");\n }\n for (const w of drainWaiters.splice(0)) w();\n };\n\n const adapter: OpDocumentAdapter<DocsOp> = {\n version: DOCS_TRANSFORM_VERSION,\n transform(x, y, side) {\n // §18: page setup replaces section breaks by array index; a barrier against every family, itself included.\n if (x != null && y != null && (touchesPageSetup(x) || touchesPageSetup(y))) return { barrier: true, reason: \"page_setup\" };\n const r = transformDocsOp(x, y, side);\n return { op: isNoopDocsOp(r.op) ? null : r.op, lost: r.lost };\n },\n compose: (a, b) => composeDocsOps(a, b),\n isNoop: (op) => isNoopDocsOp(op),\n encode: (op) => [{ cmd: \"docs.edit\", mutations: [{ id: RICH_TEXT_EDITING, params: { segmentId: \"\", actions: op } }] }],\n decode(groups) {\n let op: DocsOp = null;\n for (const g of groups) {\n for (const m of g.mutations) {\n if (m.id !== RICH_TEXT_EDITING) throw new Error(`a Docs room cannot apply ${m.id}`);\n op = composeDocsOps(op, (m.params as { actions?: DocsOp }).actions ?? null);\n }\n }\n return op;\n },\n apply(op) {\n if (isNoopDocsOp(op)) return true;\n if (composing) {\n queue.push(op);\n return true;\n }\n applyNow(op);\n return true;\n },\n async load(snapshot) {\n const next = stampDeterministicIds(snapshot ?? {});\n queue = [];\n const current = port.snapshot();\n if (current && canonicalDocsString(current) === canonicalDocsString(next)) return;\n port.load(next);\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n stacks?.undo.delete(t.unitId);\n stacks?.redo.delete(t.unitId);\n }\n },\n snapshot: () => port.snapshot(),\n async hash() {\n if (composing || queue.length) {\n await new Promise<void>((resolve) => {\n drainWaiters.push(resolve);\n setTimeout(resolve, 5000);\n });\n }\n return docsStateHash(port.snapshot());\n },\n };\n\n const onLocal = (m: DocsLocalMutation) => {\n if (!session) return;\n if (m.id !== RICH_TEXT_EDITING) {\n if (!m.content) return;\n // §6.3: an id without an allowlist never travels. Say so and put this seat back on the shared document.\n notice({ kind: \"not_shared\", mutationId: m.id });\n session.rebuild(`not_shared:${m.id}`);\n return;\n }\n const p = (m.params ?? {}) as { actions?: DocsOp };\n const applied = p.actions ?? null;\n if (isNoopDocsOp(applied)) return;\n let op: DocsOp = normalizeDocsOp(structuredClone(applied));\n let inverse: DocsOp | undefined;\n try {\n inverse = m.pre != null ? invertDocsOp(applied, m.pre) : undefined;\n } catch {\n inverse = undefined;\n }\n if (queue.length) {\n // the editor does not hold the queued remote ops yet: rebase this edit over them, and them over it\n inverse = undefined;\n const next: DocsOp[] = [];\n for (const q of queue) {\n const l2 = adapter.transform(op, q, \"left\");\n const q2 = adapter.transform(q, op, \"right\");\n if (isOpBarrier(l2) || isOpBarrier(q2)) {\n queue = [];\n session.rebuild(\"ime_barrier\");\n return;\n }\n op = l2.op;\n next.push(q2.op);\n }\n queue = next.filter((q) => !isNoopDocsOp(q));\n if (isNoopDocsOp(op)) return;\n }\n if (!session.local(op, { ...(inverse !== undefined ? { inverse } : {}), label: m.cmd ?? RICH_TEXT_EDITING })) notice({ kind: \"not_live\" });\n };\n\n const unsubLocal = port.onLocal(onLocal);\n const target = o.compositionTarget === undefined ? (typeof document !== \"undefined\" ? document : null) : o.compositionTarget;\n const onStart = () => {\n composing = true;\n };\n const onEnd = () => {\n composing = false;\n // Univer emits the composition's last mutation in the same task as compositionend: drain after it\n setTimeout(() => {\n if (!composing) drain();\n }, 0);\n };\n target?.addEventListener(\"compositionstart\", onStart, true);\n target?.addEventListener(\"compositionend\", onEnd, true);\n\n session = openOpSession<DocsOp>({\n transport: o.transport,\n adapter,\n proto: DOCS_COLLAB_PROTO,\n clientId: o.clientId,\n ...(o.presence ? { presence: o.presence } : {}),\n onNotice: (n) => notice(n),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n\n const isSaver = () => {\n if (!o.presence) return true;\n return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);\n };\n\n return {\n session,\n isSaver,\n async write(reason) {\n if (!session) return false;\n if (reason !== \"manual\" && !isSaver()) return false;\n const out = await session.save();\n if (out.saved) return true;\n if (out.reason === \"not_quiet\" || out.reason === \"changed\") setTimeout(() => port.markDirty(), 1500);\n return false;\n },\n async replace(snapshot) {\n port.load(stampDeterministicIds(snapshot));\n const loaded = port.snapshot();\n if (!loaded) throw new Error(\"The document is not open in this tab.\");\n const stateHash = await docsStateHash(loaded);\n await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });\n },\n stop() {\n unsubLocal();\n target?.removeEventListener(\"compositionstart\", onStart, true);\n target?.removeEventListener(\"compositionend\", onEnd, true);\n session?.close();\n },\n };\n}\n","/**\n * A cloud document's co-editing room on the ordered log (COLLAB-DESIGN §6, §19; unit C3), assembled from the\n * configured docs host: the `udt_document_snapshots` store, the C1 doors over the host's Supabase client, the\n * private `collab:<id>` frames on the app's one realtime manager, and Yjs awareness for presence only (who is\n * here plus `quiet_hash`; no content travels there).\n *\n * The FLIP is per room (§12.2): a document whose room exists always opens on the ordered log; a document with\n * no room opens one only when the host's `collab.ot_rooms` knob says so (`all`, or `new` for a document never\n * saved). Everything else keeps the 0.6 relay. The host reads the knob (host config lives in the app).\n */\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport {\n awarenessOpPresence,\n collabReplace,\n collabRoomExists,\n SupabaseYjsProvider,\n supabaseOpTransport,\n type AwarenessState,\n type CollabRpcClient,\n type OpSessionIncident,\n type OpSessionStatus,\n} from \"@ai-matrx/data/realtime/collab\";\n\nimport { openDocsOtRoom, type DocsOtNotice } from \"../univer/collab/docs-ot/room\";\nimport type { DocumentAwareness, DocumentOtFactory } from \"./document-model\";\nimport { getLatestDocumentSnapshot, saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\n/** `collab.ot_rooms` (§12.2): which documents without a room open one. */\nexport type OtRoomsKnob = \"off\" | \"new\" | \"all\";\n\nconst db = () => getDocsHost().getSupabase() as unknown as CollabRpcClient;\n\nasync function loadSnapshotRow(documentId: string, ref: string): Promise<unknown> {\n if (ref === \"none\") {\n const res = await getLatestDocumentSnapshot(documentId);\n if (!res.success) throw new Error(res.error);\n return res.data?.snapshot ?? null;\n }\n const { data, error } = await getDocsHost()\n .getSupabase()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"snapshot\")\n .eq(\"id\", ref)\n .maybeSingle();\n if (error) throw new Error(error.message);\n if (!data) throw new Error(`The saved version ${ref} of this document is missing.`);\n return (data as { snapshot?: unknown }).snapshot ?? null;\n}\n\n/** Whether this document opens on the ordered log: its room exists, or the knob opens one. */\nexport async function documentUsesOrderedRoom(documentId: string, knob: OtRoomsKnob, isNewDocument: () => Promise<boolean>): Promise<boolean> {\n try {\n if (await collabRoomExists(db(), documentId)) return true;\n } catch (err) {\n console.warn(\"[document] could not ask whether this document has a co-editing room; opening the relay room\", err);\n return false;\n }\n if (knob === \"all\") return true;\n if (knob === \"new\") return isNewDocument();\n return false;\n}\n\nfunction pickColor(uid: string): string {\n const palette = [\"#ef4444\", \"#f59e0b\", \"#10b981\", \"#3b82f6\", \"#8b5cf6\", \"#ec4899\", \"#14b8a6\", \"#f97316\"];\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return palette[Math.abs(h) % palette.length] ?? \"#ec4899\";\n}\n\nexport interface DocumentOtFactoryOptions {\n documentId: string;\n uid: string;\n /** One per open tab; never reused. */\n clientId: string;\n displayName?: string;\n readAntiEntropyIntervalMs?: () => Promise<number>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\n/** The `DocumentModel.startOtRoom` factory for one document. */\nexport function documentOtFactory(o: DocumentOtFactoryOptions): DocumentOtFactory {\n return async (port, onAwareness) => {\n // §7.4 / C0 surprise 5: a room's first checkpoint must be a real, Univer-normalised snapshot. A document never\n // saved gets this seat's mounted document saved first, so every seat boots from the same ids.\n const latest = await getLatestDocumentSnapshot(o.documentId);\n if (!latest.success) throw new Error(latest.error);\n if (!latest.data) {\n const mounted = port.snapshot();\n if (mounted) {\n const saved = await saveDocumentSnapshot({ documentId: o.documentId, snapshot: mounted, origin: \"autosave\" });\n if (!saved.success) throw new Error(saved.error);\n }\n }\n\n const doc = new Y.Doc();\n const awareness = new Awareness(doc);\n awareness.setLocalState({ uid: o.uid, clientId: o.clientId, name: o.displayName ?? o.uid.slice(0, 8), color: pickColor(o.uid), ts: Date.now() });\n const publishAwareness = () =>\n onAwareness({ states: new Map(awareness.getStates() as Map<number, AwarenessState>), selfUid: o.uid } satisfies DocumentAwareness);\n awareness.on(\"change\", publishAwareness);\n const provider = new SupabaseYjsProvider({\n workbookId: o.documentId,\n channelPrefix: \"document\",\n clientId: o.clientId,\n doc,\n awareness,\n ...(o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}),\n });\n await provider.connect();\n publishAwareness();\n\n const client = db();\n const room = openDocsOtRoom({\n port,\n clientId: o.clientId,\n presence: awarenessOpPresence(awareness),\n transport: supabaseOpTransport({\n client,\n roomId: o.documentId,\n kind: \"univer_doc\",\n store: {\n loadSnapshot: (ref) => loadSnapshotRow(o.documentId, ref),\n async writeSnapshot(snapshot) {\n const res = await saveDocumentSnapshot({ documentId: o.documentId, snapshot, origin: \"autosave\" });\n if (!res.success) throw new Error(res.error);\n return res.data.id;\n },\n },\n }),\n replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.documentId, snapshot, stateHash, origin: \"restore\", clientId }),\n ...(o.onNotice ? { onNotice: o.onNotice } : {}),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n await room.session.ready;\n return {\n isSaver: () => room.isSaver(),\n write: (reason) => room.write(reason),\n replace: (snapshot) => room.replace(snapshot),\n stop: () => {\n room.stop();\n awareness.off(\"change\", publishAwareness);\n provider.disconnect();\n awareness.destroy();\n doc.destroy();\n },\n };\n };\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\n/**\n * An independent copy of a document: its own row, with the latest snapshot copied over, so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":"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","names":["univerMerge","Y","import_collab","Y","import_awareness","import_collab","db","pickColor"]}
|
|
1
|
+
{"version":3,"sources":["../src/univer/collab/index.ts","../src/univer/collab/WorkbookCollabSession.ts","../src/univer/collab/covered.ts","../src/univer/collab/docs-ot/transform.ts","../src/univer/collab/docs-ot/state-hash.ts","../src/univer/collab/docs-ot/room.ts","../src/docs/document-ot-room.ts","../src/docs/document-service.ts","../src/docs/ports.ts"],"sourcesContent":["/**\n * The collab session shared by `/sheets` and `/docs` (was matrx-frontend `features/workbooks/collab`): the\n * Univer <-> Yjs bridge. It owns the Yjs import, so it is loaded on demand (`import()` when a workbook\n * or document goes live). The snapshot-insert subscription hook is its own entry,\n * `@ai-matrx/office/univer/realtime`, so a static import of the hook never carries Yjs into the editor\n * chunk. A transitional subpath, like `./univer`: it goes internal when the editors move.\n */\nexport * from \"./WorkbookCollabSession\";\nexport * from \"./docs-ot\";\nexport * from \"../../docs/document-ot-room\";\n","/**\n * WorkbookCollabSession — the Univer ↔ Yjs bridge.\n *\n * Subscribes to Univer's public `commandService.onMutationExecutedForCollab`\n * hook for local mutations and pushes them onto a `Y.Array<MutationOp>` shared\n * via `SupabaseYjsProvider`. Inbound Yjs updates produce `IMutationInfo` ops\n * that are applied through `commandService.syncExecuteCommand` with the\n * `fromCollab` execution option flagged so the outbound listener short-\n * circuits and we don't echo our own apply.\n *\n * See `FEATURE.md` in this directory for the architecture, the \"do NOT use\n * the Pro preset\" verdict, and the host-election rule. This class is the\n * runtime side of that plan.\n *\n * Lifecycle:\n * - constructor: wire references, no side effects\n * - start(): create Y.Doc + Awareness, instantiate provider, subscribe to\n * command stream, subscribe to Yjs Array observer\n * - stop(): detach all listeners, dispose provider\n *\n * The session is one-shot per workbook open. Reload = stop() + new instance.\n */\n\"use client\";\n\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport { electCollabHost, remoteOriginOf, REMOTE_PARAM_TAG } from \"@ai-matrx/data/realtime/collab\";\n\nexport { COLLAB_COVERED_KEY, stampCovered, takeCovered } from \"./covered\";\n\n/**\n * Structural transport contract. `SupabaseYjsProvider` satisfies it in\n * production; the verification harness injects an in-memory loopback\n * transport through the same seam. Keeping this structural (not the concrete\n * class) is what makes the session testable without network.\n */\nexport type CollabProviderLike = {\n connect(): Promise<void>;\n disconnect(): void;\n ready(): Promise<void>;\n /**\n * True when this is the only holder of its room in this tab allowed to act as\n * host (autosave). Same-tab holders share one client id and one uid, so\n * awareness cannot tell them apart. Absent = a lone holder = leader.\n */\n isTabLeader?(): boolean;\n};\n\n// Univer types are loose at the public hook boundary; we narrow with a\n// structural interface so we don't have to import the full Univer surface.\ntype MutationParams = Record<string, unknown> | unknown[] | null;\n\nexport type CollabMutationInfo = {\n id: string;\n type: number; // CommandType.MUTATION = 2 in Univer's enum\n params: MutationParams;\n /** Who made it (the person's uid), so a peer can tell its own other tab's edit from a stranger's. */\n uid?: string;\n /**\n * The entry's identity in the room (`<clientId>:<seq>`). A saved snapshot names the entries it holds\n * (`stampCovered`), so a seat that boots from that snapshot never replays them a second time.\n */\n eid?: string;\n};\n\n/**\n * What a seat booted from: the saved snapshot's row id and the room entries that snapshot already holds.\n * The session never replays a covered entry, and a seat that booted from an OLDER snapshot than the\n * room's newest checkpoint first reloads (the entries that checkpoint trimmed are only in that snapshot).\n */\nexport type CollabBase = {\n snapshotId: () => string | null;\n covered: () => ReadonlySet<string>;\n /** Show the newest saved snapshot (and make it the base). */\n reload: () => Promise<void>;\n};\n\ntype ExecuteOptions = {\n /** Per-Univer convention: when true, the command runs locally only and is\n * NOT broadcast to other plugins. We set this on inbound-apply so the\n * subsequent onMutationExecutedForCollab does NOT re-fire on our peer. */\n onlyLocal?: boolean;\n fromCollab?: boolean;\n};\n\nexport type CommandServiceLike = {\n onMutationExecutedForCollab(\n listener: (info: CollabMutationInfo, options?: ExecuteOptions) => void,\n ): {\n dispose: () => void;\n };\n syncExecuteCommand(\n id: string,\n params: MutationParams,\n options?: ExecuteOptions,\n ): unknown;\n};\n\nexport type WorkbookCollabSessionOptions = {\n workbookId: string;\n uid: string;\n clientId: string;\n commandService: CommandServiceLike;\n /** Factory so this file does not statically depend on the provider. */\n makeProvider: (args: {\n workbookId: string;\n clientId: string;\n doc: Y.Doc;\n awareness: Awareness;\n /** Wire to the provider so a host handover re-runs the election. */\n onLeaderChange: () => void;\n }) => CollabProviderLike;\n /** Called when the awareness set changes (peers join / leave / move cursor). */\n onAwarenessChange?: (awareness: Awareness) => void;\n /**\n * A peer replaced the whole content (history restore, Google update): the\n * newest saved snapshot is the content now. Reload it in place; never\n * re-announce. See `announceReplaced`.\n */\n onReplaced?: (snapshotId: string) => void;\n /**\n * TRUE when the room is bound to a Univer DOCUMENT unit (the Docs editor): there the `doc.mutation.*`\n * stream IS the content, so it must travel. Leave unset for a workbook, where `doc.mutation.*` is the\n * in-cell editor's scratch document and never travels (see `isCellEditorScratch`).\n */\n forwardDocumentMutations?: boolean;\n /**\n * The Univer unit id this seat mounted. Each seat can mount its own unit, so a peer's mutation\n * (addressed to the SENDER's unit) is re-addressed to this one before it is applied.\n */\n unitId?: () => string | null;\n /** A peer's mutation could not be applied here: the seat says so and re-syncs; never only a console line. */\n onApplyFailed?: (mutationId: string, error: unknown) => void;\n /**\n * The saved snapshot this seat booted from. Without it a reloading seat replays every entry still in\n * the room's log on top of a snapshot that already holds them: the text shows twice, and the next save\n * stores it twice (2026-10-16).\n */\n base?: CollabBase;\n};\n\n/** What `checkpoint` writes into the room's control map: the newest saved snapshot whose entries left the log. */\ntype CheckpointSignal = { snapshotId: string; by: string };\n\n/** What `announceReplaced` writes into the room's control map. */\ntype ReplacedSignal = { snapshotId: string; by: string; nonce: string };\n\nconst MUTATIONS_ARRAY_KEY = \"mutations\";\nconst CONTROL_MAP_KEY = \"control\";\nconst REPLACED_KEY = \"replaced\";\nconst CHECKPOINT_KEY = \"checkpoint\";\n\nexport class WorkbookCollabSession {\n private readonly options: WorkbookCollabSessionOptions;\n private doc: Y.Doc | null = null;\n private awareness: Awareness | null = null;\n private provider: CollabProviderLike | null = null;\n private commandDisposer: { dispose: () => void } | null = null;\n private yArrayObserver:\n ((event: Y.YArrayEvent<CollabMutationInfo>) => void) | null = null;\n private awarenessObserver: (() => void) | null = null;\n private controlObserver: ((event: Y.YMapEvent<unknown>) => void) | null = null;\n /** >0 while this client swaps its own content: its mutations are not edits. */\n private muted = 0;\n private started = false;\n private disposed = false;\n /** Room entries this seat holds in its content: applied from a peer, or made here. */\n private readonly applied = new Set<string>();\n /** Entries without an id (a peer on an older build) are applied once, by identity. */\n private readonly appliedRefs = new WeakSet<object>();\n private seq = 0;\n /** False until this seat has seen the room's content once (the join-time check runs then). */\n private joined = false;\n /** The base is being reloaded: entries wait in the log until it is shown. */\n private reloadingBase = false;\n\n constructor(options: WorkbookCollabSessionOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n if (this.started || this.disposed) return;\n this.started = true;\n\n this.doc = new Y.Doc();\n this.awareness = new Awareness(this.doc);\n\n // Seed local awareness with the user identity. Cursor (sheetId/row/col)\n // is set later via setCursor().\n this.awareness.setLocalState({\n uid: this.options.uid,\n clientId: this.options.clientId,\n name: this.options.uid.slice(0, 8),\n color: pickColor(this.options.uid),\n sheetId: null,\n row: null,\n col: null,\n ts: Date.now(),\n });\n\n this.provider = this.options.makeProvider({\n workbookId: this.options.workbookId,\n clientId: this.options.clientId,\n doc: this.doc,\n awareness: this.awareness,\n onLeaderChange: () => {\n if (this.awareness) this.options.onAwarenessChange?.(this.awareness);\n },\n });\n\n // Subscribe to inbound Yjs array changes BEFORE connecting the provider,\n // so the initial-state replay (if any) hits our observer.\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n this.yArrayObserver = (event) => {\n // Local transactions are OUR OWN pushes from handleLocalMutation —\n // Univer already executed those mutations. Re-applying them here would\n // double-apply every local edit on the originator. Only act on\n // transactions that arrived via Y.applyUpdate (origin 'remote').\n if (event.transaction.local) return;\n if (!event.changes.delta.some((change) => Array.isArray(change.insert) && change.insert.length > 0)) return;\n this.drain();\n };\n yArray.observe(this.yArrayObserver as Parameters<typeof yArray.observe>[0]);\n\n // Awareness change passthrough.\n if (this.options.onAwarenessChange) {\n const cb = this.options.onAwarenessChange;\n this.awarenessObserver = () => {\n if (this.awareness) cb(this.awareness);\n };\n this.awareness.on(\"change\", this.awarenessObserver);\n }\n\n // Subscribe to Univer's collab-grain mutation stream.\n this.commandDisposer =\n this.options.commandService.onMutationExecutedForCollab((info, options) =>\n this.handleLocalMutation(info, options),\n );\n\n await this.provider.connect();\n await this.provider.ready();\n this.drain();\n\n // Whole-content replacement from a peer. Bound AFTER the initial sync: a\n // joiner already loaded the newest snapshot, so the signal it finds in\n // the room's state is history, not news (the editor also skips a\n // snapshot it already shows).\n if (this.disposed || !this.doc) return;\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const seen = (control.get(REPLACED_KEY) as ReplacedSignal | undefined)?.nonce ?? null;\n this.controlObserver = (event) => {\n if (event.transaction.local || !event.keysChanged.has(REPLACED_KEY)) return;\n const signal = control.get(REPLACED_KEY) as ReplacedSignal | undefined;\n if (!signal?.snapshotId || signal.nonce === seen) return;\n this.options.onReplaced?.(signal.snapshotId);\n };\n control.observe(this.controlObserver);\n }\n\n stop(): void {\n if (this.disposed) return;\n this.disposed = true;\n\n this.commandDisposer?.dispose();\n this.commandDisposer = null;\n\n if (this.doc && this.yArrayObserver) {\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n yArray.unobserve(\n this.yArrayObserver as Parameters<typeof yArray.unobserve>[0],\n );\n this.yArrayObserver = null;\n }\n\n if (this.doc && this.controlObserver) {\n this.doc.getMap<unknown>(CONTROL_MAP_KEY).unobserve(this.controlObserver);\n this.controlObserver = null;\n }\n\n if (this.awareness && this.awarenessObserver) {\n this.awareness.off(\"change\", this.awarenessObserver);\n this.awarenessObserver = null;\n }\n\n this.provider?.disconnect();\n this.provider = null;\n\n if (this.awareness) {\n this.awareness.destroy();\n this.awareness = null;\n }\n\n if (this.doc) {\n this.doc.destroy();\n this.doc = null;\n }\n }\n\n /** How many mutations the shared log holds right now. */\n logLength(): number {\n return this.doc?.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).length ?? 0;\n }\n\n /**\n * The room entries this seat's content holds RIGHT NOW. Read it in the same synchronous step as the\n * content you are about to save, and save it with that content (`stampCovered`); after the save lands,\n * pass it to `checkpoint`.\n */\n coveredNow(): string[] {\n if (!this.doc) return [];\n const covered = this.options.base?.covered();\n const out: string[] = [];\n for (const op of this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY).toArray()) {\n if (op.eid && (this.applied.has(op.eid) || covered?.has(op.eid))) out.push(op.eid);\n }\n return out;\n }\n\n /**\n * The snapshot `snapshotId` was SAVED holding `covered` (from `coveredNow`): those entries leave the\n * shared log, and the room records the snapshot as its newest checkpoint. Removal is by entry id, never\n * by position — an entry that arrived while the save was in flight is not in the snapshot and stays.\n * Only the elected saver calls this; peers receive it as a delete (never replayed).\n */\n checkpoint(snapshotId: string, covered: readonly string[]): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const drop = new Set(covered);\n const signal: CheckpointSignal = { snapshotId, by: this.options.clientId };\n this.doc.transact(() => {\n const entries = yArray.toArray();\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const eid = entries[i]?.eid;\n if (eid && drop.has(eid)) yArray.delete(i, 1);\n }\n control.set(CHECKPOINT_KEY, signal);\n });\n }\n\n /**\n * This client replaced the whole content and SAVED it as `snapshotId`.\n * One transaction empties the shared mutation log (every entry targets the\n * content that is gone — a joiner must never replay them onto the new\n * snapshot) and tells every peer to reload the newest snapshot.\n */\n announceReplaced(snapshotId: string): void {\n if (!this.doc) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const signal: ReplacedSignal = {\n snapshotId,\n by: this.options.clientId,\n nonce: `${this.options.clientId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,\n };\n this.doc.transact(() => {\n if (yArray.length > 0) yArray.delete(0, yArray.length);\n control.set(REPLACED_KEY, signal);\n control.set(CHECKPOINT_KEY, { snapshotId, by: this.options.clientId } satisfies CheckpointSignal);\n });\n }\n\n /**\n * Run `swap` (this client tearing its content down and mounting the new\n * one) without broadcasting what Univer emits while it does: those are not\n * edits, and peers reload the same snapshot themselves.\n */\n muteWhile<T>(swap: () => T): T {\n this.muted += 1;\n try {\n return swap();\n } finally {\n this.muted -= 1;\n }\n }\n\n /**\n * Update the local awareness cursor. Call this from Univer's selection\n * listener (`worksheet.onSelectionChange(...)`). Throttle at the call site\n * (~50ms is plenty); the provider broadcasts on its own debounced cycle.\n */\n setCursor(input: {\n sheetId: string | null;\n row: number | null;\n col: number | null;\n }): void {\n if (!this.awareness) return;\n const current = this.awareness.getLocalState() ?? {};\n this.awareness.setLocalState({\n ...current,\n sheetId: input.sheetId,\n row: input.row,\n col: input.col,\n ts: Date.now(),\n });\n }\n\n /**\n * Returns the deterministic host: the connected peer with the lowest uid\n * (lexicographic). Host is the only client that writes canonical snapshots.\n * No election protocol; recompute whenever awareness changes.\n */\n electHost(opts: { tabTieBreak?: boolean } = {}): { isHost: boolean; hostUid: string | null } {\n if (!this.awareness) return { isHost: false, hostUid: null };\n const states = Array.from(this.awareness.getStates().values()) as Array<\n Record<string, unknown>\n >;\n // Lowest uid wins ACROSS tabs; inside this tab only the room's tab leader\n // may be host, because every same-tab holder carries the same uid.\n const leader = this.provider?.isTabLeader?.() ?? true;\n return electCollabHost(states, this.options.uid, this.options.clientId, leader, opts.tabTieBreak ?? false);\n }\n\n // ─── internals ────────────────────────────────────────────────────────\n\n private handleLocalMutation(info: CollabMutationInfo, options?: ExecuteOptions): void {\n if (this.muted > 0) return;\n // Univer marks a mutation `onlyLocal` when every seat derives it itself (formula-engine recalculation,\n // layout results): relaying it turns every recalculation into network traffic and a logged op.\n if (options?.onlyLocal) return;\n if (!this.options.forwardDocumentMutations && isCellEditorScratch(info)) return;\n // Inbound-applied mutations re-fire this listener because Univer's\n // syncExecuteCommand legitimately processes them through the full\n // pipeline. Skip by sniffing the sentinel we stamped on apply.\n if (\n info.params &&\n typeof info.params === \"object\" &&\n !Array.isArray(info.params) &&\n remoteOriginOf(info.params) !== null\n ) {\n return;\n }\n if (!this.doc) return;\n\n // Normalize params through a JSON round-trip BEFORE pushing into Yjs.\n // Yjs (and the Broadcast transport) only carry JSON-encodable values;\n // Univer types its mutation params as \"serializable\" but JS objects can\n // smuggle Date / Map / class instances through that promise. The\n // round-trip makes the failure mode deterministic: a non-encodable\n // mutation is skipped with a warning instead of corrupting the shared\n // doc or desyncing peers mid-session. What we push here is byte-for-byte\n // what remote peers will apply, so local-apply == remote-apply.\n let safeParams: MutationParams;\n try {\n safeParams =\n info.params === undefined || info.params === null\n ? null\n : stripSenderView(JSON.parse(JSON.stringify(info.params)) as MutationParams);\n } catch (err) {\n console.warn(\n `[collab] skipping non-serializable mutation \"${info.id}\" — peers will not receive it`,\n err,\n );\n return;\n }\n\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const eid = `${this.options.clientId}:${++this.seq}`;\n this.applied.add(eid);\n // An edit made here is made on what this seat shows: the join-time check is over.\n this.joined = true;\n yArray.push([{ id: info.id, type: info.type, params: safeParams, uid: this.options.uid, eid }]);\n }\n\n /**\n * Apply every log entry this seat's content does not hold yet, in the log's order. The first time the\n * room shows content, the join-time check runs: a seat that booted from a snapshot OLDER than the\n * room's newest checkpoint reloads first (the entries that checkpoint trimmed exist only in it).\n */\n private drain(): void {\n if (!this.doc || this.disposed || this.reloadingBase) return;\n const yArray = this.doc.getArray<CollabMutationInfo>(MUTATIONS_ARRAY_KEY);\n const entries = yArray.toArray();\n const base = this.options.base;\n if (!this.joined) {\n const control = this.doc.getMap<unknown>(CONTROL_MAP_KEY);\n const checkpoint = control.get(CHECKPOINT_KEY) as CheckpointSignal | undefined;\n if (entries.length === 0 && !checkpoint) return;\n this.joined = true;\n if (base && checkpoint?.snapshotId && checkpoint.snapshotId !== base.snapshotId()) {\n this.reloadingBase = true;\n void base\n .reload()\n .catch((error: unknown) => {\n console.warn(\"[collab] could not load the newest saved version on joining\", error);\n this.options.onApplyFailed?.(\"collab.join\", error);\n })\n .finally(() => {\n this.reloadingBase = false;\n this.drain();\n });\n return;\n }\n }\n const covered = base?.covered();\n for (const op of entries) {\n if (op.eid) {\n if (this.applied.has(op.eid) || covered?.has(op.eid)) continue;\n this.applied.add(op.eid);\n } else {\n if (this.appliedRefs.has(op)) continue;\n this.appliedRefs.add(op);\n }\n this.applyRemoteMutation(op);\n }\n }\n\n private applyRemoteMutation(op: CollabMutationInfo): void {\n // Wrap params with the sentinel so handleLocalMutation knows not to\n // echo the apply back into Yjs.\n const ownUnit = this.options.unitId?.() ?? null;\n const taggedParams: MutationParams =\n op.params && typeof op.params === \"object\" && !Array.isArray(op.params)\n ? {\n ...(op.params as Record<string, unknown>),\n ...(ownUnit && typeof (op.params as { unitId?: unknown }).unitId === \"string\" ? { unitId: ownUnit } : {}),\n [REMOTE_PARAM_TAG]: op.uid ?? true,\n }\n : op.params;\n\n try {\n this.options.commandService.syncExecuteCommand(op.id, taggedParams, {\n onlyLocal: true,\n fromCollab: true,\n });\n } catch (err) {\n // One unappliable op (already baked into the loaded snapshot, or a\n // stale target) must not throw into the realtime channel handler and\n // abort the rest of the catch-up. Said, never swallowed.\n console.warn(\n `[collab] could not apply remote mutation \"${op.id}\" — skipped`,\n err,\n );\n this.options.onApplyFailed?.(op.id, err);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────────────────\n\n/**\n * A workbook holds no Univer DOCUMENT units of its own: the `doc.mutation.*` stream a sheet emits is\n * the in-cell editor's scratch document (typing into a cell). The finished text reaches the sheet as\n * `sheet.mutation.set-range-values`, which does travel. Sending the scratch edits made a joiner replay\n * them against an editor unit it does not have (\"Trying to overwrite value at key\").\n */\nexport const SENDER_VIEW_PARAMS: readonly string[] = [\"layoutState\", \"textRanges\", \"prevTextRanges\"];\n\n/**\n * Remove what describes the SENDER'S view (the editor's layout cache, caret and selection ranges) from a\n * mutation's params before it travels: a receiver would otherwise restore the sender's layout and caret.\n * Everything else (the content-changing `actions`, ids, addresses) is left as is.\n */\nexport function stripSenderView(params: MutationParams): MutationParams {\n if (!params || typeof params !== \"object\" || Array.isArray(params)) return params;\n const out: Record<string, unknown> = { ...params };\n for (const key of SENDER_VIEW_PARAMS) delete out[key];\n return out;\n}\n\nexport function isCellEditorScratch(info: Pick<CollabMutationInfo, \"id\">): boolean {\n return typeof info.id === \"string\" && info.id.startsWith(\"doc.mutation.\");\n}\n\nconst CURSOR_PALETTE = [\n \"#3b82f6\", // blue\n \"#10b981\", // emerald\n \"#f59e0b\", // amber\n \"#ef4444\", // red\n \"#8b5cf6\", // violet\n \"#06b6d4\", // cyan\n \"#ec4899\", // pink\n \"#84cc16\", // lime\n];\n\nfunction pickColor(uid: string): string {\n // Deterministic FNV-1a-ish hash so the same user is always the same color\n // across sessions and across other users' screens.\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? \"#ec4899\";\n}\n","/**\n * A saved snapshot names the collab-room entries it already holds, so a seat that boots from it never\n * replays them (2026-10-16: a reload showed the text twice). Pure — no Yjs — so the editors' model can\n * stamp and read it without loading the room.\n */\n\n/** The key a saved snapshot carries its covered room entries under (`stampCovered` / `takeCovered`). */\nexport const COLLAB_COVERED_KEY = \"__matrxCollabCovered\";\n\n/** The snapshot to SAVE: `snapshot` plus the room entries it holds (`WorkbookCollabSession.coveredNow`). */\nexport function stampCovered<T extends object>(snapshot: T, covered: readonly string[]): T {\n return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered] };\n}\n\n/** A LOADED snapshot split into the content to mount and the room entries it already holds. */\nexport function takeCovered<T>(snapshot: T): { snapshot: T; covered: Set<string> } {\n if (!snapshot || typeof snapshot !== \"object\" || !(COLLAB_COVERED_KEY in (snapshot as object))) {\n return { snapshot, covered: new Set() };\n }\n const { [COLLAB_COVERED_KEY]: list, ...rest } = snapshot as Record<string, unknown>;\n return {\n snapshot: rest as T,\n covered: new Set(Array.isArray(list) ? list.filter((e): e is string => typeof e === \"string\") : []),\n };\n}\n","/**\n * The Docs operational transform (COLLAB-DESIGN §6.4, §6.5; C0b rules R1–R5 plus the C2 retain rule R6).\n *\n * Pure and DOM-free. ot-json1 walks the JSON tree; only the `text-x` edit transform is ours. It is a port of\n * Univer 1.0.4's `TextX._transform` / `transformBody` (Apache-2.0, dream-num/univer, core\n * src/docs/data-model/text-x) with these cases changed or added (evidence: C0-REPORT, C0b):\n *\n * R1 a whole-table delete swallows typing inside it; the typist gets a `lost` entry.\n * R2 a REPLACE (coverType 1) retain keeps a concurrent comment decoration whole.\n * R3 a REPLACE paragraph with no paragraphStyle means \"no style\" ({}), on both sides.\n * R4 style keys are tested for presence (`!== undefined`), never truthiness (a winning `bl: 0`).\n * R5 a non-monotonic op (a negative retain) is rewritten as the composition of its forward segments.\n * R6 a merge (not REPLACE) retain whose style lost every key comes back as a PLAIN retain. Without it `textRuns: [{ts:{}}]` and\n * `textRuns: []` apply differently and two-edit chains diverge (C2: 462 of 20,000; with it 0).\n *\n * Ops carrying `rangeUpdates` go to Univer's `TextX.transform` unchanged (no free 1.0.4 command emits them).\n * `T(x, y, side)` returns x rewritten to apply after y; `side` is x's side and the later-committed op takes\n * `'left'` (§6.4). A transform that throws is a barrier for that pair (the session treats a throw as one).\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- Univer's text-x action shapes are open JSON */\nimport { JSONX, TextX, getBodySliceForSplitTextXAction, normalizeTextRuns, merge as univerMerge } from \"@univerjs/core\";\nimport * as json1 from \"ot-json1\";\n\ntype Act = Record<string, any> & { t: \"i\" | \"r\" | \"d\"; len: number };\ntype Body = Record<string, any>;\ntype Zone = [number, number];\n/** One `lost` entry: what a transform dropped from either side (R1), for the author's notice. */\nexport interface DocsLost {\n rule: string;\n side: \"insert\" | \"delete\";\n len: number;\n text?: string;\n}\n\nconst isTextX = (c: unknown): c is { et: string; e: Act[] } =>\n !!c && typeof c === \"object\" && (c as { et?: unknown }).et === \"text-x\" && Array.isArray((c as { e?: unknown }).e);\nconst clone = <T>(v: T): T => (v == null ? v : structuredClone(v));\n\n// ── normalisation: the travelling shape ──────────────────────────────────────────────────────────────\n\nfunction tableZones(a: Act): Zone[] {\n const out: Zone[] = [];\n for (const t of (a.body?.tables ?? []) as Array<{ startIndex: number; endIndex: number }>) {\n if (t.startIndex >= 0 && t.endIndex <= a.len && t.endIndex > t.startIndex) out.push([t.startIndex, t.endIndex - 1]);\n }\n return out;\n}\n\n/** R5: an op whose cursor goes backwards becomes the composition of its forward-only segments. */\nfunction unrewind(actions: Act[]): Act[] {\n if (!actions.some((a) => a.len < 0)) return actions;\n const segs: Act[][] = [];\n let cur: Act[] = [];\n let cursor = 0;\n for (const a of actions) {\n if (a.len < 0) {\n if (a.t !== \"r\") return actions;\n segs.push(cur);\n cursor += a.len;\n cur = cursor > 0 ? [{ t: \"r\", len: cursor }] : [];\n continue;\n }\n cur.push(a);\n if (a.t !== \"d\") cursor += a.len;\n }\n segs.push(cur);\n const out = segs.reduce((acc, s) => TextX.compose(acc as any, s as any) as unknown as Act[]);\n return out.some((a) => a.len < 0) ? actions : out;\n}\n\nfunction normText(actions: Act[]): Act[] {\n const out: Act[] = [];\n for (const a of unrewind(actions)) {\n if (a.t === \"d\") {\n if (!(a.len > 0)) continue;\n const d: Act = { t: \"d\", len: a.len };\n if (a.valueRangeId !== undefined) d.valueRangeId = a.valueRangeId;\n const tz = (a.tz as Zone[] | undefined) ?? tableZones(a);\n if (tz.length) d.tz = tz;\n out.push(d);\n continue;\n }\n if (a.t === \"r\") {\n const { oldBody: _oldBody, ...rest } = a;\n out.push(rest as Act);\n continue;\n }\n out.push(a);\n }\n return out;\n}\n\n/** The travelling shape of a Docs JSON op: text-x edits normalised (R1 zones, R5, no oldBody). */\nexport function normalizeDocsOp<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) return { ...v, e: normText(v.e) };\n return v;\n };\n return walk(op) as T;\n}\n\n/** R6: a retain whose style lost every key to the other side is a plain retain. */\nexport function dropEmptyStyleRetains<T>(op: T): T {\n if (op == null) return op;\n const walk = (v: unknown): unknown => {\n if (Array.isArray(v)) return v.map(walk);\n if (isTextX(v)) {\n return {\n ...v,\n e: v.e.map((a) => {\n const b = a.body as Body | undefined;\n if (a.t !== \"r\" || !b || a.coverType === 1) return a;\n const runs = ((b.textRuns as Array<{ ts?: Record<string, unknown> }>) ?? []).filter((r) => r.ts && Object.keys(r.ts).length);\n const other = Object.keys(b).filter(\n (k) => k !== \"textRuns\" && k !== \"dataStream\" && !(Array.isArray(b[k]) && (b[k] as unknown[]).length === 0),\n );\n if (!runs.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: \"r\", len: a.len };\n if (b.textRuns === undefined || runs.length === (b.textRuns as unknown[]).length) return a;\n return { ...a, body: { ...b, textRuns: runs } };\n }),\n };\n }\n return v;\n };\n return walk(op) as T;\n}\n\n// ── action list helpers (Univer's TextX.push / trimEndUselessRetainAction, plus zone merging) ────────\n\nconst onlyDataStream = (body: Body) => Object.keys(body).length === 1;\nconst shiftZones = (tz: Zone[], by: number): Zone[] => tz.map(([s, e]) => [s + by, e + by]);\nfunction mergeZones(tz: Zone[]): Zone[] {\n const s = [...tz].sort((x, y) => x[0] - y[0]);\n const out: Zone[] = [];\n for (const z of s) {\n const l = out[out.length - 1];\n if (l && l[1] + 1 >= z[0]) l[1] = Math.max(l[1], z[1]);\n else out.push([z[0], z[1]]);\n }\n return out;\n}\nfunction push(list: Act[], action: Act): void {\n let index = list.length;\n let last = list[index - 1];\n const a = clone(action);\n if (a.t === \"r\" && a.len === 0 && a.body == null && !a.rangeUpdates) return;\n if (last) {\n if (last.t === \"d\" && a.t === \"d\" && last.valueRangeId === a.valueRangeId) {\n const tz = [...((last.tz as Zone[]) ?? []), ...shiftZones((a.tz as Zone[]) ?? [], last.len)];\n last.len += a.len;\n if (tz.length) last.tz = mergeZones(tz);\n return;\n }\n if (last.t === \"d\" && a.t === \"i\") {\n index -= 1;\n last = list[index - 1];\n if (last == null) {\n list.unshift(a);\n return;\n }\n }\n if (last.t === \"r\" && a.t === \"r\" && last.body == null && a.body == null && !last.rangeUpdates && !a.rangeUpdates) {\n last.len += a.len;\n return;\n }\n if (last.t === \"i\" && onlyDataStream(last.body) && a.t === \"i\" && onlyDataStream(a.body) && last.valueRangeId === a.valueRangeId) {\n last.len += a.len;\n last.body.dataStream += a.body.dataStream;\n return;\n }\n }\n if (index === list.length) list.push(a);\n else list.splice(index, 0, a);\n}\nconst BODY_FIELDS = [\n \"textRuns\", \"paragraphs\", \"customRanges\", \"customBlocks\", \"docxRawCustomBlocks\", \"docxRawBlocks\",\n \"docxExportExcludedRanges\", \"customDecorations\", \"tables\", \"columnGroups\", \"blockRanges\",\n];\nconst uselessRetain = (a: Act) => !a.rangeUpdates?.length && (a.body == null || BODY_FIELDS.every((k) => a.body[k] == null));\nfunction trimEnd(list: Act[]): Act[] {\n while (list.length && list[list.length - 1]!.t === \"r\" && uselessRetain(list[list.length - 1]!)) list.pop();\n return list;\n}\n\n/** Univer's ActionIterator, plus the offset inside the current action and table zones sliced on split. */\nclass It {\n private i = 0;\n private off = 0;\n constructor(private readonly a: Act[]) {}\n peekType(): Act[\"t\"] {\n return this.a[this.i]?.t ?? \"r\";\n }\n peekLength(): number {\n const x = this.a[this.i];\n return x ? x.len - this.off : Number.POSITIVE_INFINITY;\n }\n hasNext(): boolean {\n return this.peekLength() < Number.POSITIVE_INFINITY;\n }\n /** An insert placed now would land strictly inside a table this delete removes whole. */\n inZone(): boolean {\n const x = this.a[this.i];\n return x?.t === \"d\" && ((x.tz as Zone[]) ?? []).some(([s, e]) => s < this.off && this.off <= e);\n }\n next(length?: number): Act {\n let len = length || Number.POSITIVE_INFINITY;\n const x = this.a[this.i];\n if (!x) return { t: \"r\", len: Number.POSITIVE_INFINITY };\n const offset = this.off;\n if (len >= x.len - offset) {\n len = x.len - offset;\n this.i += 1;\n this.off = 0;\n } else this.off += len;\n if (x.t === \"d\") {\n const piece: Act = { ...clone(x), len };\n delete piece.tz;\n const tz = ((x.tz as Zone[]) ?? [])\n .map(([s, e]): Zone => [Math.max(s, offset) - offset, Math.min(e, offset + len - 1) - offset])\n .filter(([s, e]) => s <= e);\n if (tz.length) piece.tz = tz;\n return piece;\n }\n if (x.t === \"r\" && x.body == null) return { ...clone(x), len };\n return { ...clone(x), len, body: getBodySliceForSplitTextXAction(x.body, offset, offset + len, false) };\n }\n}\n\n// ── body transforms: ported from Univer transform-utils.ts, cases R3/R4 marked ───────────────────────\n\nfunction transformTextRuns(originTextRuns: any[] | undefined, targetTextRuns: any[] | undefined, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (originTextRuns == null || targetTextRuns == null) return targetTextRuns;\n if (originTextRuns.length === 0 || targetTextRuns.length === 0) return [];\n targetTextRuns = clone(targetTextRuns);\n originTextRuns = clone(originTextRuns);\n const out: any[] = [];\n const updateLength = targetTextRuns.length;\n const removeLength = originTextRuns.length;\n let updateIndex = 0;\n let removeIndex = 0;\n let pending: any = null;\n const flush = () => {\n if (pending) {\n out.push(pending);\n pending = null;\n return true;\n }\n return false;\n };\n while (updateIndex < updateLength && removeIndex < removeLength) {\n const { st: updateSt, ed: updateEd, ts: targetStyle } = targetTextRuns[updateIndex];\n const { st: removeSt, ed: removeEd, ts: originStyle, sId } = originTextRuns[removeIndex];\n let newTs: Record<string, unknown> = {};\n if (transformType === 0) {\n newTs = { ...targetStyle };\n if (originCoverType === 0 && targetCoverType === 1 && originStyle) newTs = Object.assign({}, originStyle, newTs);\n } else {\n newTs = { ...targetStyle };\n if (originCoverType === 1) {\n if (targetCoverType === 1) newTs = { ...originStyle };\n else if (targetStyle && originStyle) {\n for (const key of Object.keys(targetStyle)) if (originStyle[key] !== undefined) delete newTs[key]; // R4\n }\n } else if (targetCoverType === 1) {\n if (originStyle) for (const key of Object.keys(originStyle)) if (originStyle[key] !== undefined) newTs[key] = originStyle[key];\n } else if (originStyle) {\n for (const key of Object.keys(originStyle)) if (newTs[key] !== undefined) delete newTs[key];\n }\n }\n if (updateEd < removeSt) {\n if (!flush()) out.push(targetTextRuns[updateIndex]);\n updateIndex++;\n } else if (removeEd < updateSt) {\n if (!flush()) out.push(originTextRuns[removeIndex]);\n removeIndex++;\n } else {\n out.push({ st: Math.max(updateSt, removeSt), ed: Math.min(updateEd, removeEd), ts: newTs, sId });\n if (updateEd < removeEd) {\n updateIndex++;\n originTextRuns[removeIndex].st = updateEd;\n if (originTextRuns[removeIndex].st === originTextRuns[removeIndex].ed) removeIndex++;\n } else {\n removeIndex++;\n targetTextRuns[updateIndex].st = removeEd;\n if (targetTextRuns[updateIndex].st === targetTextRuns[updateIndex].ed) updateIndex++;\n }\n const p = {\n st: Math.min(updateEd, removeEd),\n ed: Math.max(updateEd, removeEd),\n ts: updateEd < removeEd ? { ...originStyle } : { ...targetStyle },\n sId: updateEd < removeEd ? sId : undefined,\n };\n pending = p.ed > p.st ? p : null;\n }\n }\n flush();\n const top = out[out.length - 1];\n const updateLast = targetTextRuns[updateLength - 1];\n const removeLast = originTextRuns[removeLength - 1];\n if (top.ed !== Math.max(updateLast.ed, removeLast.ed)) out.push(updateLast.ed > removeLast.ed ? updateLast : removeLast);\n return normalizeTextRuns(out, true);\n}\n\nfunction transformCustomRanges(o: any[] | undefined, t: any[] | undefined, originCoverType: number, _targetCoverType: number, transformType: 0 | 1): any[] | undefined {\n if (o == null || t == null) return t;\n if (o.length === 0 || t.length === 0) return [];\n if (o.length > 1 || t.length > 1) throw new Error(\"CustomRanges is only supported transform for length one now.\");\n if (originCoverType === 1) return transformType === 1 ? [clone(o[0])] : [clone(t[0])];\n const r = clone(t[0]);\n if (transformType === 1) Object.assign(r, clone(o[0]));\n return [r];\n}\n\nfunction transformParagraph(origin: any, target: any, originCoverType: number, targetCoverType: number, transformType: 0 | 1): any {\n const paragraph: any = { startIndex: target.startIndex, paragraphId: target.paragraphId };\n // R3: on a REPLACE paragraph, a missing paragraphStyle means \"no style\", which is a value.\n const oStyle = originCoverType === 1 ? origin.paragraphStyle ?? {} : origin.paragraphStyle;\n const tStyle = targetCoverType === 1 ? target.paragraphStyle ?? {} : target.paragraphStyle;\n if (tStyle) {\n paragraph.paragraphStyle = clone(tStyle);\n if (oStyle) {\n const ps = paragraph.paragraphStyle;\n if (originCoverType === 1) {\n if (targetCoverType === 1) {\n if (transformType === 1) paragraph.paragraphStyle = { ...oStyle };\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (targetCoverType === 1) {\n if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (oStyle[k] !== undefined) ps[k] = oStyle[k];\n } else for (const k of Object.keys(oStyle)) if (ps[k] === undefined) ps[k] = oStyle[k];\n } else if (transformType === 1) {\n for (const k of Object.keys(oStyle)) if (ps[k] !== undefined) delete ps[k]; // R3: presence, not truthiness\n }\n }\n if (targetCoverType !== 1 && Object.keys(paragraph.paragraphStyle).length === 0) delete paragraph.paragraphStyle;\n }\n if (originCoverType === 1 && targetCoverType === 1) paragraph.bullet = transformType === 1 ? clone(origin.bullet) : clone(target.bullet);\n else if (origin.bullet === undefined) paragraph.bullet = clone(target.bullet);\n else if (originCoverType === 1 || targetCoverType === 1) paragraph.bullet = transformType === 0 && target.bullet ? clone(target.bullet) : clone(origin.bullet);\n else if (transformType === 0 && target.bullet !== undefined) paragraph.bullet = clone(target.bullet);\n if (paragraph.bullet === undefined) delete paragraph.bullet;\n if (paragraph.paragraphId === undefined) delete paragraph.paragraphId;\n return paragraph;\n}\n\nfunction transformCustomDecorations(origin: any[] | undefined, target: any[] | undefined): any[] | undefined {\n if (origin == null || target == null) return target;\n if (origin.length === 0 || target.length === 0) return clone(target);\n const out: any[] = [];\n for (const d of target) {\n let pushed = false;\n for (const o of origin) {\n if (o.id === d.id) {\n if (o.type === 9999 || d.type === 9999) {\n pushed = true;\n out.push({ ...d, type: 9999 });\n }\n break;\n }\n }\n if (!pushed) out.push(d);\n }\n return out;\n}\n\nfunction transformBlockRanges(thisBlockRanges: any[], otherBlockRanges: any[], priority: boolean): any[] {\n if (!thisBlockRanges.length) return otherBlockRanges;\n if (!otherBlockRanges.length) return [];\n return otherBlockRanges.map((o) => {\n const t = thisBlockRanges.find((b) => b.blockId === o.blockId);\n return t && priority ? univerMerge(o, t) : o;\n });\n}\n\n/** transformBody(thisAction = the other op's chunk, otherAction = the chunk being transformed, priority = this wins). */\nfunction transformBody(thisAction: Act, otherAction: Act, priority: boolean): { coverType: number; body: Body } {\n const { body: thisBody, coverType: thisCoverType = 0 } = thisAction;\n const { body: otherBody, coverType: otherCoverType = 0 } = otherAction;\n if (thisBody == null || thisBody.dataStream !== \"\" || otherBody == null || otherBody.dataStream !== \"\") {\n throw new Error(\"Data stream is not supported in retain transform.\");\n }\n const ret: Body = { dataStream: \"\" };\n const { textRuns: tr1, paragraphs: p1 = [], blockRanges: b1 = [], customRanges: c1, customDecorations: d1 } = thisBody;\n const { textRuns: tr2, paragraphs: p2 = [], blockRanges: b2 = [], customRanges: c2, customDecorations: d2 } = otherBody;\n const pt: 0 | 1 = priority ? 1 : 0;\n const textRuns = transformTextRuns(tr1, tr2, thisCoverType, otherCoverType, pt);\n if (textRuns) ret.textRuns = textRuns;\n const customRanges = transformCustomRanges(c1, c2, thisCoverType, otherCoverType, pt);\n if (customRanges) ret.customRanges = customRanges;\n const customDecorations = transformCustomDecorations(d1, d2);\n if (customDecorations) ret.customDecorations = customDecorations;\n const paragraphs: any[] = [];\n let i = 0;\n let j = 0;\n while (i < p1.length && j < p2.length) {\n const a = p1[i];\n const b = p2[j];\n if (a.startIndex === b.startIndex) {\n paragraphs.push(transformParagraph(a, b, thisCoverType, otherCoverType, pt));\n i++;\n j++;\n } else if (a.startIndex < b.startIndex) i++;\n else {\n paragraphs.push(clone(b));\n j++;\n }\n }\n if (j < p2.length) paragraphs.push(...p2.slice(j));\n if (paragraphs.length) ret.paragraphs = paragraphs;\n const blockRanges = transformBlockRanges(b1, b2, priority);\n if (blockRanges.length) ret.blockRanges = blockRanges;\n return { coverType: otherCoverType, body: ret };\n}\n\n// ── the text-x transform ──────────────────────────────────────────────────────────────────────────────\n\nconst valueIds = (acts: Act[]) => new Set(acts.flatMap((a) => (a.t !== \"r\" && a.valueRangeId ? [a.valueRangeId as string] : [])));\nfunction withoutValueRangeMetadata(acts: Act[], suppressed: Set<string>): Act[] {\n return acts.map((a) => {\n if (!a.body?.customRanges?.some((r: any) => suppressed.has(r.rangeId))) return a;\n const body = { ...a.body, customRanges: a.body.customRanges.filter((r: any) => !suppressed.has(r.rangeId)) };\n if (!body.customRanges.length) delete body.customRanges;\n return { ...a, body };\n });\n}\n/** Decorations y adds, in the coordinates of the document after y. */\nfunction addedDecorations(y: Act[]): Array<{ id: string; type: number; ds: number; de: number }> {\n const out: Array<{ id: string; type: number; ds: number; de: number }> = [];\n let pos = 0;\n for (const a of y) {\n if (a.t === \"d\") continue;\n if (a.t === \"r\") for (const d of a.body?.customDecorations ?? []) if (d.type !== 9999) out.push({ id: d.id, type: d.type, ds: pos + d.startIndex, de: pos + d.endIndex });\n pos += a.len;\n }\n return out;\n}\nconst hasRangeUpdates = (acts: Act[]) => acts.some((a) => a.t === \"r\" && a.rangeUpdates?.length);\n\n/** x rewritten to apply after y over one text-x body; `side` is x's side. Drops land in `lost` (R1). */\nexport function transformTextX(xIn: Act[], yIn: Act[], side: \"left\" | \"right\", lost: DocsLost[] = []): Act[] {\n if (hasRangeUpdates(xIn) || hasRangeUpdates(yIn)) return TextX.transform(xIn as any, yIn as any, side) as unknown as Act[];\n const x = normText(xIn);\n const y = normText(yIn);\n const xLeft = side === \"left\";\n const yIds = valueIds(y);\n const conflicts = new Set([...valueIds(x)].filter((id) => yIds.has(id)));\n const X = new It(conflicts.size && !xLeft ? withoutValueRangeMetadata(x, conflicts) : x);\n const Y = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);\n const decos = addedDecorations(y).map((d) => ({ ...d, pieces: [] as Zone[] }));\n const out: Act[] = [];\n let inPos = 0;\n let outPos = 0;\n while (X.hasNext() || Y.hasNext()) {\n if (X.peekType() === \"i\" && (xLeft || Y.peekType() !== \"i\")) {\n const a = X.next();\n if (Y.inZone()) {\n lost.push({ rule: \"R1\", side: \"insert\", len: a.len, ...(a.body?.dataStream !== undefined ? { text: a.body.dataStream } : {}) });\n continue;\n }\n if (a.valueRangeId && conflicts.has(a.valueRangeId) && !xLeft) continue;\n push(out, a);\n outPos += a.len;\n } else if (Y.peekType() === \"i\") {\n const b = Y.next();\n if (X.inZone()) {\n push(out, { t: \"d\", len: b.len, tz: [[0, b.len - 1]] });\n lost.push({ rule: \"R1\", side: \"delete\", len: b.len, ...(b.body?.dataStream !== undefined ? { text: b.body.dataStream } : {}) });\n inPos += b.len;\n continue;\n }\n if (b.valueRangeId && conflicts.has(b.valueRangeId) && xLeft) push(out, { t: \"d\", len: b.len, valueRangeId: b.valueRangeId });\n else {\n push(out, { t: \"r\", len: b.len });\n outPos += b.len;\n }\n inPos += b.len;\n } else {\n const len = Math.min(X.peekLength(), Y.peekLength());\n const a = X.next(len);\n const b = Y.next(len);\n if (b.t === \"d\") continue;\n if (a.t === \"d\") {\n push(out, a);\n inPos += len;\n continue;\n }\n for (const d of decos) {\n const s = Math.max(d.ds, inPos);\n const e = Math.min(d.de, inPos + len - 1);\n if (s <= e) d.pieces.push([outPos + s - inPos, outPos + e - inPos]);\n }\n let r: Act = a;\n if (a.body != null && b.body != null) {\n const { coverType, body } = transformBody(b, a, !xLeft);\n r = { ...a, t: \"r\", coverType, body };\n }\n // R2: a REPLACE retain re-asserts, whole, every decoration y added that it overlaps.\n if (r.coverType === 1 && r.body) {\n const keep: any[] = [];\n for (const d of decos) {\n if (!(d.de >= inPos && d.ds < inPos + len)) continue;\n const ahead: Zone[] = d.de >= inPos + len ? [[outPos + len + Math.max(d.ds, inPos + len) - (inPos + len), outPos + d.de - inPos]] : [];\n for (const [s, e] of [...d.pieces, ...ahead]) keep.push({ id: d.id, type: d.type, startIndex: s - outPos, endIndex: e - outPos });\n }\n if (keep.length) r = { ...r, body: { ...r.body, customDecorations: [...(r.body.customDecorations ?? []), ...keep] } };\n }\n push(out, r);\n inPos += len;\n outPos += len;\n }\n }\n return trimEnd(out);\n}\n\n// ── ot-json1 binding ─────────────────────────────────────────────────────────────────────────────────\n\n/** A Docs operation: an ot-json1 op over the whole Univer snapshot (what `rich-text-editing` carries as `actions`). */\nexport type DocsOp = unknown[] | null;\n\nexport interface DocsTransformResult {\n op: DocsOp;\n lost: DocsLost[];\n}\n\nlet sink: DocsLost[] | null = null;\nconst ours = {\n name: \"text-x\",\n uri: (TextX as unknown as { uri: string }).uri,\n apply: (doc: any, actions: any) => TextX.apply(doc, actions),\n compose: (a: any, b: any) => TextX.compose(a, b),\n isNoop: (a: any) => TextX.isNoop(a),\n invert: (a: any) => TextX.invert(a),\n makeInvertible: (a: any, doc: any) => TextX.makeInvertible(a, doc),\n transform: (x: any, y: any, side: \"left\" | \"right\") => transformTextX(x, y, side, sink ?? []),\n};\n\n/**\n * `T(x, y, side)` for Docs: ot-json1 `transformNoConflict` (never throws on DROP_COLLISION / RM_UNEXPECTED_CONTENT /\n * BLACKHOLE, §3) with our text-x transform registered only for the duration of one call, so Univer's own apply is\n * untouched even when the bundler shares one ot-json1 instance with `@univerjs/core`. R6 runs on the result.\n */\nexport function transformDocsOp(x: DocsOp, y: DocsOp, side: \"left\" | \"right\"): DocsTransformResult {\n if (x == null) return { op: null, lost: [] };\n if (y == null) return { op: x, lost: [] };\n const lost: DocsLost[] = [];\n sink = lost;\n json1.type.registerSubtype(ours as any);\n try {\n const op = json1.type.transformNoConflict(normalizeDocsOp(x) as any, normalizeDocsOp(y) as any, side) as DocsOp;\n return { op: dropEmptyStyleRetains(op), lost };\n } finally {\n json1.type.registerSubtype(TextX as any);\n sink = null;\n }\n}\n\n/** `a` then `b` as one op (TextX is the subtype every reader composes with). */\nexport function composeDocsOps(a: DocsOp, b: DocsOp): DocsOp {\n if (a == null) return b;\n if (b == null) return a;\n json1.type.registerSubtype(TextX as any);\n return json1.type.compose(a as any, b as any) as DocsOp;\n}\n\nexport function isNoopDocsOp(op: DocsOp): boolean {\n return op == null || (Array.isArray(op) && op.length === 0) || json1.type.isNoop(op as any);\n}\n\n/** Apply an op to a plain snapshot (tests, the fold). Univer's own JSONX, so TextX applies as the editor applies. */\nexport function applyDocsOp<T>(doc: T, op: DocsOp): T {\n if (isNoopDocsOp(op)) return doc;\n return JSONX.apply(structuredClone(doc) as any, op as any) as T;\n}\n\n/** The inverse of `op` against the state it applied to. JSONX.invertWithDoc MUTATES its op: invert a copy (C0). */\nexport function invertDocsOp(op: DocsOp, preDoc: unknown): DocsOp {\n if (isNoopDocsOp(op)) return null;\n return JSONX.invertWithDoc(structuredClone(op) as any, preDoc as any) as DocsOp;\n}\n\n/** Part of `proto` (§6.4): Univer 1.0.4 + this transformer, rules R1–R6. */\nexport const DOCS_TRANSFORM_VERSION = \"univer-1.0.4+docs-ot-r6\";\n","/**\n * The canonical Docs state hash (COLLAB-DESIGN §7.2; C0 item 6, `spikes/c0-collab/lib.mjs`).\n *\n * SHA-256 of the canonical snapshot: keys sorted, empty values dropped, the unit id and seat-local fields\n * removed (revision counter, collab stamps, layout state, selections), adjacent equal text runs merged, split\n * pieces of one custom range or decoration folded, and `paragraphId` dropped (Univer's TextX.apply mints a\n * random one per seat, C0 surprise 3). Header, footer and note bodies get the same rules.\n *\n * Two seats with equal content hash equal; one character more hashes differently. Browser and Node: the\n * digest is Web Crypto's.\n */\n/* eslint-disable @typescript-eslint/no-explicit-any -- snapshot JSON */\n\n/** Never content: the collab stamps, revision counters, seat-local view state. */\nexport const DOC_LOCAL_KEYS = [\"rev\", \"__matrxCollabCovered\", \"__collab\", \"disabled\", \"layoutState\", \"textRanges\", \"selections\"];\n\nfunction sortDeep(v: any): any {\n if (Array.isArray(v)) return v.map(sortDeep);\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v).sort()) {\n const x = v[k];\n if (x === undefined || x === null) continue;\n if (Array.isArray(x) && x.length === 0) continue;\n if (x && typeof x === \"object\" && !Array.isArray(x) && Object.keys(x).length === 0) continue;\n out[k] = sortDeep(x);\n }\n return out;\n }\n return v;\n}\n\nconst sameTs = (a: unknown, b: unknown) => JSON.stringify(sortDeep(a ?? {})) === JSON.stringify(sortDeep(b ?? {}));\n\nfunction canonicalRuns(runs: any[] | undefined): any[] {\n const out: any[] = [];\n for (const r of [...(runs ?? [])].sort((x, y) => x.st - y.st)) {\n if (r.ed <= r.st) continue;\n const ts = sortDeep(r.ts ?? {});\n if (Object.keys(ts).length === 0) continue;\n const last = out[out.length - 1];\n if (last && last.ed === r.st && sameTs(last.ts, ts)) last.ed = r.ed;\n else out.push({ st: r.st, ed: r.ed, ts });\n }\n return out;\n}\n\nfunction foldPieces(items: any[] | undefined, keyOf: (it: any) => string): any[] {\n const groups = new Map<string, any[]>();\n for (const it of items ?? []) {\n const k = keyOf(it);\n const g = groups.get(k) ?? [];\n g.push(it);\n groups.set(k, g);\n }\n const out: any[] = [];\n for (const list of groups.values()) {\n list.sort((a, b) => a.startIndex - b.startIndex);\n let cur: any = null;\n for (const it of list) {\n if (cur && cur.endIndex + 1 >= it.startIndex) cur.endIndex = Math.max(cur.endIndex, it.endIndex);\n else {\n if (cur) out.push(cur);\n cur = { ...it };\n }\n }\n if (cur) out.push(cur);\n }\n return out;\n}\nconst rootId = (id: unknown) => String(id).split(\"$\")[0];\n\nfunction canonicalBody(body: any): any {\n if (!body) return body;\n const b = { ...body };\n b.textRuns = canonicalRuns(b.textRuns);\n if (Array.isArray(b.paragraphs)) b.paragraphs = b.paragraphs.map(({ paragraphId: _p, ...p }: any) => p);\n b.customRanges = foldPieces(b.customRanges, (r) => JSON.stringify([rootId(r.rangeId), r.rangeType, sortDeep(r.properties ?? {})])).map((r) => ({\n ...r,\n rangeId: rootId(r.rangeId),\n }));\n b.customDecorations = foldPieces(b.customDecorations, (d) => JSON.stringify([d.id, d.type]));\n for (const k of [\"paragraphs\", \"customRanges\", \"customBlocks\", \"tables\", \"sectionBreaks\", \"customDecorations\"]) {\n if (Array.isArray(b[k])) {\n b[k] = [...b[k]].sort(\n (x: any, y: any) =>\n (x.startIndex ?? 0) - (y.startIndex ?? 0) ||\n String(x.rangeId ?? x.blockId ?? x.tableId ?? \"\").localeCompare(String(y.rangeId ?? y.blockId ?? y.tableId ?? \"\")),\n );\n }\n }\n return b;\n}\n\n/** The canonical Docs snapshot: content only, keys sorted, runs normalised, local fields removed. */\nexport function canonicalDocsSnapshot(snapshot: unknown): unknown {\n const s = structuredClone(snapshot ?? {}) as any;\n delete s.id;\n for (const k of DOC_LOCAL_KEYS) delete s[k];\n s.body = canonicalBody(s.body);\n for (const seg of [\"headers\", \"footers\", \"notes\"]) {\n if (!s[seg]) continue;\n for (const id of Object.keys(s[seg])) s[seg][id] = { ...s[seg][id], body: canonicalBody(s[seg][id].body) };\n }\n return sortDeep(s);\n}\n\n/** The canonical form as the string the hash digests (tests compare these directly). */\nexport const canonicalDocsString = (snapshot: unknown): string => JSON.stringify(canonicalDocsSnapshot(snapshot));\n\n/** SHA-256 hex of the canonical snapshot (§7.2). */\nexport async function docsStateHash(snapshot: unknown): Promise<string> {\n const bytes = new TextEncoder().encode(canonicalDocsString(snapshot));\n const digest = await globalThis.crypto.subtle.digest(\"SHA-256\", bytes);\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * Ids every seat agrees on for a snapshot that lacks them (C0 surprise 5): a raw snapshot (an import, markdown)\n * loaded on two seats would otherwise get two random `sectionId`s / `paragraphId`s. Missing ids become\n * positional ones; ids already present are kept. Applied to every snapshot a room loads.\n */\nexport function stampDeterministicIds<T>(snapshot: T): T {\n const s = structuredClone(snapshot) as any;\n const stamp = (body: any, scope: string) => {\n if (!body) return;\n for (const p of body.paragraphs ?? []) if (!p.paragraphId) p.paragraphId = `p_${scope}${p.startIndex}`;\n for (const sb of body.sectionBreaks ?? []) if (!sb.sectionId) sb.sectionId = `s_${scope}${sb.startIndex}`;\n };\n stamp(s?.body, \"\");\n for (const seg of [\"headers\", \"footers\", \"notes\"]) for (const id of Object.keys(s?.[seg] ?? {})) stamp(s[seg][id]?.body, `${id}_`);\n return s as T;\n}\n","/**\n * The Docs co-editing room on the ordered log (COLLAB-DESIGN §6, unit C3): the `OpDocumentAdapter` for\n * `openOpSession` over a document's editors, plus saves, restore and the saver choice.\n *\n * - CAPTURE (§6.3). The document model hands over every local `doc.mutation.rich-text-editing` with the applied\n * params (the handler's own rewrite, C0 surprise 6), the pre-state cloned in `beforeCommandExecuted`, and the\n * outermost command id. `onlyLocal` / `fromCollab` never arrive here (the model filters them). Only `segmentId`\n * and `actions` travel; the inverse is computed from the APPLIED actions on a COPY (`invertWithDoc` mutates its\n * op). Each mutation goes to the session as it happens, so a remote apply can never land between a local\n * mutation and its hand-over; the command id rides along as the change's label.\n * - APPLY (§6.7). `syncExecuteCommand(id, { unitId: own, segmentId, actions, textRanges: null,\n * noNeedSetTextRange: true }, { onlyLocal: true, fromCollab: true })` through the model (every view of the\n * document in this tab). A throw, `false`, or actions the handler emptied fail the apply: the session rebuilds,\n * never skips. While an IME composition is open, remote applies QUEUE (acks continue); a local op captured\n * meanwhile is rebased over the queue (`L' = T(L, Q, 'left')`, `Q' = T(Q, L, 'right')`), and the queue drains\n * at `compositionend`.\n * - UNDO (§6.9). Each applied remote op rebases every stored undo and redo item of this seat\n * (`T(item, R1, 'left')`); `textRanges` and `layoutState` are stripped from rebased items; an item whose rebase\n * is a barrier, throws or comes back empty is dropped. Undo therefore only ever reverts this person's changes.\n * - SAVES (§7.3). Only a quiet seat whose hash matches every peer at its rev saves, and only the chosen saver\n * (the lowest client id among seats publishing a quiet hash) saves on its own; a manual save always tries.\n * - RESTORE (§20). A whole-document replace goes through `collab_replace`: the snapshot is loaded into this seat's\n * editor first, so the stored snapshot and its hash are the Univer-normalised form every seat will load.\n */\nimport type {\n OpDocumentAdapter,\n OpPresence,\n OpSession,\n OpSessionIncident,\n OpSessionNotice,\n OpSessionStatus,\n OpTransport,\n} from \"@ai-matrx/data/realtime/collab\";\nimport { isOpBarrier, openOpSession } from \"@ai-matrx/data/realtime/collab\";\n\nimport { canonicalDocsString, docsStateHash, stampDeterministicIds } from \"./state-hash\";\nimport {\n composeDocsOps,\n DOCS_TRANSFORM_VERSION,\n invertDocsOp,\n isNoopDocsOp,\n normalizeDocsOp,\n transformDocsOp,\n type DocsOp,\n} from \"./transform\";\n\nexport const RICH_TEXT_EDITING = \"doc.mutation.rich-text-editing\";\n\n/**\n * The room's protocol (§6.4): Univer 1.0.4 + transformer `DOCS_TRANSFORM_VERSION`. Any Univer or transformer\n * change raises it; a room at another proto opens read-only for this build.\n */\nexport const DOCS_COLLAB_PROTO = 1;\n\n/** One local mutation as the document model hands it over. */\nexport interface DocsLocalMutation {\n id: string;\n params: unknown;\n /** The document before this mutation (cloned in `beforeCommandExecuted`), when the view could supply it. */\n pre: unknown | null;\n /** The outermost command this mutation belongs to (the depth tracker with its try/finally guard). */\n cmd: string | null;\n /** Whether the mutation changes what a snapshot stores. */\n content: boolean;\n}\n\n/** What the document model lends the room (implemented by `DocumentModel`). */\nexport interface DocsOtPort {\n onLocal(listener: (m: DocsLocalMutation) => void): () => void;\n /** Apply one committed mutation to every view of the document; throws when any view could not. */\n applyRemote(id: string, params: Record<string, unknown>): void;\n /** The document as the editor holds it now (`doc.save()`), or null when no view is mounted. */\n snapshot(): unknown | null;\n /** Replace the document in every view (and the kept editor). */\n load(snapshot: unknown): void;\n /** Univer's undo/redo service of each mounted view and the unit it holds. */\n undoTargets(): Array<{ service: unknown; unitId: string }>;\n /** Ask for a save (the record's one coalesced save). */\n markDirty(): void;\n}\n\nexport type DocsOtNotice =\n | OpSessionNotice<DocsOp>\n | { kind: \"not_shared\"; mutationId: string }\n | { kind: \"not_live\" };\n\nexport interface OpenDocsOtRoomOptions {\n port: DocsOtPort;\n transport: OpTransport;\n clientId: string;\n presence?: OpPresence;\n /** `collab_replace` for this room (restore, whole import). */\n replace: (req: { snapshot: unknown; stateHash: string; clientId: string }) => Promise<{ rev: number; ref: string }>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n /** Watch IME composition here (default: `document`). */\n compositionTarget?: Pick<Document, \"addEventListener\" | \"removeEventListener\"> | null;\n}\n\nexport interface DocsOtRoom {\n session: OpSession<DocsOp>;\n /** The record's save: a checkpoint at a quiet point (§7.3). False when this seat does not write now. */\n write(reason: \"manual\" | string): Promise<boolean>;\n /** Restore / whole import through `collab_replace` (§20). */\n replace(snapshot: unknown): Promise<void>;\n /** This seat is the one that saves on its own. */\n isSaver(): boolean;\n stop(): void;\n}\n\n// ── helpers ───────────────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Keys in one canonical order. The log stores groups as jsonb, which returns object keys in its own order, so an\n * op read back from the door is the same op with its keys moved. The session compares wire forms (its ack check)\n * through `encode`, so `encode` must not depend on key order or every acknowledgement looks like a mismatch.\n */\nexport function canonicalKeys<T>(v: T): T {\n if (Array.isArray(v)) return v.map(canonicalKeys) as T;\n if (v && typeof v === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(v as Record<string, unknown>).sort()) out[k] = canonicalKeys((v as Record<string, unknown>)[k]);\n return out as T;\n }\n return v;\n}\n\n/** Top-level keys an op descends into (`[\"body\", …]` or `[[\"body\", …], [\"headers\", …]]`). */\nfunction branches(op: DocsOp): unknown[][] {\n if (!Array.isArray(op) || op.length === 0) return [];\n return Array.isArray(op[0]) ? (op as unknown[][]) : [op as unknown[]];\n}\nconst touchesPageSetup = (op: DocsOp) => branches(op).some((b) => b[0] === \"documentStyle\");\n\n/** The segment a branch edits: `[\"headers\", id, \"body\", …]` → id; the body → \"\". */\nfunction segmentOf(branch: unknown[]): string {\n return (branch[0] === \"headers\" || branch[0] === \"footers\") && typeof branch[1] === \"string\" ? branch[1] : \"\";\n}\n\ninterface UndoItem {\n unitID?: string;\n undoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n redoMutations?: Array<{ id: string; params: Record<string, unknown> }>;\n}\ninterface UndoServiceInternals {\n _undoStacks?: Map<string, UndoItem[]>;\n _redoStacks?: Map<string, UndoItem[]>;\n}\n\n/** The Univer 1.0.4 fields the undo rebase reads; a forcing test fails if they move (Univer is pinned). */\nexport function undoStacksOf(service: unknown): { undo: Map<string, UndoItem[]>; redo: Map<string, UndoItem[]> } | null {\n const s = service as UndoServiceInternals | null;\n if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;\n return { undo: s._undoStacks, redo: s._redoStacks };\n}\n\n/** §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped. */\nexport function rebaseUndoStack(items: UndoItem[], remote: DocsOp): number {\n let dropped = 0;\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i]!;\n let ok = true;\n for (const list of [item.undoMutations, item.redoMutations]) {\n for (const m of list ?? []) {\n if (m.id !== RICH_TEXT_EDITING) continue;\n try {\n if (touchesPageSetup(m.params.actions as DocsOp) && touchesPageSetup(remote)) throw new Error(\"page setup\");\n const r = transformDocsOp(m.params.actions as DocsOp, remote, \"left\");\n if (isNoopDocsOp(r.op)) ok = false;\n else {\n m.params = { ...m.params, actions: r.op };\n delete m.params.textRanges;\n delete m.params.layoutState;\n }\n } catch {\n ok = false;\n }\n }\n }\n if (!ok) {\n items.splice(i, 1);\n dropped++;\n }\n }\n return dropped;\n}\n\n// ── the room ──────────────────────────────────────────────────────────────────────────────────────────\n\nexport function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom {\n const { port } = o;\n let session: OpSession<DocsOp> | null = null;\n let composing = false;\n /** Remote ops held while an IME composition is open, already rebased over local composition ops. */\n let queue: DocsOp[] = [];\n const drainWaiters: Array<() => void> = [];\n\n const notice = (n: DocsOtNotice) => {\n try {\n o.onNotice?.(n);\n } catch (err) {\n console.warn(\"[docs-ot] notice handler failed\", err);\n }\n };\n\n const applyNow = (op: DocsOp) => {\n for (const b of branches(op)) {\n const params: Record<string, unknown> = { segmentId: segmentOf(b), actions: b };\n port.applyRemote(RICH_TEXT_EDITING, params);\n }\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n if (!stacks) continue;\n for (const m of [stacks.undo, stacks.redo]) {\n const items = m.get(t.unitId);\n if (items?.length) rebaseUndoStack(items, op);\n }\n }\n port.markDirty();\n };\n\n const drain = () => {\n const held = queue;\n queue = [];\n try {\n for (const op of held) applyNow(op);\n } catch (err) {\n console.warn(\"[docs-ot] a held remote edit failed after composition; reloading this seat\", err);\n session?.rebuild(\"ime_drain_failed\");\n }\n for (const w of drainWaiters.splice(0)) w();\n };\n\n const adapter: OpDocumentAdapter<DocsOp> = {\n version: DOCS_TRANSFORM_VERSION,\n transform(x, y, side) {\n // §18: page setup replaces section breaks by array index; a barrier against every family, itself included.\n if (x != null && y != null && (touchesPageSetup(x) || touchesPageSetup(y))) return { barrier: true, reason: \"page_setup\" };\n const r = transformDocsOp(x, y, side);\n return { op: isNoopDocsOp(r.op) ? null : r.op, lost: r.lost };\n },\n compose: (a, b) => composeDocsOps(a, b),\n isNoop: (op) => isNoopDocsOp(op),\n encode: (op) => [{ cmd: \"docs.edit\", mutations: [{ id: RICH_TEXT_EDITING, params: { segmentId: \"\", actions: canonicalKeys(op) } }] }],\n decode(groups) {\n let op: DocsOp = null;\n for (const g of groups) {\n for (const m of g.mutations) {\n if (m.id !== RICH_TEXT_EDITING) throw new Error(`a Docs room cannot apply ${m.id}`);\n op = composeDocsOps(op, (m.params as { actions?: DocsOp }).actions ?? null);\n }\n }\n return op;\n },\n apply(op) {\n if (isNoopDocsOp(op)) return true;\n if (composing) {\n queue.push(op);\n return true;\n }\n applyNow(op);\n return true;\n },\n async load(snapshot) {\n const next = stampDeterministicIds(snapshot ?? {});\n queue = [];\n const current = port.snapshot();\n if (current && canonicalDocsString(current) === canonicalDocsString(next)) return;\n port.load(next);\n for (const t of port.undoTargets()) {\n const stacks = undoStacksOf(t.service);\n stacks?.undo.delete(t.unitId);\n stacks?.redo.delete(t.unitId);\n }\n },\n snapshot: () => port.snapshot(),\n async hash() {\n if (composing || queue.length) {\n await new Promise<void>((resolve) => {\n drainWaiters.push(resolve);\n setTimeout(resolve, 5000);\n });\n }\n return docsStateHash(port.snapshot());\n },\n };\n\n const onLocal = (m: DocsLocalMutation) => {\n if (!session) return;\n if (m.id !== RICH_TEXT_EDITING) {\n if (!m.content) return;\n // §6.3: an id without an allowlist never travels. Say so and put this seat back on the shared document.\n notice({ kind: \"not_shared\", mutationId: m.id });\n session.rebuild(`not_shared:${m.id}`);\n return;\n }\n const p = (m.params ?? {}) as { actions?: DocsOp };\n const applied = p.actions ?? null;\n if (isNoopDocsOp(applied)) return;\n let op: DocsOp = normalizeDocsOp(structuredClone(applied));\n let inverse: DocsOp | undefined;\n try {\n inverse = m.pre != null ? invertDocsOp(applied, m.pre) : undefined;\n } catch {\n inverse = undefined;\n }\n if (queue.length) {\n // the editor does not hold the queued remote ops yet: rebase this edit over them, and them over it\n inverse = undefined;\n const next: DocsOp[] = [];\n for (const q of queue) {\n const l2 = adapter.transform(op, q, \"left\");\n const q2 = adapter.transform(q, op, \"right\");\n if (isOpBarrier(l2) || isOpBarrier(q2)) {\n queue = [];\n session.rebuild(\"ime_barrier\");\n return;\n }\n op = l2.op;\n next.push(q2.op);\n }\n queue = next.filter((q) => !isNoopDocsOp(q));\n if (isNoopDocsOp(op)) return;\n }\n if (!session.local(op, { ...(inverse !== undefined ? { inverse } : {}), label: m.cmd ?? RICH_TEXT_EDITING })) notice({ kind: \"not_live\" });\n };\n\n const unsubLocal = port.onLocal(onLocal);\n const target = o.compositionTarget === undefined ? (typeof document !== \"undefined\" ? document : null) : o.compositionTarget;\n const onStart = () => {\n composing = true;\n };\n const onEnd = () => {\n composing = false;\n // Univer emits the composition's last mutation in the same task as compositionend: drain after it\n setTimeout(() => {\n if (!composing) drain();\n }, 0);\n };\n target?.addEventListener(\"compositionstart\", onStart, true);\n target?.addEventListener(\"compositionend\", onEnd, true);\n\n session = openOpSession<DocsOp>({\n transport: o.transport,\n adapter,\n proto: DOCS_COLLAB_PROTO,\n clientId: o.clientId,\n ...(o.presence ? { presence: o.presence } : {}),\n onNotice: (n) => notice(n),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n\n const isSaver = () => {\n if (!o.presence) return true;\n return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);\n };\n\n return {\n session,\n isSaver,\n async write(reason) {\n if (!session) return false;\n if (reason !== \"manual\" && !isSaver()) return false;\n const out = await session.save();\n if (out.saved) return true;\n if (out.reason === \"not_quiet\" || out.reason === \"changed\") setTimeout(() => port.markDirty(), 1500);\n return false;\n },\n async replace(snapshot) {\n port.load(stampDeterministicIds(snapshot));\n const loaded = port.snapshot();\n if (!loaded) throw new Error(\"The document is not open in this tab.\");\n const stateHash = await docsStateHash(loaded);\n await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });\n },\n stop() {\n unsubLocal();\n target?.removeEventListener(\"compositionstart\", onStart, true);\n target?.removeEventListener(\"compositionend\", onEnd, true);\n session?.close();\n },\n };\n}\n","/**\n * A cloud document's co-editing room on the ordered log (COLLAB-DESIGN §6, §19; unit C3), assembled from the\n * configured docs host: the `udt_document_snapshots` store, the C1 doors over the host's Supabase client, the\n * private `collab:<id>` frames on the app's one realtime manager, and Yjs awareness for presence only (who is\n * here plus `quiet_hash`; no content travels there).\n *\n * The FLIP is per room (§12.2): a document whose room exists always opens on the ordered log; a document with\n * no room opens one only when the host's `collab.ot_rooms` knob says so (`all`, or `new` for a document never\n * saved). Everything else keeps the 0.6 relay. The host reads the knob (host config lives in the app).\n */\nimport * as Y from \"yjs\";\nimport { Awareness } from \"y-protocols/awareness\";\n\nimport {\n awarenessOpPresence,\n collabReplace,\n collabRoomExists,\n SupabaseYjsProvider,\n supabaseOpTransport,\n type AwarenessState,\n type CollabRpcClient,\n type OpSessionIncident,\n type OpSessionStatus,\n} from \"@ai-matrx/data/realtime/collab\";\n\nimport { openDocsOtRoom, type DocsOtNotice } from \"../univer/collab/docs-ot/room\";\nimport type { DocumentAwareness, DocumentOtFactory } from \"./document-model\";\nimport { getLatestDocumentSnapshot, saveDocumentSnapshot } from \"./document-service\";\nimport { getDocsHost } from \"./ports\";\n\n/** `collab.ot_rooms` (§12.2): which documents without a room open one. */\nexport type OtRoomsKnob = \"off\" | \"new\" | \"all\";\n\nconst db = () => getDocsHost().getSupabase() as unknown as CollabRpcClient;\n\nasync function loadSnapshotRow(documentId: string, ref: string): Promise<unknown> {\n if (ref === \"none\") {\n const res = await getLatestDocumentSnapshot(documentId);\n if (!res.success) throw new Error(res.error);\n return res.data?.snapshot ?? null;\n }\n const { data, error } = await getDocsHost()\n .getSupabase()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"snapshot\")\n .eq(\"id\", ref)\n .maybeSingle();\n if (error) throw new Error(error.message);\n if (!data) throw new Error(`The saved version ${ref} of this document is missing.`);\n return (data as { snapshot?: unknown }).snapshot ?? null;\n}\n\n/** Whether this document opens on the ordered log: its room exists, or the knob opens one. */\nexport async function documentUsesOrderedRoom(documentId: string, knob: OtRoomsKnob, isNewDocument: () => Promise<boolean>): Promise<boolean> {\n try {\n if (await collabRoomExists(db(), documentId)) return true;\n } catch (err) {\n console.warn(\"[document] could not ask whether this document has a co-editing room; opening the relay room\", err);\n return false;\n }\n if (knob === \"all\") return true;\n if (knob === \"new\") return isNewDocument();\n return false;\n}\n\nfunction pickColor(uid: string): string {\n const palette = [\"#ef4444\", \"#f59e0b\", \"#10b981\", \"#3b82f6\", \"#8b5cf6\", \"#ec4899\", \"#14b8a6\", \"#f97316\"];\n let h = 2166136261;\n for (let i = 0; i < uid.length; i++) {\n h ^= uid.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return palette[Math.abs(h) % palette.length] ?? \"#ec4899\";\n}\n\nexport interface DocumentOtFactoryOptions {\n documentId: string;\n uid: string;\n /** One per open tab; never reused. */\n clientId: string;\n displayName?: string;\n readAntiEntropyIntervalMs?: () => Promise<number>;\n onNotice?: (n: DocsOtNotice) => void;\n onIncident?: (i: OpSessionIncident) => void;\n onStatus?: (s: OpSessionStatus) => void;\n}\n\n/** The `DocumentModel.startOtRoom` factory for one document. */\nexport function documentOtFactory(o: DocumentOtFactoryOptions): DocumentOtFactory {\n return async (port, onAwareness) => {\n // §7.4 / C0 surprise 5: a room's first checkpoint must be a real, Univer-normalised snapshot. A document never\n // saved gets this seat's mounted document saved first, so every seat boots from the same ids.\n const latest = await getLatestDocumentSnapshot(o.documentId);\n if (!latest.success) throw new Error(latest.error);\n if (!latest.data) {\n const mounted = port.snapshot();\n if (mounted) {\n const saved = await saveDocumentSnapshot({ documentId: o.documentId, snapshot: mounted, origin: \"autosave\" });\n if (!saved.success) throw new Error(saved.error);\n }\n }\n\n const doc = new Y.Doc();\n const awareness = new Awareness(doc);\n awareness.setLocalState({ uid: o.uid, clientId: o.clientId, name: o.displayName ?? o.uid.slice(0, 8), color: pickColor(o.uid), ts: Date.now() });\n const publishAwareness = () =>\n onAwareness({ states: new Map(awareness.getStates() as Map<number, AwarenessState>), selfUid: o.uid } satisfies DocumentAwareness);\n awareness.on(\"change\", publishAwareness);\n const provider = new SupabaseYjsProvider({\n workbookId: o.documentId,\n channelPrefix: \"document\",\n clientId: o.clientId,\n doc,\n awareness,\n ...(o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}),\n });\n await provider.connect();\n publishAwareness();\n\n const client = db();\n const room = openDocsOtRoom({\n port,\n clientId: o.clientId,\n presence: awarenessOpPresence(awareness),\n transport: supabaseOpTransport({\n client,\n roomId: o.documentId,\n kind: \"univer_doc\",\n store: {\n loadSnapshot: (ref) => loadSnapshotRow(o.documentId, ref),\n async writeSnapshot(snapshot) {\n const res = await saveDocumentSnapshot({ documentId: o.documentId, snapshot, origin: \"autosave\" });\n if (!res.success) throw new Error(res.error);\n return res.data.id;\n },\n },\n }),\n replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.documentId, snapshot, stateHash, origin: \"restore\", clientId }),\n ...(o.onNotice ? { onNotice: o.onNotice } : {}),\n ...(o.onIncident ? { onIncident: o.onIncident } : {}),\n ...(o.onStatus ? { onStatus: o.onStatus } : {}),\n });\n await room.session.ready;\n return {\n isSaver: () => room.isSaver(),\n write: (reason) => room.write(reason),\n replace: (snapshot) => room.replace(snapshot),\n stop: () => {\n room.stop();\n awareness.off(\"change\", publishAwareness);\n provider.disconnect();\n awareness.destroy();\n doc.destroy();\n },\n };\n };\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\n/**\n * An independent copy of a document: its own row, with the latest snapshot copied over, so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":"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","names":["univerMerge","Y","import_collab","Y","import_awareness","import_collab","db","pickColor"]}
|