@abloatai/ablo 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -85
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +131 -147
  5. package/dist/Database.d.ts +54 -68
  6. package/dist/Database.js +97 -113
  7. package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
  8. package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
  9. package/dist/LazyReferenceCollection.d.ts +11 -15
  10. package/dist/LazyReferenceCollection.js +12 -16
  11. package/dist/Model.d.ts +37 -52
  12. package/dist/Model.js +46 -61
  13. package/dist/ModelRegistry.d.ts +21 -19
  14. package/dist/ModelRegistry.js +23 -27
  15. package/dist/NetworkMonitor.d.ts +5 -6
  16. package/dist/NetworkMonitor.js +5 -6
  17. package/dist/SyncClient.d.ts +112 -112
  18. package/dist/SyncClient.js +165 -172
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +9 -9
  22. package/dist/adapters/inMemoryStorage.js +9 -9
  23. package/dist/agent/Agent.d.ts +27 -32
  24. package/dist/agent/Agent.js +18 -19
  25. package/dist/agent/index.d.ts +4 -4
  26. package/dist/agent/index.js +5 -5
  27. package/dist/agent/session.d.ts +47 -44
  28. package/dist/agent/session.js +37 -48
  29. package/dist/agent/types.d.ts +26 -31
  30. package/dist/agent/types.js +6 -7
  31. package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
  32. package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
  33. package/dist/ai-sdk/coordinationContext.d.ts +46 -0
  34. package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
  35. package/dist/ai-sdk/index.d.ts +25 -22
  36. package/dist/ai-sdk/index.js +25 -22
  37. package/dist/ai-sdk/wrap.d.ts +6 -7
  38. package/dist/ai-sdk/wrap.js +1 -1
  39. package/dist/auth/credentialPolicy.d.ts +69 -74
  40. package/dist/auth/credentialPolicy.js +51 -56
  41. package/dist/auth/credentialSource.d.ts +6 -5
  42. package/dist/auth/credentialSource.js +9 -10
  43. package/dist/auth/index.d.ts +59 -58
  44. package/dist/auth/index.js +31 -37
  45. package/dist/auth/schemas.d.ts +5 -4
  46. package/dist/auth/schemas.js +5 -4
  47. package/dist/batching/index.d.ts +19 -21
  48. package/dist/batching/index.js +14 -17
  49. package/dist/cli.cjs +167 -119
  50. package/dist/client/Ablo.d.ts +73 -73
  51. package/dist/client/Ablo.js +125 -160
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +133 -38
  54. package/dist/client/auth.d.ts +47 -47
  55. package/dist/client/auth.js +108 -117
  56. package/dist/client/claimHeartbeatLoop.d.ts +50 -0
  57. package/dist/client/claimHeartbeatLoop.js +88 -0
  58. package/dist/client/consoleLogger.d.ts +5 -6
  59. package/dist/client/consoleLogger.js +5 -6
  60. package/dist/client/createInternalComponents.d.ts +14 -17
  61. package/dist/client/createInternalComponents.js +25 -30
  62. package/dist/client/createModelProxy.d.ts +130 -120
  63. package/dist/client/createModelProxy.js +152 -122
  64. package/dist/client/credentialEndpoint.d.ts +40 -42
  65. package/dist/client/credentialEndpoint.js +35 -36
  66. package/dist/client/functionalUpdate.d.ts +29 -27
  67. package/dist/client/functionalUpdate.js +21 -21
  68. package/dist/client/hostedEndpoints.d.ts +9 -12
  69. package/dist/client/hostedEndpoints.js +9 -12
  70. package/dist/client/httpClient.d.ts +57 -53
  71. package/dist/client/httpClient.js +29 -31
  72. package/dist/client/identity.d.ts +15 -20
  73. package/dist/client/identity.js +47 -58
  74. package/dist/client/modelRegistration.d.ts +5 -9
  75. package/dist/client/modelRegistration.js +67 -87
  76. package/dist/client/options.d.ts +134 -157
  77. package/dist/client/options.js +3 -7
  78. package/dist/client/registerDataSource.d.ts +9 -9
  79. package/dist/client/registerDataSource.js +15 -16
  80. package/dist/client/resourceTypes.d.ts +64 -75
  81. package/dist/client/resourceTypes.js +4 -10
  82. package/dist/client/schemaConfig.d.ts +31 -43
  83. package/dist/client/schemaConfig.js +38 -50
  84. package/dist/client/sessionMint.d.ts +16 -12
  85. package/dist/client/sessionMint.js +26 -31
  86. package/dist/client/validateAbloOptions.d.ts +12 -14
  87. package/dist/client/validateAbloOptions.js +8 -9
  88. package/dist/client/writeOptionsSchema.d.ts +18 -16
  89. package/dist/client/writeOptionsSchema.js +23 -20
  90. package/dist/client/wsMutationExecutor.d.ts +15 -20
  91. package/dist/client/wsMutationExecutor.js +17 -23
  92. package/dist/context.d.ts +6 -4
  93. package/dist/context.js +6 -4
  94. package/dist/coordination/index.d.ts +10 -8
  95. package/dist/coordination/index.js +14 -12
  96. package/dist/coordination/schema.d.ts +176 -128
  97. package/dist/coordination/schema.js +197 -133
  98. package/dist/coordination/trace.d.ts +9 -10
  99. package/dist/coordination/trace.js +13 -14
  100. package/dist/core/DatabaseManager.d.ts +5 -7
  101. package/dist/core/DatabaseManager.js +15 -19
  102. package/dist/core/QueryProcessor.d.ts +7 -9
  103. package/dist/core/QueryProcessor.js +22 -28
  104. package/dist/core/QueryView.d.ts +8 -8
  105. package/dist/core/QueryView.js +2 -2
  106. package/dist/core/StoreManager.d.ts +12 -14
  107. package/dist/core/StoreManager.js +21 -24
  108. package/dist/core/ViewRegistry.d.ts +5 -5
  109. package/dist/core/ViewRegistry.js +4 -4
  110. package/dist/core/index.d.ts +17 -12
  111. package/dist/core/index.js +32 -26
  112. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  113. package/dist/core/openIDBWithTimeout.js +42 -43
  114. package/dist/core/queryUtils.d.ts +45 -0
  115. package/dist/core/queryUtils.js +69 -0
  116. package/dist/core/storeContract.d.ts +63 -61
  117. package/dist/core/storeContract.js +8 -12
  118. package/dist/environment.d.ts +28 -0
  119. package/dist/environment.js +21 -0
  120. package/dist/errorCodes.d.ts +107 -99
  121. package/dist/errorCodes.js +131 -132
  122. package/dist/errors.d.ts +160 -166
  123. package/dist/errors.js +155 -158
  124. package/dist/index.d.ts +30 -27
  125. package/dist/index.js +89 -86
  126. package/dist/interfaces/index.d.ts +102 -113
  127. package/dist/interfaces/index.js +5 -4
  128. package/dist/keys/index.d.ts +27 -29
  129. package/dist/keys/index.js +41 -40
  130. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  131. package/dist/mutators/RecordingTransaction.js +31 -37
  132. package/dist/mutators/Transaction.d.ts +18 -26
  133. package/dist/mutators/Transaction.js +14 -20
  134. package/dist/mutators/UndoManager.d.ts +122 -131
  135. package/dist/mutators/UndoManager.js +145 -156
  136. package/dist/mutators/defineMutators.d.ts +23 -34
  137. package/dist/mutators/defineMutators.js +14 -20
  138. package/dist/mutators/inverseOp.d.ts +12 -15
  139. package/dist/mutators/inverseOp.js +12 -15
  140. package/dist/mutators/mutateActions.d.ts +10 -9
  141. package/dist/mutators/mutateActions.js +1 -1
  142. package/dist/mutators/readerActions.d.ts +9 -8
  143. package/dist/mutators/readerActions.js +2 -2
  144. package/dist/mutators/undoApply.d.ts +31 -27
  145. package/dist/mutators/undoApply.js +26 -24
  146. package/dist/policy/index.d.ts +5 -3
  147. package/dist/policy/index.js +5 -3
  148. package/dist/policy/types.d.ts +104 -100
  149. package/dist/policy/types.js +67 -66
  150. package/dist/query/client.d.ts +28 -23
  151. package/dist/query/client.js +45 -43
  152. package/dist/query/types.d.ts +37 -60
  153. package/dist/query/types.js +13 -33
  154. package/dist/react/AbloProvider.d.ts +1 -1
  155. package/dist/react/AbloProvider.js +2 -2
  156. package/dist/react/context.d.ts +25 -28
  157. package/dist/react/context.js +9 -10
  158. package/dist/react/index.d.ts +41 -42
  159. package/dist/react/index.js +37 -38
  160. package/dist/react/internalContext.d.ts +17 -19
  161. package/dist/react/useAblo.d.ts +23 -22
  162. package/dist/react/useAblo.js +16 -14
  163. package/dist/react/useCurrentUserId.d.ts +8 -7
  164. package/dist/react/useCurrentUserId.js +8 -7
  165. package/dist/react/useErrorListener.d.ts +7 -7
  166. package/dist/react/useErrorListener.js +10 -11
  167. package/dist/react/useMutationFailureListener.d.ts +8 -8
  168. package/dist/react/useMutationFailureListener.js +8 -8
  169. package/dist/react/useMutators.d.ts +11 -11
  170. package/dist/react/useMutators.js +3 -3
  171. package/dist/react/useReactive.js +2 -2
  172. package/dist/react/useSyncStatus.d.ts +4 -6
  173. package/dist/react/useUndoScope.d.ts +7 -9
  174. package/dist/react/useUndoScope.js +1 -1
  175. package/dist/schema/coordination.d.ts +21 -25
  176. package/dist/schema/coordination.js +21 -25
  177. package/dist/schema/ddl.d.ts +43 -39
  178. package/dist/schema/ddl.js +75 -68
  179. package/dist/schema/ddlLock.d.ts +20 -24
  180. package/dist/schema/ddlLock.js +18 -23
  181. package/dist/schema/diff.d.ts +99 -61
  182. package/dist/schema/diff.js +43 -34
  183. package/dist/schema/field.d.ts +37 -42
  184. package/dist/schema/field.js +35 -48
  185. package/dist/schema/generate.d.ts +12 -12
  186. package/dist/schema/generate.js +12 -12
  187. package/dist/schema/index.d.ts +2 -2
  188. package/dist/schema/index.js +21 -23
  189. package/dist/schema/model.d.ts +118 -143
  190. package/dist/schema/model.js +22 -33
  191. package/dist/schema/openapi.d.ts +10 -9
  192. package/dist/schema/openapi.js +5 -3
  193. package/dist/schema/queries.d.ts +29 -31
  194. package/dist/schema/queries.js +23 -25
  195. package/dist/schema/relation.d.ts +89 -99
  196. package/dist/schema/relation.js +13 -13
  197. package/dist/schema/residency.d.ts +16 -13
  198. package/dist/schema/residency.js +16 -13
  199. package/dist/schema/roles.d.ts +36 -43
  200. package/dist/schema/roles.js +31 -37
  201. package/dist/schema/schema.d.ts +33 -42
  202. package/dist/schema/schema.js +31 -32
  203. package/dist/schema/select.d.ts +13 -13
  204. package/dist/schema/select.js +13 -13
  205. package/dist/schema/serialize.d.ts +28 -31
  206. package/dist/schema/serialize.js +27 -31
  207. package/dist/schema/sugar.d.ts +17 -32
  208. package/dist/schema/sugar.js +14 -29
  209. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  210. package/dist/schema/syncDeltaRow.js +89 -0
  211. package/dist/schema/tenancy.d.ts +44 -46
  212. package/dist/schema/tenancy.js +46 -48
  213. package/dist/server/adapter.d.ts +58 -58
  214. package/dist/server/adapter.js +13 -14
  215. package/dist/server/commit.d.ts +60 -64
  216. package/dist/server/index.d.ts +9 -10
  217. package/dist/server/index.js +1 -1
  218. package/dist/server/readConfig.d.ts +70 -0
  219. package/dist/server/readConfig.js +8 -0
  220. package/dist/server/storageMode.d.ts +23 -0
  221. package/dist/server/storageMode.js +17 -0
  222. package/dist/source/adapter.d.ts +30 -25
  223. package/dist/source/adapter.js +10 -10
  224. package/dist/source/adapters/drizzle.d.ts +28 -23
  225. package/dist/source/adapters/drizzle.js +30 -25
  226. package/dist/source/adapters/kysely.d.ts +27 -25
  227. package/dist/source/adapters/kysely.js +24 -23
  228. package/dist/source/adapters/memory.d.ts +8 -7
  229. package/dist/source/adapters/memory.js +9 -8
  230. package/dist/source/adapters/prisma.d.ts +13 -12
  231. package/dist/source/adapters/prisma.js +22 -25
  232. package/dist/source/conformance.d.ts +18 -11
  233. package/dist/source/conformance.js +17 -11
  234. package/dist/source/connector.d.ts +31 -32
  235. package/dist/source/connector.js +28 -28
  236. package/dist/source/connectorProtocol.d.ts +160 -0
  237. package/dist/source/connectorProtocol.js +162 -0
  238. package/dist/source/contract.d.ts +26 -27
  239. package/dist/source/contract.js +28 -29
  240. package/dist/source/factory.d.ts +46 -58
  241. package/dist/source/factory.js +22 -27
  242. package/dist/source/index.d.ts +7 -9
  243. package/dist/source/index.js +12 -14
  244. package/dist/source/migrations.d.ts +9 -9
  245. package/dist/source/migrations.js +9 -9
  246. package/dist/source/next.d.ts +9 -10
  247. package/dist/source/next.js +6 -7
  248. package/dist/source/pushQueue.d.ts +69 -47
  249. package/dist/source/pushQueue.js +32 -28
  250. package/dist/source/signing.d.ts +46 -17
  251. package/dist/source/signing.js +28 -11
  252. package/dist/source/types.d.ts +121 -104
  253. package/dist/source/types.js +13 -14
  254. package/dist/stores/ObjectStore.d.ts +10 -11
  255. package/dist/stores/ObjectStore.js +11 -12
  256. package/dist/stores/ObjectStoreContract.d.ts +12 -15
  257. package/dist/stores/SyncActionStore.d.ts +7 -11
  258. package/dist/stores/SyncActionStore.js +13 -17
  259. package/dist/surface.d.ts +27 -20
  260. package/dist/surface.js +27 -20
  261. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  262. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  263. package/dist/sync/ConnectionManager.d.ts +39 -50
  264. package/dist/sync/ConnectionManager.js +55 -66
  265. package/dist/sync/NetworkProbe.d.ts +24 -29
  266. package/dist/sync/NetworkProbe.js +63 -69
  267. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  268. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  269. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  270. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  271. package/dist/sync/SyncWebSocket.d.ts +139 -165
  272. package/dist/sync/SyncWebSocket.js +191 -223
  273. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  274. package/dist/sync/awaitClaimGrant.js +11 -11
  275. package/dist/sync/bootstrapApply.d.ts +34 -24
  276. package/dist/sync/bootstrapApply.js +27 -19
  277. package/dist/sync/commitFrames.d.ts +21 -20
  278. package/dist/sync/commitFrames.js +18 -18
  279. package/dist/sync/createClaimStream.d.ts +23 -22
  280. package/dist/sync/createClaimStream.js +105 -23
  281. package/dist/sync/createPresenceStream.d.ts +19 -18
  282. package/dist/sync/createPresenceStream.js +25 -26
  283. package/dist/sync/createSnapshot.d.ts +12 -14
  284. package/dist/sync/createSnapshot.js +20 -26
  285. package/dist/sync/credentialLifecycle.d.ts +104 -104
  286. package/dist/sync/credentialLifecycle.js +140 -147
  287. package/dist/sync/deltaPipeline.d.ts +36 -34
  288. package/dist/sync/deltaPipeline.js +64 -65
  289. package/dist/sync/groupChange.d.ts +63 -61
  290. package/dist/sync/groupChange.js +74 -78
  291. package/dist/sync/heartbeat.d.ts +34 -33
  292. package/dist/sync/heartbeat.js +31 -31
  293. package/dist/sync/participants.d.ts +19 -19
  294. package/dist/sync/schemas.d.ts +3 -2
  295. package/dist/sync/schemas.js +14 -10
  296. package/dist/sync/syncCursor.d.ts +17 -21
  297. package/dist/sync/syncCursor.js +17 -21
  298. package/dist/sync/syncPlan.d.ts +28 -36
  299. package/dist/sync/syncPlan.js +18 -19
  300. package/dist/sync/syncPosition.d.ts +54 -49
  301. package/dist/sync/syncPosition.js +57 -52
  302. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  303. package/dist/sync/wsFrameHandlers.js +63 -67
  304. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  305. package/dist/testing/fixtures/bootstrap.js +12 -6
  306. package/dist/testing/fixtures/deltas.d.ts +30 -33
  307. package/dist/testing/fixtures/deltas.js +30 -33
  308. package/dist/testing/fixtures/models.d.ts +11 -10
  309. package/dist/testing/fixtures/models.js +11 -10
  310. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  311. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  312. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  313. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  314. package/dist/testing/helpers/wait.d.ts +13 -8
  315. package/dist/testing/helpers/wait.js +13 -8
  316. package/dist/testing/index.d.ts +3 -3
  317. package/dist/testing/index.js +2 -2
  318. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  319. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  320. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  321. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  322. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  323. package/dist/testing/mocks/MockSyncContext.js +15 -13
  324. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  325. package/dist/testing/mocks/MockSyncStore.js +11 -11
  326. package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
  327. package/dist/testing/mocks/MockWebSocket.js +22 -21
  328. package/dist/transactions/TransactionQueue.d.ts +181 -176
  329. package/dist/transactions/TransactionQueue.js +338 -350
  330. package/dist/transactions/TransactionStore.d.ts +6 -4
  331. package/dist/transactions/TransactionStore.js +6 -4
  332. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  333. package/dist/transactions/UnconfirmedWrites.js +104 -0
  334. package/dist/transactions/coalesceRules.d.ts +41 -17
  335. package/dist/transactions/coalesceRules.js +40 -17
  336. package/dist/transactions/commitPayload.d.ts +48 -52
  337. package/dist/transactions/commitPayload.js +48 -57
  338. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  339. package/dist/transactions/deltaConfirmation.js +37 -45
  340. package/dist/transactions/optimisticApply.d.ts +49 -0
  341. package/dist/transactions/optimisticApply.js +65 -0
  342. package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
  343. package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
  344. package/dist/types/global.d.ts +46 -41
  345. package/dist/types/global.js +20 -19
  346. package/dist/types/index.d.ts +71 -77
  347. package/dist/types/index.js +22 -22
  348. package/dist/types/modelData.d.ts +6 -8
  349. package/dist/types/modelData.js +5 -7
  350. package/dist/types/participant.d.ts +10 -11
  351. package/dist/types/participant.js +6 -8
  352. package/dist/types/streams.d.ts +208 -195
  353. package/dist/types/streams.js +7 -7
  354. package/dist/utils/asyncIterator.d.ts +25 -32
  355. package/dist/utils/asyncIterator.js +25 -32
  356. package/dist/utils/duration.d.ts +12 -15
  357. package/dist/utils/duration.js +12 -15
  358. package/dist/utils/mobxSetup.d.ts +53 -0
  359. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  360. package/dist/webhooks/events.d.ts +21 -16
  361. package/dist/webhooks/events.js +10 -8
  362. package/dist/webhooks/index.d.ts +5 -7
  363. package/dist/webhooks/index.js +5 -7
  364. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  365. package/dist/wire/delta.js +114 -0
  366. package/dist/wire/errorEnvelope.d.ts +30 -31
  367. package/dist/wire/errorEnvelope.js +34 -40
  368. package/dist/wire/frames.d.ts +79 -86
  369. package/dist/wire/frames.js +26 -33
  370. package/dist/wire/index.d.ts +14 -12
  371. package/dist/wire/index.js +30 -26
  372. package/dist/wire/listEnvelope.d.ts +16 -23
  373. package/dist/wire/listEnvelope.js +7 -6
  374. package/dist/wire/protocol.d.ts +25 -32
  375. package/dist/wire/protocol.js +25 -32
  376. package/dist/wire/protocolVersion.d.ts +44 -40
  377. package/dist/wire/protocolVersion.js +44 -40
  378. package/docs/coordination.md +59 -0
  379. package/package.json +11 -10
  380. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  381. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  382. package/dist/core/query-utils.d.ts +0 -34
  383. package/dist/core/query-utils.js +0 -59
  384. package/dist/schema/sync-delta-row.js +0 -103
  385. package/dist/schema/sync-delta-wire.js +0 -102
  386. package/dist/server/read-config.d.ts +0 -67
  387. package/dist/server/read-config.js +0 -8
  388. package/dist/server/storage-mode.d.ts +0 -8
  389. package/dist/server/storage-mode.js +0 -28
  390. package/dist/source/connector-protocol.d.ts +0 -159
  391. package/dist/source/connector-protocol.js +0 -161
  392. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  393. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  394. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  395. package/dist/transactions/mutation-error-handler.js +0 -39
  396. package/dist/transactions/optimistic.d.ts +0 -24
  397. package/dist/transactions/optimistic.js +0 -45
  398. package/dist/utils/mobx-setup.d.ts +0 -42
@@ -1,31 +1,29 @@
1
1
  /**
2
- * credentialEndpoint the endpoint-string shape of `apiKey`.
2
+ * Support for the endpoint-string form of `apiKey`.
3
3
  *
4
- * `Ablo({ schema, apiKey: '/api/ablo-session' })` point the client at your
5
- * session-mint route and the SDK owns the exchange: it POSTs the endpoint,
6
- * parses the minted token, keeps it fresh (the credential lifecycle), and
7
- * classifies failures onto the resolver tri-state. This is the Ably `authUrl`
8
- * / Liveblocks `authEndpoint` model the string form is the 95% case; the
9
- * function form of `apiKey` remains the escape hatch for custom headers,
4
+ * With `Ablo({ schema, apiKey: '/api/ablo-session' })`, you point the client at
5
+ * your own session-mint route and the client owns the exchange: it POSTs to the
6
+ * endpoint, parses the minted token, keeps it fresh, and classifies failures
7
+ * onto the resolver's three outcomes. The string form covers the common case;
8
+ * the function form of `apiKey` remains the escape hatch for custom headers,
10
9
  * bodies, or non-HTTP mints.
11
10
  *
12
- * Detection is by prefix: a string starting with `/`, `http://`, or
13
- * `https://` is an endpoint; anything else is a literal key. Real Ablo keys
14
- * are `sk_`/`pk_`/`ek_`/`rk_`-prefixed, so the two shapes cannot collide.
15
- * (`ABLO_API_KEY` env values are NEVER endpoint-detectedthe env var is
16
- * always a literal key; see `resolveApiKey`.)
11
+ * The form is detected by prefix: a string starting with `/`, `http://`, or
12
+ * `https://` is an endpoint, and anything else is a literal key. Ablo keys are
13
+ * prefixed (`sk_`/`pk_`/`ek_`/`rk_`), so the two shapes cannot collide. An
14
+ * `ABLO_API_KEY` environment value is never treated as an endpoint — it is
15
+ * always a literal key (see `resolveApiKey`).
17
16
  *
18
- * Wire contract — matches the `ablo init` scaffold route exactly:
17
+ * Wire contract:
19
18
  * POST <endpoint> (same-origin, `credentials: 'include'` so cookies flow)
20
- * → 200 `{ token, expiresAt? }` fresh short-lived `ek_`/`rk_`
21
- * → 200 `{ token: null }` or 401/403 the login itself is gone (sign out)
22
- * → anything else transient — retry, NEVER sign out
19
+ * → 200 `{ token, expiresAt? }` a fresh short-lived `ek_`/`rk_`
20
+ * → 200 `{ token: null }` or 401/403 the login itself is gone (sign out)
21
+ * → anything else transient — retry, do not sign out
23
22
  *
24
- * The tri-state mapping is the whole point of building this in: hand-written
25
- * thunks routinely get it wrong (mapping any `!res.ok` to `null` signs the
26
- * user out on a 500). Encoded here once, every consumer inherits the correct
27
- * terminal-vs-transient split (the Liveblocks `{ error: "forbidden" }` vs
28
- * retry contract, translated to HTTP statuses).
23
+ * The three-way mapping is the reason to build this in. Hand-written token
24
+ * fetchers routinely get it wrong mapping any non-OK response to `null` signs
25
+ * the user out on a 500. Encoded here once, every consumer inherits the correct
26
+ * split between a terminal sign-out and a transient retry.
29
27
  */
30
28
  /**
31
29
  * Is this `apiKey` string a session-mint endpoint rather than a literal key?
@@ -35,22 +33,23 @@ export function isCredentialEndpoint(value) {
35
33
  return value.startsWith('/') || /^https?:\/\//i.test(value);
36
34
  }
37
35
  /**
38
- * Build the resolver behind an endpoint-string `apiKey`. Conforms to the
39
- * `ApiKeySetter` contract end-to-end:
40
- * - resolves the minted token string on success,
41
- * - resolves `null` when the login is gone (401/403, or an explicit
42
- * `{ token: null }`) terminal, the client signs out,
43
- * - THROWS on anything transient (network failure, 5xx/429, malformed
44
- * response) the lifecycle backs off and retries, never signs out.
36
+ * Builds the resolver behind an endpoint-string `apiKey`. It follows the
37
+ * {@link ApiKeySetter} contract end to end:
38
+ * - resolves the minted token string on success;
39
+ * - resolves `null` when the login is gone (a 401 or 403, or an explicit
40
+ * `{ token: null }`) terminal, so the client signs out;
41
+ * - throws on anything transient (a network failure, a 5xx or 429, or a
42
+ * malformed response) so the lifecycle backs off and retries without
43
+ * signing out.
45
44
  *
46
- * A relative endpoint invoked server-side (Node fetch has no origin) throws
47
- * transient by contract, and `credentialLifecycle` already translates that
48
- * exact failure into an actionable "use an absolute URL server-side" warning.
45
+ * A relative endpoint invoked on a server (where `fetch` has no origin) throws,
46
+ * which is transient by contract; the credential lifecycle translates that exact
47
+ * failure into an actionable "use an absolute URL server-side" warning.
49
48
  */
50
49
  export function createEndpointCredentialResolver(endpoint) {
51
50
  return async () => {
52
- // fetch() rejections (offline, DNS, relative URL in Node) propagate as-is:
53
- // a throw IS the transient signal in the resolver contract.
51
+ // `fetch()` rejections (offline, DNS, a relative URL on a server) propagate
52
+ // as-is: a throw is the transient signal in the resolver contract.
54
53
  const res = await fetch(endpoint, {
55
54
  method: 'POST',
56
55
  credentials: 'include',
@@ -70,9 +69,9 @@ export function createEndpointCredentialResolver(endpoint) {
70
69
  catch {
71
70
  throw new Error(`credential endpoint ${endpoint} returned non-JSON — expected { token }`);
72
71
  }
73
- // Distinguish "explicitly signed out" ({ token: null }) from "not a mint
74
- // endpoint at all" (no `token` key misconfiguration must be LOUD and
75
- // transient, never a silent sign-out).
72
+ // Distinguish "explicitly signed out" (`{ token: null }`) from "not a mint
73
+ // endpoint at all" (no `token` key). A misconfiguration must fail loudly and
74
+ // transiently, never as a silent sign-out.
76
75
  if (typeof body !== 'object' || body === null || !('token' in body)) {
77
76
  throw new Error(`credential endpoint ${endpoint} returned no \`token\` field — expected { token }`);
78
77
  }
@@ -1,30 +1,30 @@
1
1
  /**
2
2
  * The functional update — `ablo.<model>.update(id, current => next)`.
3
3
  *
4
- * This is the "just works under contention" surface. The developer expresses
5
- * ONLY their intent — "given the latest row, here is the next state" — and the
6
- * SDK owns everything else: read the fresh row + its watermark, run the updater,
7
- * write it as a compare-and-swap against that watermark, and on any concurrent
8
- * write re-read recompute → retry. No claim, no identity, no transport
9
- * awareness, and no `stale_context` / `claim_*` error codes ever reach the
4
+ * This is the surface that just works under contention. You express only your
5
+ * intent — given the latest row, here is the next state — and the client does
6
+ * the rest: it reads the fresh row and its watermark, runs your updater, writes
7
+ * the result as a compare-and-swap against that watermark, and on any concurrent
8
+ * write it re-reads, recomputes, and retries. No claim, no identity, no transport
9
+ * awareness, and no `stale_context` or `claim_*` error codes ever reach the
10
10
  * caller. The write either lands or, at the extreme, throws a single
11
- * {@link AbloContentionError} after the reconcile budget is spent.
11
+ * {@link AbloContentionError} once the reconcile budget is spent.
12
12
  *
13
- * Correctness comes from the `readAt` watermark + `onStale: 'reject'`
14
- * (optimistic concurrency / compare-and-swap), NOT from participant identity
15
- * which is why it is immune to the shared-credential silent-clobber footgun and
16
- * behaves identically on both transports. The HTTP and WebSocket clients inject
17
- * the same two thunks ({@link ReconcileTransport}); the loop below is shared, so
18
- * the guarantee can never drift between them — only the mechanism differs.
13
+ * Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
14
+ * (optimistic concurrency, or compare-and-swap), not from participant identity.
15
+ * That is why it is immune to the shared-credential silent-overwrite hazard and
16
+ * behaves identically on both transports: the HTTP and WebSocket clients inject
17
+ * the same two functions ({@link ReconcileTransport}) into the shared loop below,
18
+ * so the guarantee cannot drift between them — only the mechanism differs.
19
19
  *
20
20
  * The mental model is React's `setState(prev => next)`: pass a function of the
21
- * current state, the runtime owns reconciliation.
21
+ * current state and the runtime owns reconciliation.
22
22
  */
23
23
  import { AbloContentionError } from '../errors.js';
24
24
  /**
25
25
  * The functional form of an update: given the freshly-read row, return the
26
- * fields to write. Return `null` / `undefined` to make NO write — a no-op the
27
- * caller decided on after seeing the latest state (e.g. "already done").
26
+ * fields to write. Return `null` or `undefined` to make no write — a no-op the
27
+ * caller chose after seeing the latest state (for example, "already done").
28
28
  */
29
29
  export type ModelUpdater<T> = (current: T) => Partial<T> | null | undefined | Promise<Partial<T> | null | undefined>;
30
30
  /** Tuning for the functional update's internal reconcile loop. */
@@ -41,30 +41,32 @@ export interface ContentionOptions {
41
41
  /** Reconcile rounds before a hot row is declared permanently contended. */
42
42
  export declare const DEFAULT_CONTENTION_RETRIES = 16;
43
43
  /**
44
- * Does this thrown error mean "another writer moved the row — re-read and
45
- * retry" rather than a genuine failure to surface? These are the optimistic-
46
- * concurrency signals the functional update reconciles against:
47
- * - `stale_context` — our `readAt` watermark was overtaken by a concurrent write
48
- * - `claim_lost` — a holder preempted us (e.g. a human under `humansOverwrite`)
44
+ * Reports whether a thrown error means "another writer moved the row — re-read
45
+ * and retry" rather than a genuine failure to surface. These are the
46
+ * optimistic-concurrency signals the functional update reconciles against:
47
+ * - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
48
+ * - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
49
49
  * - `claim_queued` — a holder is actively editing the row right now
50
50
  */
51
51
  export declare function isReconcilableConflict(err: unknown): boolean;
52
52
  /**
53
- * Transport-specific read/write the shared loop drives. Each client injects its
54
- * own pair — that's the ONLY thing that differs between HTTP and WebSocket.
53
+ * The transport-specific read and write that the shared loop drives. Each client
54
+ * injects its own pair — the one thing that differs between the HTTP and
55
+ * WebSocket transports.
55
56
  */
56
57
  export interface ReconcileTransport<T, R> {
57
58
  readonly model: string;
58
59
  readonly id: string;
59
- /** Read the latest row + its watermark from the authoritative store. */
60
+ /** Read the latest row and its watermark from the authoritative store. */
60
61
  readFresh: () => Promise<{
61
62
  readonly data: T | null | undefined;
62
63
  readonly stamp: number;
63
64
  }>;
64
65
  /**
65
- * Write the computed patch as a compare-and-swap against `readAt`. MUST throw
66
- * a reconcilable conflict (`stale_context` / `claim_*`) when the watermark was
67
- * overtaken — that rejection is what drives the next reconcile round.
66
+ * Write the computed patch as a compare-and-swap against `readAt`. It must
67
+ * throw a reconcilable conflict (`stale_context` or `claim_*`) when the
68
+ * watermark was overtaken — that rejection is what drives the next reconcile
69
+ * round.
68
70
  */
69
71
  writeNext: (patch: Partial<T>, readAt: number) => Promise<R>;
70
72
  }
@@ -1,34 +1,34 @@
1
1
  /**
2
2
  * The functional update — `ablo.<model>.update(id, current => next)`.
3
3
  *
4
- * This is the "just works under contention" surface. The developer expresses
5
- * ONLY their intent — "given the latest row, here is the next state" — and the
6
- * SDK owns everything else: read the fresh row + its watermark, run the updater,
7
- * write it as a compare-and-swap against that watermark, and on any concurrent
8
- * write re-read recompute → retry. No claim, no identity, no transport
9
- * awareness, and no `stale_context` / `claim_*` error codes ever reach the
4
+ * This is the surface that just works under contention. You express only your
5
+ * intent — given the latest row, here is the next state — and the client does
6
+ * the rest: it reads the fresh row and its watermark, runs your updater, writes
7
+ * the result as a compare-and-swap against that watermark, and on any concurrent
8
+ * write it re-reads, recomputes, and retries. No claim, no identity, no transport
9
+ * awareness, and no `stale_context` or `claim_*` error codes ever reach the
10
10
  * caller. The write either lands or, at the extreme, throws a single
11
- * {@link AbloContentionError} after the reconcile budget is spent.
11
+ * {@link AbloContentionError} once the reconcile budget is spent.
12
12
  *
13
- * Correctness comes from the `readAt` watermark + `onStale: 'reject'`
14
- * (optimistic concurrency / compare-and-swap), NOT from participant identity
15
- * which is why it is immune to the shared-credential silent-clobber footgun and
16
- * behaves identically on both transports. The HTTP and WebSocket clients inject
17
- * the same two thunks ({@link ReconcileTransport}); the loop below is shared, so
18
- * the guarantee can never drift between them — only the mechanism differs.
13
+ * Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
14
+ * (optimistic concurrency, or compare-and-swap), not from participant identity.
15
+ * That is why it is immune to the shared-credential silent-overwrite hazard and
16
+ * behaves identically on both transports: the HTTP and WebSocket clients inject
17
+ * the same two functions ({@link ReconcileTransport}) into the shared loop below,
18
+ * so the guarantee cannot drift between them — only the mechanism differs.
19
19
  *
20
20
  * The mental model is React's `setState(prev => next)`: pass a function of the
21
- * current state, the runtime owns reconciliation.
21
+ * current state and the runtime owns reconciliation.
22
22
  */
23
23
  import { AbloError, AbloNotFoundError, AbloStaleContextError, AbloClaimedError, AbloContentionError, } from '../errors.js';
24
24
  /** Reconcile rounds before a hot row is declared permanently contended. */
25
25
  export const DEFAULT_CONTENTION_RETRIES = 16;
26
26
  /**
27
- * Does this thrown error mean "another writer moved the row — re-read and
28
- * retry" rather than a genuine failure to surface? These are the optimistic-
29
- * concurrency signals the functional update reconciles against:
30
- * - `stale_context` — our `readAt` watermark was overtaken by a concurrent write
31
- * - `claim_lost` — a holder preempted us (e.g. a human under `humansOverwrite`)
27
+ * Reports whether a thrown error means "another writer moved the row — re-read
28
+ * and retry" rather than a genuine failure to surface. These are the
29
+ * optimistic-concurrency signals the functional update reconciles against:
30
+ * - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
31
+ * - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
32
32
  * - `claim_queued` — a holder is actively editing the row right now
33
33
  */
34
34
  export function isReconcilableConflict(err) {
@@ -82,6 +82,6 @@ export async function reconcileFunctionalUpdate(updater, options, transport) {
82
82
  cause: lastConflict,
83
83
  });
84
84
  }
85
- // Re-exported so call sites import the loop + its terminal error from one place;
86
- // the class itself lives with the rest of the hierarchy in `errors.ts`.
85
+ // Re-exported so call sites import the loop and its terminal error from one
86
+ // place; the class itself lives with the rest of the error hierarchy.
87
87
  export { AbloContentionError };
@@ -1,18 +1,15 @@
1
1
  /**
2
- * The canonical Ablo Cloud endpoint constants a ZERO-dependency leaf.
2
+ * The hosted Ablo Cloud endpoint constants, with no dependencies of their own.
3
3
  *
4
- * This is the single place the hosted API host is declared. Everything else
5
- * (`client/auth.ts` URL resolution, the CLI's `DEFAULT_URL`, the Data Source
6
- * connector's dial-out base, the generated OpenAPI `servers` entry, the
7
- * network probe's default) imports from here, so the next API-domain
8
- * migration is ONE edit — the `LEGACY_HOSTED_API_HOSTS` rewrite list in
9
- * `client/auth.ts` (four retired ablo.finance hosts) is proof such
10
- * migrations happen.
4
+ * This is the single place the hosted API host is declared. URL resolution, the
5
+ * CLI's default URL, the data-source connector's base, the generated OpenAPI
6
+ * server entry, and the network probe's default all import from here, so
7
+ * changing the API domain is a one-line edit.
11
8
  *
12
- * Kept dependency-free on purpose: `schema/openapi.ts` and `source/connector.ts`
13
- * consume it, and routing them through `client/auth.ts` would drag the error
14
- * registry + credential policy (and a `schema client errors →
15
- * coordination schema` cycle) into subpaths that are otherwise clean.
9
+ * These constants are kept dependency-free deliberately: several low-level
10
+ * modules consume them, and routing those modules through the auth layer would
11
+ * pull the error registry and credential policy into otherwise-clean paths and
12
+ * risk an import cycle.
16
13
  */
17
14
  /** The hosted API domain (no scheme). */
18
15
  export declare const ABLO_HOSTED_API_DOMAIN = "api.abloatai.com";
@@ -1,18 +1,15 @@
1
1
  /**
2
- * The canonical Ablo Cloud endpoint constants a ZERO-dependency leaf.
2
+ * The hosted Ablo Cloud endpoint constants, with no dependencies of their own.
3
3
  *
4
- * This is the single place the hosted API host is declared. Everything else
5
- * (`client/auth.ts` URL resolution, the CLI's `DEFAULT_URL`, the Data Source
6
- * connector's dial-out base, the generated OpenAPI `servers` entry, the
7
- * network probe's default) imports from here, so the next API-domain
8
- * migration is ONE edit — the `LEGACY_HOSTED_API_HOSTS` rewrite list in
9
- * `client/auth.ts` (four retired ablo.finance hosts) is proof such
10
- * migrations happen.
4
+ * This is the single place the hosted API host is declared. URL resolution, the
5
+ * CLI's default URL, the data-source connector's base, the generated OpenAPI
6
+ * server entry, and the network probe's default all import from here, so
7
+ * changing the API domain is a one-line edit.
11
8
  *
12
- * Kept dependency-free on purpose: `schema/openapi.ts` and `source/connector.ts`
13
- * consume it, and routing them through `client/auth.ts` would drag the error
14
- * registry + credential policy (and a `schema client errors →
15
- * coordination schema` cycle) into subpaths that are otherwise clean.
9
+ * These constants are kept dependency-free deliberately: several low-level
10
+ * modules consume them, and routing those modules through the auth layer would
11
+ * pull the error registry and credential policy into otherwise-clean paths and
12
+ * risk an import cycle.
16
13
  */
17
14
  /** The hosted API domain (no scheme). */
18
15
  export const ABLO_HOSTED_API_DOMAIN = 'api.abloatai.com';
@@ -1,26 +1,23 @@
1
1
  /**
2
- * `createAbloHttpClient` a STATELESS, typed HTTP client for server-side actors
3
- * (agents, workers, serverless), modelled on `@liveblocks/node` / the Stripe
4
- * server SDK / Netflix Conductor workers: it talks to Ablo over plain HTTP with
5
- * the credential as identity, and holds **no WebSocket and no connection state**.
2
+ * Creates a stateless, typed HTTP client for server-side actors — agents,
3
+ * workers, and serverless handlers. It talks to Ablo over plain request/response
4
+ * HTTP, uses the bearer credential as its identity, and holds no WebSocket and no
5
+ * connection state.
6
6
  *
7
- * Why this exists (docs/plans/agent-transport-event-driven.md): the stateful
8
- * `Ablo({ schema })` client is for INTERACTIVE participants it opens a
9
- * WebSocket and seeds its identity (userId/orgId) during the connect/bootstrap
10
- * step, then routes writes through a `TransactionQueue` that drops mutations
11
- * until that identity exists. A reactive agent has no socket, so that identity is
12
- * never seeded and writes drop. The proven fix (unanimous across Liveblocks,
13
- * Stripe, PlanetScale, Conductor, Better Auth) is NOT to de-socket the stateful
14
- * client — it's a separate stateless client where the credential carries identity
15
- * and the SERVER resolves it per request.
7
+ * This is the counterpart to the stateful {@link Ablo} client. The stateful
8
+ * client is for interactive participants: it opens a WebSocket, learns its
9
+ * identity (user id and organization id) during the connect-and-bootstrap step,
10
+ * and routes writes through a queue that waits for that identity. A server-side
11
+ * actor has no socket, so instead of reusing that machinery it uses this client,
12
+ * where the credential itself carries identity and the server resolves it on
13
+ * every request.
16
14
  *
17
- * Ablo already has that stateless surface: `Ablo({ schema: null })` returns the
18
- * protocol client (`createProtocolClient` `AbloApi`), which commits via
19
- * `POST /v1/commits` and reads via the HTTP `ApiClient`, authenticating with the
20
- * Bearer token on every request. Its only ergonomic gap is that model access is
21
- * string-keyed (`api.model('slides')`) rather than typed (`api.slides`). This
22
- * wraps it in a typed proxy facade so server code gets the SAME `client.<model>`
23
- * surface as the browser client — typed proxies, stateless transport.
15
+ * Under the hood this wraps the schema-agnostic protocol client that
16
+ * {@link createProtocolClient} returns in a typed proxy. The protocol client
17
+ * commits over `POST /v1/commits` and reads over HTTP, authenticating with the
18
+ * bearer token each time; its model access is string-keyed (`api.model('slides')`).
19
+ * The proxy gives server code the same typed `client.<model>` surface the
20
+ * stateful client offers, over stateless transport.
24
21
  */
25
22
  import { type AbloApiClientOptions } from './ApiClient.js';
26
23
  import type { CommitReceipt, CommitResource, HttpClaimApi, ModelRead, ModelReadOptions, CreateSessionParams, AbloSession } from './resourceTypes.js';
@@ -28,73 +25,80 @@ import type { ModelCreateParams, ModelDeleteParams, ServerReadOptions, ModelRetr
28
25
  import type { Schema, SchemaRecord, InferModel, InferCreate } from '../schema/schema.js';
29
26
  import type { ModelUpdater, ContentionOptions } from './functionalUpdate.js';
30
27
  export interface AbloHttpClientOptions<S extends SchemaRecord> extends Omit<AbloApiClientOptions, 'schema'> {
31
- /** The schema used for TYPING only (typed model proxies); never sent or used at runtime. */
28
+ /** The schema. Used only to type the model proxies; it is never sent over the wire or read at runtime. */
32
29
  readonly schema: Schema<S>;
33
30
  }
34
31
  /**
35
- * The per-model HTTP surface exactly what a stateless client can do over
36
- * request/response: reads (`retrieve`/`list`), writes (`create`/`update`/`delete`),
37
- * and the durable-lease claim plane (`claim` acquire/hold/release). It does NOT
38
- * include `get`/`getAll`/`getCount` (local synced-pool reads) or `onChange` (live
39
- * subscription); those need the stateful plane and are absent BY TYPE here.
32
+ * The per-model surface of the stateless HTTP client everything reachable over
33
+ * request/response: reads (`retrieve` and `list`), writes (`create`, `update`,
34
+ * and `delete`), and the durable-lease {@link HttpClaimApi | claim} plane for
35
+ * coordinated writes. It deliberately omits the stateful client's local-cache
36
+ * reads (`get`, `getAll`, `getCount`) and live subscriptions (`onChange`), which
37
+ * need a persistent socket; those are absent from the type, so reaching for one
38
+ * is a compile error rather than a runtime gap.
40
39
  *
41
- * Read-shape asymmetry (by design, not a gap): `retrieve(...)` returns a
42
- * `ModelRead<T>` envelope `{ data, stamp, claims }` the stateless client has no
43
- * local graph, so the watermark/claims the stateful client reads from its pool
44
- * must ride inline on the read (an agent needs the `stamp` to do a stale-guarded
45
- * write; there is no `snapshot()` to fetch it from). `list(...)` returns a bare `T[]`.
40
+ * The read shapes differ on purpose. `retrieve` returns a {@link ModelRead}
41
+ * envelope of `{ data, stamp, claims }`, because a stateless client keeps no local
42
+ * copy of the data: the watermark (`stamp`) and any active claims must travel
43
+ * inline on the read so a caller can follow it with a stale-guarded write. `list`
44
+ * returns a plain array.
46
45
  */
47
46
  export interface HttpModelClient<T, C = T> {
48
47
  retrieve(params: ModelRetrieveParams & ModelReadOptions): Promise<ModelRead<T>>;
49
48
  list(options?: ServerReadOptions<T>): Promise<T[]>;
50
49
  /**
51
- * Create a row and return it — the confirmed, authoritative server row (with
52
- * framework defaults), mirroring the WebSocket client's `create`. A re-create
53
- * of an existing caller-supplied id is idempotent and returns the EXISTING row.
50
+ * Creates a row and returns the confirmed server row, including any
51
+ * framework-applied defaults. Matches the stateful client's `create`. Passing an
52
+ * id that already exists is idempotent: the existing row is returned unchanged.
54
53
  */
55
54
  create(params: ModelCreateParams<T, C>): Promise<T>;
56
55
  update(params: ModelUpdateParams<C>): Promise<CommitReceipt>;
57
56
  /**
58
- * Functional update under contention — `update(id, current => next)`, the
59
- * `setState(prev => next)` of the data layer. The SDK reads the freshest row,
60
- * runs your updater, writes it as a compare-and-swap, and re-reads + re-runs on
61
- * any concurrent write. No claim, no identity, no conflict codes: the write
62
- * lands or throws `AbloContentionError`. Return `null`/`undefined` to skip.
57
+ * Updates a row with a function of its latest value — `update(id, current =>
58
+ * next)`, the data-layer equivalent of a `setState(prev => next)` reducer. The
59
+ * client reads the freshest row, runs your updater, and writes the result as a
60
+ * compare-and-swap against the row's watermark; if another write landed first it
61
+ * re-reads and re-runs. No claim or conflict handling is needed: the write either
62
+ * lands or throws `AbloContentionError` once its retry budget is spent. Return
63
+ * `null` or `undefined` from the updater to skip the write.
63
64
  */
64
65
  update(id: string, updater: ModelUpdater<T>, options?: ContentionOptions): Promise<CommitReceipt | undefined>;
65
66
  delete(params: ModelDeleteParams<T>): Promise<CommitReceipt>;
66
67
  claim: HttpClaimApi<T>;
67
68
  }
68
69
  /**
69
- * The honest type of the stateless HTTP client: typed model proxies (the
70
- * request/response subset) + `commits` + `dispose`. Reaching for a
71
- * stateful-only capability (`get`/`getAll`/`getCount`, `onChange`,
72
- * `claim.state`/`queue`/`reorder`) is a COMPILE error here, not a latent runtime
73
- * `undefined` — the type matches what the transport can actually do.
70
+ * The type of the stateless HTTP client: a typed {@link HttpModelClient} per
71
+ * schema model, plus `commits`, `dispose`, and the session-mint surface. It
72
+ * exposes only what request/response transport can do, so reaching for a
73
+ * stateful-only capability `get`, `getAll`, `getCount`, `onChange`, or the
74
+ * synchronous `claim.state`/`queue`/`reorder` reads is a compile error rather
75
+ * than a value that is `undefined` at runtime.
74
76
  */
75
77
  export type AbloHttpClient<S extends SchemaRecord> = {
76
78
  readonly [K in keyof S & string]: HttpModelClient<InferModel<Schema<S>, K>, InferCreate<Schema<S>, K>>;
77
79
  } & {
78
- /** Register `databaseUrl` when configured. Also runs lazily before the first request. */
80
+ /** Runs one-time setup, such as registering a configured `databaseUrl` data source, before the client is used. It also runs lazily ahead of the first request, so calling it yourself is optional. */
79
81
  ready(): Promise<void>;
80
82
  readonly commits: CommitResource;
81
83
  dispose(): Promise<void>;
82
- /** Resolve the bearer credential this client authenticates with (see `AbloApi.getAuthToken`). */
84
+ /** Resolves the bearer credential this client authenticates with, or `null` if none is set. */
83
85
  getAuthToken(): Promise<string | null>;
84
86
  /**
85
- * Mint a short-lived scoped session (Stripe ephemeral-key shape). Minting is a
86
- * stateless control-plane call, so unlike `get`/`getAll`/`onChange` it IS
87
- * available on the HTTP client. `{ user }` `ek_`, `{ agent, can }` `rk_`.
87
+ * Mints a short-lived, scoped session token. Minting is itself a stateless
88
+ * request, so it is available here even though the local-cache reads are not.
89
+ * Pass `{ user }` to mint an end-user key (`ek_`) or `{ agent, can }` to mint a
90
+ * scoped agent key (`rk_`). See {@link CreateSessionParams}.
88
91
  */
89
92
  readonly sessions: {
90
93
  create(params: CreateSessionParams<S>): Promise<AbloSession>;
91
94
  };
92
- /** String-keyed model accessor (for dynamic model names). */
95
+ /** Looks up a model client by name, for when the model name is only known at runtime. */
93
96
  model<T = Record<string, unknown>>(name: string): HttpModelClient<T>;
94
97
  };
95
98
  /**
96
- * Stateless, typed HTTP client. Each `client.<model>` resolves to the protocol
97
- * client's `model(name)`; `commits`, `dispose`, etc. pass through. No socket is
98
- * ever opened; identity is the Bearer credential.
99
+ * Builds the stateless, typed HTTP client. Each `client.<model>` resolves to the
100
+ * protocol client's model accessor, while `commits`, `dispose`, and the other
101
+ * protocol members pass through unchanged. No socket is ever opened; the bearer
102
+ * credential is the identity.
99
103
  */
100
104
  export declare function createAbloHttpClient<S extends SchemaRecord>(options: AbloHttpClientOptions<S>): AbloHttpClient<S>;
@@ -1,34 +1,31 @@
1
1
  /**
2
- * `createAbloHttpClient` a STATELESS, typed HTTP client for server-side actors
3
- * (agents, workers, serverless), modelled on `@liveblocks/node` / the Stripe
4
- * server SDK / Netflix Conductor workers: it talks to Ablo over plain HTTP with
5
- * the credential as identity, and holds **no WebSocket and no connection state**.
2
+ * Creates a stateless, typed HTTP client for server-side actors — agents,
3
+ * workers, and serverless handlers. It talks to Ablo over plain request/response
4
+ * HTTP, uses the bearer credential as its identity, and holds no WebSocket and no
5
+ * connection state.
6
6
  *
7
- * Why this exists (docs/plans/agent-transport-event-driven.md): the stateful
8
- * `Ablo({ schema })` client is for INTERACTIVE participants it opens a
9
- * WebSocket and seeds its identity (userId/orgId) during the connect/bootstrap
10
- * step, then routes writes through a `TransactionQueue` that drops mutations
11
- * until that identity exists. A reactive agent has no socket, so that identity is
12
- * never seeded and writes drop. The proven fix (unanimous across Liveblocks,
13
- * Stripe, PlanetScale, Conductor, Better Auth) is NOT to de-socket the stateful
14
- * client — it's a separate stateless client where the credential carries identity
15
- * and the SERVER resolves it per request.
7
+ * This is the counterpart to the stateful {@link Ablo} client. The stateful
8
+ * client is for interactive participants: it opens a WebSocket, learns its
9
+ * identity (user id and organization id) during the connect-and-bootstrap step,
10
+ * and routes writes through a queue that waits for that identity. A server-side
11
+ * actor has no socket, so instead of reusing that machinery it uses this client,
12
+ * where the credential itself carries identity and the server resolves it on
13
+ * every request.
16
14
  *
17
- * Ablo already has that stateless surface: `Ablo({ schema: null })` returns the
18
- * protocol client (`createProtocolClient` `AbloApi`), which commits via
19
- * `POST /v1/commits` and reads via the HTTP `ApiClient`, authenticating with the
20
- * Bearer token on every request. Its only ergonomic gap is that model access is
21
- * string-keyed (`api.model('slides')`) rather than typed (`api.slides`). This
22
- * wraps it in a typed proxy facade so server code gets the SAME `client.<model>`
23
- * surface as the browser client — typed proxies, stateless transport.
15
+ * Under the hood this wraps the schema-agnostic protocol client that
16
+ * {@link createProtocolClient} returns in a typed proxy. The protocol client
17
+ * commits over `POST /v1/commits` and reads over HTTP, authenticating with the
18
+ * bearer token each time; its model access is string-keyed (`api.model('slides')`).
19
+ * The proxy gives server code the same typed `client.<model>` surface the
20
+ * stateful client offers, over stateless transport.
24
21
  */
25
22
  import { createProtocolClient, } from './ApiClient.js';
26
23
  /**
27
- * Members of the underlying `AbloApi` that pass straight through the facade.
28
- * Deliberately EXCLUDES the resource names that collide with common schema model
29
- * names — `tasks`, `claims`, `capabilities`, `agent` — so `client.tasks` resolves
30
- * to the schema model `tasks`, not the protocol `TaskResource`. Only lifecycle +
31
- * the genuinely-protocol methods an agent uses pass through.
24
+ * Names on the underlying protocol client that pass straight through the proxy.
25
+ * This set intentionally leaves out names that collide with common schema models —
26
+ * `tasks`, `claims`, `capabilities`, `agent` — so that `client.tasks` resolves to
27
+ * the schema model named `tasks` rather than a protocol resource. Only lifecycle
28
+ * methods and the genuinely protocol-level members belong here.
32
29
  */
33
30
  const PROTOCOL_MEMBERS = new Set([
34
31
  'ready',
@@ -41,9 +38,10 @@ const PROTOCOL_MEMBERS = new Set([
41
38
  'sessions',
42
39
  ]);
43
40
  /**
44
- * Stateless, typed HTTP client. Each `client.<model>` resolves to the protocol
45
- * client's `model(name)`; `commits`, `dispose`, etc. pass through. No socket is
46
- * ever opened; identity is the Bearer credential.
41
+ * Builds the stateless, typed HTTP client. Each `client.<model>` resolves to the
42
+ * protocol client's model accessor, while `commits`, `dispose`, and the other
43
+ * protocol members pass through unchanged. No socket is ever opened; the bearer
44
+ * credential is the identity.
47
45
  */
48
46
  export function createAbloHttpClient(options) {
49
47
  // The schema is type-level only; the protocol client is schema-agnostic.
@@ -62,8 +60,8 @@ export function createAbloHttpClient(options) {
62
60
  return api.model(prop);
63
61
  },
64
62
  });
65
- // One boundary cast — and now an HONEST one: `AbloHttpClient<S>` declares only
66
- // what `api.model()` + the passed-through protocol members actually implement,
67
- // so there is no method on this type that fails at runtime.
63
+ // A single boundary cast. `AbloHttpClient<S>` declares only what the model
64
+ // accessor and the passed-through protocol members actually implement, so no
65
+ // method on this type is missing at runtime.
68
66
  return facade;
69
67
  }