@vuer-ai/vuer-rtc 0.4.2 → 0.5.0

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.
Files changed (89) hide show
  1. package/CLAUDE.md +29 -0
  2. package/COALESCE_FIX_VERIFICATION.md +81 -0
  3. package/REFACTORING_NOTES.md +229 -0
  4. package/dist/client/EditBuffer.d.ts +13 -1
  5. package/dist/client/EditBuffer.d.ts.map +1 -1
  6. package/dist/client/EditBuffer.js +47 -3
  7. package/dist/client/EditBuffer.js.map +1 -1
  8. package/dist/client/actions.d.ts +5 -1
  9. package/dist/client/actions.d.ts.map +1 -1
  10. package/dist/client/actions.js +12 -9
  11. package/dist/client/actions.js.map +1 -1
  12. package/dist/client/coalesceGraphOps.d.ts +34 -0
  13. package/dist/client/coalesceGraphOps.d.ts.map +1 -0
  14. package/dist/client/coalesceGraphOps.js +35 -0
  15. package/dist/client/coalesceGraphOps.js.map +1 -0
  16. package/dist/client/coalesceTextOperations.d.ts +42 -0
  17. package/dist/client/coalesceTextOperations.d.ts.map +1 -0
  18. package/dist/client/coalesceTextOperations.js +119 -0
  19. package/dist/client/coalesceTextOperations.js.map +1 -0
  20. package/dist/client/coalescence/index.d.ts +9 -0
  21. package/dist/client/coalescence/index.d.ts.map +1 -0
  22. package/dist/client/coalescence/index.js +9 -0
  23. package/dist/client/coalescence/index.js.map +1 -0
  24. package/dist/client/coalescence/registry.d.ts +48 -0
  25. package/dist/client/coalescence/registry.d.ts.map +1 -0
  26. package/dist/client/coalescence/registry.js +95 -0
  27. package/dist/client/coalescence/registry.js.map +1 -0
  28. package/dist/client/coalescence/textDeletes.d.ts +38 -0
  29. package/dist/client/coalescence/textDeletes.d.ts.map +1 -0
  30. package/dist/client/coalescence/textDeletes.js +68 -0
  31. package/dist/client/coalescence/textDeletes.js.map +1 -0
  32. package/dist/client/coalescence/textInserts.d.ts +45 -0
  33. package/dist/client/coalescence/textInserts.d.ts.map +1 -0
  34. package/dist/client/coalescence/textInserts.js +96 -0
  35. package/dist/client/coalescence/textInserts.js.map +1 -0
  36. package/dist/client/createGraph.d.ts.map +1 -1
  37. package/dist/client/createGraph.js +9 -2
  38. package/dist/client/createGraph.js.map +1 -1
  39. package/dist/client/createTextDocument.d.ts.map +1 -1
  40. package/dist/client/createTextDocument.js +2 -1
  41. package/dist/client/createTextDocument.js.map +1 -1
  42. package/dist/client/index.d.ts +4 -0
  43. package/dist/client/index.d.ts.map +1 -1
  44. package/dist/client/index.js +4 -0
  45. package/dist/client/index.js.map +1 -1
  46. package/dist/client/textActions.d.ts +1 -1
  47. package/dist/client/textActions.d.ts.map +1 -1
  48. package/dist/client/textActions.js +7 -2
  49. package/dist/client/textActions.js.map +1 -1
  50. package/dist/client/types.d.ts +3 -0
  51. package/dist/client/types.d.ts.map +1 -1
  52. package/dist/crdt/GraphTextCRDT.d.ts +0 -4
  53. package/dist/crdt/GraphTextCRDT.d.ts.map +1 -1
  54. package/dist/crdt/GraphTextCRDT.js +3 -0
  55. package/dist/crdt/GraphTextCRDT.js.map +1 -1
  56. package/dist/crdt/Rope.d.ts +27 -6
  57. package/dist/crdt/Rope.d.ts.map +1 -1
  58. package/dist/crdt/Rope.js +137 -69
  59. package/dist/crdt/Rope.js.map +1 -1
  60. package/dist/operations/OperationTypes.d.ts +10 -26
  61. package/dist/operations/OperationTypes.d.ts.map +1 -1
  62. package/dist/operations/apply/text.d.ts.map +1 -1
  63. package/dist/operations/apply/text.js +8 -16
  64. package/dist/operations/apply/text.js.map +1 -1
  65. package/examples/05-coalescence-usage.ts +189 -0
  66. package/package.json +1 -1
  67. package/src/client/EditBuffer.ts +51 -3
  68. package/src/client/actions.ts +13 -9
  69. package/src/client/coalesceGraphOps.ts +40 -0
  70. package/src/client/coalesceTextOperations.ts +134 -0
  71. package/src/client/coalescence/index.ts +18 -0
  72. package/src/client/coalescence/registry.ts +137 -0
  73. package/src/client/coalescence/textDeletes.ts +94 -0
  74. package/src/client/coalescence/textInserts.ts +128 -0
  75. package/src/client/createGraph.ts +11 -2
  76. package/src/client/createTextDocument.ts +2 -1
  77. package/src/client/index.ts +14 -0
  78. package/src/client/textActions.ts +9 -2
  79. package/src/client/types.ts +4 -1
  80. package/src/crdt/GraphTextCRDT.ts +0 -5
  81. package/src/crdt/Rope.ts +155 -79
  82. package/src/operations/OperationTypes.ts +10 -8
  83. package/src/operations/apply/text.ts +8 -20
  84. package/test-coalescence.ts +201 -0
  85. package/tests/client/actions.test.ts +156 -0
  86. package/tests/client/coalesce-text-operations.test.ts +327 -0
  87. package/tests/client/edit-buffer.test.ts +137 -1
  88. package/tests/crdt/graph-text-crdt.test.ts +29 -17
  89. package/tests/crdt/rope.test.ts +13 -11
package/CLAUDE.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # vuer-rtc Development Notes
2
2
 
3
+ ## Development Practices
4
+
5
+ ### Implementation Review Process
6
+
7
+ **Always have implementations reviewed before considering them complete.**
8
+
9
+ When implementing new features or making significant code changes:
10
+
11
+ 1. Use a subagent to implement the feature (non-blocking)
12
+ 2. Once implementation is complete, launch a **separate review subagent** to critique the work
13
+ 3. The review agent should check for:
14
+ - Code quality and correctness
15
+ - Edge cases and error handling
16
+ - Performance considerations
17
+ - Documentation completeness
18
+ - Consistency with existing patterns
19
+ 4. Address any issues found during review
20
+ 5. Only then consider the implementation complete
21
+
22
+ **Example workflow:**
23
+ ```
24
+ Agent A: Implement feature X
25
+ Agent B: Review Agent A's implementation, provide critique
26
+ Address Agent B's feedback
27
+ Deploy
28
+ ```
29
+
30
+ This ensures high-quality implementations and catches issues early.
31
+
3
32
  ## Text Architecture (3-Component Design)
4
33
 
5
34
  The text handling system uses a 3-component architecture with clear separation of concerns:
@@ -0,0 +1,81 @@
1
+ # Coalescence Bug Fix Verification
2
+
3
+ ## Problem
4
+ The YATA chain validation was failing after the first merge because merged operations kept the first character's ID, but the next character's `parentId` pointed to the last character in the merged content.
5
+
6
+ **Example of the bug:**
7
+ ```
8
+ Operations: ['H', 'e', 'l', 'l', 'o']
9
+ IDs: ['alice:1', 'alice:2', 'alice:3', 'alice:4', 'alice:5']
10
+ ParentIds: [null, 'alice:1', 'alice:2', 'alice:3', 'alice:4']
11
+
12
+ First merge: 'H' + 'e' = 'He'
13
+ - Merged op ID: 'alice:1' (keeps first ID)
14
+ - Merged op content: 'He'
15
+
16
+ Second merge attempt: 'He' + 'l'
17
+ - Chain validation: currOp.parentId === prevOp.id?
18
+ - 'alice:2' === 'alice:1'? ❌ FALSE
19
+ - FAILS TO MERGE (only got 'He', not 'Hello')
20
+ ```
21
+
22
+ ## Solution
23
+ Track the last character's ID in merged operations using `_lastCharId` metadata, then use that for chain validation.
24
+
25
+ ```typescript
26
+ const prevLastId = (prevOp as any)._lastCharId || prevOp.id;
27
+ const formsChain =
28
+ currOp.parentId === prevLastId ||
29
+ (prevOp.parentId === currOp.parentId && prevOp.parentId !== null);
30
+ ```
31
+
32
+ **How it works:**
33
+ ```
34
+ Operations: ['H', 'e', 'l', 'l', 'o']
35
+
36
+ First merge: 'H' + 'e' = 'He'
37
+ - op.id: 'alice:1'
38
+ - op._lastCharId: 'alice:2' ✓ (tracks last char)
39
+
40
+ Second merge: 'He' + 'l'
41
+ - Chain validation: currOp.parentId === prevLastId?
42
+ - 'alice:2' === 'alice:2' ✓ TRUE
43
+ - Merges successfully!
44
+ - op.id: 'alice:1'
45
+ - op._lastCharId: 'alice:3' ✓ (updated)
46
+
47
+ Third merge: 'Hel' + 'l'
48
+ - Chain validation: currOp.parentId === prevLastId?
49
+ - 'alice:3' === 'alice:3' ✓ TRUE
50
+ - Merges successfully!
51
+
52
+ Fourth merge: 'Hell' + 'o'
53
+ - Chain validation: currOp.parentId === prevLastId?
54
+ - 'alice:4' === 'alice:4' ✓ TRUE
55
+ - Final result: 'Hello' ✓
56
+ ```
57
+
58
+ ## Test Results
59
+ All tests pass:
60
+ - ✅ Multi-character coalescence (5 ops → 1 op with "Hello")
61
+ - ✅ Time threshold respected (separate ops when typing slowly)
62
+ - ✅ Different agents don't coalesce
63
+ - ✅ Delete operations flush pending inserts
64
+ - ✅ Metadata tracking verified
65
+
66
+ ## Files Changed
67
+ - `/Users/ge/claudespace/vuer-rtc-workspace/packages/vuer-rtc/src/client/coalesceTextOperations.ts`
68
+ - Added `_lastCharId` tracking in merged operations (line 87)
69
+ - Updated chain validation to use `prevLastId` (lines 73-76)
70
+
71
+ ## Testing
72
+ Run tests:
73
+ ```bash
74
+ pnpm test coalesce-text-operations.test.ts
75
+ ```
76
+
77
+ Manual verification in dev server:
78
+ 1. Enable coalescence
79
+ 2. Type "Hello" quickly (within 300ms)
80
+ 3. Export debug JSON
81
+ 4. Verify ONE operation with content="Hello"
@@ -0,0 +1,229 @@
1
+ # CRDT Refactoring: String IDs and Timestamp Tie-Breaking
2
+
3
+ ## Summary
4
+
5
+ Refactored the CRDT implementation to use string-based IDs and timestamp-based tie-breaking for improved performance and deterministic conflict resolution.
6
+
7
+ ## Changes
8
+
9
+ ### 1. ItemId Type Change (Rope.ts)
10
+
11
+ **Before:**
12
+ ```typescript
13
+ export interface ItemId {
14
+ agent: string;
15
+ seq: number;
16
+ }
17
+ ```
18
+
19
+ **After:**
20
+ ```typescript
21
+ export type ItemId = string; // Format: "agent:seq"
22
+ ```
23
+
24
+ **Rationale:**
25
+ - String IDs are more efficient for comparison (native string comparison vs object property access)
26
+ - Smaller serialization footprint
27
+ - Simpler equality checks (`===` instead of comparing object properties)
28
+ - Still human-readable for debugging
29
+
30
+ ### 2. Timestamp Field Addition
31
+
32
+ **Added to Item and Operations:**
33
+ ```typescript
34
+ export interface Item {
35
+ id: ItemId;
36
+ content: string;
37
+ isDeleted: boolean;
38
+ parentId: ItemId | null;
39
+ seq: number; // Lamport timestamp for total ordering
40
+ ts: number; // Wall-clock time (seconds) for tie-breaking
41
+ }
42
+ ```
43
+
44
+ **Rationale:**
45
+ - Provides deterministic tie-breaking when Lamport timestamps are equal
46
+ - Wall-clock time is more stable than agent ID comparison
47
+ - Helps with convergence in concurrent editing scenarios
48
+
49
+ ### 3. Helper Functions
50
+
51
+ **Added:**
52
+ ```typescript
53
+ export function parseItemId(id: ItemId): { agent: string; seq: number }
54
+ export function createItemId(agent: string, seq: number): ItemId
55
+ ```
56
+
57
+ These functions encapsulate the string format conversion, making the codebase more maintainable.
58
+
59
+ ### 4. Updated Comparison Logic (integrate function)
60
+
61
+ **Before:**
62
+ ```typescript
63
+ if (existingParentOrdinal === parentOrdinal && newItem.seq === existingItem.seq) {
64
+ if (itemIdCompare(newItem.id, existingItem.id) < 0) break;
65
+ }
66
+ ```
67
+
68
+ **After:**
69
+ ```typescript
70
+ if (existingParentOrdinal === parentOrdinal && newItem.seq === existingItem.seq) {
71
+ // Use ts for tie-breaking (earlier ts wins - inserts first)
72
+ if (newItem.ts < existingItem.ts) {
73
+ break;
74
+ }
75
+ // If ts also equal (rare), fall back to ID comparison for determinism
76
+ if (newItem.ts === existingItem.ts && itemIdCompare(newItem.id, existingItem.id) < 0) {
77
+ break;
78
+ }
79
+ }
80
+ ```
81
+
82
+ **Rationale:**
83
+ - Primary ordering: Lamport timestamp (seq)
84
+ - Secondary tie-breaking: Wall-clock timestamp (ts)
85
+ - Tertiary tie-breaking: ItemId string comparison (for determinism)
86
+
87
+ ### 5. Operation Types Updated
88
+
89
+ All text operations now include the `ts` field:
90
+
91
+ ```typescript
92
+ export interface TextInsertOp extends BaseOp {
93
+ key: string;
94
+ otype: 'text.insert';
95
+ path: string;
96
+ // Position-based format
97
+ position?: number;
98
+ value?: string;
99
+ // CRDT metadata format
100
+ id?: string; // ItemId string format: "agent:seq"
101
+ content?: string;
102
+ parentId?: string | null;
103
+ seq?: number;
104
+ ts?: number; // Wall-clock time (seconds) for tie-breaking
105
+ }
106
+ ```
107
+
108
+ ### 6. Test Updates
109
+
110
+ All tests updated to use string IDs and include timestamps:
111
+
112
+ **Before:**
113
+ ```typescript
114
+ const op: InsertOp = {
115
+ id: { agent: 'session-2', seq: 0 },
116
+ content: 'Hello',
117
+ parentId: null,
118
+ seq: 1,
119
+ };
120
+ ```
121
+
122
+ **After:**
123
+ ```typescript
124
+ const op: InsertOp = {
125
+ id: 'session-2:0',
126
+ content: 'Hello',
127
+ parentId: null,
128
+ seq: 1,
129
+ ts: Date.now() / 1000,
130
+ };
131
+ ```
132
+
133
+ ## Files Modified
134
+
135
+ 1. **src/crdt/Rope.ts**
136
+ - Changed ItemId type to string
137
+ - Added helper functions (parseItemId, createItemId)
138
+ - Updated integrate() for timestamp tie-breaking
139
+ - Fixed all ID creation/comparison code
140
+ - Fixed compact(), merge(), replace(), fromRaw() functions
141
+
142
+ 2. **src/operations/OperationTypes.ts**
143
+ - Added `ts` field to TextInsertOp, TextDeleteOp, TextReplaceOp
144
+ - Updated documentation for timestamp usage
145
+
146
+ 3. **src/operations/apply/text.ts**
147
+ - Updated operation handlers to pass `ts` field
148
+ - Ensured all operations generate timestamps
149
+
150
+ 4. **src/crdt/GraphTextCRDT.ts**
151
+ - Removed old ItemId interface (no longer needed)
152
+
153
+ 5. **tests/crdt/graph-text-crdt.test.ts**
154
+ - Updated all test cases to use string IDs
155
+ - Added timestamps to all operations
156
+ - Fixed 13 test cases total
157
+
158
+ 6. **tests/crdt/rope.test.ts**
159
+ - Updated ItemId test cases to use strings
160
+ - Fixed ID parsing in tests
161
+
162
+ 7. **tests/client/actions.test.ts**
163
+ - Updated CRDT metadata checks for string IDs
164
+
165
+ ## Performance Impact
166
+
167
+ ### Positive Impacts:
168
+
169
+ 1. **Faster ID Comparison**: String comparison is a native operation, faster than comparing object properties
170
+ 2. **Smaller Serialization**: Strings are more compact than objects in JSON/MessagePack
171
+ 3. **Less Memory Allocation**: Strings are immutable and can be interned
172
+ 4. **Better GC Performance**: Fewer object allocations means less garbage collection overhead
173
+
174
+ ### Neutral Changes:
175
+
176
+ 1. **Timestamp Addition**: Adds 8 bytes per item (float64), but provides deterministic ordering
177
+ 2. **Helper Functions**: parseItemId() called when needed, minimal overhead
178
+
179
+ ### Measured Performance:
180
+
181
+ All benchmarks still pass with similar performance:
182
+ - friendsforever_flat: 726,287 patches/sec (unchanged)
183
+ - sveltecomponent: 508,072 patches/sec (unchanged)
184
+ - clownschool_flat: 613,116 patches/sec (unchanged)
185
+ - rustcode: 477,242 patches/sec (unchanged)
186
+
187
+ ## Migration Guide
188
+
189
+ If you have existing code using the old format:
190
+
191
+ **Old Code:**
192
+ ```typescript
193
+ const id = { agent: 'user-1', seq: 42 };
194
+ if (id.agent === 'user-1') { ... }
195
+ ```
196
+
197
+ **New Code:**
198
+ ```typescript
199
+ const id = createItemId('user-1', 42); // Returns 'user-1:42'
200
+ const parsed = parseItemId(id); // Returns { agent: 'user-1', seq: 42 }
201
+ if (parsed.agent === 'user-1') { ... }
202
+ ```
203
+
204
+ ## Testing
205
+
206
+ All 440 tests pass:
207
+ - 17 test suites
208
+ - 440 tests passed
209
+ - 1 test skipped
210
+ - No regressions
211
+
212
+ ## Breaking Changes
213
+
214
+ 1. **ItemId format**: Any code directly accessing `id.agent` or `id.seq` needs to use `parseItemId(id)`
215
+ 2. **Operation format**: Operations now require `ts` field for proper ordering
216
+ 3. **Serialization**: Old serialized data with object-format IDs needs migration
217
+
218
+ ## Future Work
219
+
220
+ 1. Consider adding migration utility for old serialized data
221
+ 2. Monitor performance in production for any unexpected impacts
222
+ 3. Evaluate if timestamp precision needs adjustment (currently seconds)
223
+ 4. Consider using monotonic timestamps for better determinism
224
+
225
+ ## References
226
+
227
+ - YATA algorithm: https://www.researchgate.net/publication/310212186_Near_Real-Time_Peer-to-Peer_Shared_Editing_on_Extensible_Data_Types
228
+ - CRDT overview: https://crdt.tech/
229
+ - String ID comparison: https://tc39.es/ecma262/#sec-abstract-relational-comparison
@@ -52,7 +52,7 @@ interface PositionTextDeleteOp {
52
52
  */
53
53
  export declare function isPositionTextDeleteOp(op: Operation): op is PositionTextDeleteOp;
54
54
  /**
55
- * Coalesce consecutive text operations in an operation array.
55
+ * Coalesce consecutive text operations (position-based format only).
56
56
  * Merges sequential text.insert and text.delete operations.
57
57
  *
58
58
  * Insert: Consecutive inserts at adjacent positions
@@ -64,6 +64,18 @@ export declare function isPositionTextDeleteOp(op: Operation): op is PositionTex
64
64
  * - Backward (Backspace): Position moves left by length
65
65
  * del(10, 1), del(9, 1) → del(9, 2)
66
66
  *
67
+ * IMPORTANT: This function is for POSITION-BASED coalescence only.
68
+ * Operations with CRDT metadata (id, parentId, seq) are skipped and passed through unchanged.
69
+ * For CRDT-level coalescence, use coalesceGraphOps() instead.
70
+ *
71
+ * Why the distinction?
72
+ * - Position-based: Coalesce before CRDT conversion (edit buffer stage)
73
+ * - CRDT-level: Coalesce after CRDT conversion (journal/network stage)
74
+ *
75
+ * Currently, the graph store flow applies CRDT metadata during onEdit(),
76
+ * so this function is not used for graph text operations.
77
+ * See coalesceGraphOps() for CRDT-level coalescence.
78
+ *
67
79
  * Returns a new array with coalesced operations.
68
80
  */
69
81
  export declare function coalesceTextOps(ops: Operation[]): Operation[];
@@ -1 +1 @@
1
- {"version":3,"file":"EditBuffer.d.ts","sourceRoot":"","sources":["../../src/client/EditBuffer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAQhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,oBAAoB,CAIhF;AAED;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,oBAAoB,CAIhF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAwI7D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAyB1E;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,OAAO,CAAgB;IAE/B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAiBxB;;OAEG;IACH,MAAM,IAAI,SAAS,EAAE;IAIrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf"}
1
+ {"version":3,"file":"EditBuffer.d.ts","sourceRoot":"","sources":["../../src/client/EditBuffer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAQhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,oBAAoB,CAIhF;AAED;;GAEG;AACH,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,SAAS,GAAG,EAAE,IAAI,oBAAoB,CAIhF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA4K7D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAyB1E;AAED;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,OAAO,CAAgB;IAE/B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI;IAiBxB;;OAEG;IACH,MAAM,IAAI,SAAS,EAAE;IAIrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf"}
@@ -57,7 +57,7 @@ export function isPositionTextDeleteOp(op) {
57
57
  typeof op.length === 'number';
58
58
  }
59
59
  /**
60
- * Coalesce consecutive text operations in an operation array.
60
+ * Coalesce consecutive text operations (position-based format only).
61
61
  * Merges sequential text.insert and text.delete operations.
62
62
  *
63
63
  * Insert: Consecutive inserts at adjacent positions
@@ -69,6 +69,18 @@ export function isPositionTextDeleteOp(op) {
69
69
  * - Backward (Backspace): Position moves left by length
70
70
  * del(10, 1), del(9, 1) → del(9, 2)
71
71
  *
72
+ * IMPORTANT: This function is for POSITION-BASED coalescence only.
73
+ * Operations with CRDT metadata (id, parentId, seq) are skipped and passed through unchanged.
74
+ * For CRDT-level coalescence, use coalesceGraphOps() instead.
75
+ *
76
+ * Why the distinction?
77
+ * - Position-based: Coalesce before CRDT conversion (edit buffer stage)
78
+ * - CRDT-level: Coalesce after CRDT conversion (journal/network stage)
79
+ *
80
+ * Currently, the graph store flow applies CRDT metadata during onEdit(),
81
+ * so this function is not used for graph text operations.
82
+ * See coalesceGraphOps() for CRDT-level coalescence.
83
+ *
72
84
  * Returns a new array with coalesced operations.
73
85
  */
74
86
  export function coalesceTextOps(ops) {
@@ -79,12 +91,28 @@ export function coalesceTextOps(ops) {
79
91
  let pendingDelete = null;
80
92
  for (const op of ops) {
81
93
  if (isPositionTextInsertOp(op)) {
94
+ // Check if operation has CRDT metadata - if so, don't coalesce it
95
+ const hasCRDTMetadata = op.id !== undefined;
96
+ if (hasCRDTMetadata) {
97
+ // Flush any pending operations
98
+ if (pendingInsert !== null) {
99
+ result.push(pendingInsert);
100
+ pendingInsert = null;
101
+ }
102
+ if (pendingDelete !== null) {
103
+ result.push(pendingDelete);
104
+ pendingDelete = null;
105
+ }
106
+ // Pass through operations with CRDT metadata unchanged
107
+ result.push(op);
108
+ continue;
109
+ }
82
110
  // Flush any pending delete
83
111
  if (pendingDelete !== null) {
84
112
  result.push(pendingDelete);
85
113
  pendingDelete = null;
86
114
  }
87
- // Coalesce inserts
115
+ // Coalesce inserts (only for position-based operations without CRDT metadata)
88
116
  if (pendingInsert === null) {
89
117
  // Start new pending insert
90
118
  pendingInsert = {
@@ -120,12 +148,28 @@ export function coalesceTextOps(ops) {
120
148
  }
121
149
  }
122
150
  else if (isPositionTextDeleteOp(op)) {
151
+ // Check if operation has CRDT metadata - if so, don't coalesce it
152
+ const hasCRDTMetadata = op.deletions !== undefined;
153
+ if (hasCRDTMetadata) {
154
+ // Flush any pending operations
155
+ if (pendingInsert !== null) {
156
+ result.push(pendingInsert);
157
+ pendingInsert = null;
158
+ }
159
+ if (pendingDelete !== null) {
160
+ result.push(pendingDelete);
161
+ pendingDelete = null;
162
+ }
163
+ // Pass through operations with CRDT metadata unchanged
164
+ result.push(op);
165
+ continue;
166
+ }
123
167
  // Flush any pending insert
124
168
  if (pendingInsert !== null) {
125
169
  result.push(pendingInsert);
126
170
  pendingInsert = null;
127
171
  }
128
- // Coalesce deletes
172
+ // Coalesce deletes (only for position-based operations without CRDT metadata)
129
173
  if (pendingDelete === null) {
130
174
  pendingDelete = {
131
175
  otype: 'text.delete',
@@ -1 +1 @@
1
- {"version":3,"file":"EditBuffer.js","sourceRoot":"","sources":["../../src/client/EditBuffer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EditBuffer.js","sourceRoot":"","sources":["../../src/client/EditBuffer.ts"],"names":[],"mappings":"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"}
@@ -28,8 +28,12 @@ export declare function rebuildGraph(snapshot: Snapshot, journal: JournalEntry[]
28
28
  export declare function onEdit(state: ClientState, op: Operation): ClientState;
29
29
  /**
30
30
  * Action: Commit edits
31
+ *
32
+ * @param state - Current client state
33
+ * @param description - Optional message description
34
+ * @param coalescingThresholdMs - Time threshold for operation coalescence (default: no coalescence)
31
35
  */
32
- export declare function commitEdits(state: ClientState, _description?: string): {
36
+ export declare function commitEdits(state: ClientState, description?: string, coalescingThresholdMs?: number): {
33
37
  state: ClientState;
34
38
  msg: CRDTMessage | null;
35
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/client/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAa,MAAM,iCAAiC,CAAC;AACrG,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAM/E;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAkB7F;AAyGD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,UAAU,EAAE,SAAS,EAAE,GACtB,UAAU,CAkCZ;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,GAAG,WAAW,CAgErE;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CA8BjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAU3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAK1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,GAAG,WAAW,CA8BjF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAyDxF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAoDxF;AAyCD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA6BvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,GAAG,WAAW,CA4C1F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAIpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,EAAE,GACrB,WAAW,CA8Cb"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/client/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAa,MAAM,iCAAiC,CAAC;AACrG,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAO/E;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAkB7F;AAyGD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,UAAU,EAAE,SAAS,EAAE,GACtB,UAAU,CAkCZ;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,GAAG,WAAW,CA4DrE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,WAAW,CAAC,EAAE,MAAM,EACpB,qBAAqB,CAAC,EAAE,MAAM,GAC7B;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAgCjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAU3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAK1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,GAAG,WAAW,CA8BjF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAyDxF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAoDxF;AAyCD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA6BvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,GAAG,WAAW,CA4C1F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAIpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,WAAW,EAAE,GACrB,WAAW,CA8Cb"}
@@ -10,8 +10,9 @@
10
10
  import { nanoid } from 'nanoid';
11
11
  import { applyMessage, applyOperation, createEmptyGraph } from '../operations/dispatcher.js';
12
12
  import { VectorClockManager } from '../state/VectorClock.js';
13
- import { isAdditiveOp, mergeValues, opDedupKey, coalesceTextOps } from './EditBuffer.js';
13
+ import { isAdditiveOp, mergeValues, opDedupKey } from './EditBuffer.js';
14
14
  import { TextRope, snapshot as cloneRope, compact as compactRope } from '../crdt/Rope.js';
15
+ import { coalesceGraphOps } from './coalesceGraphOps.js';
15
16
  const clockManager = new VectorClockManager();
16
17
  /**
17
18
  * Generate a compact session ID (12-char nanoid, 2^72 entropy)
@@ -218,15 +219,11 @@ export function onEdit(state, op) {
218
219
  }
219
220
  for (const k of new Set(keysToClone)) {
220
221
  const orig = graph.nodes[k];
222
+ // Shallow clone preserves TextRope references (they're mutated in place)
221
223
  const cloned = {
222
224
  ...orig,
223
225
  children: orig.children ? [...orig.children] : [],
224
226
  };
225
- for (const prop of Object.keys(cloned)) {
226
- if (cloned[prop] instanceof TextRope) {
227
- cloned[prop] = cloneRope(cloned[prop]);
228
- }
229
- }
230
227
  graph.nodes[k] = cloned;
231
228
  }
232
229
  applyOperation(graph, op, {
@@ -243,15 +240,21 @@ export function onEdit(state, op) {
243
240
  }
244
241
  /**
245
242
  * Action: Commit edits
243
+ *
244
+ * @param state - Current client state
245
+ * @param description - Optional message description
246
+ * @param coalescingThresholdMs - Time threshold for operation coalescence (default: no coalescence)
246
247
  */
247
- export function commitEdits(state, _description) {
248
+ export function commitEdits(state, description, coalescingThresholdMs) {
248
249
  if (state.edits.ops.length === 0) {
249
250
  return { state, msg: null };
250
251
  }
251
252
  const newClock = clockManager.increment(state.vectorClock, state.sessionId);
252
253
  const newLamport = state.lamportTime + 1;
253
- // Coalesce consecutive text operations before sending
254
- const coalescedOps = coalesceTextOps(state.edits.ops);
254
+ // Coalesce CRDT operations before sending (if threshold specified)
255
+ const coalescedOps = coalescingThresholdMs !== undefined
256
+ ? coalesceGraphOps(state.edits.ops, { thresholdMs: coalescingThresholdMs })
257
+ : state.edits.ops;
255
258
  const msg = {
256
259
  id: `${state.sessionId}:${newLamport}`,
257
260
  sessionId: state.sessionId,