@abloatai/ablo 0.25.0 → 0.27.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 (425) hide show
  1. package/AGENTS.md +5 -3
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +104 -88
  4. package/dist/BaseSyncedStore.d.ts +140 -266
  5. package/dist/BaseSyncedStore.js +338 -739
  6. package/dist/Database.d.ts +62 -77
  7. package/dist/Database.js +106 -127
  8. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  9. package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
  10. package/dist/LazyReferenceCollection.d.ts +11 -15
  11. package/dist/LazyReferenceCollection.js +16 -15
  12. package/dist/Model.d.ts +37 -52
  13. package/dist/Model.js +52 -69
  14. package/dist/ModelRegistry.d.ts +46 -25
  15. package/dist/ModelRegistry.js +32 -30
  16. package/dist/NetworkMonitor.d.ts +5 -6
  17. package/dist/NetworkMonitor.js +6 -7
  18. package/dist/SyncClient.d.ts +119 -109
  19. package/dist/SyncClient.js +303 -224
  20. package/dist/SyncEngineContext.d.ts +1 -3
  21. package/dist/SyncEngineContext.js +1 -2
  22. package/dist/adapters/alwaysOnline.d.ts +6 -8
  23. package/dist/adapters/alwaysOnline.js +6 -8
  24. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  25. package/dist/adapters/inMemoryStorage.js +9 -9
  26. package/dist/agent/Agent.d.ts +39 -31
  27. package/dist/agent/Agent.js +35 -23
  28. package/dist/agent/index.d.ts +4 -4
  29. package/dist/agent/index.js +5 -5
  30. package/dist/agent/session.d.ts +47 -44
  31. package/dist/agent/session.js +37 -48
  32. package/dist/agent/types.d.ts +26 -31
  33. package/dist/agent/types.js +6 -7
  34. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  35. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  36. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  37. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +30 -31
  38. package/dist/ai-sdk/index.d.ts +25 -22
  39. package/dist/ai-sdk/index.js +25 -22
  40. package/dist/ai-sdk/wrap.d.ts +7 -8
  41. package/dist/ai-sdk/wrap.js +2 -2
  42. package/dist/auth/credentialPolicy.d.ts +74 -71
  43. package/dist/auth/credentialPolicy.js +51 -56
  44. package/dist/auth/credentialSource.d.ts +7 -18
  45. package/dist/auth/credentialSource.js +10 -18
  46. package/dist/auth/index.d.ts +59 -58
  47. package/dist/auth/index.js +34 -40
  48. package/dist/auth/schemas.d.ts +5 -4
  49. package/dist/auth/schemas.js +5 -4
  50. package/dist/batching/index.d.ts +19 -21
  51. package/dist/batching/index.js +14 -17
  52. package/dist/cli.cjs +483 -369
  53. package/dist/client/Ablo.d.ts +107 -836
  54. package/dist/client/Ablo.js +174 -833
  55. package/dist/client/ApiClient.d.ts +44 -20
  56. package/dist/client/ApiClient.js +193 -44
  57. package/dist/client/auth.d.ts +51 -60
  58. package/dist/client/auth.js +137 -110
  59. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  60. package/dist/client/claimHeartbeatLoop.js +88 -0
  61. package/dist/client/consoleLogger.d.ts +35 -0
  62. package/dist/client/consoleLogger.js +44 -0
  63. package/dist/client/createInternalComponents.d.ts +14 -17
  64. package/dist/client/createInternalComponents.js +26 -31
  65. package/dist/client/createModelProxy.d.ts +130 -120
  66. package/dist/client/createModelProxy.js +158 -124
  67. package/dist/client/credentialEndpoint.d.ts +61 -0
  68. package/dist/client/credentialEndpoint.js +86 -0
  69. package/dist/client/functionalUpdate.d.ts +29 -27
  70. package/dist/client/functionalUpdate.js +21 -21
  71. package/dist/client/hostedEndpoints.d.ts +21 -0
  72. package/dist/client/hostedEndpoints.js +21 -0
  73. package/dist/client/httpClient.d.ts +58 -54
  74. package/dist/client/httpClient.js +29 -31
  75. package/dist/client/identity.d.ts +15 -20
  76. package/dist/client/identity.js +49 -59
  77. package/dist/client/modelRegistration.d.ts +10 -0
  78. package/dist/client/modelRegistration.js +301 -0
  79. package/dist/client/options.d.ts +373 -0
  80. package/dist/client/options.js +6 -0
  81. package/dist/client/registerDataSource.d.ts +9 -9
  82. package/dist/client/registerDataSource.js +15 -16
  83. package/dist/client/resourceTypes.d.ts +333 -0
  84. package/dist/client/resourceTypes.js +7 -0
  85. package/dist/client/schemaConfig.d.ts +44 -0
  86. package/dist/client/schemaConfig.js +176 -0
  87. package/dist/client/sessionMint.d.ts +17 -13
  88. package/dist/client/sessionMint.js +26 -31
  89. package/dist/client/validateAbloOptions.d.ts +12 -14
  90. package/dist/client/validateAbloOptions.js +9 -10
  91. package/dist/client/writeOptionsSchema.d.ts +18 -16
  92. package/dist/client/writeOptionsSchema.js +23 -20
  93. package/dist/client/wsMutationExecutor.d.ts +28 -0
  94. package/dist/client/wsMutationExecutor.js +71 -0
  95. package/dist/context.d.ts +6 -4
  96. package/dist/context.js +6 -7
  97. package/dist/coordination/index.d.ts +13 -4
  98. package/dist/coordination/index.js +29 -4
  99. package/dist/coordination/schema.d.ts +176 -128
  100. package/dist/coordination/schema.js +197 -133
  101. package/dist/coordination/trace.d.ts +9 -11
  102. package/dist/coordination/trace.js +13 -15
  103. package/dist/core/DatabaseManager.d.ts +5 -8
  104. package/dist/core/DatabaseManager.js +38 -40
  105. package/dist/core/QueryProcessor.d.ts +7 -9
  106. package/dist/core/QueryProcessor.js +27 -34
  107. package/dist/core/QueryView.d.ts +17 -5
  108. package/dist/core/QueryView.js +6 -7
  109. package/dist/core/StoreManager.d.ts +14 -16
  110. package/dist/core/StoreManager.js +26 -25
  111. package/dist/core/ViewRegistry.d.ts +5 -5
  112. package/dist/core/ViewRegistry.js +4 -4
  113. package/dist/core/index.d.ts +18 -13
  114. package/dist/core/index.js +32 -26
  115. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  116. package/dist/core/openIDBWithTimeout.js +57 -54
  117. package/dist/core/queryUtils.d.ts +45 -0
  118. package/dist/core/queryUtils.js +69 -0
  119. package/dist/core/storeContract.d.ts +145 -0
  120. package/dist/core/storeContract.js +12 -0
  121. package/dist/environment.d.ts +28 -0
  122. package/dist/environment.js +21 -0
  123. package/dist/errorCodes.d.ts +118 -101
  124. package/dist/errorCodes.js +277 -260
  125. package/dist/errors.d.ts +170 -165
  126. package/dist/errors.js +161 -151
  127. package/dist/index.d.ts +30 -27
  128. package/dist/index.js +90 -82
  129. package/dist/interfaces/index.d.ts +108 -133
  130. package/dist/interfaces/index.js +5 -4
  131. package/dist/keys/index.d.ts +27 -29
  132. package/dist/keys/index.js +59 -49
  133. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  134. package/dist/mutators/RecordingTransaction.js +31 -37
  135. package/dist/mutators/Transaction.d.ts +18 -26
  136. package/dist/mutators/Transaction.js +14 -20
  137. package/dist/mutators/UndoManager.d.ts +122 -131
  138. package/dist/mutators/UndoManager.js +149 -155
  139. package/dist/mutators/defineMutators.d.ts +24 -37
  140. package/dist/mutators/defineMutators.js +14 -20
  141. package/dist/mutators/inverseOp.d.ts +12 -15
  142. package/dist/mutators/inverseOp.js +12 -15
  143. package/dist/mutators/mutateActions.d.ts +10 -9
  144. package/dist/mutators/mutateActions.js +1 -1
  145. package/dist/mutators/readerActions.d.ts +9 -8
  146. package/dist/mutators/readerActions.js +2 -2
  147. package/dist/mutators/undoApply.d.ts +31 -27
  148. package/dist/mutators/undoApply.js +26 -24
  149. package/dist/policy/index.d.ts +5 -3
  150. package/dist/policy/index.js +5 -3
  151. package/dist/policy/types.d.ts +105 -101
  152. package/dist/policy/types.js +67 -66
  153. package/dist/query/client.d.ts +32 -16
  154. package/dist/query/client.js +103 -72
  155. package/dist/query/types.d.ts +37 -60
  156. package/dist/query/types.js +13 -33
  157. package/dist/react/AbloProvider.d.ts +7 -11
  158. package/dist/react/AbloProvider.js +24 -17
  159. package/dist/react/context.d.ts +27 -146
  160. package/dist/react/context.js +9 -10
  161. package/dist/react/index.d.ts +41 -42
  162. package/dist/react/index.js +37 -38
  163. package/dist/react/internalContext.d.ts +17 -19
  164. package/dist/react/useAblo.d.ts +23 -22
  165. package/dist/react/useAblo.js +17 -15
  166. package/dist/react/useCurrentUserId.d.ts +8 -7
  167. package/dist/react/useCurrentUserId.js +8 -7
  168. package/dist/react/useErrorListener.d.ts +7 -7
  169. package/dist/react/useErrorListener.js +11 -12
  170. package/dist/react/useMutationFailureListener.d.ts +8 -8
  171. package/dist/react/useMutationFailureListener.js +9 -9
  172. package/dist/react/useMutators.d.ts +11 -11
  173. package/dist/react/useMutators.js +10 -4
  174. package/dist/react/useReactive.js +2 -3
  175. package/dist/react/useSyncStatus.d.ts +4 -6
  176. package/dist/react/useUndoScope.d.ts +7 -9
  177. package/dist/react/useUndoScope.js +3 -3
  178. package/dist/schema/coordination.d.ts +21 -25
  179. package/dist/schema/coordination.js +21 -25
  180. package/dist/schema/ddl.d.ts +43 -39
  181. package/dist/schema/ddl.js +75 -68
  182. package/dist/schema/ddlLock.d.ts +35 -0
  183. package/dist/schema/ddlLock.js +46 -0
  184. package/dist/schema/diff.d.ts +99 -61
  185. package/dist/schema/diff.js +43 -34
  186. package/dist/schema/field.d.ts +37 -42
  187. package/dist/schema/field.js +36 -49
  188. package/dist/schema/generate.d.ts +12 -12
  189. package/dist/schema/generate.js +12 -12
  190. package/dist/schema/index.d.ts +5 -4
  191. package/dist/schema/index.js +29 -21
  192. package/dist/schema/model.d.ts +121 -146
  193. package/dist/schema/model.js +24 -35
  194. package/dist/schema/openapi.d.ts +10 -9
  195. package/dist/schema/openapi.js +7 -1
  196. package/dist/schema/queries.d.ts +30 -32
  197. package/dist/schema/queries.js +24 -25
  198. package/dist/schema/relation.d.ts +89 -99
  199. package/dist/schema/relation.js +13 -13
  200. package/dist/schema/residency.d.ts +38 -0
  201. package/dist/schema/residency.js +30 -0
  202. package/dist/schema/roles.d.ts +45 -27
  203. package/dist/schema/roles.js +52 -21
  204. package/dist/schema/schema.d.ts +36 -45
  205. package/dist/schema/schema.js +42 -39
  206. package/dist/schema/select.d.ts +13 -13
  207. package/dist/schema/select.js +13 -13
  208. package/dist/schema/serialize.d.ts +36 -39
  209. package/dist/schema/serialize.js +27 -31
  210. package/dist/schema/sugar.d.ts +17 -32
  211. package/dist/schema/sugar.js +14 -29
  212. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +27 -50
  213. package/dist/schema/syncDeltaRow.js +89 -0
  214. package/dist/schema/tenancy.d.ts +44 -46
  215. package/dist/schema/tenancy.js +46 -48
  216. package/dist/server/adapter.d.ts +58 -58
  217. package/dist/server/adapter.js +13 -14
  218. package/dist/server/commit.d.ts +60 -64
  219. package/dist/server/index.d.ts +9 -10
  220. package/dist/server/index.js +1 -1
  221. package/dist/server/readConfig.d.ts +70 -0
  222. package/dist/server/readConfig.js +8 -0
  223. package/dist/server/storageMode.d.ts +23 -0
  224. package/dist/server/storageMode.js +17 -0
  225. package/dist/source/adapter.d.ts +31 -26
  226. package/dist/source/adapter.js +10 -10
  227. package/dist/source/adapters/drizzle.d.ts +28 -23
  228. package/dist/source/adapters/drizzle.js +34 -28
  229. package/dist/source/adapters/kysely.d.ts +27 -25
  230. package/dist/source/adapters/kysely.js +28 -26
  231. package/dist/source/adapters/memory.d.ts +8 -7
  232. package/dist/source/adapters/memory.js +10 -9
  233. package/dist/source/adapters/prisma.d.ts +13 -12
  234. package/dist/source/adapters/prisma.js +27 -29
  235. package/dist/source/conformance.d.ts +18 -11
  236. package/dist/source/conformance.js +27 -19
  237. package/dist/source/connector.d.ts +31 -32
  238. package/dist/source/connector.js +30 -28
  239. package/dist/source/connectorProtocol.d.ts +160 -0
  240. package/dist/source/connectorProtocol.js +162 -0
  241. package/dist/source/contract.d.ts +26 -27
  242. package/dist/source/contract.js +28 -29
  243. package/dist/source/factory.d.ts +94 -0
  244. package/dist/source/factory.js +268 -0
  245. package/dist/source/index.d.ts +10 -462
  246. package/dist/source/index.js +17 -421
  247. package/dist/source/migrations.d.ts +9 -9
  248. package/dist/source/migrations.js +9 -9
  249. package/dist/source/next.d.ts +10 -11
  250. package/dist/source/next.js +7 -8
  251. package/dist/source/pushQueue.d.ts +70 -48
  252. package/dist/source/pushQueue.js +36 -29
  253. package/dist/source/signing.d.ts +88 -0
  254. package/dist/source/signing.js +159 -0
  255. package/dist/source/types.d.ts +351 -0
  256. package/dist/source/types.js +43 -0
  257. package/dist/stores/ObjectStore.d.ts +11 -12
  258. package/dist/stores/ObjectStore.js +34 -35
  259. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  260. package/dist/stores/SyncActionStore.d.ts +8 -12
  261. package/dist/stores/SyncActionStore.js +77 -46
  262. package/dist/surface.d.ts +28 -21
  263. package/dist/surface.js +28 -20
  264. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
  265. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
  266. package/dist/sync/ConnectionManager.d.ts +47 -50
  267. package/dist/sync/ConnectionManager.js +74 -70
  268. package/dist/sync/NetworkProbe.d.ts +27 -31
  269. package/dist/sync/NetworkProbe.js +67 -72
  270. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
  271. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
  272. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
  273. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
  274. package/dist/sync/SyncWebSocket.d.ts +175 -250
  275. package/dist/sync/SyncWebSocket.js +431 -769
  276. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  277. package/dist/sync/awaitClaimGrant.js +38 -30
  278. package/dist/sync/bootstrapApply.d.ts +70 -0
  279. package/dist/sync/bootstrapApply.js +73 -0
  280. package/dist/sync/commitFrames.d.ts +44 -0
  281. package/dist/sync/commitFrames.js +94 -0
  282. package/dist/sync/createClaimStream.d.ts +23 -22
  283. package/dist/sync/createClaimStream.js +108 -25
  284. package/dist/sync/createPresenceStream.d.ts +19 -18
  285. package/dist/sync/createPresenceStream.js +25 -26
  286. package/dist/sync/createSnapshot.d.ts +13 -17
  287. package/dist/sync/createSnapshot.js +20 -26
  288. package/dist/sync/credentialLifecycle.d.ts +175 -0
  289. package/dist/sync/credentialLifecycle.js +322 -0
  290. package/dist/sync/deltaPipeline.d.ts +113 -0
  291. package/dist/sync/deltaPipeline.js +261 -0
  292. package/dist/sync/groupChange.d.ts +113 -0
  293. package/dist/sync/groupChange.js +242 -0
  294. package/dist/sync/heartbeat.d.ts +63 -0
  295. package/dist/sync/heartbeat.js +91 -0
  296. package/dist/sync/participants.d.ts +27 -27
  297. package/dist/sync/schemas.d.ts +3 -2
  298. package/dist/sync/schemas.js +14 -10
  299. package/dist/sync/syncCursor.d.ts +40 -0
  300. package/dist/sync/syncCursor.js +55 -0
  301. package/dist/sync/syncPlan.d.ts +54 -0
  302. package/dist/sync/syncPlan.js +50 -0
  303. package/dist/sync/syncPosition.d.ts +54 -49
  304. package/dist/sync/syncPosition.js +57 -52
  305. package/dist/sync/wsFrameHandlers.d.ts +116 -0
  306. package/dist/sync/wsFrameHandlers.js +374 -0
  307. package/dist/testing/fixtures/bootstrap.d.ts +21 -17
  308. package/dist/testing/fixtures/bootstrap.js +12 -6
  309. package/dist/testing/fixtures/deltas.d.ts +31 -34
  310. package/dist/testing/fixtures/deltas.js +30 -33
  311. package/dist/testing/fixtures/models.d.ts +11 -10
  312. package/dist/testing/fixtures/models.js +12 -10
  313. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  314. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  315. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -18
  316. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
  317. package/dist/testing/helpers/wait.d.ts +13 -8
  318. package/dist/testing/helpers/wait.js +13 -8
  319. package/dist/testing/index.d.ts +4 -4
  320. package/dist/testing/index.js +3 -3
  321. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  322. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  323. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  324. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  325. package/dist/testing/mocks/MockSyncContext.d.ts +21 -34
  326. package/dist/testing/mocks/MockSyncContext.js +16 -45
  327. package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
  328. package/dist/testing/mocks/MockSyncStore.js +11 -11
  329. package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
  330. package/dist/testing/mocks/MockWebSocket.js +22 -21
  331. package/dist/transactions/TransactionQueue.d.ts +190 -221
  332. package/dist/transactions/TransactionQueue.js +424 -822
  333. package/dist/transactions/TransactionStore.d.ts +20 -0
  334. package/dist/transactions/TransactionStore.js +53 -0
  335. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  336. package/dist/transactions/UnconfirmedWrites.js +104 -0
  337. package/dist/transactions/coalesceRules.d.ts +58 -0
  338. package/dist/transactions/coalesceRules.js +140 -0
  339. package/dist/transactions/commitPayload.d.ts +130 -0
  340. package/dist/transactions/commitPayload.js +143 -0
  341. package/dist/transactions/deltaConfirmation.d.ts +58 -0
  342. package/dist/transactions/deltaConfirmation.js +215 -0
  343. package/dist/transactions/optimisticApply.d.ts +49 -0
  344. package/dist/transactions/optimisticApply.js +65 -0
  345. package/dist/transactions/replayValidation.d.ts +99 -0
  346. package/dist/transactions/replayValidation.js +111 -0
  347. package/dist/types/global.d.ts +46 -41
  348. package/dist/types/global.js +20 -19
  349. package/dist/types/index.d.ts +74 -80
  350. package/dist/types/index.js +22 -27
  351. package/dist/types/modelData.d.ts +10 -0
  352. package/dist/types/modelData.js +9 -0
  353. package/dist/types/participant.d.ts +20 -0
  354. package/dist/types/participant.js +10 -0
  355. package/dist/types/streams.d.ts +216 -209
  356. package/dist/types/streams.js +7 -7
  357. package/dist/utils/asyncIterator.d.ts +25 -32
  358. package/dist/utils/asyncIterator.js +25 -32
  359. package/dist/utils/duration.d.ts +12 -15
  360. package/dist/utils/duration.js +12 -15
  361. package/dist/utils/mobxSetup.d.ts +53 -0
  362. package/dist/utils/{mobx-setup.js → mobxSetup.js} +44 -100
  363. package/dist/webhooks/events.d.ts +21 -16
  364. package/dist/webhooks/events.js +10 -8
  365. package/dist/webhooks/index.d.ts +5 -7
  366. package/dist/webhooks/index.js +5 -7
  367. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  368. package/dist/wire/delta.js +114 -0
  369. package/dist/wire/errorEnvelope.d.ts +35 -27
  370. package/dist/wire/errorEnvelope.js +38 -32
  371. package/dist/wire/frames.d.ts +150 -67
  372. package/dist/wire/frames.js +48 -1
  373. package/dist/wire/index.d.ts +18 -13
  374. package/dist/wire/index.js +36 -13
  375. package/dist/wire/listEnvelope.d.ts +16 -23
  376. package/dist/wire/listEnvelope.js +7 -6
  377. package/dist/wire/protocol.d.ts +38 -0
  378. package/dist/wire/protocol.js +38 -0
  379. package/dist/wire/protocolVersion.d.ts +60 -0
  380. package/dist/wire/protocolVersion.js +67 -0
  381. package/docs/api-keys.md +4 -3
  382. package/docs/coordination.md +59 -0
  383. package/docs/examples/existing-python-backend.md +3 -3
  384. package/docs/identity.md +4 -4
  385. package/docs/integration-guide.md +1 -1
  386. package/docs/react.md +1 -1
  387. package/docs/sessions.md +5 -7
  388. package/package.json +24 -21
  389. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  390. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  391. package/dist/client/index.d.ts +0 -36
  392. package/dist/client/index.js +0 -33
  393. package/dist/config/index.d.ts +0 -10
  394. package/dist/config/index.js +0 -12
  395. package/dist/core/query-utils.d.ts +0 -34
  396. package/dist/core/query-utils.js +0 -59
  397. package/dist/interfaces/headless.d.ts +0 -95
  398. package/dist/interfaces/headless.js +0 -41
  399. package/dist/query/index.d.ts +0 -6
  400. package/dist/query/index.js +0 -5
  401. package/dist/realtime/index.d.ts +0 -10
  402. package/dist/realtime/index.js +0 -9
  403. package/dist/schema/plane.d.ts +0 -23
  404. package/dist/schema/plane.js +0 -19
  405. package/dist/schema/sync-delta-row.js +0 -103
  406. package/dist/schema/sync-delta-wire.js +0 -102
  407. package/dist/server/next.d.ts +0 -51
  408. package/dist/server/next.js +0 -47
  409. package/dist/server/read-config.d.ts +0 -67
  410. package/dist/server/read-config.js +0 -8
  411. package/dist/server/storage-mode.d.ts +0 -1
  412. package/dist/server/storage-mode.js +0 -18
  413. package/dist/source/connector-protocol.d.ts +0 -159
  414. package/dist/source/connector-protocol.js +0 -161
  415. package/dist/sync/OfflineFlush.d.ts +0 -9
  416. package/dist/sync/OfflineFlush.js +0 -22
  417. package/dist/sync/OfflineTransactionStore.d.ts +0 -37
  418. package/dist/sync/OfflineTransactionStore.js +0 -263
  419. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  420. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  421. package/dist/transactions/index.d.ts +0 -16
  422. package/dist/transactions/index.js +0 -7
  423. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  424. package/dist/transactions/mutation-error-handler.js +0 -39
  425. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,23 +1,20 @@
1
1
  import { z } from 'zod';
2
2
  import { syncGroupInputSchema } from '../schema/roles.js';
3
3
  /**
4
- * Coordination wire schema — the ONE canonical source for the three layers
5
- * that keep humans and agents from clobbering each other on a shared row.
6
- * See `packages/sync-engine/docs/coordination.md` ("The model — three layers,
7
- * one decision") for the conceptual model. The layers, outer-to-inner:
4
+ * The wire schemas for coordination — the shapes that keep humans and agents
5
+ * from overwriting each other on a shared row. Coordination works in three
6
+ * layers, from outermost to innermost:
8
7
  *
9
- * 1. PRESENCE (observation) who is working where; NEVER enforces.
10
- * 2. PESSIMISTIC (claims/leases) `claim_begin`/`claim_abandon`;
11
- * mutual exclusion between participants.
12
- * 3. OPTIMISTIC (stale-context) `readAt` + `onStale` write-guard;
13
- * last-writer-wins lost-update detection.
8
+ * 1. Presence (observation): who is working where. It reports, never blocks.
9
+ * 2. Claims (pessimistic leases): `claim_begin` / `claim_abandon` grant one
10
+ * participant exclusive intent on a target while others wait.
11
+ * 3. Stale-context (optimistic): a `readAt` watermark plus an `onStale` write
12
+ * guard that catches a lost update when the row moved after you read it.
14
13
  *
15
- * Both the SDK (`types/streams.ts`) and the sync-server (`hub/types.ts`,
16
- * `presence/*`) derive their TypeScript types from THESE schemas via
17
- * `z.infer`, instead of re-declaring overlapping shapes. That collapses the
18
- * field drift this surface accreted — e.g. the SDK's claim view dropping
19
- * `status`/`error`, `onStale` declared 5×, `ClaimStatus` declared 2× — into
20
- * a single definition that the wire ingest can also validate at runtime.
14
+ * These Zod schemas are the single definition of each shape. Both the client
15
+ * SDK and the server derive their TypeScript types from them with `z.infer`
16
+ * rather than re-declaring the shapes, and the server validates inbound frames
17
+ * against them at runtime.
21
18
  */
22
19
  // ─────────────────────────────────────────────────────────────────────────
23
20
  // Shared primitives
@@ -31,21 +28,20 @@ export const targetRangeSchema = z.object({
31
28
  });
32
29
  export const participantKindSchema = z.enum(['user', 'agent', 'system']);
33
30
  /**
34
- * Wire-tolerant participant kind for INGEST. The claim/presence streams
35
- * historically labelled a non-agent participant `'human'`, while the
36
- * capability/identity/lease surfaces all say `'user'` the same participant,
37
- * two dialects. This normalizes the legacy `'human'` to the canonical `'user'`
38
- * on read so every consumer switches on ONE vocabulary. Producers emit
39
- * canonical {@link participantKindSchema} values; this only forgives an older
40
- * frame still carrying `'human'`. Additive — never widens the output union.
31
+ * Parses a participant kind from an inbound frame, tolerating an older wire
32
+ * dialect. Some presence and claim frames label a non-agent participant
33
+ * `'human'`, while the rest of the surface uses `'user'` for the same
34
+ * participant. This normalizes `'human'` to `'user'` on read so every consumer
35
+ * switches on one vocabulary. Producers emit the canonical
36
+ * {@link participantKindSchema} values, and the output union is never widened.
41
37
  */
42
38
  export const wireParticipantKindSchema = z.preprocess((value) => (value === 'human' ? 'user' : value), participantKindSchema);
43
39
  /**
44
- * Resolve a peer's kind from an inbound presence/claim frame. Prefers the
45
- * server-stamped `participantKind` (normalized via
46
- * {@link wireParticipantKindSchema}); frames from servers that predate the
47
- * field fall back to the lossy `isAgent` boolean which can say 'agent' or
48
- * 'user' but never 'system' (the flatten this field exists to remove).
40
+ * Resolves a peer's kind from an inbound presence or claim frame. It prefers
41
+ * the server-stamped `participantKind` (normalized through
42
+ * {@link wireParticipantKindSchema}). A frame from an older server that omits
43
+ * that field falls back to the `isAgent` boolean, which can tell 'agent' from
44
+ * 'user' but can never report 'system'.
49
45
  */
50
46
  export function participantKindFromWire(wireKind, isAgent) {
51
47
  const parsed = wireParticipantKindSchema.safeParse(wireKind);
@@ -54,18 +50,18 @@ export function participantKindFromWire(wireKind, isAgent) {
54
50
  return isAgent ? 'agent' : 'user';
55
51
  }
56
52
  /**
57
- * The peer-visible explanation a claim/claim carries, lifted from its opaque
58
- * `meta.description`. One place for the `typeof meta?.description === 'string'`
59
- * unfold that the claim/claim/presence surfaces each re-implemented callers
60
- * with an explicit `description` field still prefer it (`explicit ?? fromMeta`).
53
+ * Reads the peer-visible description a claim or presence frame carries in its
54
+ * opaque `meta.description`. This is the single place that unpacks that field.
55
+ * A caller that has an explicit `description` should prefer it
56
+ * (`explicit ?? fromMeta`).
61
57
  */
62
58
  export function descriptionFromMeta(meta) {
63
59
  return typeof meta?.description === 'string' ? meta.description : undefined;
64
60
  }
65
61
  /**
66
- * What a claim / claim / activity points at. The common locator shared by
67
- * all three layers an entity, optionally narrowed to a path, range, or
68
- * field, with opaque app metadata.
62
+ * What a coordination event points at the locator shared by all three
63
+ * layers. It names an entity, optionally narrowed to a path, range, or field,
64
+ * and carries opaque application metadata.
69
65
  */
70
66
  export const targetRefSchema = z.object({
71
67
  entityType: z.string(),
@@ -76,18 +72,17 @@ export const targetRefSchema = z.object({
76
72
  meta: z.record(z.string(), z.unknown()).optional(),
77
73
  });
78
74
  // ─────────────────────────────────────────────────────────────────────────
79
- // Layer 3 — OPTIMISTIC stale-context (the write-guard)
75
+ // Layer 3 — optimistic stale-context (the write guard)
80
76
  // ─────────────────────────────────────────────────────────────────────────
81
77
  /**
82
- * Mode applied when a write's snapshot watermark (`readAt`) is older than the
83
- * target row's latest delta. Three dispositions, split by the non-coercion
84
- * convention (see docs/concurrency-convention.md):
85
- * `notify` — NON-COERCIVE: hold the write, return a `StaleNotification`
86
- * with the current value; the actor (agent or human) resolves.
87
- * • `reject` — coercive escape hatch: throw `AbloStaleContextError`
88
- * (default when `readAt` is present).
89
- * • `overwrite` — coercive escape hatch: apply blindly last-writer-wins, no
90
- * signal.
78
+ * How the server treats a write whose snapshot watermark (`readAt`) is older
79
+ * than the target row's latest change. There are three dispositions:
80
+ * `notify` — hold the write and return a {@link StaleNotification}
81
+ * carrying the current value, so the actor (agent or human)
82
+ * can resolve it.
83
+ * • `reject` — throw `AbloStaleContextError`, the default when `readAt`
84
+ * is present.
85
+ * • `overwrite` — apply the write blindly, last write wins, with no signal.
91
86
  */
92
87
  export const onStaleModeSchema = z.enum(['reject', 'overwrite', 'notify']);
93
88
  /**
@@ -102,30 +97,23 @@ export const writeGuardSchema = z.object({
102
97
  bypass: z.boolean().optional(),
103
98
  });
104
99
  /**
105
- * The advisory signal returned to a committer whose write hit a stale-context
106
- * conflict under `onStale: 'notify'` — the engine's answer to "the typed value
107
- * you reasoned against changed while you were away."
100
+ * The advisory returned to a committer whose write hit a stale-context
101
+ * conflict under `onStale: 'notify'` — it reports that the value the committer
102
+ * reasoned against changed while they were away. Rather than throwing, the
103
+ * server hands back the conflicting field's current value as data so the
104
+ * actor — an agent or a human — can reconcile and re-commit. A claim is the
105
+ * prospective form of the same idea (coordinate before acting); this
106
+ * notification is the in-flight form (here is what changed, you resolve). It
107
+ * rides on the commit acknowledgement alongside `lastSyncId`; an empty or
108
+ * absent array means nothing the committer depended on moved.
108
109
  *
109
- * Philosophy: NON-COERCION. The engine's job is to surface the truthful current
110
- * state and let the intelligent actor agent OR human — decide what to do; it
111
- * does NOT force an outcome. The two *forcing* dispositions are `reject`
112
- * (force-abort, discards the work) and `overwrite` (force-clobber). This
113
- * notification is the non-coercive path: instead of throwing, the server hands
114
- * back the conflicting field's *current* value as data so the actor can solve
115
- * it. The CLAIM is the prospective form of the same principle (coordinate
116
- * before acting); this notification is the in-flight form (here's what changed,
117
- * you resolve). Both an agent reasoning over the change and a human watching the
118
- * row are valid resolvers. (Cf. CoAgent/MTPO, arXiv:2606.15376, which bets the
119
- * resolver is specifically an LLM; Ablo's bet is the same non-coercion, actor
120
- * left to agent or human.) Rides on the commit ack alongside `lastSyncId`; an
121
- * empty/absent array means no premise moved.
122
- *
123
- * Only `notify` produces this: the conflicting op was HELD (not written), and
124
- * the actor reconciles against `currentValues` and re-commits. (`reject` throws,
125
- * `overwrite` is silent — neither notifies.)
110
+ * Only `onStale: 'notify'` produces this. The conflicting operation was held,
111
+ * not written, and the actor reconciles against `currentValues` and
112
+ * re-commits. `reject` throws instead, and `overwrite` proceeds silently
113
+ * neither notifies.
126
114
  */
127
115
  export const staleNotificationSchema = z.object({
128
- /** Stripe-style object tag every returned object names its type. */
116
+ /** Names this object's type; every returned object carries such a tag. */
129
117
  object: z.literal('stale_notification').optional(),
130
118
  /** Model name of the conflicting row. */
131
119
  model: z.string(),
@@ -145,8 +133,8 @@ export const staleNotificationSchema = z.object({
145
133
  */
146
134
  conflictingFields: z.array(z.string()),
147
135
  /**
148
- * Post-conflict live values of `conflictingFields` — the part a plain stale
149
- * error never carried. Lets the LLM self-heal without a round-trip read.
136
+ * The live values of `conflictingFields` after the conflict — the piece a
137
+ * plain stale error omits. It lets the actor reconcile without a follow-up read.
150
138
  */
151
139
  currentValues: z.record(z.string(), z.unknown()),
152
140
  /** Who wrote the conflicting delta. */
@@ -164,18 +152,19 @@ export const staleNotificationSchema = z.object({
164
152
  group: z.string().optional(),
165
153
  });
166
154
  /**
167
- * A read DEPENDENCY declared on a commit the STORM "did anything I looked at
168
- * change?" layer (vs. the write-target check that only validates the rows being
169
- * written). The server re-runs stale detection against each declared read at
170
- * `readAt`; a moved premise fires the entry's `onStale` disposition (default
171
- * `reject`) over the WHOLE batch (`notify` holds every write + notifies;
172
- * `reject` aborts; `overwrite` proceeds silently). Two granularities, choice:
155
+ * A read that a commit declares it depended on, so the server can ask "did
156
+ * anything I looked at change?" broader than the write-target check, which
157
+ * only validates the rows being written. The server re-runs stale detection
158
+ * against each declared read at its `readAt`; a moved premise fires the entry's
159
+ * `onStale` disposition (default `reject`) across the whole batch (`notify`
160
+ * holds every write and notifies, `reject` aborts, `overwrite` proceeds
161
+ * silently). A dependency comes at one of two granularities:
173
162
  *
174
- * • ROW — `{ model, id, readAt, fields? }`: did this specific row (optionally
175
- * these fields) change? The literal STORM/per-object premise.
176
- * • GROUP — `{ group, readAt }`: did ANYTHING in this sync group change? `group`
177
- * is a sync-group key like `deck:abc` or `slide:s1` the same unit a
178
- * human/agent watches and claims. Coarser, and more Ablo-native.
163
+ * • Row — `{ model, id, readAt, fields? }`: did this specific row, or these
164
+ * specific fields, change?
165
+ * • Group — `{ group, readAt }`: did anything in this sync group change?
166
+ * `group` is a sync-group key such as `deck:abc` or `slide:s1`, the
167
+ * same unit a participant watches and claims.
179
168
  */
180
169
  export const readDependencySchema = z.union([
181
170
  z.object({
@@ -192,14 +181,13 @@ export const readDependencySchema = z.union([
192
181
  }),
193
182
  ]);
194
183
  // ─────────────────────────────────────────────────────────────────────────
195
- // Layer 2 — PESSIMISTIC claim / claim-lease
184
+ // Layer 2 — pessimistic claims and leases
196
185
  // ─────────────────────────────────────────────────────────────────────────
197
186
  /**
198
- * Lifecycle of an claim the Stripe `PaymentIntent.status` shape. Absent on
199
- * the wire ⇒ `'active'` (additive back-compat). The server stamps `'active'`
200
- * on `claim_begin` and emits a single terminal frame (`committed` /
201
- * `canceled` / `expired`) as the claim ends, so contenders learn *how* it
202
- * resolved, not merely that it vanished.
187
+ * The lifecycle of a claim. When absent on the wire it means `'active'` (an
188
+ * additive back-compat default). The server stamps `'active'` on `claim_begin`
189
+ * and emits one terminal frame `committed`, `canceled`, or `expired` — as the
190
+ * claim ends, so contenders learn how it resolved, not merely that it vanished.
203
191
  */
204
192
  export const claimStatusSchema = z.enum([
205
193
  'active',
@@ -241,16 +229,12 @@ export const claimErrorSchema = z.object({
241
229
  policyReason: z.string().optional(),
242
230
  });
243
231
  /**
244
- * A declared pending-mutation claim — the unit broadcast in presence
245
- * `activeClaims`. Clients supply the descriptive `targetRef` fields, an
246
- * explanatory `reason`, and a chosen `claimId`; the SERVER stamps `declaredAt` /
247
- * `expiresAt` and may set `status` / `error`.
248
- *
249
- * `status` and `error` are OPTIONAL: this single shape serves both the
250
- * server (which sets them) and the SDK view (which historically omitted
251
- * them). The superset is structurally assignable wherever the leaner view
252
- * was used, so the two prior copies collapse into this one without breaking
253
- * SDK consumers.
232
+ * A declared, pending-mutation claim — the unit broadcast inside a presence
233
+ * frame's `activeClaims`. The client supplies the descriptive `targetRef`
234
+ * fields, an explanatory `reason`, and a chosen `claimId`; the server stamps
235
+ * `declaredAt` and `expiresAt` and may set `status` and `error`. Those last
236
+ * two are optional, so one shape serves both the server, which sets them, and
237
+ * the leaner SDK view, which reads a claim without them.
254
238
  */
255
239
  export const wireClaimSchema = wireClaimBaseSchema.extend({
256
240
  error: claimErrorSchema.optional(),
@@ -266,9 +250,9 @@ export const claimRejectionSchema = z.object({
266
250
  policyReason: z.string().optional(),
267
251
  });
268
252
  /**
269
- * What a {@link ModelClaim} points at — the SDK-facing target locator, keyed by
270
- * `model`/`id` (the `ablo.<model>` vocabulary) rather than the wire's
271
- * `entityType`/`entityId`. Structurally the public `ModelTarget`.
253
+ * What a {@link ModelClaim} points at — the target locator as SDK callers see
254
+ * it, keyed by `model` and `id` rather than the wire schema's `entityType` and
255
+ * `entityId`. This is the public `ModelTarget` shape.
272
256
  */
273
257
  export const modelTargetSchema = z
274
258
  .object({
@@ -281,17 +265,16 @@ export const modelTargetSchema = z
281
265
  })
282
266
  .readonly();
283
267
  /**
284
- * A claim as surfaced to SDK callers and the HTTP claim routes
285
- * (`ablo.<model>.claim.state`, `/v1/claims`) — the resolved, peer-readable
286
- * view of one active or queued claim. The ONE canonical shape: the client
287
- * (`Ablo.ts`) derives its `ModelClaim` from this, and the sync-server's two
288
- * route copies adopt it once the engine dist is rebuilt.
268
+ * A claim as SDK callers and the HTTP claim routes see it
269
+ * (`ablo.<model>.claim.state`, `/v1/claims`) — the resolved, peer-readable view
270
+ * of one active or queued claim. The client's `ModelClaim` type derives from
271
+ * this shape.
289
272
  *
290
- * `expiresAt` is **epoch-ms** (a number) here — the same representation as the
291
- * WS `WireClaim`, so there is ONE timestamp encoding across wire, SDK, HTTP,
292
- * and errors (Stripe-style integer unix timestamps; no ISO string anywhere).
293
- * `participantKind` ingests via {@link wireParticipantKindSchema} so a legacy
294
- * `'human'` frame normalizes to `'user'`.
273
+ * `expiresAt` is epoch milliseconds (a number), the same encoding as the
274
+ * WebSocket {@link WireClaim}, so one timestamp representation spans the wire,
275
+ * the SDK, HTTP, and errors there is no ISO string anywhere.
276
+ * `participantKind` is parsed through {@link wireParticipantKindSchema}, so a
277
+ * legacy `'human'` frame normalizes to `'user'`.
295
278
  */
296
279
  export const modelClaimSchema = z
297
280
  .object({
@@ -309,10 +292,10 @@ export const modelClaimSchema = z
309
292
  })
310
293
  .readonly();
311
294
  /**
312
- * `claim_begin` payload (client → server). The descriptive target + reason,
313
- * plus an optional duration hint and the opt-in fair-queue flag. The server
314
- * stamps the lifecycle/timestamp fields, so they are NOT part of the inbound
315
- * shape — this is exactly what the WS ingest validates.
295
+ * The `claim_begin` payload a client sends. It carries the descriptive target
296
+ * and reason, an optional duration hint, and the opt-in fair-queue flag. The
297
+ * server stamps the lifecycle and timestamp fields, so they are not part of
298
+ * this inbound shape — this is exactly what the server validates on ingest.
316
299
  */
317
300
  export const claimBeginPayloadSchema = targetRefSchema.extend({
318
301
  claimId: z.string(),
@@ -320,19 +303,17 @@ export const claimBeginPayloadSchema = targetRefSchema.extend({
320
303
  /** Hint for `expiresAt`; the server caps it. */
321
304
  estimatedMs: z.number().optional(),
322
305
  /**
323
- * Opt into the fair wait queue: when the target is already held, the server
324
- * enqueues this claim (FIFO) and replies `claim_queued` → later
325
- * `claim_granted`, instead of `claim_rejected`. Clients that set this MUST
326
- * handle the grant.
306
+ * Opt into the fair wait queue. When the target is already held, the server
307
+ * enqueues this claim in FIFO order and replies `claim_queued`, then
308
+ * `claim_granted` later, instead of `claim_rejected`. A client that sets this
309
+ * must be ready to handle the grant.
327
310
  */
328
311
  queue: z.boolean().optional(),
329
312
  });
330
313
  /**
331
- * `claim_abandon` payload (client → server). `entityType`/`entityId` are
332
- * carried so the server can DEQUEUE a still-*waiting* (not held) claim from
333
- * the FIFO line the held-claim path needs only `claimId`. (The previous
334
- * wire type omitted these two even though the handler reads them; the schema
335
- * documents what the code actually uses.)
314
+ * The `claim_abandon` payload a client sends. `entityType` and `entityId` let
315
+ * the server dequeue a claim that is still waiting (not yet held) from the FIFO
316
+ * line; abandoning a claim that is already held needs only `claimId`.
336
317
  */
337
318
  export const claimAbandonPayloadSchema = z.object({
338
319
  claimId: z.string(),
@@ -340,13 +321,13 @@ export const claimAbandonPayloadSchema = z.object({
340
321
  entityId: z.string().optional(),
341
322
  });
342
323
  /**
343
- * `claim_reorder` payload (client → server). A privileged participant (e.g. a
344
- * supervisor over its sub-agents) re-ranks the FIFO wait queue for an entity:
345
- * `order` lists waiters by `heldBy`+`claimId` in the desired priority. Waiters
346
- * not listed keep their relative order behind the listed ones. The server gates
347
- * who may call this; an unauthorized sender is dropped. Unlike `claim_abandon`
348
- * (acts on the caller's own entry), reorder acts on OTHER participants' queue
349
- * positions — hence the authorization gate.
324
+ * The `claim_reorder` payload a client sends. A privileged participant, such as
325
+ * a supervisor over its sub-agents, re-ranks the FIFO wait queue for an entity:
326
+ * `order` lists waiters by `heldBy` and `claimId` in the desired priority, and
327
+ * any waiter not listed keeps its relative order behind those that are. The
328
+ * server gates who may call this and drops an unauthorized sender. Where
329
+ * `claim_abandon` acts on the caller's own entry, a reorder acts on other
330
+ * participants' queue positions — which is why it is gated.
350
331
  */
351
332
  export const claimReorderPayloadSchema = z.object({
352
333
  entityType: z.string(),
@@ -354,15 +335,98 @@ export const claimReorderPayloadSchema = z.object({
354
335
  order: z.array(z.object({ heldBy: z.string(), claimId: z.string() })),
355
336
  });
356
337
  // ─────────────────────────────────────────────────────────────────────────
338
+ // Heartbeat — the async / long-running-work surface of a claim.
339
+ //
340
+ // A claim's TTL is crash cleanup, not a work-duration estimate. Work that
341
+ // outlives it — an agent run, a background worker's job — keeps its lease by
342
+ // BEATING: request `claim_heartbeat`, reply `claim_heartbeat_ack`. One field
343
+ // set serves every shape; the single and batched payloads are both derived
344
+ // from it, and the WebSocket frame and HTTP routes are two encodings of the
345
+ // same messages. Everything long-running-work-related on the wire lives in
346
+ // this block.
347
+ // ─────────────────────────────────────────────────────────────────────────
348
+ /**
349
+ * The one field set behind every heartbeat message. The single-claim payload
350
+ * refines it; the batched payload picks from it — there is deliberately no
351
+ * second shape to keep in sync.
352
+ */
353
+ const claimHeartbeatFieldsSchema = z.object({
354
+ claimId: z.string().optional(),
355
+ entityType: z.string().optional(),
356
+ entityId: z.string().optional(),
357
+ /** Requested extension from now; the server clamps it, and an extension
358
+ * never shortens a lease. */
359
+ ttlMs: z.number().positive().optional(),
360
+ /**
361
+ * Lightweight progress the beat carries along ("42/100 pages") — stored
362
+ * as the claim's `meta.progress` (last beat wins) and peer-visible via
363
+ * `claim.state` while the lease is held. This is presence, not a
364
+ * checkpoint: it dies with the lease. Crash-recoverable progress belongs
365
+ * in the data itself — write a row, and every subscriber already sees it.
366
+ */
367
+ details: z.record(z.string(), z.unknown()).optional(),
368
+ });
369
+ /**
370
+ * The `claim_heartbeat` payload a client sends to extend a lease it holds (or
371
+ * refresh its slot in the wait queue) past the liveness window — the
372
+ * work-duration signal for long-running holders, distinct from the connection
373
+ * keepalive.
374
+ *
375
+ * The claim is identified either way: by `claimId`, or — since a claim is
376
+ * singular per (actor, entity) — by the full `entityType`/`entityId` target
377
+ * ("my claim on this row"). At least one of the two must be present. The
378
+ * target also lets the server resolve without a scan and is required to
379
+ * refresh a *queued* claim (a waiter is not in the holder set the server
380
+ * would otherwise search).
381
+ */
382
+ export const claimHeartbeatPayloadSchema = claimHeartbeatFieldsSchema.refine((payload) => payload.claimId !== undefined ||
383
+ (payload.entityType !== undefined && payload.entityId !== undefined), {
384
+ message: 'a heartbeat must identify its claim — pass claimId, or entityType and entityId together',
385
+ });
386
+ /**
387
+ * The server's reply to a `claim_heartbeat`. For a socketless worker the
388
+ * heartbeat reply is the only inbound signal path, so it carries the lease's
389
+ * fate rather than a bare ok: `held` (extended to `expiresAt`), `queued`
390
+ * (slot refreshed; `position` is the current place in line), or `lost` (the
391
+ * lease expired and the queue moved on — the worker should abandon or
392
+ * re-queue, and any write it still attempts is caught by its `readAt` guard).
393
+ */
394
+ export const claimHeartbeatAckPayloadSchema = z.object({
395
+ claimId: z.string(),
396
+ status: z.enum(['held', 'queued', 'lost']),
397
+ expiresAt: z.number().optional(),
398
+ position: z.number().optional(),
399
+ /**
400
+ * How many participants are waiting in line behind a held lease — the
401
+ * cooperative-yield pressure signal (present on `held`). A worker that can
402
+ * checkpoint may choose to release early when others wait. Hard
403
+ * cancellation needs no extra field: a preempted, expired, or revoked
404
+ * lease answers the next beat with `lost`.
405
+ */
406
+ queueDepth: z.number().optional(),
407
+ });
408
+ /**
409
+ * The batched heartbeat — one request extends every lease the caller holds
410
+ * on its plane (the socketless twin of the WebSocket keepalive, which renews
411
+ * all held leases on every ping). For a worker holding many rows this is one
412
+ * round trip per cadence instead of one per claim. Queued slots are not
413
+ * batch-refreshed: a waiter knows its target and beats it directly.
414
+ */
415
+ export const claimHeartbeatBatchPayloadSchema = claimHeartbeatFieldsSchema.pick({ ttlMs: true });
416
+ /** Reply to a batched heartbeat: one ack entry per lease that was extended. */
417
+ export const claimHeartbeatBatchAckPayloadSchema = z.object({
418
+ results: z.array(claimHeartbeatAckPayloadSchema),
419
+ });
420
+ // ─────────────────────────────────────────────────────────────────────────
357
421
  // Read interest — area-of-interest navigation (update_subscription)
358
422
  // ─────────────────────────────────────────────────────────────────────────
359
423
  /**
360
- * `update_subscription` payload (client → server). Replaces the connection's
361
- * connection-level read interest with the COMPLETE set of sync groups — the
362
- * READ counterpart to a claim (no write-claim, no TTL). Each entry is a
424
+ * The `update_subscription` payload a client sends. It replaces the
425
+ * connection's read interest with the complete set of sync groups — the read
426
+ * counterpart to a claim, with no write lock and no TTL. Each entry is a
363
427
  * {@link syncGroupInputSchema} (`'default'` or a branded `kind:id`), so a
364
- * malformed group is rejected at ingest instead of being silently indexed.
365
- * This is untrusted client input, so the element type is strict.
428
+ * malformed group is rejected on ingest rather than silently indexed. The
429
+ * element type is strict because this is untrusted client input.
366
430
  */
367
431
  export const updateSubscriptionPayloadSchema = z.object({
368
432
  syncGroups: z.array(syncGroupInputSchema),
@@ -405,7 +469,7 @@ export const commitOperationSchema = writeGuardSchema.extend({
405
469
  transactionId: z.string().nullish(),
406
470
  });
407
471
  // ─────────────────────────────────────────────────────────────────────────
408
- // Layer 1 — PRESENCE (observation only; never enforces)
472
+ // Layer 1 — presence (observation only; it never enforces)
409
473
  // ─────────────────────────────────────────────────────────────────────────
410
474
  export const presenceKindSchema = z.enum(['enter', 'update', 'leave']);
411
475
  /** What a participant is actively working on (agents fill this in). */
@@ -1,14 +1,13 @@
1
1
  /**
2
- * Claim log — the easy way to SEE agents colliding.
2
+ * A claim log — the simplest way to watch agents collide. The engine reports
3
+ * the claim lifecycle (`acquired → queued → granted → lost / rejected /
4
+ * expired`) and the notify-instead-of-abort stale write through two channels:
5
+ * human-readable `logger` lines (shown with `new Ablo({ debug: true })`) and
6
+ * structured `observability.captureClaim` / `captureConflict` calls.
3
7
  *
4
- * The engine emits the claim lifecycle (`acquired queued granted lost /
5
- * rejected / expired`) and the notify-instead-of-abort stale-write collision
6
- * through two seams: human `logger` lines (visible with `new Ablo({ debug: true })`)
7
- * and structured `observability.captureClaim` / `captureConflict` calls.
8
- *
9
- * This is the third, evals-shaped path: hand a {@link ClaimLog} to
10
- * `Ablo({ observability })`, run your scenario, then read back an ordered list
11
- * you can print for eyeballing or `collisions()` for assertions.
8
+ * This is a third channel, shaped for tests and evals. Pass a {@link ClaimLog}
9
+ * as `Ablo({ observability })`, run your scenario, then read back an ordered
10
+ * list print it to eyeball what happened, or call `collisions()` to assert on it.
12
11
  */
13
12
  import type { SyncObservabilityProvider, ClaimEvent, ConflictEvent } from '../interfaces/index.js';
14
13
  /** A claim state change as one quiet, greppable line. */
@@ -19,7 +18,7 @@ export declare function formatConflict(e: ConflictEvent): string;
19
18
  export interface ClaimLogEntry {
20
19
  /** Monotonic order index — deterministic, clock-free, eval-friendly. */
21
20
  readonly seq: number;
22
- /** The same one-line text the console and breadcrumb seams emit. */
21
+ /** The same one-line text the console and breadcrumb channels emit. */
23
22
  readonly line: string;
24
23
  /** A collision worth flagging: a rejected/lost claim or a stale write. */
25
24
  readonly collision: boolean;
@@ -83,7 +82,6 @@ export declare class ClaimLog implements SyncObservabilityProvider {
83
82
  captureReconciliation(): void;
84
83
  captureDeltaRetryExhausted(): void;
85
84
  captureWebSocketError(): void;
86
- captureOfflineFlushFailure(): void;
87
85
  captureSelfHealing(): void;
88
86
  captureCommitZeroSyncId(): void;
89
87
  startSpan<T>(_name: string, _op: string, fn: () => T): T;
@@ -1,18 +1,17 @@
1
1
  /**
2
- * Claim log — the easy way to SEE agents colliding.
2
+ * A claim log — the simplest way to watch agents collide. The engine reports
3
+ * the claim lifecycle (`acquired → queued → granted → lost / rejected /
4
+ * expired`) and the notify-instead-of-abort stale write through two channels:
5
+ * human-readable `logger` lines (shown with `new Ablo({ debug: true })`) and
6
+ * structured `observability.captureClaim` / `captureConflict` calls.
3
7
  *
4
- * The engine emits the claim lifecycle (`acquired queued granted lost /
5
- * rejected / expired`) and the notify-instead-of-abort stale-write collision
6
- * through two seams: human `logger` lines (visible with `new Ablo({ debug: true })`)
7
- * and structured `observability.captureClaim` / `captureConflict` calls.
8
- *
9
- * This is the third, evals-shaped path: hand a {@link ClaimLog} to
10
- * `Ablo({ observability })`, run your scenario, then read back an ordered list
11
- * you can print for eyeballing or `collisions()` for assertions.
8
+ * This is a third channel, shaped for tests and evals. Pass a {@link ClaimLog}
9
+ * as `Ablo({ observability })`, run your scenario, then read back an ordered
10
+ * list print it to eyeball what happened, or call `collisions()` to assert on it.
12
11
  */
13
12
  // ─────────────────────────────────────────────
14
- // Formatters — one readable line per event. Shared by the WS logger seam and
15
- // the log so console output and log output never drift.
13
+ // Formatters — one readable line per event. Shared by the debug logger and
14
+ // this log so console output and log output never drift.
16
15
  // ─────────────────────────────────────────────
17
16
  /** A claim state change as one quiet, greppable line. */
18
17
  export function formatClaim(e) {
@@ -22,7 +21,7 @@ export function formatClaim(e) {
22
21
  const actor = e.actor
23
22
  ? `${e.actor}${e.participantKind ? ` (${e.participantKind})` : ''}`
24
23
  : '';
25
- // `rejected`/`lost` name the BLOCKING holder; the rest name us (or no one).
24
+ // `rejected`/`lost` name the blocking holder; the rest name us (or no one).
26
25
  const by = actor
27
26
  ? e.phase === 'rejected' || e.phase === 'lost'
28
27
  ? ` — held by ${actor}`
@@ -54,7 +53,7 @@ export function formatConflict(e) {
54
53
  */
55
54
  export class ClaimLog {
56
55
  max;
57
- // Immutable list: a NEW array reference on every change. This is what lets
56
+ // Immutable list: a new array reference on every change. This is what lets
58
57
  // `useSyncExternalStore(log.onChange, () => log.entries)` detect updates —
59
58
  // it compares snapshots by reference, so an in-place push would never render.
60
59
  rows = [];
@@ -64,7 +63,7 @@ export class ClaimLog {
64
63
  constructor(max = 1_000) {
65
64
  this.max = max;
66
65
  }
67
- // —— the two seams we record ——
66
+ // —— the two channels we record ——
68
67
  captureClaim(claim) {
69
68
  this.add({
70
69
  line: formatClaim(claim),
@@ -135,7 +134,6 @@ export class ClaimLog {
135
134
  captureReconciliation() { }
136
135
  captureDeltaRetryExhausted() { }
137
136
  captureWebSocketError() { }
138
- captureOfflineFlushFailure() { }
139
137
  captureSelfHealing() { }
140
138
  captureCommitZeroSyncId() { }
141
139
  startSpan(_name, _op, fn) {
@@ -1,11 +1,9 @@
1
1
  /**
2
- * Ablo Sync Engine - Database Manager
3
- *
4
- * Manages the two-tier database architecture:
5
- * 1. ablo_databases - Metadata about workspace databases
6
- * 2. ablo_(hash) - Workspace-specific data storage
7
- *
8
- * Follows Ablo's architecture for database management.
2
+ * Manages the client-side IndexedDB databases the sync engine keeps in the
3
+ * browser. There are two tiers. A single registry database, `ablo_databases`,
4
+ * records metadata about every workspace database. Each user-and-workspace pair
5
+ * then gets its own data database, named `ablo_<hash>`, that holds the synced
6
+ * rows. {@link DatabaseManager} creates, versions, and deletes both tiers.
9
7
  */
10
8
  export interface DatabaseInfo {
11
9
  name: string;
@@ -25,7 +23,6 @@ export interface WorkspaceMetadata {
25
23
  updatedAt: Date;
26
24
  schemaHash?: string;
27
25
  syncGroups?: string[];
28
- versions?: Record<string, number>;
29
26
  }
30
27
  /**
31
28
  * DatabaseManager - Manages Ablo's two-tier database architecture