@abloatai/ablo 0.34.1 → 0.35.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 (483) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +674 -5
  3. package/README.md +39 -22
  4. package/dist/BaseSyncedStore.d.ts +152 -44
  5. package/dist/BaseSyncedStore.js +300 -184
  6. package/dist/Database.d.ts +9 -24
  7. package/dist/Database.js +37 -22
  8. package/dist/InstanceCache.d.ts +25 -4
  9. package/dist/InstanceCache.js +48 -15
  10. package/dist/LazyReferenceCollection.d.ts +3 -3
  11. package/dist/LazyReferenceCollection.js +4 -4
  12. package/dist/Model.d.ts +6 -6
  13. package/dist/Model.js +10 -10
  14. package/dist/ModelRegistry.d.ts +4 -4
  15. package/dist/ModelRegistry.js +3 -3
  16. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  17. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  18. package/dist/SyncClient.d.ts +42 -32
  19. package/dist/SyncClient.js +166 -110
  20. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  21. package/dist/ai-sdk/coordinatedTool.js +1 -1
  22. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  23. package/dist/ai-sdk/coordinationContext.js +1 -1
  24. package/dist/ai-sdk/wrap.d.ts +3 -3
  25. package/dist/ai-sdk/wrap.js +2 -2
  26. package/dist/auth/index.d.ts +1 -156
  27. package/dist/auth/index.js +8 -301
  28. package/dist/cli.cjs +3344 -1073
  29. package/dist/client/Ablo.d.ts +42 -287
  30. package/dist/client/Ablo.js +118 -963
  31. package/dist/client/abloClient.d.ts +309 -0
  32. package/dist/client/abloClient.js +13 -0
  33. package/dist/client/clientPrelude.d.ts +52 -0
  34. package/dist/client/clientPrelude.js +60 -0
  35. package/dist/client/consoleLogger.d.ts +2 -2
  36. package/dist/client/coreClient.d.ts +60 -0
  37. package/dist/client/coreClient.js +118 -0
  38. package/dist/client/createInternalComponents.d.ts +4 -4
  39. package/dist/client/createInternalComponents.js +9 -8
  40. package/dist/client/createModelProxy.d.ts +78 -373
  41. package/dist/client/createModelProxy.js +114 -86
  42. package/dist/client/humans.d.ts +48 -0
  43. package/dist/client/humans.js +52 -0
  44. package/dist/client/modelRegistration.d.ts +1 -1
  45. package/dist/client/modelRegistration.js +9 -9
  46. package/dist/client/options.d.ts +73 -17
  47. package/dist/client/reactiveEngine.d.ts +48 -0
  48. package/dist/client/reactiveEngine.js +910 -0
  49. package/dist/client/resourceTypes.d.ts +9 -250
  50. package/dist/client/resourceTypes.js +8 -5
  51. package/dist/client/schemaConfig.d.ts +4 -4
  52. package/dist/client/schemaConfig.js +6 -2
  53. package/dist/client/validateAbloOptions.d.ts +3 -2
  54. package/dist/client/validateAbloOptions.js +1 -1
  55. package/dist/client/wsMutationExecutor.d.ts +3 -3
  56. package/dist/client/wsMutationExecutor.js +3 -3
  57. package/dist/context.d.ts +9 -9
  58. package/dist/context.js +10 -9
  59. package/dist/coordination/ClaimLog.d.ts +26 -0
  60. package/dist/coordination/ClaimLog.js +32 -0
  61. package/dist/coordination/index.d.ts +1 -15
  62. package/dist/coordination/index.js +8 -31
  63. package/dist/core/DatabaseManager.js +1 -1
  64. package/dist/core/QueryView.d.ts +1 -1
  65. package/dist/core/QueryView.js +1 -1
  66. package/dist/core/StoreManager.d.ts +4 -23
  67. package/dist/core/StoreManager.js +5 -55
  68. package/dist/core/index.d.ts +2 -2
  69. package/dist/core/index.js +2 -2
  70. package/dist/core/storeContract.d.ts +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +227 -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 +40 -34
  78. package/dist/index.js +26 -20
  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 +2 -2
  99. package/dist/query/client.js +4 -4
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +6 -8
  103. package/dist/react/AbloProvider.js +5 -7
  104. package/dist/react/context.d.ts +1 -1
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/index.d.ts +5 -5
  107. package/dist/react/index.js +3 -3
  108. package/dist/react/internalContext.d.ts +1 -1
  109. package/dist/react/useAblo.d.ts +3 -3
  110. package/dist/react/useAblo.js +1 -1
  111. package/dist/react/useCurrentUserId.js +1 -1
  112. package/dist/react/useErrorListener.js +1 -1
  113. package/dist/react/useMutationFailureListener.d.ts +2 -2
  114. package/dist/react/useMutationFailureListener.js +1 -1
  115. package/dist/react/useMutators.d.ts +3 -3
  116. package/dist/react/useMutators.js +3 -3
  117. package/dist/react/useUndoScope.d.ts +5 -5
  118. package/dist/react/useUndoScope.js +1 -1
  119. package/dist/schema/coordination.d.ts +69 -10
  120. package/dist/schema/coordination.js +86 -9
  121. package/dist/schema/ddl.js +2 -2
  122. package/dist/schema/diff.d.ts +1 -1
  123. package/dist/schema/generate.js +1 -1
  124. package/dist/schema/index.d.ts +10 -10
  125. package/dist/schema/index.js +18 -18
  126. package/dist/schema/queries.d.ts +27 -27
  127. package/dist/schema/queries.js +23 -23
  128. package/dist/schema/select.d.ts +3 -3
  129. package/dist/schema/select.js +3 -3
  130. package/dist/schema/serialize.d.ts +15 -6
  131. package/dist/schema/serialize.js +17 -3
  132. package/dist/schema/sugar.d.ts +6 -7
  133. package/dist/schema/sugar.js +9 -12
  134. package/dist/schema/syncDeltaRow.d.ts +4 -152
  135. package/dist/schema/syncDeltaRow.js +4 -105
  136. package/dist/server/adapter.d.ts +18 -1
  137. package/dist/server/commit.d.ts +10 -16
  138. package/dist/server/index.d.ts +1 -1
  139. package/dist/server/index.js +1 -1
  140. package/dist/server/readConfig.d.ts +1 -1
  141. package/dist/source/adapters/drizzle.d.ts +1 -1
  142. package/dist/source/adapters/drizzle.js +2 -2
  143. package/dist/source/adapters/kysely.d.ts +1 -1
  144. package/dist/source/adapters/kysely.js +1 -1
  145. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  146. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  147. package/dist/source/adapters/memory.js +1 -1
  148. package/dist/source/adapters/prisma.d.ts +8 -3
  149. package/dist/source/adapters/prisma.js +1 -1
  150. package/dist/source/connector.js +1 -1
  151. package/dist/source/connectorProtocol.d.ts +2 -8
  152. package/dist/source/connectorProtocol.js +3 -2
  153. package/dist/source/contract.d.ts +29 -17
  154. package/dist/source/contract.js +27 -22
  155. package/dist/source/factory.d.ts +1 -1
  156. package/dist/source/footprint.d.ts +111 -0
  157. package/dist/source/footprint.js +0 -0
  158. package/dist/source/idempotency.js +2 -2
  159. package/dist/source/index.d.ts +1 -0
  160. package/dist/source/index.js +3 -0
  161. package/dist/source/next.d.ts +1 -1
  162. package/dist/source/signing.d.ts +9 -2
  163. package/dist/source/signing.js +4 -1
  164. package/dist/source/types.d.ts +6 -4
  165. package/dist/source/types.js +1 -1
  166. package/dist/stores/ObjectStore.d.ts +1 -1
  167. package/dist/stores/SyncActionStore.d.ts +1 -1
  168. package/dist/stores/SyncActionStore.js +2 -10
  169. package/dist/stores/syncAction.d.ts +26 -0
  170. package/dist/stores/syncAction.js +16 -0
  171. package/dist/surface.d.ts +3 -3
  172. package/dist/surface.js +6 -4
  173. package/dist/sync/BootstrapFetcher.d.ts +123 -6
  174. package/dist/sync/BootstrapFetcher.js +492 -66
  175. package/dist/sync/ConnectionManager.d.ts +6 -198
  176. package/dist/sync/ConnectionManager.js +6 -677
  177. package/dist/sync/OnDemandLoader.d.ts +2 -2
  178. package/dist/sync/OnDemandLoader.js +60 -21
  179. package/dist/sync/SubscriptionManager.d.ts +13 -2
  180. package/dist/sync/SubscriptionManager.js +23 -5
  181. package/dist/sync/SyncWebSocket.d.ts +27 -510
  182. package/dist/sync/SyncWebSocket.js +76 -954
  183. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  184. package/dist/sync/awaitClaimGrant.js +4 -109
  185. package/dist/sync/commitFrames.d.ts +6 -40
  186. package/dist/sync/commitFrames.js +6 -97
  187. package/dist/sync/contextPorts.d.ts +18 -0
  188. package/dist/sync/contextPorts.js +31 -0
  189. package/dist/sync/createClaimStream.d.ts +5 -49
  190. package/dist/sync/createClaimStream.js +5 -469
  191. package/dist/sync/createPresenceStream.d.ts +26 -4
  192. package/dist/sync/createPresenceStream.js +28 -20
  193. package/dist/sync/createSnapshot.d.ts +2 -2
  194. package/dist/sync/createSnapshot.js +1 -1
  195. package/dist/sync/credentialLifecycle.d.ts +5 -173
  196. package/dist/sync/credentialLifecycle.js +5 -320
  197. package/dist/sync/deltaPipeline.d.ts +1 -1
  198. package/dist/sync/participants.d.ts +5 -4
  199. package/dist/sync/participants.js +29 -22
  200. package/dist/sync/schemaDrift.d.ts +55 -0
  201. package/dist/sync/schemaDrift.js +53 -0
  202. package/dist/sync/schemas.d.ts +21 -32
  203. package/dist/sync/schemas.js +26 -17
  204. package/dist/sync/syncPlan.d.ts +3 -3
  205. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  206. package/dist/sync/wsFrameHandlers.js +6 -392
  207. package/dist/testing/fixtures/bootstrap.d.ts +1 -1
  208. package/dist/testing/fixtures/deltas.d.ts +1 -1
  209. package/dist/testing/fixtures/httpResponses.d.ts +70 -0
  210. package/dist/testing/fixtures/httpResponses.js +90 -0
  211. package/dist/testing/fixtures/models.js +1 -1
  212. package/dist/testing/helpers/wait.js +1 -1
  213. package/dist/testing/mocks/MockMutationExecutor.d.ts +2 -2
  214. package/dist/testing/mocks/MockMutationExecutor.js +8 -14
  215. package/dist/testing/mocks/MockSyncContext.d.ts +11 -11
  216. package/dist/testing/mocks/MockSyncContext.js +10 -9
  217. package/dist/testing/mocks/MockSyncStore.js +1 -1
  218. package/dist/testing/mocks/MockWebSocket.d.ts +2 -2
  219. package/dist/transaction/ablo.d.ts +88 -0
  220. package/dist/transaction/ablo.js +33 -0
  221. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  222. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  223. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  224. package/dist/transaction/auth/bootstrapScope.js +1 -0
  225. package/dist/transaction/auth/capability.d.ts +177 -0
  226. package/dist/transaction/auth/capability.js +199 -0
  227. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  228. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  229. package/dist/{client → transaction/auth}/identity.js +1 -1
  230. package/dist/transaction/auth/index.d.ts +162 -0
  231. package/dist/transaction/auth/index.js +304 -0
  232. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  233. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  234. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  235. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  236. package/dist/transaction/coordination/awaitClaimGrant.d.ts +49 -0
  237. package/dist/transaction/coordination/awaitClaimGrant.js +112 -0
  238. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  239. package/dist/transaction/coordination/claimMeta.js +52 -0
  240. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  241. package/dist/transaction/coordination/createClaimStream.js +475 -0
  242. package/dist/transaction/coordination/events.d.ts +74 -0
  243. package/dist/transaction/coordination/events.js +7 -0
  244. package/dist/transaction/coordination/index.d.ts +19 -0
  245. package/dist/transaction/coordination/index.js +44 -0
  246. package/dist/transaction/coordination/locator.d.ts +83 -0
  247. package/dist/transaction/coordination/locator.js +82 -0
  248. package/dist/transaction/coordination/schema.d.ts +1473 -0
  249. package/dist/{coordination → transaction/coordination}/schema.js +490 -55
  250. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  251. package/dist/transaction/coordination/targetConflict.js +103 -0
  252. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  253. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  254. package/dist/transaction/durableWrites.d.ts +62 -0
  255. package/dist/{client → transaction}/durableWrites.js +28 -3
  256. package/dist/transaction/environment.d.ts +105 -0
  257. package/dist/transaction/environment.js +108 -0
  258. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +11 -11
  259. package/dist/{errorCodes.js → transaction/errorCodes.js} +35 -12
  260. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  261. package/dist/{errors.js → transaction/errors.js} +85 -16
  262. package/dist/transaction/index.d.ts +20 -0
  263. package/dist/transaction/index.js +20 -0
  264. package/dist/transaction/keys/index.d.ts +87 -0
  265. package/dist/transaction/keys/index.js +207 -0
  266. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  267. package/dist/transaction/log/syncDeltaRow.js +95 -0
  268. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  269. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  270. package/dist/transaction/logger.d.ts +16 -0
  271. package/dist/transaction/logger.js +7 -0
  272. package/dist/transaction/observability.d.ts +53 -0
  273. package/dist/transaction/observability.js +19 -0
  274. package/dist/transaction/plugin.d.ts +192 -0
  275. package/dist/transaction/plugin.js +87 -0
  276. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  277. package/dist/{policy → transaction/policy}/types.js +2 -0
  278. package/dist/transaction/resources/httpResources.d.ts +266 -0
  279. package/dist/transaction/resources/httpResources.js +7 -0
  280. package/dist/transaction/resources/modelOperations.d.ts +319 -0
  281. package/dist/transaction/resources/modelOperations.js +12 -0
  282. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  283. package/dist/transaction/resources/mutationOptions.js +9 -0
  284. package/dist/transaction/resources/where.d.ts +85 -0
  285. package/dist/transaction/resources/where.js +70 -0
  286. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  287. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  288. package/dist/{schema → transaction/schema}/field.d.ts +5 -5
  289. package/dist/{schema → transaction/schema}/field.js +5 -5
  290. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  291. package/dist/transaction/schema/loadStrategy.js +46 -0
  292. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  293. package/dist/{schema → transaction/schema}/model.js +30 -20
  294. package/dist/transaction/schema/openapi.d.ts +57 -0
  295. package/dist/transaction/schema/openapi.js +340 -0
  296. package/dist/{schema → transaction/schema}/relation.d.ts +14 -14
  297. package/dist/{schema → transaction/schema}/relation.js +7 -7
  298. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  299. package/dist/{schema → transaction/schema}/residency.js +0 -5
  300. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  301. package/dist/{schema → transaction/schema}/roles.js +5 -5
  302. package/dist/{schema → transaction/schema}/schema.d.ts +12 -10
  303. package/dist/{schema → transaction/schema}/schema.js +4 -3
  304. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  305. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  306. package/dist/transaction/transactionLayer.d.ts +82 -0
  307. package/dist/transaction/transactionLayer.js +24 -0
  308. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +4 -5
  309. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  310. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  311. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  312. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +10 -36
  313. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  314. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  315. package/dist/transaction/transport/commitFrames.js +134 -0
  316. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  317. package/dist/transaction/transport/connectionManager.js +673 -0
  318. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  319. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  320. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  321. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  322. package/dist/{client → transaction/transport}/httpClient.d.ts +59 -16
  323. package/dist/{client → transaction/transport}/httpClient.js +5 -5
  324. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  325. package/dist/transaction/transport/httpOptions.js +12 -0
  326. package/dist/{client → transaction/transport}/httpTransport.js +171 -85
  327. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  328. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  329. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  330. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  331. package/dist/transaction/transport/wsTransport.d.ts +576 -0
  332. package/dist/transaction/transport/wsTransport.js +1017 -0
  333. package/dist/transaction/types/assertExact.d.ts +17 -0
  334. package/dist/transaction/types/assertExact.js +1 -0
  335. package/dist/{types → transaction/types}/global.d.ts +17 -2
  336. package/dist/{types → transaction/types}/global.js +2 -1
  337. package/dist/{types → transaction/types}/index.d.ts +14 -46
  338. package/dist/{types → transaction/types}/index.js +7 -16
  339. package/dist/{types → transaction/types}/streams.d.ts +63 -45
  340. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  341. package/dist/transaction/utils/json.js +276 -0
  342. package/dist/transaction/wire/accountResponses.d.ts +351 -0
  343. package/dist/transaction/wire/accountResponses.js +255 -0
  344. package/dist/transaction/wire/auth.d.ts +49 -0
  345. package/dist/transaction/wire/auth.js +57 -0
  346. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  347. package/dist/transaction/wire/claimEvent.js +73 -0
  348. package/dist/transaction/wire/claims.d.ts +463 -0
  349. package/dist/transaction/wire/claims.js +229 -0
  350. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  351. package/dist/{wire → transaction/wire}/commit.js +68 -47
  352. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  353. package/dist/{wire → transaction/wire}/delta.js +37 -13
  354. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  355. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  356. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  357. package/dist/transaction/wire/feedCursor.js +82 -0
  358. package/dist/transaction/wire/feedEvent.d.ts +177 -0
  359. package/dist/transaction/wire/feedEvent.js +39 -0
  360. package/dist/transaction/wire/frames.d.ts +194 -0
  361. package/dist/transaction/wire/frames.js +50 -0
  362. package/dist/transaction/wire/inboundFrames.d.ts +552 -0
  363. package/dist/transaction/wire/inboundFrames.js +116 -0
  364. package/dist/transaction/wire/index.d.ts +50 -0
  365. package/dist/transaction/wire/index.js +74 -0
  366. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  367. package/dist/transaction/wire/listEnvelope.js +42 -0
  368. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  369. package/dist/transaction/wire/modelResponses.js +43 -0
  370. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +79 -38
  371. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +110 -59
  372. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  373. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  374. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  375. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  376. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  377. package/dist/transactions/mutations/commitLatency.js +130 -0
  378. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  379. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  380. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +16 -15
  381. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +12 -12
  382. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +11 -11
  383. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +7 -7
  384. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  385. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  386. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  387. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +3 -3
  388. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +4 -3
  389. package/dist/utils/mobxSetup.d.ts +1 -1
  390. package/dist/utils/mobxSetup.js +5 -2
  391. package/dist/webhooks/events.d.ts +2 -2
  392. package/dist/wire/index.d.ts +1 -34
  393. package/dist/wire/index.js +8 -49
  394. package/docs/agent-messaging.md +3 -3
  395. package/docs/agents.md +19 -12
  396. package/docs/api-keys.md +8 -4
  397. package/docs/api.md +22 -18
  398. package/docs/audit.md +2 -0
  399. package/docs/cli.md +31 -3
  400. package/docs/client-behavior.md +8 -6
  401. package/docs/concurrency-convention.md +30 -24
  402. package/docs/coordination.md +48 -38
  403. package/docs/data-sources.md +3 -1
  404. package/docs/debugging.md +5 -3
  405. package/docs/deployment.md +267 -0
  406. package/docs/examples/agent-human.md +49 -42
  407. package/docs/examples/ai-sdk-tool.md +69 -44
  408. package/docs/examples/existing-python-backend.md +8 -6
  409. package/docs/examples/nextjs.md +129 -47
  410. package/docs/examples/scoped-agent.md +45 -44
  411. package/docs/examples/server-agent.md +46 -26
  412. package/docs/groups.md +32 -29
  413. package/docs/guarantees.md +4 -2
  414. package/docs/how-it-works.md +9 -7
  415. package/docs/idempotency.md +126 -0
  416. package/docs/identity.md +58 -54
  417. package/docs/index.md +172 -86
  418. package/docs/integration-guide.md +17 -16
  419. package/docs/interaction-model.md +6 -4
  420. package/docs/mcp.md +41 -16
  421. package/docs/migration.md +63 -5
  422. package/docs/operating-on-your-database.md +3 -1
  423. package/docs/projects.md +2 -0
  424. package/docs/quickstart.md +22 -5
  425. package/docs/react.md +12 -10
  426. package/docs/schema-contract.md +5 -3
  427. package/docs/session-settings.md +108 -0
  428. package/docs/sessions.md +3 -1
  429. package/docs/webhooks.md +3 -1
  430. package/llms.txt +47 -17
  431. package/package.json +10 -8
  432. package/dist/agent/Agent.d.ts +0 -366
  433. package/dist/agent/Agent.js +0 -514
  434. package/dist/agent/index.d.ts +0 -115
  435. package/dist/agent/index.js +0 -128
  436. package/dist/agent/session.d.ts +0 -93
  437. package/dist/agent/session.js +0 -149
  438. package/dist/agent/types.d.ts +0 -68
  439. package/dist/agent/types.js +0 -9
  440. package/dist/client/durableWrites.d.ts +0 -21
  441. package/dist/coordination/schema.d.ts +0 -722
  442. package/dist/schema/openapi.d.ts +0 -29
  443. package/dist/schema/openapi.js +0 -124
  444. package/dist/transactions/durableWriteStore.js +0 -30
  445. package/dist/utils/json.js +0 -88
  446. package/dist/wire/errorEnvelope.d.ts +0 -55
  447. package/dist/wire/frames.d.ts +0 -197
  448. package/dist/wire/frames.js +0 -49
  449. package/dist/wire/listEnvelope.js +0 -18
  450. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  451. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  452. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  453. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  454. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  455. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  456. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  457. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +0 -0
  458. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +0 -0
  459. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  460. /package/dist/{client → transaction}/persistence.js +0 -0
  461. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  462. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  463. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  464. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  465. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  466. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  467. /package/dist/{types → transaction/types}/modelData.js +0 -0
  468. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  469. /package/dist/{types → transaction/types}/participant.js +0 -0
  470. /package/dist/{types → transaction/types}/streams.js +0 -0
  471. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  472. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  473. /package/dist/{utils → transaction/utils}/duration.d.ts +0 -0
  474. /package/dist/{utils → transaction/utils}/duration.js +0 -0
  475. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  476. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  477. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  478. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  479. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  480. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  481. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  482. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  483. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
package/llms.txt CHANGED
@@ -1,11 +1,24 @@
1
1
  # Ablo
2
2
 
3
- Ablo is the state coordination layer for apps where humans and agents edit the same data.
3
+ Ablo is the agentic coordination layer: one API for AI agents, apps, and services to claim, change, and confirm the same rows.
4
4
 
5
- Here is the problem it solves. Two writers touch `report_stockholm` at once. The agent claims the row, does slow work (an LLM call, a fetch), and commits; the human's UI sees the claim live and never clobbers it. Claims don't lock. If another writer holds the row, `claim` waits for them, re-reads the fresh row, then hands it to you — so two writers serialize instead of clobbering.
5
+ Here is the problem it solves. Two agents reach for `report_stockholm` at once. One claims the row, does slow work (an LLM call, a fetch, a chain of tools), and commits. The second is neither rejected nor allowed to clobber: it waits in line, is handed the row as it now stands, and proceeds. Claims don't lock. If another writer holds the row, `claim` waits for them, re-reads the fresh row, then hands it to you — so writers serialize instead of colliding. A person editing that row is simply another holder; the agent waits behind them the same way.
6
6
 
7
7
  Use AI SDK for the agent loop. Use Ablo when agent reads and writes must persist, coordinate with concurrent work, and leave an audit trail.
8
8
 
9
+ ## Surfaces — pick by who is calling
10
+
11
+ Every surface reaches the same coordinated state. They are not interchangeable.
12
+
13
+ - SDK, `@abloatai/ablo` with `transport: 'http'` — THE AGENTS THEMSELVES. Stateless, request/response, nothing held open; the credential is the identity. This is the main path — default to it.
14
+ - Coordination MCP, `@abloatai/mcp` — an agent living inside an MCP host (Claude, Cursor). Two jobs: MANAGING your Ablo the way the CLI does (`get_schema`, `list_projects`, `create_project`, `tail_logs`, `get_usage`), and claim/commit as tools over your rows. Call `get_schema` first — it is the only way to learn the model names every data tool needs. `init`, `push`, `pull`, `generate` have no tools (they touch your repo); run those in a shell.
15
+ - `humans()` with `@abloatai/ablo/react` — the interfaces a person watches agent work arrive in. The bare client is the coordination layer (commit, read, observe, claim); `humans()` is the PLUGIN that adds the local watchable copy, live queries, and presence. It `requires: { duplex: true }`, so a `transport: 'http'` agent is rejected at construction rather than left holding a subscription that never delivers. It is installed by default on a socket client with no `plugins` list. There is no `agents()` plugin — agents are the default caller, not a special one. A browser NEVER receives the secret key; mint a session token.
16
+ - CLI, `ablo` — scaffolding, schema push, connecting a database. Terminals and CI. Agents must run it non-interactively (see the CLI section below).
17
+ - REST, `/api/v1` — runtimes with no SDK.
18
+ - Integration-helper MCP, hosted `/api/mcp` — teaching a coding assistant the SDK WHILE BUILDING an integration. Docs, schema lint, and scaffolds only; it has NO per-model data tools and cannot touch application rows.
19
+
20
+ The two MCP servers do different jobs and are the most common mix-up: to change application rows use the SDK or the COORDINATION server; the integration-helper server cannot do it at all. Do not hand-roll HTTP against `/api/v1` when a typed SDK exists for the runtime you are in.
21
+
9
22
  ## Start here
10
23
 
11
24
  First action when integrating into an app: run `npx ablo init --yes --framework <nextjs|vite|remix|vanilla>`. Agents have no TTY — `--yes` is REQUIRED or it HANGS. It scaffolds `ablo/schema.ts`, the `Ablo({ schema, apiKey })` client, and (for Next.js) the browser provider + session route. All on the current API. Edit the generated files rather than hand-writing from this doc. Connecting a database is a SEPARATE step with one path — logical replication via `npx ablo connect` (see Storage Boundary); the signed Data Source endpoint is the fallback when database credentials must stay inside the app.
@@ -24,7 +37,7 @@ Each app gets its own PROJECT inside the org — its own schema, its own sandbox
24
37
  import Ablo from '@abloatai/ablo';
25
38
  import { defineSchema, model, z } from '@abloatai/ablo/schema';
26
39
 
27
- TYPES: the project registers its schema ONCE via declaration merging — `npx ablo init` scaffolds `ablo/register.ts` (a regular `.ts` module beside schema.ts, NOT a hand-authored `.d.ts`): `import type { schema } from './schema'; declare module '@abloatai/ablo' { interface Register { Schema: typeof schema } }`. The top-level `import type` makes `declare module` MERGE (augment) the SDK's Register interface rather than collide — same shape TanStack Router uses in src/router.tsx; any `.ts` file in tsconfig include works, never imported. Then model types are one parameter: `type Task = Model<'tasks'>` (import type { Model } from '@abloatai/ablo/schema'). Do NOT teach `InferModel` (deprecated) or the two-param `Model<typeof schema,'tasks'>` unless multiple schemas exist. Never hand-write model interfaces — derive from the schema. To NAME the client type (function param, context value), infer from the value: `type Sync = typeof sync` — same idiom as tRPC `typeof appRouter` / Drizzle `typeof db`; it resolves the typed overload at the call site. Do NOT use `ReturnType<typeof Ablo>` (collapses to the untyped last overload) and do NOT import a bespoke client-type generic — there is none.
40
+ TYPES: the project registers its schema ONCE via declaration merging — `npx ablo init` scaffolds `ablo/register.ts` (a regular `.ts` module beside schema.ts, NOT a hand-authored `.d.ts`): `import type { schema } from './schema'; declare module '@abloatai/ablo' { interface Register { Schema: typeof schema } }`. The top-level `import type` makes `declare module` MERGE (augment) the SDK's Register interface rather than collide — same shape TanStack Router uses in src/router.tsx; any `.ts` file in tsconfig include works, never imported. Then model types are one parameter: `type Task = Model<'tasks'>` (import type { Model } from '@abloatai/ablo/schema'); the two-parameter `Model<typeof schema,'tasks'>` form is only for projects carrying multiple schemas. Never hand-write model interfaces — derive from the schema. To NAME the client type (function param, context value), infer from the value: `type Sync = typeof sync` — same idiom as tRPC `typeof appRouter` / Drizzle `typeof db`; it resolves the typed overload at the call site. Do NOT use `ReturnType<typeof Ablo>` (collapses to the untyped last overload) and do NOT import a bespoke client-type generic — there is none.
28
41
 
29
42
 
30
43
  const schema = defineSchema({
@@ -62,10 +75,12 @@ the same model API across your own Data Source-backed app databases,
62
75
  React selectors, multiplayer, and future agent workers.
63
76
 
64
77
  Reads come in two flavors, and you pick by whether you can wait. `retrieve({ id })`
65
- (one row) and `list({ where })` (many) are async — they hit the server and return
66
- a Promise, so await them. `get(id)`, `getAll({ where })`, and `getCount({ where })`
67
- are synchronous they read the local graph and are reactive in render, so no
68
- await. The query reads accept `where`, `filter`, `orderBy`, `limit`, `offset`,
78
+ (one row) and `list({ where })` (many) are async — they answer from the local
79
+ graph and fall back to the server, so await them. `local.retrieve(id)`,
80
+ `local.list({ where })`, and `local.count({ where })` are the same reads narrowed
81
+ to what has already synced: nothing to await, reactive in render. There is no
82
+ second verb to learn — `local.` is the only difference. The query reads accept
83
+ `where`, `filter`, `orderBy`, `limit`, `offset`,
69
84
  and `state`; state defaults to `'live'`, with `'archived'` and `'all'` to include
70
85
  retired rows.
71
86
 
@@ -73,10 +88,10 @@ Workers import the same app schema and select `transport: 'http'`. The transport
73
88
  changes; the typed `ablo.<model>` contract does not. There is no public
74
89
  schema-less or string-keyed model client.
75
90
 
76
- React reads should use selector `useAblo`: `useAblo((ablo) => ablo.weatherReports.get(id))` (synchronous local read, reactive in render).
91
+ React reads should use selector `useAblo`: `useAblo((ablo) => ablo.weatherReports.local.retrieve(id))` (synchronous local read, reactive in render).
77
92
  Use zero-argument `useAblo()` only when a component needs the client for an
78
- event handler or effect. The older string-keyed hooks (`useQuery`, `useOne`,
79
- `useReader`, and `useMutate`) are removed; do not import or recommend them.
93
+ event handler or effect. The selector form above is the complete reactive
94
+ surface every read goes through it.
80
95
 
81
96
  ## Multiplayer
82
97
 
@@ -90,7 +105,7 @@ coordination until the app reports it through Data Source events.
90
105
 
91
106
  ## Change propagation
92
107
 
93
- A change to one row reaches other rows three ways. ROUTING: a write fans out to every sync group the row belongs to, INCLUDING its ancestors' groups (editing a layer routes to `layer:` + `slide:` + `deck:`), so everyone watching the deck sees it — delivery, not recomputation. DELETE CASCADE: deleting a parent emits explicit tombstone deltas for its descendants, so open clients never silently hold rows that are gone. VALUE: derived values are NOT recomputed server-side — Ablo surfaces that the source moved and the actor decides. To keep dependent work fresh, declare what you read as a batch premise: `reads: [{ group: 'deck:abc', readAt: N, onStale: 'notify' }]`. At commit the server checks whether anything in that group moved past `readAt`; `notify` holds the write and returns a `StaleNotification` (re-read the group and regenerate), `reject` aborts. To chain A→B→C, put A+B in one group and B+C in another: A's change reaches B, and C hears it only once B ITSELF writes — the engine wires the edges and signals each hop, the actor walks them. No transitive auto-recompute, no convergence guarantee for cycles. `reads` guards ONE commit; for a long-running actor that reads now and writes much later, register a DURABLE premise with `track`: `ablo.<model>.track({ id })` for a row, or the `track:` write option (`track: [{ group: 'deck:abc' }]`) alongside a write. A track persists server-side; the next time you commit anything, a change that landed on the tracked target rides back on your receipt's `notifications` (same `StaleNotification` shape as `onStale: 'notify'`). It is an idempotent registration, re-baselines so a change fires once, and never notifies you of your own writes. Delivery is on your next commit — a track does not yet push out of band between commits.
108
+ A change to one row reaches other rows three ways. ROUTING: a write fans out to every sync group the row belongs to, INCLUDING its ancestors' groups (editing a block routes to `block:` + `document:` + `workspace:`), so everyone watching the workspace sees it — delivery, not recomputation. DELETE CASCADE: deleting a parent emits explicit tombstone deltas for its descendants, so open clients never silently hold rows that are gone. VALUE: derived values are NOT recomputed server-side — Ablo surfaces that the source moved and the actor decides. To keep dependent work fresh, declare what you read as a batch premise: `reads: [{ group: 'workspace:abc', readAt: N, onStale: 'notify' }]`. At commit the server checks whether anything in that group moved past `readAt`; `notify` holds the write and returns a `StaleNotification` (re-read the group and regenerate), `reject` aborts. To chain A→B→C, put A+B in one group and B+C in another: A's change reaches B, and C hears it only once B ITSELF writes — the engine wires the edges and signals each hop, the actor walks them. No transitive auto-recompute, no convergence guarantee for cycles. `reads` guards ONE commit; for a long-running actor that reads now and writes much later, register a DURABLE premise with `track`: `ablo.<model>.track({ id })` for a row, or the `track:` write option (`track: [{ group: 'workspace:abc' }]`) alongside a write. A track persists server-side; the next time you commit anything, a change that landed on the tracked target rides back on your receipt's `notifications` (same `StaleNotification` shape as `onStale: 'notify'`). It is an idempotent registration, re-baselines so a change fires once, and never notifies you of your own writes. Delivery is on your next commit — a track does not yet push out of band between commits.
94
109
 
95
110
  ## Nouns
96
111
 
@@ -107,6 +122,13 @@ even while it is claimed. Pass `ifClaimed: 'fail'` to throw
107
122
  `AbloClaimedError`, and inspect active coordination separately through
108
123
  `ablo.<model>.claim.state({ id })`.
109
124
 
125
+ A claim carries app metadata verbatim in `target.meta`. Declare its shape in the
126
+ SAME register block as the schema — `interface Register { Schema: typeof schema;
127
+ ClaimMeta: { blocks: string[] } }` — and it types both what you write
128
+ (`claim({ id, meta })`) and every read (`claim.state`, `claim.queue`, the held
129
+ claim), so no read needs a `typeof` guard. The per-call `claim.state<M>({ id })`
130
+ still works and is for a program carrying more than one metadata shape.
131
+
110
132
  Reads never block on a claim. To wait for a row to free up, `claim({ id })` it —
111
133
  the claim queues fairly behind the current holder and is granted when the row
112
134
  frees. Use `ifClaimed: 'fail'` when you'd rather refuse to read a claimed row.
@@ -133,7 +155,7 @@ RLS GOVERNS ABLO'S WRITES. The writer role is `NOSUPERUSER NOBYPASSRLS`, and bef
133
155
 
134
156
  FALLBACK (only when Ablo can't dial the database, e.g. a private VPC with no inbound route): a signed Data Source endpoint that hands Ablo an ORM `adapter` (Drizzle default; Prisma and Kysely supported) — Ablo writes and confirms through it, and it owns the transaction, exactly-once idempotency, and outbox in ONE pass; your credentials never leave your infrastructure.
135
157
 
136
- DEPRECATED removed, do NOT recommend or scaffold: the `databaseUrl` constructor option (the old DIAL-IN, where the CLIENT held a read/write connection string and committed directly, bypassing Ablo's coordination). It is deleted. DO NOT confuse it with the current model: today's writes also land in your Postgres, but through Ablo's SERVER-SIDE commit chokepoint and a scoped writer role Ablo provisions — coordination is never bypassed, and no connection string lives in your app. The NON-superuser / NON-BYPASSRLS role rule is NOT retired — it now applies to the scoped writer role `ablo connect` provisions (see RLS above), because Ablo does hold a scoped connection to write your rows. The end-state constructor is `Ablo({ schema, apiKey })`; the database is connected out of band via `ablo connect`. `ablo init` may still scaffold legacy `--storage direct`/`databaseUrl` for old projects and the CLI warns on it; prefer `ablo connect`.
158
+ The constructor is `Ablo({ schema, apiKey })` the app holds an API key and nothing else; no connection string ever lives in the app. The database is connected out of band with `ablo connect`: writes land in your Postgres through Ablo's server-side commit path using the scoped writer role `ablo connect` creates, and that role is always NON-superuser / NON-BYPASSRLS (see RLS above).
137
159
 
138
160
  ```ts
139
161
  // app/api/ablo/source/route.ts
@@ -151,7 +173,7 @@ export const { POST } = dataSourceNext({
151
173
  });
152
174
  ```
153
175
 
154
- Connect a database with `npx ablo connect` (logical replication — the one path above). The signed Data Source endpoint (code above) is the fallback when app database credentials must stay private; scaffold it with `npx ablo init --storage endpoint` — Ablo only calls the endpoint. (`--storage direct` still exists for existing dial-in projects but is deprecated; the CLI warns on it.)
176
+ Connect a database with `npx ablo connect` (logical replication — the one path above). The signed Data Source endpoint (code above) is the fallback when app database credentials must stay private; scaffold it with `npx ablo init --storage endpoint` — Ablo only calls the endpoint.
155
177
 
156
178
  ## Sandboxes
157
179
 
@@ -163,7 +185,7 @@ when an agent is asked to "make Ablo work" in an existing app.
163
185
  Authenticated org sandboxes are real test environments. Treat the default
164
186
  sandbox like Stripe test mode: it has an isolated sync group prefix and mints
165
187
  `sk_test_*` keys. The sandbox CAN host rows in Ablo's test plane, so you can try
166
- Ablo with NO database — `apiKey` only, no `databaseUrl`. (In production, your own
188
+ Ablo with NO database — `apiKey` only, nothing else. (In production, your own
167
189
  Postgres is the system of record.) Extra sandboxes can start blank or copy live
168
190
  configuration. Resetting a sandbox creates a clean future stream without
169
191
  touching live data. Use `sk_live_*` only for production.
@@ -173,6 +195,12 @@ declare schema, create the Ablo client, replace one direct mutation with a typed
173
195
  `ablo.<model>.update(...)`, use selector `useAblo` for live reads, and add a
174
196
  two-writer stale/claim smoke test.
175
197
 
198
+ ## Production
199
+
200
+ A PLANE is what a credential acts on: `production` is the root, sandboxes sit beside it. Rows, the registered database, and the active schema artifact are all PER PLANE, and a key's plane is fixed at mint by its prefix (`sk_live_` → production, `sk_test_` → sandbox) — there is no runtime override, which is why app code never passes an environment. ONE ASYMMETRY: a sandbox with no schema artifact of its own READS PRODUCTION'S, so a production push reaches sandboxes; a SANDBOX push does NOT reach production — it creates a sandbox artifact that shadows production for that sandbox's readers only. Production gets models when you push to production.
201
+
202
+ Going live is three things, each done with a `sk_live_` key: register the production database (`ablo connect apply` — the DIRECT host, never a pooler; a pooler refuses in the words of a wrong password), push the schema AHEAD of the code that needs it, and hold the right credential per runtime (server/serverless `sk_live_`; browser `pk_live_` read-only or an `authEndpoint` minting `ek_`). The live key `ablo login` stores is a RESTRICTED observe-only `rk_live_` and CANNOT push schema — a production push needs a dashboard `sk_live_` in `ABLO_API_KEY`. Gate a deploy on `npx ablo status --json` having an EMPTY `blockers` array; each blocker carries a `problem` and the one `fix`. Your agents do NOT each hold a database connection — they talk to Ablo, and Ablo holds at most 4 connections per plane (`application_name = 'ablo-direct-writer'`) however many callers write behind them, so size the database for that number and not for your agent count. Read `deployment` for the full path.
203
+
176
204
  ## Public Surface
177
205
 
178
206
  Import from these public paths only:
@@ -193,10 +221,12 @@ Do not teach `/api`, `/agent`, `/ai-sdk`, `/core`, `/realtime`, or internal subp
193
221
 
194
222
  `ablo init` and other prompts need a TTY; an agent/CI run has none and will HANG. Always:
195
223
 
196
- - `npx ablo init --yes` (flags: `--framework`, `--auth`, `--storage direct|endpoint`, `--no-agent`, `--no-pull`, `--no-install`, `--no-login`). Generates `ablo/schema.ts` + the `Ablo({ schema, apiKey })` client. `--storage endpoint` also scaffolds the `ablo/data-source.ts` fallback endpoint; `--storage direct` (deprecated, CLI warns) wires the legacy `databaseUrl`.
224
+ - `npx ablo init --yes` (flags: `--framework`, `--auth`, `--storage replication|endpoint`, `--no-agent`, `--no-pull`, `--no-install`, `--no-login`). Generates `ablo/schema.ts` + the `Ablo({ schema, apiKey })` client. `--storage replication` (the default) pairs with `ablo connect`; `--storage endpoint` also scaffolds the `ablo/data-source.ts` fallback endpoint.
197
225
  - `npx ablo connect` connects your database via logical replication — the read path (prints the `wal_level=logical` + publication + `REPLICATION`-role SQL); `npx ablo connect register` registers it, `npx ablo connect check` validates the registered database from Ablo's own side and needs only `ABLO_API_KEY` (no database credential in your environment). `npx ablo connect apply` does the whole setup from a one-time admin connection and leaves your app holding only `ABLO_API_KEY`.
198
226
  - Key: see "Start here" — env → `.env.local` → ask the human to `npx ablo login`; never run `login` yourself, never copy keys by hand (`ablo push` writes `.env.local`).
199
227
  - Adopt an existing DB: `npx ablo pull prisma [path]` / `npx ablo pull drizzle <module>`.
200
- - `npx ablo push` pushes the schema (sandbox) AND writes `ABLO_API_KEY` to `.env.local`; `npx ablo dev --no-watch` is the push-once form of the watcher; `npx ablo logs --no-follow` exits instead of tailing forever; `npx ablo mode sandbox|production` always needs the argument. `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
228
+ - `npx ablo push` pushes the schema (sandbox) AND writes `ABLO_API_KEY` to `.env.local`. A PRODUCTION push (`sk_live_` key) needs `--yes`: with no TTY it REFUSES rather than deploying unattended, and interactively it demands the destination project typed by name. Destructive steps (dropped model/field, narrowed enum, lossy cast) need `--force`; a new required field on a populated table needs `--backfill model.field=value`. `npx ablo dev --no-watch` is the push-once form of the watcher; `npx ablo logs --no-follow` exits instead of tailing forever; `npx ablo mode sandbox|production` always needs the argument. `npx ablo push`/`status`/`pull`/`check`/`generate` are one-shot.
229
+
230
+ - `npx ablo docs` lists every documentation page; `npx ablo docs <page>` prints one as markdown. These pages ship INSIDE the installed package, so they describe the version in `node_modules` and need no network. Prefer them over a docs URL whenever the project pins a version: a website always describes the newest release, so on an older pin it will hand you a call your package does not have (`retrieve`/`list` replaced `get`/`getAll`/`getCount` in 0.35.0). One-shot, safe to run unattended.
201
231
 
202
- Canonical docs to read before integrating: `quickstart`, `schema-contract`, `integration-guide`, `guarantees`, `client-behavior`, `data-sources`, `examples/existing-python-backend`, `api`, `examples/ai-sdk-tool`, and `examples/server-agent`. When upgrading an existing integration, read `migration` — every breaking change, what to change, and which version introduced it.
232
+ Canonical docs to read before integrating: `quickstart`, `schema-contract`, `integration-guide`, `deployment`, `guarantees`, `client-behavior`, `data-sources`, `examples/existing-python-backend`, `api`, `examples/ai-sdk-tool`, and `examples/server-agent` — read each with `npx ablo docs <page>`. When upgrading an existing integration, read `migration` — every breaking change, what to change, and which version introduced it. When the customer's database has row-level-security policies, read `session-settings` — the identity context Ablo sets before every write, and how to map it to the setting names those policies already read.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.34.1",
3
+ "version": "0.35.0",
4
4
  "description": "The Collaboration Layer For AI Agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -48,11 +48,6 @@
48
48
  "import": "./dist/batching/index.js",
49
49
  "default": "./dist/batching/index.js"
50
50
  },
51
- "./agent": {
52
- "types": "./dist/agent/index.d.ts",
53
- "import": "./dist/agent/index.js",
54
- "default": "./dist/agent/index.js"
55
- },
56
51
  "./ai-sdk": {
57
52
  "types": "./dist/ai-sdk/index.d.ts",
58
53
  "import": "./dist/ai-sdk/index.js",
@@ -112,6 +107,11 @@
112
107
  "types": "./dist/webhooks/index.d.ts",
113
108
  "import": "./dist/webhooks/index.js",
114
109
  "default": "./dist/webhooks/index.js"
110
+ },
111
+ "./docs": {
112
+ "types": "./dist/docs/index.d.ts",
113
+ "import": "./dist/docs/index.js",
114
+ "default": "./dist/docs/index.js"
115
115
  }
116
116
  },
117
117
  "files": [
@@ -119,7 +119,6 @@
119
119
  "!dist/__type_probe.*",
120
120
  "docs/*.md",
121
121
  "docs/examples/*.md",
122
- "docs/mcp/*.md",
123
122
  "examples",
124
123
  "AGENTS.md",
125
124
  "llms.txt",
@@ -132,7 +131,10 @@
132
131
  "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
133
132
  "build": "npm run clean && tsc -p tsconfig.build.json && npm run build:cli",
134
133
  "build:cli": "tsup --config tsup.cli.config.ts",
134
+ "typecheck": "npm run typecheck:src && npm run typecheck:cli && npm run typecheck:scripts",
135
+ "typecheck:src": "tsc -p tsconfig.json",
135
136
  "typecheck:cli": "tsc -p tsconfig.cli.json",
137
+ "typecheck:scripts": "tsc -p tsconfig.scripts.json",
136
138
  "prepack": "node scripts/strip-source-condition.mjs",
137
139
  "postpack": "node scripts/restore-source-condition.mjs",
138
140
  "pack:check": "node scripts/pack-check.mjs",
@@ -207,7 +209,7 @@
207
209
  "mobx": "^6.13.7",
208
210
  "mobx-react-lite": "^4.0.0",
209
211
  "uuid": "^11.1.0",
210
- "zod": "^4.1.11"
212
+ "zod": "^4.4.3"
211
213
  },
212
214
  "devDependencies": {
213
215
  "@ai-sdk/provider": "^3.0.0",
@@ -1,366 +0,0 @@
1
- /**
2
- * Agent — AI SDK v6 native hooks for agent awareness.
3
- *
4
- * Slots directly into generateText / streamText / ToolLoopAgent via three
5
- * hooks: prepareStep (inject awareness before each step), onStepFinish
6
- * (announce activity after each step), and wrapTool (wrap mutation tools
7
- * with freshness checks). Stateless REST under the hood — works with any
8
- * API model, no WebSocket.
9
- *
10
- * ```ts
11
- * import { generateText, tool, stepCountIs } from 'ai';
12
- * import { Agent } from '@abloatai/ablo/agent';
13
- *
14
- * const perception = new Agent({
15
- * syncServerUrl: 'http://localhost:8080',
16
- * agentId: 'researcher-1',
17
- * organizationId: 'org-1',
18
- * syncGroups: ['deal:abc'],
19
- * });
20
- *
21
- * const result = await generateText({
22
- * model: 'anthropic/claude-sonnet-4.5',
23
- * messages,
24
- * stopWhen: stepCountIs(10),
25
- * tools: {
26
- * updateSlide: perception.wrapTool(
27
- * tool({
28
- * inputSchema: z.object({ id: z.string(), title: z.string() }),
29
- * execute: async ({ id, title }) => { ... },
30
- * }),
31
- * { entityType: 'Slide', getEntityId: (args) => args.id },
32
- * ),
33
- * },
34
- * prepareStep: perception.prepareStep(), // injects awareness
35
- * onStepFinish: perception.onStepFinish(), // announces activity
36
- * });
37
- * ```
38
- *
39
- * Low-level primitives (gather, checkFreshness, announce) are also exposed
40
- * for custom integrations outside the AI SDK.
41
- */
42
- import type { PresenceAnnouncer, AgentContext } from './types.js';
43
- import type { Activity, WireClaim } from '../types/streams.js';
44
- import { createAgentSession } from './session.js';
45
- export type { AgentContext } from './types.js';
46
- export type { WireClaim } from '../types/streams.js';
47
- /**
48
- * The record shape the sync server returns from its REST `/api/presence`
49
- * endpoint. This interface is internal to this module and not exported. Its
50
- * field names (`userId`, `isAgent`, `updatedAt`) are the wire contract the
51
- * presence API sends, and {@link Agent.gather} surfaces these records
52
- * unchanged in the `presence` array of its snapshot.
53
- */
54
- interface WirePeer {
55
- userId: string;
56
- isAgent?: boolean;
57
- status: 'online' | 'away' | 'offline' | (string & {});
58
- syncGroups?: string[];
59
- activity?: Activity;
60
- updatedAt?: number;
61
- organizationId?: string;
62
- activeClaims?: WireClaim[];
63
- }
64
- import type { SyncLogger } from '../interfaces/index.js';
65
- export interface AgentOptions {
66
- /** Base URL of the sync server, e.g. `http://localhost:8080`. */
67
- syncServerUrl: string;
68
- /** Unique agent identifier — without the `agent:` prefix. */
69
- agentId: string;
70
- /** Organization this agent belongs to. */
71
- organizationId: string;
72
- /** Sync groups determine which other participants are visible. */
73
- syncGroups: string[];
74
- /** Optional bearer token for authenticated requests. */
75
- authToken?: string;
76
- /** Custom fetch — defaults to global fetch. Useful for testing. */
77
- fetch?: typeof fetch;
78
- /** Timeout per request in ms. Default 5000. */
79
- timeoutMs?: number;
80
- /**
81
- * Optional presence announcer — route `announce()` through this instead
82
- * of REST. Pass a connected SyncAgent here to reuse its WebSocket and
83
- * avoid per-step HTTP round trips.
84
- */
85
- announcer?: PresenceAnnouncer;
86
- /**
87
- * Optional logger. The agent SDK runs in standalone Node processes
88
- * that don't share the SyncEngineContext, so Agent takes
89
- * its own logger handle. Defaults to a console-backed logger; pass
90
- * your structured logger (Pino, Winston, etc.) to get consistent
91
- * agent-worker log routing.
92
- */
93
- logger?: SyncLogger;
94
- }
95
- export interface GatherOptions {
96
- /** Focus context on these entities — format: "ModelName:id". */
97
- focusEntities?: string[];
98
- /** Maximum output characters for the formatted prompt. Default 2000. */
99
- maxChars?: number;
100
- /** Include presence of other participants. Default true. */
101
- includePresence?: boolean;
102
- /** Exclude this agent's own presence from the output. Default true. */
103
- excludeSelf?: boolean;
104
- }
105
- export interface AgentSnapshot {
106
- timestamp: number;
107
- presence: WirePeer[];
108
- }
109
- export interface GatherResult {
110
- /** Natural-language summary ready to inject as a system message. */
111
- prompt: string;
112
- /** Structured data for programmatic use. */
113
- snapshot: AgentSnapshot;
114
- }
115
- export interface FreshnessCheck {
116
- stale: boolean;
117
- reason?: 'ok' | 'not_found' | 'modified';
118
- /** Current entity state from the server. */
119
- currentState?: Record<string, unknown>;
120
- lastModifiedBy?: string;
121
- lastModifiedAt?: number;
122
- /** Human-readable summary — feed this back to the LLM when stale. */
123
- summary?: string;
124
- /**
125
- * Pending-mutation claims from other participants targeting this
126
- * entity, with the agent's own claims filtered out. An empty array
127
- * means no one else is currently generating against the entity. A
128
- * non-empty array is advisory: the agent can proceed, wait, or defer.
129
- */
130
- pendingClaims?: WireClaim[];
131
- }
132
- /** Subset of AI SDK's ModelMessage — structural. */
133
- export interface AgentMessage {
134
- role: 'system' | 'user' | 'assistant' | 'tool';
135
- content: unknown;
136
- }
137
- /** Subset of AI SDK's prepareStep context. */
138
- export interface PrepareStepContext<M extends AgentMessage = AgentMessage> {
139
- stepNumber: number;
140
- steps: readonly {
141
- toolCalls?: readonly {
142
- toolName: string;
143
- input?: unknown;
144
- args?: unknown;
145
- }[];
146
- toolResults?: readonly unknown[];
147
- }[];
148
- messages: M[];
149
- model?: unknown;
150
- }
151
- /** Subset of AI SDK's prepareStep return shape. */
152
- export interface PrepareStepResult<M extends AgentMessage = AgentMessage> {
153
- messages?: M[];
154
- model?: unknown;
155
- toolChoice?: unknown;
156
- activeTools?: string[];
157
- }
158
- /** Subset of AI SDK's onStepFinish context. */
159
- export interface StepFinishContext {
160
- stepType?: 'initial' | 'continue' | 'tool-result';
161
- finishReason?: string;
162
- text?: string;
163
- toolCalls?: readonly {
164
- toolName: string;
165
- input?: unknown;
166
- args?: unknown;
167
- }[];
168
- toolResults?: readonly unknown[];
169
- usage?: {
170
- inputTokens?: number;
171
- outputTokens?: number;
172
- totalTokens?: number;
173
- };
174
- }
175
- /** Subset of AI SDK's ToolExecutionOptions. */
176
- export interface ToolExecutionOptions {
177
- toolCallId?: string;
178
- messages?: AgentMessage[];
179
- abortSignal?: AbortSignal;
180
- experimental_context?: unknown;
181
- }
182
- /** Minimal tool shape — a subset of AI SDK's Tool type. */
183
- export interface AgentTool<TArgs = unknown, TResult = unknown> {
184
- description?: string;
185
- inputSchema?: unknown;
186
- execute?: (args: TArgs, options: ToolExecutionOptions) => Promise<TResult> | TResult;
187
- [extra: string]: unknown;
188
- }
189
- export interface PrepareStepOptions {
190
- /** Max characters of awareness context to inject. Default 1500. */
191
- maxChars?: number;
192
- /**
193
- * Derive focus entities from recent tool calls so the LLM sees participants
194
- * working on the same entities. Requires a mapper from tool call to entity
195
- * tokens (format: "ModelName:id"). Default: no auto-focus.
196
- */
197
- focusFromToolCalls?: (toolCall: {
198
- toolName: string;
199
- input?: unknown;
200
- args?: unknown;
201
- }) => string[] | undefined;
202
- /** Skip awareness injection for step 0 (initial prompt). Default false. */
203
- skipFirstStep?: boolean;
204
- }
205
- export interface OnStepFinishOptions {
206
- /**
207
- * Derive an activity announcement from the finished step. Return null to
208
- * skip announcing for this step. Default: announces the last tool name
209
- * if any tool was called.
210
- */
211
- activity?: (ctx: StepFinishContext) => Activity | null;
212
- }
213
- export interface WrapToolOptions<TArgs> {
214
- /** Entity type the tool mutates — e.g. "Slide", "Sheet". */
215
- entityType: string;
216
- /** Extract the entity id from the tool's args. */
217
- getEntityId: (args: TArgs) => string | undefined;
218
- /**
219
- * Resolve the timestamp the LLM last saw this entity. If omitted or it
220
- * returns 0, the freshness check is skipped (no baseline to compare).
221
- */
222
- lastSeenAt?: (args: TArgs, options: ToolExecutionOptions) => number | undefined;
223
- /**
224
- * Announce that the agent is about to work on this entity before executing.
225
- * Default true — the agent announces `action: "editing"` automatically.
226
- */
227
- announceOnExecute?: boolean;
228
- }
229
- /**
230
- * The console-backed logger an {@link Agent} uses when the caller does not
231
- * supply one. It is the same gated factory the `Ablo()` client uses
232
- * (`createConsoleLogger`), reads its threshold from the `ABLO_LOG_LEVEL`
233
- * environment variable (default `warn`), and tags each line with `[agent]` so
234
- * agent-runtime output is easy to spot. The level is resolved when the logger
235
- * is built rather than at module load, so an `ABLO_LOG_LEVEL` that the host
236
- * process sets before constructing an Agent is honored.
237
- *
238
- * Exported so a unit test can pin the gating behavior; consumers normally pass
239
- * their own `logger` option instead.
240
- */
241
- export declare function defaultAgentLogger(): SyncLogger;
242
- export declare class Agent implements PresenceAnnouncer {
243
- private readonly opts;
244
- constructor(options: AgentOptions);
245
- /**
246
- * Build a long-lived agent session — caches `Ablo({kind:'agent'})`
247
- * instances per `(org, user, surface, target)` and refreshes capability
248
- * tokens before TTL elapses. Use on the server when the same agent
249
- * identity handles many requests.
250
- *
251
- * Returns the cache rather than an `Agent` instance: the long-lived path
252
- * uses `Ablo({kind:'agent'})` over a WebSocket, while the `Agent` class
253
- * itself is the short-lived REST helper for AI SDK tool loops. The static
254
- * method lives here so everything agent-related sits under one namespace.
255
- *
256
- * ```ts
257
- * const session = Agent.session({ syncServerUrl, schema, issueToken });
258
- * const ablo = await session.getAgent({ userId, organizationId, surfaceClass });
259
- * ```
260
- */
261
- static session: typeof createAgentSession;
262
- /** The fully-qualified userId used on the wire: `agent:<agentId>`. */
263
- get userId(): string;
264
- /**
265
- * Extract the Agent instance from an AI SDK tool's
266
- * `experimental_context`. Use it inside a tool's `execute` function to
267
- * reach the agent without capturing it in a closure.
268
- *
269
- * ```ts
270
- * execute: async (args, { experimental_context }) => {
271
- * const perception = Agent.fromContext(experimental_context);
272
- * const check = await perception.checkFreshness('Slide', args.id, lastSeenAt);
273
- * // ...
274
- * }
275
- * ```
276
- *
277
- * Throws if the context is missing or doesn't contain an Agent.
278
- * @param ctx The `experimental_context` passed to the tool.
279
- * @param toolName Optional tool name for error messages.
280
- */
281
- static fromContext(ctx: unknown, toolName?: string): Agent;
282
- /**
283
- * A lenient variant of {@link fromContext} that returns `undefined` instead
284
- * of throwing when no agent is present in the context. Useful for tools
285
- * where awareness is optional, such as read-only tools that work without it.
286
- */
287
- static tryFromContext(ctx: unknown): Agent | undefined;
288
- /**
289
- * Announce this agent's presence/activity. Fire-and-forget — logs errors
290
- * but never throws (presence failures must not block the agent loop).
291
- *
292
- * If a `announcer` was provided (e.g. a connected SyncAgent), routes
293
- * through it to reuse the WebSocket. Otherwise falls back to REST POST.
294
- */
295
- announce(status: 'online' | 'away' | 'offline', activity?: Activity): Promise<void>;
296
- /**
297
- * Gather a snapshot of current activity by peers and format it as
298
- * natural-language context for injection into the next LLM prompt.
299
- */
300
- gather(options?: GatherOptions): Promise<GatherResult>;
301
- /**
302
- * Check if an entity was modified since `lastSeenAt`. Use before
303
- * executing a mutation to detect stale state.
304
- *
305
- * Returns `{ stale: true, summary }` when the entity changed — feed
306
- * `summary` back to the LLM as a tool result so it can adjust its plan.
307
- */
308
- checkFreshness(entityType: string, entityId: string, lastSeenAt: number): Promise<FreshnessCheck>;
309
- /**
310
- * Pull the org's presence, filter to claims targeting the given
311
- * entity (self-claims excluded). Advisory — returns empty on any
312
- * error so `checkFreshness` stays usable when the presence endpoint
313
- * is down. Case-insensitive match on entityType + entityId to absorb
314
- * PascalCase / lowercase divergence.
315
- */
316
- private fetchPendingClaimsFor;
317
- /**
318
- * Build a `prepareStep` hook for AI SDK's generateText / streamText /
319
- * ToolLoopAgent. Called before each step — injects a system message
320
- * summarizing what other agents are doing right now.
321
- *
322
- * ```ts
323
- * const result = await generateText({
324
- * // ...
325
- * prepareStep: perception.prepareStep({ maxChars: 1500 }),
326
- * });
327
- * ```
328
- */
329
- prepareStep<M extends AgentMessage = AgentMessage>(options?: PrepareStepOptions): (ctx: PrepareStepContext<M>) => Promise<PrepareStepResult<M> | undefined>;
330
- /**
331
- * Build an `onStepFinish` hook for AI SDK. Called after each step —
332
- * announces the agent's activity based on the tool calls that just ran.
333
- *
334
- * ```ts
335
- * const result = await generateText({
336
- * // ...
337
- * onStepFinish: perception.onStepFinish(),
338
- * });
339
- * ```
340
- */
341
- onStepFinish(options?: OnStepFinishOptions): (ctx: StepFinishContext) => Promise<void>;
342
- /**
343
- * Wrap an AI SDK tool to check entity freshness before executing. If the
344
- * entity was modified by another actor since the LLM last saw it, returns
345
- * a diff summary as the tool result instead of executing — the LLM adjusts
346
- * its plan rather than blindly overwriting.
347
- *
348
- * ```ts
349
- * tools: {
350
- * updateSlide: perception.wrapTool(
351
- * tool({ inputSchema: ..., execute: ... }),
352
- * { entityType: 'Slide', getEntityId: (args) => args.id },
353
- * ),
354
- * }
355
- * ```
356
- */
357
- wrapTool<TArgs, TResult, TTool extends AgentTool<TArgs, TResult>>(originalTool: TTool, config: WrapToolOptions<TArgs>): TTool;
358
- private fetchPresence;
359
- private formatPrompt;
360
- private request;
361
- }
362
- export declare namespace Agent {
363
- type Options = AgentOptions;
364
- type Context = AgentContext;
365
- type SessionOptions = import('./session.js').AgentSessionOptions;
366
- }