@abloatai/ablo 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -3
- package/CHANGELOG.md +34 -0
- package/README.md +104 -88
- package/dist/BaseSyncedStore.d.ts +140 -266
- package/dist/BaseSyncedStore.js +338 -739
- package/dist/Database.d.ts +62 -77
- package/dist/Database.js +106 -127
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +16 -15
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +52 -69
- package/dist/ModelRegistry.d.ts +46 -25
- package/dist/ModelRegistry.js +32 -30
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +6 -7
- package/dist/SyncClient.d.ts +119 -109
- package/dist/SyncClient.js +303 -224
- package/dist/SyncEngineContext.d.ts +1 -3
- package/dist/SyncEngineContext.js +1 -2
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +39 -31
- package/dist/agent/Agent.js +35 -23
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +30 -31
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +7 -8
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/credentialPolicy.d.ts +74 -71
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +7 -18
- package/dist/auth/credentialSource.js +10 -18
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +34 -40
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +483 -369
- package/dist/client/Ablo.d.ts +107 -836
- package/dist/client/Ablo.js +174 -833
- package/dist/client/ApiClient.d.ts +44 -20
- package/dist/client/ApiClient.js +193 -44
- package/dist/client/auth.d.ts +51 -60
- package/dist/client/auth.js +137 -110
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +35 -0
- package/dist/client/consoleLogger.js +44 -0
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +158 -124
- package/dist/client/credentialEndpoint.d.ts +61 -0
- package/dist/client/credentialEndpoint.js +86 -0
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +21 -0
- package/dist/client/hostedEndpoints.js +21 -0
- package/dist/client/httpClient.d.ts +58 -54
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +49 -59
- package/dist/client/modelRegistration.d.ts +10 -0
- package/dist/client/modelRegistration.js +301 -0
- package/dist/client/options.d.ts +373 -0
- package/dist/client/options.js +6 -0
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +333 -0
- package/dist/client/resourceTypes.js +7 -0
- package/dist/client/schemaConfig.d.ts +44 -0
- package/dist/client/schemaConfig.js +176 -0
- package/dist/client/sessionMint.d.ts +17 -13
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +9 -10
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +28 -0
- package/dist/client/wsMutationExecutor.js +71 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -7
- package/dist/coordination/index.d.ts +13 -4
- package/dist/coordination/index.js +29 -4
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -11
- package/dist/coordination/trace.js +13 -15
- package/dist/core/DatabaseManager.d.ts +5 -8
- package/dist/core/DatabaseManager.js +38 -40
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +27 -34
- package/dist/core/QueryView.d.ts +17 -5
- package/dist/core/QueryView.js +6 -7
- package/dist/core/StoreManager.d.ts +14 -16
- package/dist/core/StoreManager.js +26 -25
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +18 -13
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +57 -54
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +145 -0
- package/dist/core/storeContract.js +12 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +118 -101
- package/dist/errorCodes.js +277 -260
- package/dist/errors.d.ts +170 -165
- package/dist/errors.js +161 -151
- package/dist/index.d.ts +30 -27
- package/dist/index.js +90 -82
- package/dist/interfaces/index.d.ts +108 -133
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +59 -49
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +149 -155
- package/dist/mutators/defineMutators.d.ts +24 -37
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +105 -101
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +32 -16
- package/dist/query/client.js +103 -72
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +7 -11
- package/dist/react/AbloProvider.js +24 -17
- package/dist/react/context.d.ts +27 -146
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +17 -15
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +11 -12
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +9 -9
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +10 -4
- package/dist/react/useReactive.js +2 -3
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +3 -3
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +35 -0
- package/dist/schema/ddlLock.js +46 -0
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +36 -49
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +29 -21
- package/dist/schema/model.d.ts +121 -146
- package/dist/schema/model.js +24 -35
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +7 -1
- package/dist/schema/queries.d.ts +30 -32
- package/dist/schema/queries.js +24 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +38 -0
- package/dist/schema/residency.js +30 -0
- package/dist/schema/roles.d.ts +45 -27
- package/dist/schema/roles.js +52 -21
- package/dist/schema/schema.d.ts +36 -45
- package/dist/schema/schema.js +42 -39
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +36 -39
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +27 -50
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +31 -26
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +34 -28
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +28 -26
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +10 -9
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +27 -29
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +27 -19
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +30 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +94 -0
- package/dist/source/factory.js +268 -0
- package/dist/source/index.d.ts +10 -462
- package/dist/source/index.js +17 -421
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +10 -11
- package/dist/source/next.js +7 -8
- package/dist/source/pushQueue.d.ts +70 -48
- package/dist/source/pushQueue.js +36 -29
- package/dist/source/signing.d.ts +88 -0
- package/dist/source/signing.js +159 -0
- package/dist/source/types.d.ts +351 -0
- package/dist/source/types.js +43 -0
- package/dist/stores/ObjectStore.d.ts +11 -12
- package/dist/stores/ObjectStore.js +34 -35
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +8 -12
- package/dist/stores/SyncActionStore.js +77 -46
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +28 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
- package/dist/sync/ConnectionManager.d.ts +47 -50
- package/dist/sync/ConnectionManager.js +74 -70
- package/dist/sync/NetworkProbe.d.ts +27 -31
- package/dist/sync/NetworkProbe.js +67 -72
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
- package/dist/sync/SyncWebSocket.d.ts +175 -250
- package/dist/sync/SyncWebSocket.js +431 -769
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +38 -30
- package/dist/sync/bootstrapApply.d.ts +70 -0
- package/dist/sync/bootstrapApply.js +73 -0
- package/dist/sync/commitFrames.d.ts +44 -0
- package/dist/sync/commitFrames.js +94 -0
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +108 -25
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +13 -17
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +175 -0
- package/dist/sync/credentialLifecycle.js +322 -0
- package/dist/sync/deltaPipeline.d.ts +113 -0
- package/dist/sync/deltaPipeline.js +261 -0
- package/dist/sync/groupChange.d.ts +113 -0
- package/dist/sync/groupChange.js +242 -0
- package/dist/sync/heartbeat.d.ts +63 -0
- package/dist/sync/heartbeat.js +91 -0
- package/dist/sync/participants.d.ts +27 -27
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +40 -0
- package/dist/sync/syncCursor.js +55 -0
- package/dist/sync/syncPlan.d.ts +54 -0
- package/dist/sync/syncPlan.js +50 -0
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +116 -0
- package/dist/sync/wsFrameHandlers.js +374 -0
- package/dist/testing/fixtures/bootstrap.d.ts +21 -17
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +31 -34
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +12 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -18
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +3 -3
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +21 -34
- package/dist/testing/mocks/MockSyncContext.js +16 -45
- package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +190 -221
- package/dist/transactions/TransactionQueue.js +424 -822
- package/dist/transactions/TransactionStore.d.ts +20 -0
- package/dist/transactions/TransactionStore.js +53 -0
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +58 -0
- package/dist/transactions/coalesceRules.js +140 -0
- package/dist/transactions/commitPayload.d.ts +130 -0
- package/dist/transactions/commitPayload.js +143 -0
- package/dist/transactions/deltaConfirmation.d.ts +58 -0
- package/dist/transactions/deltaConfirmation.js +215 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +99 -0
- package/dist/transactions/replayValidation.js +111 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +74 -80
- package/dist/types/index.js +22 -27
- package/dist/types/modelData.d.ts +10 -0
- package/dist/types/modelData.js +9 -0
- package/dist/types/participant.d.ts +20 -0
- package/dist/types/participant.js +10 -0
- package/dist/types/streams.d.ts +216 -209
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +44 -100
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +35 -27
- package/dist/wire/errorEnvelope.js +38 -32
- package/dist/wire/frames.d.ts +150 -67
- package/dist/wire/frames.js +48 -1
- package/dist/wire/index.d.ts +18 -13
- package/dist/wire/index.js +36 -13
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +38 -0
- package/dist/wire/protocol.js +38 -0
- package/dist/wire/protocolVersion.d.ts +60 -0
- package/dist/wire/protocolVersion.js +67 -0
- package/docs/api-keys.md +4 -3
- package/docs/coordination.md +59 -0
- package/docs/examples/existing-python-backend.md +3 -3
- package/docs/identity.md +4 -4
- package/docs/integration-guide.md +1 -1
- package/docs/react.md +1 -1
- package/docs/sessions.md +5 -7
- package/package.json +24 -21
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/client/index.d.ts +0 -36
- package/dist/client/index.js +0 -33
- package/dist/config/index.d.ts +0 -10
- package/dist/config/index.js +0 -12
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/interfaces/headless.d.ts +0 -95
- package/dist/interfaces/headless.js +0 -41
- package/dist/query/index.d.ts +0 -6
- package/dist/query/index.js +0 -5
- package/dist/realtime/index.d.ts +0 -10
- package/dist/realtime/index.js +0 -9
- package/dist/schema/plane.d.ts +0 -23
- package/dist/schema/plane.js +0 -19
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/next.d.ts +0 -51
- package/dist/server/next.js +0 -47
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -1
- package/dist/server/storage-mode.js +0 -18
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/sync/OfflineFlush.d.ts +0 -9
- package/dist/sync/OfflineFlush.js +0 -22
- package/dist/sync/OfflineTransactionStore.d.ts +0 -37
- package/dist/sync/OfflineTransactionStore.js +0 -263
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/index.d.ts +0 -16
- package/dist/transactions/index.js +0 -7
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sync protocol version — a single integer, increasing over time, that
|
|
3
|
+
* covers everything the client and server must agree on to talk to each other:
|
|
4
|
+
* the WebSocket frame shapes, the HTTP request and response envelopes, and the
|
|
5
|
+
* delta encodings a client replays. It is separate from the app-schema hash
|
|
6
|
+
* (WebSocket close code 4009), which detects drift in your data model; this
|
|
7
|
+
* detects drift in the protocol itself.
|
|
8
|
+
*
|
|
9
|
+
* Deploy ordering: the server is deployed first. It accepts every version in
|
|
10
|
+
* the inclusive range from {@link MIN_SUPPORTED_PROTOCOL_VERSION} to
|
|
11
|
+
* {@link PROTOCOL_VERSION}, and a client is never expected to connect to a
|
|
12
|
+
* server older than itself. If that does happen — for example a partial server
|
|
13
|
+
* rollback — {@link protocolVersionProblem} reports it as `too_new` so the
|
|
14
|
+
* mismatch is visible rather than undefined.
|
|
15
|
+
*
|
|
16
|
+
* To change the protocol:
|
|
17
|
+
* 1. Make the change backward-tolerant where you can. The server ignores
|
|
18
|
+
* unknown payload keys, so an additive field usually needs no version bump.
|
|
19
|
+
* 2. For a breaking change, bump {@link PROTOCOL_VERSION}, add a changelog
|
|
20
|
+
* entry below, and keep {@link MIN_SUPPORTED_PROTOCOL_VERSION} low enough
|
|
21
|
+
* to cover every client still in use; raise it only after a deprecation
|
|
22
|
+
* window.
|
|
23
|
+
* 3. The protocol-version contract test fails on any bump — update it in the
|
|
24
|
+
* same change, deliberately.
|
|
25
|
+
*
|
|
26
|
+
* Changelog
|
|
27
|
+
* v1 (2026-07-03) — the protocol as of this field's introduction: the
|
|
28
|
+
* sync-request frame (`cursor`, `lastSyncId`, `capabilities`, optional
|
|
29
|
+
* `protocolVersion`), the commit, mutation, claim, release, ack, and
|
|
30
|
+
* presence-update frames, the bootstrap and delta batches, and the HTTP
|
|
31
|
+
* error and list envelopes. A client that predates this field sends no
|
|
32
|
+
* `protocolVersion` and is treated as v1, since introducing the field
|
|
33
|
+
* changed no behavior.
|
|
34
|
+
*/
|
|
35
|
+
export declare const PROTOCOL_VERSION = 1;
|
|
36
|
+
/**
|
|
37
|
+
* The oldest client protocol version this build still serves. Raising it cuts
|
|
38
|
+
* off clients that have not upgraded, so do it only after a deprecation window
|
|
39
|
+
* and with a changelog entry.
|
|
40
|
+
*/
|
|
41
|
+
export declare const MIN_SUPPORTED_PROTOCOL_VERSION = 1;
|
|
42
|
+
/**
|
|
43
|
+
* The WebSocket close code the server sends to reject a protocol-version
|
|
44
|
+
* mismatch. It sits alongside the other application close codes (4001 for a
|
|
45
|
+
* credential problem, 4009 for app-schema drift), and its reason string is the
|
|
46
|
+
* error code `protocol_version_unsupported`. A client should treat this close
|
|
47
|
+
* as terminal: reconnecting cannot heal a version mismatch, but upgrading the
|
|
48
|
+
* client or rolling the server forward can.
|
|
49
|
+
*/
|
|
50
|
+
export declare const WS_CLOSE_PROTOCOL_VERSION = 4010;
|
|
51
|
+
/**
|
|
52
|
+
* Classifies a peer's announced protocol version against what this build
|
|
53
|
+
* supports, returning `'too_old'`, `'too_new'`, or `null` when the versions are
|
|
54
|
+
* compatible. An `undefined` version — a client from before versioning existed
|
|
55
|
+
* — counts as v1. A non-integer value is treated as `'too_old'` so the check
|
|
56
|
+
* fails closed and visibly.
|
|
57
|
+
*/
|
|
58
|
+
export declare function protocolVersionProblem(announced: number | undefined): 'too_old' | 'too_new' | null;
|
|
59
|
+
/** The HTTP request header a client uses to announce its protocol version. */
|
|
60
|
+
export declare const PROTOCOL_VERSION_HEADER = "Ablo-Protocol-Version";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sync protocol version — a single integer, increasing over time, that
|
|
3
|
+
* covers everything the client and server must agree on to talk to each other:
|
|
4
|
+
* the WebSocket frame shapes, the HTTP request and response envelopes, and the
|
|
5
|
+
* delta encodings a client replays. It is separate from the app-schema hash
|
|
6
|
+
* (WebSocket close code 4009), which detects drift in your data model; this
|
|
7
|
+
* detects drift in the protocol itself.
|
|
8
|
+
*
|
|
9
|
+
* Deploy ordering: the server is deployed first. It accepts every version in
|
|
10
|
+
* the inclusive range from {@link MIN_SUPPORTED_PROTOCOL_VERSION} to
|
|
11
|
+
* {@link PROTOCOL_VERSION}, and a client is never expected to connect to a
|
|
12
|
+
* server older than itself. If that does happen — for example a partial server
|
|
13
|
+
* rollback — {@link protocolVersionProblem} reports it as `too_new` so the
|
|
14
|
+
* mismatch is visible rather than undefined.
|
|
15
|
+
*
|
|
16
|
+
* To change the protocol:
|
|
17
|
+
* 1. Make the change backward-tolerant where you can. The server ignores
|
|
18
|
+
* unknown payload keys, so an additive field usually needs no version bump.
|
|
19
|
+
* 2. For a breaking change, bump {@link PROTOCOL_VERSION}, add a changelog
|
|
20
|
+
* entry below, and keep {@link MIN_SUPPORTED_PROTOCOL_VERSION} low enough
|
|
21
|
+
* to cover every client still in use; raise it only after a deprecation
|
|
22
|
+
* window.
|
|
23
|
+
* 3. The protocol-version contract test fails on any bump — update it in the
|
|
24
|
+
* same change, deliberately.
|
|
25
|
+
*
|
|
26
|
+
* Changelog
|
|
27
|
+
* v1 (2026-07-03) — the protocol as of this field's introduction: the
|
|
28
|
+
* sync-request frame (`cursor`, `lastSyncId`, `capabilities`, optional
|
|
29
|
+
* `protocolVersion`), the commit, mutation, claim, release, ack, and
|
|
30
|
+
* presence-update frames, the bootstrap and delta batches, and the HTTP
|
|
31
|
+
* error and list envelopes. A client that predates this field sends no
|
|
32
|
+
* `protocolVersion` and is treated as v1, since introducing the field
|
|
33
|
+
* changed no behavior.
|
|
34
|
+
*/
|
|
35
|
+
export const PROTOCOL_VERSION = 1;
|
|
36
|
+
/**
|
|
37
|
+
* The oldest client protocol version this build still serves. Raising it cuts
|
|
38
|
+
* off clients that have not upgraded, so do it only after a deprecation window
|
|
39
|
+
* and with a changelog entry.
|
|
40
|
+
*/
|
|
41
|
+
export const MIN_SUPPORTED_PROTOCOL_VERSION = 1;
|
|
42
|
+
/**
|
|
43
|
+
* The WebSocket close code the server sends to reject a protocol-version
|
|
44
|
+
* mismatch. It sits alongside the other application close codes (4001 for a
|
|
45
|
+
* credential problem, 4009 for app-schema drift), and its reason string is the
|
|
46
|
+
* error code `protocol_version_unsupported`. A client should treat this close
|
|
47
|
+
* as terminal: reconnecting cannot heal a version mismatch, but upgrading the
|
|
48
|
+
* client or rolling the server forward can.
|
|
49
|
+
*/
|
|
50
|
+
export const WS_CLOSE_PROTOCOL_VERSION = 4010;
|
|
51
|
+
/**
|
|
52
|
+
* Classifies a peer's announced protocol version against what this build
|
|
53
|
+
* supports, returning `'too_old'`, `'too_new'`, or `null` when the versions are
|
|
54
|
+
* compatible. An `undefined` version — a client from before versioning existed
|
|
55
|
+
* — counts as v1. A non-integer value is treated as `'too_old'` so the check
|
|
56
|
+
* fails closed and visibly.
|
|
57
|
+
*/
|
|
58
|
+
export function protocolVersionProblem(announced) {
|
|
59
|
+
const v = announced ?? 1;
|
|
60
|
+
if (!Number.isInteger(v) || v < MIN_SUPPORTED_PROTOCOL_VERSION)
|
|
61
|
+
return 'too_old';
|
|
62
|
+
if (v > PROTOCOL_VERSION)
|
|
63
|
+
return 'too_new';
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/** The HTTP request header a client uses to announce its protocol version. */
|
|
67
|
+
export const PROTOCOL_VERSION_HEADER = 'Ablo-Protocol-Version';
|
package/docs/api-keys.md
CHANGED
|
@@ -21,7 +21,7 @@ Pick your row:
|
|
|
21
21
|
|---|---|---|
|
|
22
22
|
| **Server / worker / CLI** (can hold a secret) | your secret `sk_` — it defaults to `ABLO_API_KEY`, so usually pass **nothing** | `Ablo({ schema })` |
|
|
23
23
|
| **Browser — read-only** | a publishable `pk_` (safe to ship, like a Stripe `pk_`) | `Ablo({ schema, apiKey: process.env.NEXT_PUBLIC_ABLO_PUBLISHABLE_KEY })` |
|
|
24
|
-
| **Browser — writing as the signed-in user** |
|
|
24
|
+
| **Browser — writing as the signed-in user** | `authEndpoint` — the route on your own backend that mints a short-lived per-user token | `Ablo({ schema, authEndpoint: '/api/ablo-session' })` |
|
|
25
25
|
|
|
26
26
|
That's the whole story: one knob, filled by audience.
|
|
27
27
|
|
|
@@ -48,8 +48,9 @@ session model. For a read-only app you don't need any of this — just the `pk_`
|
|
|
48
48
|
|
|
49
49
|
Server-side, because `apiKey` defaults to `process.env.ABLO_API_KEY`, most backend and agent
|
|
50
50
|
code passes nothing. The secret `sk_` (and `databaseUrl`) are **server-only** — never in a
|
|
51
|
-
browser bundle. There is no `getToken
|
|
52
|
-
|
|
51
|
+
browser bundle. There is no `getToken` or `as` option — `apiKey` (the key a server holds)
|
|
52
|
+
and `authEndpoint` (the mint route a browser points at) are the two credential
|
|
53
|
+
knobs, and you set exactly one.
|
|
53
54
|
|
|
54
55
|
### Minting per-user / agent tokens (server-side, with your `sk_`)
|
|
55
56
|
|
package/docs/coordination.md
CHANGED
|
@@ -416,6 +416,65 @@ try {
|
|
|
416
416
|
}
|
|
417
417
|
```
|
|
418
418
|
|
|
419
|
+
### `heartbeat` — holding a claim for long-running work
|
|
420
|
+
|
|
421
|
+
```ts
|
|
422
|
+
held.heartbeat(ttl?: Duration): Promise<{ expiresAt: number }>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
A claim's TTL is crash cleanup, not a work-duration estimate — so a task that
|
|
426
|
+
outlives it (an agent run, a background worker's job) keeps its lease by
|
|
427
|
+
**beating**, the same pattern as an SQS visibility heartbeat or a Temporal
|
|
428
|
+
activity heartbeat. Each beat extends the lease from now (never shortens it,
|
|
429
|
+
and each extension is clamped server-side); a crashed worker stops beating and
|
|
430
|
+
its lease lapses within one beat window, promoting the next waiter.
|
|
431
|
+
|
|
432
|
+
Usually **implicit** — pass `heartbeat` when claiming and the SDK beats every
|
|
433
|
+
third of the TTL until release:
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
await using claim = await ablo.reports.claim({
|
|
437
|
+
id: 'report_q3',
|
|
438
|
+
reason: 'generating',
|
|
439
|
+
ttl: '5m',
|
|
440
|
+
heartbeat: true, // or an explicit cadence: heartbeat: '2m'
|
|
441
|
+
onHeartbeatLost: () => abortWork(),
|
|
442
|
+
});
|
|
443
|
+
await runLongGeneration(claim.data); // lease held for the duration
|
|
444
|
+
// scope exit releases; the loop stops with it
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
A beat that comes back with a definitive loss — the lease expired and the
|
|
448
|
+
queue moved on — rejects with `AbloClaimedError` (`claim_lost`) and stops the
|
|
449
|
+
auto-loop. For a worker with no socket, **the failed beat is the loss
|
|
450
|
+
notification**; abandon or re-claim, and remember any write attempted under
|
|
451
|
+
the old lease is independently rejected by its `readAt` guard. Transient
|
|
452
|
+
failures (a connection blip) don't stop the loop — the next tick retries.
|
|
453
|
+
|
|
454
|
+
Each beat's answer carries two more things:
|
|
455
|
+
|
|
456
|
+
- **`queueDepth`** — how many participants wait in line behind the lease.
|
|
457
|
+
This is the cooperative-yield pressure signal: a worker that can checkpoint
|
|
458
|
+
may release early when others wait. Read it from the resolved beat, or pass
|
|
459
|
+
`onHeartbeat` when claiming to observe every auto-beat.
|
|
460
|
+
- **progress `details`** — `held.heartbeat({ details: { pages: 42, of: 100 } })`
|
|
461
|
+
stores the payload as the claim's peer-visible `meta.progress` (last beat
|
|
462
|
+
wins, via `claim.state`). This is presence, not a checkpoint: it dies with
|
|
463
|
+
the lease. Durable progress belongs in the data itself — write a row, and
|
|
464
|
+
every subscriber already sees it.
|
|
465
|
+
|
|
466
|
+
Works identically on both transports: the realtime client sends a
|
|
467
|
+
`claim_heartbeat` frame; the HTTP client posts
|
|
468
|
+
`POST /v1/models/{model}/{id}/claim/heartbeat` (`{ ttl?, claimId?, details? }`).
|
|
469
|
+
Over HTTP, a **queued** claim can heartbeat too — it refreshes the waiter's
|
|
470
|
+
slot in the line (a queued slot is TTL'd like a lease) and reports
|
|
471
|
+
`{ status: 'queued', position }`.
|
|
472
|
+
|
|
473
|
+
A stateless worker holding **many** rows beats them all in one round trip:
|
|
474
|
+
`ablo.claims.heartbeatAll({ ttl: '5m' })` → `POST /v1/claims/heartbeat`, one
|
|
475
|
+
entry per extended lease. This is the socketless twin of the realtime
|
|
476
|
+
keepalive, which already renews every held lease on each ping.
|
|
477
|
+
|
|
419
478
|
### `watch` — presence for a set of rows
|
|
420
479
|
|
|
421
480
|
Reading or claiming a row auto-enrolls you in its sync group, which is enough for
|
|
@@ -67,11 +67,11 @@ import Ablo from '@abloatai/ablo';
|
|
|
67
67
|
import { AbloProvider } from '@abloatai/ablo/react';
|
|
68
68
|
import { schema } from '@/ablo/schema';
|
|
69
69
|
|
|
70
|
-
// Browser client: no secret key —
|
|
71
|
-
//
|
|
70
|
+
// Browser client: no secret key — `authEndpoint` points at the session route
|
|
71
|
+
// your server exposes (below); the SDK fetches and refreshes the token.
|
|
72
72
|
const ablo = Ablo({
|
|
73
73
|
schema,
|
|
74
|
-
|
|
74
|
+
authEndpoint: '/api/ablo-session',
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
export function Providers({ children }: { children: React.ReactNode }) {
|
package/docs/identity.md
CHANGED
|
@@ -359,10 +359,10 @@ import { schema } from '@/ablo/schema';
|
|
|
359
359
|
export function makeAblo(user: { teamIds: string[] }) {
|
|
360
360
|
return Ablo({
|
|
361
361
|
schema,
|
|
362
|
-
// The browser holds no secret —
|
|
363
|
-
// short-lived session token
|
|
364
|
-
//
|
|
365
|
-
|
|
362
|
+
// The browser holds no secret — `authEndpoint` points at the route that
|
|
363
|
+
// mints the short-lived session token, and the client keeps it fresh
|
|
364
|
+
// before expiry.
|
|
365
|
+
authEndpoint: '/api/ablo-session',
|
|
366
366
|
teamIds: user.teamIds,
|
|
367
367
|
});
|
|
368
368
|
}
|
|
@@ -190,7 +190,7 @@ import { schema } from '@/ablo/schema';
|
|
|
190
190
|
// from your session route (see below) and refreshes it before expiry.
|
|
191
191
|
export const ablo = Ablo({
|
|
192
192
|
schema,
|
|
193
|
-
|
|
193
|
+
authEndpoint: '/api/ablo-session',
|
|
194
194
|
});
|
|
195
195
|
```
|
|
196
196
|
|
package/docs/react.md
CHANGED
package/docs/sessions.md
CHANGED
|
@@ -53,7 +53,7 @@ return Response.json({ token }); // return ONLY the token to the browser
|
|
|
53
53
|
A user session has **full data authority** within its org — no operation
|
|
54
54
|
allowlist. It's the human acting as themselves.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
Point a browser `Ablo` client's `authEndpoint` at that route, and pass
|
|
57
57
|
the **instance** to [`<AbloProvider>`](/react). The client fetches the token,
|
|
58
58
|
opens the connection, and re-mints before expiry — your app writes no token
|
|
59
59
|
plumbing:
|
|
@@ -67,10 +67,7 @@ import { schema } from '@/ablo.schema';
|
|
|
67
67
|
|
|
68
68
|
const ablo = Ablo({
|
|
69
69
|
schema,
|
|
70
|
-
|
|
71
|
-
fetch('/api/ablo-session', { method: 'POST' })
|
|
72
|
-
.then((r) => r.json())
|
|
73
|
-
.then((d) => d.token),
|
|
70
|
+
authEndpoint: '/api/ablo-session',
|
|
74
71
|
});
|
|
75
72
|
|
|
76
73
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
@@ -81,8 +78,9 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
81
78
|
The client owns auth, the credential lifecycle, and the connection; the provider
|
|
82
79
|
is the thin reactive binding over it (Stripe's `<Elements stripe={...}>` model).
|
|
83
80
|
Build the client **once** at module scope — a new instance per render tears down
|
|
84
|
-
the socket.
|
|
85
|
-
`
|
|
81
|
+
the socket. Need custom headers or a
|
|
82
|
+
body on the exchange? `authEndpoint` also accepts an async resolver that
|
|
83
|
+
returns the token.
|
|
86
84
|
|
|
87
85
|
## Agent sessions (`rk_`)
|
|
88
86
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/ablo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "The Collaboration Layer For AI Agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -108,11 +108,6 @@
|
|
|
108
108
|
"import": "./dist/server/index.js",
|
|
109
109
|
"default": "./dist/server/index.js"
|
|
110
110
|
},
|
|
111
|
-
"./server/next": {
|
|
112
|
-
"types": "./dist/server/next.d.ts",
|
|
113
|
-
"import": "./dist/server/next.js",
|
|
114
|
-
"default": "./dist/server/next.js"
|
|
115
|
-
},
|
|
116
111
|
"./webhooks": {
|
|
117
112
|
"types": "./dist/webhooks/index.d.ts",
|
|
118
113
|
"import": "./dist/webhooks/index.js",
|
|
@@ -121,7 +116,6 @@
|
|
|
121
116
|
},
|
|
122
117
|
"files": [
|
|
123
118
|
"dist",
|
|
124
|
-
"!dist/internal/**",
|
|
125
119
|
"!dist/__type_probe.*",
|
|
126
120
|
"docs/*.md",
|
|
127
121
|
"docs/examples/*.md",
|
|
@@ -139,7 +133,9 @@
|
|
|
139
133
|
"build": "npm run clean && tsc -p tsconfig.build.json && npm run build:cli",
|
|
140
134
|
"build:cli": "tsup --config tsup.cli.config.ts",
|
|
141
135
|
"typecheck:cli": "tsc -p tsconfig.cli.json",
|
|
142
|
-
"
|
|
136
|
+
"prepack": "node scripts/strip-source-condition.mjs",
|
|
137
|
+
"postpack": "node scripts/restore-source-condition.mjs",
|
|
138
|
+
"pack:check": "node scripts/pack-check.mjs",
|
|
143
139
|
"lint": "npm run lint:imports && npm run lint:errors && npm run lint:docs && npm run lint:mintlify",
|
|
144
140
|
"build:docs": "node scripts/build-mintlify-docs.mjs",
|
|
145
141
|
"lint:mintlify": "node scripts/build-mintlify-docs.mjs --check",
|
|
@@ -147,16 +143,17 @@
|
|
|
147
143
|
"generate:errors": "tsx scripts/generate-error-docs.mts",
|
|
148
144
|
"lint:errors": "tsx scripts/check-error-docs.mts",
|
|
149
145
|
"lint:docs": "node scripts/check-doc-drift.mjs",
|
|
146
|
+
"lint:eslint": "eslint . --cache",
|
|
150
147
|
"lint:pkg": "publint",
|
|
151
148
|
"prepublishOnly": "npm run build && npm run lint:pkg",
|
|
152
149
|
"check:dist": "node scripts/check-dist-fresh.mjs",
|
|
153
150
|
"pretest": "node scripts/check-dist-fresh.mjs",
|
|
154
151
|
"test": "jest",
|
|
155
152
|
"test:quickstart": "node scripts/test-quickstart.mjs",
|
|
156
|
-
"test:unit": "jest --
|
|
157
|
-
"test:integration": "jest --
|
|
158
|
-
"test:contract": "jest --
|
|
159
|
-
"test:property": "jest --
|
|
153
|
+
"test:unit": "jest --testPathPatterns __tests__/unit",
|
|
154
|
+
"test:integration": "jest --testPathPatterns __tests__/integration",
|
|
155
|
+
"test:contract": "jest --testPathPatterns __tests__/contract",
|
|
156
|
+
"test:property": "jest --testPathPatterns __tests__/property",
|
|
160
157
|
"test:coverage": "jest --coverage",
|
|
161
158
|
"test:e2e": "E2E_TEST=true jest --config jest.e2e.config.ts",
|
|
162
159
|
"test:e2e:up": "docker compose -f docker-compose.test.yml up -d --wait",
|
|
@@ -191,7 +188,8 @@
|
|
|
191
188
|
},
|
|
192
189
|
"peerDependencies": {
|
|
193
190
|
"react": "^19.0.0",
|
|
194
|
-
"drizzle-orm": ">=0.44.0"
|
|
191
|
+
"drizzle-orm": ">=0.44.0",
|
|
192
|
+
"ai": "^6.0.0"
|
|
195
193
|
},
|
|
196
194
|
"peerDependenciesMeta": {
|
|
197
195
|
"react": {
|
|
@@ -199,6 +197,9 @@
|
|
|
199
197
|
},
|
|
200
198
|
"drizzle-orm": {
|
|
201
199
|
"optional": true
|
|
200
|
+
},
|
|
201
|
+
"ai": {
|
|
202
|
+
"optional": true
|
|
202
203
|
}
|
|
203
204
|
},
|
|
204
205
|
"dependencies": {
|
|
@@ -211,30 +212,32 @@
|
|
|
211
212
|
"devDependencies": {
|
|
212
213
|
"@ai-sdk/provider": "^3.0.0",
|
|
213
214
|
"@clack/prompts": "^0.11.0",
|
|
215
|
+
"@jest/globals": "^30.2.0",
|
|
214
216
|
"@prisma/client": "^7.3.0",
|
|
215
|
-
"@types/jest": "^
|
|
217
|
+
"@types/jest": "^30.0.0",
|
|
216
218
|
"@types/node": "^22.0.0",
|
|
217
219
|
"@types/react": "^19.0.0",
|
|
218
220
|
"@types/uuid": "^10.0.0",
|
|
219
221
|
"@testing-library/react": "^16.0.0",
|
|
220
|
-
"@testing-library/jest-dom": "^6.6.0",
|
|
221
222
|
"ai": "^6.0.0",
|
|
222
223
|
"drizzle-orm": "^0.45.2",
|
|
224
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
223
225
|
"fake-indexeddb": "^6.0.0",
|
|
224
226
|
"fast-check": "^3.0.0",
|
|
225
|
-
"
|
|
226
|
-
"jest
|
|
227
|
-
"
|
|
228
|
-
"
|
|
227
|
+
"globals": "^16.5.0",
|
|
228
|
+
"jest": "^30.2.0",
|
|
229
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
230
|
+
"jest-environment-node": "^30.2.0",
|
|
229
231
|
"picocolors": "^1.1.0",
|
|
230
232
|
"postgres": "^3.4.0",
|
|
231
233
|
"react": "^19.0.0",
|
|
232
234
|
"react-dom": "^19.0.0",
|
|
233
|
-
"ts-jest": "^29.4.
|
|
235
|
+
"ts-jest": "^29.4.5",
|
|
234
236
|
"ts-morph": "^26.0.0",
|
|
235
237
|
"tsup": "^8.0.0",
|
|
238
|
+
"tsx": "^4.19.0",
|
|
236
239
|
"typescript": "^5.8.3",
|
|
237
240
|
"publint": "^0.3.21",
|
|
238
|
-
"
|
|
241
|
+
"ws": "^8.18.0"
|
|
239
242
|
}
|
|
240
243
|
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `coordinatedTool` — the one-liner that turns an Ablo model write into a Vercel
|
|
3
|
-
* AI SDK tool with multi-agent coordination already handled, so an AI agent can
|
|
4
|
-
* contribute to shared state without ever silently clobbering a concurrent
|
|
5
|
-
* writer.
|
|
6
|
-
*
|
|
7
|
-
* The base `./ai-sdk` pattern (see index.ts) is "write your own `tool()` and
|
|
8
|
-
* call `ablo.<model>.update({ id, data, claim })` inside `execute`". That's the
|
|
9
|
-
* right amount of control when a tool does something bespoke. But the *common*
|
|
10
|
-
* case — "the agent produced some content; save it into the shared row" — should
|
|
11
|
-
* not require every integration to re-derive optimistic concurrency by hand. This
|
|
12
|
-
* collapses it to a declaration:
|
|
13
|
-
*
|
|
14
|
-
* ```ts
|
|
15
|
-
* import { coordinatedTool } from '@abloatai/ablo/ai-sdk';
|
|
16
|
-
* import { z } from 'zod';
|
|
17
|
-
*
|
|
18
|
-
* const saveSection = coordinatedTool(ablo.documents, {
|
|
19
|
-
* description: 'Save your section into the shared document.',
|
|
20
|
-
* inputSchema: z.object({ text: z.string() }),
|
|
21
|
-
* id: () => DOC_ID,
|
|
22
|
-
* apply: (current, { text }) => ({ content: appendBlock(current.content, text) }),
|
|
23
|
-
* // strategy: 'merge' ← the default
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* await streamText({ model, messages, tools: { saveSection } });
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* `apply` is the whole API: a pure function of `(freshest row, tool input) →
|
|
30
|
-
* patch`, exactly like React's `setState(prev => next)`. Everything underneath —
|
|
31
|
-
* reading the latest row, the compare-and-swap, the jittered backoff between
|
|
32
|
-
* reconcile rounds, releasing claims — is the runtime's job, not yours.
|
|
33
|
-
*
|
|
34
|
-
* ## Strategies (pick by how writers should relate; all verified to converge
|
|
35
|
-
* under N-way agent contention)
|
|
36
|
-
*
|
|
37
|
-
* - `'merge'` *(default)* — delegates straight to the functional update
|
|
38
|
-
* `ablo.<model>.update(id, current => apply(current, input))`. The SDK re-reads
|
|
39
|
-
* and re-applies `apply` on top of every concurrent write and backs off between
|
|
40
|
-
* rounds, so N agents *accumulate* into one row and the model never sees a
|
|
41
|
-
* conflict. **Requires the model's agent conflict policy to be `reject`** (the
|
|
42
|
-
* default, or `agentsReject()`); a model declaring `agentsNotify()` HOLDS the
|
|
43
|
-
* losing write instead of rejecting it, which defeats the reconcile — use
|
|
44
|
-
* `claim`/`queue` there, or switch the policy.
|
|
45
|
-
*
|
|
46
|
-
* - `'claim'` — mutual exclusion. Takes a fail-fast claim; if another participant
|
|
47
|
-
* holds the row it returns `{ status: 'claimed' }` so the *model* decides to
|
|
48
|
-
* retry (a legible signal beats a hidden wait when the agent might do something
|
|
49
|
-
* better with its turn). Works regardless of conflict policy.
|
|
50
|
-
*
|
|
51
|
-
* - `'queue'` — fair-ish serialization over stateless HTTP, the SQS shape: a
|
|
52
|
-
* client poll-acquire loop (true FIFO needs a socket) until the claim is granted
|
|
53
|
-
* or `poll.timeoutMs` elapses. The model calls once and the tool waits its turn.
|
|
54
|
-
*/
|
|
55
|
-
import type { z } from 'zod';
|
|
56
|
-
import type { ModelOperations } from '../client/createModelProxy.js';
|
|
57
|
-
export type CoordinationStrategy = 'merge' | 'claim' | 'queue';
|
|
58
|
-
/** The structured result the tool hands back to the model (or the caller). */
|
|
59
|
-
export interface CoordinatedWriteResult<T> {
|
|
60
|
-
/**
|
|
61
|
-
* `'written'` — saved. `'claimed'` — another participant holds the row; NOT
|
|
62
|
-
* saved, the model should try again. `'timeout'` — the queue strategy could not
|
|
63
|
-
* acquire the row within `poll.timeoutMs`.
|
|
64
|
-
*/
|
|
65
|
-
status: 'written' | 'claimed' | 'timeout';
|
|
66
|
-
/** The reconciled row, on `'written'`. */
|
|
67
|
-
row?: T;
|
|
68
|
-
message?: string;
|
|
69
|
-
/** On `'written'` via the `queue` strategy, how long the tool waited in line. */
|
|
70
|
-
waitedMs?: number;
|
|
71
|
-
}
|
|
72
|
-
export interface CoordinatedToolOptions<TInput, T> {
|
|
73
|
-
/** Tool description shown to the model. */
|
|
74
|
-
description: string;
|
|
75
|
-
/** What the model may send — a normal AI SDK / zod input schema. */
|
|
76
|
-
inputSchema: z.ZodType<TInput>;
|
|
77
|
-
/** Which row this write targets, derived from the tool input. */
|
|
78
|
-
id: (input: TInput) => string;
|
|
79
|
-
/**
|
|
80
|
-
* Produce the write patch from the freshest current row + the tool input — a
|
|
81
|
-
* pure `(prev, input) => next`. Under `merge` it re-runs on every concurrent
|
|
82
|
-
* write, so it must be idempotent w.r.t. its own contribution (e.g. skip if its
|
|
83
|
-
* marker is already present) to be safe across reconcile rounds.
|
|
84
|
-
*/
|
|
85
|
-
apply: (current: T, input: TInput) => Partial<T>;
|
|
86
|
-
/** How concurrent writers relate. Defaults to `'merge'`. */
|
|
87
|
-
strategy?: CoordinationStrategy;
|
|
88
|
-
/** Human-legible coordination metadata attached to the claim (`claim`/`queue`). */
|
|
89
|
-
claim?: {
|
|
90
|
-
reason?: string;
|
|
91
|
-
description?: string;
|
|
92
|
-
};
|
|
93
|
-
/** Reconcile budget for `merge` (rounds before `AbloContentionError`). */
|
|
94
|
-
retries?: number;
|
|
95
|
-
/** Poll cadence / ceiling for `queue` (defaults 250ms / 30s). */
|
|
96
|
-
poll?: {
|
|
97
|
-
intervalMs?: number;
|
|
98
|
-
timeoutMs?: number;
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
export declare function coordinatedTool<TInput, T = Record<string, unknown>, CreateInput = Partial<T>>(model: ModelOperations<T, CreateInput>, options: CoordinatedToolOptions<TInput, T>): import("ai").Tool<TInput, CoordinatedWriteResult<T>>;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Coordination context middleware — reads peer claims on the same
|
|
3
|
-
* entity from the sync engine's presence stream and injects a brief
|
|
4
|
-
* coordination note into the prompt before the LLM call.
|
|
5
|
-
*
|
|
6
|
-
* The complement of `claim-broadcast.ts`: that one declares what
|
|
7
|
-
* THIS agent is about to do; this one reads what OTHERS are doing
|
|
8
|
-
* and tells the LLM about it. Together they make multiplayer-with-
|
|
9
|
-
* AI structurally real — the AI knows when a human or another
|
|
10
|
-
* agent is mid-edit and can defer / phrase its work as
|
|
11
|
-
* "while you finish that, I'll …" / suggest waiting / coordinate
|
|
12
|
-
* explicitly.
|
|
13
|
-
*
|
|
14
|
-
* Open-source-clean: depends only on `@ai-sdk/provider` types and
|
|
15
|
-
* the package's own `SyncAgent`. Consumers compose via the AI
|
|
16
|
-
* SDK's `wrapLanguageModel`.
|
|
17
|
-
*
|
|
18
|
-
* Cost: zero extra LLM calls (read happens locally from the agent's
|
|
19
|
-
* cached presence stream — already in memory from the WS subscription).
|
|
20
|
-
* Adds a few sentences to the system prompt (typically <100 tokens)
|
|
21
|
-
* only when peers are actively editing.
|
|
22
|
-
*/
|
|
23
|
-
import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
24
|
-
import type { Ablo } from '../client/Ablo.js';
|
|
25
|
-
import type { SchemaRecord } from '../schema/schema.js';
|
|
26
|
-
import type { ClaimTarget } from '../types/streams.js';
|
|
27
|
-
export type { ClaimTarget };
|
|
28
|
-
export interface CoordinationContextMiddlewareOptions<R extends SchemaRecord = SchemaRecord> {
|
|
29
|
-
readonly agent: Ablo<R> | null;
|
|
30
|
-
readonly target: ClaimTarget | null;
|
|
31
|
-
/**
|
|
32
|
-
* Optional claimId(s) to exclude from the read — typically this
|
|
33
|
-
* agent's own active claim so the coordination note doesn't tell
|
|
34
|
-
* the AI "you yourself are editing this." When middleware is
|
|
35
|
-
* composed with `claimBroadcastMiddleware` in the standard order,
|
|
36
|
-
* `transformParams` runs BEFORE the broadcast's `wrapStream`
|
|
37
|
-
* declares its claim, so the agent's own claim isn't yet in the
|
|
38
|
-
* cached presence and self-filtering isn't needed. The hook is
|
|
39
|
-
* here for callers that compose differently or for fleet
|
|
40
|
-
* coordination (filter sibling worker claims).
|
|
41
|
-
*/
|
|
42
|
-
readonly excludeClaimIds?: readonly string[];
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Build the middleware. When `agent` or `target` is null, returns a
|
|
46
|
-
* pass-through.
|
|
47
|
-
*
|
|
48
|
-
* Generic over the schema record — see `claimBroadcastMiddleware`
|
|
49
|
-
* for why `Ablo<S>` and `Ablo<SchemaRecord>` aren't structurally
|
|
50
|
-
* assignable.
|
|
51
|
-
*/
|
|
52
|
-
export declare function coordinationContextMiddleware<R extends SchemaRecord = SchemaRecord>(options: CoordinationContextMiddlewareOptions<R>): LanguageModelV3Middleware;
|
package/dist/client/index.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @abloatai/ablo/client — Consumer API
|
|
3
|
-
*
|
|
4
|
-
* The one-liner entry point for external consumers.
|
|
5
|
-
*
|
|
6
|
-
* `Ablo({ apiKey })` is the stateless HTTP API client. Add `schema`
|
|
7
|
-
* when you want the realtime sync engine with typed model proxies.
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* import { Ablo } from '@abloatai/ablo/client';
|
|
11
|
-
* import { schema } from './schema';
|
|
12
|
-
*
|
|
13
|
-
* const ablo = Ablo({
|
|
14
|
-
* schema,
|
|
15
|
-
* apiKey: process.env.ABLO_API_KEY,
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* const reports = ablo.weatherReports.list({ where: { status: 'pending' } });
|
|
19
|
-
* await ablo.weatherReports.create({ location: 'Stockholm', status: 'pending' });
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* For headless agents (workers, bots), pass the same schema and an API key
|
|
23
|
-
* scoped for that server runtime:
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
* const bot = Ablo({
|
|
27
|
-
* schema,
|
|
28
|
-
* apiKey: process.env.ABLO_API_KEY,
|
|
29
|
-
* });
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export { Ablo, computeFKDepthPriority, type AbloOptions, type InternalAbloOptions, type ClaimedOptions, type IfClaimedPolicy, type ClaimWaitOptions, type LocalCountOptions, type LocalReadOptions, type ModelListScope, type ServerReadOptions, type ModelOperations, type ModelReadOptions, } from './Ablo.js';
|
|
33
|
-
export { ABLO_DEFAULT_BASE_URL, ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, normalizeAbloHostedBaseUrl, } from './auth.js';
|
|
34
|
-
export type { AbloPersistence } from './persistence.js';
|
|
35
|
-
export type { AbloApi, AbloApiClientOptions, AbloApiClaims, Capability, CapabilityCreateOptions, CapabilityParticipantKind, CapabilityRecord, CapabilityResource, CapabilityRevocation, CapabilityScope, } from './ApiClient.js';
|
|
36
|
-
export type { EngineParticipant, JoinedParticipant, ParticipantJoinOptions, ParticipantManager, ParticipantScope, ParticipantStatus, ScopedClaims, ScopedPresence, } from '../sync/participants.js';
|
package/dist/client/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @abloatai/ablo/client — Consumer API
|
|
3
|
-
*
|
|
4
|
-
* The one-liner entry point for external consumers.
|
|
5
|
-
*
|
|
6
|
-
* `Ablo({ apiKey })` is the stateless HTTP API client. Add `schema`
|
|
7
|
-
* when you want the realtime sync engine with typed model proxies.
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* import { Ablo } from '@abloatai/ablo/client';
|
|
11
|
-
* import { schema } from './schema';
|
|
12
|
-
*
|
|
13
|
-
* const ablo = Ablo({
|
|
14
|
-
* schema,
|
|
15
|
-
* apiKey: process.env.ABLO_API_KEY,
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* const reports = ablo.weatherReports.list({ where: { status: 'pending' } });
|
|
19
|
-
* await ablo.weatherReports.create({ location: 'Stockholm', status: 'pending' });
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* For headless agents (workers, bots), pass the same schema and an API key
|
|
23
|
-
* scoped for that server runtime:
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
* const bot = Ablo({
|
|
27
|
-
* schema,
|
|
28
|
-
* apiKey: process.env.ABLO_API_KEY,
|
|
29
|
-
* });
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export { Ablo, computeFKDepthPriority, } from './Ablo.js';
|
|
33
|
-
export { ABLO_DEFAULT_BASE_URL, ABLO_HOSTED_API_DOMAIN, ABLO_HOSTED_HTTP_BASE_URL, normalizeAbloHostedBaseUrl, } from './auth.js';
|