@abloatai/ablo 0.26.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/CHANGELOG.md +14 -0
- package/README.md +101 -85
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +131 -147
- package/dist/Database.d.ts +54 -68
- package/dist/Database.js +97 -113
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +46 -61
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +112 -112
- package/dist/SyncClient.js +165 -172
- 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 +27 -32
- package/dist/agent/Agent.js +18 -19
- 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} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- 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 +167 -119
- package/dist/client/Ablo.d.ts +73 -73
- package/dist/client/Ablo.js +125 -160
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +133 -38
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +25 -30
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +57 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +67 -87
- package/dist/client/options.d.ts +134 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +15 -20
- package/dist/client/wsMutationExecutor.js +17 -23
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +12 -14
- package/dist/core/StoreManager.js +21 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +131 -132
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +30 -27
- package/dist/index.js +89 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- 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 +145 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- 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 +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- 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 +16 -14
- 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 +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- 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 +20 -24
- package/dist/schema/ddlLock.js +18 -23
- 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 +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +33 -42
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- 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} +26 -49
- 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 +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -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 +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +10 -11
- package/dist/stores/ObjectStore.js +11 -12
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +27 -20
- package/dist/surface.js +27 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +139 -165
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -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 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +2 -2
- 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 +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +181 -176
- package/dist/transactions/TransactionQueue.js +338 -350
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitPayload.d.ts +48 -52
- package/dist/transactions/commitPayload.js +48 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
- package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- 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} +42 -98
- 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 +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +79 -86
- package/dist/wire/frames.js +26 -33
- package/dist/wire/index.d.ts +14 -12
- package/dist/wire/index.js +30 -26
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/coordination.md +59 -0
- package/package.json +11 -10
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- 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 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/utils/mobx-setup.d.ts +0 -42
package/dist/agent/types.d.ts
CHANGED
|
@@ -1,37 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* SDK `experimental_context` bag).
|
|
2
|
+
* Types specific to running AI agents. The shared data vocabulary — `Peer`,
|
|
3
|
+
* {@link Activity}, `Claim`, `ActiveClaim`, `PresenceUpdatePayload`, and
|
|
4
|
+
* `PresenceKind` — lives in the streams module. This file adds only the two
|
|
5
|
+
* pieces the agent layer needs on top of it: {@link PresenceAnnouncer}, a
|
|
6
|
+
* transport-agnostic way to announce presence, and {@link AgentContext}, the bag
|
|
7
|
+
* of ambient state passed to AI SDK tools.
|
|
9
8
|
*/
|
|
10
9
|
import type { Activity } from '../types/streams.js';
|
|
11
10
|
/**
|
|
12
|
-
* A minimal interface for announcing presence
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* A minimal interface for announcing an agent's presence, independent of how it
|
|
12
|
+
* connects. Both the WebSocket-based agent client and the REST-based agent
|
|
13
|
+
* implement it, so higher-level code can depend on this interface without caring
|
|
14
|
+
* which transport is in use.
|
|
16
15
|
*/
|
|
17
16
|
export interface PresenceAnnouncer {
|
|
18
17
|
announce(status: 'online' | 'away' | 'offline', activity?: Activity): Promise<void>;
|
|
19
18
|
}
|
|
20
19
|
/**
|
|
21
|
-
*
|
|
20
|
+
* The ambient state passed to AI SDK tools through the AI SDK's
|
|
21
|
+
* `experimental_context`. Build one {@link AgentContext} per agent invocation and
|
|
22
|
+
* pass it as `experimental_context`; each tool's `execute` function then reads
|
|
23
|
+
* what it needs from `options.experimental_context` rather than closing over
|
|
24
|
+
* shared module state.
|
|
22
25
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* state.
|
|
28
|
-
*
|
|
29
|
-
* Benefits over closure-based tool wiring:
|
|
30
|
-
* - Tools are framework-agnostic module exports (portable across agents)
|
|
31
|
-
* - The context is typed in one place, not scattered across closures
|
|
32
|
-
* - New tools can access any field without changing tool signatures
|
|
33
|
-
*
|
|
34
|
-
* Ported from the vercel-labs/open-agents pattern.
|
|
26
|
+
* Passing context this way, rather than capturing it in each tool's closure,
|
|
27
|
+
* keeps tools as plain module exports that any agent can reuse, types the context
|
|
28
|
+
* in one place, and lets a new tool read any field without changing its
|
|
29
|
+
* signature.
|
|
35
30
|
*
|
|
36
31
|
* ```ts
|
|
37
32
|
* import { generateText, tool } from 'ai';
|
|
@@ -54,20 +49,20 @@ export interface PresenceAnnouncer {
|
|
|
54
49
|
* });
|
|
55
50
|
* ```
|
|
56
51
|
*
|
|
57
|
-
*
|
|
58
|
-
* intersecting with
|
|
52
|
+
* Extend {@link AgentContext} with your own fields through module augmentation or
|
|
53
|
+
* by intersecting it with your own context type.
|
|
59
54
|
*/
|
|
60
55
|
export interface AgentContext {
|
|
61
|
-
/**
|
|
56
|
+
/** Announces presence and checks whether an entity has changed since a given time. Required. */
|
|
62
57
|
perception: PresenceAnnouncer & {
|
|
63
58
|
checkFreshness?: (entityType: string, entityId: string, lastSeenAt: number) => Promise<unknown>;
|
|
64
59
|
};
|
|
65
|
-
/**
|
|
60
|
+
/** The organization every operation is scoped to. */
|
|
66
61
|
organizationId?: string;
|
|
67
|
-
/**
|
|
62
|
+
/** Identifier for the user or agent. Agents use the form `agent:<id>`. */
|
|
68
63
|
userId?: string;
|
|
69
|
-
/**
|
|
64
|
+
/** The sync groups this agent belongs to. */
|
|
70
65
|
syncGroups?: string[];
|
|
71
|
-
/**
|
|
66
|
+
/** Room for your own product-specific fields. */
|
|
72
67
|
[key: string]: unknown;
|
|
73
68
|
}
|
package/dist/agent/types.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* SDK `experimental_context` bag).
|
|
2
|
+
* Types specific to running AI agents. The shared data vocabulary — `Peer`,
|
|
3
|
+
* {@link Activity}, `Claim`, `ActiveClaim`, `PresenceUpdatePayload`, and
|
|
4
|
+
* `PresenceKind` — lives in the streams module. This file adds only the two
|
|
5
|
+
* pieces the agent layer needs on top of it: {@link PresenceAnnouncer}, a
|
|
6
|
+
* transport-agnostic way to announce presence, and {@link AgentContext}, the bag
|
|
7
|
+
* of ambient state passed to AI SDK tools.
|
|
9
8
|
*/
|
|
10
9
|
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns a write to one of your models into a Vercel AI SDK tool that handles
|
|
3
|
+
* multi-agent coordination for you, so an agent can contribute to shared state
|
|
4
|
+
* without silently overwriting another writer's concurrent change.
|
|
5
|
+
*
|
|
6
|
+
* The lower-level approach is to write your own `tool()` and call
|
|
7
|
+
* `ablo.<model>.update({ id, data, claim })` inside its `execute` — the right
|
|
8
|
+
* amount of control for a bespoke tool. This helper covers the common case
|
|
9
|
+
* instead: the agent produced some content and you want to save it into a shared
|
|
10
|
+
* row, without re-deriving optimistic concurrency each time. You declare the
|
|
11
|
+
* write:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { coordinatedTool } from '@abloatai/ablo/ai-sdk';
|
|
15
|
+
* import { z } from 'zod';
|
|
16
|
+
*
|
|
17
|
+
* const saveSection = coordinatedTool(ablo.documents, {
|
|
18
|
+
* description: 'Save your section into the shared document.',
|
|
19
|
+
* inputSchema: z.object({ text: z.string() }),
|
|
20
|
+
* id: () => DOC_ID,
|
|
21
|
+
* apply: (current, { text }) => ({ content: appendBlock(current.content, text) }),
|
|
22
|
+
* // strategy: 'merge' ← the default
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* await streamText({ model, messages, tools: { saveSection } });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The {@link CoordinatedToolOptions.apply} function is the whole API: a pure
|
|
29
|
+
* function from the freshest row and the tool input to a patch, in the same
|
|
30
|
+
* spirit as a functional state update. Everything beneath it — reading the latest
|
|
31
|
+
* row, the compare-and-swap, backing off between retries, and releasing claims —
|
|
32
|
+
* is the runtime's job.
|
|
33
|
+
*
|
|
34
|
+
* ## Strategies
|
|
35
|
+
*
|
|
36
|
+
* Choose a strategy by how you want concurrent writers to relate. Each is
|
|
37
|
+
* designed to converge under many agents writing at once.
|
|
38
|
+
*
|
|
39
|
+
* - `'merge'` (the default) delegates to the functional update
|
|
40
|
+
* `ablo.<model>.update(id, current => apply(current, input))`. The runtime
|
|
41
|
+
* re-reads and re-applies `apply` on top of every concurrent write, backing off
|
|
42
|
+
* between rounds, so many agents accumulate into one row and the model never
|
|
43
|
+
* sees a conflict. This requires the model's agent conflict policy to be
|
|
44
|
+
* `reject` (the default, or `agentsReject()`). A model that declares
|
|
45
|
+
* `agentsNotify()` holds the losing write instead of rejecting it, which
|
|
46
|
+
* defeats the reconcile loop — there, use `'claim'` or `'queue'`, or change the
|
|
47
|
+
* policy.
|
|
48
|
+
*
|
|
49
|
+
* - `'claim'` gives mutual exclusion. It takes a fail-fast claim; if another
|
|
50
|
+
* participant holds the row, it returns `{ status: 'claimed' }` and leaves the
|
|
51
|
+
* decision to retry up to the model. A visible signal serves the agent better
|
|
52
|
+
* than a hidden wait when it might spend its turn on something else. Works under
|
|
53
|
+
* any conflict policy.
|
|
54
|
+
*
|
|
55
|
+
* - `'queue'` serializes writers over stateless HTTP. The tool polls to acquire
|
|
56
|
+
* the claim until it is granted or `poll.timeoutMs` elapses, so the model calls
|
|
57
|
+
* once and the tool waits its turn. Ordering is approximate rather than strict
|
|
58
|
+
* first-in-first-out, which would require a persistent connection.
|
|
59
|
+
*/
|
|
60
|
+
import type { z } from 'zod';
|
|
61
|
+
import type { ModelOperations } from '../client/createModelProxy.js';
|
|
62
|
+
export type CoordinationStrategy = 'merge' | 'claim' | 'queue';
|
|
63
|
+
/** The structured result the tool hands back to the model (or the caller). */
|
|
64
|
+
export interface CoordinatedWriteResult<T> {
|
|
65
|
+
/**
|
|
66
|
+
* `'written'` means the change was saved. `'claimed'` means another participant
|
|
67
|
+
* holds the row, so nothing was saved and the model should try again.
|
|
68
|
+
* `'timeout'` means the `'queue'` strategy could not acquire the row within
|
|
69
|
+
* `poll.timeoutMs`.
|
|
70
|
+
*/
|
|
71
|
+
status: 'written' | 'claimed' | 'timeout';
|
|
72
|
+
/** The reconciled row, on `'written'`. */
|
|
73
|
+
row?: T;
|
|
74
|
+
message?: string;
|
|
75
|
+
/** On `'written'` via the `queue` strategy, how long the tool waited in line. */
|
|
76
|
+
waitedMs?: number;
|
|
77
|
+
}
|
|
78
|
+
export interface CoordinatedToolOptions<TInput, T> {
|
|
79
|
+
/** Tool description shown to the model. */
|
|
80
|
+
description: string;
|
|
81
|
+
/** The schema of what the model may send, as a standard AI SDK / Zod input schema. */
|
|
82
|
+
inputSchema: z.ZodType<TInput>;
|
|
83
|
+
/** Which row this write targets, derived from the tool input. */
|
|
84
|
+
id: (input: TInput) => string;
|
|
85
|
+
/**
|
|
86
|
+
* Produces the write patch from the freshest current row and the tool input, as
|
|
87
|
+
* a pure function of the two. Under `'merge'` it re-runs on top of every
|
|
88
|
+
* concurrent write, so it must be idempotent with respect to its own
|
|
89
|
+
* contribution — for example, skip its change when its marker is already
|
|
90
|
+
* present — to stay correct across retries.
|
|
91
|
+
*/
|
|
92
|
+
apply: (current: T, input: TInput) => Partial<T>;
|
|
93
|
+
/** How concurrent writers relate. Defaults to `'merge'`. */
|
|
94
|
+
strategy?: CoordinationStrategy;
|
|
95
|
+
/** Human-readable coordination metadata attached to the claim, used by the `'claim'` and `'queue'` strategies. */
|
|
96
|
+
claim?: {
|
|
97
|
+
reason?: string;
|
|
98
|
+
description?: string;
|
|
99
|
+
};
|
|
100
|
+
/** How many reconcile rounds `'merge'` may take before it gives up with `AbloContentionError`. */
|
|
101
|
+
retries?: number;
|
|
102
|
+
/** Poll interval and overall timeout for `'queue'`. Defaults to 250ms and 30s. */
|
|
103
|
+
poll?: {
|
|
104
|
+
intervalMs?: number;
|
|
105
|
+
timeoutMs?: number;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
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,15 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* writer.
|
|
2
|
+
* Turns a write to one of your models into a Vercel AI SDK tool that handles
|
|
3
|
+
* multi-agent coordination for you, so an agent can contribute to shared state
|
|
4
|
+
* without silently overwriting another writer's concurrent change.
|
|
6
5
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
6
|
+
* The lower-level approach is to write your own `tool()` and call
|
|
7
|
+
* `ablo.<model>.update({ id, data, claim })` inside its `execute` — the right
|
|
8
|
+
* amount of control for a bespoke tool. This helper covers the common case
|
|
9
|
+
* instead: the agent produced some content and you want to save it into a shared
|
|
10
|
+
* row, without re-deriving optimistic concurrency each time. You declare the
|
|
11
|
+
* write:
|
|
13
12
|
*
|
|
14
13
|
* ```ts
|
|
15
14
|
* import { coordinatedTool } from '@abloatai/ablo/ai-sdk';
|
|
@@ -26,31 +25,37 @@
|
|
|
26
25
|
* await streamText({ model, messages, tools: { saveSection } });
|
|
27
26
|
* ```
|
|
28
27
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* The {@link CoordinatedToolOptions.apply} function is the whole API: a pure
|
|
29
|
+
* function from the freshest row and the tool input to a patch, in the same
|
|
30
|
+
* spirit as a functional state update. Everything beneath it — reading the latest
|
|
31
|
+
* row, the compare-and-swap, backing off between retries, and releasing claims —
|
|
32
|
+
* is the runtime's job.
|
|
33
33
|
*
|
|
34
|
-
* ## Strategies
|
|
35
|
-
* under N-way agent contention)
|
|
34
|
+
* ## Strategies
|
|
36
35
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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.
|
|
36
|
+
* Choose a strategy by how you want concurrent writers to relate. Each is
|
|
37
|
+
* designed to converge under many agents writing at once.
|
|
45
38
|
*
|
|
46
|
-
* - `'
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
39
|
+
* - `'merge'` (the default) delegates to the functional update
|
|
40
|
+
* `ablo.<model>.update(id, current => apply(current, input))`. The runtime
|
|
41
|
+
* re-reads and re-applies `apply` on top of every concurrent write, backing off
|
|
42
|
+
* between rounds, so many agents accumulate into one row and the model never
|
|
43
|
+
* sees a conflict. This requires the model's agent conflict policy to be
|
|
44
|
+
* `reject` (the default, or `agentsReject()`). A model that declares
|
|
45
|
+
* `agentsNotify()` holds the losing write instead of rejecting it, which
|
|
46
|
+
* defeats the reconcile loop — there, use `'claim'` or `'queue'`, or change the
|
|
47
|
+
* policy.
|
|
50
48
|
*
|
|
51
|
-
* - `'
|
|
52
|
-
*
|
|
53
|
-
*
|
|
49
|
+
* - `'claim'` gives mutual exclusion. It takes a fail-fast claim; if another
|
|
50
|
+
* participant holds the row, it returns `{ status: 'claimed' }` and leaves the
|
|
51
|
+
* decision to retry up to the model. A visible signal serves the agent better
|
|
52
|
+
* than a hidden wait when it might spend its turn on something else. Works under
|
|
53
|
+
* any conflict policy.
|
|
54
|
+
*
|
|
55
|
+
* - `'queue'` serializes writers over stateless HTTP. The tool polls to acquire
|
|
56
|
+
* the claim until it is granted or `poll.timeoutMs` elapses, so the model calls
|
|
57
|
+
* once and the tool waits its turn. Ordering is approximate rather than strict
|
|
58
|
+
* first-in-first-out, which would require a persistent connection.
|
|
54
59
|
*/
|
|
55
60
|
import { tool } from 'ai';
|
|
56
61
|
import { AbloClaimedError, AbloNotFoundError } from '../errors.js';
|
|
@@ -63,17 +68,18 @@ export function coordinatedTool(model, options) {
|
|
|
63
68
|
execute: async (input) => {
|
|
64
69
|
const id = options.id(input);
|
|
65
70
|
if (strategy === 'merge') {
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// never sees a conflict.
|
|
71
|
+
// Read the freshest row, apply the patch, and commit it with a
|
|
72
|
+
// compare-and-swap; on any concurrent write, re-read and re-apply with
|
|
73
|
+
// backoff. The model never sees a conflict.
|
|
69
74
|
const row = await model.update(id, (current) => options.apply(current, input), {
|
|
70
75
|
retries: options.retries,
|
|
71
76
|
});
|
|
72
77
|
return { status: 'written', row: row ?? undefined };
|
|
73
78
|
}
|
|
74
|
-
// claim
|
|
75
|
-
//
|
|
76
|
-
// signal to the model
|
|
79
|
+
// The 'claim' and 'queue' strategies both acquire a claim, write under it,
|
|
80
|
+
// and release it. They differ only in what they do when the row is already
|
|
81
|
+
// held: 'claim' returns a signal to the model, while 'queue' waits and
|
|
82
|
+
// retries by polling to acquire.
|
|
77
83
|
const acquireWriteRelease = async () => {
|
|
78
84
|
const claim = await model.claim({
|
|
79
85
|
id,
|
|
@@ -104,7 +110,7 @@ export function coordinatedTool(model, options) {
|
|
|
104
110
|
throw e;
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
|
-
// strategy === 'queue':
|
|
113
|
+
// strategy === 'queue': poll to acquire the claim over stateless HTTP.
|
|
108
114
|
const interval = options.poll?.intervalMs ?? 250;
|
|
109
115
|
const timeout = options.poll?.timeoutMs ?? 30_000;
|
|
110
116
|
const start = Date.now();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language-model middleware that tells the model when other participants are
|
|
3
|
+
* editing the same entity. It reads peer claims on the target from the agent's
|
|
4
|
+
* live presence stream and, when it finds any, injects a short coordination note
|
|
5
|
+
* into the prompt before the model runs.
|
|
6
|
+
*
|
|
7
|
+
* This is the counterpart to the claim-broadcast middleware: that one announces
|
|
8
|
+
* what this agent is about to do, while this one reads what others are doing and
|
|
9
|
+
* passes it to the model. Together they let the model notice when a person or
|
|
10
|
+
* another agent is mid-edit and respond — deferring, framing its work as
|
|
11
|
+
* complementary, or suggesting it wait.
|
|
12
|
+
*
|
|
13
|
+
* It depends only on the AI SDK's provider types and a connected agent from this
|
|
14
|
+
* package, and you compose it with the AI SDK's `wrapLanguageModel`. Reading
|
|
15
|
+
* peers costs no extra model calls: the presence stream is already in memory from
|
|
16
|
+
* the agent's subscription. It adds only a few sentences to the system prompt,
|
|
17
|
+
* and only while peers are actively editing.
|
|
18
|
+
*/
|
|
19
|
+
import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
20
|
+
import type { Ablo } from '../client/Ablo.js';
|
|
21
|
+
import type { SchemaRecord } from '../schema/schema.js';
|
|
22
|
+
import type { ClaimTarget } from '../types/streams.js';
|
|
23
|
+
export type { ClaimTarget };
|
|
24
|
+
export interface CoordinationContextMiddlewareOptions<R extends SchemaRecord = SchemaRecord> {
|
|
25
|
+
readonly agent: Ablo<R> | null;
|
|
26
|
+
readonly target: ClaimTarget | null;
|
|
27
|
+
/**
|
|
28
|
+
* Claim identifiers to leave out of the read, typically this agent's own active
|
|
29
|
+
* claim so the note doesn't report that the agent is editing against itself. In
|
|
30
|
+
* the usual composition with the claim-broadcast middleware, `transformParams`
|
|
31
|
+
* runs before that middleware declares its claim, so the agent's own claim
|
|
32
|
+
* isn't in the presence stream yet and no filtering is needed. This option is
|
|
33
|
+
* here for callers that compose the middleware differently, or that coordinate a
|
|
34
|
+
* fleet and want to exclude sibling workers' claims.
|
|
35
|
+
*/
|
|
36
|
+
readonly excludeClaimIds?: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Builds the coordination-context middleware. If `agent` or `target` is null, the
|
|
40
|
+
* middleware passes the prompt through unchanged.
|
|
41
|
+
*
|
|
42
|
+
* The generic over the schema record matches the claim-broadcast middleware: a
|
|
43
|
+
* typed `Ablo<S>` and the widened `Ablo<SchemaRecord>` are not structurally
|
|
44
|
+
* assignable, so the parameter stays generic to spare callers a cast.
|
|
45
|
+
*/
|
|
46
|
+
export declare function coordinationContextMiddleware<R extends SchemaRecord = SchemaRecord>(options: CoordinationContextMiddlewareOptions<R>): LanguageModelV3Middleware;
|
|
@@ -1,32 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* entity
|
|
4
|
-
*
|
|
2
|
+
* Language-model middleware that tells the model when other participants are
|
|
3
|
+
* editing the same entity. It reads peer claims on the target from the agent's
|
|
4
|
+
* live presence stream and, when it finds any, injects a short coordination note
|
|
5
|
+
* into the prompt before the model runs.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* "while you finish that, I'll …" / suggest waiting / coordinate
|
|
12
|
-
* explicitly.
|
|
7
|
+
* This is the counterpart to the claim-broadcast middleware: that one announces
|
|
8
|
+
* what this agent is about to do, while this one reads what others are doing and
|
|
9
|
+
* passes it to the model. Together they let the model notice when a person or
|
|
10
|
+
* another agent is mid-edit and respond — deferring, framing its work as
|
|
11
|
+
* complementary, or suggesting it wait.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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.
|
|
13
|
+
* It depends only on the AI SDK's provider types and a connected agent from this
|
|
14
|
+
* package, and you compose it with the AI SDK's `wrapLanguageModel`. Reading
|
|
15
|
+
* peers costs no extra model calls: the presence stream is already in memory from
|
|
16
|
+
* the agent's subscription. It adds only a few sentences to the system prompt,
|
|
17
|
+
* and only while peers are actively editing.
|
|
22
18
|
*/
|
|
23
19
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* Builds the coordination-context middleware. If `agent` or `target` is null, the
|
|
21
|
+
* middleware passes the prompt through unchanged.
|
|
26
22
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* assignable.
|
|
23
|
+
* The generic over the schema record matches the claim-broadcast middleware: a
|
|
24
|
+
* typed `Ablo<S>` and the widened `Ablo<SchemaRecord>` are not structurally
|
|
25
|
+
* assignable, so the parameter stays generic to spare callers a cast.
|
|
30
26
|
*/
|
|
31
27
|
export function coordinationContextMiddleware(options) {
|
|
32
28
|
const { agent, target } = options;
|
|
@@ -36,13 +32,10 @@ export function coordinationContextMiddleware(options) {
|
|
|
36
32
|
transformParams: async ({ params }) => {
|
|
37
33
|
if (!agent || !target)
|
|
38
34
|
return params;
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// write the schema typename (`SlideDeck`) — the same normalization the
|
|
44
|
-
// commit plane applies (`modelMap` lookups lowercase, and
|
|
45
|
-
// `targetsOverlap` below already lowercases field/path).
|
|
35
|
+
// Look up peer claims on the same target. This reads the agent's reactive
|
|
36
|
+
// `claims.others` array in memory, with no I/O. The type is compared
|
|
37
|
+
// case-insensitively: observed claims carry a lowercased type name (such as
|
|
38
|
+
// `slidedeck`) while callers write the schema's type name (`SlideDeck`).
|
|
46
39
|
const wantedType = target.type.toLowerCase();
|
|
47
40
|
const peerClaims = agent.claims.others.filter((claim) => claim.target.type.toLowerCase() === wantedType &&
|
|
48
41
|
claim.target.id === target.id &&
|
|
@@ -78,9 +71,9 @@ function targetsOverlap(claimTarget, target) {
|
|
|
78
71
|
return fieldOverlaps && rangeOverlaps;
|
|
79
72
|
}
|
|
80
73
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
74
|
+
* Formats a one-paragraph coordination note for the model. It names who is
|
|
75
|
+
* editing and, when known, what they are doing. The note stays short: the goal is
|
|
76
|
+
* to make the model aware, not to flood the prompt.
|
|
84
77
|
*/
|
|
85
78
|
function formatCoordinationNote(claims, target) {
|
|
86
79
|
const entityLabel = target.type.toLowerCase();
|
package/dist/ai-sdk/index.d.ts
CHANGED
|
@@ -72,22 +72,24 @@
|
|
|
72
72
|
* to one entity before any tool is chosen; tool implementations stay exactly
|
|
73
73
|
* the same.
|
|
74
74
|
*
|
|
75
|
-
* ## Multi-agent coordination
|
|
76
|
-
*
|
|
77
|
-
* When several agents
|
|
78
|
-
* outcome
|
|
79
|
-
*
|
|
80
|
-
* contributions through a blind whole-row write,
|
|
81
|
-
* coordinated one
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* 1.
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
75
|
+
* ## Multi-agent coordination
|
|
76
|
+
*
|
|
77
|
+
* When several agents, or agents and people, write the same row at once, the
|
|
78
|
+
* outcome depends on the write path and the model's conflict policy, not on how
|
|
79
|
+
* capable the model is. The same model silently loses three of four concurrent
|
|
80
|
+
* contributions through a blind whole-row write, yet lands all four through a
|
|
81
|
+
* coordinated one, because a coordinated write returns a signal the model or the
|
|
82
|
+
* runtime can act on. Two rules follow:
|
|
83
|
+
*
|
|
84
|
+
* 1. Surface the signal. A write that swallows the conflict and reports success
|
|
85
|
+
* is the trap. Every reliable path returns a legible result instead of
|
|
86
|
+
* overwriting — a rejection leads to a re-read and retry, and a `'claimed'`
|
|
87
|
+
* result leads the model to try again. A larger model does not fix a silent
|
|
88
|
+
* write.
|
|
89
|
+
* 2. Back off. Under heavy contention, writers that retry in lock-step simply
|
|
90
|
+
* collide again. The shared reconcile loop already jitters its backoff, and
|
|
91
|
+
* any retry you write by hand should too, or it exhausts its budget and drops
|
|
92
|
+
* a writer.
|
|
91
93
|
*
|
|
92
94
|
* `coordinatedTool` (below) encodes both. Prefer it over a hand-written tool for
|
|
93
95
|
* "save the agent's contribution into the shared row":
|
|
@@ -107,12 +109,13 @@
|
|
|
107
109
|
* |----------|-------------------|---------------|------------------------|
|
|
108
110
|
* | `merge` | accumulate (CAS) | re-read + re-apply (silent, backed off) | must be `reject` (default) |
|
|
109
111
|
* | `claim` | mutual exclusion | returns `{status:'claimed'}` → model retries | any |
|
|
110
|
-
* | `queue` | FIFO-ish (
|
|
112
|
+
* | `queue` | FIFO-ish (poll) | poll-acquire until granted / timeout | any |
|
|
111
113
|
*
|
|
112
|
-
* Note: a model
|
|
113
|
-
* rejecting it, which defeats `merge`'s reconcile
|
|
114
|
-
* retried
|
|
114
|
+
* Note: a model that declares `agentsNotify()` holds a losing write rather than
|
|
115
|
+
* rejecting it, which defeats `'merge'`'s reconcile loop — the loser is dropped
|
|
116
|
+
* instead of retried. Use `agentsReject()` for accumulate semantics, or the
|
|
117
|
+
* `'claim'` or `'queue'` strategy.
|
|
115
118
|
*/
|
|
116
|
-
export { coordinationContextMiddleware, type CoordinationContextMiddlewareOptions, type ClaimTarget, } from './
|
|
119
|
+
export { coordinationContextMiddleware, type CoordinationContextMiddlewareOptions, type ClaimTarget, } from './coordinationContext.js';
|
|
117
120
|
export { wrapWithMultiplayer, type WrapWithMultiplayerOptions } from './wrap.js';
|
|
118
|
-
export { coordinatedTool, type CoordinationStrategy, type CoordinatedToolOptions, type CoordinatedWriteResult, } from './
|
|
121
|
+
export { coordinatedTool, type CoordinationStrategy, type CoordinatedToolOptions, type CoordinatedWriteResult, } from './coordinatedTool.js';
|
package/dist/ai-sdk/index.js
CHANGED
|
@@ -72,22 +72,24 @@
|
|
|
72
72
|
* to one entity before any tool is chosen; tool implementations stay exactly
|
|
73
73
|
* the same.
|
|
74
74
|
*
|
|
75
|
-
* ## Multi-agent coordination
|
|
76
|
-
*
|
|
77
|
-
* When several agents
|
|
78
|
-
* outcome
|
|
79
|
-
*
|
|
80
|
-
* contributions through a blind whole-row write,
|
|
81
|
-
* coordinated one
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* 1.
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
75
|
+
* ## Multi-agent coordination
|
|
76
|
+
*
|
|
77
|
+
* When several agents, or agents and people, write the same row at once, the
|
|
78
|
+
* outcome depends on the write path and the model's conflict policy, not on how
|
|
79
|
+
* capable the model is. The same model silently loses three of four concurrent
|
|
80
|
+
* contributions through a blind whole-row write, yet lands all four through a
|
|
81
|
+
* coordinated one, because a coordinated write returns a signal the model or the
|
|
82
|
+
* runtime can act on. Two rules follow:
|
|
83
|
+
*
|
|
84
|
+
* 1. Surface the signal. A write that swallows the conflict and reports success
|
|
85
|
+
* is the trap. Every reliable path returns a legible result instead of
|
|
86
|
+
* overwriting — a rejection leads to a re-read and retry, and a `'claimed'`
|
|
87
|
+
* result leads the model to try again. A larger model does not fix a silent
|
|
88
|
+
* write.
|
|
89
|
+
* 2. Back off. Under heavy contention, writers that retry in lock-step simply
|
|
90
|
+
* collide again. The shared reconcile loop already jitters its backoff, and
|
|
91
|
+
* any retry you write by hand should too, or it exhausts its budget and drops
|
|
92
|
+
* a writer.
|
|
91
93
|
*
|
|
92
94
|
* `coordinatedTool` (below) encodes both. Prefer it over a hand-written tool for
|
|
93
95
|
* "save the agent's contribution into the shared row":
|
|
@@ -107,12 +109,13 @@
|
|
|
107
109
|
* |----------|-------------------|---------------|------------------------|
|
|
108
110
|
* | `merge` | accumulate (CAS) | re-read + re-apply (silent, backed off) | must be `reject` (default) |
|
|
109
111
|
* | `claim` | mutual exclusion | returns `{status:'claimed'}` → model retries | any |
|
|
110
|
-
* | `queue` | FIFO-ish (
|
|
112
|
+
* | `queue` | FIFO-ish (poll) | poll-acquire until granted / timeout | any |
|
|
111
113
|
*
|
|
112
|
-
* Note: a model
|
|
113
|
-
* rejecting it, which defeats `merge`'s reconcile
|
|
114
|
-
* retried
|
|
114
|
+
* Note: a model that declares `agentsNotify()` holds a losing write rather than
|
|
115
|
+
* rejecting it, which defeats `'merge'`'s reconcile loop — the loser is dropped
|
|
116
|
+
* instead of retried. Use `agentsReject()` for accumulate semantics, or the
|
|
117
|
+
* `'claim'` or `'queue'` strategy.
|
|
115
118
|
*/
|
|
116
|
-
export { coordinationContextMiddleware, } from './
|
|
119
|
+
export { coordinationContextMiddleware, } from './coordinationContext.js';
|
|
117
120
|
export { wrapWithMultiplayer } from './wrap.js';
|
|
118
|
-
export { coordinatedTool, } from './
|
|
121
|
+
export { coordinatedTool, } from './coordinatedTool.js';
|
package/dist/ai-sdk/wrap.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ import { wrapLanguageModel } from 'ai';
|
|
|
29
29
|
import type { LanguageModelV3, LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
30
30
|
import type { Ablo } from '../client/Ablo.js';
|
|
31
31
|
import type { SchemaRecord } from '../schema/schema.js';
|
|
32
|
-
import { type ClaimTarget } from './
|
|
32
|
+
import { type ClaimTarget } from './coordinationContext.js';
|
|
33
33
|
export interface WrapWithMultiplayerOptions<R extends SchemaRecord = SchemaRecord> {
|
|
34
34
|
/** The base language model to wrap. Consumer brings their own. */
|
|
35
35
|
readonly model: LanguageModelV3;
|
|
@@ -52,14 +52,13 @@ export interface WrapWithMultiplayerOptions<R extends SchemaRecord = SchemaRecor
|
|
|
52
52
|
*/
|
|
53
53
|
readonly excludeClaimIds?: readonly string[];
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
55
|
+
* Extra middleware to compose. It runs in the order given, nested inside the
|
|
56
|
+
* multiplayer middleware, so the multiplayer wrap stays the outermost layer.
|
|
57
|
+
* Use it for caching, observability, or custom transforms that should not
|
|
58
|
+
* affect the multiplayer signal.
|
|
59
59
|
*
|
|
60
60
|
* For full control over ordering, skip this helper and call
|
|
61
|
-
* `wrapLanguageModel` directly with all middleware in the order
|
|
62
|
-
* you want.
|
|
61
|
+
* `wrapLanguageModel` directly with all the middleware in the order you want.
|
|
63
62
|
*/
|
|
64
63
|
readonly extraMiddleware?: readonly LanguageModelV3Middleware[];
|
|
65
64
|
}
|