@ai-matrx/office 0.8.45 → 0.8.46

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.
@@ -617,13 +617,14 @@ type SheetsLocalEvent = SheetsLocalGroup | SheetsNotShared;
617
617
  /** What the workbook editor lends the room (implemented by `univerSheetsOtPort`). */
618
618
  interface SheetsOtPort {
619
619
  onLocal(listener: (e: SheetsLocalEvent) => void): () => void;
620
- /** True while a local command is still running (its group is not handed over yet). */
620
+ /** True while a local command is still running (its group is not handed over yet). Every remote op waits. */
621
621
  busy(): boolean;
622
622
  /** Run `fn` once no local command is running (immediately when none is). */
623
623
  whenIdle(fn: () => void): void;
624
624
  /**
625
- * True when this remote op must wait (and so must every op after it) until `whenIdle`: the port's cell editor is
626
- * open on a cell the op touches. The held ops apply when it closes, and the person's commit is rebased over them.
625
+ * True when this remote op must wait until `whenIdle`: the port's cell editor is open on a cell the op writes, or
626
+ * the op moves or removes that cell. A later op waits behind a held one only when the two do not commute; every
627
+ * other op applies live. The held ops apply when the editor closes, and the person's commit is rebased over them.
627
628
  */
628
629
  defers?(op: SheetMutation[]): boolean;
629
630
  /** Apply one committed mutation to this seat's workbook; throws when the editor refused it. */
@@ -704,6 +705,8 @@ interface SheetsOtAdapterHooks {
704
705
  onUndoRebased?: (dropped: number) => void;
705
706
  /** Called with the milliseconds of undo bookkeeping each remote op (and each catch-up) cost (tests, logs). */
706
707
  onUndoWork?: (ms: number, kind: "remote" | "catch_up") => void;
708
+ /** The session's rev right now (the rev of the op being applied): a held op remembers it for `overrode`. */
709
+ rev?: () => number;
707
710
  /**
708
711
  * The state hash of a snapshot (default `sheetsStateHash`, Web Crypto). A seeded test passes a synchronous one:
709
712
  * Web Crypto resolves on a worker thread, outside a virtual clock, so the same seed would not replay.
@@ -714,8 +717,17 @@ interface SheetsOtAdapterHooks {
714
717
  interface SheetsOtAdapter extends OpDocumentAdapter<SheetOp> {
715
718
  /** Remote ops held while a local command runs. */
716
719
  held(): number;
717
- /** A local group finished while remote ops were held: rebase it over them and them over it (Docs IME rule). */
718
- rebaseLocalOverHeld(local: SheetMutation[]): SheetMutation[] | "barrier";
720
+ /**
721
+ * A local group finished while remote ops were held: rebase it over them and them over it (Docs IME rule).
722
+ * `overrode` names what it overrode of each held op (by the rev it was committed at), for that op's author.
723
+ */
724
+ rebaseLocalOverHeld(local: SheetMutation[]): {
725
+ op: SheetMutation[];
726
+ overrode: Array<{
727
+ rev: number;
728
+ lost: string[];
729
+ }>;
730
+ } | "barrier";
719
731
  clearHeld(): void;
720
732
  }
721
733
  declare function createSheetsOtAdapter(port: SheetsOtPort, hooks?: SheetsOtAdapterHooks): SheetsOtAdapter;
@@ -846,9 +858,10 @@ interface UniverSheetsOtPortOptions {
846
858
  * `isVisible().visible` and `getEditLocation()`). Univer rewrites an open editor's text whenever any write lands on
847
859
  * its cell (`EditorDataSyncController` → `refreshEditCellState` → the editor's `ReplaceSnapshotCommand`, caret back
848
860
  * to 0), so a peer's value landing mid-typing spliced into the draft and Enter committed the mix (the attack's
849
- * "$1,234.50" vs "$7" → 507). While the editor is open, a remote op that touches its cell or its sheet is held,
850
- * and so is everything after it: the person's draft and the cell it is committed against stay as they saw them,
851
- * and their commit is rebased over the held ops when the editor closes (the later commit wins whole).
861
+ * "$1,234.50" vs "$7" → 507). While the editor is open, a remote op whose ranges cover its cell, or that moves or
862
+ * removes it (a row/column insert, remove or move, a sheet removal, a shrink), is held: the person's draft and the
863
+ * cell it is committed against stay as they saw them, and their commit is rebased over the held ops when the editor
864
+ * closes (the later commit wins whole). Everything else applies live, so the person still sees the others work.
852
865
  */
853
866
  cellEditor?(): EditedCell | null;
854
867
  /** Replace the workbook's whole content, keeping its unit id. */
@@ -905,6 +918,13 @@ declare function univerSheetsOtPort(o: UniverSheetsOtPortOptions): SheetsOtPort
905
918
  dispose(): void;
906
919
  running(): string[];
907
920
  };
921
+ /**
922
+ * Whether a remote mutation must wait for the open cell editor: it writes the editor's cell (a value, a style, a
923
+ * merge, a format, a rule or a sort whose ranges cover it), or it moves or removes that cell (a row/column insert,
924
+ * remove or move before it, its sheet's removal, a row or column count below it). A mutation with no range on that
925
+ * sheet (a rename, a sheet order, a filter's criteria) never touches the cell. Anything this cannot read waits.
926
+ */
927
+ declare function touchesEditedCell(m: SheetMutation, at: EditedCell): boolean;
908
928
  /**
909
929
  * This seat's selections after a remote structural op: indices move with their rows/columns; one the op removed
910
930
  * lands on the first surviving index; everything is clamped to the sheet; whole-row/column ranges span the sheet.
@@ -994,4 +1014,4 @@ declare function startWorkbookOtRoom(port: SheetsOtPort & {
994
1014
  dispose?: () => void;
995
1015
  }, o: WorkbookOtRoomOptions): Promise<WorkbookOtRoomHandle>;
996
1016
 
997
- export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
1017
+ export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, touchesEditedCell, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
@@ -617,13 +617,14 @@ type SheetsLocalEvent = SheetsLocalGroup | SheetsNotShared;
617
617
  /** What the workbook editor lends the room (implemented by `univerSheetsOtPort`). */
618
618
  interface SheetsOtPort {
619
619
  onLocal(listener: (e: SheetsLocalEvent) => void): () => void;
620
- /** True while a local command is still running (its group is not handed over yet). */
620
+ /** True while a local command is still running (its group is not handed over yet). Every remote op waits. */
621
621
  busy(): boolean;
622
622
  /** Run `fn` once no local command is running (immediately when none is). */
623
623
  whenIdle(fn: () => void): void;
624
624
  /**
625
- * True when this remote op must wait (and so must every op after it) until `whenIdle`: the port's cell editor is
626
- * open on a cell the op touches. The held ops apply when it closes, and the person's commit is rebased over them.
625
+ * True when this remote op must wait until `whenIdle`: the port's cell editor is open on a cell the op writes, or
626
+ * the op moves or removes that cell. A later op waits behind a held one only when the two do not commute; every
627
+ * other op applies live. The held ops apply when the editor closes, and the person's commit is rebased over them.
627
628
  */
628
629
  defers?(op: SheetMutation[]): boolean;
629
630
  /** Apply one committed mutation to this seat's workbook; throws when the editor refused it. */
@@ -704,6 +705,8 @@ interface SheetsOtAdapterHooks {
704
705
  onUndoRebased?: (dropped: number) => void;
705
706
  /** Called with the milliseconds of undo bookkeeping each remote op (and each catch-up) cost (tests, logs). */
706
707
  onUndoWork?: (ms: number, kind: "remote" | "catch_up") => void;
708
+ /** The session's rev right now (the rev of the op being applied): a held op remembers it for `overrode`. */
709
+ rev?: () => number;
707
710
  /**
708
711
  * The state hash of a snapshot (default `sheetsStateHash`, Web Crypto). A seeded test passes a synchronous one:
709
712
  * Web Crypto resolves on a worker thread, outside a virtual clock, so the same seed would not replay.
@@ -714,8 +717,17 @@ interface SheetsOtAdapterHooks {
714
717
  interface SheetsOtAdapter extends OpDocumentAdapter<SheetOp> {
715
718
  /** Remote ops held while a local command runs. */
716
719
  held(): number;
717
- /** A local group finished while remote ops were held: rebase it over them and them over it (Docs IME rule). */
718
- rebaseLocalOverHeld(local: SheetMutation[]): SheetMutation[] | "barrier";
720
+ /**
721
+ * A local group finished while remote ops were held: rebase it over them and them over it (Docs IME rule).
722
+ * `overrode` names what it overrode of each held op (by the rev it was committed at), for that op's author.
723
+ */
724
+ rebaseLocalOverHeld(local: SheetMutation[]): {
725
+ op: SheetMutation[];
726
+ overrode: Array<{
727
+ rev: number;
728
+ lost: string[];
729
+ }>;
730
+ } | "barrier";
719
731
  clearHeld(): void;
720
732
  }
721
733
  declare function createSheetsOtAdapter(port: SheetsOtPort, hooks?: SheetsOtAdapterHooks): SheetsOtAdapter;
@@ -846,9 +858,10 @@ interface UniverSheetsOtPortOptions {
846
858
  * `isVisible().visible` and `getEditLocation()`). Univer rewrites an open editor's text whenever any write lands on
847
859
  * its cell (`EditorDataSyncController` → `refreshEditCellState` → the editor's `ReplaceSnapshotCommand`, caret back
848
860
  * to 0), so a peer's value landing mid-typing spliced into the draft and Enter committed the mix (the attack's
849
- * "$1,234.50" vs "$7" → 507). While the editor is open, a remote op that touches its cell or its sheet is held,
850
- * and so is everything after it: the person's draft and the cell it is committed against stay as they saw them,
851
- * and their commit is rebased over the held ops when the editor closes (the later commit wins whole).
861
+ * "$1,234.50" vs "$7" → 507). While the editor is open, a remote op whose ranges cover its cell, or that moves or
862
+ * removes it (a row/column insert, remove or move, a sheet removal, a shrink), is held: the person's draft and the
863
+ * cell it is committed against stay as they saw them, and their commit is rebased over the held ops when the editor
864
+ * closes (the later commit wins whole). Everything else applies live, so the person still sees the others work.
852
865
  */
853
866
  cellEditor?(): EditedCell | null;
854
867
  /** Replace the workbook's whole content, keeping its unit id. */
@@ -905,6 +918,13 @@ declare function univerSheetsOtPort(o: UniverSheetsOtPortOptions): SheetsOtPort
905
918
  dispose(): void;
906
919
  running(): string[];
907
920
  };
921
+ /**
922
+ * Whether a remote mutation must wait for the open cell editor: it writes the editor's cell (a value, a style, a
923
+ * merge, a format, a rule or a sort whose ranges cover it), or it moves or removes that cell (a row/column insert,
924
+ * remove or move before it, its sheet's removal, a row or column count below it). A mutation with no range on that
925
+ * sheet (a rename, a sheet order, a filter's criteria) never touches the cell. Anything this cannot read waits.
926
+ */
927
+ declare function touchesEditedCell(m: SheetMutation, at: EditedCell): boolean;
908
928
  /**
909
929
  * This seat's selections after a remote structural op: indices move with their rows/columns; one the op removed
910
930
  * lands on the first surviving index; everything is clamped to the sheet; whole-row/column ranges span the sheet.
@@ -994,4 +1014,4 @@ declare function startWorkbookOtRoom(port: SheetsOtPort & {
994
1014
  dispose?: () => void;
995
1015
  }, o: WorkbookOtRoomOptions): Promise<WorkbookOtRoomHandle>;
996
1016
 
997
- export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
1017
+ export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, touchesEditedCell, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
@@ -3936,6 +3936,12 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3936
3936
  function createSheetsOtAdapter(port, hooks = {}) {
3937
3937
  let queue = [];
3938
3938
  let draining = false;
3939
+ const sameOp = (a, b) => JSON.stringify(canonicalKeys(a ?? [])) === JSON.stringify(canonicalKeys(b ?? []));
3940
+ const commutesWithHeld = (op) => queue.every((q) => {
3941
+ const a = transformSheetOp(op, q.op, "left");
3942
+ const b = transformSheetOp(q.op, op, "right");
3943
+ return !("barrier" in a) && !("barrier" in b) && sameOp(a.op, op) && sameOp(b.op, q.op);
3944
+ });
3939
3945
  const lazy = typeof port.beforeUndo === "function";
3940
3946
  let pending = [];
3941
3947
  let pendingBase = 0;
@@ -4008,15 +4014,16 @@ function createSheetsOtAdapter(port, hooks = {}) {
4008
4014
  decode: decodeSheetOp,
4009
4015
  apply(op) {
4010
4016
  if (isNoopSheetOp(op)) return true;
4011
- if (port.busy() || queue.length || port.defers?.(op)) {
4012
- queue.push(op);
4017
+ const hold = port.busy() || !!port.defers?.(op) || queue.length > 0 && !commutesWithHeld(op);
4018
+ if (hold) {
4019
+ queue.push({ op, rev: hooks.rev?.() ?? 0 });
4013
4020
  if (!draining) {
4014
4021
  draining = true;
4015
4022
  port.whenIdle(() => {
4016
4023
  draining = false;
4017
4024
  const held = queue;
4018
4025
  queue = [];
4019
- for (const q of held) applyNow(q);
4026
+ for (const q of held) applyNow(q.op);
4020
4027
  });
4021
4028
  }
4022
4029
  return true;
@@ -4054,15 +4061,17 @@ function createSheetsOtAdapter(port, hooks = {}) {
4054
4061
  rebaseLocalOverHeld(local) {
4055
4062
  let op = local;
4056
4063
  const next = [];
4064
+ const overrode = [];
4057
4065
  for (const q of queue) {
4058
- const l2 = transformSheetOp(op, q, "left");
4059
- const q2 = transformSheetOp(q, op, "right");
4066
+ const l2 = transformSheetOp(op, q.op, "left");
4067
+ const q2 = transformSheetOp(q.op, op, "right");
4060
4068
  if ("barrier" in l2 || "barrier" in q2) return "barrier";
4069
+ if (l2.lost.length && q.rev > 0) overrode.push({ rev: q.rev, lost: l2.lost });
4061
4070
  op = l2.op ?? [];
4062
- if (q2.op?.length) next.push(q2.op);
4071
+ if (q2.op?.length) next.push({ op: q2.op, rev: q.rev });
4063
4072
  }
4064
4073
  queue = next;
4065
- return op;
4074
+ return { op, overrode };
4066
4075
  },
4067
4076
  clearHeld() {
4068
4077
  queue = [];
@@ -4080,7 +4089,7 @@ function openSheetsOtRoom(o) {
4080
4089
  console.warn("[sheets-ot] notice handler failed", err);
4081
4090
  }
4082
4091
  };
4083
- const adapter = createSheetsOtAdapter(port);
4092
+ const adapter = createSheetsOtAdapter(port, { rev: () => session?.rev() ?? 0 });
4084
4093
  let healing = null;
4085
4094
  const HEALS = /* @__PURE__ */ new Set(["hash_mismatch", "save_hash_mismatch", "ack_mismatch"]);
4086
4095
  const screen = () => {
@@ -4122,6 +4131,7 @@ function openSheetsOtRoom(o) {
4122
4131
  }
4123
4132
  let op = e.mutations;
4124
4133
  let inverse = e.inverse;
4134
+ let overrode = [];
4125
4135
  if (adapter.held()) {
4126
4136
  inverse = void 0;
4127
4137
  const r = adapter.rebaseLocalOverHeld(op);
@@ -4130,10 +4140,11 @@ function openSheetsOtRoom(o) {
4130
4140
  session.rebuild("held_barrier");
4131
4141
  return;
4132
4142
  }
4133
- op = r;
4143
+ op = r.op;
4144
+ overrode = r.overrode;
4134
4145
  if (!op.length) return;
4135
4146
  }
4136
- if (!session.local(op, { ...inverse !== void 0 ? { inverse } : {}, label: e.label ?? SHEETS_EDIT_GROUP })) notice({ kind: "not_live" });
4147
+ if (!session.local(op, { ...inverse !== void 0 ? { inverse } : {}, label: e.label ?? SHEETS_EDIT_GROUP, ...overrode.length ? { overrode } : {} })) notice({ kind: "not_live" });
4137
4148
  };
4138
4149
  const unsubLocal = port.onLocal(onLocal);
4139
4150
  session = openOpSession2({
@@ -4639,9 +4650,9 @@ function univerSheetsOtPort(o) {
4639
4650
  listeners.add(listener);
4640
4651
  return () => void listeners.delete(listener);
4641
4652
  },
4642
- busy: () => tracker.stack.length > 0 || group !== null || holding(),
4653
+ // the editor hold is not "busy": only the ops that touch its cell wait (defers), the rest apply live
4654
+ busy: () => tracker.stack.length > 0 || group !== null,
4643
4655
  defers(op) {
4644
- if (holding()) return true;
4645
4656
  const at = edited();
4646
4657
  if (!at || !op.some((m) => touchesEditedCell(m, at))) return false;
4647
4658
  editorHold = true;
@@ -4718,11 +4729,46 @@ function inverseStyle(prev, wrote) {
4718
4729
  return out;
4719
4730
  }
4720
4731
  function touchesEditedCell(m, at) {
4721
- const sheet = String(m.params.subUnitId ?? "");
4732
+ const p = m.params;
4733
+ const sheet = String(p.subUnitId ?? p.sheetId ?? "");
4722
4734
  if (sheet !== at.sheetId) return false;
4723
- if (m.id !== VALUES) return true;
4724
- const row = m.params.cellValue?.[at.row];
4725
- return !!row && Object.prototype.hasOwnProperty.call(row, at.col);
4735
+ if (m.id === VALUES) {
4736
+ const row = p.cellValue?.[at.row];
4737
+ return !!row && Object.prototype.hasOwnProperty.call(row, at.col);
4738
+ }
4739
+ if (m.id === REMOVE_SHEET2) return true;
4740
+ if (m.id === "sheet.mutation.set-worksheet-row-count") return !(Number(p.rowCount) > at.row);
4741
+ if (m.id === "sheet.mutation.set-worksheet-column-count") return !(Number(p.columnCount) > at.col);
4742
+ const axis = axisOpOf(m);
4743
+ if (axis) {
4744
+ const i = axis.axis === "row" ? at.row : at.col;
4745
+ return mapIndex(axis.op, i) !== i;
4746
+ }
4747
+ const ranges = [];
4748
+ let unreadable = false;
4749
+ const walk = (v, depth) => {
4750
+ if (!v || typeof v !== "object" || depth > 6) return;
4751
+ if (Array.isArray(v)) {
4752
+ for (const x of v) walk(x, depth + 1);
4753
+ return;
4754
+ }
4755
+ const o = v;
4756
+ if (["startRow", "endRow", "startColumn", "endColumn"].some((k) => k in o)) {
4757
+ const r = o;
4758
+ if (![r.startRow, r.endRow, r.startColumn, r.endColumn].every((n) => typeof n === "number" && Number.isFinite(n)) && !(r.rangeType && r.rangeType > 0)) unreadable = true;
4759
+ else ranges.push(r);
4760
+ return;
4761
+ }
4762
+ if (typeof o.row === "number" && typeof o.col === "number") ranges.push({ startRow: o.row, endRow: o.row, startColumn: o.col, endColumn: o.col });
4763
+ for (const x of Object.values(o)) walk(x, depth + 1);
4764
+ };
4765
+ walk(p, 0);
4766
+ return unreadable || ranges.some((r) => covers(r, at));
4767
+ }
4768
+ function covers(r, at) {
4769
+ const rows = r.rangeType === 2 || r.rangeType === 3 || r.startRow <= at.row && at.row <= r.endRow;
4770
+ const cols = r.rangeType === 1 || r.rangeType === 3 || r.startColumn <= at.col && at.col <= r.endColumn;
4771
+ return rows && cols;
4726
4772
  }
4727
4773
  function fullContent(cell) {
4728
4774
  const out = {};
@@ -5078,6 +5124,7 @@ export {
5078
5124
  startWorkbookOtRoom,
5079
5125
  stripSenderView,
5080
5126
  takeCovered,
5127
+ touchesEditedCell,
5081
5128
  transformDocsOp,
5082
5129
  transformSheetOp,
5083
5130
  transformTextX,