@abloatai/ablo 0.34.1 → 0.36.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 (536) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +758 -5
  3. package/README.md +56 -502
  4. package/bin/ablo.cjs +39 -0
  5. package/dist/BaseSyncedStore.d.ts +176 -48
  6. package/dist/BaseSyncedStore.js +346 -214
  7. package/dist/Database.d.ts +17 -44
  8. package/dist/Database.js +96 -79
  9. package/dist/InstanceCache.d.ts +31 -6
  10. package/dist/InstanceCache.js +65 -30
  11. package/dist/LazyReferenceCollection.d.ts +3 -3
  12. package/dist/LazyReferenceCollection.js +4 -4
  13. package/dist/Model.d.ts +23 -13
  14. package/dist/Model.js +27 -17
  15. package/dist/ModelRegistry.d.ts +8 -4
  16. package/dist/ModelRegistry.js +20 -18
  17. package/dist/NetworkMonitor.d.ts +3 -1
  18. package/dist/NetworkMonitor.js +7 -5
  19. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  20. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  21. package/dist/SyncClient.d.ts +47 -47
  22. package/dist/SyncClient.js +215 -156
  23. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  24. package/dist/ai-sdk/coordinatedTool.js +1 -1
  25. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  26. package/dist/ai-sdk/coordinationContext.js +1 -1
  27. package/dist/ai-sdk/wrap.d.ts +3 -3
  28. package/dist/ai-sdk/wrap.js +2 -2
  29. package/dist/auth/index.d.ts +1 -156
  30. package/dist/auth/index.js +8 -301
  31. package/dist/client/Ablo.d.ts +42 -287
  32. package/dist/client/Ablo.js +129 -963
  33. package/dist/client/abloClient.d.ts +309 -0
  34. package/dist/client/abloClient.js +13 -0
  35. package/dist/client/clientPrelude.d.ts +52 -0
  36. package/dist/client/clientPrelude.js +60 -0
  37. package/dist/client/consoleLogger.d.ts +2 -2
  38. package/dist/client/coreClient.d.ts +60 -0
  39. package/dist/client/coreClient.js +118 -0
  40. package/dist/client/createInternalComponents.d.ts +8 -4
  41. package/dist/client/createInternalComponents.js +17 -10
  42. package/dist/client/createModelProxy.d.ts +98 -373
  43. package/dist/client/createModelProxy.js +233 -139
  44. package/dist/client/humans.d.ts +69 -0
  45. package/dist/client/humans.js +78 -0
  46. package/dist/client/modelRegistration.d.ts +1 -1
  47. package/dist/client/modelRegistration.js +9 -9
  48. package/dist/client/options.d.ts +73 -17
  49. package/dist/client/reactiveEngine.d.ts +53 -0
  50. package/dist/client/reactiveEngine.js +688 -0
  51. package/dist/client/resourceTypes.d.ts +9 -250
  52. package/dist/client/resourceTypes.js +8 -5
  53. package/dist/client/schemaConfig.d.ts +4 -4
  54. package/dist/client/schemaConfig.js +6 -2
  55. package/dist/client/storeCluster.d.ts +47 -0
  56. package/dist/client/storeCluster.js +118 -0
  57. package/dist/client/storeLifecycle.d.ts +61 -0
  58. package/dist/client/storeLifecycle.js +231 -0
  59. package/dist/client/validateAbloOptions.d.ts +3 -2
  60. package/dist/client/validateAbloOptions.js +1 -1
  61. package/dist/client/wsMutationExecutor.d.ts +3 -3
  62. package/dist/client/wsMutationExecutor.js +3 -3
  63. package/dist/context.d.ts +22 -9
  64. package/dist/context.js +33 -9
  65. package/dist/coordination/ClaimLog.d.ts +26 -0
  66. package/dist/coordination/ClaimLog.js +32 -0
  67. package/dist/coordination/index.d.ts +1 -15
  68. package/dist/coordination/index.js +8 -31
  69. package/dist/core/index.d.ts +3 -3
  70. package/dist/core/index.js +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +230 -0
  73. package/dist/docs/index.d.ts +10 -0
  74. package/dist/docs/index.js +10 -0
  75. package/dist/environment.d.ts +1 -40
  76. package/dist/environment.js +8 -37
  77. package/dist/index.d.ts +44 -36
  78. package/dist/index.js +30 -22
  79. package/dist/interfaces/index.d.ts +44 -134
  80. package/dist/keys/index.d.ts +1 -77
  81. package/dist/keys/index.js +8 -190
  82. package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
  83. package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
  84. package/dist/mutators/Transaction.d.ts +1 -1
  85. package/dist/mutators/Transaction.js +1 -1
  86. package/dist/mutators/UndoManager.d.ts +6 -6
  87. package/dist/mutators/UndoManager.js +5 -5
  88. package/dist/mutators/defineMutators.d.ts +3 -3
  89. package/dist/mutators/defineMutators.js +1 -1
  90. package/dist/mutators/inverseOp.js +2 -2
  91. package/dist/mutators/mutateActions.d.ts +3 -3
  92. package/dist/mutators/mutateActions.js +1 -1
  93. package/dist/mutators/readerActions.d.ts +1 -1
  94. package/dist/mutators/undoApply.d.ts +1 -1
  95. package/dist/mutators/undoApply.js +1 -1
  96. package/dist/policy/index.d.ts +2 -2
  97. package/dist/policy/index.js +1 -1
  98. package/dist/query/client.d.ts +5 -2
  99. package/dist/query/client.js +10 -9
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +18 -8
  103. package/dist/react/AbloProvider.js +10 -9
  104. package/dist/react/context.d.ts +3 -3
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/createAbloReact.d.ts +56 -0
  107. package/dist/react/createAbloReact.js +51 -0
  108. package/dist/react/index.d.ts +6 -5
  109. package/dist/react/index.js +6 -3
  110. package/dist/react/internalContext.d.ts +1 -1
  111. package/dist/react/useAblo.d.ts +12 -5
  112. package/dist/react/useAblo.js +26 -8
  113. package/dist/react/useCurrentUserId.js +1 -1
  114. package/dist/react/useErrorListener.js +1 -1
  115. package/dist/react/useMutationFailureListener.d.ts +2 -2
  116. package/dist/react/useMutationFailureListener.js +1 -1
  117. package/dist/react/useMutators.d.ts +3 -3
  118. package/dist/react/useMutators.js +3 -3
  119. package/dist/react/useUndoScope.d.ts +5 -5
  120. package/dist/react/useUndoScope.js +1 -1
  121. package/dist/schema/coordination.d.ts +69 -10
  122. package/dist/schema/coordination.js +90 -9
  123. package/dist/schema/ddl.js +2 -2
  124. package/dist/schema/diff.d.ts +1 -1
  125. package/dist/schema/generate.js +1 -1
  126. package/dist/schema/index.d.ts +11 -10
  127. package/dist/schema/index.js +22 -18
  128. package/dist/schema/queries.d.ts +27 -27
  129. package/dist/schema/queries.js +23 -23
  130. package/dist/schema/select.d.ts +3 -3
  131. package/dist/schema/select.js +6 -3
  132. package/dist/schema/serialize.d.ts +15 -6
  133. package/dist/schema/serialize.js +20 -3
  134. package/dist/schema/sugar.d.ts +6 -7
  135. package/dist/schema/sugar.js +9 -12
  136. package/dist/schema/syncDeltaRow.d.ts +4 -152
  137. package/dist/schema/syncDeltaRow.js +4 -105
  138. package/dist/server/adapter.d.ts +18 -1
  139. package/dist/server/commit.d.ts +10 -16
  140. package/dist/server/index.d.ts +1 -1
  141. package/dist/server/index.js +1 -1
  142. package/dist/server/readConfig.d.ts +1 -1
  143. package/dist/source/adapter.d.ts +7 -5
  144. package/dist/source/adapter.js +7 -5
  145. package/dist/source/adapters/drizzle.d.ts +1 -1
  146. package/dist/source/adapters/drizzle.js +2 -2
  147. package/dist/source/adapters/kysely.d.ts +1 -1
  148. package/dist/source/adapters/kysely.js +1 -1
  149. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  150. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  151. package/dist/source/adapters/memory.js +1 -1
  152. package/dist/source/adapters/prisma.d.ts +8 -3
  153. package/dist/source/adapters/prisma.js +1 -1
  154. package/dist/source/connector.js +1 -1
  155. package/dist/source/connectorProtocol.d.ts +2 -8
  156. package/dist/source/connectorProtocol.js +3 -2
  157. package/dist/source/contract.d.ts +29 -17
  158. package/dist/source/contract.js +27 -22
  159. package/dist/source/factory.d.ts +1 -1
  160. package/dist/source/idempotency.js +2 -2
  161. package/dist/source/index.d.ts +1 -0
  162. package/dist/source/index.js +3 -0
  163. package/dist/source/next.d.ts +1 -1
  164. package/dist/source/signing.d.ts +9 -2
  165. package/dist/source/signing.js +4 -1
  166. package/dist/source/types.d.ts +6 -4
  167. package/dist/source/types.js +1 -1
  168. package/dist/{core/storeContract.d.ts → storeContract.d.ts} +6 -6
  169. package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
  170. package/dist/{core → stores}/DatabaseManager.js +14 -13
  171. package/dist/stores/ObjectStore.d.ts +1 -1
  172. package/dist/{core → stores}/StoreManager.d.ts +9 -26
  173. package/dist/{core → stores}/StoreManager.js +29 -77
  174. package/dist/stores/SyncActionStore.d.ts +4 -2
  175. package/dist/stores/SyncActionStore.js +11 -17
  176. package/dist/stores/syncAction.d.ts +26 -0
  177. package/dist/stores/syncAction.js +16 -0
  178. package/dist/surface.d.ts +3 -3
  179. package/dist/surface.js +6 -4
  180. package/dist/sync/BootstrapFetcher.d.ts +127 -6
  181. package/dist/sync/BootstrapFetcher.js +511 -83
  182. package/dist/sync/ConnectionManager.d.ts +6 -198
  183. package/dist/sync/ConnectionManager.js +6 -677
  184. package/dist/sync/OnDemandLoader.d.ts +5 -2
  185. package/dist/sync/OnDemandLoader.js +61 -21
  186. package/dist/sync/SubscriptionManager.d.ts +13 -2
  187. package/dist/sync/SubscriptionManager.js +23 -5
  188. package/dist/sync/SyncWebSocket.d.ts +27 -510
  189. package/dist/sync/SyncWebSocket.js +76 -954
  190. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  191. package/dist/sync/awaitClaimGrant.js +4 -109
  192. package/dist/sync/bootstrapApply.d.ts +3 -0
  193. package/dist/sync/bootstrapApply.js +2 -2
  194. package/dist/sync/commitFrames.d.ts +6 -40
  195. package/dist/sync/commitFrames.js +6 -97
  196. package/dist/sync/contextPorts.d.ts +18 -0
  197. package/dist/sync/contextPorts.js +31 -0
  198. package/dist/sync/createClaimStream.d.ts +5 -49
  199. package/dist/sync/createClaimStream.js +5 -469
  200. package/dist/sync/createPresenceStream.d.ts +26 -4
  201. package/dist/sync/createPresenceStream.js +28 -20
  202. package/dist/sync/createSnapshot.d.ts +2 -2
  203. package/dist/sync/createSnapshot.js +1 -1
  204. package/dist/sync/credentialLifecycle.d.ts +5 -173
  205. package/dist/sync/credentialLifecycle.js +5 -320
  206. package/dist/sync/deltaPipeline.d.ts +13 -12
  207. package/dist/sync/deltaPipeline.js +21 -4
  208. package/dist/sync/groupChange.d.ts +3 -0
  209. package/dist/sync/groupChange.js +16 -14
  210. package/dist/sync/participants.d.ts +24 -6
  211. package/dist/sync/participants.js +32 -23
  212. package/dist/sync/schemaDrift.d.ts +55 -0
  213. package/dist/sync/schemaDrift.js +53 -0
  214. package/dist/sync/schemas.d.ts +23 -33
  215. package/dist/sync/schemas.js +29 -20
  216. package/dist/sync/syncPlan.d.ts +3 -3
  217. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  218. package/dist/sync/wsFrameHandlers.js +6 -392
  219. package/dist/syncLog/contract.d.ts +20 -0
  220. package/dist/syncLog/contract.js +19 -0
  221. package/dist/syncLog/index.d.ts +1 -0
  222. package/dist/syncLog/index.js +1 -0
  223. package/dist/transaction/ablo.d.ts +88 -0
  224. package/dist/transaction/ablo.js +33 -0
  225. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  226. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  227. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  228. package/dist/transaction/auth/bootstrapScope.js +1 -0
  229. package/dist/transaction/auth/capability.d.ts +212 -0
  230. package/dist/transaction/auth/capability.js +224 -0
  231. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  232. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  233. package/dist/{client → transaction/auth}/identity.js +1 -1
  234. package/dist/transaction/auth/index.d.ts +162 -0
  235. package/dist/transaction/auth/index.js +304 -0
  236. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  237. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  238. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  239. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  240. package/dist/transaction/coordination/awaitClaimGrant.d.ts +56 -0
  241. package/dist/transaction/coordination/awaitClaimGrant.js +124 -0
  242. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +34 -0
  243. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +20 -0
  244. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  245. package/dist/transaction/coordination/claimMeta.js +52 -0
  246. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  247. package/dist/transaction/coordination/createClaimStream.js +475 -0
  248. package/dist/transaction/coordination/events.d.ts +74 -0
  249. package/dist/transaction/coordination/events.js +7 -0
  250. package/dist/transaction/coordination/index.d.ts +19 -0
  251. package/dist/transaction/coordination/index.js +45 -0
  252. package/dist/transaction/coordination/locator.d.ts +104 -0
  253. package/dist/transaction/coordination/locator.js +102 -0
  254. package/dist/transaction/coordination/schema.d.ts +1536 -0
  255. package/dist/transaction/coordination/schema.js +1177 -0
  256. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  257. package/dist/transaction/coordination/targetConflict.js +107 -0
  258. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  259. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  260. package/dist/transaction/durableWrites.d.ts +62 -0
  261. package/dist/{client → transaction}/durableWrites.js +28 -3
  262. package/dist/transaction/environment.d.ts +105 -0
  263. package/dist/transaction/environment.js +108 -0
  264. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +12 -12
  265. package/dist/{errorCodes.js → transaction/errorCodes.js} +45 -18
  266. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  267. package/dist/{errors.js → transaction/errors.js} +85 -16
  268. package/dist/transaction/footprint.d.ts +111 -0
  269. package/dist/transaction/footprint.js +0 -0
  270. package/dist/transaction/index.d.ts +20 -0
  271. package/dist/transaction/index.js +20 -0
  272. package/dist/transaction/keys/index.d.ts +87 -0
  273. package/dist/transaction/keys/index.js +207 -0
  274. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  275. package/dist/transaction/log/syncDeltaRow.js +95 -0
  276. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  277. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  278. package/dist/transaction/logger.d.ts +16 -0
  279. package/dist/transaction/logger.js +7 -0
  280. package/dist/transaction/observability.d.ts +53 -0
  281. package/dist/transaction/observability.js +19 -0
  282. package/dist/transaction/plugin.d.ts +285 -0
  283. package/dist/transaction/plugin.js +106 -0
  284. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  285. package/dist/{policy → transaction/policy}/types.js +2 -0
  286. package/dist/transaction/resources/httpResources.d.ts +321 -0
  287. package/dist/transaction/resources/httpResources.js +7 -0
  288. package/dist/transaction/resources/modelOperations.d.ts +427 -0
  289. package/dist/transaction/resources/modelOperations.js +12 -0
  290. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  291. package/dist/transaction/resources/mutationOptions.js +9 -0
  292. package/dist/transaction/resources/where.d.ts +101 -0
  293. package/dist/transaction/resources/where.js +115 -0
  294. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  295. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  296. package/dist/{schema → transaction/schema}/field.d.ts +17 -23
  297. package/dist/{schema → transaction/schema}/field.js +5 -5
  298. package/dist/transaction/schema/fieldRef.d.ts +38 -0
  299. package/dist/transaction/schema/fieldRef.js +11 -0
  300. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  301. package/dist/transaction/schema/loadStrategy.js +46 -0
  302. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  303. package/dist/{schema → transaction/schema}/model.js +30 -20
  304. package/dist/transaction/schema/openapi.d.ts +58 -0
  305. package/dist/transaction/schema/openapi.js +501 -0
  306. package/dist/{schema → transaction/schema}/relation.d.ts +21 -16
  307. package/dist/{schema → transaction/schema}/relation.js +7 -7
  308. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  309. package/dist/{schema → transaction/schema}/residency.js +0 -5
  310. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  311. package/dist/{schema → transaction/schema}/roles.js +5 -5
  312. package/dist/{schema → transaction/schema}/schema.d.ts +39 -10
  313. package/dist/{schema → transaction/schema}/schema.js +24 -3
  314. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  315. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  316. package/dist/transaction/transactionLayer.d.ts +82 -0
  317. package/dist/transaction/transactionLayer.js +24 -0
  318. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +5 -6
  319. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  320. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  321. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  322. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +11 -37
  323. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  324. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  325. package/dist/transaction/transport/commitFrames.js +134 -0
  326. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  327. package/dist/transaction/transport/connectionManager.js +673 -0
  328. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  329. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  330. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  331. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  332. package/dist/transaction/transport/httpClient.d.ts +131 -0
  333. package/dist/{client → transaction/transport}/httpClient.js +6 -5
  334. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  335. package/dist/transaction/transport/httpOptions.js +12 -0
  336. package/dist/{client → transaction/transport}/httpTransport.js +295 -97
  337. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  338. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  339. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  340. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  341. package/dist/transaction/transport/wsTransport.d.ts +574 -0
  342. package/dist/transaction/transport/wsTransport.js +1023 -0
  343. package/dist/transaction/types/assertExact.d.ts +17 -0
  344. package/dist/transaction/types/assertExact.js +1 -0
  345. package/dist/{types → transaction/types}/global.d.ts +17 -2
  346. package/dist/{types → transaction/types}/global.js +2 -1
  347. package/dist/{types → transaction/types}/index.d.ts +14 -46
  348. package/dist/{types → transaction/types}/index.js +7 -16
  349. package/dist/{types → transaction/types}/streams.d.ts +73 -45
  350. package/dist/transaction/utils/duration.d.ts +50 -0
  351. package/dist/{utils → transaction/utils}/duration.js +32 -0
  352. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  353. package/dist/transaction/utils/json.js +276 -0
  354. package/dist/transaction/wire/accountResponses.d.ts +420 -0
  355. package/dist/transaction/wire/accountResponses.js +290 -0
  356. package/dist/transaction/wire/auth.d.ts +56 -0
  357. package/dist/transaction/wire/auth.js +63 -0
  358. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  359. package/dist/transaction/wire/claimEvent.js +73 -0
  360. package/dist/transaction/wire/claims.d.ts +530 -0
  361. package/dist/transaction/wire/claims.js +327 -0
  362. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  363. package/dist/{wire → transaction/wire}/commit.js +68 -47
  364. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  365. package/dist/{wire → transaction/wire}/delta.js +37 -13
  366. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  367. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  368. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  369. package/dist/transaction/wire/feedCursor.js +82 -0
  370. package/dist/transaction/wire/feedEvent.d.ts +204 -0
  371. package/dist/transaction/wire/feedEvent.js +65 -0
  372. package/dist/transaction/wire/frames.d.ts +194 -0
  373. package/dist/transaction/wire/frames.js +50 -0
  374. package/dist/transaction/wire/inboundFrames.d.ts +562 -0
  375. package/dist/transaction/wire/inboundFrames.js +116 -0
  376. package/dist/transaction/wire/index.d.ts +54 -0
  377. package/dist/transaction/wire/index.js +83 -0
  378. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  379. package/dist/transaction/wire/listEnvelope.js +42 -0
  380. package/dist/transaction/wire/modelMutations.d.ts +31 -0
  381. package/dist/transaction/wire/modelMutations.js +52 -0
  382. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  383. package/dist/transaction/wire/modelResponses.js +43 -0
  384. package/dist/transaction/wire/modelShape.d.ts +78 -0
  385. package/dist/transaction/wire/modelShape.js +74 -0
  386. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +85 -38
  387. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +141 -80
  388. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  389. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  390. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  391. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  392. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  393. package/dist/transactions/mutations/commitLatency.js +130 -0
  394. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  395. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  396. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +18 -16
  397. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +15 -15
  398. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +15 -11
  399. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +14 -12
  400. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  401. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  402. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  403. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +4 -3
  404. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +7 -5
  405. package/dist/utils/mobxSetup.d.ts +1 -1
  406. package/dist/utils/mobxSetup.js +5 -2
  407. package/dist/{core → views}/QueryView.d.ts +2 -2
  408. package/dist/{core → views}/QueryView.js +2 -2
  409. package/dist/{core → views}/ViewRegistry.d.ts +1 -1
  410. package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
  411. package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
  412. package/dist/webhooks/events.d.ts +2 -2
  413. package/dist/wire/index.d.ts +1 -34
  414. package/dist/wire/index.js +8 -49
  415. package/docs/agent-messaging.md +3 -3
  416. package/docs/agents.md +20 -13
  417. package/docs/api-keys.md +14 -10
  418. package/docs/api.md +27 -61
  419. package/docs/audit.md +6 -3
  420. package/docs/cli.md +41 -13
  421. package/docs/client-behavior.md +11 -9
  422. package/docs/concurrency-convention.md +49 -57
  423. package/docs/coordination.md +283 -121
  424. package/docs/data-sources.md +7 -5
  425. package/docs/debugging.md +39 -15
  426. package/docs/deployment.md +267 -0
  427. package/docs/examples/agent-human.md +49 -42
  428. package/docs/examples/ai-sdk-tool.md +69 -44
  429. package/docs/examples/existing-python-backend.md +8 -6
  430. package/docs/examples/nextjs.md +129 -47
  431. package/docs/examples/scoped-agent.md +46 -45
  432. package/docs/examples/server-agent.md +46 -26
  433. package/docs/groups.md +87 -30
  434. package/docs/guarantees.md +41 -12
  435. package/docs/how-it-works.md +38 -12
  436. package/docs/idempotency.md +126 -0
  437. package/docs/identity.md +77 -74
  438. package/docs/index.md +172 -86
  439. package/docs/integration-guide.md +31 -19
  440. package/docs/mcp.md +46 -21
  441. package/docs/migration.md +95 -18
  442. package/docs/operating-on-your-database.md +3 -1
  443. package/docs/projects.md +3 -1
  444. package/docs/quickstart.md +22 -5
  445. package/docs/react.md +31 -18
  446. package/docs/schema-contract.md +5 -3
  447. package/docs/session-settings.md +108 -0
  448. package/docs/sessions.md +4 -2
  449. package/docs/webhooks.md +12 -10
  450. package/llms.txt +48 -18
  451. package/package.json +21 -26
  452. package/dist/agent/Agent.d.ts +0 -366
  453. package/dist/agent/Agent.js +0 -514
  454. package/dist/agent/index.d.ts +0 -115
  455. package/dist/agent/index.js +0 -128
  456. package/dist/agent/session.d.ts +0 -93
  457. package/dist/agent/session.js +0 -149
  458. package/dist/agent/types.d.ts +0 -68
  459. package/dist/agent/types.js +0 -9
  460. package/dist/cli.cjs +0 -286329
  461. package/dist/client/durableWrites.d.ts +0 -21
  462. package/dist/client/httpClient.d.ts +0 -80
  463. package/dist/coordination/schema.d.ts +0 -722
  464. package/dist/coordination/schema.js +0 -578
  465. package/dist/schema/openapi.d.ts +0 -29
  466. package/dist/schema/openapi.js +0 -124
  467. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  468. package/dist/testing/fixtures/bootstrap.js +0 -59
  469. package/dist/testing/fixtures/deltas.d.ts +0 -83
  470. package/dist/testing/fixtures/deltas.js +0 -136
  471. package/dist/testing/fixtures/models.d.ts +0 -83
  472. package/dist/testing/fixtures/models.js +0 -272
  473. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  474. package/dist/testing/helpers/reactWrapper.js +0 -67
  475. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  476. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  477. package/dist/testing/helpers/wait.d.ts +0 -30
  478. package/dist/testing/helpers/wait.js +0 -49
  479. package/dist/testing/index.d.ts +0 -23
  480. package/dist/testing/index.js +0 -33
  481. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  482. package/dist/testing/mocks/FakeDatabase.js +0 -10
  483. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  484. package/dist/testing/mocks/MockMutationExecutor.js +0 -192
  485. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  486. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  487. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  488. package/dist/testing/mocks/MockSyncContext.js +0 -71
  489. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  490. package/dist/testing/mocks/MockSyncStore.js +0 -171
  491. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  492. package/dist/testing/mocks/MockWebSocket.js +0 -118
  493. package/dist/transactions/durableWriteStore.js +0 -30
  494. package/dist/utils/duration.d.ts +0 -25
  495. package/dist/utils/json.js +0 -88
  496. package/dist/wire/errorEnvelope.d.ts +0 -55
  497. package/dist/wire/frames.d.ts +0 -197
  498. package/dist/wire/frames.js +0 -49
  499. package/dist/wire/listEnvelope.js +0 -18
  500. package/docs/interaction-model.md +0 -97
  501. /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
  502. /package/dist/{core → query}/QueryProcessor.js +0 -0
  503. /package/dist/{core/storeContract.js → storeContract.js} +0 -0
  504. /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
  505. /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
  506. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  507. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  508. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  509. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  510. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  511. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  512. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  513. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  514. /package/dist/{client → transaction}/persistence.js +0 -0
  515. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  516. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  517. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  518. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  519. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  520. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  521. /package/dist/{types → transaction/types}/modelData.js +0 -0
  522. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  523. /package/dist/{types → transaction/types}/participant.js +0 -0
  524. /package/dist/{types → transaction/types}/streams.js +0 -0
  525. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  526. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  527. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  528. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  529. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  530. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  531. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  532. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  533. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  534. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  535. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
  536. /package/dist/{core → views}/ViewRegistry.js +0 -0
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <strong>The coordination infrastructure for fleets of AI agents.</strong>
6
+ <strong>Collaboration infrastructure for AI agents.</strong>
7
7
  </p>
8
8
 
9
9
  <p align="center">
@@ -23,535 +23,89 @@
23
23
 
24
24
  ---
25
25
 
26
- Development stopped being the bottleneck; coordination is. The moment a *fleet*
27
- of agents not one, and not just people — edits the same rows, work gets lost:
28
- one agent clobbers another, or acts on data that already moved. Ablo is the
29
- infrastructure that lets the fleet work as one — the load-bearing coordination
30
- layer the way operational-transform and presence sit invisibly under a shared
31
- document. You build the agents; Ablo is the substrate that lets them run together
32
- on shared state without stepping on each other, with the people and server
33
- actions alongside them on the exact same path.
26
+ Every write to your data, whether it comes from a person, a server, or an agent,
27
+ arrives coordinated with the others and stays attributed afterward.
34
28
 
35
- The core idea is a **claim**. An agent's work is rarely one instant write; it
36
- reads something, thinks, calls an LLM or a tool, then writes back and in that
37
- gap the row can move under it. So before the slow work starts, the agent claims
38
- the row. If another agent is already on it, `claim` waits its turn in a fair
39
- line, re-reads the fresh row, then hands it over. No stale overwrite, no separate
40
- agent mutation path. People are exempt by policy: a human edit is never made to
41
- queue behind an agent, and by declared conflict rules always wins.
29
+ We work on the same things by looking and talking. You see someone's cursor in
30
+ the paragraph, so you wait, or you say you'll take the first half. None of that
31
+ is in the software. It's just what people do, and the software only has to show
32
+ them enough to do it.
42
33
 
43
- When the row moves anyway say a record an agent generated against gets bumped
44
- the moment before it commits the commit is rejected and the agent is handed
45
- back exactly the records that changed, so it re-reads only those, not the world.
46
- The pattern we kept measuring: with real agents contending on shared state, the
47
- win comes from the coordination layer, not a bigger model. Org beats intelligence.
48
-
49
- Under the hood, you define your data once with a Zod schema and get the same
50
- typed model client for every actor — people, server actions, and agents:
51
-
52
- ```ts
53
- await ablo.weatherReports.create({ data }) // create
54
- await ablo.weatherReports.retrieve({ id }) // read
55
- await ablo.weatherReports.update({ id, data }) // update
56
- await using claim = await ablo.weatherReports.claim({ id }) // hold for slow agent work
57
- ```
58
-
59
- The schema is the public contract. It gives you typed model methods, realtime
60
- fanout, React selectors, agent writes, and the HTTP/Data Source shape for
61
- non-JavaScript services. Every confirmed change shows up everywhere, and active
62
- claims are visible while the work is still in progress.
63
-
64
- **[Get started](#set-up)** &nbsp;·&nbsp; point your coding agent at the shipped
65
- `llms.txt` &nbsp;·&nbsp; **upgrading?** see the
66
- [Version History &amp; Migration Guide](./docs/migration.md)
67
-
68
- It works with the auth and database you already have. **In production, your
69
- database is the system of record.** Ablo is the sync + coordination layer on top
70
- of it: it consumes your Postgres' logical-replication stream, scopes realtime
71
- data to *sync groups* from your own identity, and your application keeps owning
72
- the write path — every row lives in your Postgres. (Trying Ablo with no database
73
- yet? A **sandbox** `sk_test` key holds throwaway **test data** — like Stripe test
74
- mode — so you can explore before pointing it at your Postgres. Test-mode only; in
75
- production every row lives in your database.)
76
-
77
- **Built for** fleets of agents working a shared backlog, AI agent workflows on
78
- your own infrastructure, collaborative editors where agents and people co-edit,
79
- and internal tools — anywhere agents (and the people alongside them) change
80
- shared state and everyone has to see it live.
81
-
82
- ## Set up
83
-
84
- The CLI takes you from nothing to a synced schema — it handles the account,
85
- the key, and the env file. You bring one thing: a Postgres you already have —
86
- the same `DATABASE_URL` (local, Neon, RDS — any will do) that backs your auth,
87
- audit, and log tables. Ablo syncs a *subset* of models against it; **in
88
- production, your database is the system of record**.
89
-
90
- ```bash
91
- npm install @abloatai/ablo
92
- npx ablo login # opens the browser: sign in (or sign up) → a sk_test_ key is saved locally
93
- npx ablo init # scaffolds ablo/schema.ts (offers to log in if you skipped it)
94
- npx ablo push # pushes your schema (sandbox), writes ABLO_API_KEY to .env.local, watches for changes
95
- ```
96
-
97
- Then point Ablo at the tables for your synced models. Most teams **already
98
- have those tables** (often Prisma- or Drizzle-managed) — adopt them with
99
- `npx ablo pull` / `npx ablo check`, the common case. Let Ablo own its own
100
- tables instead? `npx ablo migrate` provisions them in your Postgres (reads
101
- `DATABASE_URL`). Either way your other tables are left untouched.
102
-
103
- After `ablo push`, the [Quick Start](#quick-start) below runs as-is —
104
- `ABLO_API_KEY` is already in `.env.local` (frameworks load it automatically;
105
- plain Node: `node --env-file=.env.local app.ts`). `npx ablo status` shows
106
- what's configured at any time.
107
-
108
- **Keys & runtime.** Ablo needs Node 24+ and TypeScript 5+. Keys come in two of
109
- *your* environments — `sk_test_` and `sk_live_`, like Stripe — and `ablo login`
110
- mints both. Keep the key in trusted server runtimes only. In the browser,
111
- `<AbloProvider>` authenticates with the signed-in user's session — never the raw
112
- key. Your database is connected once, out of band, via `npx ablo connect`
113
- (logical replication); if it can't grant a replication role, expose a signed
114
- [Data Source endpoint](./docs/data-sources.md) instead.
115
-
116
- For production (React, an existing backend, Data Source, agents), the
117
- [Integration Guide](./docs/integration-guide.md) is the deeper map.
118
-
119
- **Prefer to let an agent wire it?** The package ships an `llms.txt` — a precise
120
- map of the API — so Claude Code or Cursor integrates from the real surface
121
- instead of guessing:
122
-
123
- > Read `node_modules/@abloatai/ablo/llms.txt`, then add an Ablo schema, a `<AbloProvider>`, and my first create / retrieve / update.
124
-
125
- ## Quick Start
126
-
127
- One schema, one client, one write path for humans and agents — this runs as-is
128
- after `ablo push`:
129
-
130
- ```ts
131
- import Ablo from '@abloatai/ablo';
132
- import { defineSchema, model, z } from '@abloatai/ablo/schema';
133
-
134
- const schema = defineSchema({
135
- // id, createdAt, updatedAt, organizationId, createdBy come free on every model
136
- weatherReports: model({
137
- location: z.string(),
138
- status: z.enum(['pending', 'ready']),
139
- forecast: z.string().optional(),
140
- }),
141
- });
142
-
143
- const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
144
- await ablo.ready();
145
-
146
- const created = await ablo.weatherReports.create({
147
- data: { location: 'Stockholm', status: 'pending' },
148
- });
149
-
150
- // Claim the row before slow work — anyone else waits in line, then re-reads.
151
- await using claim = await ablo.weatherReports.claim({ id: created.id });
152
- const forecast = await fetchForecast(claim.data.location); // slow: API or LLM call
153
- await ablo.weatherReports.update({
154
- id: created.id,
155
- data: { status: 'ready', forecast },
156
- claim, // the write completes the claimed work and releases the lease
157
- });
158
-
159
- const ready = ablo.weatherReports.get(created.id);
160
- console.log({ id: ready?.id, status: ready?.status });
161
-
162
- await ablo.dispose();
163
- ```
164
-
165
- Expected output:
166
-
167
- ```txt
168
- { id: '...', status: 'ready' }
169
- ```
170
-
171
- ### TypeScript setup (once, scaffolded for you)
172
-
173
- `npx ablo init` writes `ablo/register.ts` next to your schema. It binds your
174
- schema to the SDK's types once — the same declaration-merging shape
175
- [TanStack Router uses](https://tanstack.com/router/latest/docs/framework/react/guide/type-safety) —
176
- so every hook and client infers from it:
177
-
178
- ```ts
179
- // ablo/register.ts — scaffolded by `npx ablo init`
180
- import type { schema } from './schema';
181
- declare module '@abloatai/ablo' {
182
- interface Register { Schema: typeof schema }
183
- }
184
- export {};
185
- ```
186
-
187
- ```ts
188
- import type { Model } from '@abloatai/ablo/schema';
189
-
190
- type WeatherReport = Model<'weatherReports'>; // fully typed from your schema
191
- ```
192
-
193
- To pass the client around, take the type from the value — the tRPC /
194
- Drizzle idiom:
195
-
196
- ```ts
197
- export const sync = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
198
- export type Sync = typeof sync;
199
-
200
- function persist(client: Sync) { /* ... */ }
201
- ```
202
-
203
- ## Reading
204
-
205
- Two ways to read, depending on whether you can wait. `get(id)` / `getAll({ where })`
206
- / `getCount({ where })` are instant — they read what's already local and re-render
207
- on their own when it changes, so they're what your UI uses. `retrieve(id)` /
208
- `list({ where })` go ask the server and return a `Promise`, for when you need the
209
- authoritative answer right now.
34
+ Agents have neither. Two of them read the same row, think for thirty seconds,
35
+ and the second one writes over the first, and nobody finds out. The writes
36
+ aren't even the main part: an agent acts on what it read, so if any of it moved
37
+ while it was thinking, it does the wrong thing without colliding with anyone at
38
+ all. That probably doesn't get better as the models get better.
210
39
 
211
40
  ```ts
212
- ablo.weatherReports.get('report_stockholm');
41
+ // Two agents reprice the same order. One gets it at a time.
42
+ await using claim = await ablo.orders.claim({ id: orderId });
213
43
 
214
- const pending = ablo.weatherReports.getAll({
215
- where: { status: 'pending' },
216
- orderBy: { location: 'asc' },
217
- limit: 20,
218
- });
44
+ const order = claim.data; // the current row, not the one you read a minute ago
45
+ const priced = await pricingAgent(order); // slow: an LLM call, a vendor API
219
46
 
220
- const ready = await ablo.weatherReports.list({
221
- where: { status: 'ready' },
222
- type: 'complete',
47
+ await ablo.orders.update({
48
+ id: order.id,
49
+ data: { total: priced.total, discount: priced.discount, status: 'repriced' },
50
+ claim,
223
51
  });
224
52
  ```
225
53
 
226
- An array value in `where` means `IN`. On `list`, `type: 'complete'` waits for
227
- the server; `'unknown'` returns what's local now and refreshes in the background.
228
-
229
- ## Writing
54
+ The second agent waits its turn, then gets handed the order as it now stands. If
55
+ the pricing call throws, the row frees on the way out, unchanged. A person
56
+ editing that order in the UI is in the same line as the agents.
230
57
 
231
- `create` / `update` apply optimistically and resolve to the row. Two options
232
- matter day to day:
233
-
234
- | Option | Values | What it does |
235
- | --- | --- | --- |
236
- | `wait` | `'queued'` \| `'confirmed'` | `'confirmed'` resolves only after the server acks the write; `'queued'` resolves as soon as it's locally queued (fire-and-forget). |
237
- | `idempotencyKey` | `string` | Auto-generated per call. Override only when you own the retry boundary (e.g. a job id) so a re-run dedupes server-side. |
58
+ And the write it eventually makes is signed:
238
59
 
239
60
  ```ts
240
- await ablo.weatherReports.update({ id, data: { status: 'ready' }, wait: 'confirmed' });
241
- ```
242
-
243
- To guard a write against a row that changed under you, pass `readAt` + `onStale`
244
- — see [Coordinating long agent work](#coordinating-long-agent-work).
245
-
246
- ## Coordinating long agent work
247
-
248
- An agent reads a row, thinks for 30s, writes back — and clobbers whatever changed
249
- meanwhile, or worse, acts on stale state. `claim` holds the row across that gap:
250
-
251
- ```ts
252
- await using claim = await ablo.weatherReports.claim({ id: 'report_stockholm' });
253
- const report = claim.data;
254
- const forecast = await weatherAgent.getWeather(report.location);
255
- await ablo.weatherReports.update({
256
- id: report.id,
257
- data: { forecast, status: 'ready' },
258
- claim, // attribute the write to the held claim
259
- });
260
- ```
261
-
262
- If someone else holds the row, `claim()` waits in a fair queue, then re-reads —
263
- so `report` is the current row, never a stale snapshot. Reads stay open by
264
- default; only acting on the row serializes. The claim releases when the `await
265
- using` scope exits — on return, and on a throw. That "on throw" is why `await
266
- using` earns its keep: if the agent call fails before the write, the row frees
267
- for the next in line and stays exactly as it was, with no cleanup of your own.
268
-
269
- See who's mid-edit before you act — decide to wait, or skip:
270
-
271
- ```ts
272
- ablo.weatherReports.claim.state({ id: 'report_stockholm' });
273
- ablo.weatherReports.claim.queue({ id: 'report_stockholm' });
274
-
275
- {
276
- await using claim = await ablo.weatherReports.claim({ id, queue: false });
277
- /* do the held work */
278
- }
279
-
280
61
  {
281
- await using claim = await ablo.weatherReports.claim({ id, maxQueueDepth: 2 });
282
- /* do the held work */
283
- }
284
- ```
285
-
286
- `claim.state` returns the holder (or `null`); `claim.queue` returns the line waiting
287
- behind it. `queue: false` skips rather than waiting when the row is held;
288
- `maxQueueDepth: 2` bails when two or more are already ahead.
289
-
290
- Default reads keep working while a row is claimed. Server reads that need claimed
291
- semantics can opt in with `ifClaimed: 'return' | 'fail'`.
292
-
293
- Even an unclaimed write can't land on stale reasoning — the commit is guarded:
294
-
295
- ```ts
296
- try {
297
- await ablo.weatherReports.update({ id, data: { status: 'ready' }, readAt, onStale: 'reject' });
298
- } catch (e) {
299
- if (e instanceof AbloStaleContextError) { /* row moved under you — re-read, retry */ }
300
- }
301
- ```
302
-
303
- > Use `await using` for ordinary held work — the claim releases when the scope
304
- > exits. Call `claim.release({ id })` only to give a manually held claim back
305
- > early.
306
-
307
- See [Coordination](./docs/coordination.md) for the full `claim` / `claim.state` /
308
- `claim.queue` / `claim.release` reference.
309
-
310
- ## Background workers — jobs that run for minutes, not seconds
311
-
312
- Your API route enqueues a job on your own queue (SQS, EventBridge, anything);
313
- a worker on your own infrastructure does the slow part. **Keep that queue —
314
- Ablo is the worker's data layer.** It covers the two things every queue leaves
315
- to you: keeping the row safe, and showing progress live.
316
-
317
- Long work holds its claim by **heartbeating** — the same pattern as an SQS
318
- visibility heartbeat or a Temporal activity heartbeat:
319
-
320
- ```ts
321
- // on your worker — stateless HTTP, no socket to hold
322
- await using claim = await ablo.weatherReports.claim({
323
- id: msg.reportId,
324
- ttl: '10m',
325
- heartbeat: true, // beats automatically until release
326
- onHeartbeatLost: () => abort(), // the lease is gone → stop working
327
- });
328
-
329
- for (const step of steps) {
330
- await runStep(step);
331
- // write progress to the row — every subscribed UI updates live
332
- await ablo.weatherReports.update({ id: msg.reportId, data: { progress: step.pct }, claim });
62
+ actorKind: 'agent', // 'user' | 'agent' | 'system'
63
+ actorId: 'agent_pricing',
64
+ onBehalfOfKind: 'user',
65
+ onBehalfOfId: 'user_amir', // the person the agent acted for
66
+ capabilityId: 'key_live_ops',
67
+ confirmationState: 'approved', // ran on its own, was previewed, or was signed off
333
68
  }
334
69
  ```
335
70
 
336
- - A worker that **crashes** stops beating; the row frees within one beat and
337
- the next worker takes over.
338
- - A worker that **wakes up late** learns it on its next beat
339
- (`AbloClaimedError`), and the write path rejects its stale writes anyway.
340
- - **Retries stay on your queue** — the redelivered job claims the now-free
341
- row, reads its current state, and resumes.
342
- - A worker holding **many rows** extends them all in one call:
343
- `ablo.claims.heartbeatAll({ ttl: '5m' })`.
344
-
345
- SQS's heartbeat protects the *message* from redelivery; Ablo's protects the
346
- *row* from concurrent and stale writes. SQS is at-least-once, so two workers
347
- will eventually get the same job — the claim is what keeps that from
348
- corrupting data.
349
-
350
- ## React
351
-
352
- In a React app it's the **same `ablo.<model>` API** — just mounted through a
353
- provider and read with hooks, from `@abloatai/ablo/react`. Wrap your tree once;
354
- everything inside is live.
71
+ Every committed change lands in an audit log carrying that attribution, chained
72
+ with a keyed hash so any later alteration shows up. You write none of it.
355
73
 
356
- ```tsx
357
- import Ablo from '@abloatai/ablo';
358
- import { AbloProvider, useAblo } from '@abloatai/ablo/react';
359
- import { schema } from './ablo/schema';
74
+ - **Coordination.** Claims, a fair queue, and stale-write rejection, so slow agent work can't land on a moved row.
75
+ - **Realtime.** Every confirmed change reaches every connected client, agent or human, with no separate multiplayer mode to enable.
76
+ - **Your database and your auth stay yours.** Rows live in your Postgres under your own security policies; Ablo runs no migrations and owns no schema. Bring Clerk, Auth0, NextAuth, whatever you have.
77
+ - **A history you can answer questions from.** Who changed what, on whose behalf, with which key, and whether a human approved it.
360
78
 
361
- // Build the client once — authEndpoint is your session route; no key in the browser.
362
- const ablo = Ablo({
363
- schema,
364
- authEndpoint: '/api/ablo-session',
365
- });
366
-
367
- function App() {
368
- return (
369
- <AbloProvider client={ablo}>
370
- <Report id="report_stockholm" />
371
- </AbloProvider>
372
- );
373
- }
374
-
375
- function Report({ id }: { id: string }) {
376
- const report = useAblo((ablo) => ablo.weatherReports.get(id));
377
- const ablo = useAblo();
378
-
379
- if (!report) return null;
380
-
381
- return (
382
- <button onClick={() => ablo?.weatherReports.update({ id, data: { status: 'ready' } })}>
383
- {report.status}
384
- </button>
385
- );
386
- }
387
- ```
388
-
389
- The `useAblo(selector)` read re-renders whenever the row changes — whether you,
390
- a teammate, or an agent changed it. The write is the same optimistic, fan-out
391
- method as the server example above.
392
-
393
- `<AbloProvider>` owns the connection — no API key in the browser. That's the
394
- whole loop: read with `useAblo(selector)`, write with `ablo.<model>`, and every
395
- other client (human or agent) on that row sees it in real time. See
396
- [React](./docs/react.md) for the `<AbloProvider>` prop surface (`client`,
397
- `userId`, `fallback`, `onError`) — schema, scope, and team membership live on the
398
- `Ablo({ … })` client you pass it — plus status hooks.
399
-
400
- ## Identity & Sync Groups
401
-
402
- Ablo is **not** an auth provider — you keep your own (Clerk, Auth0, NextAuth,
403
- whatever). Ablo's job starts after you've authenticated a request: you tell it
404
- *who* is connecting, and it scopes their realtime data to the right **sync
405
- groups** (named channels like `org:acme` or `deck:abc123` that are both the unit
406
- of fan-out and the unit of access).
407
-
408
- The model is a proxy: your `ABLO_API_KEY` stays on your trusted server, your
409
- server resolves the signed-in user (org / team / user) from your own auth, and
410
- the browser connects as an already-scoped participant — it never holds the key
411
- and can't widen its own scope. Your schema's `identityRoles` map that identity
412
- to sync-group strings.
413
-
414
- `userId` / `teamIds` come from your auth, resolved server-side:
415
-
416
- ```tsx
417
- // team membership is asserted server-side when the session route mints the token.
418
- const ablo = Ablo({
419
- schema,
420
- authEndpoint: '/api/ablo-session',
421
- });
422
-
423
- <AbloProvider client={ablo} userId={user.id}>
424
- <App />
425
- </AbloProvider>
426
- ```
427
-
428
- If it isn't obvious where org / team / user come from in the Quick Start above,
429
- that's because they come from *your* app — see
430
- [Identity & Sync Groups](./docs/identity.md) for the full picture: what a sync
431
- group is, the two halves of scoping (`identityRoles` + per-model `orgScoped` /
432
- `syncGroupFormat`), and how identity reaches Ablo without an API key in the
433
- browser.
434
-
435
- ## Multiplayer
436
-
437
- There is no separate multiplayer mode. When human UI, server actions, and agent
438
- workers share the same schema and write through `ablo.<model>`, they all see
439
- each other's changes in real time — that's the default, not a feature you turn on.
440
-
441
- - `ablo.<model>.create/update/delete` fan out confirmed deltas to subscribers.
442
- - `useAblo(...)` gives React clients the live row, kept current automatically.
443
- - `ablo.<model>.claim({ id })` / `claim.state({ id })` / `claim.queue({ id })` let humans and agents coordinate (and observe) active work on a row — and the line waiting behind it — before a write lands.
444
-
445
- Writes go through Ablo. `ablo.<model>.create/update/delete` and the HTTP write
446
- endpoint enter Ablo's commit chokepoint — where claims, ordering, and idempotency
447
- are enforced — and Ablo lands the change in your database. It then tails the WAL to
448
- confirm the row landed and fans the confirmed change out to every connected client.
449
- One surface for humans, servers, and agents; one place coordination happens.
450
-
451
- ## HTTP Writes
452
-
453
- Use the SDK when you are in JavaScript and want typed models or realtime. Use the
454
- HTTP endpoint when a server-to-server caller needs to write without opening a
455
- WebSocket:
79
+ ## Start
456
80
 
457
81
  ```bash
458
- curl https://api.abloatai.com/api/v1/commits \
459
- -H "Authorization: Bearer sk_test_..." \
460
- -H "Content-Type: application/json" \
461
- -d '{ "operations": [
462
- { "action": "update", "model": "weatherReports", "id": "report_stockholm", "data": { "status": "ready" } }
463
- ] }'
464
- ```
465
-
466
- ```json
467
- { "object": "commit_receipt", "status": "confirmed", "serverTxId": "tx_…", "lastSyncId": 1042, "ops": 1 }
82
+ npm install @abloatai/ablo
83
+ npx ablo login # sign in; saves a test key
84
+ npx ablo init # scaffolds your schema
85
+ npx ablo push # writes ABLO_API_KEY to .env.local, and you're running
468
86
  ```
469
87
 
470
- ## Your Database
471
-
472
- In production, every schema model is backed by **your own database**, and that's
473
- where your rows live. You write through Ablo; it lands each change in your Postgres
474
- through a scoped role, then tails the WAL to confirm it and fan it out. Ablo holds
475
- the ordered transaction log and coordination — never your rows. Two ways it
476
- connects:
477
-
478
- | | How Ablo connects to your Postgres | Use when |
479
- | --- | --- | --- |
480
- | **`ablo connect`** (primary) | Sets up logical replication and a scoped writer role (`npx ablo connect apply` does it end to end). Ablo writes your rows through the writer role and reads them back over the WAL to confirm — it writes rows but runs no DDL and owns no schema. | Your database can grant a `REPLICATION` role (most can). |
481
- | **Signed endpoint** (fallback) | Your app exposes one route built from an ORM adapter (`prismaDataSource` / `drizzleDataSource`); Ablo writes and confirms through it. Needs no replication setup. | Your database **can't** grant a replication role (a locked-down managed DB). |
482
-
483
- Your database is the system of record. See
484
- [Connect Your Database](./docs/data-sources.md).
485
-
486
- ## Configuration
487
-
488
- `Ablo({ ... })` takes your schema and your key. Your database is connected
489
- **out of band** — once, via `npx ablo connect` (logical replication) or a signed
490
- [Data Source endpoint](./docs/data-sources.md) — not through the constructor.
491
- Every other option has correct defaults:
88
+ Point it at your own Postgres when you're ready with `npx ablo connect`.
492
89
 
493
- | Option | Type | Default | Purpose |
494
- | --- | --- | --- | --- |
495
- | `schema` | `Schema` | — (required) | Typed model proxies (`ablo.<model>.*`) |
496
- | `apiKey` | `string \| ApiKeySetter \| null` | `process.env.ABLO_API_KEY` | Server key — a string, or an async function for rotation |
90
+ ## Docs
497
91
 
498
- Keep `apiKey` in trusted server runtimes. In the browser, `<AbloProvider>`
499
- authenticates with the signed-in user's session; the raw-key path is gated
500
- behind `dangerouslyAllowBrowser` for server-proxy setups only. Advanced hooks
501
- (custom `fetch`, logging, observability, transport overrides) live in
502
- [Client Behavior](./docs/client-behavior.md).
503
-
504
- ## Errors
505
-
506
- Every SDK error extends `AbloError` and carries a `requestId` for support.
507
- Discriminate with `instanceof` or the `type` string — the string form also
508
- survives worker / `postMessage` boundaries, where `instanceof` does not:
509
-
510
- ```ts
511
- try {
512
- await ablo.weatherReports.update({ id, data: { status: 'ready' }, readAt, onStale: 'reject' });
513
- } catch (e) {
514
- if (e instanceof AbloStaleContextError) { /* row moved under you — re-read, retry */ }
515
- if ((e as AbloError).type === 'AbloClaimedError') { /* another participant holds it */ }
516
- }
92
+ ```bash
93
+ npx ablo docs # every page, for the version you installed
94
+ npx ablo docs audit # or any one of them
517
95
  ```
518
96
 
519
- | Error | When |
520
- | --- | --- |
521
- | `AbloAuthenticationError` | Invalid / missing / expired credentials |
522
- | `AbloPermissionError` / `CapabilityError` | Action forbidden by scope |
523
- | `AbloRateLimitError` | Rate limited (carries `retryAfterSeconds`) |
524
- | `AbloIdempotencyError` | Same `idempotencyKey` reused with a different body |
525
- | `AbloValidationError` | Invalid request payload |
526
- | `AbloStaleContextError` | Write carried `readAt`, but the row has newer changes (`conflicts`) |
527
- | `AbloClaimedError` | Target is claimed by another participant (`claims`) |
528
- | `AbloConnectionError` / `AbloServerError` | Transport failure / server 5xx |
529
- | `SyncSessionError` | Session expired (prompts re-auth) |
530
-
531
- ## Reconnect & retries
532
-
533
- The client owns reconnection so your code doesn't have to. A dropped WebSocket
534
- reconnects automatically with exponential backoff (1s → 30s, ±15% jitter, up to
535
- ~7.5 minutes); session errors (401/403) suppress it so you re-authenticate
536
- instead of looping. Commits are idempotent by client transaction id, and a
537
- commit that times out is never silently rolled back — the client reconciles
538
- against authoritative server state on reconnect. These defaults are the
539
- contract; there are no retry or timeout knobs to tune.
97
+ Those pages ship inside the package, so they match your install and need no
98
+ network. The same pages are at [docs.abloatai.com](https://docs.abloatai.com).
540
99
 
541
- ## Production Reference
100
+ Building with a coding agent? Point it at `node_modules/@abloatai/ablo/llms.txt`.
542
101
 
543
- - [Version History & Migration Guide](./docs/migration.md) — every breaking change, what to change, and which version introduced it. Read before bumping a minor.
544
- - [Identity & Sync Groups](./docs/identity.md) — use your own authentication; tell Ablo who's connecting and how org / team / user map to sync-group scope.
545
- - [Schema Contract](./docs/schema-contract.md) — one schema becomes typed model clients, React reads, agent writes, Data Source shape, and schema push.
546
- - [Guarantees](./docs/guarantees.md) — confirmed writes, stale-write protection, claim coordination, and agent lifecycle.
547
- - [Integration Guide](./docs/integration-guide.md) — integrate React, your database, multiplayer, and agents.
548
- - [React](./docs/react.md) — `<AbloProvider>`, `useAblo`, presence, status, and bootstrap gating.
549
- - [Coordination](./docs/coordination.md) — `claim` / `claim.state` / `claim.queue` / `claim.release` / `heartbeat` reference: hold a row across slow agent work — minutes or hours, via heartbeats — and observe the line waiting behind it.
550
- - [Client Behavior](./docs/client-behavior.md) — options, errors, retries, timeouts, and public imports.
551
- - [Connect Your Database](./docs/data-sources.md) — connect your Postgres by logical replication (`npx ablo connect`) or, as a fallback, a signed endpoint; your database is the system of record either way.
552
- - [Existing Python Backend](./docs/examples/existing-python-backend.md) — migrate existing Python endpoints to multiplayer and agent-safe writes gradually.
553
- - [AI SDK Tool](./docs/examples/ai-sdk-tool.md) — use Ablo inside an AI SDK tool call.
554
- - [Server Agent](./docs/examples/server-agent.md) — schema-backed worker.
102
+ Start with [Quickstart](./docs/quickstart.md) ·
103
+ [Integration Guide](./docs/integration-guide.md) ·
104
+ [Coordination](./docs/coordination.md) ·
105
+ [Audit log](./docs/audit.md) ·
106
+ [Connect your database](./docs/data-sources.md) ·
107
+ [Guarantees](./docs/guarantees.md) ·
108
+ [Migration](./docs/migration.md)
555
109
 
556
110
  ## License
557
111
 
package/bin/ablo.cjs ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ // `npx ablo` — the SDK's bin. The command itself lives in its own package so
3
+ // installing the SDK never downloads the CLI's tooling; this file only finds
4
+ // that package and hands over.
5
+ //
6
+ // Resolution order:
7
+ // 1. An installed CLI — the project's own, or one hoisted beside this SDK.
8
+ // Requiring it runs it: the CLI's entry executes on load and reads
9
+ // process.argv itself, which this shim leaves untouched.
10
+ // 2. `npm exec` — fetches the CLI on demand, so `npx ablo init` in a fresh
11
+ // project keeps working with nothing else installed.
12
+
13
+ 'use strict';
14
+
15
+ // The published name first; the workspace name resolves inside the monorepo.
16
+ const CLI_PACKAGES = ['@abloatai/cli', '@ablo/cli'];
17
+
18
+ for (const name of CLI_PACKAGES) {
19
+ let resolved;
20
+ try {
21
+ resolved = require.resolve(name);
22
+ } catch {
23
+ continue; // not installed under this name — try the next
24
+ }
25
+ require(resolved);
26
+ return;
27
+ }
28
+
29
+ const { spawnSync } = require('child_process');
30
+ const result = spawnSync(
31
+ process.platform === 'win32' ? 'npm.cmd' : 'npm',
32
+ ['exec', '--yes', '--package=@abloatai/cli', '--', 'ablo', ...process.argv.slice(2)],
33
+ { stdio: 'inherit', shell: process.platform === 'win32' },
34
+ );
35
+ if (result.error) {
36
+ console.error('Could not run the ablo CLI. Install it with: npm i -D @abloatai/cli');
37
+ process.exit(1);
38
+ }
39
+ process.exit(result.status ?? 1);