@abloatai/ablo 0.26.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 (398) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -85
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +131 -147
  5. package/dist/Database.d.ts +54 -68
  6. package/dist/Database.js +97 -113
  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 +37 -52
  12. package/dist/Model.js +46 -61
  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 +112 -112
  18. package/dist/SyncClient.js +165 -172
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  22. package/dist/adapters/inMemoryStorage.js +9 -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 +167 -119
  50. package/dist/client/Ablo.d.ts +73 -73
  51. package/dist/client/Ablo.js +125 -160
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +133 -38
  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 +14 -17
  61. package/dist/client/createInternalComponents.js +25 -30
  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 +57 -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 +67 -87
  76. package/dist/client/options.d.ts +134 -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 +15 -20
  91. package/dist/client/wsMutationExecutor.js +17 -23
  92. package/dist/context.d.ts +6 -4
  93. package/dist/context.js +6 -4
  94. package/dist/coordination/index.d.ts +10 -8
  95. package/dist/coordination/index.js +14 -12
  96. package/dist/coordination/schema.d.ts +176 -128
  97. package/dist/coordination/schema.js +197 -133
  98. package/dist/coordination/trace.d.ts +9 -10
  99. package/dist/coordination/trace.js +13 -14
  100. package/dist/core/DatabaseManager.d.ts +5 -7
  101. package/dist/core/DatabaseManager.js +15 -19
  102. package/dist/core/QueryProcessor.d.ts +7 -9
  103. package/dist/core/QueryProcessor.js +22 -28
  104. package/dist/core/QueryView.d.ts +8 -8
  105. package/dist/core/QueryView.js +2 -2
  106. package/dist/core/StoreManager.d.ts +12 -14
  107. package/dist/core/StoreManager.js +21 -24
  108. package/dist/core/ViewRegistry.d.ts +5 -5
  109. package/dist/core/ViewRegistry.js +4 -4
  110. package/dist/core/index.d.ts +17 -12
  111. package/dist/core/index.js +32 -26
  112. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  113. package/dist/core/openIDBWithTimeout.js +42 -43
  114. package/dist/core/queryUtils.d.ts +45 -0
  115. package/dist/core/queryUtils.js +69 -0
  116. package/dist/core/storeContract.d.ts +63 -61
  117. package/dist/core/storeContract.js +8 -12
  118. package/dist/environment.d.ts +28 -0
  119. package/dist/environment.js +21 -0
  120. package/dist/errorCodes.d.ts +107 -99
  121. package/dist/errorCodes.js +131 -132
  122. package/dist/errors.d.ts +160 -166
  123. package/dist/errors.js +155 -158
  124. package/dist/index.d.ts +30 -27
  125. package/dist/index.js +89 -86
  126. package/dist/interfaces/index.d.ts +102 -113
  127. package/dist/interfaces/index.js +5 -4
  128. package/dist/keys/index.d.ts +27 -29
  129. package/dist/keys/index.js +41 -40
  130. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  131. package/dist/mutators/RecordingTransaction.js +31 -37
  132. package/dist/mutators/Transaction.d.ts +18 -26
  133. package/dist/mutators/Transaction.js +14 -20
  134. package/dist/mutators/UndoManager.d.ts +122 -131
  135. package/dist/mutators/UndoManager.js +145 -156
  136. package/dist/mutators/defineMutators.d.ts +23 -34
  137. package/dist/mutators/defineMutators.js +14 -20
  138. package/dist/mutators/inverseOp.d.ts +12 -15
  139. package/dist/mutators/inverseOp.js +12 -15
  140. package/dist/mutators/mutateActions.d.ts +10 -9
  141. package/dist/mutators/mutateActions.js +1 -1
  142. package/dist/mutators/readerActions.d.ts +9 -8
  143. package/dist/mutators/readerActions.js +2 -2
  144. package/dist/mutators/undoApply.d.ts +31 -27
  145. package/dist/mutators/undoApply.js +26 -24
  146. package/dist/policy/index.d.ts +5 -3
  147. package/dist/policy/index.js +5 -3
  148. package/dist/policy/types.d.ts +104 -100
  149. package/dist/policy/types.js +67 -66
  150. package/dist/query/client.d.ts +28 -23
  151. package/dist/query/client.js +45 -43
  152. package/dist/query/types.d.ts +37 -60
  153. package/dist/query/types.js +13 -33
  154. package/dist/react/AbloProvider.d.ts +1 -1
  155. package/dist/react/AbloProvider.js +2 -2
  156. package/dist/react/context.d.ts +25 -28
  157. package/dist/react/context.js +9 -10
  158. package/dist/react/index.d.ts +41 -42
  159. package/dist/react/index.js +37 -38
  160. package/dist/react/internalContext.d.ts +17 -19
  161. package/dist/react/useAblo.d.ts +23 -22
  162. package/dist/react/useAblo.js +16 -14
  163. package/dist/react/useCurrentUserId.d.ts +8 -7
  164. package/dist/react/useCurrentUserId.js +8 -7
  165. package/dist/react/useErrorListener.d.ts +7 -7
  166. package/dist/react/useErrorListener.js +10 -11
  167. package/dist/react/useMutationFailureListener.d.ts +8 -8
  168. package/dist/react/useMutationFailureListener.js +8 -8
  169. package/dist/react/useMutators.d.ts +11 -11
  170. package/dist/react/useMutators.js +3 -3
  171. package/dist/react/useReactive.js +2 -2
  172. package/dist/react/useSyncStatus.d.ts +4 -6
  173. package/dist/react/useUndoScope.d.ts +7 -9
  174. package/dist/react/useUndoScope.js +1 -1
  175. package/dist/schema/coordination.d.ts +21 -25
  176. package/dist/schema/coordination.js +21 -25
  177. package/dist/schema/ddl.d.ts +43 -39
  178. package/dist/schema/ddl.js +75 -68
  179. package/dist/schema/ddlLock.d.ts +20 -24
  180. package/dist/schema/ddlLock.js +18 -23
  181. package/dist/schema/diff.d.ts +99 -61
  182. package/dist/schema/diff.js +43 -34
  183. package/dist/schema/field.d.ts +37 -42
  184. package/dist/schema/field.js +35 -48
  185. package/dist/schema/generate.d.ts +12 -12
  186. package/dist/schema/generate.js +12 -12
  187. package/dist/schema/index.d.ts +2 -2
  188. package/dist/schema/index.js +21 -23
  189. package/dist/schema/model.d.ts +118 -143
  190. package/dist/schema/model.js +22 -33
  191. package/dist/schema/openapi.d.ts +10 -9
  192. package/dist/schema/openapi.js +5 -3
  193. package/dist/schema/queries.d.ts +29 -31
  194. package/dist/schema/queries.js +23 -25
  195. package/dist/schema/relation.d.ts +89 -99
  196. package/dist/schema/relation.js +13 -13
  197. package/dist/schema/residency.d.ts +16 -13
  198. package/dist/schema/residency.js +16 -13
  199. package/dist/schema/roles.d.ts +36 -43
  200. package/dist/schema/roles.js +31 -37
  201. package/dist/schema/schema.d.ts +33 -42
  202. package/dist/schema/schema.js +31 -32
  203. package/dist/schema/select.d.ts +13 -13
  204. package/dist/schema/select.js +13 -13
  205. package/dist/schema/serialize.d.ts +28 -31
  206. package/dist/schema/serialize.js +27 -31
  207. package/dist/schema/sugar.d.ts +17 -32
  208. package/dist/schema/sugar.js +14 -29
  209. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  210. package/dist/schema/syncDeltaRow.js +89 -0
  211. package/dist/schema/tenancy.d.ts +44 -46
  212. package/dist/schema/tenancy.js +46 -48
  213. package/dist/server/adapter.d.ts +58 -58
  214. package/dist/server/adapter.js +13 -14
  215. package/dist/server/commit.d.ts +60 -64
  216. package/dist/server/index.d.ts +9 -10
  217. package/dist/server/index.js +1 -1
  218. package/dist/server/readConfig.d.ts +70 -0
  219. package/dist/server/readConfig.js +8 -0
  220. package/dist/server/storageMode.d.ts +23 -0
  221. package/dist/server/storageMode.js +17 -0
  222. package/dist/source/adapter.d.ts +30 -25
  223. package/dist/source/adapter.js +10 -10
  224. package/dist/source/adapters/drizzle.d.ts +28 -23
  225. package/dist/source/adapters/drizzle.js +30 -25
  226. package/dist/source/adapters/kysely.d.ts +27 -25
  227. package/dist/source/adapters/kysely.js +24 -23
  228. package/dist/source/adapters/memory.d.ts +8 -7
  229. package/dist/source/adapters/memory.js +9 -8
  230. package/dist/source/adapters/prisma.d.ts +13 -12
  231. package/dist/source/adapters/prisma.js +22 -25
  232. package/dist/source/conformance.d.ts +18 -11
  233. package/dist/source/conformance.js +17 -11
  234. package/dist/source/connector.d.ts +31 -32
  235. package/dist/source/connector.js +28 -28
  236. package/dist/source/connectorProtocol.d.ts +160 -0
  237. package/dist/source/connectorProtocol.js +162 -0
  238. package/dist/source/contract.d.ts +26 -27
  239. package/dist/source/contract.js +28 -29
  240. package/dist/source/factory.d.ts +46 -58
  241. package/dist/source/factory.js +22 -27
  242. package/dist/source/index.d.ts +7 -9
  243. package/dist/source/index.js +12 -14
  244. package/dist/source/migrations.d.ts +9 -9
  245. package/dist/source/migrations.js +9 -9
  246. package/dist/source/next.d.ts +9 -10
  247. package/dist/source/next.js +6 -7
  248. package/dist/source/pushQueue.d.ts +69 -47
  249. package/dist/source/pushQueue.js +32 -28
  250. package/dist/source/signing.d.ts +46 -17
  251. package/dist/source/signing.js +28 -11
  252. package/dist/source/types.d.ts +121 -104
  253. package/dist/source/types.js +13 -14
  254. package/dist/stores/ObjectStore.d.ts +10 -11
  255. package/dist/stores/ObjectStore.js +11 -12
  256. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  257. package/dist/stores/SyncActionStore.d.ts +7 -11
  258. package/dist/stores/SyncActionStore.js +13 -17
  259. package/dist/surface.d.ts +27 -20
  260. package/dist/surface.js +27 -20
  261. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  262. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  263. package/dist/sync/ConnectionManager.d.ts +39 -50
  264. package/dist/sync/ConnectionManager.js +55 -66
  265. package/dist/sync/NetworkProbe.d.ts +24 -29
  266. package/dist/sync/NetworkProbe.js +63 -69
  267. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  268. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  269. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  270. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  271. package/dist/sync/SyncWebSocket.d.ts +139 -165
  272. package/dist/sync/SyncWebSocket.js +191 -223
  273. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  274. package/dist/sync/awaitClaimGrant.js +11 -11
  275. package/dist/sync/bootstrapApply.d.ts +34 -24
  276. package/dist/sync/bootstrapApply.js +27 -19
  277. package/dist/sync/commitFrames.d.ts +21 -20
  278. package/dist/sync/commitFrames.js +18 -18
  279. package/dist/sync/createClaimStream.d.ts +23 -22
  280. package/dist/sync/createClaimStream.js +105 -23
  281. package/dist/sync/createPresenceStream.d.ts +19 -18
  282. package/dist/sync/createPresenceStream.js +25 -26
  283. package/dist/sync/createSnapshot.d.ts +12 -14
  284. package/dist/sync/createSnapshot.js +20 -26
  285. package/dist/sync/credentialLifecycle.d.ts +104 -104
  286. package/dist/sync/credentialLifecycle.js +140 -147
  287. package/dist/sync/deltaPipeline.d.ts +36 -34
  288. package/dist/sync/deltaPipeline.js +64 -65
  289. package/dist/sync/groupChange.d.ts +63 -61
  290. package/dist/sync/groupChange.js +74 -78
  291. package/dist/sync/heartbeat.d.ts +34 -33
  292. package/dist/sync/heartbeat.js +31 -31
  293. package/dist/sync/participants.d.ts +19 -19
  294. package/dist/sync/schemas.d.ts +3 -2
  295. package/dist/sync/schemas.js +14 -10
  296. package/dist/sync/syncCursor.d.ts +17 -21
  297. package/dist/sync/syncCursor.js +17 -21
  298. package/dist/sync/syncPlan.d.ts +28 -36
  299. package/dist/sync/syncPlan.js +18 -19
  300. package/dist/sync/syncPosition.d.ts +54 -49
  301. package/dist/sync/syncPosition.js +57 -52
  302. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  303. package/dist/sync/wsFrameHandlers.js +63 -67
  304. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  305. package/dist/testing/fixtures/bootstrap.js +12 -6
  306. package/dist/testing/fixtures/deltas.d.ts +30 -33
  307. package/dist/testing/fixtures/deltas.js +30 -33
  308. package/dist/testing/fixtures/models.d.ts +11 -10
  309. package/dist/testing/fixtures/models.js +11 -10
  310. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  311. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  312. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  313. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  314. package/dist/testing/helpers/wait.d.ts +13 -8
  315. package/dist/testing/helpers/wait.js +13 -8
  316. package/dist/testing/index.d.ts +3 -3
  317. package/dist/testing/index.js +2 -2
  318. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  319. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  320. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  321. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  322. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  323. package/dist/testing/mocks/MockSyncContext.js +15 -13
  324. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  325. package/dist/testing/mocks/MockSyncStore.js +11 -11
  326. package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
  327. package/dist/testing/mocks/MockWebSocket.js +22 -21
  328. package/dist/transactions/TransactionQueue.d.ts +181 -176
  329. package/dist/transactions/TransactionQueue.js +338 -350
  330. package/dist/transactions/TransactionStore.d.ts +6 -4
  331. package/dist/transactions/TransactionStore.js +6 -4
  332. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  333. package/dist/transactions/UnconfirmedWrites.js +104 -0
  334. package/dist/transactions/coalesceRules.d.ts +41 -17
  335. package/dist/transactions/coalesceRules.js +40 -17
  336. package/dist/transactions/commitPayload.d.ts +48 -52
  337. package/dist/transactions/commitPayload.js +48 -57
  338. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  339. package/dist/transactions/deltaConfirmation.js +37 -45
  340. package/dist/transactions/optimisticApply.d.ts +49 -0
  341. package/dist/transactions/optimisticApply.js +65 -0
  342. package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
  343. package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
  344. package/dist/types/global.d.ts +46 -41
  345. package/dist/types/global.js +20 -19
  346. package/dist/types/index.d.ts +71 -77
  347. package/dist/types/index.js +22 -22
  348. package/dist/types/modelData.d.ts +6 -8
  349. package/dist/types/modelData.js +5 -7
  350. package/dist/types/participant.d.ts +10 -11
  351. package/dist/types/participant.js +6 -8
  352. package/dist/types/streams.d.ts +208 -195
  353. package/dist/types/streams.js +7 -7
  354. package/dist/utils/asyncIterator.d.ts +25 -32
  355. package/dist/utils/asyncIterator.js +25 -32
  356. package/dist/utils/duration.d.ts +12 -15
  357. package/dist/utils/duration.js +12 -15
  358. package/dist/utils/mobxSetup.d.ts +53 -0
  359. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  360. package/dist/webhooks/events.d.ts +21 -16
  361. package/dist/webhooks/events.js +10 -8
  362. package/dist/webhooks/index.d.ts +5 -7
  363. package/dist/webhooks/index.js +5 -7
  364. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  365. package/dist/wire/delta.js +114 -0
  366. package/dist/wire/errorEnvelope.d.ts +30 -31
  367. package/dist/wire/errorEnvelope.js +34 -40
  368. package/dist/wire/frames.d.ts +79 -86
  369. package/dist/wire/frames.js +26 -33
  370. package/dist/wire/index.d.ts +14 -12
  371. package/dist/wire/index.js +30 -26
  372. package/dist/wire/listEnvelope.d.ts +16 -23
  373. package/dist/wire/listEnvelope.js +7 -6
  374. package/dist/wire/protocol.d.ts +25 -32
  375. package/dist/wire/protocol.js +25 -32
  376. package/dist/wire/protocolVersion.d.ts +44 -40
  377. package/dist/wire/protocolVersion.js +44 -40
  378. package/docs/coordination.md +59 -0
  379. package/package.json +11 -10
  380. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  381. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  382. package/dist/core/query-utils.d.ts +0 -34
  383. package/dist/core/query-utils.js +0 -59
  384. package/dist/schema/sync-delta-row.js +0 -103
  385. package/dist/schema/sync-delta-wire.js +0 -102
  386. package/dist/server/read-config.d.ts +0 -67
  387. package/dist/server/read-config.js +0 -8
  388. package/dist/server/storage-mode.d.ts +0 -8
  389. package/dist/server/storage-mode.js +0 -28
  390. package/dist/source/connector-protocol.d.ts +0 -159
  391. package/dist/source/connector-protocol.js +0 -161
  392. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  393. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  394. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  395. package/dist/transactions/mutation-error-handler.js +0 -39
  396. package/dist/transactions/optimistic.d.ts +0 -24
  397. package/dist/transactions/optimistic.js +0 -45
  398. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Ablo — The one-liner consumer API.
3
- *
4
- * Hides all internal wiring (ObjectPool, Database, SyncClient, WebSocket,
5
- * bootstrap, offline queue, DI adapters) behind a single function call.
2
+ * `Ablo`the one-call entry point to the sync engine client. It hides the
3
+ * internal wiring — the object pool, local database, sync client, WebSocket,
4
+ * bootstrap, and offline queue behind a single function that returns a typed
5
+ * client with one property per model in your schema.
6
6
  *
7
7
  * Usage:
8
8
  * import { Ablo } from '@abloatai/ablo';
@@ -24,7 +24,7 @@ import { initSyncEngine } from '../context.js';
24
24
  import { noopObservability, browserOnlineStatus, defaultSessionErrorDetector, noopAnalytics, } from '../SyncEngineContext.js';
25
25
  import { alwaysOnline } from '../adapters/alwaysOnline.js';
26
26
  import { validateAbloOptions } from './validateAbloOptions.js';
27
- import { ObjectPool } from '../ObjectPool.js';
27
+ import { InstanceCache } from '../InstanceCache.js';
28
28
  import {} from '../auth/index.js';
29
29
  import { mintSession } from './sessionMint.js';
30
30
  import { createAuthCredentialSource } from '../auth/credentialSource.js';
@@ -55,17 +55,18 @@ import { assertWriteOptions } from './writeOptionsSchema.js';
55
55
  // that read it. Re-exported there for use elsewhere in the file.
56
56
  // ── Auth normalization ─────────────────────────────────────────────────────
57
57
  /**
58
- * The one resolver the credential lifecycle needs: an async `() => token | null`,
59
- * or `null` when auth is static (a plain long-lived `apiKey` STRING with no
60
- * refresh the common case).
58
+ * The single resolver the credential lifecycle needs: an async
59
+ * `() => token | null`, or `null` when auth is static a plain long-lived
60
+ * `apiKey` string with no refresh, which is the common case.
61
61
  *
62
- * The short-lived per-user browser path passes a FUNCTION `apiKey` (an
63
- * `ApiKeySetter`): the SDK then drives the full credential lifecycle off it —
64
- * mint-before-connect, the proactive refresh timer + wake/online/focus re-mint,
65
- * and the reactive `credential_stale` re-mint. The resolver's contract is the
66
- * `ApiKeySetter` contract end-to-end: resolve a token, resolve `null` when the
67
- * login is gone (terminal `session_expired` → sign out), or THROW on a
68
- * transient failure ( back off, never sign out).
62
+ * The short-lived per-user browser path passes a function `apiKey` (an
63
+ * {@link ApiKeySetter}), and the SDK then drives the whole credential lifecycle
64
+ * from it: mint-before-connect, the proactive refresh timer with its
65
+ * wake/online/focus re-mint, and the reactive `credential_stale` re-mint. The
66
+ * resolver follows the `ApiKeySetter` contract end to end: resolve a token,
67
+ * resolve `null` when the login is gone (terminal surfaces `session_expired`
68
+ * and signs the user out), or throw on a transient failure (backs off, without
69
+ * signing out).
69
70
  */
70
71
  function resolveCredentialResolver(apiKey) {
71
72
  if (typeof apiKey === 'function')
@@ -86,10 +87,10 @@ export function Ablo(options) {
86
87
  const authInput = { options, env };
87
88
  const configuredApiKey = resolveApiKey(authInput);
88
89
  const configuredAuthToken = resolveAuthToken(authInput);
89
- // The client OWNS its credential lifecycle (not the React layer): this resolver
90
- // drives both the reactive re-mint (FSM `credential_stale`) and the proactive
91
- // refresh timer + wake/online/focus triggers. Null for the common static
92
- // `apiKey` path no refresh needed.
90
+ // The client owns its credential lifecycle (not the React layer): this resolver
91
+ // drives both the reactive re-mint (the connection's `credential_stale` state)
92
+ // and the proactive refresh timer with its wake/online/focus triggers. Null for
93
+ // the common static `apiKey` path, which needs no refresh.
93
94
  const credentialResolver = resolveCredentialResolver(configuredApiKey);
94
95
  const authCredentials = createAuthCredentialSource(
95
96
  // eslint-disable-next-line @typescript-eslint/no-deprecated -- load-bearing on the self-hosted path; server-internal cap-mint (Phase 3) not shipped
@@ -118,24 +119,19 @@ export function Ablo(options) {
118
119
  ...deriveConfigFromSchema(schema),
119
120
  ...internalOptions.configOverrides,
120
121
  };
121
- // 2. Create the mutation executor + dispatcher.
122
+ // 2. Create the mutation executor and dispatcher.
122
123
  //
123
- // The default executor sends `{ type: 'commit', ... }` over the
124
- // engine's WebSocket. The WS doesn't exist yet at this point (it's
125
- // created later when `BaseSyncedStore` initializes), so the default
126
- // takes a lazy getter that resolves the live WS at commit time.
127
- // `storeForTransport` is captured by the closure and assigned below
128
- // once the store is built JS closures close over bindings, not
129
- // values, so by the time the first commit fires the store is live.
124
+ // The default executor sends `{ type: 'commit', ... }` over the engine's
125
+ // WebSocket. The socket doesn't exist yet at this point (it's created later
126
+ // when the store initializes), so the default takes a lazy getter that
127
+ // resolves the live socket at commit time. `storeHolder` is captured by the
128
+ // closure and assigned below once the store is built — JS closures close
129
+ // over bindings, not values, so by the time the first commit fires the store
130
+ // is live.
130
131
  //
131
- // Caller-supplied executors are still honored for advanced cases
132
- // (test mocks, alternative transports) but the public `<AbloProvider>`
133
- // surface will mark this option `@internal` — apps should almost
134
- // never need to override transport. See Zero's `ClientOptions`
135
- // (packages/zero-client/src/client/options.ts) and Liveblocks'
136
- // `ClientOptions` (packages/liveblocks-core/src/client.ts) for the
137
- // reference shape: URLs + auth + declarative mutators, never a
138
- // pluggable commit transport.
132
+ // Caller-supplied executors are still honored for advanced cases (test
133
+ // mocks, alternative transports), but apps should almost never need to
134
+ // override the transport.
139
135
  // Captured-by-reference binding — assigned below after BaseSyncedStore
140
136
  // is constructed. The default executor's `getWs` closure reads it
141
137
  // lazily at commit time.
@@ -195,18 +191,16 @@ export function Ablo(options) {
195
191
  });
196
192
  // Hand the credential lifecycle to the client (refresher + proactive refresh
197
193
  // timer + wake/online/focus re-mint). Installed once here so refresh works for
198
- // ANY consumer of `Ablo({ auth })` not only those who render `<AbloProvider>`.
194
+ // any consumer of `Ablo({ auth })`, not only those who render `<AbloProvider>`.
199
195
  // The first mint happens in `ready()` so the first connection carries a token.
200
196
  //
201
- // Long-lived server clients also get the pre-roll TIMER on windowless hosts
202
- // (`proactiveInNode`): their socket must renew its `rk_`/`ek_` BEFORE the
203
- // hub's keepalive reaper closes it (4001 `credential_expired`). Two signals
204
- // qualify — agent/system participants (the axis `createConnectionManager`
205
- // gates on; `kind` is deprecated but still what agent runtimes pass today),
206
- // and an ABSOLUTE endpoint-string `apiKey` (a relative one can't fetch in
207
- // Node at all, so an absolute URL is unambiguously a deliberate server
208
- // client, kind or no kind). User-kind clients in Node (an SSR/RSC module
209
- // eval of scaffolded browser code) stay reactive-only.
197
+ // Long-lived server clients also get the pre-roll timer on windowless hosts
198
+ // (`proactiveInNode`): their socket must renew its `rk_` or `ek_` before the
199
+ // server's keepalive reaper closes it (4001 `credential_expired`). Two signals
200
+ // qualify — an agent or system participant, and an absolute endpoint-string
201
+ // `apiKey` (a relative one can't be fetched in Node, so an absolute URL is
202
+ // unambiguously a deliberate server client). User-kind clients in Node (an
203
+ // SSR/RSC module evaluating scaffolded browser code) stay reactive-only.
210
204
  if (credentialResolver) {
211
205
  const rawEndpoint = internalOptions.authEndpoint ?? internalOptions.apiKey;
212
206
  const absoluteEndpoint = typeof rawEndpoint === 'string' && /^https?:\/\//i.test(rawEndpoint);
@@ -218,27 +212,25 @@ export function Ablo(options) {
218
212
  /* eslint-enable @typescript-eslint/no-deprecated */
219
213
  });
220
214
  }
221
- // Put the lazy-query lane on the SAME auth-recovery backbone as the WS probe
215
+ // Put the lazy-query lane on the same auth-recovery path as the WebSocket probe
222
216
  // and the proactive pre-roll: a 401 on `/sync/query` re-mints via the store's
223
- // single-flight lifecycle and replays once, instead of silently returning
224
- // empty rows against an expired `ek_` until the next proactive tick (the
225
- // "Could not load documents apikey_expired" wedge). Late-bound because the
226
- // coordinator is constructed before the store exists.
217
+ // single-flight lifecycle and replays once, instead of silently returning empty
218
+ // rows against an expired `ek_` until the next proactive tick. Late-bound
219
+ // because the coordinator is constructed before the store exists.
227
220
  hydration.setCredentialRecovery((recovery) => store.recoverFromAuthRejection(recovery));
228
221
  // Wire the store back into the default executor's lazy getter (see
229
222
  // `storeHolder` above). The executor was constructed before the store
230
223
  // existed; this late binding closes the loop so commits dispatch over
231
224
  // the engine's WebSocket once it opens.
232
225
  storeHolder.store = store;
233
- // Bind THIS executor to THIS Ablo's TransactionQueue. Without this,
234
- // the queue resolves `mutationExecutor` from the module-level
235
- // `getContext()`, which `initSyncEngine()` overwrites on every Ablo
236
- // construction. In multi-Ablo flows (e.g. agent-worker's worker +
237
- // per-job peer) the second `initSyncEngine()` call would silently
238
- // redirect the first Ablo's queue through the second Ablo's executor
239
- // closure and when the second Ablo disposes, its `storeHolder.store`
240
- // becomes null, so the first Ablo's commits start throwing
241
- // `ws_not_ready` forever (terminal AgentJob writes hang on retry).
226
+ // Bind this executor to this client's TransactionQueue. Without it, the queue
227
+ // resolves `mutationExecutor` from the module-level `getContext()`, which
228
+ // `initSyncEngine()` overwrites on every client construction. In multi-client
229
+ // flows (for example a worker plus a per-job peer) the second `initSyncEngine()`
230
+ // call would silently redirect the first client's queue through the second
231
+ // client's executor closure and when the second client disposes, its
232
+ // `storeHolder.store` becomes null, so the first client's commits start throwing
233
+ // `ws_not_ready` forever.
242
234
  syncClient.getTransactionQueue().setMutationExecutor(executor);
243
235
  // Presence + claim streams — built eagerly so `engine.presence`
244
236
  // and `engine.claims` return the same reference for the engine's
@@ -317,13 +309,13 @@ export function Ablo(options) {
317
309
  }
318
310
  _readyPromise = (async () => {
319
311
  try {
320
- // Mint the FIRST access credential before we connect, so the initial
321
- // WebSocket upgrade + bootstrap carry a valid bearer (no tokenless first
322
- // connect that has to self-heal). Only when a refreshing resolver is
323
- // wired AND no static credential is already present. Contract mirrors
324
- // the `apiKey` resolver: `null` the login is gone (terminal — fail ready so the
325
- // app shows sign-in); a THROW transient (rethrown; autoStart swallows
326
- // and the lifecycle's online/wake triggers retry).
312
+ // Mint the first access credential before we connect, so the initial
313
+ // WebSocket upgrade and bootstrap carry a valid bearer (no tokenless first
314
+ // connect that has to self-heal). Only when a refreshing resolver is wired
315
+ // and no static credential is already present. Follows the `apiKey`
316
+ // resolver contract: `null` means the login is gone (terminal — fail ready
317
+ // so the app shows sign-in); a throw means transient (rethrown; autoStart
318
+ // swallows it and the lifecycle's online/wake triggers retry).
327
319
  if (credentialResolver && !authCredentials.getAuthToken()) {
328
320
  const token = await credentialResolver();
329
321
  if (!token) {
@@ -331,7 +323,7 @@ export function Ablo(options) {
331
323
  }
332
324
  authCredentials.setAuthToken(token);
333
325
  }
334
- // Register the caller's own database for write-back BEFORE bootstrap, so
326
+ // Register the caller's own database for write-back before bootstrap, so
335
327
  // the server resolves this org's data plane to the customer's DB rather
336
328
  // than serving an empty/wrong store. The org is derived server-side from
337
329
  // the API key. Idempotent server-side (register-or-update). Skipped when
@@ -353,15 +345,15 @@ export function Ablo(options) {
353
345
  url,
354
346
  kind,
355
347
  configuredApiKey,
356
- // Resolve identity against the LIVE token, not the construction-time
357
- // `configuredAuthToken`. Consumers using a function `apiKey` (apps/web)
358
- // never pass `authToken` at construction — the lifecycle mints the
359
- // first `ek_`/`rk_` and calls `setAuthToken()` before
360
- // `ready()`, which updates the shared credential source. Reading the frozen
361
- // `configuredAuthToken` here made `/auth/identity` fire with no Bearer
362
- // (→ `no_matching_provider` / `session_expired`) even though the JWT
363
- // was present. Mirrors every other transport by reading the shared
364
- // credential source.
348
+ // Resolve identity against the live token, not the construction-time
349
+ // `configuredAuthToken`. Consumers using a function `apiKey` never pass
350
+ // `authToken` at construction — the lifecycle mints the first `ek_` or
351
+ // `rk_` and calls `setAuthToken()` before `ready()`, which updates the
352
+ // shared credential source. Reading the frozen `configuredAuthToken`
353
+ // here made `/auth/identity` fire with no bearer (returning
354
+ // `no_matching_provider` / `session_expired`) even though the token was
355
+ // present. This reads the shared credential source, like every other
356
+ // transport.
365
357
  configuredAuthToken: authCredentials.getAuthToken() ?? configuredAuthToken,
366
358
  bootstrapHelper,
367
359
  auth: authCredentials,
@@ -369,11 +361,11 @@ export function Ablo(options) {
369
361
  });
370
362
  const { userId, accountScope, teamIds, capabilityToken, syncGroups, participantKind, } = resolved;
371
363
  // Fail-loud guard: detect the degenerate "no real sync groups
372
- // resolved" state before opening the WS. Same class of bug as
373
- // the schema-drift `[commit] dropped stale field` warning —
364
+ // resolved" state before opening the socket. It is the same class of bug as
365
+ // a
374
366
  // sensible-looking default that's functionally broken: the
375
367
  // SDK ends up subscribing only to the server-side
376
- // `['default']` fallback (bootstrap.ts:45, Hub.ts:480), no
368
+ // `['default']` fallback, no
377
369
  // delta has that tag, live fan-out silently never delivers.
378
370
  // For human users (kind:'user') this is almost certainly a
379
371
  // misconfiguration upstream — either the caller didn't pass
@@ -385,9 +377,9 @@ export function Ablo(options) {
385
377
  if (participantKind === 'user' &&
386
378
  (resolvedSyncGroups.length === 0 ||
387
379
  (resolvedSyncGroups.length === 1 && resolvedSyncGroups[0] === 'default'))) {
388
- // Actionable and NOT self-healing (no live updates until fixed):
389
- // kept at warn, consumer register engine jargon and the internal
390
- // file pointer stripped; forensic fields ride the debug companion.
380
+ // Actionable and not self-healing (no live updates until fixed):
381
+ // kept at warn level for consumers; the low-level diagnostic
382
+ // fields ride the debug log below.
391
383
  logger.warn('This client was started without sync groups, so it will not receive ' +
392
384
  'live updates. Pass `syncGroups` (for example ' +
393
385
  '`["org:<id>", "user:<id>"]`) or check that your auth provider supplies them.');
@@ -459,15 +451,15 @@ export function Ablo(options) {
459
451
  httpStatus: error.httpStatus,
460
452
  error: error.message,
461
453
  });
462
- // Clear the memo so a FUTURE `ready()` re-attempts bootstrap instead of
463
- // replaying this rejection forever. Bootstrap failures here are
464
- // transient by nature — offline, an IndexedDB open timeout, a bootstrap
465
- // fetch hiccup — and used to brick the engine until a full page reload
466
- // because line ~2013 (`if (_readyPromise) return _readyPromise`) handed
467
- // every later caller this same dead promise. Nulling it lets the
468
- // provider's online/wake/retry triggers drive a clean re-bootstrap.
469
- // (The terminal `_validationError` branch above intentionally stays
470
- // cached — config can't change without recreating the engine.)
454
+ // Clear the memo so a future `ready()` re-attempts bootstrap instead of
455
+ // replaying this rejection forever. Bootstrap failures here are transient
456
+ // by nature — offline, an IndexedDB open timeout, a bootstrap fetch
457
+ // hiccup — and the early `if (_readyPromise) return _readyPromise` guard
458
+ // would otherwise hand every later caller this same dead promise, bricking
459
+ // the engine until a full page reload. Nulling it lets the provider's
460
+ // online/wake/retry triggers drive a clean re-bootstrap. (The terminal
461
+ // `_validationError` branch above intentionally stays cached — config
462
+ // can't change without recreating the engine.)
471
463
  _readyPromise = null;
472
464
  throw error;
473
465
  }
@@ -574,27 +566,6 @@ export function Ablo(options) {
574
566
  },
575
567
  };
576
568
  }
577
- function modelClaimFromQueued(claim) {
578
- return {
579
- id: claim.id,
580
- actor: claim.heldBy ?? "",
581
- participantKind: claim.participantKind ?? "user",
582
- reason: claim.reason,
583
- ...(claim.description ? { description: claim.description } : {}),
584
- field: claim.target.field,
585
- status: 'queued',
586
- position: claim.position,
587
- expiresAt: claim.expiresAt ?? 0,
588
- target: {
589
- model: claim.target.type,
590
- id: claim.target.id,
591
- path: claim.target.path,
592
- range: claim.target.range,
593
- field: claim.target.field,
594
- meta: claim.target.meta,
595
- },
596
- };
597
- }
598
569
  function targetMatchesModel(target, claim) {
599
570
  if (target.model &&
600
571
  claim.target.type.toLowerCase() !== target.model.toLowerCase()) {
@@ -611,14 +582,6 @@ export function Ablo(options) {
611
582
  .filter((claim) => (target ? targetMatchesModel(target, claim) : true))
612
583
  .map(modelClaimFromActive);
613
584
  }
614
- function listModelClaimQueue(target) {
615
- if (!target?.model || !target.id)
616
- return [];
617
- return publicClaims
618
- .queueFor({ type: target.model, id: target.id })
619
- .filter((claim) => (target.field ? claim.target.field === target.field : true))
620
- .map(modelClaimFromQueued);
621
- }
622
585
  function waitForModelUnclaimed(target, options) {
623
586
  if (listModelClaims(target).length === 0)
624
587
  return Promise.resolve();
@@ -690,6 +653,10 @@ export function Ablo(options) {
690
653
  waited,
691
654
  release,
692
655
  revoke: claim.revoke,
656
+ // The lease-control members are forwarded explicitly — this wrapper
657
+ // rebuilds the handle field by field, so anything not named here is
658
+ // silently dropped from the public claim.
659
+ heartbeat: claim.heartbeat,
693
660
  [Symbol.asyncDispose]: release,
694
661
  };
695
662
  }
@@ -752,7 +719,7 @@ export function Ablo(options) {
752
719
  createSnapshot: (modelKey, id) => createSnapshot({
753
720
  pool: objectPool,
754
721
  transport: store.getSyncWebSocket(),
755
- // `position.readFloor` is THE value claims/snapshots stamp as
722
+ // `position.readFloor` is the value claims and snapshots stamp as
756
723
  // `readAt` (max of the pool-applied cursor and the acked
757
724
  // watermark for our own writes — see sync/syncPosition.ts).
758
725
  // Stamping a bare stream cursor made a claim taken right after
@@ -798,19 +765,18 @@ export function Ablo(options) {
798
765
  selfParticipantKind: kind,
799
766
  // Read-interest / write-intent enrolment for the typed surface.
800
767
  // `enterScope`/`pinScope` resolve the `{ [schemaKey]: id }` scope
801
- // through the SAME resolver the claim path uses, landing this client in
768
+ // through the same resolver the claim path uses, landing this client in
802
769
  // the entity-scoped group the holder's claim presence fans out on.
803
- // Return the store promise so the claim write path can AWAIT pinScope
804
- // BEFORE acquiring the lease (closing the subscribe-vs-broadcast race);
770
+ // Returns the store promise so the claim write path can await pinScope
771
+ // before acquiring the lease (closing the subscribe-vs-broadcast race);
805
772
  // read-interest callers (`retrieve`/`claim.state`) still `void` it and
806
- // stay fire-and-forget. SOFT either way — the store swallows reconcile
807
- // errors so read interest never makes a read reject or stall.
773
+ // stay fire-and-forget. It's soft either way — the store swallows
774
+ // reconcile errors so read interest never makes a read reject or stall.
808
775
  enterScope: (scope) => store.enterScope(scope),
809
776
  pinScope: (scope) => store.pinScope(scope),
810
- // `ablo.<model>.watch(ids, { ttl })` a scoped participant join on
811
- // this model's sync group(s). The model-scoped relocation of the old
812
- // `ablo.participants.join({ scope: { <model>: ids } })`. WebSocket
813
- // only — `join` throws AbloConnectionError if the socket isn't ready.
777
+ // `ablo.<model>.watch(ids, { ttl })` performs a scoped participant join
778
+ // on this model's sync group(s). WebSocket only `join` throws
779
+ // `AbloConnectionError` if the socket isn't ready.
814
780
  createWatch: (modelKey, ids, options) => participantManager.join({
815
781
  scope: { [modelKey]: ids },
816
782
  ...(options?.ttl !== undefined ? { ttlSeconds: options.ttl } : {}),
@@ -960,7 +926,7 @@ export function Ablo(options) {
960
926
  const id = params.id ?? createModelId();
961
927
  await applyClaimedPolicy({ model: name, id }, params);
962
928
  // Confirm, then return the authoritative row (with framework defaults;
963
- // the EXISTING row on an idempotent re-create) — mirrors the WS client.
929
+ // the existing row on an idempotent re-create) — mirrors the WebSocket client.
964
930
  await commits.create({
965
931
  claimRef: params.claimRef,
966
932
  idempotencyKey: params.idempotencyKey,
@@ -1005,13 +971,13 @@ export function Ablo(options) {
1005
971
  };
1006
972
  }
1007
973
  /**
1008
- * The CONTROL-PLANE credential: always the original configured secret key.
974
+ * The control-plane credential: always the original configured secret key.
1009
975
  * Never reads `authCredentials` — that holds the exchanged sync credential
1010
976
  * (a wide-scope `rk_` on the hosted path), which control-plane routes
1011
977
  * rightly refuse (e.g. the user-session mint is sk_-gated). Counterpart to
1012
978
  * `getAuthToken()`, which resolves the sync-plane token.
1013
979
  *
1014
- * The sk_-only rule is enforced server-side; the credential KIND taxonomy
980
+ * The secret-key-only rule is enforced on the server; the credential-kind taxonomy
1015
981
  * (secret/restricted/ephemeral/publishable) lives in `auth/credentialPolicy`.
1016
982
  */
1017
983
  async function controlPlaneApiKey() {
@@ -1019,7 +985,7 @@ export function Ablo(options) {
1019
985
  }
1020
986
  /**
1021
987
  * Resolve the control-plane context a session/agent mint needs (sk_ +
1022
- * bootstrap base URL + the schema-key→typename map the Hub gates on).
988
+ * bootstrap base URL + the schema-key→typename map the server gates on).
1023
989
  * Shared by `sessions.create` and `agents.create` so the two mint doors
1024
990
  * can never drift on how a token is minted. Throws if no `sk_` is present —
1025
991
  * minting is a backend-only operation.
@@ -1036,7 +1002,7 @@ export function Ablo(options) {
1036
1002
  bootstrapBaseUrl: internalOptions.bootstrapBaseUrl,
1037
1003
  }),
1038
1004
  ...(internalOptions.fetch ? { fetch: internalOptions.fetch } : {}),
1039
- // Map every `can` schema-key to the wire typename the Hub gates on, so a
1005
+ // Map every `can` schema-key to the wire typename the server gates on, so a
1040
1006
  // typename override (`documents` → `Document`) doesn't mint a capability
1041
1007
  // the server then denies. See `MintSessionContext`.
1042
1008
  modelTypenames: Object.fromEntries(Object.entries(schema.models).map(([key, def]) => [
@@ -1064,9 +1030,9 @@ export function Ablo(options) {
1064
1030
  // The live short-lived bearer (set via `setAuthToken` / `apiKey`-resolver refresh)
1065
1031
  // is the canonical credential; fall back to a configured API key.
1066
1032
  //
1067
- // This is the SYNC-PLANE token (bootstrap, WS, query HTTP). Control-plane
1033
+ // This is the sync-plane token (bootstrap, WebSocket, query HTTP). Control-plane
1068
1034
  // calls (sessions.create, datasource registration) never use it — they
1069
- // present the ORIGINAL secret key via `controlPlaneApiKey()` below. The
1035
+ // present the original secret key via `controlPlaneApiKey()` below. The
1070
1036
  // split matters: after the startup exchange this resolver returns the
1071
1037
  // derived wide-scope `rk_`, a credential the control-plane routes
1072
1038
  // correctly refuse (an agent token must never mint humans).
@@ -1078,9 +1044,8 @@ export function Ablo(options) {
1078
1044
  setCredentialRefresher(refresher) {
1079
1045
  store.setCredentialRefresher(refresher);
1080
1046
  },
1081
- // The org this client resolved to — null until `ready()` completes.
1082
- // Integrators previously had no programmatic way to learn it (the Pulse
1083
- // agent regex-scraped `ablo status` output); now it's a property.
1047
+ // The org this client resolved to — null until `ready()` completes. Exposed
1048
+ // as a property so integrators can read it programmatically.
1084
1049
  get organizationId() {
1085
1050
  return _resolvedOrganizationId;
1086
1051
  },
@@ -1088,33 +1053,33 @@ export function Ablo(options) {
1088
1053
  store.nudgeReconnect();
1089
1054
  },
1090
1055
  sessions: {
1091
- // Stripe `ephemeralKeys.create` shape: a BACKEND (holding `sk_`) mints a
1092
- // short-lived scoped token for one end user OR one agent.
1056
+ // A backend (holding `sk_`) mints a short-lived scoped token for one end
1057
+ // user or one agent.
1093
1058
  //
1094
- // CONTROL-PLANE CREDENTIAL RULE: both arms authenticate with the
1095
- // ORIGINAL secret key (`controlPlaneApiKey()`), never the wide-scope
1096
- // `rk_` the startup exchange installed as the sync credential. A derived
1097
- // agent credential silently replacing the secret key on control-plane
1098
- // calls is how humans get minted as agents — attribution is the product.
1059
+ // Both arms authenticate with the original secret key
1060
+ // (`controlPlaneApiKey()`), never the wide-scope `rk_` the startup exchange
1061
+ // installed as the sync credential. A derived agent credential silently
1062
+ // replacing the secret key on control-plane calls is how humans would get
1063
+ // minted as agents — and correct attribution is the point.
1099
1064
  async create(params) {
1100
- // Both mint doors (`{ user }` → /auth/ephemeral-keys → `ek_`,
1065
+ // Both mint paths (`{ user }` → /auth/ephemeral-keys → `ek_`,
1101
1066
  // `{ agent, can }` → /auth/capability → scoped `rk_`) resolve their
1102
1067
  // control-plane context through the shared `buildMintContext`, so this
1103
- // client, `agents.create`, and the stateless HTTP client can never drift
1104
- // on how a token is minted.
1068
+ // client, `agents.create`, and the stateless HTTP client can't drift on
1069
+ // how a token is minted.
1105
1070
  return mintSession(params, await buildMintContext('sessions.create'));
1106
1071
  },
1107
1072
  },
1108
- // Mint a scoped agent IDENTITY and hand back a connected client bound to it
1109
- // `sessions.create({ agent })` + `Ablo({ apiKey })` fused into one call,
1110
- // for agents that run in THIS (sk_-holding) process. Omitting `id` yields a
1111
- // fresh uuid per call, so concurrent agents are distinct participants that
1112
- // queue behind each other (even when they share a `name`). Humans don't get
1113
- // a server-built client — ship them a token via `sessions.create({ user })`.
1073
+ // Mint a scoped agent identity and hand back a connected client bound to it
1074
+ // `sessions.create({ agent })` plus `Ablo({ apiKey })` fused into one call,
1075
+ // for agents that run in this (secret-key-holding) process. Omitting `id`
1076
+ // yields a fresh uuid per call, so concurrent agents are distinct participants
1077
+ // that queue behind each other (even when they share a `name`). Humans don't
1078
+ // get a server-built client — ship them a token via `sessions.create({ user })`.
1114
1079
  agents: {
1115
1080
  async create(params) {
1116
1081
  // Distinct participant by default: omit `id` → a fresh uuid, so even two
1117
- // agents that share a `name` are INDEPENDENT participants and queue
1082
+ // agents that share a `name` are independent participants and queue
1118
1083
  // behind one another. `name` is display only (→ userMeta.name); it never
1119
1084
  // derives the id. Pass an explicit `id` only to re-attach an agent to
1120
1085
  // its own held claims.
@@ -1128,7 +1093,7 @@ export function Ablo(options) {
1128
1093
  ...(userMeta ? { userMeta } : {}),
1129
1094
  };
1130
1095
  // Re-mint the `rk_` on every resolver call so a long-lived agent client
1131
- // never hits token expiry; the `sk_` stays in THIS process — the child
1096
+ // never hits token expiry; the `sk_` stays in this process — the child
1132
1097
  // only ever sees its own short-lived `rk_`.
1133
1098
  const mintToken = async () => (await mintSession(sessionParams, await buildMintContext('agents.create')))
1134
1099
  .token;
@@ -1175,7 +1140,7 @@ export function Ablo(options) {
1175
1140
  * the session (WebSocket close code 1008/4001/4003 or a session_error
1176
1141
  * frame). Multiple subscribers supported; returns an unsubscribe
1177
1142
  * function. Consumers typically use this to trigger auth-failed UI
1178
- * flows (e.g., redirect to sign-in). Does NOT automatically purge the
1143
+ * flows (e.g., redirect to sign-in). Does not automatically purge the
1179
1144
  * IndexedDB — call `engine.purge()` from the listener if you need
1180
1145
  * that behavior (the SDK's `<AbloProvider>` does this by default).
1181
1146
  */
@@ -1202,7 +1167,7 @@ export function Ablo(options) {
1202
1167
  // the pool). Prefixed with _ to signal "internal but stable."
1203
1168
  /** The BaseSyncedStore — implements SyncStoreContract for SyncContext.Provider. */
1204
1169
  get _store() { return store; },
1205
- /** The ObjectPool — for demand loaders that need pool.createFromData(). */
1170
+ /** The InstanceCache — for demand loaders that need pool.createFromData(). */
1206
1171
  get _pool() { return objectPool; },
1207
1172
  /** The SyncWebSocket — for collaboration events (slide selection, cursors). */
1208
1173
  get _ws() { return store.getSyncWebSocket() ?? null; },
@@ -1,23 +1,22 @@
1
1
  /**
2
- * Stateless API client for `Ablo({ apiKey })`.
3
- *
4
- * This is the hosted-API product surface: no schema, no object pool, no
5
- * IndexedDB, no WebSocket. It maps the public Model / Claim / Commit
6
- * nouns directly to HTTP routes on sync-server.
2
+ * The stateless API client behind `Ablo({ apiKey })`. It carries no schema,
3
+ * object pool, local database, or WebSocket, and maps the public Model, Claim,
4
+ * and Commit nouns directly to HTTP routes on the server. This is the transport
5
+ * used for server-side agents, workers, and serverless code.
7
6
  */
8
7
  import type { AbloOptions } from './options.js';
9
8
  import type { CommitResource, ClaimCreateOptions, ClaimWaitOptions, ModelClient, ModelClaim, ModelTarget, CreateSessionParams, AbloSession } from './resourceTypes.js';
10
9
  import type { SchemaRecord } from '../schema/schema.js';
11
10
  import type { Duration } from '../utils/duration.js';
12
- import type { Claim } from '../types/streams.js';
11
+ import type { Claim, ClaimHeartbeat } from '../types/streams.js';
13
12
  import type { SyncObservabilityProvider } from '../interfaces/index.js';
14
13
  export type AbloApiClientOptions = Omit<AbloOptions, 'schema'> & {
15
14
  readonly schema?: null | undefined;
16
15
  readonly bootstrapBaseUrl?: string | undefined;
17
16
  /**
18
- * Observability provider forwarded from `Ablo({ observability })`. The HTTP
19
- * transport emits the same claim/conflict seams as the WS transport so a
20
- * `ClaimLog` works identically for headless (server-agent) evals.
17
+ * The observability provider forwarded from `Ablo({ observability })`. The HTTP
18
+ * transport emits the same claim and conflict events as the WebSocket transport,
19
+ * so a `ClaimLog` works identically for headless server-agent evaluations.
21
20
  */
22
21
  readonly observability?: SyncObservabilityProvider;
23
22
  /**
@@ -37,6 +36,18 @@ export interface AbloApiClaims {
37
36
  create(options: ClaimCreateOptions): Promise<Claim>;
38
37
  list(target?: Partial<ModelTarget>): Promise<readonly ModelClaim[]>;
39
38
  waitFor(target: Partial<ModelTarget>, options?: ClaimWaitOptions): Promise<void>;
39
+ /**
40
+ * The batched beat — extend every lease this credential holds in one
41
+ * request (`POST /v1/claims/heartbeat`), the stateless twin of the
42
+ * WebSocket keepalive. One round trip per cadence for a worker holding
43
+ * many rows. Returns one {@link ClaimHeartbeat} per extended lease,
44
+ * tagged with its claim id — no separate result type to learn.
45
+ */
46
+ heartbeatAll(options?: {
47
+ ttl?: Duration;
48
+ }): Promise<readonly (ClaimHeartbeat & {
49
+ readonly claimId: string;
50
+ })[]>;
40
51
  }
41
52
  export type CapabilityParticipantKind = 'agent' | 'system';
42
53
  export interface CapabilityCreateBaseOptions {
@@ -97,14 +108,14 @@ export interface CapabilityRevocation {
97
108
  }
98
109
  export interface CapabilityRotateOptions {
99
110
  /**
100
- * Overlap window — the OLD token keeps authenticating for this long after
101
- * rotation, so you can deploy the replacement with zero downtime. Default
102
- * 24h server-side.
111
+ * The overlap window — the old token keeps authenticating for this long after
112
+ * rotation, so you can deploy the replacement with zero downtime. Defaults to
113
+ * 24h on the server.
103
114
  */
104
115
  readonly grace?: Duration;
105
116
  readonly graceSeconds?: number;
106
117
  /**
107
- * Lifetime of the REPLACEMENT capability. Omit to inherit the original's
118
+ * The lifetime of the replacement capability. Omit to inherit the original's
108
119
  * lifetime.
109
120
  */
110
121
  readonly lease?: Duration;
@@ -126,9 +137,9 @@ export interface CapabilityResource {
126
137
  retrieve(id: string): Promise<CapabilityRecord>;
127
138
  revoke(id: string): Promise<CapabilityRevocation>;
128
139
  /**
129
- * Rotate with overlap (Stripe's "roll" model): mint a fresh capability
130
- * carrying the SAME scope, and keep the old token working for a grace
131
- * window so you can roll out the replacement without downtime.
140
+ * Rotate with overlap: mint a fresh capability that carries the same scope, and
141
+ * keep the old token working for a grace window so you can roll out the
142
+ * replacement without downtime.
132
143
  */
133
144
  rotate(id: string, options?: CapabilityRotateOptions): Promise<RotatedCapability>;
134
145
  /**
@@ -155,9 +166,9 @@ export interface AbloApi {
155
166
  */
156
167
  getAuthToken(): Promise<string | null>;
157
168
  /**
158
- * Mint a short-lived scoped session the Stripe `ephemeralKeys.create` shape.
159
- * Minting is a control-plane HTTP call (no socket), so it lives on this stateless
160
- * client too, not only the realtime one. `{ user }` `ek_`, `{ agent, can }` `rk_`.
169
+ * Mint a short-lived scoped session. Minting is a control-plane HTTP call (no
170
+ * socket), so it lives on this stateless client too, not only the realtime one.
171
+ * `{ user }` mints an `ek_`; `{ agent, can }` mints an `rk_`.
161
172
  */
162
173
  readonly sessions: {
163
174
  create(params: CreateSessionParams<SchemaRecord>): Promise<AbloSession>;