@abloatai/ablo 0.26.0 → 0.28.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 (418) hide show
  1. package/CHANGELOG.md +42 -2
  2. package/README.md +102 -86
  3. package/dist/BaseSyncedStore.d.ts +85 -88
  4. package/dist/BaseSyncedStore.js +134 -151
  5. package/dist/Database.d.ts +68 -69
  6. package/dist/Database.js +316 -135
  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 +54 -52
  12. package/dist/Model.js +78 -62
  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 +122 -118
  18. package/dist/SyncClient.js +541 -245
  19. package/dist/adapters/alwaysOnline.d.ts +6 -8
  20. package/dist/adapters/alwaysOnline.js +6 -8
  21. package/dist/adapters/inMemoryStorage.d.ts +10 -9
  22. package/dist/adapters/inMemoryStorage.js +21 -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 +173 -121
  50. package/dist/client/Ablo.d.ts +97 -74
  51. package/dist/client/Ablo.js +129 -163
  52. package/dist/client/ApiClient.d.ts +30 -19
  53. package/dist/client/ApiClient.js +442 -81
  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 +16 -17
  61. package/dist/client/createInternalComponents.js +26 -31
  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 +59 -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 +78 -87
  76. package/dist/client/options.d.ts +157 -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 +16 -20
  91. package/dist/client/wsMutationExecutor.js +18 -23
  92. package/dist/commit/contract.d.ts +493 -0
  93. package/dist/commit/contract.js +187 -0
  94. package/dist/commit/index.d.ts +6 -0
  95. package/dist/commit/index.js +5 -0
  96. package/dist/context.d.ts +6 -4
  97. package/dist/context.js +6 -4
  98. package/dist/coordination/index.d.ts +10 -8
  99. package/dist/coordination/index.js +14 -12
  100. package/dist/coordination/schema.d.ts +176 -128
  101. package/dist/coordination/schema.js +197 -133
  102. package/dist/coordination/trace.d.ts +9 -10
  103. package/dist/coordination/trace.js +13 -14
  104. package/dist/core/DatabaseManager.d.ts +5 -7
  105. package/dist/core/DatabaseManager.js +15 -19
  106. package/dist/core/QueryProcessor.d.ts +7 -9
  107. package/dist/core/QueryProcessor.js +22 -28
  108. package/dist/core/QueryView.d.ts +8 -8
  109. package/dist/core/QueryView.js +2 -2
  110. package/dist/core/StoreManager.d.ts +14 -14
  111. package/dist/core/StoreManager.js +33 -24
  112. package/dist/core/ViewRegistry.d.ts +5 -5
  113. package/dist/core/ViewRegistry.js +4 -4
  114. package/dist/core/index.d.ts +17 -12
  115. package/dist/core/index.js +32 -26
  116. package/dist/core/openIDBWithTimeout.d.ts +38 -36
  117. package/dist/core/openIDBWithTimeout.js +42 -43
  118. package/dist/core/queryUtils.d.ts +45 -0
  119. package/dist/core/queryUtils.js +69 -0
  120. package/dist/core/storeContract.d.ts +63 -61
  121. package/dist/core/storeContract.js +8 -12
  122. package/dist/environment.d.ts +28 -0
  123. package/dist/environment.js +21 -0
  124. package/dist/errorCodes.d.ts +107 -99
  125. package/dist/errorCodes.js +137 -134
  126. package/dist/errors.d.ts +160 -166
  127. package/dist/errors.js +155 -158
  128. package/dist/index.d.ts +36 -27
  129. package/dist/index.js +91 -86
  130. package/dist/interfaces/index.d.ts +102 -113
  131. package/dist/interfaces/index.js +5 -4
  132. package/dist/keys/index.d.ts +27 -29
  133. package/dist/keys/index.js +41 -40
  134. package/dist/mutators/RecordingTransaction.d.ts +16 -16
  135. package/dist/mutators/RecordingTransaction.js +31 -37
  136. package/dist/mutators/Transaction.d.ts +18 -26
  137. package/dist/mutators/Transaction.js +14 -20
  138. package/dist/mutators/UndoManager.d.ts +124 -131
  139. package/dist/mutators/UndoManager.js +177 -156
  140. package/dist/mutators/defineMutators.d.ts +23 -34
  141. package/dist/mutators/defineMutators.js +14 -20
  142. package/dist/mutators/inverseOp.d.ts +12 -15
  143. package/dist/mutators/inverseOp.js +12 -15
  144. package/dist/mutators/mutateActions.d.ts +10 -9
  145. package/dist/mutators/mutateActions.js +1 -1
  146. package/dist/mutators/readerActions.d.ts +9 -8
  147. package/dist/mutators/readerActions.js +2 -2
  148. package/dist/mutators/undoApply.d.ts +31 -27
  149. package/dist/mutators/undoApply.js +26 -24
  150. package/dist/policy/index.d.ts +5 -3
  151. package/dist/policy/index.js +5 -3
  152. package/dist/policy/types.d.ts +104 -100
  153. package/dist/policy/types.js +67 -66
  154. package/dist/query/client.d.ts +28 -23
  155. package/dist/query/client.js +45 -43
  156. package/dist/query/types.d.ts +37 -60
  157. package/dist/query/types.js +13 -33
  158. package/dist/react/AbloProvider.d.ts +1 -1
  159. package/dist/react/AbloProvider.js +2 -2
  160. package/dist/react/context.d.ts +25 -28
  161. package/dist/react/context.js +9 -10
  162. package/dist/react/index.d.ts +41 -42
  163. package/dist/react/index.js +37 -38
  164. package/dist/react/internalContext.d.ts +17 -19
  165. package/dist/react/useAblo.d.ts +28 -25
  166. package/dist/react/useAblo.js +41 -17
  167. package/dist/react/useCurrentUserId.d.ts +8 -7
  168. package/dist/react/useCurrentUserId.js +8 -7
  169. package/dist/react/useErrorListener.d.ts +7 -7
  170. package/dist/react/useErrorListener.js +10 -11
  171. package/dist/react/useMutationFailureListener.d.ts +8 -8
  172. package/dist/react/useMutationFailureListener.js +8 -8
  173. package/dist/react/useMutators.d.ts +11 -11
  174. package/dist/react/useMutators.js +3 -3
  175. package/dist/react/useReactive.js +2 -2
  176. package/dist/react/useSyncStatus.d.ts +4 -6
  177. package/dist/react/useUndoScope.d.ts +7 -9
  178. package/dist/react/useUndoScope.js +1 -1
  179. package/dist/schema/coordination.d.ts +21 -25
  180. package/dist/schema/coordination.js +21 -25
  181. package/dist/schema/ddl.d.ts +43 -39
  182. package/dist/schema/ddl.js +75 -68
  183. package/dist/schema/ddlLock.d.ts +20 -24
  184. package/dist/schema/ddlLock.js +18 -23
  185. package/dist/schema/diff.d.ts +99 -61
  186. package/dist/schema/diff.js +43 -34
  187. package/dist/schema/field.d.ts +37 -42
  188. package/dist/schema/field.js +35 -48
  189. package/dist/schema/generate.d.ts +12 -12
  190. package/dist/schema/generate.js +12 -12
  191. package/dist/schema/index.d.ts +3 -3
  192. package/dist/schema/index.js +21 -23
  193. package/dist/schema/model.d.ts +118 -143
  194. package/dist/schema/model.js +22 -33
  195. package/dist/schema/openapi.d.ts +10 -9
  196. package/dist/schema/openapi.js +5 -3
  197. package/dist/schema/queries.d.ts +29 -31
  198. package/dist/schema/queries.js +23 -25
  199. package/dist/schema/relation.d.ts +89 -99
  200. package/dist/schema/relation.js +13 -13
  201. package/dist/schema/residency.d.ts +16 -13
  202. package/dist/schema/residency.js +16 -13
  203. package/dist/schema/roles.d.ts +36 -43
  204. package/dist/schema/roles.js +31 -37
  205. package/dist/schema/schema.d.ts +64 -43
  206. package/dist/schema/schema.js +31 -32
  207. package/dist/schema/select.d.ts +13 -13
  208. package/dist/schema/select.js +13 -13
  209. package/dist/schema/serialize.d.ts +28 -31
  210. package/dist/schema/serialize.js +27 -31
  211. package/dist/schema/sugar.d.ts +17 -32
  212. package/dist/schema/sugar.js +14 -29
  213. package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
  214. package/dist/schema/syncDeltaRow.js +89 -0
  215. package/dist/schema/tenancy.d.ts +44 -46
  216. package/dist/schema/tenancy.js +46 -48
  217. package/dist/server/adapter.d.ts +58 -58
  218. package/dist/server/adapter.js +13 -14
  219. package/dist/server/commit.d.ts +60 -64
  220. package/dist/server/index.d.ts +9 -10
  221. package/dist/server/index.js +1 -1
  222. package/dist/server/readConfig.d.ts +70 -0
  223. package/dist/server/readConfig.js +8 -0
  224. package/dist/server/storageMode.d.ts +23 -0
  225. package/dist/server/storageMode.js +17 -0
  226. package/dist/source/adapter.d.ts +30 -25
  227. package/dist/source/adapter.js +10 -10
  228. package/dist/source/adapters/drizzle.d.ts +28 -23
  229. package/dist/source/adapters/drizzle.js +30 -25
  230. package/dist/source/adapters/kysely.d.ts +27 -25
  231. package/dist/source/adapters/kysely.js +24 -23
  232. package/dist/source/adapters/memory.d.ts +8 -7
  233. package/dist/source/adapters/memory.js +9 -8
  234. package/dist/source/adapters/prisma.d.ts +13 -12
  235. package/dist/source/adapters/prisma.js +22 -25
  236. package/dist/source/conformance.d.ts +18 -11
  237. package/dist/source/conformance.js +17 -11
  238. package/dist/source/connector.d.ts +31 -32
  239. package/dist/source/connector.js +28 -28
  240. package/dist/source/connectorProtocol.d.ts +160 -0
  241. package/dist/source/connectorProtocol.js +162 -0
  242. package/dist/source/contract.d.ts +26 -27
  243. package/dist/source/contract.js +28 -29
  244. package/dist/source/factory.d.ts +46 -58
  245. package/dist/source/factory.js +22 -27
  246. package/dist/source/index.d.ts +7 -9
  247. package/dist/source/index.js +12 -14
  248. package/dist/source/migrations.d.ts +9 -9
  249. package/dist/source/migrations.js +9 -9
  250. package/dist/source/next.d.ts +9 -10
  251. package/dist/source/next.js +6 -7
  252. package/dist/source/pushQueue.d.ts +69 -47
  253. package/dist/source/pushQueue.js +32 -28
  254. package/dist/source/signing.d.ts +46 -17
  255. package/dist/source/signing.js +28 -11
  256. package/dist/source/types.d.ts +121 -104
  257. package/dist/source/types.js +13 -14
  258. package/dist/stores/ObjectStore.d.ts +24 -12
  259. package/dist/stores/ObjectStore.js +38 -16
  260. package/dist/stores/ObjectStoreContract.d.ts +14 -15
  261. package/dist/stores/SyncActionStore.d.ts +7 -11
  262. package/dist/stores/SyncActionStore.js +13 -17
  263. package/dist/surface.d.ts +28 -21
  264. package/dist/surface.js +29 -20
  265. package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
  266. package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
  267. package/dist/sync/ConnectionManager.d.ts +39 -50
  268. package/dist/sync/ConnectionManager.js +55 -66
  269. package/dist/sync/NetworkProbe.d.ts +24 -29
  270. package/dist/sync/NetworkProbe.js +63 -69
  271. package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
  272. package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
  273. package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
  274. package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
  275. package/dist/sync/SyncWebSocket.d.ts +141 -166
  276. package/dist/sync/SyncWebSocket.js +191 -223
  277. package/dist/sync/awaitClaimGrant.d.ts +18 -18
  278. package/dist/sync/awaitClaimGrant.js +11 -11
  279. package/dist/sync/bootstrapApply.d.ts +34 -24
  280. package/dist/sync/bootstrapApply.js +27 -19
  281. package/dist/sync/commitFrames.d.ts +21 -20
  282. package/dist/sync/commitFrames.js +18 -18
  283. package/dist/sync/createClaimStream.d.ts +23 -22
  284. package/dist/sync/createClaimStream.js +105 -23
  285. package/dist/sync/createPresenceStream.d.ts +19 -18
  286. package/dist/sync/createPresenceStream.js +25 -26
  287. package/dist/sync/createSnapshot.d.ts +12 -14
  288. package/dist/sync/createSnapshot.js +20 -26
  289. package/dist/sync/credentialLifecycle.d.ts +104 -104
  290. package/dist/sync/credentialLifecycle.js +140 -147
  291. package/dist/sync/deltaPipeline.d.ts +36 -34
  292. package/dist/sync/deltaPipeline.js +64 -65
  293. package/dist/sync/groupChange.d.ts +63 -61
  294. package/dist/sync/groupChange.js +74 -78
  295. package/dist/sync/heartbeat.d.ts +34 -33
  296. package/dist/sync/heartbeat.js +31 -31
  297. package/dist/sync/participants.d.ts +19 -19
  298. package/dist/sync/persistedPrefix.d.ts +12 -0
  299. package/dist/sync/persistedPrefix.js +22 -0
  300. package/dist/sync/schemas.d.ts +3 -2
  301. package/dist/sync/schemas.js +14 -10
  302. package/dist/sync/syncCursor.d.ts +17 -21
  303. package/dist/sync/syncCursor.js +17 -21
  304. package/dist/sync/syncPlan.d.ts +28 -36
  305. package/dist/sync/syncPlan.js +18 -19
  306. package/dist/sync/syncPosition.d.ts +54 -49
  307. package/dist/sync/syncPosition.js +57 -52
  308. package/dist/sync/wsFrameHandlers.d.ts +35 -36
  309. package/dist/sync/wsFrameHandlers.js +63 -67
  310. package/dist/testing/fixtures/bootstrap.d.ts +12 -6
  311. package/dist/testing/fixtures/bootstrap.js +12 -6
  312. package/dist/testing/fixtures/deltas.d.ts +30 -33
  313. package/dist/testing/fixtures/deltas.js +30 -33
  314. package/dist/testing/fixtures/models.d.ts +11 -10
  315. package/dist/testing/fixtures/models.js +11 -10
  316. package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
  317. package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
  318. package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
  319. package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
  320. package/dist/testing/helpers/wait.d.ts +13 -8
  321. package/dist/testing/helpers/wait.js +13 -8
  322. package/dist/testing/index.d.ts +5 -3
  323. package/dist/testing/index.js +3 -2
  324. package/dist/testing/mocks/FakeDatabase.d.ts +18 -0
  325. package/dist/testing/mocks/FakeDatabase.js +10 -0
  326. package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
  327. package/dist/testing/mocks/MockMutationExecutor.js +15 -14
  328. package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
  329. package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
  330. package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
  331. package/dist/testing/mocks/MockSyncContext.js +15 -13
  332. package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
  333. package/dist/testing/mocks/MockSyncStore.js +11 -11
  334. package/dist/testing/mocks/MockWebSocket.d.ts +28 -23
  335. package/dist/testing/mocks/MockWebSocket.js +22 -21
  336. package/dist/transactions/TransactionQueue.d.ts +244 -181
  337. package/dist/transactions/TransactionQueue.js +929 -423
  338. package/dist/transactions/TransactionStore.d.ts +6 -4
  339. package/dist/transactions/TransactionStore.js +6 -4
  340. package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
  341. package/dist/transactions/UnconfirmedWrites.js +104 -0
  342. package/dist/transactions/coalesceRules.d.ts +41 -17
  343. package/dist/transactions/coalesceRules.js +40 -17
  344. package/dist/transactions/commitEnvelope.d.ts +132 -0
  345. package/dist/transactions/commitEnvelope.js +139 -0
  346. package/dist/transactions/commitOutboxStore.d.ts +32 -0
  347. package/dist/transactions/commitOutboxStore.js +26 -0
  348. package/dist/transactions/commitPayload.d.ts +63 -52
  349. package/dist/transactions/commitPayload.js +54 -57
  350. package/dist/transactions/deltaConfirmation.d.ts +20 -22
  351. package/dist/transactions/deltaConfirmation.js +37 -45
  352. package/dist/transactions/httpCommitEnvelope.d.ts +43 -0
  353. package/dist/transactions/httpCommitEnvelope.js +179 -0
  354. package/dist/transactions/optimisticApply.d.ts +49 -0
  355. package/dist/transactions/optimisticApply.js +65 -0
  356. package/dist/transactions/replayValidation.d.ts +182 -0
  357. package/dist/transactions/replayValidation.js +156 -0
  358. package/dist/types/global.d.ts +46 -41
  359. package/dist/types/global.js +20 -19
  360. package/dist/types/index.d.ts +71 -77
  361. package/dist/types/index.js +22 -22
  362. package/dist/types/modelData.d.ts +6 -8
  363. package/dist/types/modelData.js +5 -7
  364. package/dist/types/participant.d.ts +10 -11
  365. package/dist/types/participant.js +6 -8
  366. package/dist/types/streams.d.ts +208 -195
  367. package/dist/types/streams.js +7 -7
  368. package/dist/utils/asyncIterator.d.ts +25 -32
  369. package/dist/utils/asyncIterator.js +25 -32
  370. package/dist/utils/duration.d.ts +12 -15
  371. package/dist/utils/duration.js +12 -15
  372. package/dist/utils/mobxSetup.d.ts +53 -0
  373. package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
  374. package/dist/webhooks/events.d.ts +21 -16
  375. package/dist/webhooks/events.js +10 -8
  376. package/dist/webhooks/index.d.ts +5 -7
  377. package/dist/webhooks/index.js +5 -7
  378. package/dist/wire/bootstrapReason.d.ts +9 -0
  379. package/dist/wire/bootstrapReason.js +8 -0
  380. package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
  381. package/dist/wire/delta.js +114 -0
  382. package/dist/wire/errorEnvelope.d.ts +30 -31
  383. package/dist/wire/errorEnvelope.js +34 -40
  384. package/dist/wire/frames.d.ts +315 -86
  385. package/dist/wire/frames.js +47 -33
  386. package/dist/wire/index.d.ts +18 -14
  387. package/dist/wire/index.js +32 -27
  388. package/dist/wire/listEnvelope.d.ts +16 -23
  389. package/dist/wire/listEnvelope.js +7 -6
  390. package/dist/wire/protocol.d.ts +25 -32
  391. package/dist/wire/protocol.js +25 -32
  392. package/dist/wire/protocolVersion.d.ts +44 -40
  393. package/dist/wire/protocolVersion.js +44 -40
  394. package/docs/api.md +10 -10
  395. package/docs/coordination.md +59 -0
  396. package/docs/mcp.md +1 -1
  397. package/package.json +17 -11
  398. package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
  399. package/dist/ai-sdk/coordination-context.d.ts +0 -52
  400. package/dist/core/query-utils.d.ts +0 -34
  401. package/dist/core/query-utils.js +0 -59
  402. package/dist/schema/sync-delta-row.js +0 -103
  403. package/dist/schema/sync-delta-wire.js +0 -102
  404. package/dist/server/read-config.d.ts +0 -67
  405. package/dist/server/read-config.js +0 -8
  406. package/dist/server/storage-mode.d.ts +0 -8
  407. package/dist/server/storage-mode.js +0 -28
  408. package/dist/source/connector-protocol.d.ts +0 -159
  409. package/dist/source/connector-protocol.js +0 -161
  410. package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
  411. package/dist/transactions/OptimisticEchoTracker.js +0 -104
  412. package/dist/transactions/mutation-error-handler.d.ts +0 -5
  413. package/dist/transactions/mutation-error-handler.js +0 -39
  414. package/dist/transactions/optimistic.d.ts +0 -24
  415. package/dist/transactions/optimistic.js +0 -45
  416. package/dist/transactions/persistedReplay.d.ts +0 -93
  417. package/dist/transactions/persistedReplay.js +0 -105
  418. package/dist/utils/mobx-setup.d.ts +0 -42
package/docs/api.md CHANGED
@@ -206,27 +206,27 @@ The SDK is a convenience wrapper over a model-scoped HTTP surface — the same
206
206
  noun (`model`) and verbs as `ablo.<model>.…`. Non-JS callers (or curl) use it
207
207
  directly. The table below shows the shape with `{model}` as a placeholder; the
208
208
  [OpenAPI spec](./openapi.json) expands it into one **typed** path per model
209
- (`/v1/models/task`, `/v1/models/deck`, …, generated from your schema) so each
209
+ (`/api/v1/models/task`, `/api/v1/models/deck`, …, generated from your schema) so each
210
210
  endpoint documents that model's real field contract instead of a generic blob.
211
211
 
212
212
  | SDK call | HTTP |
213
213
  |---|---|
214
- | `ablo.<model>.create({ data })` | `POST /v1/models/{model}` |
215
- | `ablo.<model>.list({ where })` | `GET /v1/models/{model}` |
216
- | `ablo.<model>.retrieve({ id })` | `GET /v1/models/{model}/{id}` |
217
- | `ablo.<model>.update({ id, data })` | `PATCH /v1/models/{model}/{id}` |
218
- | `ablo.<model>.delete({ id })` | `DELETE /v1/models/{model}/{id}` |
219
- | `ablo.<model>.claim({ id })` | `POST /v1/models/{model}/{id}/claim` |
220
- | (release a claim) | `DELETE /v1/models/{model}/{id}/claim` |
214
+ | `ablo.<model>.create({ data })` | `POST /api/v1/models/{model}` |
215
+ | `ablo.<model>.list({ where })` | `GET /api/v1/models/{model}` |
216
+ | `ablo.<model>.retrieve({ id })` | `GET /api/v1/models/{model}/{id}` |
217
+ | `ablo.<model>.update({ id, data })` | `PATCH /api/v1/models/{model}/{id}` |
218
+ | `ablo.<model>.delete({ id })` | `DELETE /api/v1/models/{model}/{id}` |
219
+ | `ablo.<model>.claim({ id })` | `POST /api/v1/models/{model}/{id}/claim` |
220
+ | (release a claim) | `DELETE /api/v1/models/{model}/{id}/claim` |
221
221
 
222
222
  Auth is a bearer API key: `Authorization: Bearer sk_…`. Mutations take an
223
223
  `Idempotency-Key` header — derive it from the business event, not a random
224
224
  value, so a retry never double-writes. Writes return a `CommitReceipt`; a
225
225
  rejected write carries an error `code` (e.g. `stale_context`, `intent_conflict`)
226
- to act on. `GET /v1/models/{model}` is cursor-paginated (`limit`, `order`,
226
+ to act on. `GET /api/v1/models/{model}` is cursor-paginated (`limit`, `order`,
227
227
  `order_by`, `starting_after`) and returns `{ data, has_more, next_cursor }`.
228
228
 
229
- `POST /v1/commits` remains the path for **atomic multi-op** writes (several
229
+ `POST /api/v1/commits` remains the path for **atomic multi-op** writes (several
230
230
  operations across rows/models that must commit together) — the per-model routes
231
231
  above are the one-record path. Both run the identical guarded-write engine.
232
232
 
@@ -416,6 +416,65 @@ try {
416
416
  }
417
417
  ```
418
418
 
419
+ ### `heartbeat` — holding a claim for long-running work
420
+
421
+ ```ts
422
+ held.heartbeat(ttl?: Duration): Promise<{ expiresAt: number }>
423
+ ```
424
+
425
+ A claim's TTL is crash cleanup, not a work-duration estimate — so a task that
426
+ outlives it (an agent run, a background worker's job) keeps its lease by
427
+ **beating**, the same pattern as an SQS visibility heartbeat or a Temporal
428
+ activity heartbeat. Each beat extends the lease from now (never shortens it,
429
+ and each extension is clamped server-side); a crashed worker stops beating and
430
+ its lease lapses within one beat window, promoting the next waiter.
431
+
432
+ Usually **implicit** — pass `heartbeat` when claiming and the SDK beats every
433
+ third of the TTL until release:
434
+
435
+ ```ts
436
+ await using claim = await ablo.reports.claim({
437
+ id: 'report_q3',
438
+ reason: 'generating',
439
+ ttl: '5m',
440
+ heartbeat: true, // or an explicit cadence: heartbeat: '2m'
441
+ onHeartbeatLost: () => abortWork(),
442
+ });
443
+ await runLongGeneration(claim.data); // lease held for the duration
444
+ // scope exit releases; the loop stops with it
445
+ ```
446
+
447
+ A beat that comes back with a definitive loss — the lease expired and the
448
+ queue moved on — rejects with `AbloClaimedError` (`claim_lost`) and stops the
449
+ auto-loop. For a worker with no socket, **the failed beat is the loss
450
+ notification**; abandon or re-claim, and remember any write attempted under
451
+ the old lease is independently rejected by its `readAt` guard. Transient
452
+ failures (a connection blip) don't stop the loop — the next tick retries.
453
+
454
+ Each beat's answer carries two more things:
455
+
456
+ - **`queueDepth`** — how many participants wait in line behind the lease.
457
+ This is the cooperative-yield pressure signal: a worker that can checkpoint
458
+ may release early when others wait. Read it from the resolved beat, or pass
459
+ `onHeartbeat` when claiming to observe every auto-beat.
460
+ - **progress `details`** — `held.heartbeat({ details: { pages: 42, of: 100 } })`
461
+ stores the payload as the claim's peer-visible `meta.progress` (last beat
462
+ wins, via `claim.state`). This is presence, not a checkpoint: it dies with
463
+ the lease. Durable progress belongs in the data itself — write a row, and
464
+ every subscriber already sees it.
465
+
466
+ Works identically on both transports: the realtime client sends a
467
+ `claim_heartbeat` frame; the HTTP client posts
468
+ `POST /api/v1/models/{model}/{id}/claim/heartbeat` (`{ ttl?, claimId?, details? }`).
469
+ Over HTTP, a **queued** claim can heartbeat too — it refreshes the waiter's
470
+ slot in the line (a queued slot is TTL'd like a lease) and reports
471
+ `{ status: 'queued', position }`.
472
+
473
+ A stateless worker holding **many** rows beats them all in one round trip:
474
+ `ablo.claims.heartbeatAll({ ttl: '5m' })` → `POST /api/v1/claims/heartbeat`, one
475
+ entry per extended lease. This is the socketless twin of the realtime
476
+ keepalive, which already renews every held lease on each ping.
477
+
419
478
  ### `watch` — presence for a set of rows
420
479
 
421
480
  Reading or claiming a row auto-enrolls you in its sync group, which is enough for
package/docs/mcp.md CHANGED
@@ -16,7 +16,7 @@ edits rows → coordination; teaching your IDE assistant the SDK → helper.
16
16
  ## Coordination server (`@ablo/mcp`)
17
17
 
18
18
  The coordination server is the MCP projection of the model-scoped API
19
- (`/v1/models/...`) — the same surface as `ablo.<model>.create/update/claim` and
19
+ (`/api/v1/models/...`) — the same surface as `ablo.<model>.create/update/claim` and
20
20
  the REST routes, rendered as tools. An agent connects with your API key and
21
21
  gets one safe loop: **claim → read → commit → release.**
22
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "The Collaboration Layer For AI Agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -28,6 +28,11 @@
28
28
  "import": "./dist/coordination/index.js",
29
29
  "default": "./dist/coordination/index.js"
30
30
  },
31
+ "./commit": {
32
+ "types": "./dist/commit/index.d.ts",
33
+ "import": "./dist/commit/index.js",
34
+ "default": "./dist/commit/index.js"
35
+ },
31
36
  "./react": {
32
37
  "types": "./dist/react/index.d.ts",
33
38
  "import": "./dist/react/index.js",
@@ -150,10 +155,10 @@
150
155
  "pretest": "node scripts/check-dist-fresh.mjs",
151
156
  "test": "jest",
152
157
  "test:quickstart": "node scripts/test-quickstart.mjs",
153
- "test:unit": "jest --testPathPattern=__tests__/unit",
154
- "test:integration": "jest --testPathPattern=__tests__/integration",
155
- "test:contract": "jest --testPathPattern=__tests__/contract",
156
- "test:property": "jest --testPathPattern=__tests__/property",
158
+ "test:unit": "jest --testPathPatterns __tests__/unit",
159
+ "test:integration": "jest --testPathPatterns __tests__/integration",
160
+ "test:contract": "jest --testPathPatterns __tests__/contract",
161
+ "test:property": "jest --testPathPatterns __tests__/property",
157
162
  "test:coverage": "jest --coverage",
158
163
  "test:e2e": "E2E_TEST=true jest --config jest.e2e.config.ts",
159
164
  "test:e2e:up": "docker compose -f docker-compose.test.yml up -d --wait",
@@ -207,14 +212,14 @@
207
212
  "mobx": "^6.13.7",
208
213
  "mobx-react-lite": "^4.0.0",
209
214
  "uuid": "^11.1.0",
210
- "zod": "^4.0.17"
215
+ "zod": "^4.1.11"
211
216
  },
212
217
  "devDependencies": {
213
218
  "@ai-sdk/provider": "^3.0.0",
214
219
  "@clack/prompts": "^0.11.0",
215
- "@jest/globals": "^29.7.0",
220
+ "@jest/globals": "^30.2.0",
216
221
  "@prisma/client": "^7.3.0",
217
- "@types/jest": "^29.5.0",
222
+ "@types/jest": "^30.0.0",
218
223
  "@types/node": "^22.0.0",
219
224
  "@types/react": "^19.0.0",
220
225
  "@types/uuid": "^10.0.0",
@@ -225,13 +230,14 @@
225
230
  "fake-indexeddb": "^6.0.0",
226
231
  "fast-check": "^3.0.0",
227
232
  "globals": "^16.5.0",
228
- "jest": "^29.7.0",
229
- "jest-environment-jsdom": "^29.7.0",
233
+ "jest": "^30.2.0",
234
+ "jest-environment-jsdom": "^30.2.0",
235
+ "jest-environment-node": "^30.2.0",
230
236
  "picocolors": "^1.1.0",
231
237
  "postgres": "^3.4.0",
232
238
  "react": "^19.0.0",
233
239
  "react-dom": "^19.0.0",
234
- "ts-jest": "^29.4.0",
240
+ "ts-jest": "^29.4.5",
235
241
  "ts-morph": "^26.0.0",
236
242
  "tsup": "^8.0.0",
237
243
  "tsx": "^4.19.0",
@@ -1,101 +0,0 @@
1
- /**
2
- * `coordinatedTool` — the one-liner that turns an Ablo model write into a Vercel
3
- * AI SDK tool with multi-agent coordination already handled, so an AI agent can
4
- * contribute to shared state without ever silently clobbering a concurrent
5
- * writer.
6
- *
7
- * The base `./ai-sdk` pattern (see index.ts) is "write your own `tool()` and
8
- * call `ablo.<model>.update({ id, data, claim })` inside `execute`". That's the
9
- * right amount of control when a tool does something bespoke. But the *common*
10
- * case — "the agent produced some content; save it into the shared row" — should
11
- * not require every integration to re-derive optimistic concurrency by hand. This
12
- * collapses it to a declaration:
13
- *
14
- * ```ts
15
- * import { coordinatedTool } from '@abloatai/ablo/ai-sdk';
16
- * import { z } from 'zod';
17
- *
18
- * const saveSection = coordinatedTool(ablo.documents, {
19
- * description: 'Save your section into the shared document.',
20
- * inputSchema: z.object({ text: z.string() }),
21
- * id: () => DOC_ID,
22
- * apply: (current, { text }) => ({ content: appendBlock(current.content, text) }),
23
- * // strategy: 'merge' ← the default
24
- * });
25
- *
26
- * await streamText({ model, messages, tools: { saveSection } });
27
- * ```
28
- *
29
- * `apply` is the whole API: a pure function of `(freshest row, tool input) →
30
- * patch`, exactly like React's `setState(prev => next)`. Everything underneath —
31
- * reading the latest row, the compare-and-swap, the jittered backoff between
32
- * reconcile rounds, releasing claims — is the runtime's job, not yours.
33
- *
34
- * ## Strategies (pick by how writers should relate; all verified to converge
35
- * under N-way agent contention)
36
- *
37
- * - `'merge'` *(default)* — delegates straight to the functional update
38
- * `ablo.<model>.update(id, current => apply(current, input))`. The SDK re-reads
39
- * and re-applies `apply` on top of every concurrent write and backs off between
40
- * rounds, so N agents *accumulate* into one row and the model never sees a
41
- * conflict. **Requires the model's agent conflict policy to be `reject`** (the
42
- * default, or `agentsReject()`); a model declaring `agentsNotify()` HOLDS the
43
- * losing write instead of rejecting it, which defeats the reconcile — use
44
- * `claim`/`queue` there, or switch the policy.
45
- *
46
- * - `'claim'` — mutual exclusion. Takes a fail-fast claim; if another participant
47
- * holds the row it returns `{ status: 'claimed' }` so the *model* decides to
48
- * retry (a legible signal beats a hidden wait when the agent might do something
49
- * better with its turn). Works regardless of conflict policy.
50
- *
51
- * - `'queue'` — fair-ish serialization over stateless HTTP, the SQS shape: a
52
- * client poll-acquire loop (true FIFO needs a socket) until the claim is granted
53
- * or `poll.timeoutMs` elapses. The model calls once and the tool waits its turn.
54
- */
55
- import type { z } from 'zod';
56
- import type { ModelOperations } from '../client/createModelProxy.js';
57
- export type CoordinationStrategy = 'merge' | 'claim' | 'queue';
58
- /** The structured result the tool hands back to the model (or the caller). */
59
- export interface CoordinatedWriteResult<T> {
60
- /**
61
- * `'written'` — saved. `'claimed'` — another participant holds the row; NOT
62
- * saved, the model should try again. `'timeout'` — the queue strategy could not
63
- * acquire the row within `poll.timeoutMs`.
64
- */
65
- status: 'written' | 'claimed' | 'timeout';
66
- /** The reconciled row, on `'written'`. */
67
- row?: T;
68
- message?: string;
69
- /** On `'written'` via the `queue` strategy, how long the tool waited in line. */
70
- waitedMs?: number;
71
- }
72
- export interface CoordinatedToolOptions<TInput, T> {
73
- /** Tool description shown to the model. */
74
- description: string;
75
- /** What the model may send — a normal AI SDK / zod input schema. */
76
- inputSchema: z.ZodType<TInput>;
77
- /** Which row this write targets, derived from the tool input. */
78
- id: (input: TInput) => string;
79
- /**
80
- * Produce the write patch from the freshest current row + the tool input — a
81
- * pure `(prev, input) => next`. Under `merge` it re-runs on every concurrent
82
- * write, so it must be idempotent w.r.t. its own contribution (e.g. skip if its
83
- * marker is already present) to be safe across reconcile rounds.
84
- */
85
- apply: (current: T, input: TInput) => Partial<T>;
86
- /** How concurrent writers relate. Defaults to `'merge'`. */
87
- strategy?: CoordinationStrategy;
88
- /** Human-legible coordination metadata attached to the claim (`claim`/`queue`). */
89
- claim?: {
90
- reason?: string;
91
- description?: string;
92
- };
93
- /** Reconcile budget for `merge` (rounds before `AbloContentionError`). */
94
- retries?: number;
95
- /** Poll cadence / ceiling for `queue` (defaults 250ms / 30s). */
96
- poll?: {
97
- intervalMs?: number;
98
- timeoutMs?: number;
99
- };
100
- }
101
- export declare function coordinatedTool<TInput, T = Record<string, unknown>, CreateInput = Partial<T>>(model: ModelOperations<T, CreateInput>, options: CoordinatedToolOptions<TInput, T>): import("ai").Tool<TInput, CoordinatedWriteResult<T>>;
@@ -1,52 +0,0 @@
1
- /**
2
- * Coordination context middleware — reads peer claims on the same
3
- * entity from the sync engine's presence stream and injects a brief
4
- * coordination note into the prompt before the LLM call.
5
- *
6
- * The complement of `claim-broadcast.ts`: that one declares what
7
- * THIS agent is about to do; this one reads what OTHERS are doing
8
- * and tells the LLM about it. Together they make multiplayer-with-
9
- * AI structurally real — the AI knows when a human or another
10
- * agent is mid-edit and can defer / phrase its work as
11
- * "while you finish that, I'll …" / suggest waiting / coordinate
12
- * explicitly.
13
- *
14
- * Open-source-clean: depends only on `@ai-sdk/provider` types and
15
- * the package's own `SyncAgent`. Consumers compose via the AI
16
- * SDK's `wrapLanguageModel`.
17
- *
18
- * Cost: zero extra LLM calls (read happens locally from the agent's
19
- * cached presence stream — already in memory from the WS subscription).
20
- * Adds a few sentences to the system prompt (typically <100 tokens)
21
- * only when peers are actively editing.
22
- */
23
- import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
24
- import type { Ablo } from '../client/Ablo.js';
25
- import type { SchemaRecord } from '../schema/schema.js';
26
- import type { ClaimTarget } from '../types/streams.js';
27
- export type { ClaimTarget };
28
- export interface CoordinationContextMiddlewareOptions<R extends SchemaRecord = SchemaRecord> {
29
- readonly agent: Ablo<R> | null;
30
- readonly target: ClaimTarget | null;
31
- /**
32
- * Optional claimId(s) to exclude from the read — typically this
33
- * agent's own active claim so the coordination note doesn't tell
34
- * the AI "you yourself are editing this." When middleware is
35
- * composed with `claimBroadcastMiddleware` in the standard order,
36
- * `transformParams` runs BEFORE the broadcast's `wrapStream`
37
- * declares its claim, so the agent's own claim isn't yet in the
38
- * cached presence and self-filtering isn't needed. The hook is
39
- * here for callers that compose differently or for fleet
40
- * coordination (filter sibling worker claims).
41
- */
42
- readonly excludeClaimIds?: readonly string[];
43
- }
44
- /**
45
- * Build the middleware. When `agent` or `target` is null, returns a
46
- * pass-through.
47
- *
48
- * Generic over the schema record — see `claimBroadcastMiddleware`
49
- * for why `Ablo<S>` and `Ablo<SchemaRecord>` aren't structurally
50
- * assignable.
51
- */
52
- export declare function coordinationContextMiddleware<R extends SchemaRecord = SchemaRecord>(options: CoordinationContextMiddlewareOptions<R>): LanguageModelV3Middleware;
@@ -1,34 +0,0 @@
1
- /**
2
- * query-utils — Pure query helpers for the MobX `QueryView`. One source of
3
- * truth for sort, filter, and binary insertion logic.
4
- *
5
- * No MobX, no ObjectPool, no Model — just arrays and values.
6
- */
7
- /**
8
- * The incremental-update contract a view satisfies. `ViewRegistry` stores views
9
- * as this base type so it can dispatch to many views with different `T`
10
- * parameters from one Set — `View<T>` is invariant in T, so without this shared
11
- * base the registry would have to widen via `unknown as View<Record<...>>` at
12
- * every register/unregister/notify call.
13
- */
14
- export interface IncrementalView {
15
- handleAdded(entity: Record<string, unknown>): void;
16
- handleUpdated(entity: Record<string, unknown>): void;
17
- handleRemoved(id: string): void;
18
- }
19
- /** Compare two values for sorting, null-safe. Returns -1 | 0 | 1. */
20
- export declare function compareValues(a: unknown, b: unknown, dir: 1 | -1): number;
21
- /**
22
- * Binary search for the correct insertion index in a sorted array.
23
- * Returns the index at which `item` should be inserted.
24
- */
25
- export declare function binaryInsertionIndex<T>(arr: ArrayLike<T>, item: T, sortKey: string, dir: 1 | -1): number;
26
- /**
27
- * Check whether an entity matches a declarative `where` clause.
28
- * Every key in `where` must exactly match the entity's value.
29
- */
30
- export declare function matchesWhere<T extends Record<string, unknown>>(entity: T, where: Partial<T>): boolean;
31
- /**
32
- * Find the index of an entity by id in an array. Returns -1 if not found.
33
- */
34
- export declare function findIndexById<T extends Record<string, unknown>>(arr: ArrayLike<T>, id: string): number;
@@ -1,59 +0,0 @@
1
- /**
2
- * query-utils — Pure query helpers for the MobX `QueryView`. One source of
3
- * truth for sort, filter, and binary insertion logic.
4
- *
5
- * No MobX, no ObjectPool, no Model — just arrays and values.
6
- */
7
- /** Compare two values for sorting, null-safe. Returns -1 | 0 | 1. */
8
- export function compareValues(a, b, dir) {
9
- if (a === b)
10
- return 0;
11
- if (a == null)
12
- return 1;
13
- if (b == null)
14
- return -1;
15
- return (a < b ? -1 : 1) * dir;
16
- }
17
- /**
18
- * Binary search for the correct insertion index in a sorted array.
19
- * Returns the index at which `item` should be inserted.
20
- */
21
- export function binaryInsertionIndex(arr, item, sortKey, dir) {
22
- let lo = 0;
23
- let hi = arr.length;
24
- const itemVal = item[sortKey];
25
- while (lo < hi) {
26
- const mid = (lo + hi) >>> 1;
27
- const midVal = arr[mid][sortKey];
28
- if (compareValues(midVal, itemVal, dir) <= 0) {
29
- lo = mid + 1;
30
- }
31
- else {
32
- hi = mid;
33
- }
34
- }
35
- return lo;
36
- }
37
- /**
38
- * Check whether an entity matches a declarative `where` clause.
39
- * Every key in `where` must exactly match the entity's value.
40
- */
41
- export function matchesWhere(entity, where) {
42
- for (const [key, value] of Object.entries(where)) {
43
- if (value === undefined)
44
- continue;
45
- if (entity[key] !== value)
46
- return false;
47
- }
48
- return true;
49
- }
50
- /**
51
- * Find the index of an entity by id in an array. Returns -1 if not found.
52
- */
53
- export function findIndexById(arr, id) {
54
- for (let i = 0; i < arr.length; i++) {
55
- if (arr[i]?.id === id)
56
- return i;
57
- }
58
- return -1;
59
- }
@@ -1,103 +0,0 @@
1
- /**
2
- * Canonical Zod description of the `sync_deltas` STORAGE ROW, decomposed by the
3
- * subsystem it belongs to and the database plane it lives in.
4
- *
5
- * `sync_deltas` fuses five control-plane subsystems onto one denormalized row
6
- * (see `docs/plans/sync-delta-zod-decomposition.md`). This module is **P0** of
7
- * that decomposition: it DESCRIBES the existing columns as Zod schemas — no DB
8
- * change, no rewiring — so the subsystem + plane boundaries become explicit and
9
- * type-enforced:
10
- *
11
- * - {@link syncDeltaCoreSchema} — the SYNC-PROTOCOL slice. `tenant` plane:
12
- * the only part that must be written
13
- * atomically with the app row, and the shape
14
- * a BYO outbox marker carries (the portable
15
- * slice).
16
- * - {@link deltaAttributionSchema} — who / on whose authority. `control` plane.
17
- * - {@link deltaProvenanceSchema} — which AI task caused it. `control` plane.
18
- *
19
- * {@link syncDeltaRowSchema} is the full stored row (core ∪ attribution ∪
20
- * provenance). {@link DELTA_RESIDENCY} declares each slice's plane so provisioning
21
- * (P1) can derive "what a customer DB gets" from the schema, not hand-code it.
22
- *
23
- * Distinct from the WIRE `SyncDelta` (`sync/SyncWebSocket.ts`, client-facing) and
24
- * `SourceDelta` (`source/index.ts`, source-mode input) — those are projections of
25
- * this row. Field names mirror those + `AuditChainRow` (`@ablo/audit-chain`).
26
- *
27
- * Monorepo is on Zod v4 — `.extend(...).shape` (not deprecated `.merge`).
28
- */
29
- import { z } from 'zod';
30
- // ── Enums (mirror the Postgres enums; @@map name in the comment) ──────────────
31
- /** `participant_kind` */
32
- export const participantKindSchema = z.enum(['user', 'agent', 'system']);
33
- /** `confirmation_state` */
34
- export const confirmationStateSchema = z.enum([
35
- 'auto',
36
- 'previewed',
37
- 'approved',
38
- 'required_human_approval',
39
- 'auto_historical',
40
- ]);
41
- /** `backfill_provenance` */
42
- export const backfillProvenanceSchema = z.enum(['exact', 'inferred', 'unknown']);
43
- /** A delta payload: the full post-mutation row (or null for deletes). */
44
- const deltaDataSchema = z.record(z.string(), z.unknown()).nullable();
45
- // ── Core — `tenant` plane (the sync-protocol slice) ───────────────────────────
46
- /**
47
- * Everything a client needs to materialize the change, plus the tenant key. The
48
- * portable slice: the only part written atomically with the app row, and the
49
- * shape a BYO outbox marker carries. `id` / `createdAt` / `syncGroups` are
50
- * control-plane-assigned at enrich/append time, so they're optional here (an
51
- * outbox marker doesn't have them yet).
52
- */
53
- export const syncDeltaCoreSchema = z.object({
54
- /** Monotonic sync id; assigned control-plane on append (absent on a marker). */
55
- id: z.union([z.bigint(), z.number()]).optional(),
56
- /** `action_type` — single char: `I` | `U` | `D`. */
57
- actionType: z.string().min(1).max(1),
58
- modelName: z.string().min(1),
59
- modelId: z.string().min(1),
60
- data: deltaDataSchema,
61
- previousData: deltaDataSchema.optional(),
62
- /** Sync-group routing keys; computed control-plane (`buildDeltaSyncGroups`). */
63
- syncGroups: z.array(z.string()).optional(),
64
- /** The TRUSTED committing org — the coarse tenant-isolation boundary. */
65
- organizationId: z.string().nullable(),
66
- /** ISO timestamp; control-plane-assigned at append. */
67
- createdAt: z.string().optional(),
68
- transactionId: z.string().nullable(),
69
- });
70
- // ── Attribution — `control` plane ─────────────────────────────────────────────
71
- export const deltaAttributionSchema = z.object({
72
- /** Legacy single-actor column, derived during the dual-write window. */
73
- createdBy: z.string().nullable(),
74
- actorId: z.string().nullable(),
75
- actorKind: participantKindSchema.nullable(),
76
- onBehalfOfId: z.string().nullable(),
77
- onBehalfOfKind: participantKindSchema.nullable(),
78
- capabilityId: z.string().nullable(),
79
- delegationChainRootUserId: z.string().nullable().optional(),
80
- confirmationState: confirmationStateSchema.nullable(),
81
- backfillProvenance: backfillProvenanceSchema.nullable(),
82
- });
83
- // ── Provenance — `control` plane (→ tasks) ────────────────────────────────────
84
- export const deltaProvenanceSchema = z.object({
85
- /** FK to `Task.id` — the LLM turn that produced this commit. */
86
- causedByTaskId: z.string().nullable(),
87
- });
88
- // ── Full stored row + plane map ───────────────────────────────────────────────
89
- /** The complete `sync_deltas` row as stored today (core ∪ attribution ∪ provenance). */
90
- export const syncDeltaRowSchema = syncDeltaCoreSchema
91
- .extend(deltaAttributionSchema.shape)
92
- .extend(deltaProvenanceSchema.shape);
93
- /**
94
- * Each slice's database plane. The durable answer to "what does a BYO customer DB
95
- * get?" — only `tenant`-plane slices. Provisioning (P1) reads this instead of
96
- * hand-coding the boundary; the BYO outbox writes the `tenant` slice and the
97
- * relay enriches the `control` slices in Ablo's own database.
98
- */
99
- export const DELTA_RESIDENCY = {
100
- core: 'tenant',
101
- attribution: 'control',
102
- provenance: 'control',
103
- };
@@ -1,102 +0,0 @@
1
- /**
2
- * Canonical Zod contract for the WIRE delta — the broadcast object that travels
3
- * server → client (the `delta` / `sync_response` frame payload). This is the
4
- * "same contract across both" seam: the SDK client and the sync-server each
5
- * derive their `SyncDelta` type from THESE schemas via `z.infer`, instead of
6
- * hand-maintaining two interfaces that drift (they had: the server typed
7
- * `actionType` as `string` and `createdBy` as a nested ref; the client typed
8
- * `actionType` as the 8-value union and `createdBy` as a flat string — a silent
9
- * divergence the client never noticed because it ignores attribution).
10
- *
11
- * Distinct from {@link import('./sync-delta-row.js').syncDeltaRowSchema} — that
12
- * is the STORED ROW (has `organizationId`, flat `actor_id`/`actor_kind`
13
- * columns, single-char action). The wire delta is a PROJECTION: no
14
- * `organizationId` (the server-trusted isolation predicate is never broadcast),
15
- * the full Linear action vocabulary, and attribution hydrated into nested
16
- * {@link ParticipantRef}s.
17
- *
18
- * Shape (per the "shared core + layer extensions" decision):
19
- * - {@link syncDeltaWireCoreSchema} — the fields BOTH sides agree on.
20
- * - {@link clientSyncDeltaSchema} — core + the SDK-only extras.
21
- * - {@link serverSyncDeltaSchema} — core + the audit attribution the server
22
- * enriches each broadcast with (the client
23
- * structurally ignores these).
24
- *
25
- * Monorepo is on Zod v4.
26
- */
27
- import { z } from 'zod';
28
- import { participantKindSchema, confirmationStateSchema } from './sync-delta-row.js';
29
- /**
30
- * `action_type` on the WIRE — the full Linear-compatible vocabulary a broadcast
31
- * carries (vs the stored row's core CRUD). `I`nsert, `U`pdate, `D`elete,
32
- * `A`rchive, `V` reVive/unarchive, `C`overing (gained visibility), `G`roupAdded,
33
- * `S` groupRemoved.
34
- */
35
- export const syncDeltaActionSchema = z.enum(['I', 'U', 'D', 'A', 'V', 'C', 'G', 'S']);
36
- /**
37
- * A wire delta payload: the post-mutation row object, a control-frame STRING
38
- * (e.g. a serialized group-change payload on `G`/`S` deltas), or `null` (on
39
- * deletes). Wider than the stored `data` (row-or-null) precisely because the
40
- * group/permission frames serialize a string.
41
- */
42
- export const wireDeltaDataSchema = z
43
- .union([z.record(z.string(), z.unknown()), z.string()])
44
- .nullable();
45
- /**
46
- * A nested participant reference as carried on a BROADCAST delta. The server
47
- * hydrates the flat `actor_id`/`actor_kind` stored columns into this.
48
- */
49
- export const participantRefSchema = z.object({
50
- kind: participantKindSchema,
51
- id: z.string(),
52
- });
53
- /**
54
- * The fields BOTH server and client agree on for a broadcast delta — the shared
55
- * contract. `transactionId` is modelled as the client sees it (optional string);
56
- * the server projection widens it to nullable. No `organizationId` (never
57
- * broadcast). No `createdBy`/attribution here — those types differ per layer and
58
- * live in the extensions below.
59
- */
60
- export const syncDeltaWireCoreSchema = z.object({
61
- id: z.number(),
62
- actionType: syncDeltaActionSchema,
63
- modelName: z.string().min(1),
64
- modelId: z.string().min(1),
65
- data: wireDeltaDataSchema,
66
- previousData: wireDeltaDataSchema.optional(),
67
- syncGroups: z.array(z.string()),
68
- transactionId: z.string().optional(),
69
- createdAt: z.string(),
70
- });
71
- /**
72
- * Client projection — core + the SDK-only fields the client reads locally.
73
- * `z.infer` of this is the SDK's `SyncDelta` (see `sync/SyncWebSocket.ts`).
74
- */
75
- export const clientSyncDeltaSchema = syncDeltaWireCoreSchema.extend({
76
- /** @deprecated Flat actor id; superseded by the server's nested `actor`. The
77
- * client never reads it — kept only so the wire shape round-trips. */
78
- createdBy: z.string().optional(),
79
- /** Client-only payload slot (e.g. legacy group-change metadata). */
80
- metadata: wireDeltaDataSchema.optional(),
81
- /** Echo-matching id the client correlates against its optimistic mutation. */
82
- clientMutationId: z.string().optional(),
83
- });
84
- /**
85
- * Server projection — core + the audit attribution the server enriches each
86
- * broadcast with (for the audit pane). The client ignores all of it. Overrides
87
- * `transactionId` to nullable (the server's stored-column reality).
88
- */
89
- export const serverSyncDeltaSchema = syncDeltaWireCoreSchema.extend({
90
- transactionId: z.string().nullable(),
91
- /** @deprecated Mirrors `actor` 1:1. */
92
- createdBy: participantRefSchema.nullable(),
93
- /** Who DID the action. */
94
- actor: participantRefSchema.nullable(),
95
- /** On WHOSE AUTHORITY they acted (equals `actor` for human-direct commits). */
96
- onBehalfOf: participantRefSchema.nullable(),
97
- /** FK to AgentCapabilityRoot.capabilityId; non-null for agent/system commits. */
98
- capabilityId: z.string().nullable(),
99
- confirmationState: confirmationStateSchema.nullable(),
100
- /** FK to AgentTurn.id — the prompt that caused this delta. */
101
- causedByTaskId: z.string().nullable(),
102
- });