@abloatai/ablo 0.26.0 → 0.28.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 (418) hide show
  1. package/CHANGELOG.md +42 -2
  2. package/README.md +102 -86
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +134 -151
  5. package/dist/Database.d.ts +68 -69
  6. package/dist/Database.js +316 -135
  7. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  8. package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
  9. package/dist/LazyReferenceCollection.d.ts +11 -15
  10. package/dist/LazyReferenceCollection.js +12 -16
  11. package/dist/Model.d.ts +54 -52
  12. package/dist/Model.js +78 -62
  13. package/dist/ModelRegistry.d.ts +21 -19
  14. package/dist/ModelRegistry.js +23 -27
  15. package/dist/NetworkMonitor.d.ts +5 -6
  16. package/dist/NetworkMonitor.js +5 -6
  17. package/dist/SyncClient.d.ts +122 -118
  18. package/dist/SyncClient.js +541 -245
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +10 -9
  22. package/dist/adapters/inMemoryStorage.js +21 -9
  23. package/dist/agent/Agent.d.ts +27 -32
  24. package/dist/agent/Agent.js +18 -19
  25. package/dist/agent/index.d.ts +4 -4
  26. package/dist/agent/index.js +5 -5
  27. package/dist/agent/session.d.ts +47 -44
  28. package/dist/agent/session.js +37 -48
  29. package/dist/agent/types.d.ts +26 -31
  30. package/dist/agent/types.js +6 -7
  31. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  32. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  33. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  34. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
  35. package/dist/ai-sdk/index.d.ts +25 -22
  36. package/dist/ai-sdk/index.js +25 -22
  37. package/dist/ai-sdk/wrap.d.ts +6 -7
  38. package/dist/ai-sdk/wrap.js +1 -1
  39. package/dist/auth/credentialPolicy.d.ts +69 -74
  40. package/dist/auth/credentialPolicy.js +51 -56
  41. package/dist/auth/credentialSource.d.ts +6 -5
  42. package/dist/auth/credentialSource.js +9 -10
  43. package/dist/auth/index.d.ts +59 -58
  44. package/dist/auth/index.js +31 -37
  45. package/dist/auth/schemas.d.ts +5 -4
  46. package/dist/auth/schemas.js +5 -4
  47. package/dist/batching/index.d.ts +19 -21
  48. package/dist/batching/index.js +14 -17
  49. package/dist/cli.cjs +173 -121
  50. package/dist/client/Ablo.d.ts +97 -74
  51. package/dist/client/Ablo.js +129 -163
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +442 -81
  54. package/dist/client/auth.d.ts +47 -47
  55. package/dist/client/auth.js +108 -117
  56. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  57. package/dist/client/claimHeartbeatLoop.js +88 -0
  58. package/dist/client/consoleLogger.d.ts +5 -6
  59. package/dist/client/consoleLogger.js +5 -6
  60. package/dist/client/createInternalComponents.d.ts +16 -17
  61. package/dist/client/createInternalComponents.js +26 -31
  62. package/dist/client/createModelProxy.d.ts +130 -120
  63. package/dist/client/createModelProxy.js +152 -122
  64. package/dist/client/credentialEndpoint.d.ts +40 -42
  65. package/dist/client/credentialEndpoint.js +35 -36
  66. package/dist/client/functionalUpdate.d.ts +29 -27
  67. package/dist/client/functionalUpdate.js +21 -21
  68. package/dist/client/hostedEndpoints.d.ts +9 -12
  69. package/dist/client/hostedEndpoints.js +9 -12
  70. package/dist/client/httpClient.d.ts +59 -53
  71. package/dist/client/httpClient.js +29 -31
  72. package/dist/client/identity.d.ts +15 -20
  73. package/dist/client/identity.js +47 -58
  74. package/dist/client/modelRegistration.d.ts +5 -9
  75. package/dist/client/modelRegistration.js +78 -87
  76. package/dist/client/options.d.ts +157 -157
  77. package/dist/client/options.js +3 -7
  78. package/dist/client/registerDataSource.d.ts +9 -9
  79. package/dist/client/registerDataSource.js +15 -16
  80. package/dist/client/resourceTypes.d.ts +64 -75
  81. package/dist/client/resourceTypes.js +4 -10
  82. package/dist/client/schemaConfig.d.ts +31 -43
  83. package/dist/client/schemaConfig.js +38 -50
  84. package/dist/client/sessionMint.d.ts +16 -12
  85. package/dist/client/sessionMint.js +26 -31
  86. package/dist/client/validateAbloOptions.d.ts +12 -14
  87. package/dist/client/validateAbloOptions.js +8 -9
  88. package/dist/client/writeOptionsSchema.d.ts +18 -16
  89. package/dist/client/writeOptionsSchema.js +23 -20
  90. package/dist/client/wsMutationExecutor.d.ts +16 -20
  91. package/dist/client/wsMutationExecutor.js +18 -23
  92. package/dist/commit/contract.d.ts +493 -0
  93. package/dist/commit/contract.js +187 -0
  94. package/dist/commit/index.d.ts +6 -0
  95. package/dist/commit/index.js +5 -0
  96. package/dist/context.d.ts +6 -4
  97. package/dist/context.js +6 -4
  98. package/dist/coordination/index.d.ts +10 -8
  99. package/dist/coordination/index.js +14 -12
  100. package/dist/coordination/schema.d.ts +176 -128
  101. package/dist/coordination/schema.js +197 -133
  102. package/dist/coordination/trace.d.ts +9 -10
  103. package/dist/coordination/trace.js +13 -14
  104. package/dist/core/DatabaseManager.d.ts +5 -7
  105. package/dist/core/DatabaseManager.js +15 -19
  106. package/dist/core/QueryProcessor.d.ts +7 -9
  107. package/dist/core/QueryProcessor.js +22 -28
  108. package/dist/core/QueryView.d.ts +8 -8
  109. package/dist/core/QueryView.js +2 -2
  110. package/dist/core/StoreManager.d.ts +14 -14
  111. package/dist/core/StoreManager.js +33 -24
  112. package/dist/core/ViewRegistry.d.ts +5 -5
  113. package/dist/core/ViewRegistry.js +4 -4
  114. package/dist/core/index.d.ts +17 -12
  115. package/dist/core/index.js +32 -26
  116. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  117. package/dist/core/openIDBWithTimeout.js +42 -43
  118. package/dist/core/queryUtils.d.ts +45 -0
  119. package/dist/core/queryUtils.js +69 -0
  120. package/dist/core/storeContract.d.ts +63 -61
  121. package/dist/core/storeContract.js +8 -12
  122. package/dist/environment.d.ts +28 -0
  123. package/dist/environment.js +21 -0
  124. package/dist/errorCodes.d.ts +107 -99
  125. package/dist/errorCodes.js +137 -134
  126. package/dist/errors.d.ts +160 -166
  127. package/dist/errors.js +155 -158
  128. package/dist/index.d.ts +36 -27
  129. package/dist/index.js +91 -86
  130. package/dist/interfaces/index.d.ts +102 -113
  131. package/dist/interfaces/index.js +5 -4
  132. package/dist/keys/index.d.ts +27 -29
  133. package/dist/keys/index.js +41 -40
  134. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  135. package/dist/mutators/RecordingTransaction.js +31 -37
  136. package/dist/mutators/Transaction.d.ts +18 -26
  137. package/dist/mutators/Transaction.js +14 -20
  138. package/dist/mutators/UndoManager.d.ts +124 -131
  139. package/dist/mutators/UndoManager.js +177 -156
  140. package/dist/mutators/defineMutators.d.ts +23 -34
  141. package/dist/mutators/defineMutators.js +14 -20
  142. package/dist/mutators/inverseOp.d.ts +12 -15
  143. package/dist/mutators/inverseOp.js +12 -15
  144. package/dist/mutators/mutateActions.d.ts +10 -9
  145. package/dist/mutators/mutateActions.js +1 -1
  146. package/dist/mutators/readerActions.d.ts +9 -8
  147. package/dist/mutators/readerActions.js +2 -2
  148. package/dist/mutators/undoApply.d.ts +31 -27
  149. package/dist/mutators/undoApply.js +26 -24
  150. package/dist/policy/index.d.ts +5 -3
  151. package/dist/policy/index.js +5 -3
  152. package/dist/policy/types.d.ts +104 -100
  153. package/dist/policy/types.js +67 -66
  154. package/dist/query/client.d.ts +28 -23
  155. package/dist/query/client.js +45 -43
  156. package/dist/query/types.d.ts +37 -60
  157. package/dist/query/types.js +13 -33
  158. package/dist/react/AbloProvider.d.ts +1 -1
  159. package/dist/react/AbloProvider.js +2 -2
  160. package/dist/react/context.d.ts +25 -28
  161. package/dist/react/context.js +9 -10
  162. package/dist/react/index.d.ts +41 -42
  163. package/dist/react/index.js +37 -38
  164. package/dist/react/internalContext.d.ts +17 -19
  165. package/dist/react/useAblo.d.ts +28 -25
  166. package/dist/react/useAblo.js +41 -17
  167. package/dist/react/useCurrentUserId.d.ts +8 -7
  168. package/dist/react/useCurrentUserId.js +8 -7
  169. package/dist/react/useErrorListener.d.ts +7 -7
  170. package/dist/react/useErrorListener.js +10 -11
  171. package/dist/react/useMutationFailureListener.d.ts +8 -8
  172. package/dist/react/useMutationFailureListener.js +8 -8
  173. package/dist/react/useMutators.d.ts +11 -11
  174. package/dist/react/useMutators.js +3 -3
  175. package/dist/react/useReactive.js +2 -2
  176. package/dist/react/useSyncStatus.d.ts +4 -6
  177. package/dist/react/useUndoScope.d.ts +7 -9
  178. package/dist/react/useUndoScope.js +1 -1
  179. package/dist/schema/coordination.d.ts +21 -25
  180. package/dist/schema/coordination.js +21 -25
  181. package/dist/schema/ddl.d.ts +43 -39
  182. package/dist/schema/ddl.js +75 -68
  183. package/dist/schema/ddlLock.d.ts +20 -24
  184. package/dist/schema/ddlLock.js +18 -23
  185. package/dist/schema/diff.d.ts +99 -61
  186. package/dist/schema/diff.js +43 -34
  187. package/dist/schema/field.d.ts +37 -42
  188. package/dist/schema/field.js +35 -48
  189. package/dist/schema/generate.d.ts +12 -12
  190. package/dist/schema/generate.js +12 -12
  191. package/dist/schema/index.d.ts +3 -3
  192. package/dist/schema/index.js +21 -23
  193. package/dist/schema/model.d.ts +118 -143
  194. package/dist/schema/model.js +22 -33
  195. package/dist/schema/openapi.d.ts +10 -9
  196. package/dist/schema/openapi.js +5 -3
  197. package/dist/schema/queries.d.ts +29 -31
  198. package/dist/schema/queries.js +23 -25
  199. package/dist/schema/relation.d.ts +89 -99
  200. package/dist/schema/relation.js +13 -13
  201. package/dist/schema/residency.d.ts +16 -13
  202. package/dist/schema/residency.js +16 -13
  203. package/dist/schema/roles.d.ts +36 -43
  204. package/dist/schema/roles.js +31 -37
  205. package/dist/schema/schema.d.ts +64 -43
  206. package/dist/schema/schema.js +31 -32
  207. package/dist/schema/select.d.ts +13 -13
  208. package/dist/schema/select.js +13 -13
  209. package/dist/schema/serialize.d.ts +28 -31
  210. package/dist/schema/serialize.js +27 -31
  211. package/dist/schema/sugar.d.ts +17 -32
  212. package/dist/schema/sugar.js +14 -29
  213. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  214. package/dist/schema/syncDeltaRow.js +89 -0
  215. package/dist/schema/tenancy.d.ts +44 -46
  216. package/dist/schema/tenancy.js +46 -48
  217. package/dist/server/adapter.d.ts +58 -58
  218. package/dist/server/adapter.js +13 -14
  219. package/dist/server/commit.d.ts +60 -64
  220. package/dist/server/index.d.ts +9 -10
  221. package/dist/server/index.js +1 -1
  222. package/dist/server/readConfig.d.ts +70 -0
  223. package/dist/server/readConfig.js +8 -0
  224. package/dist/server/storageMode.d.ts +23 -0
  225. package/dist/server/storageMode.js +17 -0
  226. package/dist/source/adapter.d.ts +30 -25
  227. package/dist/source/adapter.js +10 -10
  228. package/dist/source/adapters/drizzle.d.ts +28 -23
  229. package/dist/source/adapters/drizzle.js +30 -25
  230. package/dist/source/adapters/kysely.d.ts +27 -25
  231. package/dist/source/adapters/kysely.js +24 -23
  232. package/dist/source/adapters/memory.d.ts +8 -7
  233. package/dist/source/adapters/memory.js +9 -8
  234. package/dist/source/adapters/prisma.d.ts +13 -12
  235. package/dist/source/adapters/prisma.js +22 -25
  236. package/dist/source/conformance.d.ts +18 -11
  237. package/dist/source/conformance.js +17 -11
  238. package/dist/source/connector.d.ts +31 -32
  239. package/dist/source/connector.js +28 -28
  240. package/dist/source/connectorProtocol.d.ts +160 -0
  241. package/dist/source/connectorProtocol.js +162 -0
  242. package/dist/source/contract.d.ts +26 -27
  243. package/dist/source/contract.js +28 -29
  244. package/dist/source/factory.d.ts +46 -58
  245. package/dist/source/factory.js +22 -27
  246. package/dist/source/index.d.ts +7 -9
  247. package/dist/source/index.js +12 -14
  248. package/dist/source/migrations.d.ts +9 -9
  249. package/dist/source/migrations.js +9 -9
  250. package/dist/source/next.d.ts +9 -10
  251. package/dist/source/next.js +6 -7
  252. package/dist/source/pushQueue.d.ts +69 -47
  253. package/dist/source/pushQueue.js +32 -28
  254. package/dist/source/signing.d.ts +46 -17
  255. package/dist/source/signing.js +28 -11
  256. package/dist/source/types.d.ts +121 -104
  257. package/dist/source/types.js +13 -14
  258. package/dist/stores/ObjectStore.d.ts +24 -12
  259. package/dist/stores/ObjectStore.js +38 -16
  260. package/dist/stores/ObjectStoreContract.d.ts +14 -15
  261. package/dist/stores/SyncActionStore.d.ts +7 -11
  262. package/dist/stores/SyncActionStore.js +13 -17
  263. package/dist/surface.d.ts +28 -21
  264. package/dist/surface.js +29 -20
  265. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  266. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  267. package/dist/sync/ConnectionManager.d.ts +39 -50
  268. package/dist/sync/ConnectionManager.js +55 -66
  269. package/dist/sync/NetworkProbe.d.ts +24 -29
  270. package/dist/sync/NetworkProbe.js +63 -69
  271. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  272. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  273. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  274. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  275. package/dist/sync/SyncWebSocket.d.ts +141 -166
  276. package/dist/sync/SyncWebSocket.js +191 -223
  277. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  278. package/dist/sync/awaitClaimGrant.js +11 -11
  279. package/dist/sync/bootstrapApply.d.ts +34 -24
  280. package/dist/sync/bootstrapApply.js +27 -19
  281. package/dist/sync/commitFrames.d.ts +21 -20
  282. package/dist/sync/commitFrames.js +18 -18
  283. package/dist/sync/createClaimStream.d.ts +23 -22
  284. package/dist/sync/createClaimStream.js +105 -23
  285. package/dist/sync/createPresenceStream.d.ts +19 -18
  286. package/dist/sync/createPresenceStream.js +25 -26
  287. package/dist/sync/createSnapshot.d.ts +12 -14
  288. package/dist/sync/createSnapshot.js +20 -26
  289. package/dist/sync/credentialLifecycle.d.ts +104 -104
  290. package/dist/sync/credentialLifecycle.js +140 -147
  291. package/dist/sync/deltaPipeline.d.ts +36 -34
  292. package/dist/sync/deltaPipeline.js +64 -65
  293. package/dist/sync/groupChange.d.ts +63 -61
  294. package/dist/sync/groupChange.js +74 -78
  295. package/dist/sync/heartbeat.d.ts +34 -33
  296. package/dist/sync/heartbeat.js +31 -31
  297. package/dist/sync/participants.d.ts +19 -19
  298. package/dist/sync/persistedPrefix.d.ts +12 -0
  299. package/dist/sync/persistedPrefix.js +22 -0
  300. package/dist/sync/schemas.d.ts +3 -2
  301. package/dist/sync/schemas.js +14 -10
  302. package/dist/sync/syncCursor.d.ts +17 -21
  303. package/dist/sync/syncCursor.js +17 -21
  304. package/dist/sync/syncPlan.d.ts +28 -36
  305. package/dist/sync/syncPlan.js +18 -19
  306. package/dist/sync/syncPosition.d.ts +54 -49
  307. package/dist/sync/syncPosition.js +57 -52
  308. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  309. package/dist/sync/wsFrameHandlers.js +63 -67
  310. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  311. package/dist/testing/fixtures/bootstrap.js +12 -6
  312. package/dist/testing/fixtures/deltas.d.ts +30 -33
  313. package/dist/testing/fixtures/deltas.js +30 -33
  314. package/dist/testing/fixtures/models.d.ts +11 -10
  315. package/dist/testing/fixtures/models.js +11 -10
  316. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  317. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  318. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  319. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  320. package/dist/testing/helpers/wait.d.ts +13 -8
  321. package/dist/testing/helpers/wait.js +13 -8
  322. package/dist/testing/index.d.ts +5 -3
  323. package/dist/testing/index.js +3 -2
  324. package/dist/testing/mocks/FakeDatabase.d.ts +18 -0
  325. package/dist/testing/mocks/FakeDatabase.js +10 -0
  326. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  327. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  328. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  329. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  330. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  331. package/dist/testing/mocks/MockSyncContext.js +15 -13
  332. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  333. package/dist/testing/mocks/MockSyncStore.js +11 -11
  334. package/dist/testing/mocks/MockWebSocket.d.ts +28 -23
  335. package/dist/testing/mocks/MockWebSocket.js +22 -21
  336. package/dist/transactions/TransactionQueue.d.ts +244 -181
  337. package/dist/transactions/TransactionQueue.js +929 -423
  338. package/dist/transactions/TransactionStore.d.ts +6 -4
  339. package/dist/transactions/TransactionStore.js +6 -4
  340. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  341. package/dist/transactions/UnconfirmedWrites.js +104 -0
  342. package/dist/transactions/coalesceRules.d.ts +41 -17
  343. package/dist/transactions/coalesceRules.js +40 -17
  344. package/dist/transactions/commitEnvelope.d.ts +132 -0
  345. package/dist/transactions/commitEnvelope.js +139 -0
  346. package/dist/transactions/commitOutboxStore.d.ts +32 -0
  347. package/dist/transactions/commitOutboxStore.js +26 -0
  348. package/dist/transactions/commitPayload.d.ts +63 -52
  349. package/dist/transactions/commitPayload.js +54 -57
  350. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  351. package/dist/transactions/deltaConfirmation.js +37 -45
  352. package/dist/transactions/httpCommitEnvelope.d.ts +43 -0
  353. package/dist/transactions/httpCommitEnvelope.js +179 -0
  354. package/dist/transactions/optimisticApply.d.ts +49 -0
  355. package/dist/transactions/optimisticApply.js +65 -0
  356. package/dist/transactions/replayValidation.d.ts +182 -0
  357. package/dist/transactions/replayValidation.js +156 -0
  358. package/dist/types/global.d.ts +46 -41
  359. package/dist/types/global.js +20 -19
  360. package/dist/types/index.d.ts +71 -77
  361. package/dist/types/index.js +22 -22
  362. package/dist/types/modelData.d.ts +6 -8
  363. package/dist/types/modelData.js +5 -7
  364. package/dist/types/participant.d.ts +10 -11
  365. package/dist/types/participant.js +6 -8
  366. package/dist/types/streams.d.ts +208 -195
  367. package/dist/types/streams.js +7 -7
  368. package/dist/utils/asyncIterator.d.ts +25 -32
  369. package/dist/utils/asyncIterator.js +25 -32
  370. package/dist/utils/duration.d.ts +12 -15
  371. package/dist/utils/duration.js +12 -15
  372. package/dist/utils/mobxSetup.d.ts +53 -0
  373. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  374. package/dist/webhooks/events.d.ts +21 -16
  375. package/dist/webhooks/events.js +10 -8
  376. package/dist/webhooks/index.d.ts +5 -7
  377. package/dist/webhooks/index.js +5 -7
  378. package/dist/wire/bootstrapReason.d.ts +9 -0
  379. package/dist/wire/bootstrapReason.js +8 -0
  380. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  381. package/dist/wire/delta.js +114 -0
  382. package/dist/wire/errorEnvelope.d.ts +30 -31
  383. package/dist/wire/errorEnvelope.js +34 -40
  384. package/dist/wire/frames.d.ts +315 -86
  385. package/dist/wire/frames.js +47 -33
  386. package/dist/wire/index.d.ts +18 -14
  387. package/dist/wire/index.js +32 -27
  388. package/dist/wire/listEnvelope.d.ts +16 -23
  389. package/dist/wire/listEnvelope.js +7 -6
  390. package/dist/wire/protocol.d.ts +25 -32
  391. package/dist/wire/protocol.js +25 -32
  392. package/dist/wire/protocolVersion.d.ts +44 -40
  393. package/dist/wire/protocolVersion.js +44 -40
  394. package/docs/api.md +10 -10
  395. package/docs/coordination.md +59 -0
  396. package/docs/mcp.md +1 -1
  397. package/package.json +17 -11
  398. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  399. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  400. package/dist/core/query-utils.d.ts +0 -34
  401. package/dist/core/query-utils.js +0 -59
  402. package/dist/schema/sync-delta-row.js +0 -103
  403. package/dist/schema/sync-delta-wire.js +0 -102
  404. package/dist/server/read-config.d.ts +0 -67
  405. package/dist/server/read-config.js +0 -8
  406. package/dist/server/storage-mode.d.ts +0 -8
  407. package/dist/server/storage-mode.js +0 -28
  408. package/dist/source/connector-protocol.d.ts +0 -159
  409. package/dist/source/connector-protocol.js +0 -161
  410. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  411. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  412. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  413. package/dist/transactions/mutation-error-handler.js +0 -39
  414. package/dist/transactions/optimistic.d.ts +0 -24
  415. package/dist/transactions/optimistic.js +0 -45
  416. package/dist/transactions/persistedReplay.d.ts +0 -93
  417. package/dist/transactions/persistedReplay.js +0 -105
  418. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,16 +1,15 @@
1
1
  /**
2
- * SyncWebSocket - Manages WebSocket connection to Go sync engine
3
- *
4
- * Handles:
5
- * - WebSocket lifecycle (connect, reconnect, disconnect)
6
- * - Delta reception and processing
7
- * - Multi-tab support
8
- * - Automatic reconnection with exponential backoff
2
+ * Manages the WebSocket connection to the sync server. It owns the socket
3
+ * lifecycle (connect, reconnect, disconnect), receives and validates the
4
+ * incoming delta stream, sends commits and claims over the same socket, and
5
+ * reconnects automatically with exponential backoff. Consumers subscribe to its
6
+ * typed events (see {@link CoreSyncEventMap}) to react to deltas, presence, and
7
+ * connection changes.
9
8
  */
10
9
  import { EventEmitter } from 'events';
11
10
  import { getContext } from '../context.js';
12
11
  import { AbloConnectionError, AbloError, SyncSessionError, toAbloError, } from '../errors.js';
13
- import { clientSyncDeltaSchema } from '../schema/sync-delta-wire.js';
12
+ import { clientSyncDeltaSchema } from '../wire/delta.js';
14
13
  // Commit-path frame builders (pure) — extracted leaf; the host re-exports
15
14
  // `CommitAck` below so importers keep this module as their path.
16
15
  import { buildCommitFrame } from './commitFrames.js';
@@ -24,11 +23,11 @@ import { HeartbeatController } from './heartbeat.js';
24
23
  import { WS_BEARER_SUBPROTOCOL_PREFIX, WS_SYNC_SUBPROTOCOL, } from '../auth/credentialSource.js';
25
24
  // SyncObservability replaced by getContext().observability
26
25
  /**
27
- * Periodic catch-up poll cadence — while connected, request any deltas
28
- * whose fire-and-forget pub/sub broadcast was lost in transit. Deliberately
29
- * LOCAL (not `wire/protocol.ts`): an SDK eventual-consistency knob, not a
30
- * cross-boundary contract the server derives anything from. That it equals
31
- * the 30s ping today is coincidence, not an invariant.
26
+ * How often, while connected, the client polls for any deltas whose best-effort
27
+ * broadcast was lost in transit. This is a client-side eventual-consistency
28
+ * setting, not part of the wire contract, so the server derives nothing from
29
+ * it. That it currently equals the 30-second ping is a coincidence, not a
30
+ * guarantee.
32
31
  */
33
32
  const CATCHUP_POLL_INTERVAL_MS = 30_000;
34
33
  /**
@@ -37,8 +36,7 @@ const CATCHUP_POLL_INTERVAL_MS = 30_000;
37
36
  */
38
37
  const MAX_RECONNECT_DELAY_MS = 30_000;
39
38
  // ---------------------------------------------------------------------------
40
- // Ablo-specific collaboration events moved to apps/web/src/lib/sync/collaboration-events.ts
41
- // Consumers pass their own event types as TCollaboration generic parameter.
39
+ // Consumers pass their own event types as the TCollaboration generic parameter.
42
40
  export class SyncWebSocket extends EventEmitter {
43
41
  /**
44
42
  * Subscribe to events with automatic cleanup.
@@ -69,10 +67,10 @@ export class SyncWebSocket extends EventEmitter {
69
67
  /** Periodic catchup interval — polls for missed deltas every 30s while connected */
70
68
  catchupInterval = null;
71
69
  /**
72
- * Application-level heartbeat ping every 30s, force-close on a 10s
73
- * silent watchdog. The full zombie-socket rationale lives with the
74
- * timers in `sync/heartbeat.ts`; the transport closures below are the
75
- * only socket access the controller gets.
70
+ * Application-level heartbeat: ping every 30 seconds and force-close after a
71
+ * 10-second silence. The {@link HeartbeatController} holds the timing and the
72
+ * zombie-socket rationale; the closures below are the only socket access it
73
+ * gets.
76
74
  */
77
75
  heartbeat = new HeartbeatController({
78
76
  isSocketOpen: () => this.ws?.readyState === WebSocket.OPEN,
@@ -111,20 +109,19 @@ export class SyncWebSocket extends EventEmitter {
111
109
  lastForceCloseReason = null;
112
110
  sessionErrorAt = null;
113
111
  /**
114
- * Sync-position state (lastSyncId watermark, version vector, server
115
- * cursor). The advance discipline stays documented at `sendAck` /
116
- * `handleDelta`; the state itself lives in `sync/syncCursor.ts`.
112
+ * Sync-position state: the lastSyncId watermark, version vector, and server
113
+ * cursor. The advance discipline is documented at `sendAck` and `handleDelta`;
114
+ * the state itself lives in {@link SyncCursor}.
117
115
  */
118
116
  cursor;
119
117
  /** Registered collaboration event keys (colon format) for dispatch in onmessage */
120
118
  collaborationEventTypes;
121
119
  /**
122
- * Minimal session adapter handed to the frame dispatch table
123
- * (`sync/wsFrameHandlers.ts`). Exposes ONLY the members the handlers
124
- * touch; the closure members read live state so host-side reassignment
125
- * (e.g. the `pendingSubscriptions` reset on close) can't strand the
126
- * handlers on a stale reference. Built in the constructor, after the
127
- * state it captures exists.
120
+ * A minimal session adapter handed to the inbound frame dispatch table
121
+ * ({@link dispatchWsFrame}). It exposes only the members the handlers touch;
122
+ * the closure members read live state so a reassignment here (for example the
123
+ * `pendingSubscriptions` reset on close) cannot strand a handler on a stale
124
+ * reference. Built in the constructor, after the state it captures exists.
128
125
  */
129
126
  frameSession;
130
127
  /**
@@ -135,10 +132,10 @@ export class SyncWebSocket extends EventEmitter {
135
132
  */
136
133
  pendingMutations = new Map();
137
134
  /**
138
- * In-flight `claim` requests keyed by claimId. Resolved when the
139
- * matching `claim_ack` arrives, or rejected on timeout/disconnect.
140
- * Same shape as pendingMutations Phoenix-style request/response
141
- * over a multiplexed connection.
135
+ * In-flight `claim` requests keyed by claimId. Resolved when the matching
136
+ * `claim_ack` arrives, or rejected on timeout or disconnect — the same
137
+ * request/response pattern as `pendingMutations`, multiplexed over the one
138
+ * connection.
142
139
  */
143
140
  pendingClaims = new Map();
144
141
  /**
@@ -152,7 +149,7 @@ export class SyncWebSocket extends EventEmitter {
152
149
  pendingSubscriptions = [];
153
150
  constructor(options) {
154
151
  super();
155
- // Construct WebSocket URL from base Go server URL
152
+ // Construct the WebSocket URL from the base server URL.
156
153
  const baseUrl = options.baseUrl || options.url || "http://localhost:8080";
157
154
  const wsProtocol = baseUrl.startsWith('https') ? 'wss' : 'ws';
158
155
  const wsUrl = baseUrl.replace(/^https?/, wsProtocol) + '/api/sync/ws';
@@ -173,9 +170,9 @@ export class SyncWebSocket extends EventEmitter {
173
170
  };
174
171
  this.cursor = new SyncCursor(this.options.lastSyncId);
175
172
  this.collaborationEventTypes = new Set(options.collaborationEvents ?? ['sheet:selection', 'slide:selection', 'slide:cursor']);
176
- // Session slice for the inbound frame dispatch table — see the field
177
- // doc on `frameSession` for why members that the host reassigns are
178
- // exposed through closures instead of captured references.
173
+ // Session slice for the inbound frame dispatch table — see the field doc on
174
+ // `frameSession` for why reassigned members are exposed through closures
175
+ // instead of captured references.
179
176
  this.frameSession = {
180
177
  emit: (event, ...args) => this.emit(event, ...args),
181
178
  pendingMutations: this.pendingMutations,
@@ -238,18 +235,18 @@ export class SyncWebSocket extends EventEmitter {
238
235
  }
239
236
  this.isConnecting = true;
240
237
  this.isManualClose = false;
241
- // Pattern: one credential, server-resolved identity. The bearer travels
242
- // in a `Sec-WebSocket-Protocol` value (built below), NOT the URL. The
243
- // server is bearer-only (`apiKeyProvider`) and resolves identity from the
244
- // verified token — userId/organizationId are NEVER read from URL params.
238
+ // One credential, server-resolved identity. The bearer travels in a
239
+ // `Sec-WebSocket-Protocol` value (built below), not the URL. The server is
240
+ // bearer-only and resolves identity from the verified token; userId and
241
+ // organizationId are never read from URL parameters.
245
242
  const params = new URLSearchParams({
246
243
  // Intentionally omit lastSyncId, capabilities from URL; these are sent in sync_request
247
244
  // and ack messages to avoid stale baselines on reconnect.
248
245
  cursor: this.cursor.syncCursor || '',
249
246
  });
250
- // Participant kind — defaults to `user` for backward compatibility
251
- // with web sessions. Agent runtimes pass `'agent'` so the server's
252
- // capability-token path activates instead of session auth.
247
+ // Participant kind — defaults to `user` for session connections. Agent
248
+ // runtimes pass `'agent'` so the server's capability-token path activates
249
+ // instead of session auth.
253
250
  if (this.options.kind && this.options.kind !== 'user') {
254
251
  params.set('kind', this.options.kind);
255
252
  }
@@ -258,13 +255,13 @@ export class SyncWebSocket extends EventEmitter {
258
255
  params.append('syncGroups', group);
259
256
  });
260
257
  const wsUrl = `${this.options.url}?${params.toString()}`;
261
- // Carry the bearer in a `Sec-WebSocket-Protocol` value, NOT the URL. A
262
- // browser can't set an Authorization header on a WS, but it CAN offer
263
- // subprotocols — and unlike the query string, those don't land in ALB
264
- // access logs, proxies, or browser history. The server reads
265
- // `ablo.bearer.<token>` and selects the real `ablo.sync.v1` protocol,
266
- // never echoing the token-bearing value back. (Token is the raw ek_/rk_,
267
- // which is subprotocol-token-safe alphanumerics + `_`.)
258
+ // Carry the bearer in a `Sec-WebSocket-Protocol` value, not the URL. A
259
+ // browser cannot set an Authorization header on a WebSocket, but it can
260
+ // offer subprotocols — and unlike the query string, those do not land in
261
+ // load-balancer access logs, proxies, or browser history. The server reads
262
+ // `ablo.bearer.<token>` and selects the real `ablo.sync.v1` protocol, never
263
+ // echoing the token-bearing value back. The token is the raw `ek_`/`rk_`,
264
+ // which is safe as a subprotocol value (alphanumerics and `_`).
268
265
  const authToken = this.resolveAuthToken();
269
266
  const protocols = authToken
270
267
  ? [`${WS_BEARER_SUBPROTOCOL_PREFIX}${authToken}`, WS_SYNC_SUBPROTOCOL]
@@ -290,14 +287,14 @@ export class SyncWebSocket extends EventEmitter {
290
287
  * Setup WebSocket event handlers
291
288
  */
292
289
  setupEventHandlers() {
293
- // Capture the socket THIS call wires. Every handler below guards on
294
- // `this.ws === socket` (onclose additionally tolerates a nulled host
295
- // see there) so a handler firing late, after `connect()` replaced the
296
- // socket, can never clobber the NEW connection's shared state. Without
297
- // this, an old socket's `onclose` ran `this.ws = null;
298
- // stopCatchupInterval(); stopHeartbeat()` unconditionally — a reconnect
299
- // during close teardown orphaned the fresh socket (zombie receiving
300
- // deltas with no timers and broken send paths).
290
+ // Capture the socket this call wires. Every handler below guards on
291
+ // `this.ws === socket` (onclose additionally tolerates a nulled field
292
+ // see there), so a handler firing late, after `connect()` has replaced the
293
+ // socket, can never clobber the new connection's shared state. Without this
294
+ // guard, an old socket's `onclose` would unconditionally run `this.ws =
295
+ // null; stopCatchupInterval(); stopHeartbeat()` — a reconnect during close
296
+ // teardown then orphaned the fresh socket (a zombie receiving deltas with
297
+ // no timers and broken send paths).
301
298
  const socket = this.ws;
302
299
  if (!socket)
303
300
  return;
@@ -337,10 +334,9 @@ export class SyncWebSocket extends EventEmitter {
337
334
  }
338
335
  this.requestIncrementalSync().catch(reportSyncRequestFailure);
339
336
  // Start periodic catchup — polls for missed deltas every
340
- // CATCHUP_POLL_INTERVAL_MS while connected. Real-time WebSocket
341
- // delivery is best-effort (fire-and-forget Redis pub/sub). This
342
- // interval guarantees eventual consistency by fetching any deltas
343
- // that were committed to the DB but whose broadcast was lost in
337
+ // CATCHUP_POLL_INTERVAL_MS while connected. Real-time WebSocket delivery
338
+ // is best-effort, so this interval guarantees eventual consistency by
339
+ // fetching any deltas that were committed but whose broadcast was lost in
344
340
  // transit.
345
341
  this.stopCatchupInterval();
346
342
  this.catchupInterval = setInterval(() => {
@@ -355,7 +351,7 @@ export class SyncWebSocket extends EventEmitter {
355
351
  });
356
352
  }
357
353
  }, CATCHUP_POLL_INTERVAL_MS);
358
- // Start application-level heartbeat see sync/heartbeat.ts for rationale.
354
+ // Start the application-level heartbeat (see HeartbeatController).
359
355
  this.heartbeat.start();
360
356
  };
361
357
  socket.onmessage = (event) => {
@@ -366,7 +362,7 @@ export class SyncWebSocket extends EventEmitter {
366
362
  // the frame-envelope guard before dispatch. Payload-level
367
363
  // validation (deltas etc.) happens per-frame downstream.
368
364
  const message = JSON.parse(event.data);
369
- // ANY inbound frame proves the socket is alive — clear the
365
+ // Any inbound frame proves the socket is alive — clear the
370
366
  // heartbeat-timeout timer so we don't false-trip force-close
371
367
  // during normal traffic.
372
368
  this.heartbeat.clearHeartbeatTimeout();
@@ -376,10 +372,9 @@ export class SyncWebSocket extends EventEmitter {
376
372
  });
377
373
  return;
378
374
  }
379
- // Frame-type handler dispatch (sync/wsFrameHandlers.ts). The
380
- // session adapter exposes only the members the handlers touch;
381
- // keepalives, the legacy bare-delta form, and collaboration
382
- // events are all routed there too.
375
+ // Dispatch by frame type (see dispatchWsFrame). The session adapter
376
+ // exposes only the members the handlers touch; keepalives, the older
377
+ // bare-delta form, and collaboration events are all routed there too.
383
378
  dispatchWsFrame(this.frameSession, message);
384
379
  }
385
380
  catch (error) {
@@ -399,8 +394,8 @@ export class SyncWebSocket extends EventEmitter {
399
394
  this.emit('error', new AbloConnectionError('Network is offline', { code: 'bootstrap_offline' }));
400
395
  return;
401
396
  }
402
- // After session error, suppress Sentry capture — the root cause is already reported.
403
- // Still emit so SyncedStore can update UI state.
397
+ // After a session error, suppress error capture — the root cause is
398
+ // already reported. Still emit so the store can update UI state.
404
399
  const error = new AbloConnectionError(`WebSocket connection failed`);
405
400
  if (!this._sessionErrorDetected) {
406
401
  getContext().observability.captureWebSocketError({
@@ -411,7 +406,7 @@ export class SyncWebSocket extends EventEmitter {
411
406
  this.emit('error', error);
412
407
  };
413
408
  socket.onclose = (event) => {
414
- // Stale-socket close: a NEWER socket already owns the connection
409
+ // Stale-socket close: a newer socket already owns the connection
415
410
  // state — don't null it, stop its timers, or schedule a duplicate
416
411
  // reconnect (the orphaning race this guard exists for). The one
417
412
  // deliberate asymmetry vs the other handlers: `this.ws === null`
@@ -480,9 +475,9 @@ export class SyncWebSocket extends EventEmitter {
480
475
  }
481
476
  this.pendingSubscriptions = [];
482
477
  }
483
- // Protocol-version rejection (4010): TERMINAL. Reconnecting cannot heal
484
- // a version mismatch — only upgrading the SDK (or rolling the server
485
- // forward) can — so a blind retry here would loop forever against the
478
+ // Protocol-version rejection (4010): terminal. Reconnecting cannot heal a
479
+ // version mismatch — only upgrading the SDK, or rolling the server
480
+ // forward, can — so a blind retry here would loop forever against the
486
481
  // same typed close. Surface it and stop.
487
482
  if (event.code === WS_CLOSE_PROTOCOL_VERSION) {
488
483
  getContext().observability.captureWebSocketError({
@@ -511,25 +506,24 @@ export class SyncWebSocket extends EventEmitter {
511
506
  reason: event.reason,
512
507
  });
513
508
  this.emit('session_error', new SyncSessionError(event.reason || 'Session expired', event.code));
514
- // Don't reconnect from HERE. For a genuine session loss the user
515
- // must re-authenticate; for an expired ACCESS credential
516
- // (`credential_expired`) the store's session_error handler re-mints,
517
- // clears the latch, and drives the reconnect — see
518
- // BaseSyncedStore.setupWebSocketSync.
509
+ // Don't reconnect from here. For a genuine session loss the user must
510
+ // re-authenticate; for an expired access credential (`credential_expired`)
511
+ // the store's session-error handler re-mints, clears the latch, and
512
+ // drives the reconnect itself.
519
513
  this.emit('disconnected', event);
520
514
  return;
521
515
  }
522
516
  // Handshake failure: `onclose` fired before `onopen` ever did, so the
523
- // server rejected the upgrade (typically 401/403 on a bad cookie, but
524
- // could also be a CORS/origin reject or an LB 5xx). The browser hides
525
- // the HTTP status behind code 1006, so we can't tell which from here.
517
+ // server rejected the upgrade (typically 401/403 on a bad cookie, but it
518
+ // could also be a CORS/origin reject or a load-balancer 5xx). The browser
519
+ // hides the HTTP status behind code 1006, so we cannot tell which from
520
+ // here.
526
521
  //
527
- // Emit a dedicated event and SKIP the internal reconnect — the owner
528
- // (SyncedStore / ConnectionStore) should run an auth-validating HTTP
529
- // probe to distinguish session expiry from a transient network issue
530
- // and transition the UI accordingly. Reconnecting blindly is what
531
- // produced the infinite "offline → reconnecting → offline" loop on
532
- // stale cookies.
522
+ // Emit a dedicated event and skip the internal reconnect — the owner
523
+ // should run an auth-validating HTTP probe to distinguish session expiry
524
+ // from a transient network issue and transition the UI accordingly.
525
+ // Reconnecting blindly is what produced the infinite
526
+ // "offline → reconnecting → offline" loop on stale cookies.
533
527
  if (!everOpened && !this.isManualClose) {
534
528
  getContext().observability.captureWebSocketError({
535
529
  context: 'handshake-failed-close',
@@ -548,28 +542,25 @@ export class SyncWebSocket extends EventEmitter {
548
542
  };
549
543
  }
550
544
  /**
551
- * Validate + normalize a wire delta at the receive boundary — the ONE
552
- * seam every inbound delta (`delta` frame, batch element, `sync_response`
553
- * replay, legacy bare frame) passes through before it is emitted,
554
- * persisted to IDB, or allowed to advance any watermark.
545
+ * Validates and normalizes a wire delta at the receive boundary — the single
546
+ * seam every inbound delta (a `delta` frame, a batch element, a `sync_response`
547
+ * replay, or the older bare frame) passes through before it is emitted,
548
+ * persisted, or allowed to advance any watermark.
555
549
  *
556
- * Normalization (older/deployed servers stay compatible):
557
- * - `id`: the contract says `number`, but deployed servers have sent the
558
- * raw Postgres BIGINT serialization — a STRING — and every downstream
559
- * watermark gate (`typeof syncId === 'number'` in
560
- * `Database.processDeltaBatch`, the metadata-cursor update, numeric
561
- * `>=` thresholds in TransactionQueue) silently breaks on strings:
562
- * acks are withheld, the resume cursor never advances, and every
563
- * reconnect replays from 0. Coerce ONCE here.
564
- * - `transactionId` / `createdBy`: the SERVER projection sends these as
565
- * nullable (and `createdBy` as a nested ParticipantRef); the client
566
- * contract types them as optional strings and never reads them.
567
- * Normalize to absent instead of rejecting every real server delta.
550
+ * Normalization keeps already-deployed servers compatible:
551
+ * - `id`: the contract says `number`, but some servers have sent the raw
552
+ * Postgres BIGINT serialization — a string — and every downstream watermark
553
+ * gate treats a string as invalid, so acks are withheld, the resume cursor
554
+ * never advances, and every reconnect replays from zero. Coerce it once here.
555
+ * - `transactionId` / `createdBy`: the server projection sends these as
556
+ * nullable (and `createdBy` as a nested reference); the client contract
557
+ * types them as optional strings and never reads them, so normalize them to
558
+ * absent rather than reject every real server delta.
568
559
  *
569
- * Validation: `clientSyncDeltaSchema.safeParse` the canonical Zod wire
570
- * contract. A frame that fails is DROPPED (returns `null`) with a
571
- * debug-level log + observability breadcrumb; it is never applied. One
572
- * parse per delta — callers must not re-parse.
560
+ * Validation runs `clientSyncDeltaSchema.safeParse`, the canonical wire
561
+ * contract. A frame that fails is dropped (returns `null`) with a debug log
562
+ * and an observability breadcrumb; it is never applied. There is one parse per
563
+ * delta — callers must not re-parse.
573
564
  */
574
565
  normalizeWireDelta(raw) {
575
566
  let candidate = raw;
@@ -614,30 +605,27 @@ export class SyncWebSocket extends EventEmitter {
614
605
  id: delta.modelId,
615
606
  syncId: delta.id,
616
607
  });
617
- // DO NOT advance `this.cursor.lastSyncId` on receipt. The runtime cursor
618
- // must stay consistent with what's persisted in IDB otherwise the
619
- // next `requestIncrementalSync()` (and the connect-time handshake)
620
- // sends an optimistic cursor and the server skips deltas that never
621
- // landed in IDB. `this.cursor.lastSyncId` is advanced only in `sendAck()`,
622
- // which is gated on `BaseSyncedStore.flushPendingDeltas`'s
623
- // `persistedSyncId` watermark. See Replicache's "lastMutationID
624
- // read in the same transaction as the client view" rule.
608
+ // Do not advance `this.cursor.lastSyncId` on receipt. The runtime cursor
609
+ // must stay consistent with what has been persisted locally; otherwise the
610
+ // next `requestIncrementalSync()` (and the connect-time handshake) would
611
+ // send an optimistic cursor and the server would skip deltas that never
612
+ // landed in local storage. `this.cursor.lastSyncId` advances only in
613
+ // `sendAck()`, which the store gates on its persisted-syncId watermark, so
614
+ // the cursor is never read ahead of the persisted client view.
625
615
  //
626
- // Version vector is also intentionally NOT updated here for the
627
- // same reason left to the persistence-gated path.
616
+ // The version vector is intentionally not updated here for the same reason;
617
+ // it is left to the persistence-gated path.
628
618
  // Emit delta for processing. Ack will be sent by SyncedStore after persistence.
629
619
  this.emit('delta', delta);
630
620
  }
631
621
  /**
632
- * Send acknowledgment for received delta with version vector.
633
- *
634
- * This is the SOLE forward-mover of `this.cursor.lastSyncId` for live
635
- * deltas. Called by `BaseSyncedStore.flushPendingDeltas` with the
636
- * `persistedSyncId` watermark i.e. only after the deltas have
637
- * actually committed to IDB. Keeping the cursor advance here (rather
638
- * than at receipt in `handleDelta`/`handleSyncResponse`) means the
639
- * cursor never gets ahead of the persisted view, so reconnect/
640
- * catch-up requests can't accidentally skip un-persisted deltas.
622
+ * Acknowledges received deltas up to the given syncId. This is the only place
623
+ * `this.cursor.lastSyncId` moves forward for live deltas. The store calls it
624
+ * with its persisted-syncId watermark that is, only after the deltas have
625
+ * committed to local storage. Advancing the cursor here, rather than at
626
+ * receipt in `handleDelta` or `handleSyncResponse`, keeps the cursor from
627
+ * getting ahead of the persisted view, so reconnect and catch-up requests
628
+ * cannot skip un-persisted deltas.
641
629
  */
642
630
  sendAck(syncId) {
643
631
  // Advance the local cursor *and* the version vector for this ack —
@@ -691,23 +679,15 @@ export class SyncWebSocket extends EventEmitter {
691
679
  }
692
680
  }
693
681
  /**
694
- * Send a `commit` mutation request over the existing WebSocket and
695
- * resolve when the server's `mutation_result` frame comes back with
696
- * the same `clientTxId`. The wire-level frame is `{ type: 'commit',
697
- * payload: { operations, clientTxId } }` — matching the
698
- * `handleCommit` path on `apps/sync-server/src/hub/Hub.ts` (see the
699
- * dispatch at Hub.ts:737).
700
- *
701
- * Historical naming note: this was originally `sendBatchAck` back when
702
- * the Go sync-engine used a GraphQL `batchAck` mutation. The TS
703
- * sync-server uses `type: 'commit'` over WebSocket exclusively. The
704
- * method name now matches the wire protocol so the ack/commit naming
705
- * confusion stops here.
682
+ * Sends a `commit` mutation request over the existing WebSocket and resolves
683
+ * when the server's `mutation_result` frame comes back with the same
684
+ * `clientTxId`. The wire frame is `{ type: 'commit', payload: { operations,
685
+ * clientTxId } }`.
706
686
  *
707
- * Times out after 15s of silence from the server. The socket may close
708
- * during an in-flight mutation (network flap, server restart); we do
709
- * NOT auto-retry here — the caller's TransactionQueue owns retry +
710
- * offline replay semantics and the SDK shouldn't duplicate that logic.
687
+ * Times out after 15 seconds of silence from the server. The socket may close
688
+ * during an in-flight mutation (a network flap, a server restart); this does
689
+ * not auto-retry — the caller's transaction queue owns retry and offline
690
+ * replay, and the SDK does not duplicate that logic.
711
691
  */
712
692
  sendCommit(operations, clientTxId, timeoutMs = 15_000, causedByTaskId, reads) {
713
693
  if (this.ws?.readyState !== WebSocket.OPEN) {
@@ -750,21 +730,14 @@ export class SyncWebSocket extends EventEmitter {
750
730
  this.ws.send(JSON.stringify(frame));
751
731
  }
752
732
  /**
753
- * Activate a participant claim on this connection. Multiplexed
754
- * subscription pattern (Phoenix Channels / Pusher) the same
755
- * connection can hold N concurrent claims, each scoped to a
756
- * different set of sync groups.
757
- *
758
- * Returns a promise that resolves with the server-canonicalized
759
- * `syncGroups` and effective `ttlSeconds` once `claim_ack` arrives,
760
- * or rejects with a typed error on `success: false` ack /
761
- * timeout / disconnect.
733
+ * Activates a participant claim on this connection. One connection can hold
734
+ * several concurrent claims at once, each scoped to a different set of sync
735
+ * groups, so the SDK reuses the existing connection instead of opening a
736
+ * separate socket per scope.
762
737
  *
763
- * Why this exists: the old scoped-participant path opened a separate
764
- * WS per scope. With claims, the SDK reuses the existing session/agent
765
- * connection one TCP, N logical participants. See
766
- * `apps/sync-server/docs/PARTICIPANT_CLAIMS.md` for the migration
767
- * framing (Phase A.1).
738
+ * Returns a promise that resolves with the server-canonicalized `syncGroups`
739
+ * and effective `ttlSeconds` once `claim_ack` arrives, or rejects with a typed
740
+ * error on a failed ack, a timeout, or a disconnect.
768
741
  */
769
742
  sendClaim(claimId, syncGroups, options) {
770
743
  if (this.ws?.readyState !== WebSocket.OPEN) {
@@ -829,22 +802,21 @@ export class SyncWebSocket extends EventEmitter {
829
802
  }
830
803
  }
831
804
  /**
832
- * Move this connection's READ interest — replace the connection-level
833
- * sync groups mid-session as the user opens/closes entities. This is the
834
- * area-of-interest (AOI) navigation primitive: the server fans out
835
- * deltas only for groups currently in view, instead of the frozen set
836
- * chosen at connect.
805
+ * Moves this connection's read interest — replaces the connection-level sync
806
+ * groups mid-session as the user opens and closes entities. This is the
807
+ * area-of-interest navigation primitive: the server fans out deltas only for
808
+ * the groups currently in view, rather than the fixed set chosen at connect.
837
809
  *
838
- * Full-set replace semantics — pass the complete new group list, not a
839
- * delta. Resolves with the server's effective set once `subscription_ack`
840
- * arrives; rejects (typed) on a scope denial (a restricted `rk_` key
841
- * requesting a group outside its allowlist), timeout, or disconnect. On
842
- * success the new set is recorded as `options.syncGroups` so a later
843
- * reconnect re-subscribes to current interest, not the connect-time set.
810
+ * This is a full-set replace: pass the complete new group list, not a delta.
811
+ * Resolves with the server's effective set once `subscription_ack` arrives;
812
+ * rejects (with a typed error) on a scope denial (a restricted `rk_` key
813
+ * requesting a group outside its allowlist), a timeout, or a disconnect. On
814
+ * success the new set is recorded as `options.syncGroups`, so a later reconnect
815
+ * re-subscribes to the current interest rather than the connect-time set.
844
816
  *
845
- * Distinct from {@link sendClaim} (write-claim, per-op, TTL'd) — this is
846
- * the read side and carries no capability token of its own; it's bounded
847
- * by the connection credential's grant.
817
+ * Distinct from {@link sendClaim} (a write claim, per operation, with a TTL):
818
+ * this is the read side, carries no capability token of its own, and is
819
+ * bounded by the connection credential's grant.
848
820
  */
849
821
  updateSubscription(syncGroups, options) {
850
822
  if (this.ws?.readyState !== WebSocket.OPEN) {
@@ -879,9 +851,9 @@ export class SyncWebSocket extends EventEmitter {
879
851
  });
880
852
  }
881
853
  /**
882
- * Compatibility setter for direct SyncWebSocket users. The SDK-owned
883
- * `Ablo()` path passes `getAuthToken`, so reconnect URL auth reads the
884
- * shared credential source instead of this copied value.
854
+ * Sets a fixed credential for callers that construct the socket directly. The
855
+ * SDK instead supplies `getAuthToken`, so reconnects read the shared
856
+ * credential source rather than this copied value.
885
857
  */
886
858
  setCapabilityToken(token) {
887
859
  this.options.capabilityToken = token;
@@ -976,17 +948,17 @@ export class SyncWebSocket extends EventEmitter {
976
948
  if (this._sessionErrorDetected) {
977
949
  return;
978
950
  }
979
- // Don't attempt reconnection while offline.
980
- // SyncedStore.handleNetworkOnline() owns the offline→online transition:
981
- // it bootstraps first, then calls syncWebSocket.connect() explicitly.
982
- // Self-reconnecting here would bypass the bootstrap gate and cause stale data.
951
+ // Don't attempt reconnection while offline. The owning store manages the
952
+ // offline→online transition: it bootstraps first, then calls `connect()`
953
+ // explicitly. Self-reconnecting here would bypass that bootstrap gate and
954
+ // surface stale data.
983
955
  if (!getContext().onlineStatus.isOnline()) {
984
956
  this.emit('reconnecting', { attempt: this.reconnectAttempts + 1, delay: 0 });
985
957
  return;
986
958
  }
987
- // Give up after MAX_RECONNECT_ATTEMPTS consecutive failures.
988
- // The user can recover by refreshing or when network comes back online
989
- // (handleNetworkOnline resets attempts and reconnects).
959
+ // Give up after MAX_RECONNECT_ATTEMPTS consecutive failures. The user can
960
+ // recover by refreshing, or the store resets the attempt count and
961
+ // reconnects when the network returns.
990
962
  if (this.reconnectAttempts >= SyncWebSocket.MAX_RECONNECT_ATTEMPTS) {
991
963
  this.emit('reconnect_failed', { attempts: this.reconnectAttempts });
992
964
  return;
@@ -1098,12 +1070,12 @@ export class SyncWebSocket extends EventEmitter {
1098
1070
  */
1099
1071
  notConnectedError(action) {
1100
1072
  const d = this.getConnectionDiagnostics();
1101
- // Session-latched is NOT a transient transport hiccup: reconnection is
1102
- // suppressed until re-auth (or the store's credential re-mint clears the
1103
- // latch), so retrying can never succeed. Reject with the PERMANENT
1104
- // session type — `isPermanentError` surfaces it to the caller as
1105
- // "re-authenticate" instead of parking the write for a reconnect that
1106
- // will never happen (the old `ws_not_ready` retry-forever hazard).
1073
+ // A session-latched socket is not a transient transport hiccup: reconnection
1074
+ // is suppressed until re-auth (or the store's credential re-mint clears the
1075
+ // latch), so retrying can never succeed. Reject with the permanent session
1076
+ // error type — `isPermanentError` surfaces it to the caller as
1077
+ // "re-authenticate" instead of parking the write for a reconnect that will
1078
+ // never happen.
1107
1079
  if (d.sessionErrorDetected) {
1108
1080
  return Object.assign(new SyncSessionError(`SyncWebSocket not connected — cannot send ${action}: session expired` +
1109
1081
  (d.lastCloseReason ? ` (${d.lastCloseReason})` : '') +
@@ -1134,10 +1106,10 @@ export class SyncWebSocket extends EventEmitter {
1134
1106
  else {
1135
1107
  detail = 'never_connected';
1136
1108
  }
1137
- // Typed so it lands in the AbloError hierarchy AND `isPermanentError`
1138
- // sees a transient transport failure (retry on reconnect, don't roll
1139
- // back). `diagnostics` stays a property — the queue's failure log walks
1140
- // the cause chain for it.
1109
+ // Typed so it lands in the AbloError hierarchy and `isPermanentError` sees a
1110
+ // transient transport failure (retry on reconnect, don't roll back).
1111
+ // `diagnostics` stays a property — the queue's failure log walks the cause
1112
+ // chain for it.
1141
1113
  const err = Object.assign(new AbloConnectionError(`SyncWebSocket not connected — cannot send ${action} (${detail})`, { code: 'ws_not_ready' }), { diagnostics: d });
1142
1114
  return err;
1143
1115
  }
@@ -1145,8 +1117,8 @@ export class SyncWebSocket extends EventEmitter {
1145
1117
  getSyncGroups() {
1146
1118
  return this.options.syncGroups;
1147
1119
  }
1148
- // Cursor accessors — thin delegates; the state + semantics live in
1149
- // sync/syncCursor.ts (SyncCursor).
1120
+ // Cursor accessors — thin delegates; the state and semantics live in
1121
+ // SyncCursor.
1150
1122
  /**
1151
1123
  * Update last sync ID (for persistence)
1152
1124
  */
@@ -1172,7 +1144,7 @@ export class SyncWebSocket extends EventEmitter {
1172
1144
  return this.cursor.getLastSyncId();
1173
1145
  }
1174
1146
  /**
1175
- * Linear-style incremental sync request
1147
+ * Requests an incremental sync from the server, starting at the current cursor.
1176
1148
  */
1177
1149
  async requestIncrementalSync() {
1178
1150
  if (this.ws?.readyState !== WebSocket.OPEN) {
@@ -1194,7 +1166,7 @@ export class SyncWebSocket extends EventEmitter {
1194
1166
  lastSyncId: this.cursor.lastSyncId,
1195
1167
  capabilities: capsArr,
1196
1168
  // Protocol handshake: the server rejects an out-of-range version with
1197
- // WS close 4010 before serving any deltas (wire/protocolVersion.ts).
1169
+ // WebSocket close code 4010 before serving any deltas.
1198
1170
  protocolVersion: PROTOCOL_VERSION,
1199
1171
  },
1200
1172
  });
@@ -1228,25 +1200,22 @@ export class SyncWebSocket extends EventEmitter {
1228
1200
  const rawDeltas = Array.isArray(payload.deltas)
1229
1201
  ? payload.deltas
1230
1202
  : null;
1231
- // Cursor reconciliation — Linear-style handshake. The server stamps
1232
- // its authoritative `currentSyncId` on every sync_response. If our
1233
- // local cursor is AHEAD of the server, our local view has somehow
1234
- // diverged (corrupted metadata, future regression reintroducing an
1235
- // eager-advance, IDB lying about a successful commit). Trust the
1236
- // server, reset the cursor, and request another sync so any deltas
1237
- // we *should* have applied get re-delivered. Backward-compatible
1238
- // when the field is absent (older server build) — we just skip the
1239
- // reconciliation step.
1203
+ // Cursor reconciliation. The server stamps its authoritative `currentSyncId`
1204
+ // on every sync_response. If our local cursor is ahead of the server, our
1205
+ // local view has somehow diverged (corrupted metadata, a regression that
1206
+ // reintroduced an eager advance, or local storage lying about a successful
1207
+ // commit). Trust the server, reset the cursor, and request another sync so
1208
+ // any deltas we should have applied get re-delivered. When the field is
1209
+ // absent (an older server build) we simply skip this step.
1240
1210
  //
1241
- // We only reconcile when the response carries NO deltas. If deltas
1242
- // are present, they'll advance our cursor through the normal
1243
- // persistence-gated path anyway — and the in-flight request/response
1244
- // round-trip means the snapshot's `currentSyncId` is naturally a
1245
- // few syncIds behind our locally-advanced cursor at receive time
1246
- // (live deltas may have landed in the meantime). Restricting to
1247
- // empty-delta responses eliminates this benign false positive while
1248
- // still catching the real corruption case (server head < local AND
1249
- // server has nothing new to send).
1211
+ // We only reconcile when the response carries no deltas. If deltas are
1212
+ // present they advance our cursor through the normal persistence-gated path
1213
+ // anyway — and the in-flight round-trip means the snapshot's `currentSyncId`
1214
+ // is naturally a few syncIds behind our locally-advanced cursor at receive
1215
+ // time (live deltas may have landed in the meantime). Restricting to
1216
+ // empty-delta responses eliminates that benign false positive while still
1217
+ // catching the real corruption case (server head < local, and the server
1218
+ // has nothing new to send).
1250
1219
  const hasDeltas = rawDeltas !== null && rawDeltas.length > 0;
1251
1220
  if (!hasDeltas && typeof payload.currentSyncId === 'number') {
1252
1221
  const serverHead = payload.currentSyncId;
@@ -1314,10 +1283,10 @@ export class SyncWebSocket extends EventEmitter {
1314
1283
  * Handle bootstrap response from server
1315
1284
  */
1316
1285
  handleBootstrapResponse(payload) {
1317
- // Emit bootstrap data for processing. (A `version` field from
1318
- // pre-cutover servers is ignored version vector removed in W4a.)
1319
- // Field-wise typeof guards mirror the cursor handling above: the frame
1320
- // is server-produced, so coercion only bites on malformed frames.
1286
+ // Emit the bootstrap data for processing. (A `version` field from older
1287
+ // servers is ignored; the version vector is no longer used.) The typeof
1288
+ // guards mirror the cursor handling above: the frame is server-produced, so
1289
+ // coercion only bites on a malformed frame.
1321
1290
  const p = (payload && typeof payload === 'object' ? payload : {});
1322
1291
  this.emit('bootstrap_data', {
1323
1292
  entityType: typeof p.entityType === 'string' ? p.entityType : '',
@@ -1327,13 +1296,12 @@ export class SyncWebSocket extends EventEmitter {
1327
1296
  });
1328
1297
  }
1329
1298
  /**
1330
- * Handle presence update from server. The wire frame's payload is
1331
- * forwarded as-is so every consumer (web entity cache,
1332
- * PresenceStream, agent runtime) reads from the same shape.
1333
- * Stripping fields here was a prior bug — it silently dropped
1334
- * `kind`, `activity`, `syncGroups`, `isAgent` for rich consumers.
1299
+ * Handles a presence update from the server. The wire frame's payload is
1300
+ * forwarded as-is, so every consumer reads the same shape; stripping fields
1301
+ * here would drop `kind`, `activity`, `syncGroups`, and `isAgent` for
1302
+ * consumers that need them.
1335
1303
  *
1336
- * Wire frame (apps/sync-server/src/hub/types.ts PresenceUpdateMessage):
1304
+ * The wire frame is:
1337
1305
  * { type: 'presence_update', payload: { kind, userId, status,
1338
1306
  * syncGroups, activity, isAgent, timestamp, activeClaims } }
1339
1307
  */