@abloatai/ablo 0.35.0 → 0.37.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 (622) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +71 -1929
  3. package/NOTICE +2 -2
  4. package/README.md +23 -532
  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 -112
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -161
  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 +2 -2
  59. package/docs/api-keys.md +13 -12
  60. package/docs/api.md +15 -53
  61. package/docs/audit.md +4 -3
  62. package/docs/cli.md +11 -11
  63. package/docs/client-behavior.md +9 -9
  64. package/docs/concurrency-convention.md +28 -42
  65. package/docs/coordination.md +228 -86
  66. package/docs/data-sources.md +5 -5
  67. package/docs/debugging.md +34 -12
  68. package/docs/deployment.md +8 -8
  69. package/docs/examples/agent-human.md +4 -4
  70. package/docs/examples/ai-sdk-tool.md +1 -1
  71. package/docs/examples/existing-python-backend.md +15 -4
  72. package/docs/examples/nextjs.md +27 -6
  73. package/docs/examples/scoped-agent.md +3 -3
  74. package/docs/examples/server-agent.md +2 -2
  75. package/docs/groups.md +57 -3
  76. package/docs/guarantees.md +37 -10
  77. package/docs/how-it-works.md +32 -8
  78. package/docs/idempotency.md +6 -6
  79. package/docs/identity.md +24 -24
  80. package/docs/index.md +8 -8
  81. package/docs/integration-guide.md +38 -16
  82. package/docs/internal/README.md +18 -0
  83. package/docs/internal/agent-fleet-coordination-design.md +171 -0
  84. package/docs/internal/agent-orchestration.md +58 -0
  85. package/docs/internal/commit-identifiers.md +91 -0
  86. package/docs/internal/concurrency-open-decisions.md +37 -0
  87. package/docs/internal/data-source-reverse-channel.md +150 -0
  88. package/docs/internal/per-field-conflict-detection.md +165 -0
  89. package/docs/internal/postgres-replication.md +64 -0
  90. package/docs/internal/serializable-schema.md +119 -0
  91. package/docs/internal/structure.md +32 -0
  92. package/docs/mcp.md +9 -9
  93. package/docs/migration.md +37 -18
  94. package/docs/projects.md +1 -1
  95. package/docs/quickstart.md +2 -2
  96. package/docs/react.md +24 -13
  97. package/docs/schema-contract.md +3 -3
  98. package/docs/sessions.md +91 -37
  99. package/docs/webhooks.md +9 -9
  100. package/examples/README.md +2 -2
  101. package/examples/data-source/README.md +1 -1
  102. package/examples/data-source/ablo-driver.ts +1 -1
  103. package/examples/data-source/customer-server.ts +1 -1
  104. package/examples/data-source/run.ts +1 -1
  105. package/examples/data-source/schema.ts +1 -1
  106. package/examples/quickstart.ts +2 -2
  107. package/llms.txt +12 -12
  108. package/package.json +64 -174
  109. package/dist/BaseSyncedStore.d.ts +0 -823
  110. package/dist/BaseSyncedStore.js +0 -1955
  111. package/dist/Database.d.ts +0 -335
  112. package/dist/Database.js +0 -1500
  113. package/dist/InstanceCache.d.ts +0 -233
  114. package/dist/InstanceCache.js +0 -1164
  115. package/dist/LazyReferenceCollection.d.ts +0 -177
  116. package/dist/LazyReferenceCollection.js +0 -461
  117. package/dist/Model.d.ts +0 -444
  118. package/dist/Model.js +0 -909
  119. package/dist/ModelRegistry.d.ts +0 -221
  120. package/dist/ModelRegistry.js +0 -537
  121. package/dist/NetworkMonitor.d.ts +0 -26
  122. package/dist/NetworkMonitor.js +0 -77
  123. package/dist/RuntimeContext.d.ts +0 -52
  124. package/dist/RuntimeContext.js +0 -80
  125. package/dist/SyncClient.d.ts +0 -551
  126. package/dist/SyncClient.js +0 -2199
  127. package/dist/adapters/alwaysOnline.d.ts +0 -14
  128. package/dist/adapters/alwaysOnline.js +0 -17
  129. package/dist/adapters/inMemoryStorage.d.ts +0 -31
  130. package/dist/adapters/inMemoryStorage.js +0 -110
  131. package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
  132. package/dist/ai-sdk/coordinatedTool.js +0 -134
  133. package/dist/ai-sdk/coordinationContext.d.ts +0 -46
  134. package/dist/ai-sdk/coordinationContext.js +0 -106
  135. package/dist/ai-sdk/index.d.ts +0 -121
  136. package/dist/ai-sdk/index.js +0 -121
  137. package/dist/ai-sdk/wrap.d.ts +0 -65
  138. package/dist/ai-sdk/wrap.js +0 -39
  139. package/dist/auth/index.d.ts +0 -1
  140. package/dist/auth/index.js +0 -8
  141. package/dist/batching/index.d.ts +0 -55
  142. package/dist/batching/index.js +0 -147
  143. package/dist/cli.cjs +0 -288600
  144. package/dist/client/Ablo.d.ts +0 -231
  145. package/dist/client/Ablo.js +0 -149
  146. package/dist/client/abloClient.d.ts +0 -309
  147. package/dist/client/abloClient.js +0 -13
  148. package/dist/client/clientPrelude.d.ts +0 -52
  149. package/dist/client/clientPrelude.js +0 -60
  150. package/dist/client/consoleLogger.d.ts +0 -35
  151. package/dist/client/consoleLogger.js +0 -44
  152. package/dist/client/coreClient.d.ts +0 -60
  153. package/dist/client/coreClient.js +0 -118
  154. package/dist/client/createInternalComponents.d.ts +0 -46
  155. package/dist/client/createInternalComponents.js +0 -92
  156. package/dist/client/createModelProxy.d.ts +0 -228
  157. package/dist/client/createModelProxy.js +0 -818
  158. package/dist/client/humans.d.ts +0 -48
  159. package/dist/client/humans.js +0 -52
  160. package/dist/client/modelRegistration.d.ts +0 -10
  161. package/dist/client/modelRegistration.js +0 -312
  162. package/dist/client/options.d.ts +0 -461
  163. package/dist/client/options.js +0 -7
  164. package/dist/client/reactiveEngine.d.ts +0 -48
  165. package/dist/client/reactiveEngine.js +0 -910
  166. package/dist/client/resourceTypes.d.ts +0 -12
  167. package/dist/client/resourceTypes.js +0 -10
  168. package/dist/client/schemaConfig.d.ts +0 -44
  169. package/dist/client/schemaConfig.js +0 -185
  170. package/dist/client/validateAbloOptions.d.ts +0 -42
  171. package/dist/client/validateAbloOptions.js +0 -43
  172. package/dist/client/wsMutationExecutor.d.ts +0 -27
  173. package/dist/client/wsMutationExecutor.js +0 -72
  174. package/dist/context.d.ts +0 -29
  175. package/dist/context.js +0 -58
  176. package/dist/coordination/ClaimLog.d.ts +0 -26
  177. package/dist/coordination/ClaimLog.js +0 -32
  178. package/dist/coordination/index.d.ts +0 -1
  179. package/dist/coordination/index.js +0 -8
  180. package/dist/core/DatabaseManager.d.ts +0 -105
  181. package/dist/core/DatabaseManager.js +0 -387
  182. package/dist/core/QueryProcessor.d.ts +0 -75
  183. package/dist/core/QueryProcessor.js +0 -255
  184. package/dist/core/QueryView.d.ts +0 -79
  185. package/dist/core/QueryView.js +0 -218
  186. package/dist/core/StoreManager.d.ts +0 -112
  187. package/dist/core/StoreManager.js +0 -302
  188. package/dist/core/ViewRegistry.d.ts +0 -20
  189. package/dist/core/ViewRegistry.js +0 -55
  190. package/dist/core/index.d.ts +0 -33
  191. package/dist/core/index.js +0 -48
  192. package/dist/core/openIDBWithTimeout.d.ts +0 -65
  193. package/dist/core/openIDBWithTimeout.js +0 -153
  194. package/dist/core/queryUtils.d.ts +0 -45
  195. package/dist/core/queryUtils.js +0 -69
  196. package/dist/core/storeContract.d.ts +0 -145
  197. package/dist/core/storeContract.js +0 -12
  198. package/dist/docs/catalog.d.ts +0 -72
  199. package/dist/docs/catalog.js +0 -227
  200. package/dist/docs/index.d.ts +0 -10
  201. package/dist/docs/index.js +0 -10
  202. package/dist/environment.d.ts +0 -1
  203. package/dist/environment.js +0 -8
  204. package/dist/interfaces/index.d.ts +0 -311
  205. package/dist/interfaces/index.js +0 -9
  206. package/dist/keys/index.d.ts +0 -1
  207. package/dist/keys/index.js +0 -8
  208. package/dist/mutators/RecordingMutation.d.ts +0 -36
  209. package/dist/mutators/RecordingMutation.js +0 -182
  210. package/dist/mutators/Transaction.d.ts +0 -40
  211. package/dist/mutators/Transaction.js +0 -58
  212. package/dist/mutators/UndoManager.d.ts +0 -258
  213. package/dist/mutators/UndoManager.js +0 -658
  214. package/dist/mutators/defineMutators.d.ts +0 -60
  215. package/dist/mutators/defineMutators.js +0 -18
  216. package/dist/mutators/inverseOp.d.ts +0 -126
  217. package/dist/mutators/inverseOp.js +0 -71
  218. package/dist/mutators/mutateActions.d.ts +0 -45
  219. package/dist/mutators/mutateActions.js +0 -105
  220. package/dist/mutators/readerActions.d.ts +0 -33
  221. package/dist/mutators/readerActions.js +0 -57
  222. package/dist/mutators/undoApply.d.ts +0 -51
  223. package/dist/mutators/undoApply.js +0 -117
  224. package/dist/policy/index.d.ts +0 -21
  225. package/dist/policy/index.js +0 -20
  226. package/dist/query/client.d.ts +0 -61
  227. package/dist/query/client.js +0 -137
  228. package/dist/query/types.d.ts +0 -85
  229. package/dist/query/types.js +0 -16
  230. package/dist/react/AbloProvider.d.ts +0 -230
  231. package/dist/react/AbloProvider.js +0 -455
  232. package/dist/react/ClientSideSuspense.d.ts +0 -36
  233. package/dist/react/ClientSideSuspense.js +0 -17
  234. package/dist/react/DefaultFallback.d.ts +0 -24
  235. package/dist/react/DefaultFallback.js +0 -43
  236. package/dist/react/context.d.ts +0 -55
  237. package/dist/react/context.js +0 -29
  238. package/dist/react/index.d.ts +0 -61
  239. package/dist/react/index.js +0 -66
  240. package/dist/react/internalContext.d.ts +0 -33
  241. package/dist/react/internalContext.js +0 -3
  242. package/dist/react/useAblo.d.ts +0 -75
  243. package/dist/react/useAblo.js +0 -102
  244. package/dist/react/useCurrentUserId.d.ts +0 -22
  245. package/dist/react/useCurrentUserId.js +0 -34
  246. package/dist/react/useErrorListener.d.ts +0 -20
  247. package/dist/react/useErrorListener.js +0 -38
  248. package/dist/react/useMutationFailureListener.d.ts +0 -26
  249. package/dist/react/useMutationFailureListener.js +0 -38
  250. package/dist/react/useMutators.d.ts +0 -56
  251. package/dist/react/useMutators.js +0 -84
  252. package/dist/react/useReactive.d.ts +0 -35
  253. package/dist/react/useReactive.js +0 -123
  254. package/dist/react/useSyncStatus.d.ts +0 -59
  255. package/dist/react/useSyncStatus.js +0 -76
  256. package/dist/react/useUndoScope.d.ts +0 -34
  257. package/dist/react/useUndoScope.js +0 -81
  258. package/dist/schema/coordination.d.ts +0 -112
  259. package/dist/schema/coordination.js +0 -129
  260. package/dist/schema/ddl.d.ts +0 -97
  261. package/dist/schema/ddl.js +0 -491
  262. package/dist/schema/ddlLock.d.ts +0 -35
  263. package/dist/schema/ddlLock.js +0 -46
  264. package/dist/schema/diff.d.ts +0 -225
  265. package/dist/schema/diff.js +0 -289
  266. package/dist/schema/generate.d.ts +0 -19
  267. package/dist/schema/generate.js +0 -86
  268. package/dist/schema/index.d.ts +0 -41
  269. package/dist/schema/index.js +0 -76
  270. package/dist/schema/queries.d.ts +0 -201
  271. package/dist/schema/queries.js +0 -144
  272. package/dist/schema/select.d.ts +0 -40
  273. package/dist/schema/select.js +0 -87
  274. package/dist/schema/serialize.d.ts +0 -115
  275. package/dist/schema/serialize.js +0 -262
  276. package/dist/schema/sugar.d.ts +0 -109
  277. package/dist/schema/sugar.js +0 -83
  278. package/dist/schema/syncDeltaRow.d.ts +0 -6
  279. package/dist/schema/syncDeltaRow.js +0 -6
  280. package/dist/server/adapter.d.ts +0 -173
  281. package/dist/server/adapter.js +0 -18
  282. package/dist/server/commit.d.ts +0 -107
  283. package/dist/server/commit.js +0 -1
  284. package/dist/server/index.d.ts +0 -14
  285. package/dist/server/index.js +0 -2
  286. package/dist/server/readConfig.d.ts +0 -80
  287. package/dist/server/readConfig.js +0 -8
  288. package/dist/server/storageMode.d.ts +0 -23
  289. package/dist/server/storageMode.js +0 -17
  290. package/dist/source/adapter.d.ts +0 -81
  291. package/dist/source/adapter.js +0 -22
  292. package/dist/source/adapters/drizzle.d.ts +0 -48
  293. package/dist/source/adapters/drizzle.js +0 -219
  294. package/dist/source/adapters/kysely.d.ts +0 -42
  295. package/dist/source/adapters/kysely.js +0 -205
  296. package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
  297. package/dist/source/adapters/kyselyMutationCore.js +0 -125
  298. package/dist/source/adapters/memory.d.ts +0 -13
  299. package/dist/source/adapters/memory.js +0 -130
  300. package/dist/source/adapters/prisma.d.ts +0 -63
  301. package/dist/source/adapters/prisma.js +0 -202
  302. package/dist/source/conformance.d.ts +0 -37
  303. package/dist/source/conformance.js +0 -215
  304. package/dist/source/connector.d.ts +0 -95
  305. package/dist/source/connector.js +0 -266
  306. package/dist/source/connectorProtocol.d.ts +0 -154
  307. package/dist/source/connectorProtocol.js +0 -163
  308. package/dist/source/contract.d.ts +0 -195
  309. package/dist/source/contract.js +0 -164
  310. package/dist/source/factory.d.ts +0 -92
  311. package/dist/source/factory.js +0 -286
  312. package/dist/source/footprint.d.ts +0 -111
  313. package/dist/source/footprint.js +0 -0
  314. package/dist/source/idempotency.d.ts +0 -61
  315. package/dist/source/idempotency.js +0 -144
  316. package/dist/source/index.d.ts +0 -23
  317. package/dist/source/index.js +0 -30
  318. package/dist/source/migrations.d.ts +0 -21
  319. package/dist/source/migrations.js +0 -103
  320. package/dist/source/next.d.ts +0 -32
  321. package/dist/source/next.js +0 -25
  322. package/dist/source/pushQueue.d.ts +0 -134
  323. package/dist/source/pushQueue.js +0 -256
  324. package/dist/source/signing.d.ts +0 -92
  325. package/dist/source/signing.js +0 -162
  326. package/dist/source/types.d.ts +0 -401
  327. package/dist/source/types.js +0 -59
  328. package/dist/stores/ObjectStore.d.ts +0 -115
  329. package/dist/stores/ObjectStore.js +0 -393
  330. package/dist/stores/ObjectStoreContract.d.ts +0 -38
  331. package/dist/stores/ObjectStoreContract.js +0 -1
  332. package/dist/stores/SyncActionStore.d.ts +0 -97
  333. package/dist/stores/SyncActionStore.js +0 -504
  334. package/dist/stores/syncAction.d.ts +0 -26
  335. package/dist/stores/syncAction.js +0 -16
  336. package/dist/surface.d.ts +0 -36
  337. package/dist/surface.js +0 -75
  338. package/dist/sync/BootstrapFetcher.d.ts +0 -280
  339. package/dist/sync/BootstrapFetcher.js +0 -962
  340. package/dist/sync/ConnectionManager.d.ts +0 -8
  341. package/dist/sync/ConnectionManager.js +0 -8
  342. package/dist/sync/OnDemandLoader.d.ts +0 -228
  343. package/dist/sync/OnDemandLoader.js +0 -742
  344. package/dist/sync/SubscriptionManager.d.ts +0 -159
  345. package/dist/sync/SubscriptionManager.js +0 -243
  346. package/dist/sync/SyncWebSocket.d.ts +0 -173
  347. package/dist/sync/SyncWebSocket.js +0 -438
  348. package/dist/sync/awaitClaimGrant.d.ts +0 -6
  349. package/dist/sync/awaitClaimGrant.js +0 -6
  350. package/dist/sync/bootstrapApply.d.ts +0 -70
  351. package/dist/sync/bootstrapApply.js +0 -73
  352. package/dist/sync/commitFrames.d.ts +0 -8
  353. package/dist/sync/commitFrames.js +0 -8
  354. package/dist/sync/contextPorts.d.ts +0 -18
  355. package/dist/sync/contextPorts.js +0 -31
  356. package/dist/sync/createClaimStream.d.ts +0 -7
  357. package/dist/sync/createClaimStream.js +0 -7
  358. package/dist/sync/createPresenceStream.d.ts +0 -69
  359. package/dist/sync/createPresenceStream.js +0 -200
  360. package/dist/sync/createSnapshot.d.ts +0 -29
  361. package/dist/sync/createSnapshot.js +0 -118
  362. package/dist/sync/credentialLifecycle.d.ts +0 -7
  363. package/dist/sync/credentialLifecycle.js +0 -7
  364. package/dist/sync/deltaPipeline.d.ts +0 -113
  365. package/dist/sync/deltaPipeline.js +0 -261
  366. package/dist/sync/groupChange.d.ts +0 -113
  367. package/dist/sync/groupChange.js +0 -242
  368. package/dist/sync/participants.d.ts +0 -115
  369. package/dist/sync/participants.js +0 -344
  370. package/dist/sync/persistedPrefix.d.ts +0 -12
  371. package/dist/sync/persistedPrefix.js +0 -22
  372. package/dist/sync/schemaDrift.d.ts +0 -55
  373. package/dist/sync/schemaDrift.js +0 -53
  374. package/dist/sync/schemas.d.ts +0 -70
  375. package/dist/sync/schemas.js +0 -94
  376. package/dist/sync/syncCursor.d.ts +0 -40
  377. package/dist/sync/syncCursor.js +0 -55
  378. package/dist/sync/syncPlan.d.ts +0 -54
  379. package/dist/sync/syncPlan.js +0 -50
  380. package/dist/sync/wsFrameHandlers.d.ts +0 -8
  381. package/dist/sync/wsFrameHandlers.js +0 -8
  382. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  383. package/dist/testing/fixtures/bootstrap.js +0 -59
  384. package/dist/testing/fixtures/deltas.d.ts +0 -83
  385. package/dist/testing/fixtures/deltas.js +0 -136
  386. package/dist/testing/fixtures/httpResponses.d.ts +0 -70
  387. package/dist/testing/fixtures/httpResponses.js +0 -90
  388. package/dist/testing/fixtures/models.d.ts +0 -83
  389. package/dist/testing/fixtures/models.js +0 -272
  390. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  391. package/dist/testing/helpers/reactWrapper.js +0 -67
  392. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  393. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  394. package/dist/testing/helpers/wait.d.ts +0 -30
  395. package/dist/testing/helpers/wait.js +0 -49
  396. package/dist/testing/index.d.ts +0 -23
  397. package/dist/testing/index.js +0 -33
  398. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  399. package/dist/testing/mocks/FakeDatabase.js +0 -10
  400. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  401. package/dist/testing/mocks/MockMutationExecutor.js +0 -186
  402. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  403. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  404. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  405. package/dist/testing/mocks/MockSyncContext.js +0 -72
  406. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  407. package/dist/testing/mocks/MockSyncStore.js +0 -171
  408. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  409. package/dist/testing/mocks/MockWebSocket.js +0 -118
  410. package/dist/transaction/ablo.d.ts +0 -88
  411. package/dist/transaction/ablo.js +0 -33
  412. package/dist/transaction/auth/apiKey.d.ts +0 -152
  413. package/dist/transaction/auth/apiKey.js +0 -419
  414. package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
  415. package/dist/transaction/auth/bootstrapScope.js +0 -1
  416. package/dist/transaction/auth/capability.d.ts +0 -177
  417. package/dist/transaction/auth/capability.js +0 -199
  418. package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
  419. package/dist/transaction/auth/credentialEndpoint.js +0 -86
  420. package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
  421. package/dist/transaction/auth/credentialPolicy.js +0 -125
  422. package/dist/transaction/auth/credentialSource.d.ts +0 -30
  423. package/dist/transaction/auth/credentialSource.js +0 -55
  424. package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
  425. package/dist/transaction/auth/hostedEndpoints.js +0 -21
  426. package/dist/transaction/auth/identity.d.ts +0 -55
  427. package/dist/transaction/auth/identity.js +0 -210
  428. package/dist/transaction/auth/index.d.ts +0 -162
  429. package/dist/transaction/auth/index.js +0 -304
  430. package/dist/transaction/auth/schemas.d.ts +0 -59
  431. package/dist/transaction/auth/schemas.js +0 -85
  432. package/dist/transaction/auth/sessionMint.d.ts +0 -28
  433. package/dist/transaction/auth/sessionMint.js +0 -85
  434. package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -49
  435. package/dist/transaction/coordination/awaitClaimGrant.js +0 -112
  436. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -50
  437. package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -88
  438. package/dist/transaction/coordination/claimMeta.d.ts +0 -49
  439. package/dist/transaction/coordination/claimMeta.js +0 -52
  440. package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
  441. package/dist/transaction/coordination/createClaimStream.js +0 -475
  442. package/dist/transaction/coordination/events.d.ts +0 -74
  443. package/dist/transaction/coordination/events.js +0 -7
  444. package/dist/transaction/coordination/index.d.ts +0 -19
  445. package/dist/transaction/coordination/index.js +0 -44
  446. package/dist/transaction/coordination/locator.d.ts +0 -83
  447. package/dist/transaction/coordination/locator.js +0 -82
  448. package/dist/transaction/coordination/schema.d.ts +0 -1473
  449. package/dist/transaction/coordination/schema.js +0 -1013
  450. package/dist/transaction/coordination/targetConflict.d.ts +0 -2
  451. package/dist/transaction/coordination/targetConflict.js +0 -103
  452. package/dist/transaction/coordination/trace.d.ts +0 -78
  453. package/dist/transaction/coordination/trace.js +0 -138
  454. package/dist/transaction/durableWrites.d.ts +0 -62
  455. package/dist/transaction/durableWrites.js +0 -71
  456. package/dist/transaction/environment.d.ts +0 -105
  457. package/dist/transaction/environment.js +0 -108
  458. package/dist/transaction/errorCodes.d.ts +0 -403
  459. package/dist/transaction/errorCodes.js +0 -480
  460. package/dist/transaction/errors.d.ts +0 -428
  461. package/dist/transaction/errors.js +0 -686
  462. package/dist/transaction/index.d.ts +0 -20
  463. package/dist/transaction/index.js +0 -20
  464. package/dist/transaction/keys/index.d.ts +0 -87
  465. package/dist/transaction/keys/index.js +0 -207
  466. package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
  467. package/dist/transaction/log/syncDeltaRow.js +0 -95
  468. package/dist/transaction/logPosition.d.ts +0 -97
  469. package/dist/transaction/logPosition.js +0 -125
  470. package/dist/transaction/logger.d.ts +0 -16
  471. package/dist/transaction/logger.js +0 -7
  472. package/dist/transaction/observability.d.ts +0 -53
  473. package/dist/transaction/observability.js +0 -19
  474. package/dist/transaction/persistence.d.ts +0 -12
  475. package/dist/transaction/persistence.js +0 -11
  476. package/dist/transaction/plugin.d.ts +0 -192
  477. package/dist/transaction/plugin.js +0 -87
  478. package/dist/transaction/policy/types.d.ts +0 -217
  479. package/dist/transaction/policy/types.js +0 -126
  480. package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
  481. package/dist/transaction/resources/functionalUpdate.js +0 -87
  482. package/dist/transaction/resources/httpResources.d.ts +0 -266
  483. package/dist/transaction/resources/httpResources.js +0 -7
  484. package/dist/transaction/resources/modelOperations.d.ts +0 -319
  485. package/dist/transaction/resources/modelOperations.js +0 -12
  486. package/dist/transaction/resources/mutationOptions.d.ts +0 -66
  487. package/dist/transaction/resources/mutationOptions.js +0 -9
  488. package/dist/transaction/resources/where.d.ts +0 -85
  489. package/dist/transaction/resources/where.js +0 -70
  490. package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
  491. package/dist/transaction/resources/writeOptionsSchema.js +0 -73
  492. package/dist/transaction/schema/field.d.ts +0 -126
  493. package/dist/transaction/schema/field.js +0 -265
  494. package/dist/transaction/schema/loadStrategy.d.ts +0 -45
  495. package/dist/transaction/schema/loadStrategy.js +0 -46
  496. package/dist/transaction/schema/model.d.ts +0 -379
  497. package/dist/transaction/schema/model.js +0 -123
  498. package/dist/transaction/schema/openapi.d.ts +0 -57
  499. package/dist/transaction/schema/openapi.js +0 -340
  500. package/dist/transaction/schema/relation.d.ts +0 -199
  501. package/dist/transaction/schema/relation.js +0 -104
  502. package/dist/transaction/schema/residency.d.ts +0 -29
  503. package/dist/transaction/schema/residency.js +0 -25
  504. package/dist/transaction/schema/roles.d.ts +0 -249
  505. package/dist/transaction/schema/roles.js +0 -230
  506. package/dist/transaction/schema/schema.d.ts +0 -324
  507. package/dist/transaction/schema/schema.js +0 -305
  508. package/dist/transaction/schema/tenancy.d.ts +0 -139
  509. package/dist/transaction/schema/tenancy.js +0 -190
  510. package/dist/transaction/transactionLayer.d.ts +0 -82
  511. package/dist/transaction/transactionLayer.js +0 -24
  512. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
  513. package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
  514. package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
  515. package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
  516. package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
  517. package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
  518. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
  519. package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
  520. package/dist/transaction/transport/commitFrames.d.ts +0 -90
  521. package/dist/transaction/transport/commitFrames.js +0 -134
  522. package/dist/transaction/transport/connectionManager.d.ts +0 -215
  523. package/dist/transaction/transport/connectionManager.js +0 -673
  524. package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
  525. package/dist/transaction/transport/credentialLifecycle.js +0 -324
  526. package/dist/transaction/transport/heartbeat.d.ts +0 -65
  527. package/dist/transaction/transport/heartbeat.js +0 -93
  528. package/dist/transaction/transport/httpClient.d.ts +0 -123
  529. package/dist/transaction/transport/httpClient.js +0 -145
  530. package/dist/transaction/transport/httpOptions.d.ts +0 -33
  531. package/dist/transaction/transport/httpOptions.js +0 -12
  532. package/dist/transaction/transport/httpTransport.d.ts +0 -8
  533. package/dist/transaction/transport/httpTransport.js +0 -1276
  534. package/dist/transaction/transport/networkProbe.d.ts +0 -84
  535. package/dist/transaction/transport/networkProbe.js +0 -207
  536. package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
  537. package/dist/transaction/transport/wsFrameHandlers.js +0 -429
  538. package/dist/transaction/transport/wsTransport.d.ts +0 -576
  539. package/dist/transaction/transport/wsTransport.js +0 -1017
  540. package/dist/transaction/types/assertExact.d.ts +0 -17
  541. package/dist/transaction/types/assertExact.js +0 -1
  542. package/dist/transaction/types/global.d.ts +0 -107
  543. package/dist/transaction/types/global.js +0 -40
  544. package/dist/transaction/types/index.d.ts +0 -205
  545. package/dist/transaction/types/index.js +0 -56
  546. package/dist/transaction/types/modelData.d.ts +0 -10
  547. package/dist/transaction/types/modelData.js +0 -9
  548. package/dist/transaction/types/participant.d.ts +0 -20
  549. package/dist/transaction/types/participant.js +0 -10
  550. package/dist/transaction/types/streams.d.ts +0 -540
  551. package/dist/transaction/types/streams.js +0 -11
  552. package/dist/transaction/utils/asyncIterator.d.ts +0 -34
  553. package/dist/transaction/utils/asyncIterator.js +0 -135
  554. package/dist/transaction/utils/duration.d.ts +0 -25
  555. package/dist/transaction/utils/duration.js +0 -45
  556. package/dist/transaction/utils/json.d.ts +0 -57
  557. package/dist/transaction/utils/json.js +0 -276
  558. package/dist/transaction/wire/accountResponses.d.ts +0 -351
  559. package/dist/transaction/wire/accountResponses.js +0 -255
  560. package/dist/transaction/wire/auth.d.ts +0 -49
  561. package/dist/transaction/wire/auth.js +0 -57
  562. package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
  563. package/dist/transaction/wire/bootstrapReason.js +0 -8
  564. package/dist/transaction/wire/claimEvent.d.ts +0 -76
  565. package/dist/transaction/wire/claimEvent.js +0 -73
  566. package/dist/transaction/wire/claims.d.ts +0 -463
  567. package/dist/transaction/wire/claims.js +0 -229
  568. package/dist/transaction/wire/commit.d.ts +0 -603
  569. package/dist/transaction/wire/commit.js +0 -321
  570. package/dist/transaction/wire/delta.d.ts +0 -250
  571. package/dist/transaction/wire/delta.js +0 -147
  572. package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
  573. package/dist/transaction/wire/errorEnvelope.js +0 -123
  574. package/dist/transaction/wire/feedCursor.d.ts +0 -60
  575. package/dist/transaction/wire/feedCursor.js +0 -82
  576. package/dist/transaction/wire/feedEvent.d.ts +0 -177
  577. package/dist/transaction/wire/feedEvent.js +0 -39
  578. package/dist/transaction/wire/frames.d.ts +0 -194
  579. package/dist/transaction/wire/frames.js +0 -50
  580. package/dist/transaction/wire/inboundFrames.d.ts +0 -552
  581. package/dist/transaction/wire/inboundFrames.js +0 -116
  582. package/dist/transaction/wire/index.d.ts +0 -50
  583. package/dist/transaction/wire/index.js +0 -74
  584. package/dist/transaction/wire/listEnvelope.d.ts +0 -37
  585. package/dist/transaction/wire/listEnvelope.js +0 -42
  586. package/dist/transaction/wire/modelResponses.d.ts +0 -85
  587. package/dist/transaction/wire/modelResponses.js +0 -43
  588. package/dist/transaction/wire/protocol.d.ts +0 -38
  589. package/dist/transaction/wire/protocol.js +0 -38
  590. package/dist/transaction/wire/protocolVersion.d.ts +0 -73
  591. package/dist/transaction/wire/protocolVersion.js +0 -83
  592. package/dist/transactions/mutations/MutationQueue.d.ts +0 -655
  593. package/dist/transactions/mutations/MutationQueue.js +0 -2797
  594. package/dist/transactions/mutations/MutationStore.d.ts +0 -20
  595. package/dist/transactions/mutations/MutationStore.js +0 -53
  596. package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
  597. package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
  598. package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
  599. package/dist/transactions/mutations/coalesceRules.js +0 -140
  600. package/dist/transactions/mutations/commitLatency.d.ts +0 -52
  601. package/dist/transactions/mutations/commitLatency.js +0 -130
  602. package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
  603. package/dist/transactions/mutations/commitOutboxStore.js +0 -26
  604. package/dist/transactions/mutations/commitPayload.d.ts +0 -164
  605. package/dist/transactions/mutations/commitPayload.js +0 -152
  606. package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -59
  607. package/dist/transactions/mutations/deltaConfirmation.js +0 -233
  608. package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
  609. package/dist/transactions/mutations/durableWriteStore.js +0 -12
  610. package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
  611. package/dist/transactions/mutations/optimisticApply.js +0 -65
  612. package/dist/transactions/mutations/replayValidation.d.ts +0 -186
  613. package/dist/transactions/mutations/replayValidation.js +0 -163
  614. package/dist/utils/mobxSetup.d.ts +0 -53
  615. package/dist/utils/mobxSetup.js +0 -330
  616. package/dist/webhooks/events.d.ts +0 -43
  617. package/dist/webhooks/events.js +0 -42
  618. package/dist/webhooks/index.d.ts +0 -8
  619. package/dist/webhooks/index.js +0 -8
  620. package/dist/wire/index.d.ts +0 -1
  621. package/dist/wire/index.js +0 -8
  622. package/docs/interaction-model.md +0 -99
@@ -1,1013 +0,0 @@
1
- import { z } from 'zod';
2
- import { syncGroupInputSchema } from '../schema/roles.js';
3
- /**
4
- * The wire schemas for coordination — the shapes that keep agents and people
5
- * from overwriting each other on a shared row. Coordination works in three
6
- * layers, from outermost to innermost:
7
- *
8
- * 1. Presence (observation): who is working where. It reports, never blocks.
9
- * 2. Claims (pessimistic leases): `claim_begin` / `claim_abandon` grant one
10
- * participant exclusive intent on a target while others wait.
11
- * 3. Stale-context (optimistic): a `readAt` watermark plus an `onStale` write
12
- * guard that catches a lost update when the row moved after you read it.
13
- *
14
- * These Zod schemas are the single definition of each shape. Both the client
15
- * SDK and the server derive their TypeScript types from them with `z.infer`
16
- * rather than re-declaring the shapes, and the server validates inbound frames
17
- * against them at runtime.
18
- */
19
- // ─────────────────────────────────────────────────────────────────────────
20
- // Shared primitives
21
- // ─────────────────────────────────────────────────────────────────────────
22
- /** A line/column span within a text-bearing field (section body, doc, cell). */
23
- export const targetRangeSchema = z.object({
24
- startLine: z.number(),
25
- endLine: z.number(),
26
- startColumn: z.number().optional(),
27
- endColumn: z.number().optional(),
28
- });
29
- export const participantKindSchema = z.enum(['user', 'agent', 'system']);
30
- const _participantKindContract = true;
31
- void _participantKindContract;
32
- /**
33
- * Parses a participant kind from an inbound frame, tolerating an older wire
34
- * dialect. Some presence and claim frames label a non-agent participant
35
- * `'human'`, while the rest of the surface uses `'user'` for the same
36
- * participant. This normalizes `'human'` to `'user'` on read so every consumer
37
- * switches on one vocabulary. Producers emit the canonical
38
- * {@link participantKindSchema} values, and the output union is never widened.
39
- */
40
- export const wireParticipantKindSchema = z.preprocess((value) => (value === 'human' ? 'user' : value), participantKindSchema);
41
- /**
42
- * Resolves a peer's kind from an inbound presence or claim frame. It prefers
43
- * the server-stamped `participantKind` (normalized through
44
- * {@link wireParticipantKindSchema}). A frame from an older server that omits
45
- * that field falls back to the `isAgent` boolean, which can tell 'agent' from
46
- * 'user' but can never report 'system'.
47
- */
48
- export function participantKindFromWire(wireKind, isAgent) {
49
- const parsed = wireParticipantKindSchema.safeParse(wireKind);
50
- if (parsed.success)
51
- return parsed.data;
52
- return isAgent ? 'agent' : 'user';
53
- }
54
- /**
55
- * Reads the peer-visible description a claim or presence frame carries in its
56
- * opaque `meta.description`. This is the single place that unpacks that field.
57
- * A caller that has an explicit `description` should prefer it
58
- * (`explicit ?? fromMeta`).
59
- *
60
- * The parameter is `unknown` because that is the honest requirement: this reads
61
- * one optional string off a value it does not own. Demanding the wire's open
62
- * record instead forced every caller holding a claim's *declared* `meta` — the
63
- * shape registered on `Register`'s `ClaimMeta` slot — through a conversion to
64
- * ask a question that never needed one.
65
- */
66
- export function descriptionFromMeta(meta) {
67
- if (typeof meta !== 'object' || meta === null)
68
- return undefined;
69
- if (!('description' in meta))
70
- return undefined;
71
- const { description } = meta;
72
- return typeof description === 'string' ? description : undefined;
73
- }
74
- /** The default a claim carries when its holder describes no work. */
75
- export const DEFAULT_CLAIM_DESCRIPTION = 'editing';
76
- /**
77
- * Resolves the peer-visible description of a claim from the places a caller may
78
- * have put it, falling back to a plain default.
79
- *
80
- * `reason` was this field's name before it was renamed, and the rename shipped
81
- * without leaving anything behind — so the wire kept accepting both spellings
82
- * while the SDK type quietly offered only one, and two branches "fixed" the
83
- * gap in opposite directions without either being contradicted by a compiler.
84
- * The precedence is declared once, here, and both the client and the server
85
- * read it from this function rather than each spelling out the same `??` chain.
86
- *
87
- * A caller whose default differs — a claim taken around a `create` describes
88
- * itself as `'creating'` — passes that word as `fallback`; the precedence above
89
- * it stays this function's.
90
- */
91
- export function claimDescription(source, fallback = DEFAULT_CLAIM_DESCRIPTION) {
92
- return (source.description ??
93
- descriptionFromMeta(source.meta) ??
94
- source.reason ??
95
- fallback);
96
- }
97
- /**
98
- * What a coordination event points at — the locator shared by all three
99
- * layers. It names an entity, optionally narrowed to a path, range, or field,
100
- * and carries opaque application metadata.
101
- */
102
- export const targetRefSchema = z.object({
103
- entityType: z.string(),
104
- entityId: z.string(),
105
- path: z.string().optional(),
106
- range: targetRangeSchema.optional(),
107
- field: z.string().optional(),
108
- /**
109
- * Several named parts of one row, claimed together — three sections of a
110
- * document, two cells of a table.
111
- *
112
- * This exists because there was no way to say it. A caller who needed it
113
- * packed the set into `field` as one delimited string, and the conflict rule
114
- * compares `field` for equality: `blocks:b_1` and `blocks:b_1,b_2` read as
115
- * unrelated targets, so both writers were granted a lease on `b_1` and one
116
- * of their updates was lost with nothing raised. A set compares as a set —
117
- * overlapping sets conflict, disjoint sets do not.
118
- *
119
- * `field` remains for the single-field case and is read as a set of one, so
120
- * a claim naming `field` and a claim naming `fields` still compare correctly
121
- * against each other.
122
- */
123
- fields: z.array(z.string()).readonly().optional(),
124
- meta: z.record(z.string(), z.unknown()).optional(),
125
- });
126
- /**
127
- * The same locator in the spelling the wait line and the claim handle use —
128
- * `{ type, id }` for the entity, the sub-entity half unchanged. It is a
129
- * projection of {@link targetRefSchema} rather than a second declaration, so a
130
- * member added to the locator reaches the wait line without anyone editing it;
131
- * a hand-written copy here is how `fields` came to be missing from queue frames.
132
- */
133
- const streamTargetSchema = targetRefSchema
134
- .omit({ entityType: true, entityId: true })
135
- .extend({ type: z.string(), id: z.string() });
136
- // ─────────────────────────────────────────────────────────────────────────
137
- // Layer 3 — optimistic stale-context (the write guard)
138
- // ─────────────────────────────────────────────────────────────────────────
139
- /**
140
- * How the server treats a write whose snapshot watermark (`readAt`) is older
141
- * than the target row's latest change. There are three dispositions:
142
- * • `notify` — hold the write and return a {@link StaleNotification}
143
- * carrying the current value, so the actor (agent or human)
144
- * can resolve it.
145
- * • `reject` — throw `AbloStaleContextError`, the default when `readAt`
146
- * is present.
147
- * • `overwrite` — apply the write blindly, last write wins, with no signal.
148
- */
149
- export const onStaleModeSchema = z.enum(['reject', 'overwrite', 'notify']);
150
- /**
151
- * The optimistic guard carried on a commit operation. `readAt` is the
152
- * snapshot watermark from `context.capture` (null/absent ⇒ unguarded write).
153
- * `bypass` is the explicit, recorded override of a *foreign* pessimistic
154
- * claim — see the claim layer below.
155
- */
156
- export const writeGuardSchema = z.object({
157
- readAt: z.number().nullish(),
158
- onStale: onStaleModeSchema.nullish(),
159
- bypass: z.boolean().optional(),
160
- });
161
- /**
162
- * The advisory returned to a committer whose write hit a stale-context
163
- * conflict under `onStale: 'notify'` — it reports that the value the committer
164
- * reasoned against changed while they were away. Rather than throwing, the
165
- * server hands back the conflicting field's current value as data so the
166
- * actor — an agent or a human — can reconcile and re-commit. A claim is the
167
- * prospective form of the same idea (coordinate before acting); this
168
- * notification is the in-flight form (here is what changed, you resolve). It
169
- * rides on the commit acknowledgement alongside `lastSyncId`; an empty or
170
- * absent array means nothing the committer depended on moved.
171
- *
172
- * Only `onStale: 'notify'` produces this. The conflicting operation was held,
173
- * not written, and the actor reconciles against `currentValues` and
174
- * re-commits. `reject` throws instead, and `overwrite` proceeds silently —
175
- * neither notifies.
176
- */
177
- export const staleNotificationSchema = z.object({
178
- /** Names this object's type; every returned object carries such a tag. */
179
- object: z.literal('stale_notification').optional(),
180
- /** Model name of the conflicting row. */
181
- model: z.string(),
182
- /** Row id. */
183
- id: z.string(),
184
- /** The watermark the committer reasoned against (its `readAt`). */
185
- readAt: z.number(),
186
- /**
187
- * Newest delta id on the row — the committer's new watermark. Re-capture
188
- * context at/after this id to reconcile.
189
- */
190
- observedSyncId: z.number(),
191
- /**
192
- * Fields whose concurrent change collided with this write (intersection of
193
- * the committer's written columns and a newer delta's `changed_fields`).
194
- * Empty ⇒ a whole-entity change (CREATE/DELETE/legacy delta).
195
- */
196
- conflictingFields: z.array(z.string()),
197
- /**
198
- * The live values of `conflictingFields` after the conflict — the piece a
199
- * plain stale error omits. It lets the actor reconcile without a follow-up read.
200
- */
201
- currentValues: z.record(z.string(), z.unknown()),
202
- /** Who wrote the conflicting delta. */
203
- writtenBy: z.object({
204
- kind: participantKindSchema,
205
- id: z.string(),
206
- }),
207
- /**
208
- * Set when this notification is for a GROUP premise (e.g. `report:abc`,
209
- * `section:s1`) rather than a single row — "something in the group you read
210
- * changed." For a group notification `conflictingFields`/`currentValues` are
211
- * empty (the change could span many rows); re-read the group at
212
- * `observedSyncId` to reconcile. Absent ⇒ a row-scoped notification.
213
- */
214
- group: z.string().optional(),
215
- });
216
- /**
217
- * One entry in a commit's batch premise — a read it was based on, so the
218
- * server can ask "did anything I looked at change?" — broader than the
219
- * write-target check, which only validates the rows being written. The server
220
- * re-runs stale detection against each entry at its `readAt`; a moved premise
221
- * fires the entry's `onStale` disposition (default `reject`) across the whole
222
- * batch (`notify` holds every write and notifies, `reject` aborts, `overwrite`
223
- * proceeds silently). An entry comes at one of two granularities:
224
- *
225
- * • Row — `{ model, id, readAt, fields? }`: did this specific row, or these
226
- * specific fields, change?
227
- * • Group — `{ group, readAt }`: did anything in this sync group change?
228
- * `group` is a sync-group key such as `report:abc` or `section:s1`, the
229
- * same unit a participant watches and claims.
230
- *
231
- * See `packages/sync-engine/docs/concurrency-convention.md` (§4) for the
232
- * governing convention and the receive → reconcile loop.
233
- */
234
- export const readDependencySchema = z.union([
235
- z.object({
236
- model: z.string(),
237
- id: z.string(),
238
- readAt: z.number(),
239
- fields: z.array(z.string()).readonly().optional(),
240
- onStale: onStaleModeSchema.optional(),
241
- }),
242
- z.object({
243
- group: z.string(),
244
- readAt: z.number(),
245
- onStale: onStaleModeSchema.optional(),
246
- }),
247
- ]);
248
- /**
249
- * A durable premise — what a participant is watching so that a later
250
- * change to it opens a {@link StaleNotification}. It is the persisted sibling of
251
- * a {@link ReadDependency}: the same reference shape, minus the disposition (a
252
- * track always notifies — that is what tracking is), with an optional `readAt`
253
- * that defaults to the watermark of the commit that registered it. The row form
254
- * watches one object; the group form watches a whole sync group ("anything in
255
- * `report:abc`"). Where a `ReadDependency` is checked once at commit and
256
- * discarded, a `TrackDependency` is kept and re-checked against every future
257
- * delta. See `packages/sync-engine/docs/groups.md` for how it drives change
258
- * propagation.
259
- */
260
- export const trackDependencySchema = z.union([
261
- z.object({
262
- model: z.string(),
263
- id: z.string(),
264
- readAt: z.number().optional(),
265
- }),
266
- z.object({
267
- group: z.string(),
268
- readAt: z.number().optional(),
269
- }),
270
- ]);
271
- // ─────────────────────────────────────────────────────────────────────────
272
- // Layer 2 — pessimistic claims and leases
273
- // ─────────────────────────────────────────────────────────────────────────
274
- /**
275
- * The lifecycle of a claim. When absent on the wire it means `'active'` (an
276
- * additive back-compat default). The server stamps `'active'` on `claim_begin`
277
- * and emits one terminal frame — `committed`, `canceled`, or `expired` — as the
278
- * claim ends, so contenders learn how it resolved, not merely that it vanished.
279
- */
280
- export const wireClaimStatusSchema = z.enum([
281
- 'active',
282
- 'committed',
283
- 'expired',
284
- 'canceled',
285
- ]);
286
- /**
287
- * Every lifecycle state of a claim, as a caller sees it.
288
- *
289
- * `active` is the current holder — the lock itself. `queued` is waiting in line
290
- * behind the holder and carries an advisory `position`. The rest are terminal
291
- * and drop the claim from the synced set.
292
- *
293
- * Distinct from {@link wireClaimStatusSchema}, which never carries `queued`
294
- * because the wire frame for a waiter is a different message. This is the one a
295
- * published contract describes, so it is a schema rather than a bare TS union —
296
- * a union cannot be derived into the API reference.
297
- */
298
- export const publicClaimStatusSchema = z.enum([
299
- 'active',
300
- 'queued',
301
- 'committed',
302
- 'expired',
303
- 'canceled',
304
- ]);
305
- /**
306
- * @deprecated Renamed to {@link wireClaimStatusSchema} — this is the wire enum,
307
- * which never carries `'queued'`; the five-state public status lives in
308
- * types/streams. Removed in 0.36.0.
309
- */
310
- export const claimStatusSchema = wireClaimStatusSchema;
311
- /**
312
- * Server-owned grant stamps — minted once when a claim is first granted and
313
- * preserved verbatim across a re-announce of the same `claimId`, so neither a
314
- * reconnect nor a client-supplied value can move them (unlike `declaredAt`,
315
- * which the client sends afresh each announce). Both optional: a frame without
316
- * them stays valid, and the feature each backs simply does not engage.
317
- */
318
- const grantStampFields = {
319
- /**
320
- * The monotonic fencing token minted for this grant (Option B). Strictly
321
- * increasing per entity across successive grants, so a write that carries it
322
- * is rejected at commit if a later holder already advanced the entity's
323
- * high-water. A token-less write is simply not fence-checked.
324
- */
325
- fenceToken: z.number().optional(),
326
- /**
327
- * Lease origin (epoch ms): when THIS holding was acquired. The cumulative-
328
- * hold ceiling measures a holder's fair share from here — and because it
329
- * survives a re-announce, a reconnect cannot rewind the clock.
330
- */
331
- acquiredAt: z.number().optional(),
332
- };
333
- /**
334
- * A holder as the participant blocked behind them sees it: who has the row,
335
- * what they said they are doing, and until when.
336
- *
337
- * This is the smaller half of a claim, so it is declared first and the full
338
- * claim extends it — the waiter's view cannot omit a member the holder's view
339
- * has, because there is nowhere for it to be omitted. Listing what to keep was
340
- * the bug: this named `field` and not `path`, `range`, or `fields`, so a waiter
341
- * could see that a row was held but never which part of it, and every locator
342
- * member added later would have been missing here too.
343
- */
344
- export const wireClaimSummarySchema = targetRefSchema.extend({
345
- claimId: z.string(),
346
- /**
347
- * Peer-visible description of the work being done (`'rewriting the risk
348
- * section to match Q3'`). The server stamps a default when a frame carries
349
- * none.
350
- */
351
- description: z.string().optional(),
352
- /** Server-stamped declaration time (epoch ms). */
353
- declaredAt: z.number(),
354
- /** Server-computed TTL deadline (epoch ms). Readers treat as advisory. */
355
- expiresAt: z.number(),
356
- /**
357
- * On whose authority the holder acts, and under which grant — stamped by the
358
- * server off the connection's credential, never accepted from the frame. The
359
- * same three fields the delta this claim produces will record, so "who is
360
- * doing this" and "who did this" answer in one vocabulary.
361
- *
362
- * On the summary rather than the full claim because this is precisely what a
363
- * blocked waiter needs: yielding to a colleague and queuing behind another
364
- * customer's agent are different decisions.
365
- *
366
- * All three optional and additive — an older server omits them, which is a
367
- * different fact from a holder that has no delegator.
368
- */
369
- onBehalfOfId: z.string().nullish(),
370
- onBehalfOfKind: wireParticipantKindSchema.nullish(),
371
- capabilityId: z.string().nullish(),
372
- });
373
- /**
374
- * The full claim as its holder's own frames carry it — the waiter's view plus
375
- * the lifecycle and grant stamps that belong to the holding itself.
376
- */
377
- const wireClaimBaseSchema = wireClaimSummarySchema.extend({
378
- status: wireClaimStatusSchema.optional(),
379
- ...grantStampFields,
380
- });
381
- /** Why a claim ended in a non-success terminal state. */
382
- export const claimErrorSchema = z.object({
383
- code: z.string(),
384
- message: z.string().optional(),
385
- /** Participant already holding the target (conflict rejections). */
386
- heldBy: z.string().optional(),
387
- heldByClaimId: z.string().optional(),
388
- heldByExpiresAt: z.number().optional(),
389
- /** Rich holder context for conflict rejections. Additive: older frames omit it. */
390
- heldByClaim: wireClaimSummarySchema.optional(),
391
- /** Optional conflict-policy explanation. Additive: older frames omit it. */
392
- policyReason: z.string().optional(),
393
- });
394
- /**
395
- * A declared, pending-mutation claim — the unit broadcast inside a presence
396
- * frame's `activeClaims`. The client supplies the descriptive `targetRef`
397
- * fields, a `description` of the work, and a chosen `claimId`; the server stamps
398
- * `declaredAt` and `expiresAt` and may set `status` and `error`. Those last
399
- * two are optional, so one shape serves both the server, which sets them, and
400
- * the leaner SDK view, which reads a claim without them.
401
- */
402
- export const wireClaimSchema = wireClaimBaseSchema.extend({
403
- error: claimErrorSchema.optional(),
404
- });
405
- export const claimRejectionSchema = z.object({
406
- claimId: z.string(),
407
- reason: z.string(),
408
- target: targetRefSchema.optional(),
409
- heldBy: z.string().optional(),
410
- /**
411
- * Whether the holder blocking this claim is a person, an agent, or the
412
- * system. The server already derives this from the holder's id when it
413
- * builds the conflict; carrying it means a caller can decide how to respond
414
- * — yield to a person, queue behind an agent — without parsing an opaque id
415
- * for a prefix and guessing. Additive: an older server omits it.
416
- */
417
- heldByKind: wireParticipantKindSchema.optional(),
418
- heldByClaimId: z.string().optional(),
419
- heldByExpiresAt: z.number().optional(),
420
- heldByClaim: wireClaimSummarySchema.optional(),
421
- policyReason: z.string().optional(),
422
- });
423
- /**
424
- * The point-to-point notification sent to a holder whose lease ended without
425
- * a successful commit. This remains a wire-shaped target because it arrives
426
- * directly from the WebSocket; the schema is the single validation boundary
427
- * before the event reaches public `claims.onLost` listeners.
428
- */
429
- export const claimLostSchema = z.object({
430
- claimId: z.string(),
431
- reason: z.enum(['expired', 'preempted']),
432
- target: targetRefSchema,
433
- });
434
- /**
435
- * The lease is ours without waiting — the target was free when the claim
436
- * arrived. `fenceToken` is present whenever the coordinator minted one, and a
437
- * write carries it back so a lapsed lease cannot apply late.
438
- */
439
- export const claimAcquiredSchema = z.object({
440
- claimId: z.string(),
441
- fenceToken: z.number().optional(),
442
- target: targetRefSchema,
443
- });
444
- /**
445
- * A queued claim reached the head of the line and the lease is now ours. The
446
- * shape matches {@link claimAcquiredSchema} exactly — the two frames differ
447
- * only in whether the caller waited — but they stay separate declarations
448
- * because they are separate wire contracts, and collapsing them would let a
449
- * change to one silently redefine the other.
450
- */
451
- export const claimGrantedSchema = z.object({
452
- claimId: z.string(),
453
- fenceToken: z.number().optional(),
454
- target: targetRefSchema,
455
- });
456
- /**
457
- * Our claim is waiting in line behind a live holder — the same conflict
458
- * {@link claimRejectionSchema} reports, delivered as a wait rather than a
459
- * refusal, plus the caller's `position`.
460
- *
461
- * `reason` is the one member that does not carry over as required. A refusal
462
- * states why it refused; a wait has only ever named the conflict through
463
- * `heldBy`/`heldByClaim`, and no server has ever stamped `reason` on this
464
- * frame. Requiring it here — inherited silently by extending the rejection
465
- * schema — made the parse boundary reject every genuine `claim_queued` as
466
- * malformed the moment frame validation went in. Optional is what the wire
467
- * actually is, and it stays derived from the rejection field so the two cannot
468
- * describe the value differently.
469
- *
470
- * `position` is advisory: a privileged reorder can move it up, so a caller
471
- * that asserts monotonic position will fail in production. Only the arrival of
472
- * a grant is authoritative.
473
- */
474
- export const claimQueuedSchema = claimRejectionSchema.extend({
475
- position: z.number(),
476
- reason: claimRejectionSchema.shape.reason.optional(),
477
- });
478
- /**
479
- * One entry in a wait-line snapshot.
480
- *
481
- * NOTE — this is the third spelling of a target locator on the wire: here it is
482
- * `{ type, id }`, the HTTP claim DTO uses `{ model, id }`
483
- * ({@link modelTargetSchema}), and the claim frames use
484
- * `{ entityType, entityId }` ({@link targetRefSchema}). The schema describes
485
- * what the server sends today rather than what it should send; unifying the
486
- * three is a coordinated protocol change scheduled behind the protocol version.
487
- * Until it happens, the translation between the spellings lives in one place —
488
- * `wireTarget`, `modelTarget` and `streamTarget` in ./locator.ts — so no hop
489
- * gets to invent a fourth.
490
- */
491
- export const claimQueueEntrySchema = z.object({
492
- object: z.literal('claim'),
493
- id: z.string(),
494
- status: z.literal('queued'),
495
- target: streamTargetSchema,
496
- /**
497
- * Peer-visible description of the work. A claim may be declared without one,
498
- * and the public `Claim` promises the field is always there — so the default
499
- * lives here, applied as the frame is decoded, rather than being restated by
500
- * each reader.
501
- */
502
- description: z.string().default('editing'),
503
- heldBy: z.string().optional(),
504
- participantKind: wireParticipantKindSchema.optional(),
505
- position: z.number(),
506
- expiresAt: z.number(),
507
- });
508
- /**
509
- * The whole wait line for one row, rebroadcast to that row's peers on every
510
- * queue mutation. This is what backs the reactive
511
- * `ablo.<model>.claim.queue({ id })` read, which is why it carries the full
512
- * line rather than a delta against it.
513
- */
514
- export const claimQueueSchema = z.object({
515
- target: streamTargetSchema.pick({ type: true, id: true }),
516
- queue: z.array(claimQueueEntrySchema),
517
- });
518
- /**
519
- * A held claim's TTL lapsed server-side. The claim is already inactive by the
520
- * time this arrives, so a consumer either re-claims with a fresh credential or
521
- * accepts the drop; there is nothing to release.
522
- */
523
- export const claimExpiredSchema = z.object({
524
- claimId: z.string(),
525
- });
526
- /**
527
- * Why a claim ended without its holder releasing it, or was refused.
528
- *
529
- * A closed set, because the two refusals are different guarantees and a reader
530
- * has to be able to tell them apart: `conflict` means someone holds the row
531
- * right now and you may queue behind them, while `coordination_unavailable`
532
- * means the coordinator could not answer, so nothing is known about the row.
533
- * `expired` and `preempted` are the two ways a lease you held ends.
534
- *
535
- * The rejection frame's `reason` stays a plain string on the wire — it is
536
- * frozen, and an older server may send a word not listed here. This is the
537
- * reader's side of it: a value that parses becomes the typed reason, and one
538
- * that does not is simply absent rather than smuggled through as prose.
539
- * {@link claimExpiredSchema} and {@link claimLostSchema} already spelled their
540
- * reasons as enums; this brings the refusals into line.
541
- */
542
- export const claimEventReasonSchema = z.enum([
543
- 'conflict',
544
- 'coordination_unavailable',
545
- 'expired',
546
- 'preempted',
547
- ]);
548
- /**
549
- * What a {@link ModelClaim} points at — the target locator as SDK callers see
550
- * it, keyed by `model` and `id` rather than the wire schema's `entityType` and
551
- * `entityId`. This is the public `ModelTarget` shape.
552
- */
553
- export const modelTargetSchema = z
554
- .object({
555
- model: z.string(),
556
- id: z.string(),
557
- path: z.string().optional(),
558
- range: targetRangeSchema.optional(),
559
- field: z.string().optional(),
560
- /** Several named parts at once — see {@link targetRefSchema}. */
561
- fields: z.array(z.string()).readonly().optional(),
562
- meta: z.record(z.string(), z.unknown()).optional(),
563
- })
564
- .readonly();
565
- /**
566
- * The two states a claim can be observed in while it still exists.
567
- *
568
- * Derived from {@link publicClaimStatusSchema} rather than spelled again: the
569
- * other three are terminal and drop the claim from the observable set, so a
570
- * listing or a peer's view can only ever see these. Extracting them by name
571
- * means a state added to the public vocabulary is a deliberate decision about
572
- * whether it is observable, not a silent omission.
573
- */
574
- export const heldClaimStatusSchema = publicClaimStatusSchema.extract([
575
- 'active',
576
- 'queued',
577
- ]);
578
- /**
579
- * ONE CLAIM — everything true about a lease at a moment: what it points at, who
580
- * holds it, what they said they are doing, where it stands, and until when.
581
- *
582
- * Every caller-facing surface that answers a question about a claim is a
583
- * PROJECTION of this record, never a second object: {@link modelClaimSchema} is
584
- * what a peer may see, and `claimStateSchema` (`wire/claims.ts`) is what a
585
- * caller polls about a claim of its own. Each is pinned to this record, so a
586
- * field added here either reaches the people it was declared for or fails to
587
- * compile.
588
- *
589
- * Before this, the peer-visible shape was a standalone `z.object` deriving from
590
- * nothing, and the polling shape was a third. That is why it took reading four
591
- * files to answer whether a heartbeat's progress reaches an asker — the
592
- * declaring surface and the observing surface were kept in step by hand, and
593
- * three of their shared fields had already drifted on how strictly they parse.
594
- *
595
- * What this record deliberately does NOT unify is the socket family
596
- * ({@link wireClaimSchema} and its base). Those carry the same claim under the
597
- * `entityType`/`entityId` locator rather than `model`/`id`, and they already
598
- * derive from one another; collapsing the two locator spellings is a wire
599
- * rename, not a projection.
600
- */
601
- export const claimRecordSchema = z.object({
602
- /** The claim's identity. Spelled `claimId` where a message names a claim it
603
- * is not itself, and `id` where the claim is the resource. */
604
- id: z.string(),
605
- /** Who holds it. */
606
- actor: z.string(),
607
- /** Parsed through {@link wireParticipantKindSchema}, so a legacy `'human'`
608
- * frame normalizes to `'user'`. */
609
- participantKind: wireParticipantKindSchema,
610
- /**
611
- * On whose authority the holder acts — the same three fields, with the same
612
- * meanings, that `deltaAttributionSchema` records on every delta the claim
613
- * goes on to produce, and sourced the same way: off the credential the
614
- * connection authenticated with, never from the caller.
615
- *
616
- * A claim that carries only `actor` can say who is doing something and not
617
- * who asked for it. "What is agent a7f3 doing" is a debugging question;
618
- * "what is running on behalf of this customer right now" is an operations
619
- * question, and until these are here it is answerable only in hindsight,
620
- * against the audit log, after the fact.
621
- *
622
- * Null rather than absent when there is genuinely no delegator or no grant —
623
- * a person acting directly is their own principal, and a session holds no
624
- * capability.
625
- */
626
- onBehalfOfId: z.string().nullable(),
627
- onBehalfOfKind: wireParticipantKindSchema.nullable(),
628
- capabilityId: z.string().nullable(),
629
- /**
630
- * What the holder said they are doing (`'rewriting the risk section'`).
631
- *
632
- * A caller may declare it as `description`, as the older `reason`, or inside
633
- * `meta`; {@link claimDescription} resolves those to this one field with a
634
- * declared precedence, so only one of them is ever a shape.
635
- */
636
- description: z.string(),
637
- /** Holding the row, or waiting in line for it. */
638
- status: heldClaimStatusSchema,
639
- /**
640
- * Place in the wait line. Advisory: a privileged caller can reorder the
641
- * queue, so a position can go UP between reads — only `status` is
642
- * authoritative.
643
- */
644
- position: z.number().int().nonnegative(),
645
- /**
646
- * When the lease lapses without a heartbeat, in epoch milliseconds — the same
647
- * encoding as the WebSocket {@link WireClaim}, so one timestamp
648
- * representation spans the wire, the SDK, HTTP, and errors. There is no ISO
649
- * string anywhere.
650
- */
651
- expiresAt: z.number().int(),
652
- /** The grant's fencing token, minted at acquisition. Present on a claim that
653
- * is held, never on one that is queued. */
654
- fenceToken: z.number().int(),
655
- /** The row, and which part of it. */
656
- target: modelTargetSchema,
657
- /**
658
- * The claim's metadata as an OPEN record — including what the coordinator
659
- * writes there rather than the holder. A heartbeat's `details` lands here as
660
- * `progress` (last beat wins), so an asker reads
661
- * `claim.state({ id })?.meta.progress`. It is presence, not a checkpoint: it
662
- * dies with the lease.
663
- *
664
- * This is the same bag the wire carries; what is new is that it has a home at
665
- * the CLAIM level. Both projections used to file it under `target` alone, and
666
- * `target.meta` is typed as the shape the program registered for its own claim
667
- * metadata — so a server-written key was unreadable there by construction:
668
- * `target.meta.progress` does not typecheck for any program that declared a
669
- * shape, and the value was arriving in a slot whose type forbids it.
670
- *
671
- * Two views of one field, each typed for its reader: `target.meta` stays the
672
- * holder's declared shape, and this stays open, because a peer reading someone
673
- * else's claim has no grounds to assume the writer's declaration.
674
- */
675
- meta: z.record(z.string(), z.unknown()).optional(),
676
- });
677
- /**
678
- * A claim as SDK callers and the HTTP claim routes see it
679
- * (`ablo.<model>.claim.state`, `GET /v1/claims`) — the resolved, peer-readable
680
- * view of one active or queued claim. The client's `ModelClaim` type derives
681
- * from this shape.
682
- *
683
- * Everything but the deprecated `field` is projected from
684
- * {@link claimRecordSchema}. Four members are optional here and required on the
685
- * record, and the split is the same in each case: the record says what a claim
686
- * IS, while a peer's view of one may legitimately have been built without them
687
- * — a queued claim has no `fenceToken`, a held one has no `position`, an older
688
- * producer sends no `status`, and a claim may be declared with no description.
689
- */
690
- export const modelClaimSchema = claimRecordSchema
691
- .partial({
692
- description: true,
693
- status: true,
694
- position: true,
695
- fenceToken: true,
696
- // Additive: a server that predates the delegation trio omits all three,
697
- // which is a different fact from a claim that has no delegator (null).
698
- onBehalfOfId: true,
699
- onBehalfOfKind: true,
700
- capabilityId: true,
701
- })
702
- .extend({
703
- /**
704
- * @deprecated Read `target.field` instead, and `target.fields` for a claim
705
- * on several parts of the row. Removed in 0.36.0.
706
- *
707
- * This says the same thing as `target.field` and nothing keeps the two
708
- * agreeing, so a producer that sets one and not the other publishes a
709
- * claim that contradicts itself. It also cannot express a field set at
710
- * all, which is the reason `target.fields` exists.
711
- */
712
- field: z.string().optional(),
713
- })
714
- .readonly();
715
- /**
716
- * The peer-visible view covers the record. A field added to a claim is either
717
- * projected to the people it was declared for, or deliberately dropped by an
718
- * `.omit` here — never missing because nobody remembered the second object.
719
- */
720
- const _modelClaimCoversRecord = true;
721
- void _modelClaimCoversRecord;
722
- /**
723
- * The `claim_begin` payload a client sends. It carries the descriptive target
724
- * and a `description` of the work, an optional duration hint, and the opt-in
725
- * fair-queue flag. The server stamps the lifecycle and timestamp fields, so they
726
- * are not part of this inbound shape — this is exactly what the server validates
727
- * on ingest.
728
- */
729
- export const claimBeginPayloadSchema = targetRefSchema.extend({
730
- claimId: z.string(),
731
- /** Peer-visible description of the work. The server stamps `'editing'` when a
732
- * frame carries none. */
733
- description: z.string().optional(),
734
- /** Hint for `expiresAt`; the server caps it. */
735
- estimatedMs: z.number().optional(),
736
- /**
737
- * Opt into the fair wait queue. When the target is already held, the server
738
- * enqueues this claim in FIFO order and replies `claim_queued`, then
739
- * `claim_granted` later, instead of `claim_rejected`. A client that sets this
740
- * must be ready to handle the grant.
741
- */
742
- queue: z.boolean().optional(),
743
- });
744
- /**
745
- * The `claim_abandon` payload a client sends. `entityType` and `entityId` let
746
- * the server dequeue a claim that is still waiting (not yet held) from the FIFO
747
- * line; abandoning a claim that is already held needs only `claimId`.
748
- */
749
- export const claimAbandonPayloadSchema = z.object({
750
- claimId: z.string(),
751
- entityType: z.string().optional(),
752
- entityId: z.string().optional(),
753
- });
754
- /**
755
- * The `claim_reorder` payload a client sends. A privileged participant, such as
756
- * a supervisor over its sub-agents, re-ranks the FIFO wait queue for an entity:
757
- * `order` lists waiters by `heldBy` and `claimId` in the desired priority, and
758
- * any waiter not listed keeps its relative order behind those that are. The
759
- * server gates who may call this and drops an unauthorized sender. Where
760
- * `claim_abandon` acts on the caller's own entry, a reorder acts on other
761
- * participants' queue positions — which is why it is gated.
762
- */
763
- export const claimReorderPayloadSchema = z.object({
764
- entityType: z.string(),
765
- entityId: z.string(),
766
- order: z.array(z.object({ heldBy: z.string(), claimId: z.string() })),
767
- });
768
- // ─────────────────────────────────────────────────────────────────────────
769
- // Heartbeat — the async / long-running-work surface of a claim.
770
- //
771
- // A claim's TTL is crash cleanup, not a work-duration estimate. Work that
772
- // outlives it — an agent run, a background worker's job — keeps its lease by
773
- // BEATING: request `claim_heartbeat`, reply `claim_heartbeat_ack`. One field
774
- // set serves every shape; the single and batched payloads are both derived
775
- // from it, and the WebSocket frame and HTTP routes are two encodings of the
776
- // same messages. Everything long-running-work-related on the wire lives in
777
- // this block.
778
- // ─────────────────────────────────────────────────────────────────────────
779
- /**
780
- * The one field set behind every heartbeat message. The single-claim payload
781
- * refines it; the batched payload picks from it — there is deliberately no
782
- * second shape to keep in sync.
783
- */
784
- const claimHeartbeatFieldsSchema = z.object({
785
- claimId: z.string().optional(),
786
- entityType: z.string().optional(),
787
- entityId: z.string().optional(),
788
- /** Requested extension from now; the server clamps it, and an extension
789
- * never shortens a lease. */
790
- ttlMs: z.number().positive().optional(),
791
- /**
792
- * Lightweight progress the beat carries along ("42/100 pages") — stored
793
- * as the claim's `meta.progress` (last beat wins) and peer-visible via
794
- * `claim.state` while the lease is held. This is presence, not a
795
- * checkpoint: it dies with the lease. Crash-recoverable progress belongs
796
- * in the data itself — write a row, and every subscriber already sees it.
797
- */
798
- details: z.record(z.string(), z.unknown()).optional(),
799
- });
800
- /**
801
- * The `claim_heartbeat` payload a client sends to extend a lease it holds (or
802
- * refresh its slot in the wait queue) past the liveness window — the
803
- * work-duration signal for long-running holders, distinct from the connection
804
- * keepalive.
805
- *
806
- * The claim is identified either way: by `claimId`, or — since a claim is
807
- * singular per (actor, entity) — by the full `entityType`/`entityId` target
808
- * ("my claim on this row"). At least one of the two must be present. The
809
- * target also lets the server resolve without a scan and is required to
810
- * refresh a *queued* claim (a waiter is not in the holder set the server
811
- * would otherwise search).
812
- */
813
- export const claimHeartbeatPayloadSchema = claimHeartbeatFieldsSchema.refine((payload) => payload.claimId !== undefined ||
814
- (payload.entityType !== undefined && payload.entityId !== undefined), {
815
- message: 'a heartbeat must identify its claim — pass claimId, or entityType and entityId together',
816
- });
817
- /**
818
- * The server's reply to a `claim_heartbeat`. For a socketless worker the
819
- * heartbeat reply is the only inbound signal path, so it carries the lease's
820
- * fate rather than a bare ok: `held` (extended to `expiresAt`), `queued`
821
- * (slot refreshed; `position` is the current place in line), or `lost` (the
822
- * lease expired and the queue moved on — the worker should abandon or
823
- * re-queue, and any write it still attempts is caught by its `readAt` guard).
824
- */
825
- export const claimHeartbeatAckPayloadSchema = z.object({
826
- claimId: z.string(),
827
- status: z.enum(['held', 'queued', 'lost']),
828
- expiresAt: z.number().optional(),
829
- position: z.number().optional(),
830
- /**
831
- * How many participants are waiting in line behind a held lease — the
832
- * cooperative-yield pressure signal (present on `held`). A worker that can
833
- * checkpoint may choose to release early when others wait. Hard
834
- * cancellation needs no extra field: a preempted, expired, or revoked
835
- * lease answers the next beat with `lost`.
836
- */
837
- queueDepth: z.number().optional(),
838
- });
839
- /**
840
- * The batched heartbeat — one request extends every lease the caller holds
841
- * on its plane (the socketless twin of the WebSocket keepalive, which renews
842
- * all held leases on every ping). For a worker holding many rows this is one
843
- * round trip per cadence instead of one per claim. Queued slots are not
844
- * batch-refreshed: a waiter knows its target and beats it directly.
845
- */
846
- export const claimHeartbeatBatchPayloadSchema = claimHeartbeatFieldsSchema.pick({ ttlMs: true });
847
- /** Reply to a batched heartbeat: one ack entry per lease that was extended. */
848
- export const claimHeartbeatBatchAckPayloadSchema = z.object({
849
- results: z.array(claimHeartbeatAckPayloadSchema),
850
- });
851
- // ─────────────────────────────────────────────────────────────────────────
852
- // Read interest — area-of-interest navigation (update_subscription)
853
- // ─────────────────────────────────────────────────────────────────────────
854
- /**
855
- * The `update_subscription` payload a client sends. It replaces the
856
- * connection's read interest with the complete set of sync groups — the read
857
- * counterpart to a claim, with no write lock and no TTL. Each entry is a
858
- * {@link syncGroupInputSchema} (`'default'` or a branded `kind:id`), so a
859
- * malformed group is rejected on ingest rather than silently indexed. The
860
- * element type is strict because this is untrusted client input.
861
- */
862
- export const updateSubscriptionPayloadSchema = z.object({
863
- syncGroups: z.array(syncGroupInputSchema),
864
- });
865
- /**
866
- * `subscription_ack` payload (server → client). Echoes the connection's
867
- * effective read set after the update (unchanged on rejection — the update is
868
- * atomic). `error` is present iff `success` is false (e.g. a scoped key
869
- * requesting a group outside its grant). `syncGroups` is lenient
870
- * (`z.string()`) here, not branded: it is the server's own echo for display,
871
- * not untrusted input, and includes base anchors like `org:<id>`.
872
- */
873
- export const subscriptionAckPayloadSchema = z.object({
874
- success: z.boolean(),
875
- syncGroups: z.array(z.string()),
876
- error: z.object({ code: z.string(), message: z.string() }).optional(),
877
- });
878
- // ─────────────────────────────────────────────────────────────────────────
879
- // Commit operation — carries the optimistic write-guard (Layer 3)
880
- // ─────────────────────────────────────────────────────────────────────────
881
- export const commitOperationTypeSchema = z.enum([
882
- 'CREATE',
883
- 'UPDATE',
884
- 'DELETE',
885
- 'ARCHIVE',
886
- 'UNARCHIVE',
887
- ]);
888
- /**
889
- * A single mutation in a commit batch, as it arrives on the wire. Extends the
890
- * optimistic `writeGuard` (`readAt`/`onStale`/`bypass`) — the structural link
891
- * that makes "every write is stale-guarded" legible in the type, not just in
892
- * prose.
893
- */
894
- export const commitOperationSchema = writeGuardSchema.extend({
895
- type: commitOperationTypeSchema,
896
- model: z.string(),
897
- id: z.string().nullish(),
898
- input: z.record(z.string(), z.unknown()).nullish(),
899
- /** Per-op client tx id, echoed on the broadcast delta. */
900
- transactionId: z.string().nullish(),
901
- /**
902
- * The fencing token from the held claim this write belongs to (Option B).
903
- * Present only on a write issued under a claim that was granted one; the
904
- * server checks it against the entity's persisted high-water and rejects a
905
- * stale token. Absent (nullish) on every unclaimed write — those are governed
906
- * by version-CAS and the Option A blind-write guard, unchanged.
907
- */
908
- fenceToken: z.number().nullish(),
909
- });
910
- // ─────────────────────────────────────────────────────────────────────────
911
- // Layer 1 — presence (observation only; it never enforces)
912
- // ─────────────────────────────────────────────────────────────────────────
913
- export const presenceKindSchema = z.enum(['enter', 'update', 'leave']);
914
- /**
915
- * What a participant is actively working on (agents fill this in).
916
- *
917
- * The two backpressure fields are part of the frame, not an extension of it:
918
- * an agent worker announces them on every step, and an orchestrator reading
919
- * peer activity routes work by them. They are declared here because a reader
920
- * that validates this frame would otherwise drop them on the floor — the
921
- * server passes both through without interpreting either.
922
- */
923
- export const presenceActivitySchema = targetRefSchema.extend({
924
- action: z.string(),
925
- detail: z.string().optional(),
926
- /** Backpressure signal in `[0, 1]`: `0` idle, `1` at capacity. */
927
- loadFactor: z.number().optional(),
928
- /** Gate for new assignments; absent means yes. */
929
- acceptingNewWork: z.boolean().optional(),
930
- });
931
- /**
932
- * Full `presence_update` frame as the server broadcasts it. The activity +
933
- * `activeClaims` are the observation surface for the other two layers —
934
- * rendered, never acted on as enforcement.
935
- *
936
- * Open for the same reason {@link presenceUpdatePayloadSchema} is, and it has to
937
- * be the same in both directions: whatever vocabulary an application announces
938
- * through presence, it reads back off its peers' frames. A reader that parsed
939
- * this strictly would validate the frame and quietly discard the part the
940
- * application actually came for.
941
- */
942
- export const presenceUpdateSchema = z.object({
943
- kind: presenceKindSchema,
944
- /**
945
- * Who the frame is about. Required, because every one of the five sites that
946
- * builds a presence frame stamps it from the connection's identity — an
947
- * anonymous presence frame has never been sent and would say nothing. It was
948
- * optional here for as long as nothing parsed the frame, and the hand-written
949
- * copy the transport used to carry declared it required; two descriptions of
950
- * one frame can disagree indefinitely while neither is ever checked.
951
- */
952
- userId: z.string(),
953
- syncGroups: z.array(z.string()).optional(),
954
- timestamp: z.number().optional(),
955
- status: z.string(),
956
- timezone: z.string().optional(),
957
- customStatus: z.string().optional(),
958
- activity: presenceActivitySchema.optional(),
959
- isAgent: z.boolean().optional(),
960
- /**
961
- * Server-stamped canonical kind. Additive — older servers omit it and
962
- * readers fall back to `isAgent` (see {@link participantKindFromWire}).
963
- */
964
- participantKind: wireParticipantKindSchema.optional(),
965
- activeClaims: z.array(wireClaimSchema).optional(),
966
- delegatedFrom: z.string().nullish(),
967
- }).catchall(z.unknown());
968
- /**
969
- * @deprecated Renamed to {@link presenceUpdateSchema}. Removed in 0.36.0.
970
- *
971
- * `Frame` was the only such suffix in this vocabulary: every other frame the
972
- * server sends is named plainly — {@link claimLostSchema},
973
- * {@link claimAcquiredSchema}, {@link claimRejectionSchema} — and the client's
974
- * half carries `Payload`. One name did not follow the rule the other fifteen do.
975
- */
976
- export const presenceUpdateFrameSchema = presenceUpdateSchema;
977
- /**
978
- * The `presence_update` payload a client SENDS — deliberately much smaller
979
- * than the frame the server broadcasts back.
980
- *
981
- * Everything that identifies or situates the participant is stamped by the
982
- * server and cannot be declared here: `userId`, `participantKind`, `isAgent`,
983
- * `syncGroups`, `timestamp`, `kind`, and `delegatedFrom` all come from the
984
- * connection's own identity. A client that sends them is not believed — an
985
- * older SDK once hardcoded `isAgent: true` on every announce, and because the
986
- * payload was spread into the broadcast unfiltered, every human session
987
- * rendered to its peers as an agent. Parsing an inbound payload through this
988
- * schema and broadcasting the *result* is what makes that structurally
989
- * impossible rather than a rule the broadcast has to remember.
990
- *
991
- * `status` is a plain string, matching the outbound frame: the three canonical
992
- * values are conventions the presence UI understands, not a closed set the
993
- * protocol enforces.
994
- *
995
- * The payload is deliberately OPEN — `catchall` keeps keys this schema does not
996
- * name. Presence is the one frame an application extends: an agent mesh
997
- * announces its own coordination vocabulary through it and reads it back off
998
- * peer frames, without the protocol having to learn each app's words. So the
999
- * fields named here are validated and typed, and anything else rides along
1000
- * untouched. Openness is not the same as trust: the server-stamped identity
1001
- * fields are applied AFTER this payload is spread into the broadcast, so a
1002
- * client that sends its own `userId` or `isAgent` is overwritten either way.
1003
- */
1004
- export const presenceUpdatePayloadSchema = z
1005
- .object({
1006
- status: z.string().optional(),
1007
- activity: presenceActivitySchema.optional(),
1008
- /** The sender's own open claims, which replace what the server holds. */
1009
- activeClaims: z.array(wireClaimSchema).optional(),
1010
- timezone: z.string().optional(),
1011
- customStatus: z.string().optional(),
1012
- })
1013
- .catchall(z.unknown());