@abloatai/ablo 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/CHANGELOG.md +713 -629
  2. package/README.md +56 -519
  3. package/bin/ablo.cjs +39 -0
  4. package/dist/BaseSyncedStore.d.ts +24 -4
  5. package/dist/BaseSyncedStore.js +53 -37
  6. package/dist/Database.d.ts +8 -20
  7. package/dist/Database.js +61 -59
  8. package/dist/InstanceCache.d.ts +6 -2
  9. package/dist/InstanceCache.js +18 -16
  10. package/dist/Model.d.ts +17 -7
  11. package/dist/Model.js +17 -7
  12. package/dist/ModelRegistry.d.ts +4 -0
  13. package/dist/ModelRegistry.js +17 -15
  14. package/dist/NetworkMonitor.d.ts +3 -1
  15. package/dist/NetworkMonitor.js +7 -5
  16. package/dist/SyncClient.d.ts +5 -15
  17. package/dist/SyncClient.js +60 -57
  18. package/dist/client/Ablo.js +30 -19
  19. package/dist/client/createInternalComponents.d.ts +4 -0
  20. package/dist/client/createInternalComponents.js +8 -2
  21. package/dist/client/createModelProxy.d.ts +21 -1
  22. package/dist/client/createModelProxy.js +123 -57
  23. package/dist/client/humans.d.ts +30 -9
  24. package/dist/client/humans.js +45 -19
  25. package/dist/client/reactiveEngine.d.ts +16 -11
  26. package/dist/client/reactiveEngine.js +113 -335
  27. package/dist/client/storeCluster.d.ts +47 -0
  28. package/dist/client/storeCluster.js +118 -0
  29. package/dist/client/storeLifecycle.d.ts +61 -0
  30. package/dist/client/storeLifecycle.js +231 -0
  31. package/dist/context.d.ts +13 -0
  32. package/dist/context.js +23 -0
  33. package/dist/core/index.d.ts +1 -1
  34. package/dist/docs/catalog.js +6 -3
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/dist/query/client.d.ts +3 -0
  38. package/dist/query/client.js +6 -5
  39. package/dist/react/AbloProvider.d.ts +13 -1
  40. package/dist/react/AbloProvider.js +5 -2
  41. package/dist/react/context.d.ts +2 -2
  42. package/dist/react/createAbloReact.d.ts +56 -0
  43. package/dist/react/createAbloReact.js +51 -0
  44. package/dist/react/index.d.ts +1 -0
  45. package/dist/react/index.js +3 -0
  46. package/dist/react/useAblo.d.ts +9 -2
  47. package/dist/react/useAblo.js +25 -7
  48. package/dist/schema/coordination.js +5 -1
  49. package/dist/schema/index.d.ts +1 -0
  50. package/dist/schema/index.js +4 -0
  51. package/dist/schema/select.js +3 -0
  52. package/dist/schema/serialize.js +3 -0
  53. package/dist/source/adapter.d.ts +7 -5
  54. package/dist/source/adapter.js +7 -5
  55. package/dist/source/index.d.ts +1 -1
  56. package/dist/source/index.js +1 -1
  57. package/dist/{core/storeContract.d.ts → storeContract.d.ts} +5 -5
  58. package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
  59. package/dist/{core → stores}/DatabaseManager.js +13 -12
  60. package/dist/{core → stores}/StoreManager.d.ts +5 -3
  61. package/dist/{core → stores}/StoreManager.js +24 -22
  62. package/dist/stores/SyncActionStore.d.ts +3 -1
  63. package/dist/stores/SyncActionStore.js +9 -7
  64. package/dist/sync/BootstrapFetcher.d.ts +4 -0
  65. package/dist/sync/BootstrapFetcher.js +28 -26
  66. package/dist/sync/OnDemandLoader.d.ts +3 -0
  67. package/dist/sync/OnDemandLoader.js +1 -0
  68. package/dist/sync/bootstrapApply.d.ts +3 -0
  69. package/dist/sync/bootstrapApply.js +2 -2
  70. package/dist/sync/deltaPipeline.d.ts +13 -12
  71. package/dist/sync/deltaPipeline.js +21 -4
  72. package/dist/sync/groupChange.d.ts +3 -0
  73. package/dist/sync/groupChange.js +16 -14
  74. package/dist/sync/participants.d.ts +19 -2
  75. package/dist/sync/participants.js +3 -1
  76. package/dist/sync/schemas.d.ts +2 -1
  77. package/dist/sync/schemas.js +3 -3
  78. package/dist/syncLog/contract.d.ts +20 -0
  79. package/dist/syncLog/contract.js +19 -0
  80. package/dist/syncLog/index.d.ts +1 -0
  81. package/dist/syncLog/index.js +1 -0
  82. package/dist/transaction/auth/capability.d.ts +35 -0
  83. package/dist/transaction/auth/capability.js +25 -0
  84. package/dist/transaction/coordination/awaitClaimGrant.d.ts +7 -0
  85. package/dist/transaction/coordination/awaitClaimGrant.js +12 -0
  86. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +34 -0
  87. package/dist/transaction/coordination/claimHeartbeatLoop.js +20 -0
  88. package/dist/transaction/coordination/index.d.ts +4 -4
  89. package/dist/transaction/coordination/index.js +4 -3
  90. package/dist/transaction/coordination/locator.d.ts +23 -2
  91. package/dist/transaction/coordination/locator.js +22 -2
  92. package/dist/transaction/coordination/schema.d.ts +125 -62
  93. package/dist/transaction/coordination/schema.js +228 -64
  94. package/dist/transaction/coordination/targetConflict.js +32 -28
  95. package/dist/transaction/errorCodes.d.ts +2 -2
  96. package/dist/transaction/errorCodes.js +13 -9
  97. package/dist/transaction/plugin.d.ts +95 -2
  98. package/dist/transaction/plugin.js +21 -2
  99. package/dist/transaction/resources/httpResources.d.ts +57 -2
  100. package/dist/transaction/resources/modelOperations.d.ts +148 -40
  101. package/dist/transaction/resources/where.d.ts +16 -0
  102. package/dist/transaction/resources/where.js +45 -0
  103. package/dist/transaction/schema/field.d.ts +12 -18
  104. package/dist/transaction/schema/fieldRef.d.ts +38 -0
  105. package/dist/transaction/schema/fieldRef.js +11 -0
  106. package/dist/transaction/schema/openapi.d.ts +16 -15
  107. package/dist/transaction/schema/openapi.js +186 -25
  108. package/dist/transaction/schema/relation.d.ts +7 -2
  109. package/dist/transaction/schema/schema.d.ts +27 -0
  110. package/dist/transaction/schema/schema.js +20 -0
  111. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +1 -1
  112. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +1 -1
  113. package/dist/transaction/transport/httpClient.d.ts +9 -1
  114. package/dist/transaction/transport/httpClient.js +1 -0
  115. package/dist/transaction/transport/httpTransport.js +156 -44
  116. package/dist/transaction/transport/wsTransport.d.ts +2 -4
  117. package/dist/transaction/transport/wsTransport.js +16 -10
  118. package/dist/transaction/types/streams.d.ts +10 -0
  119. package/dist/transaction/utils/duration.d.ts +25 -0
  120. package/dist/transaction/utils/duration.js +32 -0
  121. package/dist/transaction/wire/accountResponses.d.ts +69 -0
  122. package/dist/transaction/wire/accountResponses.js +36 -1
  123. package/dist/transaction/wire/auth.d.ts +9 -2
  124. package/dist/transaction/wire/auth.js +7 -1
  125. package/dist/transaction/wire/claims.d.ts +164 -97
  126. package/dist/transaction/wire/claims.js +126 -28
  127. package/dist/transaction/wire/commit.d.ts +1 -1
  128. package/dist/transaction/wire/feedEvent.d.ts +27 -0
  129. package/dist/transaction/wire/feedEvent.js +27 -1
  130. package/dist/transaction/wire/frames.d.ts +2 -2
  131. package/dist/transaction/wire/inboundFrames.d.ts +12 -2
  132. package/dist/transaction/wire/index.d.ts +10 -6
  133. package/dist/transaction/wire/index.js +12 -3
  134. package/dist/transaction/wire/modelMutations.d.ts +31 -0
  135. package/dist/transaction/wire/modelMutations.js +52 -0
  136. package/dist/transaction/wire/modelShape.d.ts +78 -0
  137. package/dist/transaction/wire/modelShape.js +74 -0
  138. package/dist/transactions/mutations/MutationQueue.d.ts +6 -0
  139. package/dist/transactions/mutations/MutationQueue.js +55 -45
  140. package/dist/transactions/mutations/commitPayload.d.ts +3 -2
  141. package/dist/transactions/mutations/commitPayload.js +5 -5
  142. package/dist/transactions/mutations/deltaConfirmation.d.ts +4 -0
  143. package/dist/transactions/mutations/deltaConfirmation.js +10 -8
  144. package/dist/transactions/mutations/replayValidation.d.ts +2 -1
  145. package/dist/transactions/mutations/replayValidation.js +3 -2
  146. package/dist/{core → views}/QueryView.d.ts +1 -1
  147. package/dist/{core → views}/QueryView.js +1 -1
  148. package/dist/{core → views}/ViewRegistry.d.ts +1 -1
  149. package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
  150. package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
  151. package/docs/agents.md +1 -1
  152. package/docs/api-keys.md +6 -6
  153. package/docs/api.md +5 -43
  154. package/docs/audit.md +4 -3
  155. package/docs/cli.md +11 -11
  156. package/docs/client-behavior.md +4 -4
  157. package/docs/concurrency-convention.md +28 -42
  158. package/docs/coordination.md +235 -83
  159. package/docs/data-sources.md +4 -4
  160. package/docs/debugging.md +34 -12
  161. package/docs/deployment.md +8 -8
  162. package/docs/examples/scoped-agent.md +3 -3
  163. package/docs/groups.md +57 -3
  164. package/docs/guarantees.md +37 -10
  165. package/docs/how-it-works.md +29 -5
  166. package/docs/idempotency.md +6 -6
  167. package/docs/identity.md +22 -23
  168. package/docs/index.md +8 -8
  169. package/docs/integration-guide.md +14 -3
  170. package/docs/mcp.md +7 -7
  171. package/docs/migration.md +34 -15
  172. package/docs/projects.md +1 -1
  173. package/docs/react.md +19 -8
  174. package/docs/sessions.md +1 -1
  175. package/docs/webhooks.md +9 -9
  176. package/llms.txt +4 -4
  177. package/package.json +13 -20
  178. package/dist/cli.cjs +0 -288600
  179. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  180. package/dist/testing/fixtures/bootstrap.js +0 -59
  181. package/dist/testing/fixtures/deltas.d.ts +0 -83
  182. package/dist/testing/fixtures/deltas.js +0 -136
  183. package/dist/testing/fixtures/httpResponses.d.ts +0 -70
  184. package/dist/testing/fixtures/httpResponses.js +0 -90
  185. package/dist/testing/fixtures/models.d.ts +0 -83
  186. package/dist/testing/fixtures/models.js +0 -272
  187. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  188. package/dist/testing/helpers/reactWrapper.js +0 -67
  189. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  190. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  191. package/dist/testing/helpers/wait.d.ts +0 -30
  192. package/dist/testing/helpers/wait.js +0 -49
  193. package/dist/testing/index.d.ts +0 -23
  194. package/dist/testing/index.js +0 -33
  195. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  196. package/dist/testing/mocks/FakeDatabase.js +0 -10
  197. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  198. package/dist/testing/mocks/MockMutationExecutor.js +0 -186
  199. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  200. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  201. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  202. package/dist/testing/mocks/MockSyncContext.js +0 -72
  203. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  204. package/dist/testing/mocks/MockSyncStore.js +0 -171
  205. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  206. package/dist/testing/mocks/MockWebSocket.js +0 -118
  207. package/docs/interaction-model.md +0 -99
  208. /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
  209. /package/dist/{core → query}/QueryProcessor.js +0 -0
  210. /package/dist/{core/storeContract.js → storeContract.js} +0 -0
  211. /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
  212. /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
  213. /package/dist/{source → transaction}/footprint.d.ts +0 -0
  214. /package/dist/{source → transaction}/footprint.js +0 -0
  215. /package/dist/{core → views}/ViewRegistry.js +0 -0
package/docs/migration.md CHANGED
@@ -13,6 +13,7 @@ change when you upgrade.
13
13
 
14
14
  | Version | What changed | What to do |
15
15
  |---|---|---|
16
+ | **0.36.0** | `ttlSeconds` deprecated on the join surfaces in favour of `ttl` | `useJoin({ scope, ttlSeconds: '5m' })` → `useJoin({ scope, ttl: '5m' })`; same for `ParticipantJoinOptions`. Both spellings work until 0.37.0 |
16
17
  | **0.35.0** | Synchronous reads moved under `local`, mirroring the async verbs | `get(id)` → `local.retrieve(id)`; `getAll(options)` → `local.list(options)`; `getCount(options)` → `local.count(options)` |
17
18
  | **0.35.0** | `causedByTaskId` write option + seven `turn_*` error codes removed | Delete the `causedByTaskId` argument from writes; a branch on `turn_validation_failed` was unreachable and can go with it |
18
19
  | **0.34.0** | Presence verb renamed `watch` → `join` | `ablo.<model>.watch(ids)` → `ablo.<model>.join(ids)`; `useWatch` → `useJoin`; the `WatchOptions` / `UseWatchOptions` / `UseWatchReturn` types → `JoinOptions` / `UseJoinOptions` / `UseJoinReturn`; error code `model_watch_not_configured` → `model_join_not_configured` |
@@ -31,7 +32,25 @@ change when you upgrade.
31
32
 
32
33
  ---
33
34
 
34
- ## 0.35.0 the synchronous reads move under `local`
35
+ ## 0.36.0: one lease is spelled `ttl`
36
+
37
+ ```diff
38
+ - useJoin({ scope: { documents: [id] }, ttlSeconds: '5m' })
39
+ + useJoin({ scope: { documents: [id] }, ttl: '5m' })
40
+ ```
41
+
42
+ `ablo.<model>.join(ids, { ttl })` has always said `ttl`, and so does every other
43
+ lease in the SDK: `claim`'s `ttl`, `ClaimLeaseOptions.ttl`. The lower-level join
44
+ surfaces said `ttlSeconds` while accepting exactly the same values, including
45
+ duration strings, so a `ttl: '5m'` handed down from the model verb arrived as
46
+ `ttlSeconds: '5m'`, a field asserting a unit its value did not carry.
47
+
48
+ Both spellings work until 0.37.0, and `ttl` wins if you pass both. The wire is
49
+ unchanged: it has always carried seconds and still does.
50
+
51
+ ---
52
+
53
+ ## 0.35.0: the synchronous reads move under `local`
35
54
 
36
55
  ```diff
37
56
  - const task = ablo.tasks.get(id);
@@ -53,7 +72,7 @@ in most codebases it is outnumbered many times over by `Map.get` and
53
72
  the compiler name the sites — each one is a type error at exactly the call that
54
73
  has to move.
55
74
 
56
- ## 0.35.0 `causedByTaskId` and the `turn_*` error codes removed
75
+ ## 0.35.0: `causedByTaskId` and the `turn_*` error codes removed
57
76
 
58
77
  0.9.2 retired the `turn` primitive but left one field standing: `causedByTaskId`
59
78
  on the write options bag. It was never usable. The server validated it against a
@@ -85,7 +104,7 @@ migration of its own.
85
104
 
86
105
  ---
87
106
 
88
- ## 0.34.0 presence verb renamed `watch` → `join`
107
+ ## 0.34.0: presence verb renamed `watch` → `join`
89
108
 
90
109
  The model-level presence verb read like a data subscription but delivered
91
110
  presence — who else is on a row and what they hold — so it now says what it
@@ -108,7 +127,7 @@ no compatibility alias — rename the call sites and the `WatchOptions` /
108
127
 
109
128
  ---
110
129
 
111
- ## 0.28.0 dead React multiplayer placeholders removed
130
+ ## 0.28.0: dead React multiplayer placeholders removed
112
131
 
113
132
  Four React exports looked usable but had no live implementation:
114
133
 
@@ -123,7 +142,7 @@ Four React exports looked usable but had no live implementation:
123
142
  There is no compatibility alias: the replacement APIs were already the only
124
143
  working paths.
125
144
 
126
- ## 0.11.0 `intent` → `claim` rename completed
145
+ ## 0.11.0: `intent` → `claim` rename completed
127
146
 
128
147
  > **Historical note:** this section documents the 0.11.0 transition.
129
148
  > `useClaim` was subsequently removed in 0.28.0 because its provider callback
@@ -166,7 +185,7 @@ contending holders (`AbloClaimedError.claims` and a policy reason folded into th
166
185
  message), and `participantKind` is the canonical `'user' | 'agent' | 'system'`
167
186
  on presence and claim state.
168
187
 
169
- ## 0.10.0 environment enum `sandbox` / `production`; stateless HTTP transport
188
+ ## 0.10.0: environment enum `sandbox` / `production`; stateless HTTP transport
170
189
 
171
190
  ### Environment enum rename (the only breaking change)
172
191
 
@@ -222,7 +241,7 @@ await ablo.tasks.update({ id, data: { status: 'done' } });
222
241
 
223
242
  ---
224
243
 
225
- ## 0.9.2 `turn` / agent-`tasks` removed; `intents` deprecated
244
+ ## 0.9.2: `turn` / agent-`tasks` removed; `intents` deprecated
226
245
 
227
246
  The SDK's coordination surface is now exactly two things: `ablo.<model>` writes
228
247
  and `claim`. The parallel `turn` / agent-`tasks` mechanism was redundant —
@@ -271,7 +290,7 @@ everywhere you coordinate concurrent work.
271
290
 
272
291
  ---
273
292
 
274
- ## 0.9.0 one options object per verb; disposable `claim`
293
+ ## 0.9.0: one options object per verb; disposable `claim`
275
294
 
276
295
  Every model verb takes a single options object, so the id, the data, and every
277
296
  modifier are named siblings. Reactive local reads stay on the synchronous
@@ -305,7 +324,7 @@ options object.
305
324
 
306
325
  ---
307
326
 
308
- ## 0.8.0 callable `claim` namespace
327
+ ## 0.8.0: callable `claim` namespace
309
328
 
310
329
  The flat coordination methods are gone; everything lives under `claim`.
311
330
 
@@ -318,7 +337,7 @@ The flat coordination methods are gone; everything lives under `claim`.
318
337
 
319
338
  ---
320
339
 
321
- ## 0.7.0 legacy React hooks removed
340
+ ## 0.7.0: legacy React hooks removed
322
341
 
323
342
  The query/mutation hooks were replaced by the single `useAblo()` accessor over
324
343
  typed model methods.
@@ -340,7 +359,7 @@ shape with the canonical `{ type, code, message, doc_url, request_id }` envelope
340
359
 
341
360
  ---
342
361
 
343
- ## 0.6.0 `onChange` and the Resource → Model rename
362
+ ## 0.6.0: `onChange` and the Resource → Model rename
344
363
 
345
364
  ```diff
346
365
  - ablo.tasks.subscribe(cb)
@@ -356,7 +375,7 @@ Also renamed: `Ablo.Resource.*` → `Ablo.Model.*`, `ModelTarget.resource` →
356
375
 
357
376
  ---
358
377
 
359
- ## 0.5.0 intent-handle method renames
378
+ ## 0.5.0: intent-handle method renames
360
379
 
361
380
  On the model intent handle (`ablo.<model>.intent(id)`):
362
381
 
@@ -373,7 +392,7 @@ unchanged at this release. (They were later folded under `claim` in 0.9.2.)
373
392
 
374
393
  ---
375
394
 
376
- ## 0.3.0 umbrella `<AbloProvider>`
395
+ ## 0.3.0: umbrella `<AbloProvider>`
377
396
 
378
397
  One provider component now owns the full React lifecycle. `<SyncProvider>`,
379
398
  `createAbloContext()`, and `withSync` were removed.
@@ -407,10 +426,10 @@ old code or old docs, this is the through-line:
407
426
 
408
427
  | Release | State of coordination |
409
428
  |---|---|
410
- | 0.4.0 | `ablo.<model>.intent(id)` introduced per-entity intent handle |
429
+ | 0.4.0 | `ablo.<model>.intent(id)` introduced: per-entity intent handle |
411
430
  | 0.5.0 | Intent-handle methods renamed to claim vocabulary (`acquire`→`claim`, …) |
412
431
  | 0.8.0 | Callable `claim` namespace (`claim(id)`, `claim.state`, `claim.queue`, …) |
413
432
  | 0.9.0 | `claim` returns an `await using` disposable handle |
414
- | 0.9.2 | `intents` deprecated and made `@internal` **`claim` is the one coordination API** |
433
+ | 0.9.2 | `intents` deprecated and made `@internal`: **`claim` is the one coordination API** |
415
434
 
416
435
  For the full chronological history, see the [Changelog](../CHANGELOG.md).
package/docs/projects.md CHANGED
@@ -95,5 +95,5 @@ another org's project ids 404 — never confirm existence across orgs.
95
95
 
96
96
  | Code | Status | Meaning |
97
97
  |------|--------|---------|
98
- | `project_scope_denied` | 403 | The model/resource belongs to another project in your org use a key minted for that project. |
98
+ | `project_scope_denied` | 403 | The model/resource belongs to another project in your org: use a key minted for that project. |
99
99
  | `project_slug_taken` | 409 | A project with this slug already exists in the organization. |
package/docs/react.md CHANGED
@@ -27,6 +27,7 @@ the thing, then pass it.
27
27
  ```ts
28
28
  // lib/ablo.ts
29
29
  import Ablo from '@abloatai/ablo';
30
+ import { createAbloReact } from '@abloatai/ablo/react';
30
31
  import { schema } from '@/ablo/schema';
31
32
 
32
33
  // The browser never holds your API key. It mints a short-lived session token
@@ -35,8 +36,18 @@ export const ablo = Ablo({
35
36
  schema,
36
37
  authEndpoint: '/api/ablo-session',
37
38
  });
39
+
40
+ // The typed binding: capture the schema once, and every component imports
41
+ // born-typed hooks from this file — `useAblo()` takes no type arguments,
42
+ // and a selector's `ablo` parameter knows your models.
43
+ export const { AbloProvider, useAblo } = createAbloReact(schema);
38
44
  ```
39
45
 
46
+ Import `AbloProvider` and `useAblo` from `lib/ablo` rather than from the
47
+ package, and the schema generic never appears at a call site again — the
48
+ same one-binding-file convention as tRPC's `createTRPCReact` or
49
+ react-redux's typed hooks.
50
+
40
51
  ## AbloProvider
41
52
 
42
53
  Mount it once near the root of your tree. It owns the connection, the local
@@ -67,10 +78,10 @@ export function Providers({
67
78
 
68
79
  | Prop | Default | Purpose |
69
80
  | ----------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
70
- | `client` | | **Required.** The `Ablo({ schema, apiKey })` instance. It carries the schema and connection config. |
81
+ | `client` |: | **Required.** The `Ablo({ schema, apiKey })` instance. It carries the schema and connection config. |
71
82
  | `userId` | resolved from auth | App participant id for app-owned fields and your `identityRoles`. Not the security boundary. |
72
83
  | `fallback` | neutral spinner | Rendered during the *first* bootstrap only. Pass a branded skeleton, `null`, or `'passthrough'`. |
73
- | `onError` | | Engine / WebSocket / bootstrap errors. Wire to Sentry / Datadog. |
84
+ | `onError` |: | Engine / WebSocket / bootstrap errors. Wire to Sentry / Datadog. |
74
85
 
75
86
  Everything that used to be a provider prop — `schema`, `url`, `apiKey`,
76
87
  `teamIds`, `syncGroups`, `persistence`, `bootstrapMode` — now lives on
@@ -79,7 +90,7 @@ identity comes from, and why the API key never reaches the browser, is the whole
79
90
  of [Identity & Sync Groups](./identity.md) — read that if it isn't obvious how
80
91
  org / team / user map to what a participant can see.
81
92
 
82
- ## useAblo model client
93
+ ## useAblo: model client
83
94
 
84
95
  ```tsx
85
96
  'use client';
@@ -180,7 +191,7 @@ imperative work after an event or effect.
180
191
 
181
192
  See [API reference](/docs/api) for the full options surface.
182
193
 
183
- ## useJoin scoped presence + read interest
194
+ ## useJoin: scoped presence + read interest
184
195
 
185
196
  `useJoin` is the React form of `ablo.<model>.join`. It joins multiplayer for a
186
197
  scope on the engine's existing socket (one TCP connection, N logical
@@ -209,10 +220,10 @@ Options (`UseJoinOptions`):
209
220
 
210
221
  | Option | Default | Effect |
211
222
  | --- | --- | --- |
212
- | `scope` | | Model-form scope (`{ slideDecks: id }`), resolved through the schema. Omit for engine-wide. |
213
- | `claim` | `false` | Acquire a write-claim on the scope (sent so peers observe it; pins the scope so it never warm-drops while held). A viewer is not a claimant leave `false` for read-only. |
223
+ | `scope` |: | Model-form scope (`{ slideDecks: id }`), resolved through the schema. Omit for engine-wide. |
224
+ | `claim` | `false` | Acquire a write-claim on the scope (sent so peers observe it; pins the scope so it never warm-drops while held). A viewer is not a claimant: leave `false` for read-only. |
214
225
  | `hydrate` | `false` | Backfill the scope's current rows into the pool once on enter, then keep them fresh via the live tail. Set `true` for deep-linked / never-opened entities. Single-flight; soft-fails. |
215
- | `ttlSeconds` | | Lease TTL for the scope claim. |
226
+ | `ttlSeconds` |: | Lease TTL for the scope claim. |
216
227
  | `paused` | `false` | Tear down and don't re-join while true. |
217
228
 
218
229
  Returns (`UseJoinReturn`): `{ participant, peers, claims, status, error }`.
@@ -220,7 +231,7 @@ Returns (`UseJoinReturn`): `{ participant, peers, claims, status, error }`.
220
231
  write-claims; `status` is the join lifecycle. Auto-cleans up on unmount or when
221
232
  `paused` flips true.
222
233
 
223
- ## usePeers read-only presence
234
+ ## usePeers: read-only presence
224
235
 
225
236
  `usePeers` is a *pure reader* of the presence stream already flowing on the
226
237
  connection. Unlike `useJoin`, it does **not** enter/leave a scope (no
package/docs/sessions.md CHANGED
@@ -175,7 +175,7 @@ Your schema lives in a **project** — you push it once (`npx ablo push`) and ev
175
175
  session you mint resolves against it. The flow for serving end-users:
176
176
 
177
177
  1. **Push your schema** to your project.
178
- 2. **Mint an `ek_` per user** `sessions.create({ user: { id } })`. Your users
178
+ 2. **Mint an `ek_` per user:** `sessions.create({ user: { id } })`. Your users
179
179
  commit to that one schema.
180
180
 
181
181
  **Your users do not have Ablo accounts.** You authenticate them however you
package/docs/webhooks.md CHANGED
@@ -25,7 +25,7 @@ There are two ways data flows out of Ablo, and they're for different jobs:
25
25
  | | reaches | use it for |
26
26
  |---|---|---|
27
27
  | **Realtime** (`useAblo`, WSS) | your live UI | instant, optimistic rendering |
28
- | **Webhooks** (this page) | your database | a durable copy you own analytics, backups, server logic |
28
+ | **Webhooks** (this page) | your database | a durable copy you own: analytics, backups, server logic |
29
29
 
30
30
  Most apps use both: the realtime stream for the UI, the webhook stream to keep
31
31
  their database in sync. This page is the webhook stream.
@@ -34,8 +34,8 @@ If you know Stripe, you already know the shape:
34
34
 
35
35
  | Stripe | Ablo |
36
36
  |---|---|
37
- | `stripe.x.create(...)` make the change | the Ablo client make the change (+ live sync) |
38
- | `/stripe-webhook` confirm and persist | `/api/ablo/[...all]` persist into your database |
37
+ | `stripe.x.create(...)`: make the change | the Ablo client: make the change (+ live sync) |
38
+ | `/stripe-webhook`: confirm and persist | `/api/ablo/[...all]`: persist into your database |
39
39
  | Stripe owns the charges | Ablo owns the transaction log |
40
40
  | you mirror charges into your database | you mirror the log into your database |
41
41
 
@@ -50,11 +50,11 @@ Every delivery is a batch of events. Each event:
50
50
  | field | meaning |
51
51
  |---|---|
52
52
  | `type` | `"<model>.<verb>"` with the model name lowercased, e.g. `task.updated` |
53
- | `model` | the model name exactly as declared in your schema the table to write |
53
+ | `model` | the model name exactly as declared in your schema: the table to write |
54
54
  | `objectId` | the changed row's id |
55
55
  | `data` | the post-change row, or `null` on delete (like Stripe's `event.data.object`) |
56
- | `syncId` | monotonic log position **dedupe and order by this** |
57
- | `id` | `String(syncId)` the event id |
56
+ | `syncId` | monotonic log position: **dedupe and order by this** |
57
+ | `id` | `String(syncId)`: the event id |
58
58
  | `createdAt` | ISO commit timestamp |
59
59
 
60
60
  ```ts
@@ -200,8 +200,8 @@ sequenceDiagram
200
200
 
201
201
  | behavior | how it works |
202
202
  |---|---|
203
- | **Ordering** | Every event carries `syncId`, a monotonic log position. Apply in `syncId` order Ablo guarantees the order because it owns the log. |
204
- | **Retries** | A non-`2xx` (or no response within the timeout) is retried with backoff: immediate, 5s, 5m, 30m, 2h, 5h, 10h, 10h 8 attempts over ~32h. |
203
+ | **Ordering** | Every event carries `syncId`, a monotonic log position. Apply in `syncId` order: Ablo guarantees the order because it owns the log. |
204
+ | **Retries** | A non-`2xx` (or no response within the timeout) is retried with backoff: immediate, 5s, 5m, 30m, 2h, 5h, 10h, 10h: 8 attempts over ~32h. |
205
205
  | **Auto-disable** | After the retries exhaust, the endpoint is marked `disabled` and delivery stops until you `ablo webhooks enable <id>`. |
206
206
  | **Replay** | Nothing is lost on failure: the log *is* the durable buffer, and delivery resumes from the endpoint's cursor once it's healthy. |
207
207
 
@@ -213,7 +213,7 @@ sequenceDiagram
213
213
  - **Return `2xx` fast.** Acknowledge first, then do slow work asynchronously.
214
214
  - **Subscribe to only what you need.** Set `enabledEvents` to the models you
215
215
  mirror (`['*']` is the default = all).
216
- - **Roll secrets periodically.** `ablo webhooks roll <id>` mints a new secret;
216
+ - **Roll secrets periodically:** `ablo webhooks roll <id>` mints a new secret;
217
217
  Standard Webhooks supports a rotation window so in-flight events still verify.
218
218
  - **Verify the raw body.** Frameworks that re-serialize JSON will break the
219
219
  signature — verify the bytes you received.
package/llms.txt CHANGED
@@ -1,12 +1,12 @@
1
1
  # Ablo
2
2
 
3
- Ablo is the agentic coordination layer: one API for AI agents, apps, and services to claim, change, and confirm the same rows.
3
+ Ablo is collaboration infrastructure for AI agents: one API for agents, apps, and services to claim, change, and confirm the same rows.
4
4
 
5
- Here is the problem it solves. Two agents reach for `report_stockholm` at once. One claims the row, does slow work (an LLM call, a fetch, a chain of tools), and commits. The second is neither rejected nor allowed to clobber: it waits in line, is handed the row as it now stands, and proceeds. Claims don't lock. If another writer holds the row, `claim` waits for them, re-reads the fresh row, then hands it to you — so writers serialize instead of colliding. A person editing that row is simply another holder; the agent waits behind them the same way.
5
+ Here is the problem it solves. Two agents reach for `report_stockholm` at once. One claims the row, does slow work (an LLM call, a fetch, a chain of tools), and commits. The second is neither rejected nor allowed to clobber: it waits in line, is handed the row as it now stands, and proceeds. Claims don't lock. If another writer holds the row, `claim` waits for them, re-reads the fresh row, then hands it to you — so writers serialize instead of colliding. A person editing that row is simply another holder; the agent waits behind them the same way. And a claim is as narrow as its target: name a `path`, a `range`, or a `field` and two claims on non-overlapping parts of the same row are both granted — region locking within one row, with no queueing between regions.
6
6
 
7
7
  Use AI SDK for the agent loop. Use Ablo when agent reads and writes must persist, coordinate with concurrent work, and leave an audit trail.
8
8
 
9
- ## Surfaces pick by who is calling
9
+ ## Surfaces: pick by who is calling
10
10
 
11
11
  Every surface reaches the same coordinated state. They are not interchangeable.
12
12
 
@@ -217,7 +217,7 @@ Import from these public paths only:
217
217
 
218
218
  Do not teach `/api`, `/agent`, `/ai-sdk`, `/core`, `/realtime`, or internal subpaths. (`/source` IS public — it's the Data Source endpoint surface above.)
219
219
 
220
- ## CLI agents run it NON-INTERACTIVELY
220
+ ## CLI: agents run it NON-INTERACTIVELY
221
221
 
222
222
  `ablo init` and other prompts need a TTY; an agent/CI run has none and will HANG. Always:
223
223
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "The Collaboration Layer For AI Agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -10,7 +10,7 @@
10
10
  "main": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts",
12
12
  "bin": {
13
- "ablo": "./dist/cli.cjs"
13
+ "ablo": "./bin/ablo.cjs"
14
14
  },
15
15
  "exports": {
16
16
  ".": {
@@ -33,11 +33,6 @@
33
33
  "import": "./dist/react/index.js",
34
34
  "default": "./dist/react/index.js"
35
35
  },
36
- "./testing": {
37
- "types": "./dist/testing/index.d.ts",
38
- "import": "./dist/testing/index.js",
39
- "default": "./dist/testing/index.js"
40
- },
41
36
  "./core": {
42
37
  "types": "./dist/core/index.d.ts",
43
38
  "import": "./dist/core/index.js",
@@ -98,6 +93,11 @@
98
93
  "import": "./dist/wire/index.js",
99
94
  "default": "./dist/wire/index.js"
100
95
  },
96
+ "./syncLog": {
97
+ "types": "./dist/syncLog/index.d.ts",
98
+ "import": "./dist/syncLog/index.js",
99
+ "default": "./dist/syncLog/index.js"
100
+ },
101
101
  "./server": {
102
102
  "types": "./dist/server/index.d.ts",
103
103
  "import": "./dist/server/index.js",
@@ -115,6 +115,7 @@
115
115
  }
116
116
  },
117
117
  "files": [
118
+ "bin",
118
119
  "dist",
119
120
  "!dist/__type_probe.*",
120
121
  "docs/*.md",
@@ -129,21 +130,21 @@
129
130
  ],
130
131
  "scripts": {
131
132
  "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
132
- "build": "npm run clean && tsc -p tsconfig.build.json && npm run build:cli",
133
- "build:cli": "tsup --config tsup.cli.config.ts",
134
- "typecheck": "npm run typecheck:src && npm run typecheck:cli && npm run typecheck:scripts",
133
+ "build": "npm run clean && tsc -p tsconfig.build.json",
134
+ "typecheck": "npm run typecheck:src && npm run typecheck:scripts",
135
135
  "typecheck:src": "tsc -p tsconfig.json",
136
- "typecheck:cli": "tsc -p tsconfig.cli.json",
137
136
  "typecheck:scripts": "tsc -p tsconfig.scripts.json",
138
137
  "prepack": "node scripts/strip-source-condition.mjs",
139
138
  "postpack": "node scripts/restore-source-condition.mjs",
140
139
  "pack:check": "node scripts/pack-check.mjs",
141
- "lint": "npm run lint:imports && npm run lint:errors && npm run lint:docs && npm run lint:docs-site",
140
+ "lint": "npm run lint:imports && npm run lint:errors && npm run lint:openapi && npm run lint:docs && npm run lint:docs-site",
142
141
  "build:docs": "node scripts/build-blume-docs.mjs",
143
142
  "lint:docs-site": "node scripts/build-blume-docs.mjs --check",
144
143
  "lint:imports": "node scripts/check-js-extensions.mjs",
145
144
  "generate:errors": "tsx scripts/generate-error-docs.mts",
145
+ "generate:openapi": "tsx --conditions=@ablo/source scripts/generate-openapi.mts",
146
146
  "lint:errors": "tsx scripts/check-error-docs.mts",
147
+ "lint:openapi": "tsx --conditions=@ablo/source scripts/generate-openapi.mts --check",
147
148
  "lint:docs": "node scripts/check-doc-drift.mjs",
148
149
  "lint:eslint": "eslint . --cache",
149
150
  "lint:pkg": "publint",
@@ -151,7 +152,6 @@
151
152
  "check:dist": "node scripts/check-dist-fresh.mjs",
152
153
  "pretest": "node scripts/check-dist-fresh.mjs",
153
154
  "test": "jest",
154
- "test:quickstart": "node scripts/test-quickstart.mjs",
155
155
  "test:unit": "jest --testPathPatterns __tests__/unit",
156
156
  "test:integration": "jest --testPathPatterns __tests__/integration",
157
157
  "test:contract": "jest --testPathPatterns __tests__/contract",
@@ -205,7 +205,6 @@
205
205
  }
206
206
  },
207
207
  "dependencies": {
208
- "jiti": "^2.7.0",
209
208
  "mobx": "^6.13.7",
210
209
  "mobx-react-lite": "^4.0.0",
211
210
  "uuid": "^11.1.0",
@@ -213,9 +212,7 @@
213
212
  },
214
213
  "devDependencies": {
215
214
  "@ai-sdk/provider": "^3.0.0",
216
- "@clack/prompts": "^0.11.0",
217
215
  "@jest/globals": "^30.2.0",
218
- "@prisma/client": "^7.3.0",
219
216
  "@types/jest": "^30.0.0",
220
217
  "@types/node": "^22.0.0",
221
218
  "@types/react": "^19.0.0",
@@ -230,13 +227,9 @@
230
227
  "jest": "^30.2.0",
231
228
  "jest-environment-jsdom": "^30.2.0",
232
229
  "jest-environment-node": "^30.2.0",
233
- "picocolors": "^1.1.0",
234
- "postgres": "^3.4.0",
235
230
  "react": "^19.0.0",
236
231
  "react-dom": "^19.0.0",
237
232
  "ts-jest": "^29.4.5",
238
- "ts-morph": "^26.0.0",
239
- "tsup": "^8.0.0",
240
233
  "tsx": "^4.19.0",
241
234
  "typescript": "^5.8.3",
242
235
  "publint": "^0.3.21",