@abloatai/ablo 0.36.0 → 0.37.1

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 (597) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +55 -2014
  3. package/NOTICE +2 -2
  4. package/README.md +45 -63
  5. package/assets/banner.png +0 -0
  6. package/dist/auth.d.ts +2 -0
  7. package/dist/auth.d.ts.map +1 -0
  8. package/dist/auth.js +2 -0
  9. package/dist/auth.js.map +1 -0
  10. package/dist/client.d.ts +3 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +3 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/coordination.d.ts +2 -0
  15. package/dist/coordination.d.ts.map +1 -0
  16. package/dist/coordination.js +2 -0
  17. package/dist/coordination.js.map +1 -0
  18. package/dist/index.d.ts +3 -114
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -163
  21. package/dist/index.js.map +1 -0
  22. package/dist/react.d.ts +4 -0
  23. package/dist/react.d.ts.map +1 -0
  24. package/dist/react.js +3 -0
  25. package/dist/react.js.map +1 -0
  26. package/dist/schema.d.ts +2 -0
  27. package/dist/schema.d.ts.map +1 -0
  28. package/dist/schema.js +2 -0
  29. package/dist/schema.js.map +1 -0
  30. package/dist/server.d.ts +2 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +2 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/source-conformance.d.ts +2 -0
  35. package/dist/source-conformance.d.ts.map +1 -0
  36. package/dist/source-conformance.js +2 -0
  37. package/dist/source-conformance.js.map +1 -0
  38. package/dist/source-drizzle.d.ts +2 -0
  39. package/dist/source-drizzle.d.ts.map +1 -0
  40. package/dist/source-drizzle.js +2 -0
  41. package/dist/source-drizzle.js.map +1 -0
  42. package/dist/source-kysely.d.ts +2 -0
  43. package/dist/source-kysely.d.ts.map +1 -0
  44. package/dist/source-kysely.js +2 -0
  45. package/dist/source-kysely.js.map +1 -0
  46. package/dist/source-next.d.ts +2 -0
  47. package/dist/source-next.d.ts.map +1 -0
  48. package/dist/source-next.js +2 -0
  49. package/dist/source-next.js.map +1 -0
  50. package/dist/source.d.ts +2 -0
  51. package/dist/source.d.ts.map +1 -0
  52. package/dist/source.js +2 -0
  53. package/dist/source.js.map +1 -0
  54. package/dist/wire.d.ts +2 -0
  55. package/dist/wire.d.ts.map +1 -0
  56. package/dist/wire.js +2 -0
  57. package/dist/wire.js.map +1 -0
  58. package/docs/agents.md +1 -1
  59. package/docs/api-keys.md +7 -6
  60. package/docs/api.md +10 -10
  61. package/docs/client-behavior.md +5 -5
  62. package/docs/coordination.md +52 -62
  63. package/docs/data-sources.md +1 -1
  64. package/docs/examples/agent-human.md +4 -4
  65. package/docs/examples/ai-sdk-tool.md +1 -1
  66. package/docs/examples/existing-python-backend.md +15 -4
  67. package/docs/examples/nextjs.md +27 -6
  68. package/docs/examples/server-agent.md +2 -2
  69. package/docs/how-it-works.md +4 -4
  70. package/docs/identity.md +2 -1
  71. package/docs/integration-guide.md +24 -13
  72. package/docs/internal/README.md +18 -0
  73. package/docs/internal/agent-fleet-coordination-design.md +171 -0
  74. package/docs/internal/agent-orchestration.md +58 -0
  75. package/docs/internal/commit-identifiers.md +91 -0
  76. package/docs/internal/concurrency-open-decisions.md +37 -0
  77. package/docs/internal/data-source-reverse-channel.md +150 -0
  78. package/docs/internal/per-field-conflict-detection.md +165 -0
  79. package/docs/internal/postgres-replication.md +64 -0
  80. package/docs/internal/serializable-schema.md +119 -0
  81. package/docs/internal/structure.md +32 -0
  82. package/docs/mcp.md +2 -2
  83. package/docs/migration.md +3 -3
  84. package/docs/quickstart.md +2 -2
  85. package/docs/react.md +5 -5
  86. package/docs/schema-contract.md +3 -3
  87. package/docs/sessions.md +91 -37
  88. package/examples/README.md +2 -2
  89. package/examples/data-source/README.md +1 -1
  90. package/examples/data-source/ablo-driver.ts +1 -1
  91. package/examples/data-source/customer-server.ts +1 -1
  92. package/examples/data-source/run.ts +1 -1
  93. package/examples/data-source/schema.ts +1 -1
  94. package/examples/quickstart.ts +2 -2
  95. package/llms.txt +8 -8
  96. package/package.json +63 -166
  97. package/bin/ablo.cjs +0 -39
  98. package/dist/BaseSyncedStore.d.ts +0 -843
  99. package/dist/BaseSyncedStore.js +0 -1971
  100. package/dist/Database.d.ts +0 -323
  101. package/dist/Database.js +0 -1502
  102. package/dist/InstanceCache.d.ts +0 -237
  103. package/dist/InstanceCache.js +0 -1166
  104. package/dist/LazyReferenceCollection.d.ts +0 -177
  105. package/dist/LazyReferenceCollection.js +0 -461
  106. package/dist/Model.d.ts +0 -454
  107. package/dist/Model.js +0 -919
  108. package/dist/ModelRegistry.d.ts +0 -225
  109. package/dist/ModelRegistry.js +0 -539
  110. package/dist/NetworkMonitor.d.ts +0 -28
  111. package/dist/NetworkMonitor.js +0 -79
  112. package/dist/RuntimeContext.d.ts +0 -52
  113. package/dist/RuntimeContext.js +0 -80
  114. package/dist/SyncClient.d.ts +0 -541
  115. package/dist/SyncClient.js +0 -2202
  116. package/dist/adapters/alwaysOnline.d.ts +0 -14
  117. package/dist/adapters/alwaysOnline.js +0 -17
  118. package/dist/adapters/inMemoryStorage.d.ts +0 -31
  119. package/dist/adapters/inMemoryStorage.js +0 -110
  120. package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
  121. package/dist/ai-sdk/coordinatedTool.js +0 -134
  122. package/dist/ai-sdk/coordinationContext.d.ts +0 -46
  123. package/dist/ai-sdk/coordinationContext.js +0 -106
  124. package/dist/ai-sdk/index.d.ts +0 -121
  125. package/dist/ai-sdk/index.js +0 -121
  126. package/dist/ai-sdk/wrap.d.ts +0 -65
  127. package/dist/ai-sdk/wrap.js +0 -39
  128. package/dist/auth/index.d.ts +0 -1
  129. package/dist/auth/index.js +0 -8
  130. package/dist/batching/index.d.ts +0 -55
  131. package/dist/batching/index.js +0 -147
  132. package/dist/client/Ablo.d.ts +0 -231
  133. package/dist/client/Ablo.js +0 -160
  134. package/dist/client/abloClient.d.ts +0 -309
  135. package/dist/client/abloClient.js +0 -13
  136. package/dist/client/clientPrelude.d.ts +0 -52
  137. package/dist/client/clientPrelude.js +0 -60
  138. package/dist/client/consoleLogger.d.ts +0 -35
  139. package/dist/client/consoleLogger.js +0 -44
  140. package/dist/client/coreClient.d.ts +0 -60
  141. package/dist/client/coreClient.js +0 -118
  142. package/dist/client/createInternalComponents.d.ts +0 -50
  143. package/dist/client/createInternalComponents.js +0 -98
  144. package/dist/client/createModelProxy.d.ts +0 -248
  145. package/dist/client/createModelProxy.js +0 -884
  146. package/dist/client/humans.d.ts +0 -69
  147. package/dist/client/humans.js +0 -78
  148. package/dist/client/modelRegistration.d.ts +0 -10
  149. package/dist/client/modelRegistration.js +0 -312
  150. package/dist/client/options.d.ts +0 -461
  151. package/dist/client/options.js +0 -7
  152. package/dist/client/reactiveEngine.d.ts +0 -53
  153. package/dist/client/reactiveEngine.js +0 -688
  154. package/dist/client/resourceTypes.d.ts +0 -12
  155. package/dist/client/resourceTypes.js +0 -10
  156. package/dist/client/schemaConfig.d.ts +0 -44
  157. package/dist/client/schemaConfig.js +0 -185
  158. package/dist/client/storeCluster.d.ts +0 -47
  159. package/dist/client/storeCluster.js +0 -118
  160. package/dist/client/storeLifecycle.d.ts +0 -61
  161. package/dist/client/storeLifecycle.js +0 -231
  162. package/dist/client/validateAbloOptions.d.ts +0 -42
  163. package/dist/client/validateAbloOptions.js +0 -43
  164. package/dist/client/wsMutationExecutor.d.ts +0 -27
  165. package/dist/client/wsMutationExecutor.js +0 -72
  166. package/dist/context.d.ts +0 -42
  167. package/dist/context.js +0 -81
  168. package/dist/coordination/ClaimLog.d.ts +0 -26
  169. package/dist/coordination/ClaimLog.js +0 -32
  170. package/dist/coordination/index.d.ts +0 -1
  171. package/dist/coordination/index.js +0 -8
  172. package/dist/core/index.d.ts +0 -33
  173. package/dist/core/index.js +0 -48
  174. package/dist/docs/catalog.d.ts +0 -72
  175. package/dist/docs/catalog.js +0 -230
  176. package/dist/docs/index.d.ts +0 -10
  177. package/dist/docs/index.js +0 -10
  178. package/dist/environment.d.ts +0 -1
  179. package/dist/environment.js +0 -8
  180. package/dist/interfaces/index.d.ts +0 -311
  181. package/dist/interfaces/index.js +0 -9
  182. package/dist/keys/index.d.ts +0 -1
  183. package/dist/keys/index.js +0 -8
  184. package/dist/mutators/RecordingMutation.d.ts +0 -36
  185. package/dist/mutators/RecordingMutation.js +0 -182
  186. package/dist/mutators/Transaction.d.ts +0 -40
  187. package/dist/mutators/Transaction.js +0 -58
  188. package/dist/mutators/UndoManager.d.ts +0 -258
  189. package/dist/mutators/UndoManager.js +0 -658
  190. package/dist/mutators/defineMutators.d.ts +0 -60
  191. package/dist/mutators/defineMutators.js +0 -18
  192. package/dist/mutators/inverseOp.d.ts +0 -126
  193. package/dist/mutators/inverseOp.js +0 -71
  194. package/dist/mutators/mutateActions.d.ts +0 -45
  195. package/dist/mutators/mutateActions.js +0 -105
  196. package/dist/mutators/readerActions.d.ts +0 -33
  197. package/dist/mutators/readerActions.js +0 -57
  198. package/dist/mutators/undoApply.d.ts +0 -51
  199. package/dist/mutators/undoApply.js +0 -117
  200. package/dist/policy/index.d.ts +0 -21
  201. package/dist/policy/index.js +0 -20
  202. package/dist/query/QueryProcessor.d.ts +0 -75
  203. package/dist/query/QueryProcessor.js +0 -255
  204. package/dist/query/client.d.ts +0 -64
  205. package/dist/query/client.js +0 -138
  206. package/dist/query/types.d.ts +0 -85
  207. package/dist/query/types.js +0 -16
  208. package/dist/react/AbloProvider.d.ts +0 -242
  209. package/dist/react/AbloProvider.js +0 -458
  210. package/dist/react/ClientSideSuspense.d.ts +0 -36
  211. package/dist/react/ClientSideSuspense.js +0 -17
  212. package/dist/react/DefaultFallback.d.ts +0 -24
  213. package/dist/react/DefaultFallback.js +0 -43
  214. package/dist/react/context.d.ts +0 -55
  215. package/dist/react/context.js +0 -29
  216. package/dist/react/createAbloReact.d.ts +0 -56
  217. package/dist/react/createAbloReact.js +0 -51
  218. package/dist/react/index.d.ts +0 -62
  219. package/dist/react/index.js +0 -69
  220. package/dist/react/internalContext.d.ts +0 -33
  221. package/dist/react/internalContext.js +0 -3
  222. package/dist/react/useAblo.d.ts +0 -82
  223. package/dist/react/useAblo.js +0 -120
  224. package/dist/react/useCurrentUserId.d.ts +0 -22
  225. package/dist/react/useCurrentUserId.js +0 -34
  226. package/dist/react/useErrorListener.d.ts +0 -20
  227. package/dist/react/useErrorListener.js +0 -38
  228. package/dist/react/useMutationFailureListener.d.ts +0 -26
  229. package/dist/react/useMutationFailureListener.js +0 -38
  230. package/dist/react/useMutators.d.ts +0 -56
  231. package/dist/react/useMutators.js +0 -84
  232. package/dist/react/useReactive.d.ts +0 -35
  233. package/dist/react/useReactive.js +0 -123
  234. package/dist/react/useSyncStatus.d.ts +0 -59
  235. package/dist/react/useSyncStatus.js +0 -76
  236. package/dist/react/useUndoScope.d.ts +0 -34
  237. package/dist/react/useUndoScope.js +0 -81
  238. package/dist/schema/coordination.d.ts +0 -112
  239. package/dist/schema/coordination.js +0 -133
  240. package/dist/schema/ddl.d.ts +0 -97
  241. package/dist/schema/ddl.js +0 -491
  242. package/dist/schema/ddlLock.d.ts +0 -35
  243. package/dist/schema/ddlLock.js +0 -46
  244. package/dist/schema/diff.d.ts +0 -225
  245. package/dist/schema/diff.js +0 -289
  246. package/dist/schema/generate.d.ts +0 -19
  247. package/dist/schema/generate.js +0 -86
  248. package/dist/schema/index.d.ts +0 -42
  249. package/dist/schema/index.js +0 -80
  250. package/dist/schema/queries.d.ts +0 -201
  251. package/dist/schema/queries.js +0 -144
  252. package/dist/schema/select.d.ts +0 -40
  253. package/dist/schema/select.js +0 -90
  254. package/dist/schema/serialize.d.ts +0 -115
  255. package/dist/schema/serialize.js +0 -265
  256. package/dist/schema/sugar.d.ts +0 -109
  257. package/dist/schema/sugar.js +0 -83
  258. package/dist/schema/syncDeltaRow.d.ts +0 -6
  259. package/dist/schema/syncDeltaRow.js +0 -6
  260. package/dist/server/adapter.d.ts +0 -173
  261. package/dist/server/adapter.js +0 -18
  262. package/dist/server/commit.d.ts +0 -107
  263. package/dist/server/commit.js +0 -1
  264. package/dist/server/index.d.ts +0 -14
  265. package/dist/server/index.js +0 -2
  266. package/dist/server/readConfig.d.ts +0 -80
  267. package/dist/server/readConfig.js +0 -8
  268. package/dist/server/storageMode.d.ts +0 -23
  269. package/dist/server/storageMode.js +0 -17
  270. package/dist/source/adapter.d.ts +0 -83
  271. package/dist/source/adapter.js +0 -24
  272. package/dist/source/adapters/drizzle.d.ts +0 -48
  273. package/dist/source/adapters/drizzle.js +0 -219
  274. package/dist/source/adapters/kysely.d.ts +0 -42
  275. package/dist/source/adapters/kysely.js +0 -205
  276. package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
  277. package/dist/source/adapters/kyselyMutationCore.js +0 -125
  278. package/dist/source/adapters/memory.d.ts +0 -13
  279. package/dist/source/adapters/memory.js +0 -130
  280. package/dist/source/adapters/prisma.d.ts +0 -63
  281. package/dist/source/adapters/prisma.js +0 -202
  282. package/dist/source/conformance.d.ts +0 -37
  283. package/dist/source/conformance.js +0 -215
  284. package/dist/source/connector.d.ts +0 -95
  285. package/dist/source/connector.js +0 -266
  286. package/dist/source/connectorProtocol.d.ts +0 -154
  287. package/dist/source/connectorProtocol.js +0 -163
  288. package/dist/source/contract.d.ts +0 -195
  289. package/dist/source/contract.js +0 -164
  290. package/dist/source/factory.d.ts +0 -92
  291. package/dist/source/factory.js +0 -286
  292. package/dist/source/idempotency.d.ts +0 -61
  293. package/dist/source/idempotency.js +0 -144
  294. package/dist/source/index.d.ts +0 -23
  295. package/dist/source/index.js +0 -30
  296. package/dist/source/migrations.d.ts +0 -21
  297. package/dist/source/migrations.js +0 -103
  298. package/dist/source/next.d.ts +0 -32
  299. package/dist/source/next.js +0 -25
  300. package/dist/source/pushQueue.d.ts +0 -134
  301. package/dist/source/pushQueue.js +0 -256
  302. package/dist/source/signing.d.ts +0 -92
  303. package/dist/source/signing.js +0 -162
  304. package/dist/source/types.d.ts +0 -401
  305. package/dist/source/types.js +0 -59
  306. package/dist/storeContract.d.ts +0 -145
  307. package/dist/storeContract.js +0 -12
  308. package/dist/stores/DatabaseManager.d.ts +0 -107
  309. package/dist/stores/DatabaseManager.js +0 -388
  310. package/dist/stores/ObjectStore.d.ts +0 -115
  311. package/dist/stores/ObjectStore.js +0 -393
  312. package/dist/stores/ObjectStoreContract.d.ts +0 -38
  313. package/dist/stores/ObjectStoreContract.js +0 -1
  314. package/dist/stores/StoreManager.d.ts +0 -114
  315. package/dist/stores/StoreManager.js +0 -304
  316. package/dist/stores/SyncActionStore.d.ts +0 -99
  317. package/dist/stores/SyncActionStore.js +0 -506
  318. package/dist/stores/openIDBWithTimeout.d.ts +0 -65
  319. package/dist/stores/openIDBWithTimeout.js +0 -153
  320. package/dist/stores/syncAction.d.ts +0 -26
  321. package/dist/stores/syncAction.js +0 -16
  322. package/dist/surface.d.ts +0 -36
  323. package/dist/surface.js +0 -75
  324. package/dist/sync/BootstrapFetcher.d.ts +0 -284
  325. package/dist/sync/BootstrapFetcher.js +0 -964
  326. package/dist/sync/ConnectionManager.d.ts +0 -8
  327. package/dist/sync/ConnectionManager.js +0 -8
  328. package/dist/sync/OnDemandLoader.d.ts +0 -231
  329. package/dist/sync/OnDemandLoader.js +0 -743
  330. package/dist/sync/SubscriptionManager.d.ts +0 -159
  331. package/dist/sync/SubscriptionManager.js +0 -243
  332. package/dist/sync/SyncWebSocket.d.ts +0 -173
  333. package/dist/sync/SyncWebSocket.js +0 -438
  334. package/dist/sync/awaitClaimGrant.d.ts +0 -6
  335. package/dist/sync/awaitClaimGrant.js +0 -6
  336. package/dist/sync/bootstrapApply.d.ts +0 -73
  337. package/dist/sync/bootstrapApply.js +0 -73
  338. package/dist/sync/commitFrames.d.ts +0 -8
  339. package/dist/sync/commitFrames.js +0 -8
  340. package/dist/sync/contextPorts.d.ts +0 -18
  341. package/dist/sync/contextPorts.js +0 -31
  342. package/dist/sync/createClaimStream.d.ts +0 -7
  343. package/dist/sync/createClaimStream.js +0 -7
  344. package/dist/sync/createPresenceStream.d.ts +0 -69
  345. package/dist/sync/createPresenceStream.js +0 -200
  346. package/dist/sync/createSnapshot.d.ts +0 -29
  347. package/dist/sync/createSnapshot.js +0 -118
  348. package/dist/sync/credentialLifecycle.d.ts +0 -7
  349. package/dist/sync/credentialLifecycle.js +0 -7
  350. package/dist/sync/deltaPipeline.d.ts +0 -114
  351. package/dist/sync/deltaPipeline.js +0 -278
  352. package/dist/sync/groupChange.d.ts +0 -116
  353. package/dist/sync/groupChange.js +0 -244
  354. package/dist/sync/participants.d.ts +0 -132
  355. package/dist/sync/participants.js +0 -346
  356. package/dist/sync/persistedPrefix.d.ts +0 -12
  357. package/dist/sync/persistedPrefix.js +0 -22
  358. package/dist/sync/schemaDrift.d.ts +0 -55
  359. package/dist/sync/schemaDrift.js +0 -53
  360. package/dist/sync/schemas.d.ts +0 -71
  361. package/dist/sync/schemas.js +0 -94
  362. package/dist/sync/syncCursor.d.ts +0 -40
  363. package/dist/sync/syncCursor.js +0 -55
  364. package/dist/sync/syncPlan.d.ts +0 -54
  365. package/dist/sync/syncPlan.js +0 -50
  366. package/dist/sync/wsFrameHandlers.d.ts +0 -8
  367. package/dist/sync/wsFrameHandlers.js +0 -8
  368. package/dist/syncLog/contract.d.ts +0 -20
  369. package/dist/syncLog/contract.js +0 -19
  370. package/dist/syncLog/index.d.ts +0 -1
  371. package/dist/syncLog/index.js +0 -1
  372. package/dist/transaction/ablo.d.ts +0 -88
  373. package/dist/transaction/ablo.js +0 -33
  374. package/dist/transaction/auth/apiKey.d.ts +0 -152
  375. package/dist/transaction/auth/apiKey.js +0 -419
  376. package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
  377. package/dist/transaction/auth/bootstrapScope.js +0 -1
  378. package/dist/transaction/auth/capability.d.ts +0 -212
  379. package/dist/transaction/auth/capability.js +0 -224
  380. package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
  381. package/dist/transaction/auth/credentialEndpoint.js +0 -86
  382. package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
  383. package/dist/transaction/auth/credentialPolicy.js +0 -125
  384. package/dist/transaction/auth/credentialSource.d.ts +0 -30
  385. package/dist/transaction/auth/credentialSource.js +0 -55
  386. package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
  387. package/dist/transaction/auth/hostedEndpoints.js +0 -21
  388. package/dist/transaction/auth/identity.d.ts +0 -55
  389. package/dist/transaction/auth/identity.js +0 -210
  390. package/dist/transaction/auth/index.d.ts +0 -162
  391. package/dist/transaction/auth/index.js +0 -304
  392. package/dist/transaction/auth/schemas.d.ts +0 -59
  393. package/dist/transaction/auth/schemas.js +0 -85
  394. package/dist/transaction/auth/sessionMint.d.ts +0 -28
  395. package/dist/transaction/auth/sessionMint.js +0 -85
  396. package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -56
  397. package/dist/transaction/coordination/awaitClaimGrant.js +0 -124
  398. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -84
  399. package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -108
  400. package/dist/transaction/coordination/claimMeta.d.ts +0 -49
  401. package/dist/transaction/coordination/claimMeta.js +0 -52
  402. package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
  403. package/dist/transaction/coordination/createClaimStream.js +0 -475
  404. package/dist/transaction/coordination/events.d.ts +0 -74
  405. package/dist/transaction/coordination/events.js +0 -7
  406. package/dist/transaction/coordination/index.d.ts +0 -19
  407. package/dist/transaction/coordination/index.js +0 -45
  408. package/dist/transaction/coordination/locator.d.ts +0 -104
  409. package/dist/transaction/coordination/locator.js +0 -102
  410. package/dist/transaction/coordination/schema.d.ts +0 -1536
  411. package/dist/transaction/coordination/schema.js +0 -1177
  412. package/dist/transaction/coordination/targetConflict.d.ts +0 -2
  413. package/dist/transaction/coordination/targetConflict.js +0 -107
  414. package/dist/transaction/coordination/trace.d.ts +0 -78
  415. package/dist/transaction/coordination/trace.js +0 -138
  416. package/dist/transaction/durableWrites.d.ts +0 -62
  417. package/dist/transaction/durableWrites.js +0 -71
  418. package/dist/transaction/environment.d.ts +0 -105
  419. package/dist/transaction/environment.js +0 -108
  420. package/dist/transaction/errorCodes.d.ts +0 -403
  421. package/dist/transaction/errorCodes.js +0 -484
  422. package/dist/transaction/errors.d.ts +0 -428
  423. package/dist/transaction/errors.js +0 -686
  424. package/dist/transaction/footprint.d.ts +0 -111
  425. package/dist/transaction/footprint.js +0 -0
  426. package/dist/transaction/index.d.ts +0 -20
  427. package/dist/transaction/index.js +0 -20
  428. package/dist/transaction/keys/index.d.ts +0 -87
  429. package/dist/transaction/keys/index.js +0 -207
  430. package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
  431. package/dist/transaction/log/syncDeltaRow.js +0 -95
  432. package/dist/transaction/logPosition.d.ts +0 -97
  433. package/dist/transaction/logPosition.js +0 -125
  434. package/dist/transaction/logger.d.ts +0 -16
  435. package/dist/transaction/logger.js +0 -7
  436. package/dist/transaction/observability.d.ts +0 -53
  437. package/dist/transaction/observability.js +0 -19
  438. package/dist/transaction/persistence.d.ts +0 -12
  439. package/dist/transaction/persistence.js +0 -11
  440. package/dist/transaction/plugin.d.ts +0 -285
  441. package/dist/transaction/plugin.js +0 -106
  442. package/dist/transaction/policy/types.d.ts +0 -217
  443. package/dist/transaction/policy/types.js +0 -126
  444. package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
  445. package/dist/transaction/resources/functionalUpdate.js +0 -87
  446. package/dist/transaction/resources/httpResources.d.ts +0 -321
  447. package/dist/transaction/resources/httpResources.js +0 -7
  448. package/dist/transaction/resources/modelOperations.d.ts +0 -427
  449. package/dist/transaction/resources/modelOperations.js +0 -12
  450. package/dist/transaction/resources/mutationOptions.d.ts +0 -66
  451. package/dist/transaction/resources/mutationOptions.js +0 -9
  452. package/dist/transaction/resources/where.d.ts +0 -101
  453. package/dist/transaction/resources/where.js +0 -115
  454. package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
  455. package/dist/transaction/resources/writeOptionsSchema.js +0 -73
  456. package/dist/transaction/schema/field.d.ts +0 -120
  457. package/dist/transaction/schema/field.js +0 -265
  458. package/dist/transaction/schema/fieldRef.d.ts +0 -38
  459. package/dist/transaction/schema/fieldRef.js +0 -11
  460. package/dist/transaction/schema/loadStrategy.d.ts +0 -45
  461. package/dist/transaction/schema/loadStrategy.js +0 -46
  462. package/dist/transaction/schema/model.d.ts +0 -379
  463. package/dist/transaction/schema/model.js +0 -123
  464. package/dist/transaction/schema/openapi.d.ts +0 -58
  465. package/dist/transaction/schema/openapi.js +0 -501
  466. package/dist/transaction/schema/relation.d.ts +0 -204
  467. package/dist/transaction/schema/relation.js +0 -104
  468. package/dist/transaction/schema/residency.d.ts +0 -29
  469. package/dist/transaction/schema/residency.js +0 -25
  470. package/dist/transaction/schema/roles.d.ts +0 -249
  471. package/dist/transaction/schema/roles.js +0 -230
  472. package/dist/transaction/schema/schema.d.ts +0 -351
  473. package/dist/transaction/schema/schema.js +0 -325
  474. package/dist/transaction/schema/tenancy.d.ts +0 -139
  475. package/dist/transaction/schema/tenancy.js +0 -190
  476. package/dist/transaction/transactionLayer.d.ts +0 -82
  477. package/dist/transaction/transactionLayer.js +0 -24
  478. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
  479. package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
  480. package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
  481. package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
  482. package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
  483. package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
  484. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
  485. package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
  486. package/dist/transaction/transport/commitFrames.d.ts +0 -90
  487. package/dist/transaction/transport/commitFrames.js +0 -134
  488. package/dist/transaction/transport/connectionManager.d.ts +0 -215
  489. package/dist/transaction/transport/connectionManager.js +0 -673
  490. package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
  491. package/dist/transaction/transport/credentialLifecycle.js +0 -324
  492. package/dist/transaction/transport/heartbeat.d.ts +0 -65
  493. package/dist/transaction/transport/heartbeat.js +0 -93
  494. package/dist/transaction/transport/httpClient.d.ts +0 -131
  495. package/dist/transaction/transport/httpClient.js +0 -146
  496. package/dist/transaction/transport/httpOptions.d.ts +0 -33
  497. package/dist/transaction/transport/httpOptions.js +0 -12
  498. package/dist/transaction/transport/httpTransport.d.ts +0 -8
  499. package/dist/transaction/transport/httpTransport.js +0 -1388
  500. package/dist/transaction/transport/networkProbe.d.ts +0 -84
  501. package/dist/transaction/transport/networkProbe.js +0 -207
  502. package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
  503. package/dist/transaction/transport/wsFrameHandlers.js +0 -429
  504. package/dist/transaction/transport/wsTransport.d.ts +0 -574
  505. package/dist/transaction/transport/wsTransport.js +0 -1023
  506. package/dist/transaction/types/assertExact.d.ts +0 -17
  507. package/dist/transaction/types/assertExact.js +0 -1
  508. package/dist/transaction/types/global.d.ts +0 -107
  509. package/dist/transaction/types/global.js +0 -40
  510. package/dist/transaction/types/index.d.ts +0 -205
  511. package/dist/transaction/types/index.js +0 -56
  512. package/dist/transaction/types/modelData.d.ts +0 -10
  513. package/dist/transaction/types/modelData.js +0 -9
  514. package/dist/transaction/types/participant.d.ts +0 -20
  515. package/dist/transaction/types/participant.js +0 -10
  516. package/dist/transaction/types/streams.d.ts +0 -550
  517. package/dist/transaction/types/streams.js +0 -11
  518. package/dist/transaction/utils/asyncIterator.d.ts +0 -34
  519. package/dist/transaction/utils/asyncIterator.js +0 -135
  520. package/dist/transaction/utils/duration.d.ts +0 -50
  521. package/dist/transaction/utils/duration.js +0 -77
  522. package/dist/transaction/utils/json.d.ts +0 -57
  523. package/dist/transaction/utils/json.js +0 -276
  524. package/dist/transaction/wire/accountResponses.d.ts +0 -420
  525. package/dist/transaction/wire/accountResponses.js +0 -290
  526. package/dist/transaction/wire/auth.d.ts +0 -56
  527. package/dist/transaction/wire/auth.js +0 -63
  528. package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
  529. package/dist/transaction/wire/bootstrapReason.js +0 -8
  530. package/dist/transaction/wire/claimEvent.d.ts +0 -76
  531. package/dist/transaction/wire/claimEvent.js +0 -73
  532. package/dist/transaction/wire/claims.d.ts +0 -530
  533. package/dist/transaction/wire/claims.js +0 -327
  534. package/dist/transaction/wire/commit.d.ts +0 -603
  535. package/dist/transaction/wire/commit.js +0 -321
  536. package/dist/transaction/wire/delta.d.ts +0 -250
  537. package/dist/transaction/wire/delta.js +0 -147
  538. package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
  539. package/dist/transaction/wire/errorEnvelope.js +0 -123
  540. package/dist/transaction/wire/feedCursor.d.ts +0 -60
  541. package/dist/transaction/wire/feedCursor.js +0 -82
  542. package/dist/transaction/wire/feedEvent.d.ts +0 -204
  543. package/dist/transaction/wire/feedEvent.js +0 -65
  544. package/dist/transaction/wire/frames.d.ts +0 -194
  545. package/dist/transaction/wire/frames.js +0 -50
  546. package/dist/transaction/wire/inboundFrames.d.ts +0 -562
  547. package/dist/transaction/wire/inboundFrames.js +0 -116
  548. package/dist/transaction/wire/index.d.ts +0 -54
  549. package/dist/transaction/wire/index.js +0 -83
  550. package/dist/transaction/wire/listEnvelope.d.ts +0 -37
  551. package/dist/transaction/wire/listEnvelope.js +0 -42
  552. package/dist/transaction/wire/modelMutations.d.ts +0 -31
  553. package/dist/transaction/wire/modelMutations.js +0 -52
  554. package/dist/transaction/wire/modelResponses.d.ts +0 -85
  555. package/dist/transaction/wire/modelResponses.js +0 -43
  556. package/dist/transaction/wire/modelShape.d.ts +0 -78
  557. package/dist/transaction/wire/modelShape.js +0 -74
  558. package/dist/transaction/wire/protocol.d.ts +0 -38
  559. package/dist/transaction/wire/protocol.js +0 -38
  560. package/dist/transaction/wire/protocolVersion.d.ts +0 -73
  561. package/dist/transaction/wire/protocolVersion.js +0 -83
  562. package/dist/transactions/mutations/MutationQueue.d.ts +0 -661
  563. package/dist/transactions/mutations/MutationQueue.js +0 -2807
  564. package/dist/transactions/mutations/MutationStore.d.ts +0 -20
  565. package/dist/transactions/mutations/MutationStore.js +0 -53
  566. package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
  567. package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
  568. package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
  569. package/dist/transactions/mutations/coalesceRules.js +0 -140
  570. package/dist/transactions/mutations/commitLatency.d.ts +0 -52
  571. package/dist/transactions/mutations/commitLatency.js +0 -130
  572. package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
  573. package/dist/transactions/mutations/commitOutboxStore.js +0 -26
  574. package/dist/transactions/mutations/commitPayload.d.ts +0 -165
  575. package/dist/transactions/mutations/commitPayload.js +0 -152
  576. package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -63
  577. package/dist/transactions/mutations/deltaConfirmation.js +0 -235
  578. package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
  579. package/dist/transactions/mutations/durableWriteStore.js +0 -12
  580. package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
  581. package/dist/transactions/mutations/optimisticApply.js +0 -65
  582. package/dist/transactions/mutations/replayValidation.d.ts +0 -187
  583. package/dist/transactions/mutations/replayValidation.js +0 -164
  584. package/dist/utils/mobxSetup.d.ts +0 -53
  585. package/dist/utils/mobxSetup.js +0 -330
  586. package/dist/views/QueryView.d.ts +0 -79
  587. package/dist/views/QueryView.js +0 -218
  588. package/dist/views/ViewRegistry.d.ts +0 -20
  589. package/dist/views/ViewRegistry.js +0 -55
  590. package/dist/views/incrementalView.d.ts +0 -45
  591. package/dist/views/incrementalView.js +0 -69
  592. package/dist/webhooks/events.d.ts +0 -43
  593. package/dist/webhooks/events.js +0 -42
  594. package/dist/webhooks/index.d.ts +0 -8
  595. package/dist/webhooks/index.js +0 -8
  596. package/dist/wire/index.d.ts +0 -1
  597. package/dist/wire/index.js +0 -8
@@ -1,688 +0,0 @@
1
- /**
2
- * The reactive engine assembly (ADR 0016). `Ablo({ ... })` resolves auth and
3
- * capabilities; `humans().init` constructs the store cluster; the lifecycle
4
- * — first mint, identity, ready() — lives in `./storeLifecycle.ts`. What
5
- * remains here is assembly around those parts: the claim stream and
6
- * participant manager, options validation, the typed model proxies, and the
7
- * commit/claim/session resources — composed into the reactive client.
8
- *
9
- * Extracted from the factory so the composition root stays a root: resolve,
10
- * dispatch, return. The remaining assembly converts to decoration of a
11
- * host-built core client with the per-model surface split — the cut's own
12
- * design step (docs/plans/package-split.md).
13
- */
14
- import { durableCommitOperationSchema, } from '../transaction/transactions/settlement/commitEnvelope.js';
15
- import { AbloAuthenticationError, AbloConnectionError, AbloValidationError, claimedError } from '../transaction/errors.js';
16
- import { batchFence, fenceTokenFor, modelTarget, streamTarget, subTarget, } from '../transaction/coordination/index.js';
17
- import { validateAbloOptions } from './validateAbloOptions.js';
18
- import { mintSession } from '../transaction/auth/sessionMint.js';
19
- import { modelWireNames } from '../transaction/auth/capability.js';
20
- import { startStoreLifecycle } from './storeLifecycle.js';
21
- import { createClaimStream } from '../sync/createClaimStream.js';
22
- import { awaitClaimGrant } from '../sync/awaitClaimGrant.js';
23
- import { createSnapshot } from '../sync/createSnapshot.js';
24
- import { createParticipantManager } from '../sync/participants.js';
25
- import { resolveApiKeyValue, resolveBootstrapBaseUrl } from '../transaction/auth/apiKey.js';
26
- import { createModelProxy } from './createModelProxy.js';
27
- import { assertWriteOptions } from '../transaction/resources/writeOptionsSchema.js';
28
- export function buildReactiveEngine(inputs) {
29
- const { options, internalOptions, url, logger, configuredApiKey, configuredAuthToken, credentialResolver, authCredentials, transport, participantId, kind, presence, cluster, createSibling, } = inputs;
30
- const schema = options.schema;
31
- // The store cluster — this client's runtime, the component graph, the
32
- // registered models, and the store — was constructed by `humans().init`
33
- // from the widened plugin context (see `./storeCluster.ts`). The engine
34
- // assembles around it.
35
- const { runtime, components, store } = cluster;
36
- const { modelRegistry, objectPool, bootstrapHelper, database, syncClient, hydration, } = components;
37
- // Self identity, late-bound the same way the connection's values are: the
38
- // construction-time guess seeds it (correct on the self-hosted path, empty
39
- // on the hosted path), and `ready()` overwrites it with what identity
40
- // resolution derives from the credential's scope. The model proxies read
41
- // it through getters, so the is-this-claim-mine checks always compare
42
- // against the resolved identity.
43
- let selfParticipantId = participantId;
44
- let selfParticipantKind = kind;
45
- // Presence + claim streams — the same reference for the engine's lifetime,
46
- // attached to the connection at construction (it exists — the host built
47
- // it; sends before the socket opens are dropped by the transport's
48
- // send-during-reconnect contract, and each stream re-announces on
49
- // `connected`). The presence stream is the humans() plugin's contribution,
50
- // built and attached by its `init` (ADR 0016); the claim stream is core
51
- // coordination, so the root constructs it regardless of the list. Both
52
- // filter own echoes by participant id, seeded in `ready()` alongside the
53
- // locals above.
54
- const presenceStream = presence;
55
- const claimStream = createClaimStream({ participantId, logger }, transport);
56
- // 6. Validate options up front — fail loudly on obviously wrong inputs so
57
- // strangers don't get silent empty results. Validation errors are written
58
- // into `store.syncStatus` (the single source of truth).
59
- const _validationError = validateAbloOptions({
60
- options: internalOptions,
61
- url,
62
- configuredApiKey,
63
- configuredAuthToken,
64
- });
65
- if (_validationError) {
66
- logger.error(_validationError.message);
67
- store.syncStatus.state = 'error';
68
- store.syncStatus.error = _validationError;
69
- }
70
- // Deprecated identity overrides are a silent no-op under hosted cloud: when an
71
- // `apiKey` is configured the SERVER derives participant kind + id from the
72
- // key's scope, so `kind` / `agentId` passed here are ignored. Setting them and
73
- // trusting them is the trap (you think you're an agent; the key says user).
74
- // Warn loudly rather than removing the fields — `agentId` is still load-bearing
75
- // on the self-hosted path (no apiKey; paired with `capabilityToken`).
76
- // eslint-disable-next-line @typescript-eslint/no-deprecated -- reads the deprecated fields precisely to warn callers off them under a configured apiKey
77
- if (configuredApiKey && (internalOptions.kind || internalOptions.agentId)) {
78
- logger.warn('Ablo: `kind` / `agentId` are ignored when an `apiKey` is configured — ' +
79
- 'the server derives participant identity from the key’s scope. Remove ' +
80
- 'them (or mint a scoped session via `ablo.sessions.create({ agent })` ' +
81
- 'for a distinct agent identity). They apply only to the self-hosted ' +
82
- '`capabilityToken` path.');
83
- }
84
- // 7. The lifecycle — first mint, identity resolution, credential refresh,
85
- // and the idempotent ready() driving store.initialize() — is the
86
- // materialiser's own (`./storeLifecycle.ts`); the engine wires it with
87
- // the prelude's credential slice and seeds its own state through the
88
- // callback: the self locals (read by the model proxies' getters) and
89
- // the streams' own-echo filters, before the store ever connects.
90
- /** Resolved account scope — seeded once identity resolution completes;
91
- * exposed as the readonly `ablo.organizationId` accessor. */
92
- let _resolvedOrganizationId = null;
93
- const lifecycle = startStoreLifecycle({
94
- cluster,
95
- schema,
96
- internalOptions,
97
- authCredentials,
98
- credentialResolver,
99
- configuredApiKey,
100
- configuredAuthToken,
101
- url,
102
- kind,
103
- logger,
104
- validationError: _validationError,
105
- onIdentityResolved: ({ userId, participantKind, accountScope, syncGroups }) => {
106
- selfParticipantId = userId;
107
- selfParticipantKind = participantKind;
108
- _resolvedOrganizationId = accountScope;
109
- presenceStream.setParticipant({
110
- id: userId,
111
- kind: participantKind,
112
- syncGroups: [...syncGroups],
113
- });
114
- claimStream.setParticipant({ id: userId });
115
- },
116
- });
117
- const ready = lifecycle.ready;
118
- const participantManager = createParticipantManager({
119
- ready,
120
- transport,
121
- presence: presenceStream,
122
- claims: claimStream,
123
- schema,
124
- });
125
- // 9b. waitForFlush — drains pending mutations using the store's
126
- // pendingChanges counter (already maintained by BaseSyncedStore based
127
- // on MutationQueue events). Polls every 50ms; uses the existing
128
- // observable rather than introducing a new event channel.
129
- async function waitForFlush(timeoutMs) {
130
- const start = Date.now();
131
- while (store.syncStatus.pendingChanges > 0) {
132
- if (timeoutMs !== undefined && Date.now() - start > timeoutMs) {
133
- throw new AbloConnectionError(`Flush timeout: ${store.syncStatus.pendingChanges} pending mutations after ${timeoutMs}ms`, { code: 'flush_timeout' });
134
- }
135
- await new Promise((resolve) => setTimeout(resolve, 50));
136
- }
137
- }
138
- function createClientTxId(idempotencyKey) {
139
- if (idempotencyKey && idempotencyKey.length > 0)
140
- return idempotencyKey;
141
- return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
142
- ? crypto.randomUUID()
143
- : `tx_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
144
- }
145
- function normalizeCommitOperation(op, defaults, fence) {
146
- const type = op.action.toUpperCase();
147
- const id = op.id ?? '';
148
- return durableCommitOperationSchema.parse({
149
- type,
150
- model: op.model.toLowerCase(),
151
- id,
152
- input: op.data ?? undefined,
153
- transactionId: op.transactionId ?? undefined,
154
- readAt: op.readAt ?? defaults.readAt ?? undefined,
155
- onStale: op.onStale ?? defaults.onStale ?? undefined,
156
- fenceToken: op.fenceToken ?? fenceTokenFor(fence, op.model, op.id ?? null) ?? undefined,
157
- });
158
- }
159
- function normalizeCommitOperations(commitOptions, fence) {
160
- if (commitOptions.operations.length === 0) {
161
- throw new AbloValidationError('Commit requires a non-empty `operations` array.', { code: 'commit_operation_required' });
162
- }
163
- return commitOptions.operations.map((op) => normalizeCommitOperation(op, commitOptions, fence));
164
- }
165
- function modelClaimFromActive(claim) {
166
- const target = {
167
- ...modelTarget(claim.target),
168
- ...subTarget(claim.target),
169
- };
170
- return {
171
- id: claim.id,
172
- actor: claim.heldBy ?? "",
173
- participantKind: claim.participantKind ?? "user",
174
- description: claim.description,
175
- field: claim.target.field,
176
- status: 'active',
177
- expiresAt: claim.expiresAt ?? 0,
178
- target,
179
- // The claim's metadata read as the open record it is on the wire, so a
180
- // key the coordinator wrote — a heartbeat's `progress` — is readable.
181
- // `target.meta` is the same bag under the shape the program declared,
182
- // and a declared shape has no member for something the holder did not
183
- // write.
184
- ...(target.meta !== undefined ? { meta: target.meta } : {}),
185
- };
186
- }
187
- function targetMatchesModel(target, claim) {
188
- if (target.model &&
189
- claim.target.type.toLowerCase() !== target.model.toLowerCase()) {
190
- return false;
191
- }
192
- if (target.id && claim.target.id !== target.id)
193
- return false;
194
- if (target.field && claim.target.field !== target.field)
195
- return false;
196
- return true;
197
- }
198
- function listModelClaims(target) {
199
- return claimStream.others
200
- .filter((claim) => (target ? targetMatchesModel(target, claim) : true))
201
- .map(modelClaimFromActive);
202
- }
203
- function waitForModelUnclaimed(target, options) {
204
- if (listModelClaims(target).length === 0)
205
- return Promise.resolve();
206
- return new Promise((resolve, reject) => {
207
- let settled = false;
208
- let timeoutId;
209
- const cleanup = () => {
210
- if (timeoutId)
211
- clearTimeout(timeoutId);
212
- unsubscribe();
213
- options?.signal?.removeEventListener('abort', onAbort);
214
- };
215
- const finish = (fn) => {
216
- if (settled)
217
- return;
218
- settled = true;
219
- cleanup();
220
- fn();
221
- };
222
- const check = () => {
223
- if (listModelClaims(target).length === 0) {
224
- finish(resolve);
225
- }
226
- };
227
- const abortError = () => new AbloConnectionError('Claim wait aborted.', {
228
- code: 'claim_wait_aborted',
229
- cause: options?.signal?.reason,
230
- });
231
- const onAbort = () => {
232
- finish(() => { reject(abortError()); });
233
- };
234
- // Answered before the subscription, the listener, and the timer exist,
235
- // so there is nothing for `cleanup` to undo — and nothing that would
236
- // read `unsubscribe` ahead of the line that binds it.
237
- if (options?.signal?.aborted) {
238
- reject(abortError());
239
- return;
240
- }
241
- const unsubscribe = claimStream.onChange(check);
242
- options?.signal?.addEventListener('abort', onAbort, { once: true });
243
- if (options?.timeout != null) {
244
- timeoutId = setTimeout(() => {
245
- finish(() => {
246
- reject(claimedError(target, listModelClaims(target), 'model_claimed_timeout'));
247
- });
248
- }, options.timeout);
249
- }
250
- });
251
- }
252
- function wrapClaimHandle(claim, waited = false, fenceToken) {
253
- const release = () => {
254
- claim.revoke?.();
255
- return Promise.resolve();
256
- };
257
- // The token is server-stamped and arrives on the grant frame, so prefer
258
- // the one `awaitClaimGrant` read there; fall back to any the local handle
259
- // already carried (immediate, non-queued grants).
260
- const resolvedFenceToken = fenceToken ?? claim.fenceToken;
261
- return {
262
- object: 'claim',
263
- id: claim.id,
264
- description: claim.description,
265
- target: claim.target,
266
- waited,
267
- ...(resolvedFenceToken !== undefined ? { fenceToken: resolvedFenceToken } : {}),
268
- release,
269
- revoke: claim.revoke,
270
- // The lease-control members are forwarded explicitly — this wrapper
271
- // rebuilds the handle field by field, so anything not named here is
272
- // silently dropped from the public claim.
273
- heartbeat: claim.heartbeat,
274
- [Symbol.asyncDispose]: release,
275
- };
276
- }
277
- const publicClaims = Object.assign(claimStream, {
278
- async create(claimOptions) {
279
- await ready();
280
- const claim = claimStream.claim({
281
- ...streamTarget(claimOptions.target),
282
- ...subTarget(claimOptions.target),
283
- }, {
284
- description: claimOptions.description,
285
- ttl: claimOptions.ttl,
286
- queue: claimOptions.queue,
287
- });
288
- // With `queue`, the claim is only really *ours* once the server says
289
- // so (`claim_acquired` if the target was free, `claim_granted` once
290
- // we reach the head of the FIFO line). Block here on that grant so
291
- // callers — chiefly `ablo.<model>.claim` — get a handle that already
292
- // holds the lease, never a half-claimed one racing the queue.
293
- let waited = false;
294
- let fenceToken;
295
- if (claimOptions.queue) {
296
- try {
297
- ({ waited, fenceToken } = await awaitClaimGrant(transport, claim.id, {
298
- timeoutMs: claimOptions.waitTimeoutMs,
299
- maxQueueDepth: claimOptions.maxQueueDepth,
300
- signal: claimOptions.signal,
301
- logger,
302
- }));
303
- }
304
- catch (err) {
305
- // Gave up waiting (queue too deep, timed out, or lost) — abandon
306
- // the queued claim so we don't leave a phantom entry in the
307
- // line that would block or mislead other claimers.
308
- claim.revoke?.();
309
- throw err;
310
- }
311
- }
312
- return wrapClaimHandle(claim, waited, fenceToken);
313
- },
314
- list(target) {
315
- return listModelClaims(target);
316
- },
317
- waitFor(target, options) {
318
- return waitForModelUnclaimed(target, options);
319
- },
320
- });
321
- /**
322
- * One held claim, as the public claim-state object.
323
- *
324
- * The live claim stream only tracks *open* claims; terminal states
325
- * (committed / expired / canceled) drop out of the list entirely — exactly
326
- * the ephemeral coordination model — so a present entry is by definition
327
- * `status: 'active'`.
328
- */
329
- const claimStateOf = (held) => {
330
- if (!held)
331
- return null;
332
- return {
333
- object: 'claim',
334
- id: held.id,
335
- status: 'active',
336
- target: {
337
- ...streamTarget(held.target),
338
- ...subTarget(held.target),
339
- },
340
- description: held.description ?? 'editing',
341
- heldBy: held.actor,
342
- participantKind: held.participantKind,
343
- expiresAt: held.expiresAt,
344
- // Carried, not dropped: the coordinator writes a heartbeat's `details`
345
- // into `meta.progress` on the holder's record so an observer can see
346
- // what a long hold is doing. It reached `ModelClaim` and stopped here,
347
- // which left the beat writable and unreadable — a channel with a setter
348
- // and no getter. `target.meta` beside it stays the declared shape; this
349
- // is the open record, because a declared shape has no member for a key
350
- // the holder did not write.
351
- ...(held.meta !== undefined ? { meta: held.meta } : {}),
352
- };
353
- };
354
- // Build the typed proxy — one property per model. Done after publicClaims
355
- // exists so model clients can expose workflow helpers such as
356
- // `ablo.files.edit(...)` without importing protocol wiring.
357
- const modelProxies = {};
358
- for (const [schemaKey, modelDef] of Object.entries(schema.models)) {
359
- const registeredModelName = modelDef.typename ?? schemaKey;
360
- modelProxies[schemaKey] = createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, modelRegistry, hydration, {
361
- createClaim: (claimOptions) => publicClaims.create(claimOptions),
362
- createSnapshot: (modelKey, id) => createSnapshot({
363
- pool: objectPool,
364
- transport,
365
- // `position.readFloor` is the value claims and snapshots stamp as
366
- // `readAt` (max of the pool-applied cursor and the acked
367
- // watermark for our own writes — see logPosition.ts).
368
- // Stamping a bare stream cursor made a claim taken right after
369
- // an ack-confirmed write stale against that write's own delta.
370
- // The socket/store cursors are persistence-gated and therefore
371
- // never ahead of `applied` — no extra max() needed here.
372
- getLastSyncId: () => syncClient.position.readFloor,
373
- entities: { [modelKey]: id },
374
- }),
375
- queue: (target) => publicClaims.queueFor(streamTarget(target)),
376
- reorder: (target, order) => { publicClaims.reorder(streamTarget(target), order); },
377
- // One row can have several holders — sub-row claims on disjoint
378
- // targets are all granted — so `state` and `holders` read the same
379
- // list and differ only in how much of it they answer with. The
380
- // projection lives here once: two copies of it would drift the
381
- // moment a field is added to one caller's answer.
382
- state: (target) => claimStateOf(publicClaims.list(modelTarget(target))[0]),
383
- holders: (target) => publicClaims
384
- .list(modelTarget(target))
385
- .map((held) => claimStateOf(held))
386
- .filter((claim) => claim !== null),
387
- waitFor: (target, waitOptions) => publicClaims.waitFor(modelTarget(target), waitOptions),
388
- // Getters, not copies: identity is late-bound (seeded in `ready()`),
389
- // and the contended / heldBy checks must compare against whoever
390
- // this client resolved to, not the construction-time guess.
391
- get selfParticipantId() { return selfParticipantId; },
392
- get selfParticipantKind() { return selfParticipantKind; },
393
- // Read-interest / write-intent enrolment for the typed surface.
394
- // `enterScope`/`pinScope` resolve the `{ [schemaKey]: id }` scope
395
- // through the same resolver the claim path uses, landing this client in
396
- // the entity-scoped group the holder's claim presence fans out on.
397
- // Returns the store promise so the claim write path can await pinScope
398
- // before acquiring the lease (closing the subscribe-vs-broadcast race);
399
- // read-interest callers (`retrieve`/`claim.state`) still `void` it and
400
- // stay fire-and-forget. It's soft either way — the store swallows
401
- // reconcile errors so read interest never makes a read reject or stall.
402
- enterScope: (scope) => store.enterScope(scope),
403
- pinScope: (scope) => store.pinScope(scope),
404
- // `ablo.<model>.join(ids, { ttl })` performs a scoped participant join
405
- // on this model's sync group(s). WebSocket only — `join` throws
406
- // `AbloConnectionError` if the socket isn't ready.
407
- // `ttl` passes straight through — both surfaces spell the lease the
408
- // same way now, so there is no rename here to make a field's name
409
- // disagree with the value it carries.
410
- createJoin: (modelKey, ids, options) => participantManager.join({
411
- scope: { [modelKey]: ids },
412
- ...(options?.ttl !== undefined ? { ttl: options.ttl } : {}),
413
- }),
414
- },
415
- // The client-wide `wait` default; a per-call `wait` still wins.
416
- internalOptions.wait);
417
- }
418
- const commits = {
419
- async create(commitOptions) {
420
- await ready();
421
- // Same runtime contract as the per-model writes — one schema.
422
- assertWriteOptions({
423
- idempotencyKey: commitOptions.idempotencyKey,
424
- readAt: commitOptions.readAt,
425
- onStale: commitOptions.onStale,
426
- wait: commitOptions.wait,
427
- claim: commitOptions.claim,
428
- }, 'commits.create');
429
- const clientTxId = createClientTxId(commitOptions.idempotencyKey);
430
- // A claim handle supplies the batch stale-guard defaults — same
431
- // semantics as `ablo.<model>.update({ id, data, claim })`, so the
432
- // two write doors speak one claim vocabulary. Explicit options win.
433
- const claim = commitOptions.claim ?? null;
434
- const operations = normalizeCommitOperations({
435
- ...commitOptions,
436
- readAt: commitOptions.readAt ?? claim?.readAt ?? null,
437
- onStale: commitOptions.onStale ?? (claim?.readAt !== undefined ? 'reject' : null),
438
- }, batchFence(claim?.target, claim?.fenceToken));
439
- const wait = commitOptions.wait ?? 'confirmed';
440
- // Route through the MutationQueue's commit lane so the call
441
- // tolerates WS disconnects: the envelope stays in memory until
442
- // reconnect, mutationExecutor.commit() owns transport-level
443
- // retry, and `mutation_log` server-side dedupes replays by
444
- // clientTxId. Replaces the direct ws.sendCommit /
445
- // sendCommitQueued path that threw synchronously on
446
- // `ws.readyState !== OPEN`. The queue lives on the internal
447
- // SyncClient we already hold from createInternalComponents —
448
- // no need to leak an accessor through BaseSyncedStore.
449
- const queue = syncClient.getMutationQueue();
450
- await queue.enqueueCommit(clientTxId, operations, {
451
- ...(commitOptions.reads ? { reads: [...commitOptions.reads] } : {}),
452
- ...(commitOptions.track ? { track: [...commitOptions.track] } : {}),
453
- });
454
- if (wait === 'queued') {
455
- return { id: clientTxId, status: 'queued' };
456
- }
457
- const { lastSyncId, notifications, missingIds } = await queue.waitForCommitReceipt(clientTxId);
458
- return {
459
- id: clientTxId,
460
- status: 'confirmed',
461
- lastSyncId,
462
- ...(notifications && notifications.length > 0 ? { notifications } : {}),
463
- ...(missingIds && missingIds.length > 0 ? { missingIds } : {}),
464
- };
465
- },
466
- };
467
- /**
468
- * The control-plane credential: always the original configured secret key.
469
- * Never reads `authCredentials` — that holds the exchanged sync credential
470
- * (a wide-scope `rk_` on the hosted path), which control-plane routes
471
- * rightly refuse (e.g. the user-session mint is sk_-gated). Counterpart to
472
- * `getAuthToken()`, which resolves the sync-plane token.
473
- *
474
- * The secret-key-only rule is enforced on the server; the credential-kind taxonomy
475
- * (secret/restricted/ephemeral/publishable) lives in `auth/credentialPolicy`.
476
- */
477
- async function controlPlaneApiKey() {
478
- return resolveApiKeyValue(configuredApiKey);
479
- }
480
- /**
481
- * Resolve the control-plane context a session/agent mint needs (sk_ +
482
- * bootstrap base URL + the schema-key→typename map the server gates on).
483
- * Shared by `sessions.create` and `agents.create` so the two mint doors
484
- * can never drift on how a token is minted. Throws if no `sk_` is present —
485
- * minting is a backend-only operation.
486
- */
487
- async function buildMintContext(resource) {
488
- const apiKey = await controlPlaneApiKey();
489
- if (!apiKey) {
490
- throw new AbloAuthenticationError(`${resource} requires a secret (sk_) API key — call it from your backend, not the browser.`, { code: 'apikey_missing' });
491
- }
492
- return {
493
- apiKey,
494
- baseUrl: resolveBootstrapBaseUrl({
495
- url,
496
- bootstrapBaseUrl: internalOptions.bootstrapBaseUrl,
497
- }),
498
- ...(internalOptions.fetch ? { fetch: internalOptions.fetch } : {}),
499
- // Map every `can` schema-key to the wire typename the server gates on, so a
500
- // typename override (`documents` → `Document`) doesn't mint a capability
501
- // the server then denies. Derived from this client's schema by the one rule
502
- // the HTTP client and the mint route also read. See `MintSessionContext`.
503
- modelTypenames: modelWireNames(schema.models),
504
- };
505
- }
506
- const engine = {
507
- ...modelProxies,
508
- ready,
509
- waitForFlush,
510
- /** Durable frame subscription — delegates to the store's registry, which
511
- * re-attaches across socket rebuilds. */
512
- subscribe: (event, handler) => store.subscribe(event, handler),
513
- setAuthToken(token) {
514
- // The single credential source is read lazily by bootstrap HTTP,
515
- // lazy query HTTP, network probes, and WebSocket reconnect URL auth.
516
- // Updating it here is enough for the next request/connect to use the
517
- // refreshed token; no per-transport patching.
518
- authCredentials.setAuthToken(token);
519
- // A fresh credential is useless to a connection parked in offline /
520
- // backoff / auth_blocked until the next probe trigger — so kick one now.
521
- // Harmless while connected (the FSM ignores the nudge there).
522
- store.nudgeReconnect();
523
- },
524
- async getAuthToken() {
525
- // The live short-lived bearer (set via `setAuthToken` / `apiKey`-resolver refresh)
526
- // is the canonical credential; fall back to a configured API key.
527
- //
528
- // This is the sync-plane token (bootstrap, WebSocket, query HTTP). Control-plane
529
- // calls (sessions.create, datasource registration) never use it — they
530
- // present the original secret key via `controlPlaneApiKey()` below. The
531
- // split matters: after the startup exchange this resolver returns the
532
- // derived wide-scope `rk_`, a credential the control-plane routes
533
- // correctly refuse (an agent token must never mint humans).
534
- return (authCredentials.getAuthToken() ??
535
- (await resolveApiKeyValue(configuredApiKey)) ??
536
- configuredAuthToken ??
537
- null);
538
- },
539
- setCredentialRefresher(refresher) {
540
- store.setCredentialRefresher(refresher);
541
- },
542
- // The org this client resolved to — null until `ready()` completes. Exposed
543
- // as a property so integrators can read it programmatically.
544
- get organizationId() {
545
- return _resolvedOrganizationId;
546
- },
547
- nudgeReconnect() {
548
- store.nudgeReconnect();
549
- },
550
- sessions: {
551
- // A backend (holding `sk_`) mints a short-lived scoped token for one end
552
- // user or one agent.
553
- //
554
- // Both arms authenticate with the original secret key
555
- // (`controlPlaneApiKey()`), never the wide-scope `rk_` the startup exchange
556
- // installed as the sync credential. A derived agent credential silently
557
- // replacing the secret key on control-plane calls is how humans would get
558
- // minted as agents — and correct attribution is the point.
559
- async create(params) {
560
- // Both mint paths (`{ user }` → /auth/ephemeral-keys → `ek_`,
561
- // `{ agent, can }` → /auth/capability → scoped `rk_`) resolve their
562
- // control-plane context through the shared `buildMintContext`, so this
563
- // client, `agents.create`, and the stateless HTTP client can't drift on
564
- // how a token is minted.
565
- return mintSession(params, await buildMintContext('sessions.create'));
566
- },
567
- },
568
- // Mint a scoped agent identity and hand back a connected client bound to it —
569
- // `sessions.create({ agent })` plus a typed `Ablo({ schema, apiKey })` client,
570
- // for agents that run in this (secret-key-holding) process. Omitting `id`
571
- // yields a fresh uuid per call, so concurrent agents are distinct participants
572
- // that queue behind each other (even when they share a `name`). Humans don't
573
- // get a server-built client — ship them a token via `sessions.create({ user })`.
574
- agents: {
575
- async create(params) {
576
- // Distinct participant by default: omit `id` → a fresh uuid, so even two
577
- // agents that share a `name` are independent participants and queue
578
- // behind one another. `name` is display only (→ userMeta.name); it never
579
- // derives the id. Pass an explicit `id` only to re-attach an agent to
580
- // its own held claims.
581
- const id = params.id ?? globalThis.crypto.randomUUID();
582
- const userMeta = params.name !== undefined ? { ...params.userMeta, name: params.name } : params.userMeta;
583
- const sessionParams = {
584
- agent: { id },
585
- can: params.can,
586
- ...(params.syncGroups ? { syncGroups: params.syncGroups } : {}),
587
- ...(params.ttlSeconds !== undefined ? { ttlSeconds: params.ttlSeconds } : {}),
588
- ...(userMeta ? { userMeta } : {}),
589
- };
590
- // Re-mint the `rk_` on every resolver call so a long-lived agent client
591
- // never hits token expiry; the `sk_` stays in this process — the child
592
- // only ever sees its own short-lived `rk_`.
593
- const mintToken = async () => (await mintSession(sessionParams, await buildMintContext('agents.create')))
594
- .token;
595
- // Mint once up front so a bad key / denied scope throws HERE, not later
596
- // inside the child's bootstrap; reuse that first token, re-mint on refresh.
597
- let pending = await mintToken();
598
- const apiKey = async () => {
599
- if (pending !== null) {
600
- const token = pending;
601
- pending = null;
602
- return token;
603
- }
604
- return mintToken();
605
- };
606
- return createSibling({ ...internalOptions, apiKey });
607
- },
608
- },
609
- async dispose() {
610
- lifecycle.dispose();
611
- try {
612
- await store.disconnect();
613
- }
614
- catch (err) {
615
- // Best-effort teardown — a disposal hiccup isn't consumer-actionable → debug.
616
- logger.debug('Error during sync engine disposal', { error: err.message });
617
- }
618
- presenceStream.dispose();
619
- claimStream.dispose();
620
- syncClient.dispose();
621
- },
622
- /**
623
- * Destroy every IndexedDB database owned by this engine. Disconnects
624
- * the WebSocket, releases timers, and deletes all `ablo_*` / `ablo-*`
625
- * databases. Typically called on session expiry or explicit logout.
626
- * Best-effort — errors from individual deletions are swallowed.
627
- */
628
- async purge() {
629
- await store.purge();
630
- syncClient.dispose();
631
- },
632
- /**
633
- * Subscribe to session-error events. Fires when the server rejects
634
- * the session (WebSocket close code 1008/4001/4003 or a session_error
635
- * frame). Multiple subscribers supported; returns an unsubscribe
636
- * function. Consumers typically use this to trigger auth-failed UI
637
- * flows (e.g., redirect to sign-in). Does not automatically purge the
638
- * IndexedDB — call `engine.purge()` from the listener if you need
639
- * that behavior (the SDK's `<AbloProvider>` does this by default).
640
- */
641
- onSessionError(listener) {
642
- return store.subscribeSessionError(listener);
643
- },
644
- onMutationFailure(listener) {
645
- return store.subscribeMutationFailure(listener);
646
- },
647
- onCommitLatency(listener) {
648
- return store.subscribeCommitLatency(listener);
649
- },
650
- waitForConfirmation(modelName, modelId) {
651
- return store.waitForConfirmation(modelName, modelId);
652
- },
653
- // Expose the store's MobX observable directly — single source of truth.
654
- // React components using observer() will re-render automatically on
655
- // any state change (syncing, error, offline, pendingChanges, progress).
656
- get syncStatus() {
657
- return store.syncStatus;
658
- },
659
- schema,
660
- // ── Internal accessors for framework integration ─────────────────
661
- // These expose internal components for consumers that need direct
662
- // access (e.g., SyncEngineProvider wiring SyncContext, collaboration
663
- // events accessing the WebSocket handle, demand loaders accessing
664
- // the pool). Prefixed with _ to signal "internal but stable."
665
- /** The BaseSyncedStore — implements SyncStoreContract for SyncContext.Provider. */
666
- get _store() { return store; },
667
- /** The InstanceCache — for demand loaders that need pool.createFromData(). */
668
- get _pool() { return objectPool; },
669
- /** The SyncWebSocket — for collaboration events (selection, cursors). */
670
- get _ws() { return store.getSyncWebSocket(); },
671
- /** Presence livestream — same socket as entity sync, no second
672
- * connection. Stable reference across the engine's lifetime. */
673
- presence: presenceStream,
674
- /** Claim livestream — same socket. Stable reference. */
675
- claims: publicClaims,
676
- commits,
677
- /** Context-staleness snapshot — see `engine.snapshot(...)` JSDoc. */
678
- snapshot(entities) {
679
- return createSnapshot({
680
- pool: objectPool,
681
- transport,
682
- getLastSyncId: () => transport.getLastSyncId(),
683
- entities,
684
- });
685
- },
686
- };
687
- return engine;
688
- }