@vuer-ai/vuer-rtc 0.1.3 → 0.2.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.
Files changed (162) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/.claude-plugin/skills/vuer-rtc.md +158 -0
  4. package/.pytest_cache/README.md +8 -0
  5. package/README.md +27 -12
  6. package/dist/client/EditBuffer.d.ts +10 -0
  7. package/dist/client/EditBuffer.d.ts.map +1 -1
  8. package/dist/client/EditBuffer.js +19 -1
  9. package/dist/client/EditBuffer.js.map +1 -1
  10. package/dist/client/actions.d.ts +12 -14
  11. package/dist/client/actions.d.ts.map +1 -1
  12. package/dist/client/actions.js +298 -164
  13. package/dist/client/actions.js.map +1 -1
  14. package/dist/client/createGraph.d.ts.map +1 -1
  15. package/dist/client/createGraph.js +4 -7
  16. package/dist/client/createGraph.js.map +1 -1
  17. package/dist/client/index.d.ts +2 -0
  18. package/dist/client/index.d.ts.map +1 -1
  19. package/dist/client/index.js +2 -0
  20. package/dist/client/index.js.map +1 -1
  21. package/dist/client/types.d.ts +2 -1
  22. package/dist/client/types.d.ts.map +1 -1
  23. package/dist/crdt/BTree.d.ts +102 -0
  24. package/dist/crdt/BTree.d.ts.map +1 -0
  25. package/dist/crdt/BTree.js +461 -0
  26. package/dist/crdt/BTree.js.map +1 -0
  27. package/dist/crdt/ContentTree.d.ts +102 -0
  28. package/dist/crdt/ContentTree.d.ts.map +1 -0
  29. package/dist/crdt/ContentTree.js +461 -0
  30. package/dist/crdt/ContentTree.js.map +1 -0
  31. package/dist/crdt/Rope.d.ts +31 -63
  32. package/dist/crdt/Rope.d.ts.map +1 -1
  33. package/dist/crdt/Rope.js +429 -306
  34. package/dist/crdt/Rope.js.map +1 -1
  35. package/dist/crdt/index.d.ts +2 -2
  36. package/dist/crdt/index.d.ts.map +1 -1
  37. package/dist/crdt/index.js +2 -2
  38. package/dist/crdt/index.js.map +1 -1
  39. package/dist/index.d.ts +4 -2
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +5 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/operations/OperationTypes.d.ts +70 -9
  44. package/dist/operations/OperationTypes.d.ts.map +1 -1
  45. package/dist/operations/OperationValidator.d.ts +2 -0
  46. package/dist/operations/OperationValidator.d.ts.map +1 -1
  47. package/dist/operations/OperationValidator.js +37 -5
  48. package/dist/operations/OperationValidator.js.map +1 -1
  49. package/dist/operations/apply/array.js +4 -4
  50. package/dist/operations/apply/array.js.map +1 -1
  51. package/dist/operations/apply/boolean.js +3 -3
  52. package/dist/operations/apply/boolean.js.map +1 -1
  53. package/dist/operations/apply/color.js +2 -2
  54. package/dist/operations/apply/color.js.map +1 -1
  55. package/dist/operations/apply/euler.js +2 -2
  56. package/dist/operations/apply/euler.js.map +1 -1
  57. package/dist/operations/apply/index.d.ts +2 -2
  58. package/dist/operations/apply/index.d.ts.map +1 -1
  59. package/dist/operations/apply/index.js +2 -2
  60. package/dist/operations/apply/index.js.map +1 -1
  61. package/dist/operations/apply/node.d.ts +11 -1
  62. package/dist/operations/apply/node.d.ts.map +1 -1
  63. package/dist/operations/apply/node.js +62 -8
  64. package/dist/operations/apply/node.js.map +1 -1
  65. package/dist/operations/apply/number.js +5 -5
  66. package/dist/operations/apply/number.js.map +1 -1
  67. package/dist/operations/apply/object.js +5 -5
  68. package/dist/operations/apply/object.js.map +1 -1
  69. package/dist/operations/apply/quaternion.js +2 -2
  70. package/dist/operations/apply/quaternion.js.map +1 -1
  71. package/dist/operations/apply/string.js +2 -2
  72. package/dist/operations/apply/string.js.map +1 -1
  73. package/dist/operations/apply/text.d.ts +6 -2
  74. package/dist/operations/apply/text.d.ts.map +1 -1
  75. package/dist/operations/apply/text.js +48 -11
  76. package/dist/operations/apply/text.js.map +1 -1
  77. package/dist/operations/apply/types.d.ts +7 -3
  78. package/dist/operations/apply/types.d.ts.map +1 -1
  79. package/dist/operations/apply/types.js +47 -8
  80. package/dist/operations/apply/types.js.map +1 -1
  81. package/dist/operations/apply/vector3.js +5 -5
  82. package/dist/operations/apply/vector3.js.map +1 -1
  83. package/dist/operations/dispatcher.d.ts.map +1 -1
  84. package/dist/operations/dispatcher.js +25 -2
  85. package/dist/operations/dispatcher.js.map +1 -1
  86. package/dist/operations/index.d.ts +1 -1
  87. package/dist/operations/index.d.ts.map +1 -1
  88. package/dist/operations/index.js.map +1 -1
  89. package/dist/serdes.d.ts +47 -0
  90. package/dist/serdes.d.ts.map +1 -0
  91. package/dist/serdes.js +21 -0
  92. package/dist/serdes.js.map +1 -0
  93. package/dist/sync/BloomFilter.d.ts +31 -0
  94. package/dist/sync/BloomFilter.d.ts.map +1 -0
  95. package/dist/sync/BloomFilter.js +113 -0
  96. package/dist/sync/BloomFilter.js.map +1 -0
  97. package/dist/sync/digest.d.ts +28 -0
  98. package/dist/sync/digest.d.ts.map +1 -0
  99. package/dist/sync/digest.js +33 -0
  100. package/dist/sync/digest.js.map +1 -0
  101. package/dist/sync/index.d.ts +3 -0
  102. package/dist/sync/index.d.ts.map +1 -0
  103. package/dist/sync/index.js +3 -0
  104. package/dist/sync/index.js.map +1 -0
  105. package/docs/RETRY.md +1 -1
  106. package/docs/rope-optimization-plan.md +329 -0
  107. package/examples/01-basic-usage.ts +4 -4
  108. package/examples/02-concurrent-edits.ts +7 -7
  109. package/examples/03-scene-building.ts +8 -8
  110. package/examples/04-conflict-resolution.ts +19 -19
  111. package/examples/README.md +5 -0
  112. package/package.json +4 -2
  113. package/skills/vuer-rtc/SKILL.md +164 -0
  114. package/src/client/EditBuffer.ts +17 -1
  115. package/src/client/actions.ts +307 -171
  116. package/src/client/createGraph.ts +5 -15
  117. package/src/client/index.ts +13 -0
  118. package/src/client/types.ts +2 -1
  119. package/src/crdt/BTree.ts +567 -0
  120. package/src/crdt/Rope.ts +470 -355
  121. package/src/crdt/index.ts +6 -2
  122. package/src/index.ts +11 -1
  123. package/src/operations/OperationTypes.ts +63 -11
  124. package/src/operations/OperationValidator.ts +45 -5
  125. package/src/operations/apply/array.ts +4 -4
  126. package/src/operations/apply/boolean.ts +3 -3
  127. package/src/operations/apply/color.ts +2 -2
  128. package/src/operations/apply/euler.ts +2 -2
  129. package/src/operations/apply/index.ts +2 -1
  130. package/src/operations/apply/node.ts +69 -9
  131. package/src/operations/apply/number.ts +5 -5
  132. package/src/operations/apply/object.ts +5 -5
  133. package/src/operations/apply/quaternion.ts +2 -2
  134. package/src/operations/apply/string.ts +2 -2
  135. package/src/operations/apply/text.ts +56 -10
  136. package/src/operations/apply/types.ts +56 -8
  137. package/src/operations/apply/vector3.ts +5 -5
  138. package/src/operations/dispatcher.ts +24 -2
  139. package/src/operations/index.ts +5 -0
  140. package/src/serdes.ts +39 -0
  141. package/src/sync/BloomFilter.ts +124 -0
  142. package/src/sync/digest.ts +45 -0
  143. package/src/sync/index.ts +2 -0
  144. package/tests/client/actions.test.ts +269 -5
  145. package/tests/crdt/btree.test.ts +455 -0
  146. package/tests/crdt/rope-benchmark.test.ts +67 -0
  147. package/tests/crdt/rope.test.ts +682 -13
  148. package/tests/crdt/text-operations.test.ts +3 -2
  149. package/tests/fixtures/benchmark_data/automerge-paper.json.gz +0 -0
  150. package/tests/fixtures/benchmark_data/clownschool_flat.json.gz +0 -0
  151. package/tests/fixtures/benchmark_data/friendsforever_flat.json.gz +0 -0
  152. package/tests/fixtures/benchmark_data/rustcode.json.gz +0 -0
  153. package/tests/fixtures/benchmark_data/seph-blog1.json.gz +0 -0
  154. package/tests/fixtures/benchmark_data/sveltecomponent.json.gz +0 -0
  155. package/tests/helpers/loadBenchmarkData.ts +63 -0
  156. package/tests/operations/collections.test.ts +1 -1
  157. package/tests/operations/nodes.test.ts +3 -3
  158. package/tests/operations/primitives.test.ts +1 -1
  159. package/tests/operations/unified-schema.test.ts +1 -1
  160. package/tests/operations/vectors.test.ts +1 -1
  161. package/tests/sync/bloom-filter.test.ts +83 -0
  162. package/tests/sync/digest.test.ts +77 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "vuer-rtc",
3
+ "owner": {
4
+ "name": "Ge Yang"
5
+ },
6
+ "description": "CRDT-based real-time collaborative state management for 3D scenes",
7
+ "plugins": [
8
+ {
9
+ "name": "vuer-rtc",
10
+ "source": "./",
11
+ "description": "vuer-rtc skills for real-time collaborative 3D scene editing"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "vuer-rtc",
3
+ "version": "0.1.3",
4
+ "description": "CRDT-based real-time collaborative state management for 3D scenes",
5
+ "author": {
6
+ "name": "Ge Yang"
7
+ },
8
+ "repository": "https://github.com/vuer-ai/vuer-rtc-workspace",
9
+ "license": "MIT",
10
+ "keywords": ["crdt", "real-time", "collaboration", "3d", "scene-graph"],
11
+ "skills": "./skills/"
12
+ }
@@ -0,0 +1,158 @@
1
+ # vuer-rtc Skill
2
+
3
+ CRDT-based real-time collaborative state management for 3D scenes and text.
4
+
5
+ ## When to Use This Skill
6
+
7
+ Use when the user is working with:
8
+ - Real-time collaborative editing (multiplayer)
9
+ - Scene graph state management
10
+ - Collaborative text editing (TextRope CRDT)
11
+ - Undo/redo that syncs across clients
12
+ - React hooks for vuer-rtc
13
+
14
+ ## Package Structure
15
+
16
+ ```
17
+ @vuer-ai/vuer-rtc
18
+ ├── client/ → State management, actions, journal
19
+ ├── crdt/ → TextRope for collaborative text
20
+ ├── operations/ → Scene graph CRDT operations
21
+ ├── hooks.ts → React integration
22
+ └── index.ts → Main exports
23
+ ```
24
+
25
+ ## Quick Patterns
26
+
27
+ ### 1. Basic Setup
28
+ ```typescript
29
+ import { createGraph } from '@vuer-ai/vuer-rtc';
30
+
31
+ const store = createGraph({
32
+ sessionId: 'user-123',
33
+ onSend: (msg) => websocket.send(JSON.stringify(msg)),
34
+ });
35
+
36
+ websocket.onmessage = (e) => store.receive(JSON.parse(e.data));
37
+ ```
38
+
39
+ ### 2. Edit → Commit Flow
40
+ ```typescript
41
+ // Edits are local-only until committed
42
+ store.edit({ otype: 'vector3.set', key: 'cube', path: 'position', value: [1, 2, 3] });
43
+ store.edit({ otype: 'number.set', key: 'cube', path: 'opacity', value: 0.5 });
44
+
45
+ // Commit sends all edits as one message
46
+ store.commit('Update cube');
47
+
48
+ // Or cancel uncommitted edits
49
+ store.cancel();
50
+ ```
51
+
52
+ ### 3. Undo/Redo (Synced)
53
+ ```typescript
54
+ store.undo(); // Creates meta.undo message, syncs to all clients
55
+ store.redo(); // Creates meta.redo message, syncs to all clients
56
+ ```
57
+
58
+ ### 4. React Hooks
59
+ ```typescript
60
+ import { useGraph, useNode, useUndo } from '@vuer-ai/vuer-rtc';
61
+
62
+ function Component() {
63
+ const store = useGraph();
64
+ const cube = useNode('cube-1');
65
+ const { undo, redo, canUndo, canRedo } = useUndo();
66
+
67
+ return <mesh position={cube?.position} />;
68
+ }
69
+ ```
70
+
71
+ ### 5. TextRope (Collaborative Text)
72
+ ```typescript
73
+ import { create, getText, insertWithSplit, remove, replace } from '@vuer-ai/vuer-rtc/crdt';
74
+
75
+ const rope = create('agent-1');
76
+ insertWithSplit(rope, 0, 'Hello');
77
+ replace(rope, 0, 5, 'Hi'); // Atomic delete+insert
78
+ console.log(getText(rope)); // "Hi"
79
+ ```
80
+
81
+ ## Operation Types (Quick Reference)
82
+
83
+ | Category | Operations |
84
+ |----------|------------|
85
+ | **Numbers** | `number.set`, `number.add`, `number.multiply`, `number.min`, `number.max` |
86
+ | **Vectors** | `vector3.set`, `vector3.add`, `vector3.multiply` |
87
+ | **Rotations** | `quaternion.set`, `euler.set` |
88
+ | **Booleans** | `boolean.set`, `boolean.and`, `boolean.or` |
89
+ | **Collections** | `array.set`, `array.push`, `array.remove`, `object.set`, `object.merge` |
90
+ | **Nodes** | `node.insert`, `node.remove` |
91
+ | **Text** | `text.init`, `text.insert`, `text.delete` |
92
+ | **Meta** | `meta.undo`, `meta.redo` |
93
+
94
+ ## Conflict Resolution
95
+
96
+ | Pattern | Strategy |
97
+ |---------|----------|
98
+ | `*.set` | Last-Write-Wins (higher lamport timestamp) |
99
+ | `*.add`, `*.multiply` | Commutative merge |
100
+ | `meta.undo/redo` | Marks `deletedAt` on target message |
101
+
102
+ ## Detailed Documentation
103
+
104
+ For in-depth API references, fetch these docs:
105
+
106
+ | Topic | URL |
107
+ |-------|-----|
108
+ | **Architecture** | https://rtc.vuer.ai/architecture |
109
+ | **Operations** | https://rtc.vuer.ai/operations |
110
+ | **TextRope CRDT** | https://rtc.vuer.ai/rope |
111
+ | **React Hooks** | https://rtc.vuer.ai/react-hooks |
112
+ | **Server Setup** | https://rtc.vuer.ai/server |
113
+ | **Examples** | https://rtc.vuer.ai/examples |
114
+
115
+ ## Common Tasks
116
+
117
+ ### Add a node to scene
118
+ ```typescript
119
+ store.edit({
120
+ otype: 'node.insert',
121
+ key: 'parent-key', // Parent node ('' for root)
122
+ path: 'children',
123
+ value: { key: 'new-node', tag: 'Mesh', name: 'Cube' },
124
+ });
125
+ store.commit('Add cube');
126
+ ```
127
+
128
+ ### Update node property
129
+ ```typescript
130
+ store.edit({
131
+ otype: 'vector3.set',
132
+ key: 'cube-1',
133
+ path: 'position',
134
+ value: [1, 2, 3],
135
+ });
136
+ ```
137
+
138
+ ### Initialize collaborative text
139
+ ```typescript
140
+ store.edit({ otype: 'text.init', key: 'doc-1', path: 'content', value: 'Hello' });
141
+ store.edit({ otype: 'text.insert', key: 'doc-1', path: 'content', position: 5, value: ' World' });
142
+ ```
143
+
144
+ ### Handle reconnection
145
+ ```typescript
146
+ // Get unacked messages to resend
147
+ const pending = store.getUnackedMessages();
148
+ pending.forEach(msg => websocket.send(JSON.stringify(msg)));
149
+ ```
150
+
151
+ ## Troubleshooting
152
+
153
+ | Issue | Solution |
154
+ |-------|----------|
155
+ | Edits not syncing | Check `store.commit()` was called |
156
+ | Undo not working | Ensure target message is acked by server |
157
+ | Text interleaving | Use `insertWithSplit()` instead of `insert()` |
158
+ | State divergence | Verify all clients receive same messages |
@@ -0,0 +1,8 @@
1
+ # pytest cache directory #
2
+
3
+ This directory contains data from the pytest's cache plugin,
4
+ which provides the `--lf` and `--ff` options, as well as the `cache` fixture.
5
+
6
+ **Do not** commit this to version control.
7
+
8
+ See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.
package/README.md CHANGED
@@ -8,6 +8,19 @@ CRDT-based real-time collaborative state management for 3D scenes.
8
8
  pnpm add @vuer-ai/vuer-rtc
9
9
  ```
10
10
 
11
+ ## Claude Code Skill
12
+
13
+ Add vuer-rtc knowledge to Claude Code for CRDT-based real-time collaboration assistance:
14
+
15
+ ```bash
16
+ # Plugin marketplace
17
+ /plugin marketplace add vuer-ai/vuer-rtc-workspace
18
+ /plugin install vuer-rtc@vuer-rtc
19
+
20
+ # Or add to your CLAUDE.md
21
+ # @import https://raw.githubusercontent.com/vuer-ai/vuer-rtc-workspace/main/skill/vuer-rtc.md
22
+ ```
23
+
11
24
  ## Quick Start
12
25
 
13
26
  ```typescript
@@ -80,18 +93,20 @@ function Node({ nodeKey }: { nodeKey: string }) {
80
93
 
81
94
  ## Operation Types
82
95
 
83
- | Category | Operations |
84
- |----------|-----------|
85
- | Number | `number.set`, `number.add`, `number.multiply`, `number.min`, `number.max` |
86
- | Vector3 | `vector3.set`, `vector3.add`, `vector3.multiply` |
87
- | Quaternion | `quaternion.set`, `quaternion.multiply` |
88
- | Color | `color.set`, `color.blend` |
89
- | String | `string.set`, `string.concat` |
90
- | Boolean | `boolean.set`, `boolean.or`, `boolean.and` |
91
- | Array | `array.set`, `array.push`, `array.union`, `array.remove` |
92
- | Object | `object.set`, `object.merge` |
93
- | Node | `node.insert`, `node.remove` |
94
- | Meta | `meta.undo`, `meta.redo` |
96
+ | Category | Operations | Merge Behavior |
97
+ |----------|-----------|----------------|
98
+ | Node | `node.insert`, `node.remove`, `node.move` | Idempotent / Tombstone |
99
+ | Text | `text.init`, `text.insert`, `text.delete`, `text.replace` | CRDT (YATA) |
100
+ | Number | `number.set`, `number.add`, `number.multiply`, `number.min`, `number.max` | LWW / Commutative |
101
+ | String | `string.set`, `string.concat` | LWW / Append |
102
+ | Boolean | `boolean.set`, `boolean.or`, `boolean.and` | LWW / Commutative |
103
+ | Vector3 | `vector3.set`, `vector3.add`, `vector3.multiply`, `vector3.applyEuler`, `vector3.applyQuaternion` | LWW / Commutative |
104
+ | Euler | `euler.set`, `euler.add` | LWW / Commutative |
105
+ | Quaternion | `quaternion.set`, `quaternion.multiply` | LWW / Commutative |
106
+ | Color | `color.set`, `color.blend` | LWW / Blend |
107
+ | Array | `array.set`, `array.push`, `array.union`, `array.remove` | LWW / Set ops |
108
+ | Object | `object.set`, `object.merge` | LWW / Merge |
109
+ | Meta | `meta.undo`, `meta.redo` | Journal-based |
95
110
 
96
111
  ## Documentation
97
112
 
@@ -5,6 +5,16 @@
5
5
  * Merges additive operations to reduce message size.
6
6
  */
7
7
  import type { Operation } from '../operations/OperationTypes.js';
8
+ /**
9
+ * Compute the dedup key for an operation.
10
+ *
11
+ * Property operations use `key:path` — e.g. two `vector3.set` on the
12
+ * same node+path should merge/replace.
13
+ *
14
+ * Node structural operations include the target node key so that
15
+ * multiple inserts/removes under the same parent are NOT deduped.
16
+ */
17
+ export declare function opDedupKey(op: Operation): string;
8
18
  /**
9
19
  * Check if an operation type is additive (can be merged)
10
20
  */
@@ -1 +1 @@
1
- {"version":3,"file":"EditBuffer.d.ts","sourceRoot":"","sources":["../../src/client/EditBuffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKnD;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;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAKnD;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"}
@@ -4,6 +4,24 @@
4
4
  * Accumulates uncommitted operations during gestures (e.g., dragging).
5
5
  * Merges additive operations to reduce message size.
6
6
  */
7
+ /**
8
+ * Compute the dedup key for an operation.
9
+ *
10
+ * Property operations use `key:path` — e.g. two `vector3.set` on the
11
+ * same node+path should merge/replace.
12
+ *
13
+ * Node structural operations include the target node key so that
14
+ * multiple inserts/removes under the same parent are NOT deduped.
15
+ */
16
+ export function opDedupKey(op) {
17
+ if (op.otype === 'node.insert')
18
+ return `${op.key}:${op.path}:insert:${op.value.key}`;
19
+ if (op.otype === 'node.remove')
20
+ return `${op.key}:${op.path}:remove:${op.value}`;
21
+ if (op.otype === 'node.move')
22
+ return `${op.key}:${op.path}:move:${op.value.nodeKey}`;
23
+ return `${op.key}:${op.path}`;
24
+ }
7
25
  /**
8
26
  * Check if an operation type is additive (can be merged)
9
27
  */
@@ -52,7 +70,7 @@ export class EditBufferImpl {
52
70
  * Add or merge an operation
53
71
  */
54
72
  add(op) {
55
- const key = `${op.key}:${op.path}`;
73
+ const key = opDedupKey(op);
56
74
  const existing = this.opsMap.get(key);
57
75
  if (existing && existing.otype === op.otype && isAdditiveOp(op.otype)) {
58
76
  // Merge additive ops
@@ -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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"}
@@ -3,11 +3,14 @@
3
3
  *
4
4
  * Pure functions that transform ClientState.
5
5
  * Used by createGraph and React hooks.
6
+ *
7
+ * No Immer — manual immutable state construction to avoid proxy issues
8
+ * with mutable CRDT structures (TextRope, B-tree back-pointers, WeakMaps).
6
9
  */
7
10
  import type { CRDTMessage, Operation, SceneGraph } from '../operations/OperationTypes.js';
8
11
  import type { ClientState, JournalEntry, Snapshot } from './types.js';
9
12
  /**
10
- * Generate a UUID
13
+ * Generate a compact session ID (12-char nanoid, 2^72 entropy)
11
14
  */
12
15
  export declare function generateUUID(): string;
13
16
  /**
@@ -56,31 +59,26 @@ export declare function redo(state: ClientState): {
56
59
  msg: CRDTMessage | null;
57
60
  };
58
61
  /**
59
- * Action: Compact (create snapshot from acked entries)
62
+ * Action: Compact (create snapshot from acked entries).
63
+ *
64
+ * Folds all acknowledged entries into the snapshot and removes them from
65
+ * the journal. This reduces journal size (and bloom filter size for sync)
66
+ * but compacted entries can no longer be undone.
67
+ *
68
+ * Call this manually or on a periodic timer. Not called automatically
69
+ * because undo() requires target entries to be in the journal.
60
70
  */
61
71
  export declare function compact(state: ClientState): ClientState;
62
72
  /**
63
73
  * Get unacknowledged messages for retry
64
- *
65
- * Returns messages that haven't been acknowledged by the server.
66
- * Use this for implementing retry logic on network failures.
67
- *
68
- * @param state - Current client state
69
- * @returns Array of messages that need to be (re)sent to server
70
74
  */
71
75
  export declare function getUnackedMessages(state: ClientState): CRDTMessage[];
72
76
  /**
73
77
  * Check if there are pending messages to send
74
- *
75
- * @param state - Current client state
76
- * @returns True if there are unacknowledged messages
77
78
  */
78
79
  export declare function hasPendingMessages(state: ClientState): boolean;
79
80
  /**
80
81
  * Get count of pending (unacked) messages
81
- *
82
- * @param state - Current client state
83
- * @returns Number of unacknowledged messages
84
82
  */
85
83
  export declare function getPendingCount(state: ClientState): number;
86
84
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/client/actions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtE;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAkB7F;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,EAAE,EACvB,UAAU,EAAE,SAAS,EAAE,GACtB,UAAU,CA4BZ;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,GAAG,WAAW,CAqCrE;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,CA6BjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAa3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAO1E;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,CAqDxF;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAyCxF;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA2BvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAIpE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE9D;AAED;;;;;GAKG;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,CAqCb"}
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;AAQtE;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAkB7F;AAmGD;;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,CAiErE;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,CA0BjD;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;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CA0BvD;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,CAqCb"}