@abloatai/ablo 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +758 -5
- package/README.md +56 -502
- package/bin/ablo.cjs +39 -0
- package/dist/BaseSyncedStore.d.ts +176 -48
- package/dist/BaseSyncedStore.js +346 -214
- package/dist/Database.d.ts +17 -44
- package/dist/Database.js +96 -79
- package/dist/InstanceCache.d.ts +31 -6
- package/dist/InstanceCache.js +65 -30
- package/dist/LazyReferenceCollection.d.ts +3 -3
- package/dist/LazyReferenceCollection.js +4 -4
- package/dist/Model.d.ts +23 -13
- package/dist/Model.js +27 -17
- package/dist/ModelRegistry.d.ts +8 -4
- package/dist/ModelRegistry.js +20 -18
- package/dist/NetworkMonitor.d.ts +3 -1
- package/dist/NetworkMonitor.js +7 -5
- package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
- package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
- package/dist/SyncClient.d.ts +47 -47
- package/dist/SyncClient.js +215 -156
- package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
- package/dist/ai-sdk/coordinatedTool.js +1 -1
- package/dist/ai-sdk/coordinationContext.d.ts +2 -2
- package/dist/ai-sdk/coordinationContext.js +1 -1
- package/dist/ai-sdk/wrap.d.ts +3 -3
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/index.d.ts +1 -156
- package/dist/auth/index.js +8 -301
- package/dist/client/Ablo.d.ts +42 -287
- package/dist/client/Ablo.js +129 -963
- package/dist/client/abloClient.d.ts +309 -0
- package/dist/client/abloClient.js +13 -0
- package/dist/client/clientPrelude.d.ts +52 -0
- package/dist/client/clientPrelude.js +60 -0
- package/dist/client/consoleLogger.d.ts +2 -2
- package/dist/client/coreClient.d.ts +60 -0
- package/dist/client/coreClient.js +118 -0
- package/dist/client/createInternalComponents.d.ts +8 -4
- package/dist/client/createInternalComponents.js +17 -10
- package/dist/client/createModelProxy.d.ts +98 -373
- package/dist/client/createModelProxy.js +233 -139
- package/dist/client/humans.d.ts +69 -0
- package/dist/client/humans.js +78 -0
- package/dist/client/modelRegistration.d.ts +1 -1
- package/dist/client/modelRegistration.js +9 -9
- package/dist/client/options.d.ts +73 -17
- package/dist/client/reactiveEngine.d.ts +53 -0
- package/dist/client/reactiveEngine.js +688 -0
- package/dist/client/resourceTypes.d.ts +9 -250
- package/dist/client/resourceTypes.js +8 -5
- package/dist/client/schemaConfig.d.ts +4 -4
- package/dist/client/schemaConfig.js +6 -2
- package/dist/client/storeCluster.d.ts +47 -0
- package/dist/client/storeCluster.js +118 -0
- package/dist/client/storeLifecycle.d.ts +61 -0
- package/dist/client/storeLifecycle.js +231 -0
- package/dist/client/validateAbloOptions.d.ts +3 -2
- package/dist/client/validateAbloOptions.js +1 -1
- package/dist/client/wsMutationExecutor.d.ts +3 -3
- package/dist/client/wsMutationExecutor.js +3 -3
- package/dist/context.d.ts +22 -9
- package/dist/context.js +33 -9
- package/dist/coordination/ClaimLog.d.ts +26 -0
- package/dist/coordination/ClaimLog.js +32 -0
- package/dist/coordination/index.d.ts +1 -15
- package/dist/coordination/index.js +8 -31
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +2 -2
- package/dist/docs/catalog.d.ts +72 -0
- package/dist/docs/catalog.js +230 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +10 -0
- package/dist/environment.d.ts +1 -40
- package/dist/environment.js +8 -37
- package/dist/index.d.ts +44 -36
- package/dist/index.js +30 -22
- package/dist/interfaces/index.d.ts +44 -134
- package/dist/keys/index.d.ts +1 -77
- package/dist/keys/index.js +8 -190
- package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
- package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
- package/dist/mutators/Transaction.d.ts +1 -1
- package/dist/mutators/Transaction.js +1 -1
- package/dist/mutators/UndoManager.d.ts +6 -6
- package/dist/mutators/UndoManager.js +5 -5
- package/dist/mutators/defineMutators.d.ts +3 -3
- package/dist/mutators/defineMutators.js +1 -1
- package/dist/mutators/inverseOp.js +2 -2
- package/dist/mutators/mutateActions.d.ts +3 -3
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +1 -1
- package/dist/mutators/undoApply.d.ts +1 -1
- package/dist/mutators/undoApply.js +1 -1
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +1 -1
- package/dist/query/client.d.ts +5 -2
- package/dist/query/client.js +10 -9
- package/dist/query/types.d.ts +6 -41
- package/dist/query/types.js +2 -2
- package/dist/react/AbloProvider.d.ts +18 -8
- package/dist/react/AbloProvider.js +10 -9
- package/dist/react/context.d.ts +3 -3
- package/dist/react/context.js +1 -1
- package/dist/react/createAbloReact.d.ts +56 -0
- package/dist/react/createAbloReact.js +51 -0
- package/dist/react/index.d.ts +6 -5
- package/dist/react/index.js +6 -3
- package/dist/react/internalContext.d.ts +1 -1
- package/dist/react/useAblo.d.ts +12 -5
- package/dist/react/useAblo.js +26 -8
- package/dist/react/useCurrentUserId.js +1 -1
- package/dist/react/useErrorListener.js +1 -1
- package/dist/react/useMutationFailureListener.d.ts +2 -2
- package/dist/react/useMutationFailureListener.js +1 -1
- package/dist/react/useMutators.d.ts +3 -3
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useUndoScope.d.ts +5 -5
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +69 -10
- package/dist/schema/coordination.js +90 -9
- package/dist/schema/ddl.js +2 -2
- package/dist/schema/diff.d.ts +1 -1
- package/dist/schema/generate.js +1 -1
- package/dist/schema/index.d.ts +11 -10
- package/dist/schema/index.js +22 -18
- package/dist/schema/queries.d.ts +27 -27
- package/dist/schema/queries.js +23 -23
- package/dist/schema/select.d.ts +3 -3
- package/dist/schema/select.js +6 -3
- package/dist/schema/serialize.d.ts +15 -6
- package/dist/schema/serialize.js +20 -3
- package/dist/schema/sugar.d.ts +6 -7
- package/dist/schema/sugar.js +9 -12
- package/dist/schema/syncDeltaRow.d.ts +4 -152
- package/dist/schema/syncDeltaRow.js +4 -105
- package/dist/server/adapter.d.ts +18 -1
- package/dist/server/commit.d.ts +10 -16
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +1 -1
- package/dist/source/adapter.d.ts +7 -5
- package/dist/source/adapter.js +7 -5
- package/dist/source/adapters/drizzle.d.ts +1 -1
- package/dist/source/adapters/drizzle.js +2 -2
- package/dist/source/adapters/kysely.d.ts +1 -1
- package/dist/source/adapters/kysely.js +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +2 -2
- package/dist/source/adapters/memory.js +1 -1
- package/dist/source/adapters/prisma.d.ts +8 -3
- package/dist/source/adapters/prisma.js +1 -1
- package/dist/source/connector.js +1 -1
- package/dist/source/connectorProtocol.d.ts +2 -8
- package/dist/source/connectorProtocol.js +3 -2
- package/dist/source/contract.d.ts +29 -17
- package/dist/source/contract.js +27 -22
- package/dist/source/factory.d.ts +1 -1
- package/dist/source/idempotency.js +2 -2
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.js +3 -0
- package/dist/source/next.d.ts +1 -1
- package/dist/source/signing.d.ts +9 -2
- package/dist/source/signing.js +4 -1
- package/dist/source/types.d.ts +6 -4
- package/dist/source/types.js +1 -1
- package/dist/{core/storeContract.d.ts → storeContract.d.ts} +6 -6
- package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
- package/dist/{core → stores}/DatabaseManager.js +14 -13
- package/dist/stores/ObjectStore.d.ts +1 -1
- package/dist/{core → stores}/StoreManager.d.ts +9 -26
- package/dist/{core → stores}/StoreManager.js +29 -77
- package/dist/stores/SyncActionStore.d.ts +4 -2
- package/dist/stores/SyncActionStore.js +11 -17
- package/dist/stores/syncAction.d.ts +26 -0
- package/dist/stores/syncAction.js +16 -0
- package/dist/surface.d.ts +3 -3
- package/dist/surface.js +6 -4
- package/dist/sync/BootstrapFetcher.d.ts +127 -6
- package/dist/sync/BootstrapFetcher.js +511 -83
- package/dist/sync/ConnectionManager.d.ts +6 -198
- package/dist/sync/ConnectionManager.js +6 -677
- package/dist/sync/OnDemandLoader.d.ts +5 -2
- package/dist/sync/OnDemandLoader.js +61 -21
- package/dist/sync/SubscriptionManager.d.ts +13 -2
- package/dist/sync/SubscriptionManager.js +23 -5
- package/dist/sync/SyncWebSocket.d.ts +27 -510
- package/dist/sync/SyncWebSocket.js +76 -954
- package/dist/sync/awaitClaimGrant.d.ts +4 -44
- package/dist/sync/awaitClaimGrant.js +4 -109
- package/dist/sync/bootstrapApply.d.ts +3 -0
- package/dist/sync/bootstrapApply.js +2 -2
- package/dist/sync/commitFrames.d.ts +6 -40
- package/dist/sync/commitFrames.js +6 -97
- package/dist/sync/contextPorts.d.ts +18 -0
- package/dist/sync/contextPorts.js +31 -0
- package/dist/sync/createClaimStream.d.ts +5 -49
- package/dist/sync/createClaimStream.js +5 -469
- package/dist/sync/createPresenceStream.d.ts +26 -4
- package/dist/sync/createPresenceStream.js +28 -20
- package/dist/sync/createSnapshot.d.ts +2 -2
- package/dist/sync/createSnapshot.js +1 -1
- package/dist/sync/credentialLifecycle.d.ts +5 -173
- package/dist/sync/credentialLifecycle.js +5 -320
- package/dist/sync/deltaPipeline.d.ts +13 -12
- package/dist/sync/deltaPipeline.js +21 -4
- package/dist/sync/groupChange.d.ts +3 -0
- package/dist/sync/groupChange.js +16 -14
- package/dist/sync/participants.d.ts +24 -6
- package/dist/sync/participants.js +32 -23
- package/dist/sync/schemaDrift.d.ts +55 -0
- package/dist/sync/schemaDrift.js +53 -0
- package/dist/sync/schemas.d.ts +23 -33
- package/dist/sync/schemas.js +29 -20
- package/dist/sync/syncPlan.d.ts +3 -3
- package/dist/sync/wsFrameHandlers.d.ts +6 -114
- package/dist/sync/wsFrameHandlers.js +6 -392
- package/dist/syncLog/contract.d.ts +20 -0
- package/dist/syncLog/contract.js +19 -0
- package/dist/syncLog/index.d.ts +1 -0
- package/dist/syncLog/index.js +1 -0
- package/dist/transaction/ablo.d.ts +88 -0
- package/dist/transaction/ablo.js +33 -0
- package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
- package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
- package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
- package/dist/transaction/auth/bootstrapScope.js +1 -0
- package/dist/transaction/auth/capability.d.ts +212 -0
- package/dist/transaction/auth/capability.js +224 -0
- package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
- package/dist/{client → transaction/auth}/identity.d.ts +8 -7
- package/dist/{client → transaction/auth}/identity.js +1 -1
- package/dist/transaction/auth/index.d.ts +162 -0
- package/dist/transaction/auth/index.js +304 -0
- package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
- package/dist/{auth → transaction/auth}/schemas.js +13 -13
- package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
- package/dist/{client → transaction/auth}/sessionMint.js +4 -7
- package/dist/transaction/coordination/awaitClaimGrant.d.ts +56 -0
- package/dist/transaction/coordination/awaitClaimGrant.js +124 -0
- package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +34 -0
- package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +20 -0
- package/dist/transaction/coordination/claimMeta.d.ts +49 -0
- package/dist/transaction/coordination/claimMeta.js +52 -0
- package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
- package/dist/transaction/coordination/createClaimStream.js +475 -0
- package/dist/transaction/coordination/events.d.ts +74 -0
- package/dist/transaction/coordination/events.js +7 -0
- package/dist/transaction/coordination/index.d.ts +19 -0
- package/dist/transaction/coordination/index.js +45 -0
- package/dist/transaction/coordination/locator.d.ts +104 -0
- package/dist/transaction/coordination/locator.js +102 -0
- package/dist/transaction/coordination/schema.d.ts +1536 -0
- package/dist/transaction/coordination/schema.js +1177 -0
- package/dist/transaction/coordination/targetConflict.d.ts +2 -0
- package/dist/transaction/coordination/targetConflict.js +107 -0
- package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
- package/dist/{coordination → transaction/coordination}/trace.js +18 -25
- package/dist/transaction/durableWrites.d.ts +62 -0
- package/dist/{client → transaction}/durableWrites.js +28 -3
- package/dist/transaction/environment.d.ts +105 -0
- package/dist/transaction/environment.js +108 -0
- package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +12 -12
- package/dist/{errorCodes.js → transaction/errorCodes.js} +45 -18
- package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
- package/dist/{errors.js → transaction/errors.js} +85 -16
- package/dist/transaction/footprint.d.ts +111 -0
- package/dist/transaction/footprint.js +0 -0
- package/dist/transaction/index.d.ts +20 -0
- package/dist/transaction/index.js +20 -0
- package/dist/transaction/keys/index.d.ts +87 -0
- package/dist/transaction/keys/index.js +207 -0
- package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
- package/dist/transaction/log/syncDeltaRow.js +95 -0
- package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
- package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
- package/dist/transaction/logger.d.ts +16 -0
- package/dist/transaction/logger.js +7 -0
- package/dist/transaction/observability.d.ts +53 -0
- package/dist/transaction/observability.js +19 -0
- package/dist/transaction/plugin.d.ts +285 -0
- package/dist/transaction/plugin.js +106 -0
- package/dist/{policy → transaction/policy}/types.d.ts +3 -3
- package/dist/{policy → transaction/policy}/types.js +2 -0
- package/dist/transaction/resources/httpResources.d.ts +321 -0
- package/dist/transaction/resources/httpResources.js +7 -0
- package/dist/transaction/resources/modelOperations.d.ts +427 -0
- package/dist/transaction/resources/modelOperations.js +12 -0
- package/dist/transaction/resources/mutationOptions.d.ts +66 -0
- package/dist/transaction/resources/mutationOptions.js +9 -0
- package/dist/transaction/resources/where.d.ts +101 -0
- package/dist/transaction/resources/where.js +115 -0
- package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
- package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
- package/dist/{schema → transaction/schema}/field.d.ts +17 -23
- package/dist/{schema → transaction/schema}/field.js +5 -5
- package/dist/transaction/schema/fieldRef.d.ts +38 -0
- package/dist/transaction/schema/fieldRef.js +11 -0
- package/dist/transaction/schema/loadStrategy.d.ts +45 -0
- package/dist/transaction/schema/loadStrategy.js +46 -0
- package/dist/{schema → transaction/schema}/model.d.ts +50 -35
- package/dist/{schema → transaction/schema}/model.js +30 -20
- package/dist/transaction/schema/openapi.d.ts +58 -0
- package/dist/transaction/schema/openapi.js +501 -0
- package/dist/{schema → transaction/schema}/relation.d.ts +21 -16
- package/dist/{schema → transaction/schema}/relation.js +7 -7
- package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
- package/dist/{schema → transaction/schema}/residency.js +0 -5
- package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
- package/dist/{schema → transaction/schema}/roles.js +5 -5
- package/dist/{schema → transaction/schema}/schema.d.ts +39 -10
- package/dist/{schema → transaction/schema}/schema.js +24 -3
- package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
- package/dist/{schema → transaction/schema}/tenancy.js +7 -4
- package/dist/transaction/transactionLayer.d.ts +82 -0
- package/dist/transaction/transactionLayer.js +24 -0
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +5 -6
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
- package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +11 -37
- package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
- package/dist/transaction/transport/commitFrames.d.ts +90 -0
- package/dist/transaction/transport/commitFrames.js +134 -0
- package/dist/transaction/transport/connectionManager.d.ts +215 -0
- package/dist/transaction/transport/connectionManager.js +673 -0
- package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
- package/dist/transaction/transport/credentialLifecycle.js +324 -0
- package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
- package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
- package/dist/transaction/transport/httpClient.d.ts +131 -0
- package/dist/{client → transaction/transport}/httpClient.js +6 -5
- package/dist/transaction/transport/httpOptions.d.ts +33 -0
- package/dist/transaction/transport/httpOptions.js +12 -0
- package/dist/{client → transaction/transport}/httpTransport.js +295 -97
- package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
- package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
- package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
- package/dist/transaction/transport/wsFrameHandlers.js +429 -0
- package/dist/transaction/transport/wsTransport.d.ts +574 -0
- package/dist/transaction/transport/wsTransport.js +1023 -0
- package/dist/transaction/types/assertExact.d.ts +17 -0
- package/dist/transaction/types/assertExact.js +1 -0
- package/dist/{types → transaction/types}/global.d.ts +17 -2
- package/dist/{types → transaction/types}/global.js +2 -1
- package/dist/{types → transaction/types}/index.d.ts +14 -46
- package/dist/{types → transaction/types}/index.js +7 -16
- package/dist/{types → transaction/types}/streams.d.ts +73 -45
- package/dist/transaction/utils/duration.d.ts +50 -0
- package/dist/{utils → transaction/utils}/duration.js +32 -0
- package/dist/{utils → transaction/utils}/json.d.ts +18 -0
- package/dist/transaction/utils/json.js +276 -0
- package/dist/transaction/wire/accountResponses.d.ts +420 -0
- package/dist/transaction/wire/accountResponses.js +290 -0
- package/dist/transaction/wire/auth.d.ts +56 -0
- package/dist/transaction/wire/auth.js +63 -0
- package/dist/transaction/wire/claimEvent.d.ts +76 -0
- package/dist/transaction/wire/claimEvent.js +73 -0
- package/dist/transaction/wire/claims.d.ts +530 -0
- package/dist/transaction/wire/claims.js +327 -0
- package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
- package/dist/{wire → transaction/wire}/commit.js +68 -47
- package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
- package/dist/{wire → transaction/wire}/delta.js +37 -13
- package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
- package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
- package/dist/transaction/wire/feedCursor.d.ts +60 -0
- package/dist/transaction/wire/feedCursor.js +82 -0
- package/dist/transaction/wire/feedEvent.d.ts +204 -0
- package/dist/transaction/wire/feedEvent.js +65 -0
- package/dist/transaction/wire/frames.d.ts +194 -0
- package/dist/transaction/wire/frames.js +50 -0
- package/dist/transaction/wire/inboundFrames.d.ts +562 -0
- package/dist/transaction/wire/inboundFrames.js +116 -0
- package/dist/transaction/wire/index.d.ts +54 -0
- package/dist/transaction/wire/index.js +83 -0
- package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
- package/dist/transaction/wire/listEnvelope.js +42 -0
- package/dist/transaction/wire/modelMutations.d.ts +31 -0
- package/dist/transaction/wire/modelMutations.js +52 -0
- package/dist/transaction/wire/modelResponses.d.ts +85 -0
- package/dist/transaction/wire/modelResponses.js +43 -0
- package/dist/transaction/wire/modelShape.d.ts +78 -0
- package/dist/transaction/wire/modelShape.js +74 -0
- package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +85 -38
- package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +141 -80
- package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
- package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
- package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
- package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
- package/dist/transactions/mutations/commitLatency.d.ts +52 -0
- package/dist/transactions/mutations/commitLatency.js +130 -0
- package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
- package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
- package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +18 -16
- package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +15 -15
- package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +15 -11
- package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +14 -12
- package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
- package/dist/transactions/mutations/durableWriteStore.js +12 -0
- package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
- package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +4 -3
- package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +7 -5
- package/dist/utils/mobxSetup.d.ts +1 -1
- package/dist/utils/mobxSetup.js +5 -2
- package/dist/{core → views}/QueryView.d.ts +2 -2
- package/dist/{core → views}/QueryView.js +2 -2
- package/dist/{core → views}/ViewRegistry.d.ts +1 -1
- package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
- package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
- package/dist/webhooks/events.d.ts +2 -2
- package/dist/wire/index.d.ts +1 -34
- package/dist/wire/index.js +8 -49
- package/docs/agent-messaging.md +3 -3
- package/docs/agents.md +20 -13
- package/docs/api-keys.md +14 -10
- package/docs/api.md +27 -61
- package/docs/audit.md +6 -3
- package/docs/cli.md +41 -13
- package/docs/client-behavior.md +11 -9
- package/docs/concurrency-convention.md +49 -57
- package/docs/coordination.md +283 -121
- package/docs/data-sources.md +7 -5
- package/docs/debugging.md +39 -15
- package/docs/deployment.md +267 -0
- package/docs/examples/agent-human.md +49 -42
- package/docs/examples/ai-sdk-tool.md +69 -44
- package/docs/examples/existing-python-backend.md +8 -6
- package/docs/examples/nextjs.md +129 -47
- package/docs/examples/scoped-agent.md +46 -45
- package/docs/examples/server-agent.md +46 -26
- package/docs/groups.md +87 -30
- package/docs/guarantees.md +41 -12
- package/docs/how-it-works.md +38 -12
- package/docs/idempotency.md +126 -0
- package/docs/identity.md +77 -74
- package/docs/index.md +172 -86
- package/docs/integration-guide.md +31 -19
- package/docs/mcp.md +46 -21
- package/docs/migration.md +95 -18
- package/docs/operating-on-your-database.md +3 -1
- package/docs/projects.md +3 -1
- package/docs/quickstart.md +22 -5
- package/docs/react.md +31 -18
- package/docs/schema-contract.md +5 -3
- package/docs/session-settings.md +108 -0
- package/docs/sessions.md +4 -2
- package/docs/webhooks.md +12 -10
- package/llms.txt +48 -18
- package/package.json +21 -26
- package/dist/agent/Agent.d.ts +0 -366
- package/dist/agent/Agent.js +0 -514
- package/dist/agent/index.d.ts +0 -115
- package/dist/agent/index.js +0 -128
- package/dist/agent/session.d.ts +0 -93
- package/dist/agent/session.js +0 -149
- package/dist/agent/types.d.ts +0 -68
- package/dist/agent/types.js +0 -9
- package/dist/cli.cjs +0 -286329
- package/dist/client/durableWrites.d.ts +0 -21
- package/dist/client/httpClient.d.ts +0 -80
- package/dist/coordination/schema.d.ts +0 -722
- package/dist/coordination/schema.js +0 -578
- package/dist/schema/openapi.d.ts +0 -29
- package/dist/schema/openapi.js +0 -124
- package/dist/testing/fixtures/bootstrap.d.ts +0 -49
- package/dist/testing/fixtures/bootstrap.js +0 -59
- package/dist/testing/fixtures/deltas.d.ts +0 -83
- package/dist/testing/fixtures/deltas.js +0 -136
- package/dist/testing/fixtures/models.d.ts +0 -83
- package/dist/testing/fixtures/models.js +0 -272
- package/dist/testing/helpers/reactWrapper.d.ts +0 -69
- package/dist/testing/helpers/reactWrapper.js +0 -67
- package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
- package/dist/testing/helpers/syncEngineHarness.js +0 -73
- package/dist/testing/helpers/wait.d.ts +0 -30
- package/dist/testing/helpers/wait.js +0 -49
- package/dist/testing/index.d.ts +0 -23
- package/dist/testing/index.js +0 -33
- package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
- package/dist/testing/mocks/FakeDatabase.js +0 -10
- package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
- package/dist/testing/mocks/MockMutationExecutor.js +0 -192
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
- package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
- package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
- package/dist/testing/mocks/MockSyncContext.js +0 -71
- package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
- package/dist/testing/mocks/MockSyncStore.js +0 -171
- package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
- package/dist/testing/mocks/MockWebSocket.js +0 -118
- package/dist/transactions/durableWriteStore.js +0 -30
- package/dist/utils/duration.d.ts +0 -25
- package/dist/utils/json.js +0 -88
- package/dist/wire/errorEnvelope.d.ts +0 -55
- package/dist/wire/frames.d.ts +0 -197
- package/dist/wire/frames.js +0 -49
- package/dist/wire/listEnvelope.js +0 -18
- package/docs/interaction-model.md +0 -97
- /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
- /package/dist/{core → query}/QueryProcessor.js +0 -0
- /package/dist/{core/storeContract.js → storeContract.js} +0 -0
- /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
- /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
- /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
- /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
- /package/dist/{client → transaction}/persistence.d.ts +0 -0
- /package/dist/{client → transaction}/persistence.js +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
- /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.js +0 -0
- /package/dist/{types → transaction/types}/participant.d.ts +0 -0
- /package/dist/{types → transaction/types}/participant.js +0 -0
- /package/dist/{types → transaction/types}/streams.js +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
- /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocol.js +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
- /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
- /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
- /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
- /package/dist/{core → views}/ViewRegistry.js +0 -0
package/docs/data-sources.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Connect Your Database
|
|
2
2
|
|
|
3
|
+
> Keep the rows in your own Postgres while Ablo coordinates and confirms every write.
|
|
4
|
+
|
|
3
5
|
You write through Ablo, and Ablo writes to your Postgres. A call to
|
|
4
6
|
`ablo.<model>.create / update / delete` enters Ablo's commit chokepoint — where
|
|
5
7
|
claims, ordering, and idempotency are enforced — and Ablo applies the change to
|
|
@@ -73,7 +75,7 @@ Run it against your database as a superuser or the DB owner. It creates:
|
|
|
73
75
|
|
|
74
76
|
Scope it to a subset with `npx ablo connect --tables a,b,c`.
|
|
75
77
|
|
|
76
|
-
- **A replication role
|
|
78
|
+
- **A replication role:** it streams the WAL and `SELECT`s, nothing more. This is
|
|
77
79
|
the role Ablo reads and confirms through. You choose the password; it never
|
|
78
80
|
passes through Ablo's CLI or servers:
|
|
79
81
|
|
|
@@ -85,7 +87,7 @@ Run it against your database as a superuser or the DB owner. It creates:
|
|
|
85
87
|
On Amazon RDS the `REPLICATION` attribute is granted, not set directly:
|
|
86
88
|
`GRANT rds_replication TO "ablo_replicator";`.
|
|
87
89
|
|
|
88
|
-
- **A scoped writer role
|
|
90
|
+
- **A scoped writer role:** the role Ablo writes your rows through. It gets row
|
|
89
91
|
DML (`SELECT, INSERT, UPDATE, DELETE`) and the sync ledger, and nothing else: no
|
|
90
92
|
`REPLICATION`, no schema `CREATE`, `NOSUPERUSER NOBYPASSRLS`, row security on. It
|
|
91
93
|
can change rows in your tables; it cannot change your database:
|
|
@@ -180,14 +182,14 @@ await ablo.weatherReports.update({ id: 'report_stockholm', data: { high: 21 } })
|
|
|
180
182
|
await ablo.weatherReports.update({ id: 'report_stockholm', data: { high: 21 }, wait: 'confirmed' });
|
|
181
183
|
|
|
182
184
|
// Reads are live off the same stream.
|
|
183
|
-
const report = ablo.weatherReports.
|
|
185
|
+
const report = ablo.weatherReports.local.retrieve('report_stockholm');
|
|
184
186
|
```
|
|
185
187
|
|
|
186
188
|
A commit is accepted the moment Ablo takes it (`queued`); it becomes `confirmed`
|
|
187
189
|
once the row appears on your WAL. See [Guarantees](./guarantees.md) for what each
|
|
188
190
|
state means and when to wait.
|
|
189
191
|
|
|
190
|
-
## What Ablo touches in your database
|
|
192
|
+
## What Ablo touches in your database: the honest footprint
|
|
191
193
|
|
|
192
194
|
This is the complete list. Nothing else.
|
|
193
195
|
|
|
@@ -195,7 +197,7 @@ This is the complete list. Nothing else.
|
|
|
195
197
|
|---|---|---|
|
|
196
198
|
| `ablo_publication` | A publication naming the tables Ablo reads and confirms against. | You create it (step 2). |
|
|
197
199
|
| `ablo_replicator` role | A `REPLICATION` + `SELECT` role Ablo reads and confirms through. | You create it (step 2). |
|
|
198
|
-
| `ablo_writer` role | A scoped DML role Ablo writes your rows through
|
|
200
|
+
| `ablo_writer` role | A scoped DML role Ablo writes your rows through: row DML + ledger, nothing more. | You create it (step 2). |
|
|
199
201
|
| Replication slot | A logical slot Ablo subscribes through to track its WAL position. | Ablo's runtime creates it on first connect. |
|
|
200
202
|
| `wal_level = logical` | A server setting that **requires a restart**. | You set it (step 1). |
|
|
201
203
|
|
package/docs/debugging.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Debugging & Logs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Watch claims, queueing, and grants as they happen while you build.
|
|
4
|
+
|
|
5
|
+
By default the SDK is quiet — it logs only warnings and errors. When you're building a multi-agent flow and want to *see* the coordination happen (who claimed what, who's waiting in line, who got preempted), turn on Ablo's diagnostic logging. Every line is prefixed `[Ablo]` so it's obvious which output is ours in a console full of other tools.
|
|
4
6
|
|
|
5
7
|
## Turn it on
|
|
6
8
|
|
|
@@ -11,6 +13,17 @@ import { schema } from './ablo/schema';
|
|
|
11
13
|
const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY, debug: true });
|
|
12
14
|
```
|
|
13
15
|
|
|
16
|
+
## CLI environment and target
|
|
17
|
+
|
|
18
|
+
The CLI checks an explicit credential in this order: exported `ABLO_API_KEY`,
|
|
19
|
+
`.env.local`, `.env`, then the key saved by `ablo login`. An exported value wins
|
|
20
|
+
over project files. If a stale shell export (for example `OPENAI_API_KEY`) is
|
|
21
|
+
shadowing a value in `.env.local`, restart the shell or unset the stale variable.
|
|
22
|
+
|
|
23
|
+
When a command appears to use the wrong plane or project, run `ablo status`.
|
|
24
|
+
It reports the credential source and, when reachable, the server-confirmed
|
|
25
|
+
project and environment; that confirmed target is authoritative.
|
|
26
|
+
|
|
14
27
|
`debug: true` is the simple switch. For finer control use `logLevel`, or set it without touching code via the `ABLO_LOG_LEVEL` environment variable.
|
|
15
28
|
|
|
16
29
|
```ts
|
|
@@ -29,17 +42,17 @@ ABLO_LOG_LEVEL=debug npm run dev # same, from the environment
|
|
|
29
42
|
|---|---|
|
|
30
43
|
| `silent` | nothing |
|
|
31
44
|
| `error` | failures only |
|
|
32
|
-
| `warn` | **default
|
|
45
|
+
| `warn` | **default**: warnings + errors |
|
|
33
46
|
| `info` | the above + the **coordination trace** (claims, grants, queueing) + connection state |
|
|
34
|
-
| `debug` | the above + internal lifecycle (per-model registration, store hydration)
|
|
47
|
+
| `debug` | the above + internal lifecycle (per-model registration, store hydration): the full firehose |
|
|
35
48
|
|
|
36
49
|
Precedence: an explicit `logLevel` wins, then `debug: true` (⇒ `debug`), then `ABLO_LOG_LEVEL`, then the `warn` default. `debug: false` (or omitting it) just means "don't raise the level."
|
|
37
50
|
|
|
38
51
|
> For watching coordination, **`logLevel: 'info'` is the sweet spot** — you get the claim trace without the per-model registration chatter that `debug` adds.
|
|
39
52
|
|
|
40
|
-
## What you'll see
|
|
53
|
+
## What you'll see: the coordination trace
|
|
41
54
|
|
|
42
|
-
These lines (all at `info`) let you watch the
|
|
55
|
+
These lines (all at `info`) let you watch the handover you built:
|
|
43
56
|
|
|
44
57
|
```
|
|
45
58
|
[Ablo] claim: requesting documents:doc_42 for "editing" (will queue if contended)
|
|
@@ -52,16 +65,16 @@ These lines (all at `info`) let you watch the human + agent handover you built:
|
|
|
52
65
|
|
|
53
66
|
Read it as the lifecycle of one claim:
|
|
54
67
|
|
|
55
|
-
- **`requesting
|
|
56
|
-
- **`queued … position N of M
|
|
57
|
-
- **`granted … your turn
|
|
58
|
-
- **`rejected … held by <who
|
|
59
|
-
- **`lost
|
|
60
|
-
- **`released
|
|
68
|
+
- **`requesting`:** your code (or an agent) called `ablo.<model>.claim(...)`. `(will queue if contended)` appears when you passed `{ queue: true }`.
|
|
69
|
+
- **`queued … position N of M`:** the row was held, so you're waiting in the FIFO line. This is the "an agent is waiting behind a claim" moment; it re-logs only when your position changes, so you can watch it advance.
|
|
70
|
+
- **`granted … your turn`:** you reached the head of the line; the lease is now yours and the row may have changed while you waited.
|
|
71
|
+
- **`rejected … held by <who>`:** your claim was refused because someone else holds it (and the model's policy didn't let you in).
|
|
72
|
+
- **`lost`:** you held the lease and it was taken (preempted by a higher-priority writer, or it expired).
|
|
73
|
+
- **`released`:** you (or `await using`'s scope exit) gave the lease back.
|
|
61
74
|
|
|
62
75
|
## Where the logs run
|
|
63
76
|
|
|
64
|
-
The coordination trace and the proactive credential refresh run **in the browser** (and any client that holds a live socket) — that's where the
|
|
77
|
+
The coordination trace and the proactive credential refresh run **in the browser** (and any client that holds a live socket) — that's where the live coordination activity is. Server-side code that mints credentials or does one-shot reads won't emit the trace; it has no live session to narrate.
|
|
65
78
|
|
|
66
79
|
## Bring your own logger
|
|
67
80
|
|
|
@@ -80,7 +93,7 @@ Ablo({
|
|
|
80
93
|
});
|
|
81
94
|
```
|
|
82
95
|
|
|
83
|
-
## Read the coordination in code
|
|
96
|
+
## Read the coordination in code: the activity log
|
|
84
97
|
|
|
85
98
|
The console trace above is for *you*, at a terminal. To put the same activity **inside your app** — an activity feed, a "who's editing" badge, a Sentry breadcrumb trail — read it programmatically. Same events, three layers; pick by audience:
|
|
86
99
|
|
|
@@ -112,7 +125,7 @@ interface ConflictEvent {
|
|
|
112
125
|
|
|
113
126
|
`phase` is past-tense — the state the claim just entered — and maps one-to-one to what arrives on the wire.
|
|
114
127
|
|
|
115
|
-
### Collect them
|
|
128
|
+
### Collect them: `ClaimLog`
|
|
116
129
|
|
|
117
130
|
`ClaimLog` records both into an ordered list. Hand it to `observability`, then read it back:
|
|
118
131
|
|
|
@@ -134,7 +147,7 @@ It's also the simplest way to **assert** coordination in a test — no log scrap
|
|
|
134
147
|
expect(log.collisions()).toHaveLength(0); // no one stepped on anyone
|
|
135
148
|
```
|
|
136
149
|
|
|
137
|
-
### Show it on a page
|
|
150
|
+
### Show it on a page: reactive
|
|
138
151
|
|
|
139
152
|
`ClaimLog.onChange` fires on every event and returns an unsubscribe — the exact shape `useSyncExternalStore` wants, so a live feed is a few lines:
|
|
140
153
|
|
|
@@ -183,6 +196,17 @@ const ablo = Ablo({
|
|
|
183
196
|
});
|
|
184
197
|
```
|
|
185
198
|
|
|
199
|
+
`ClaimLog` implements the full `SyncObservabilityProvider`, so it drops straight
|
|
200
|
+
into the `observability` slot. The surface exports `ClaimLog`, `formatClaim`,
|
|
201
|
+
`formatConflict`, and `noopObservability`, plus the types `ClaimEvent`,
|
|
202
|
+
`ConflictEvent`, `ClaimLogEntry`, and `SyncObservabilityProvider`.
|
|
203
|
+
|
|
204
|
+
> **Both transports, from 0.21.0.** Observability fires on the WebSocket and on
|
|
205
|
+
> the stateless HTTP transport (claim acquired, plus coordination-conflict
|
|
206
|
+
> rejections on every write door). Before 0.21.0 only WebSocket emitted, so a
|
|
207
|
+
> `ClaimLog` on an HTTP client, such as a headless server-agent eval, stayed
|
|
208
|
+
> silent even though coordination still worked.
|
|
209
|
+
|
|
186
210
|
## Errors
|
|
187
211
|
|
|
188
212
|
Ablo's thrown errors are typed and self-describing — `String(err)` (or logging it) yields one clean line, never a stack dump:
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Deployment
|
|
2
|
+
|
|
3
|
+
> What production takes: a database Ablo can reach, a key minted for the plane you mean, and a schema push in the deploy.
|
|
4
|
+
|
|
5
|
+
One command answers the question this page exists for — would a write succeed
|
|
6
|
+
right now, and if not, why:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
ABLO_API_KEY=sk_live_… npx ablo status
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
ablo status
|
|
14
|
+
|
|
15
|
+
key sk_live_51H8… (ABLO_API_KEY env — overrides stored)
|
|
16
|
+
mode production
|
|
17
|
+
org org_3nKq…
|
|
18
|
+
project checkout (prj_7Yb2…)
|
|
19
|
+
acts on production
|
|
20
|
+
○ sandbox sk_test_9fJd… · expires in 71d
|
|
21
|
+
● production — no key
|
|
22
|
+
push production with sk_live_51H8… (env)
|
|
23
|
+
api https://api.abloatai.com reachable
|
|
24
|
+
data ✓ database connected to this plane (direct)
|
|
25
|
+
schema 4 models pushed (rev 12) hash 3f9a2c81 @ 2026-07-18
|
|
26
|
+
• orders typename=orders
|
|
27
|
+
• lineItems typename=lineItems
|
|
28
|
+
• fulfilments typename=fulfilments
|
|
29
|
+
• reviews typename=reviews
|
|
30
|
+
|
|
31
|
+
✓ ready — a write should succeed
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`status` asks the routing authority rather than sampling a read, because reads
|
|
35
|
+
resolve while writes are held — a plane with no database connected serves every
|
|
36
|
+
read and refuses every write. The verdict at the bottom is the whole page in one
|
|
37
|
+
line, and `--json` puts the same conclusion in a `blockers` array you can gate a
|
|
38
|
+
deploy on.
|
|
39
|
+
|
|
40
|
+
## The three ingredients
|
|
41
|
+
|
|
42
|
+
There is no Ablo service for you to deploy. Ablo is hosted, your rows live in
|
|
43
|
+
your own Postgres, and your app runs where it already runs — so a deployment is
|
|
44
|
+
three pieces pointed at the same plane.
|
|
45
|
+
|
|
46
|
+
| Ingredient | Who runs it | What "deploying" means for it |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| **Your Postgres** | You (or your provider) | Registering it against your production plane, once, with a production key. |
|
|
49
|
+
| **Ablo** | Hosted at `api.abloatai.com` | Nothing to run. You choose a project, a plane, and the keys that reach them. |
|
|
50
|
+
| **Your app and agents** | You | Holding the right credential for the runtime, and pushing the schema in the deploy. |
|
|
51
|
+
|
|
52
|
+
Everything below is those three in order.
|
|
53
|
+
|
|
54
|
+
### Planes: what a deployment targets
|
|
55
|
+
|
|
56
|
+
A **plane** is the isolation unit a credential acts on. `production` is the root
|
|
57
|
+
plane; every sandbox sits beside it. Three things are per-plane, and knowing
|
|
58
|
+
which three is most of what production readiness means:
|
|
59
|
+
|
|
60
|
+
- **Rows:** a sandbox write is invisible to production and to every other sandbox.
|
|
61
|
+
- **The registered database:** one per plane, so your production database and
|
|
62
|
+
your dev database are separate registrations.
|
|
63
|
+
- **The active schema artifact:** the model shapes the engine actually routes on.
|
|
64
|
+
|
|
65
|
+
A key's plane is fixed at mint and spelled in its prefix: `sk_live_` acts on
|
|
66
|
+
production, `sk_test_` on a sandbox. There is no runtime override — the
|
|
67
|
+
credential *is* the environment selector, which is why application code never
|
|
68
|
+
passes one.
|
|
69
|
+
|
|
70
|
+
One asymmetry is worth carrying into your deploy plan. A sandbox with no schema
|
|
71
|
+
artifact of its own reads **production's**, so a schema pushed to production
|
|
72
|
+
reaches your sandboxes automatically. The reverse does not hold: a push from a
|
|
73
|
+
sandbox key creates a sandbox artifact that shadows production **for that
|
|
74
|
+
sandbox's readers only**, and production keeps running the schema it was last
|
|
75
|
+
pushed. Production gets its models when you push to production.
|
|
76
|
+
|
|
77
|
+
## 1. The database production writes to
|
|
78
|
+
|
|
79
|
+
Your production database joins Ablo the same way your dev database did — logical
|
|
80
|
+
replication so Ablo can read and confirm, a scoped writer role so Ablo can land
|
|
81
|
+
rows — run once, with a production key so the registration attaches to the
|
|
82
|
+
production plane:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
ABLO_API_KEY=sk_live_… npx ablo connect apply --url postgres://admin:…@host:5432/db
|
|
86
|
+
ABLO_API_KEY=sk_live_… npx ablo connect check
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
[Connect Your Database](./data-sources.md) is the full walkthrough — the SQL, the
|
|
90
|
+
two roles, and the complete list of what Ablo touches. Five things about it are
|
|
91
|
+
specifically production concerns:
|
|
92
|
+
|
|
93
|
+
**Your agents do not each hold a connection.** Every agent, worker, and function
|
|
94
|
+
talks to Ablo, and Ablo holds the database connections — at most 4 connections
|
|
95
|
+
per plane, the same 4 whether one caller is writing behind them or ten thousand
|
|
96
|
+
are. They identify themselves as `ablo-direct-writer`, so `pg_stat_activity`
|
|
97
|
+
accounts for everything Ablo has open at any moment. Size the database for that
|
|
98
|
+
number rather than for your agent count.
|
|
99
|
+
|
|
100
|
+
**Register the direct host, not the pooler.** A pooler terminates the session
|
|
101
|
+
that replication needs, and it refuses the connection in the same words a wrong
|
|
102
|
+
password would — so a pooled host reads as a credentials problem for as long as
|
|
103
|
+
you let it. `ablo status` names a pooled host when it sees one, with the direct
|
|
104
|
+
host to use instead.
|
|
105
|
+
|
|
106
|
+
**Reachability is measured from Ablo's network, not yours.** `connect check`
|
|
107
|
+
runs from the infrastructure replication runs on, so an IPv6-only,
|
|
108
|
+
IP-allowlisted, or VPC-private database still verifies — and a database your
|
|
109
|
+
laptop can reach but Ablo cannot fails here rather than at the first write.
|
|
110
|
+
|
|
111
|
+
**`wal_level = logical` needs a restart.** It is server-wide and not reloadable.
|
|
112
|
+
On RDS and Aurora it is a parameter-group change plus a reboot. Schedule it;
|
|
113
|
+
it is the one setup step with downtime in it.
|
|
114
|
+
|
|
115
|
+
**A replication slot retains WAL.** While Ablo is connected the slot holds what
|
|
116
|
+
it has not yet acknowledged, so a long disconnection accumulates disk. Ablo
|
|
117
|
+
monitors slot lag and retention and surfaces it, and drops an abandoned slot
|
|
118
|
+
rather than letting it grow without bound.
|
|
119
|
+
|
|
120
|
+
A database that cannot grant a `REPLICATION` role connects through the signed
|
|
121
|
+
[Data Source endpoint](./data-sources.md) instead. Same model surface, same
|
|
122
|
+
commit chokepoint — it is the marked fallback, so reach for it when replication
|
|
123
|
+
is genuinely unavailable.
|
|
124
|
+
|
|
125
|
+
## 2. The credential each runtime holds
|
|
126
|
+
|
|
127
|
+
There is one field, `apiKey`, and what goes in it follows from where the code
|
|
128
|
+
runs. In production that resolves to four rows:
|
|
129
|
+
|
|
130
|
+
| Runtime | Credential | Notes |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| Server, worker, agent, cron | `sk_live_` in `ABLO_API_KEY` | Defaults from the environment, so most code passes nothing. |
|
|
133
|
+
| Serverless function | `sk_live_` in `ABLO_API_KEY`, with `transport: 'http'` | Stateless request/response; nothing held open across invocations. |
|
|
134
|
+
| Browser, read-only | `pk_live_` | Publishable and safe to ship, like a Stripe `pk_`. Reads only. |
|
|
135
|
+
| Browser, writing as the signed-in user | `authEndpoint` | A route on your backend mints a short-lived `ek_` per user. |
|
|
136
|
+
|
|
137
|
+
[API Keys](./api-keys.md) covers the model; [Sessions](./sessions.md) covers
|
|
138
|
+
minting. Two things bite specifically at deploy time.
|
|
139
|
+
|
|
140
|
+
**The live key `ablo login` gives you cannot push schema.** It is a restricted,
|
|
141
|
+
observe-only `rk_live_` by design, so a stolen CLI config cannot write to
|
|
142
|
+
production. A production deploy needs a **secret** `sk_live_` from the dashboard,
|
|
143
|
+
supplied as `ABLO_API_KEY`. You do not have to discover this from a failed
|
|
144
|
+
deploy: `ablo login`, `ablo mode production`, and `ablo status` each name what
|
|
145
|
+
the key in hand does, and `ablo status --json` reports it as `effectiveKey.kind`
|
|
146
|
+
for a pipeline to check before it pushes.
|
|
147
|
+
|
|
148
|
+
**An explicit key always wins.** The CLI resolves `ABLO_API_KEY`, then
|
|
149
|
+
`.env.local`, then `.env`, then the stored login — and `ablo status` prints which
|
|
150
|
+
one it found under `key`, with its source. When a deploy lands somewhere
|
|
151
|
+
surprising, that line is usually the answer.
|
|
152
|
+
|
|
153
|
+
## 3. Pushing the schema is a deploy step
|
|
154
|
+
|
|
155
|
+
The server keeps its own copy of your schema and routes on that copy. Until it
|
|
156
|
+
has yours, a write to a new model fails with `server_execute_unknown_model` — so
|
|
157
|
+
`ablo push` belongs in your deploy pipeline, ordered **before** the code that
|
|
158
|
+
depends on the new models goes live.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
ABLO_API_KEY=sk_live_… npx ablo push --yes
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Production requires confirmation: interactively you type the destination
|
|
165
|
+
project's name, which is what makes a wrong-project deploy impossible to do by
|
|
166
|
+
reflex. In CI there is no TTY, so `--yes` is the confirmation and a push without
|
|
167
|
+
it stops rather than proceeding unattended.
|
|
168
|
+
|
|
169
|
+
**Additive changes pass; destructive ones ask.** Adding a model or an optional
|
|
170
|
+
field applies cleanly. Dropping a model or a field, narrowing an enum, or a lossy
|
|
171
|
+
cast is classified as data loss and needs `--force`; adding a required field to a
|
|
172
|
+
populated table needs a `--backfill`. A push that fails is recorded `failed` and
|
|
173
|
+
never activated, so a broken migration cannot leave clients gated against tables
|
|
174
|
+
that do not match.
|
|
175
|
+
|
|
176
|
+
This is the same expand-and-contract shape any online migration has, and it
|
|
177
|
+
sequences the same way: push the additive change, deploy the code that writes
|
|
178
|
+
both shapes, backfill, then push the removal in a later deploy once nothing reads
|
|
179
|
+
the old field.
|
|
180
|
+
|
|
181
|
+
**Drift is a connect-time rejection, not a runtime surprise.** A client built
|
|
182
|
+
against a schema the server is no longer running is turned away when it connects.
|
|
183
|
+
`ablo status` prints the local hash beside the deployed one, and the running
|
|
184
|
+
client reports the same `serverSchemaHash` value, so the two can be matched at a
|
|
185
|
+
glance.
|
|
186
|
+
|
|
187
|
+
## Gate the deploy on the verdict
|
|
188
|
+
|
|
189
|
+
`ablo status --json` reports the same conclusion the human output ends with, in a
|
|
190
|
+
form a pipeline can act on. An empty `blockers` array is the machine-readable
|
|
191
|
+
form of "ready":
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
blockers=$(ABLO_API_KEY=$ABLO_API_KEY npx ablo status --json | jq '.blockers | length')
|
|
195
|
+
[ "$blockers" -eq 0 ] || { npx ablo status; exit 1; }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Each blocker carries a `problem` and the single `fix` that resolves it, in the
|
|
199
|
+
order you should act on them: an unreachable API makes every other finding
|
|
200
|
+
unverifiable, and a plane with nothing connected makes a schema question
|
|
201
|
+
academic. The JSON also carries `confirmedTarget` — the org, project, and
|
|
202
|
+
environment the server says this key resolves to — which is the authoritative
|
|
203
|
+
answer to where a push would land.
|
|
204
|
+
|
|
205
|
+
## Webhooks point at the deployed URL
|
|
206
|
+
|
|
207
|
+
`npx ablo dev` forwards commits to your machine while you build, the way
|
|
208
|
+
`stripe listen` does. A deployed endpoint is registered once, and Ablo returns
|
|
209
|
+
the signing secret a single time:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
ABLO_API_KEY=sk_live_… npx ablo webhooks create https://yourapp.com/api/ablo/[...all]
|
|
213
|
+
ABLO_API_KEY=sk_live_… npx ablo webhooks list # endpoints + delivery health
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`webhooks list` reports each endpoint's status, cursor, and last error — the
|
|
217
|
+
place to look when a mirror falls behind. [Webhooks](./webhooks.md) covers the
|
|
218
|
+
handler, the Standard Webhooks signature, and rolling a secret.
|
|
219
|
+
|
|
220
|
+
## What to watch once it is live
|
|
221
|
+
|
|
222
|
+
- **`ablo logs`:** commit activity as it happens, scoped by the key, so a live
|
|
223
|
+
key streams the org and a test key streams only its sandbox. `--json` emits
|
|
224
|
+
NDJSON for piping.
|
|
225
|
+
- **`ablo status`:** the readiness verdict. Cheap enough to run from a health
|
|
226
|
+
check on your own side.
|
|
227
|
+
- **The [audit log](./audit.md):** every confirmed write traced back to the key
|
|
228
|
+
that made it and the person who authorized that key.
|
|
229
|
+
- **Your own logger:** pass `logger` to the client and SDK lifecycle, sync,
|
|
230
|
+
retry, and rollback events join your existing pipeline.
|
|
231
|
+
|
|
232
|
+
Writes carry receipts rather than being fire-and-forget: a commit is accepted the
|
|
233
|
+
moment Ablo takes it (`queued`) and becomes `confirmed` once the row appears on
|
|
234
|
+
your database's WAL. [Guarantees](./guarantees.md) covers which state to wait for
|
|
235
|
+
and what each promises.
|
|
236
|
+
|
|
237
|
+
## When something is wrong
|
|
238
|
+
|
|
239
|
+
| What you see | What it means | The fix |
|
|
240
|
+
|---|---|---|
|
|
241
|
+
| `no database is connected to this plane` | Writes are held rather than routed. Reads still resolve, which is why a read probe stays quiet. | `ablo connect apply` with a key for that plane. |
|
|
242
|
+
| `password authentication failed` during connect | Often a pooled host refusing a session it cannot serve, in the words of a wrong password. | Register the direct database host. |
|
|
243
|
+
| `server_execute_unknown_model` | The plane's active schema does not carry that model. | `ablo push` with a key for that plane. |
|
|
244
|
+
| Clients rejected at connect | The deployed schema and the client's schema disagree. | Push this tree, or deploy the revision the server is running. |
|
|
245
|
+
| `project_scope_denied` (403) | The model belongs to another project in your org. | Use a key minted for that project: a push cannot cross projects. |
|
|
246
|
+
| 403 on `ablo push` | The key authenticated but cannot author schema. | A secret `sk_live_`; the `ablo login` live key is observe-only. |
|
|
247
|
+
|
|
248
|
+
## The checklist
|
|
249
|
+
|
|
250
|
+
1. Production database registered against the production plane, direct host, and
|
|
251
|
+
`ablo connect check` all green.
|
|
252
|
+
2. A secret `sk_live_` in the deploy environment as `ABLO_API_KEY` — never in a
|
|
253
|
+
browser bundle.
|
|
254
|
+
3. `ablo push --yes` in the pipeline, ahead of the code that needs the new models.
|
|
255
|
+
4. `ablo status --json` gating the deploy on an empty `blockers` array.
|
|
256
|
+
5. Browser clients on a `pk_live_` or an `authEndpoint`, not a secret key.
|
|
257
|
+
6. Webhook endpoints registered at their deployed URLs, with the signing secret
|
|
258
|
+
in your environment.
|
|
259
|
+
|
|
260
|
+
## Next steps
|
|
261
|
+
|
|
262
|
+
- [Connect Your Database](./data-sources.md) — the setup this page registers, in full.
|
|
263
|
+
- [Projects](./projects.md) — one org, many apps, each with its own planes and keys.
|
|
264
|
+
- [API Keys](./api-keys.md) — which credential each runtime holds, and what it may do.
|
|
265
|
+
- [CLI](./cli.md) — every command, its flags, and the environment variables.
|
|
266
|
+
- [Operating on Your Database](./operating-on-your-database.md) — which actions run freely and which belong to a human.
|
|
267
|
+
- [Debugging & Logs](./debugging.md) — watching claims, queueing, and grants while you build.
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# Agent + Human
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> An agent that yields the row when a person is already holding it.
|
|
4
|
+
|
|
5
|
+
A task-writing agent that yields when a person is editing the same task.
|
|
4
6
|
|
|
5
7
|
## Scenario
|
|
6
8
|
|
|
7
|
-
The same
|
|
9
|
+
The same tasks are edited by agents and by the people watching them. They must
|
|
10
|
+
not collide:
|
|
8
11
|
|
|
9
|
-
- If a
|
|
12
|
+
- If a person already holds the row, the agent yields instead of fighting for it.
|
|
10
13
|
- While the agent is updating, the UI can show who is active.
|
|
11
|
-
- If the
|
|
12
|
-
|
|
14
|
+
- If the task changes mid-run, the commit is rejected instead of overwriting the
|
|
15
|
+
newer edit.
|
|
13
16
|
|
|
14
17
|
A **claim** does both jobs. Claims don't lock — if another writer holds the row,
|
|
15
18
|
`claim` waits for them, re-reads the fresh row, then hands it back to you on
|
|
@@ -21,70 +24,74 @@ a typed error if the row moved underneath you while the agent was busy.
|
|
|
21
24
|
|
|
22
25
|
## Schema-Backed Worker
|
|
23
26
|
|
|
24
|
-
The worker uses the same schema client the app uses. It reads the
|
|
25
|
-
|
|
26
|
-
`ablo.
|
|
27
|
-
|
|
27
|
+
The worker uses the same schema client the app uses. It reads the task from the
|
|
28
|
+
server with `retrieve({ id })`, claims the row, and writes through
|
|
29
|
+
`ablo.tasks.update(...)` with a stale-check so a concurrent edit can't be
|
|
30
|
+
overwritten.
|
|
28
31
|
|
|
29
32
|
```ts
|
|
30
33
|
import Ablo, { AbloClaimedError, AbloStaleContextError } from '@abloatai/ablo';
|
|
31
34
|
import { defineSchema, model, z } from '@abloatai/ablo/schema';
|
|
32
35
|
|
|
33
36
|
const schema = defineSchema({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
status: z.enum(['
|
|
37
|
+
tasks: model({
|
|
38
|
+
title: z.string(),
|
|
39
|
+
status: z.enum(['todo', 'doing', 'done']),
|
|
37
40
|
}),
|
|
38
41
|
});
|
|
39
42
|
|
|
40
|
-
const ablo = Ablo({
|
|
43
|
+
const ablo = Ablo({
|
|
44
|
+
schema,
|
|
45
|
+
apiKey: process.env.ABLO_API_KEY,
|
|
46
|
+
transport: 'http',
|
|
47
|
+
});
|
|
41
48
|
|
|
42
|
-
export async function
|
|
49
|
+
export async function markDone(taskId: string) {
|
|
43
50
|
await ablo.ready();
|
|
44
51
|
|
|
45
52
|
// retrieve({ id }) is an async server read — await it.
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
53
|
+
const task = await ablo.tasks.retrieve({ id: taskId });
|
|
54
|
+
if (!task) return { status: 'not_found' };
|
|
48
55
|
|
|
49
56
|
try {
|
|
50
|
-
// queue: false → don't queue behind a current holder. If
|
|
57
|
+
// queue: false → don't queue behind a current holder. If someone already
|
|
51
58
|
// holds the row, claim rejects with AbloClaimedError (caught below), so the
|
|
52
59
|
// agent yields instead of waiting. Omit it, or pass queue: true, to queue
|
|
53
60
|
// behind them. description → the label observers see while we work.
|
|
54
|
-
await using claim = await ablo.
|
|
55
|
-
id:
|
|
61
|
+
await using claim = await ablo.tasks.claim({
|
|
62
|
+
id: taskId,
|
|
56
63
|
queue: false,
|
|
57
|
-
description: '
|
|
64
|
+
description: 'marking_done',
|
|
58
65
|
});
|
|
59
|
-
|
|
66
|
+
if (claim.data.status === 'done') return { status: 'noop' };
|
|
60
67
|
|
|
61
68
|
// Inside an active claim, `update` is stale-checked automatically: the SDK
|
|
62
69
|
// attaches the claim's snapshot version as `readAt` and sets
|
|
63
70
|
// `onStale: 'reject'`. The write below is therefore equivalent to passing
|
|
64
71
|
// those options yourself:
|
|
65
72
|
//
|
|
66
|
-
// ablo.
|
|
67
|
-
// id:
|
|
68
|
-
// data: { status: '
|
|
73
|
+
// ablo.tasks.update({
|
|
74
|
+
// id: claim.data.id,
|
|
75
|
+
// data: { status: 'done' },
|
|
69
76
|
// wait: 'confirmed',
|
|
70
77
|
// readAt: <claim snapshot version>,
|
|
71
78
|
// onStale: 'reject',
|
|
72
79
|
// });
|
|
73
80
|
//
|
|
74
|
-
// If a
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
const updated = await ablo.
|
|
78
|
-
id:
|
|
79
|
-
data: { status: '
|
|
81
|
+
// If a newer version landed mid-run, the row no longer matches `readAt`, so
|
|
82
|
+
// the server rejects this commit with AbloStaleContextError (caught below)
|
|
83
|
+
// instead of clobbering that edit.
|
|
84
|
+
const updated = await ablo.tasks.update({
|
|
85
|
+
id: claim.data.id,
|
|
86
|
+
data: { status: 'done' },
|
|
80
87
|
wait: 'confirmed',
|
|
81
88
|
});
|
|
82
89
|
|
|
83
|
-
return { status: '
|
|
90
|
+
return { status: 'done', task: updated };
|
|
84
91
|
} catch (err) {
|
|
85
|
-
//
|
|
92
|
+
// Someone already holds the row — yield this run and let them finish.
|
|
86
93
|
if (err instanceof AbloClaimedError) return { status: 'yielded' };
|
|
87
|
-
// A
|
|
94
|
+
// A newer version was saved while we held the claim. The stale-check
|
|
88
95
|
// rejected our commit, so nothing was overwritten — re-run on fresh data.
|
|
89
96
|
if (err instanceof AbloStaleContextError) return { status: 'stale' };
|
|
90
97
|
throw err;
|
|
@@ -101,14 +108,14 @@ Keep workers on the same schema-backed client as the app.
|
|
|
101
108
|
|
|
102
109
|
import { useAblo } from '@abloatai/ablo/react';
|
|
103
110
|
|
|
104
|
-
export function
|
|
105
|
-
const data = useAblo((ablo) => ablo.
|
|
106
|
-
const
|
|
107
|
-
const agentActive =
|
|
111
|
+
export function TaskRow({ task: serverTask }: Props) {
|
|
112
|
+
const data = useAblo((ablo) => ablo.tasks.local.retrieve(serverTask.id)) ?? serverTask;
|
|
113
|
+
const holder = useAblo((ablo) => ablo.tasks.claim.state({ id: serverTask.id }));
|
|
114
|
+
const agentActive = holder?.participantKind === 'agent';
|
|
108
115
|
|
|
109
116
|
return (
|
|
110
117
|
<div>
|
|
111
|
-
<span>{data.
|
|
118
|
+
<span>{data.title}</span>
|
|
112
119
|
{agentActive ? <span>Agent is updating...</span> : null}
|
|
113
120
|
</div>
|
|
114
121
|
);
|
|
@@ -120,9 +127,9 @@ export function ReportRow({ report: serverReport }: Props) {
|
|
|
120
127
|
- The claim is visible to everyone: the UI reads it synchronously with
|
|
121
128
|
`claim.state({ id })`, and it also arrives over the live stream.
|
|
122
129
|
- `claim({ id })` makes writers take turns instead of racing — with
|
|
123
|
-
`queue: false`, the agent simply yields when
|
|
124
|
-
- The `update` made while the claim is held is stale-checked automatically, so
|
|
130
|
+
`queue: false`, the agent simply yields when someone already holds the row.
|
|
131
|
+
- The `update` made while the claim is held is stale-checked automatically, so an
|
|
125
132
|
edit landing mid-run rejects the agent's write with a typed
|
|
126
133
|
`AbloStaleContextError` instead of overwriting it.
|
|
127
|
-
- That same write carries the claim, so each accepted change is attributed to
|
|
128
|
-
|
|
134
|
+
- That same write carries the claim, so each accepted change is attributed to the
|
|
135
|
+
run that made it.
|