@adcp/sdk 14.1.0 → 14.2.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/dist/lib/core/SingleAgentClient.d.mts +4 -1
- package/dist/lib/core/SingleAgentClient.d.ts +4 -1
- package/dist/lib/core/SingleAgentClient.js +25 -4
- package/dist/lib/core/SingleAgentClient.mjs +25 -4
- package/dist/lib/core/TaskExecutor.d.mts +3 -1
- package/dist/lib/core/TaskExecutor.d.ts +3 -1
- package/dist/lib/core/TaskExecutor.js +15 -11
- package/dist/lib/core/TaskExecutor.mjs +15 -11
- package/dist/lib/core/buyer-account-registry.d.mts +30 -2
- package/dist/lib/core/buyer-account-registry.d.ts +30 -2
- package/dist/lib/core/buyer-account-registry.js +126 -42
- package/dist/lib/core/buyer-account-registry.mjs +127 -43
- package/dist/lib/index.d.mts +3 -2
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.mjs +12 -1
- package/dist/lib/net/agent-transport-fetch.d.mts +4 -0
- package/dist/lib/net/agent-transport-fetch.d.ts +4 -0
- package/dist/lib/net/agent-transport-fetch.js +18 -5
- package/dist/lib/net/agent-transport-fetch.mjs +17 -5
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/agent-resolver/errors.d.mts +2 -0
- package/dist/lib/signing/agent-resolver/errors.d.ts +2 -0
- package/dist/lib/signing/agent-resolver/errors.js +6 -0
- package/dist/lib/signing/agent-resolver/errors.mjs +6 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.mts +9 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.ts +9 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.js +35 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +38 -2
- package/dist/lib/signing/agent-resolver/legacy-brand.js +1 -1
- package/dist/lib/signing/agent-resolver/legacy-brand.mjs +2 -2
- package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.js +47 -5
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +55 -6
- package/dist/lib/signing/brand-jwks.d.mts +2 -0
- package/dist/lib/signing/brand-jwks.d.ts +2 -0
- package/dist/lib/signing/brand-jwks.js +10 -2
- package/dist/lib/signing/brand-jwks.mjs +10 -2
- package/dist/lib/signing/errors.d.mts +4 -2
- package/dist/lib/signing/errors.d.ts +4 -2
- package/dist/lib/signing/errors.js +3 -1
- package/dist/lib/signing/errors.mjs +3 -1
- package/dist/lib/signing/verifier.js +1 -1
- package/dist/lib/signing/verifier.mjs +1 -1
- package/dist/lib/signing/webhook-verifier.js +2 -2
- package/dist/lib/signing/webhook-verifier.mjs +3 -3
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/accept-proposal.d.ts +19 -1
- package/dist/lib/types/buy-products.d.ts +19 -1
- package/dist/lib/types/check-governance.d.ts +19 -1
- package/dist/lib/types/comply-test-controller.d.ts +19 -1
- package/dist/lib/types/control-media-buy.d.ts +19 -1
- package/dist/lib/types/core.generated.d.mts +14 -1
- package/dist/lib/types/core.generated.d.ts +14 -1
- package/dist/lib/types/create-media-buy.d.ts +14 -1
- package/dist/lib/types/get-media-buys.d.ts +14 -1
- package/dist/lib/types/get-products.d.ts +19 -1
- package/dist/lib/types/list-products.d.ts +19 -1
- package/dist/lib/types/refine-proposals.d.ts +19 -1
- package/dist/lib/types/request-proposals.d.ts +19 -1
- package/dist/lib/types/schemas.generated.d.ts +12 -3
- package/dist/lib/types/schemas.generated.js +4 -1
- package/dist/lib/types/schemas.generated.mjs +4 -1
- package/dist/lib/types/tools.generated.d.mts +14 -1
- package/dist/lib/types/tools.generated.d.ts +14 -1
- package/dist/lib/types/update-media-buy.d.ts +14 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/webhooks/index.d.mts +24 -0
- package/dist/lib/webhooks/index.d.ts +24 -0
- package/dist/lib/webhooks/index.js +50 -24
- package/dist/lib/webhooks/index.mjs +49 -24
- package/dist/lib/wholesale-feed-sync/index.d.mts +2 -0
- package/dist/lib/wholesale-feed-sync/index.d.ts +2 -0
- package/dist/lib/wholesale-feed-sync/index.js +7 -0
- package/dist/lib/wholesale-feed-sync/index.mjs +4 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.mts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.ts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.js +350 -0
- package/dist/lib/wholesale-feed-sync/mirror.mjs +322 -0
- package/dist/lib/wholesale-feed-sync/sync.d.mts +12 -29
- package/dist/lib/wholesale-feed-sync/sync.d.ts +12 -29
- package/dist/lib/wholesale-feed-sync/sync.js +153 -297
- package/dist/lib/wholesale-feed-sync/sync.mjs +158 -297
- package/docs/README.md +6 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/BUYER-STORAGE.md +3 -0
- package/docs/guides/FIRST-CALL-TO-A-SELLER.md +3 -1
- package/docs/guides/account-resolution.md +46 -10
- package/docs/llms.txt +2 -2
- package/docs/migration-14.0-to-14.1.md +85 -0
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-agent-resolution-3.3.md +5 -3
- package/docs/recipes/verifying-inbound-webhooks.md +4 -0
- package/package.json +2 -1
- package/skills/adcp-brand.previous/SKILL.md +0 -200
- package/skills/adcp-creative.previous/SKILL.md +0 -305
- package/skills/adcp-governance.previous/SKILL.md +0 -566
- package/skills/adcp-measurement.previous/SKILL.md +0 -136
- package/skills/adcp-media-buy.previous/SKILL.md +0 -556
- package/skills/adcp-si.previous/SKILL.md +0 -206
- package/skills/adcp-signals.previous/SKILL.md +0 -204
|
@@ -199,6 +199,7 @@ export interface SingleAgentClientConfig extends ConversationConfig {
|
|
|
199
199
|
accountPolicy?: AccountPolicy;
|
|
200
200
|
accountStorage?: BuyerAccountStorage;
|
|
201
201
|
accountRegistryMaxEntries?: number;
|
|
202
|
+
accountRegistryOptions?: Pick<import('./buyer-account-registry.mjs').BuyerAccountRegistryOptions, 'onDispatchStart' | 'onResult'>;
|
|
202
203
|
/** Trusted stable caller identity for durable registry partitioning. Default is credential fingerprint. */
|
|
203
204
|
accountRegistryScope?: string;
|
|
204
205
|
productCache?: ProductCache;
|
|
@@ -1061,7 +1062,9 @@ export declare class SingleAgentClient {
|
|
|
1061
1062
|
/**
|
|
1062
1063
|
* Sync accounts
|
|
1063
1064
|
*/
|
|
1064
|
-
syncAccounts(params: MutatingRequestInput<SyncAccountsRequest>, inputHandler?: InputHandler, options?: TaskOptions
|
|
1065
|
+
syncAccounts(params: MutatingRequestInput<SyncAccountsRequest>, inputHandler?: InputHandler, options?: TaskOptions,
|
|
1066
|
+
/** @internal Registry-owned final dispatch boundary. */
|
|
1067
|
+
dispatch?: import('./buyer-account-registry.mjs').BuyerAccountProvisioningDispatch): Promise<TaskResult<SyncAccountsResponse>>;
|
|
1065
1068
|
/**
|
|
1066
1069
|
* Sync audiences
|
|
1067
1070
|
*/
|
|
@@ -199,6 +199,7 @@ export interface SingleAgentClientConfig extends ConversationConfig {
|
|
|
199
199
|
accountPolicy?: AccountPolicy;
|
|
200
200
|
accountStorage?: BuyerAccountStorage;
|
|
201
201
|
accountRegistryMaxEntries?: number;
|
|
202
|
+
accountRegistryOptions?: Pick<import('./buyer-account-registry').BuyerAccountRegistryOptions, 'onDispatchStart' | 'onResult'>;
|
|
202
203
|
/** Trusted stable caller identity for durable registry partitioning. Default is credential fingerprint. */
|
|
203
204
|
accountRegistryScope?: string;
|
|
204
205
|
productCache?: ProductCache;
|
|
@@ -1061,7 +1062,9 @@ export declare class SingleAgentClient {
|
|
|
1061
1062
|
/**
|
|
1062
1063
|
* Sync accounts
|
|
1063
1064
|
*/
|
|
1064
|
-
syncAccounts(params: MutatingRequestInput<SyncAccountsRequest>, inputHandler?: InputHandler, options?: TaskOptions
|
|
1065
|
+
syncAccounts(params: MutatingRequestInput<SyncAccountsRequest>, inputHandler?: InputHandler, options?: TaskOptions,
|
|
1066
|
+
/** @internal Registry-owned final dispatch boundary. */
|
|
1067
|
+
dispatch?: import('./buyer-account-registry').BuyerAccountProvisioningDispatch): Promise<TaskResult<SyncAccountsResponse>>;
|
|
1065
1068
|
/**
|
|
1066
1069
|
* Sync audiences
|
|
1067
1070
|
*/
|
|
@@ -883,7 +883,7 @@ class SingleAgentClient {
|
|
|
883
883
|
getAccountRegistry() {
|
|
884
884
|
return this._accounts ??= new import_buyer_account_registry.BuyerAccountRegistry(
|
|
885
885
|
() => this.accountScope(),
|
|
886
|
-
async (account, options, taskOptions) => {
|
|
886
|
+
async (account, options, taskOptions, dispatch) => {
|
|
887
887
|
const caps = await this.getCapabilities(taskOptions);
|
|
888
888
|
const supported = caps.account?.supportedBilling ?? [];
|
|
889
889
|
const billing = options.billing ?? caps.account?.defaultBilling ?? (supported.length === 1 ? supported[0] : void 0);
|
|
@@ -896,6 +896,7 @@ class SingleAgentClient {
|
|
|
896
896
|
}
|
|
897
897
|
return this.syncAccounts(
|
|
898
898
|
{
|
|
899
|
+
...dispatch && { idempotency_key: dispatch.idempotencyKey },
|
|
899
900
|
accounts: [
|
|
900
901
|
{
|
|
901
902
|
...account,
|
|
@@ -906,7 +907,8 @@ class SingleAgentClient {
|
|
|
906
907
|
]
|
|
907
908
|
},
|
|
908
909
|
void 0,
|
|
909
|
-
taskOptions
|
|
910
|
+
{ ...taskOptions, [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true },
|
|
911
|
+
dispatch
|
|
910
912
|
);
|
|
911
913
|
},
|
|
912
914
|
this.config.accountStorage,
|
|
@@ -933,6 +935,8 @@ class SingleAgentClient {
|
|
|
933
935
|
throw new Error("Account status reconciliation could not complete pagination.");
|
|
934
936
|
},
|
|
935
937
|
{
|
|
938
|
+
...this.config.accountRegistryOptions,
|
|
939
|
+
provisionOwnsDispatchBoundary: true,
|
|
936
940
|
maxEntries: this.config.accountRegistryMaxEntries,
|
|
937
941
|
normalizeOptions: async (options, taskOptions) => {
|
|
938
942
|
if (options.billing) return options;
|
|
@@ -950,7 +954,7 @@ class SingleAgentClient {
|
|
|
950
954
|
* `resolveAccount()` keeps the SDK 14.0 sync-on-every-call behavior.
|
|
951
955
|
*/
|
|
952
956
|
accountRegistryOptedIn() {
|
|
953
|
-
return (this.config.accountPolicy ?? "off") !== "off" || this.config.accountStorage !== void 0 || this.config.accountRegistryScope !== void 0 || this.config.accountRegistryMaxEntries !== void 0;
|
|
957
|
+
return (this.config.accountPolicy ?? "off") !== "off" || this.config.accountStorage !== void 0 || this.config.accountRegistryScope !== void 0 || this.config.accountRegistryMaxEntries !== void 0 || this.config.accountRegistryOptions !== void 0;
|
|
954
958
|
}
|
|
955
959
|
accountRegistryContext(task, params, options) {
|
|
956
960
|
const knownOnly = !this.accountRegistryExplicitlyAccessed && (this.config.accountPolicy ?? "off") === "off" && !this.config.accountStorage;
|
|
@@ -5307,7 +5311,24 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5307
5311
|
/**
|
|
5308
5312
|
* Sync accounts
|
|
5309
5313
|
*/
|
|
5310
|
-
async syncAccounts(params, inputHandler, options) {
|
|
5314
|
+
async syncAccounts(params, inputHandler, options, dispatch) {
|
|
5315
|
+
if (dispatch)
|
|
5316
|
+
return this.executeTaskUnprojected(
|
|
5317
|
+
"sync_accounts",
|
|
5318
|
+
params,
|
|
5319
|
+
inputHandler,
|
|
5320
|
+
options,
|
|
5321
|
+
"onSyncAccountsStatusChange",
|
|
5322
|
+
Object.assign(
|
|
5323
|
+
async (effectiveParams) => {
|
|
5324
|
+
if (dispatch.requireIdempotencyKey !== false && effectiveParams.idempotency_key !== dispatch.idempotencyKey)
|
|
5325
|
+
throw new import_errors.ConfigurationError("Account provisioning idempotency key changed before dispatch.");
|
|
5326
|
+
await dispatch.beforeDispatch();
|
|
5327
|
+
return { action: "dispatch_ready" };
|
|
5328
|
+
},
|
|
5329
|
+
{ terminalSettlement: "executor" }
|
|
5330
|
+
)
|
|
5331
|
+
);
|
|
5311
5332
|
return this.executeAndHandle(
|
|
5312
5333
|
"sync_accounts",
|
|
5313
5334
|
"onSyncAccountsStatusChange",
|
|
@@ -953,7 +953,7 @@ class SingleAgentClient {
|
|
|
953
953
|
getAccountRegistry() {
|
|
954
954
|
return this._accounts ??= new BuyerAccountRegistry(
|
|
955
955
|
() => this.accountScope(),
|
|
956
|
-
async (account, options, taskOptions) => {
|
|
956
|
+
async (account, options, taskOptions, dispatch) => {
|
|
957
957
|
const caps = await this.getCapabilities(taskOptions);
|
|
958
958
|
const supported = caps.account?.supportedBilling ?? [];
|
|
959
959
|
const billing = options.billing ?? caps.account?.defaultBilling ?? (supported.length === 1 ? supported[0] : void 0);
|
|
@@ -966,6 +966,7 @@ class SingleAgentClient {
|
|
|
966
966
|
}
|
|
967
967
|
return this.syncAccounts(
|
|
968
968
|
{
|
|
969
|
+
...dispatch && { idempotency_key: dispatch.idempotencyKey },
|
|
969
970
|
accounts: [
|
|
970
971
|
{
|
|
971
972
|
...account,
|
|
@@ -976,7 +977,8 @@ class SingleAgentClient {
|
|
|
976
977
|
]
|
|
977
978
|
},
|
|
978
979
|
void 0,
|
|
979
|
-
taskOptions
|
|
980
|
+
{ ...taskOptions, [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true },
|
|
981
|
+
dispatch
|
|
980
982
|
);
|
|
981
983
|
},
|
|
982
984
|
this.config.accountStorage,
|
|
@@ -1003,6 +1005,8 @@ class SingleAgentClient {
|
|
|
1003
1005
|
throw new Error("Account status reconciliation could not complete pagination.");
|
|
1004
1006
|
},
|
|
1005
1007
|
{
|
|
1008
|
+
...this.config.accountRegistryOptions,
|
|
1009
|
+
provisionOwnsDispatchBoundary: true,
|
|
1006
1010
|
maxEntries: this.config.accountRegistryMaxEntries,
|
|
1007
1011
|
normalizeOptions: async (options, taskOptions) => {
|
|
1008
1012
|
if (options.billing) return options;
|
|
@@ -1020,7 +1024,7 @@ class SingleAgentClient {
|
|
|
1020
1024
|
* `resolveAccount()` keeps the SDK 14.0 sync-on-every-call behavior.
|
|
1021
1025
|
*/
|
|
1022
1026
|
accountRegistryOptedIn() {
|
|
1023
|
-
return (this.config.accountPolicy ?? "off") !== "off" || this.config.accountStorage !== void 0 || this.config.accountRegistryScope !== void 0 || this.config.accountRegistryMaxEntries !== void 0;
|
|
1027
|
+
return (this.config.accountPolicy ?? "off") !== "off" || this.config.accountStorage !== void 0 || this.config.accountRegistryScope !== void 0 || this.config.accountRegistryMaxEntries !== void 0 || this.config.accountRegistryOptions !== void 0;
|
|
1024
1028
|
}
|
|
1025
1029
|
accountRegistryContext(task, params, options) {
|
|
1026
1030
|
const knownOnly = !this.accountRegistryExplicitlyAccessed && (this.config.accountPolicy ?? "off") === "off" && !this.config.accountStorage;
|
|
@@ -5377,7 +5381,24 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5377
5381
|
/**
|
|
5378
5382
|
* Sync accounts
|
|
5379
5383
|
*/
|
|
5380
|
-
async syncAccounts(params, inputHandler, options) {
|
|
5384
|
+
async syncAccounts(params, inputHandler, options, dispatch) {
|
|
5385
|
+
if (dispatch)
|
|
5386
|
+
return this.executeTaskUnprojected(
|
|
5387
|
+
"sync_accounts",
|
|
5388
|
+
params,
|
|
5389
|
+
inputHandler,
|
|
5390
|
+
options,
|
|
5391
|
+
"onSyncAccountsStatusChange",
|
|
5392
|
+
Object.assign(
|
|
5393
|
+
async (effectiveParams) => {
|
|
5394
|
+
if (dispatch.requireIdempotencyKey !== false && effectiveParams.idempotency_key !== dispatch.idempotencyKey)
|
|
5395
|
+
throw new ConfigurationError("Account provisioning idempotency key changed before dispatch.");
|
|
5396
|
+
await dispatch.beforeDispatch();
|
|
5397
|
+
return { action: "dispatch_ready" };
|
|
5398
|
+
},
|
|
5399
|
+
{ terminalSettlement: "executor" }
|
|
5400
|
+
)
|
|
5401
|
+
);
|
|
5381
5402
|
return this.executeAndHandle(
|
|
5382
5403
|
"sync_accounts",
|
|
5383
5404
|
"onSyncAccountsStatusChange",
|
|
@@ -41,6 +41,8 @@ export declare function acknowledgeDeferredSettlement(result: TaskResult<any>):
|
|
|
41
41
|
export declare function rejectDeferredSettlement(result: TaskResult<any>): Promise<void>;
|
|
42
42
|
/** Supporting contract for the internal pre-dispatch boundary. */
|
|
43
43
|
export type BeforeProtocolDispatchHookResult<T> = {
|
|
44
|
+
action: 'dispatch_ready';
|
|
45
|
+
} | {
|
|
44
46
|
action: 'dispatch_committed';
|
|
45
47
|
/** Require the owning durable coordinator to authorize every seller-input continuation. */
|
|
46
48
|
requireDeferredSettlementResumeAuthorization?: boolean;
|
|
@@ -84,7 +86,7 @@ export interface ExternalTaskStatusResult {
|
|
|
84
86
|
error?: string;
|
|
85
87
|
}
|
|
86
88
|
/** Hook used by higher-level SDK coordinators at the final dispatch boundary. */
|
|
87
|
-
export type BeforeProtocolDispatchHook<T> = (effectiveParams: any, context: BeforeProtocolDispatchContext) => Promise<BeforeProtocolDispatchHookResult<T
|
|
89
|
+
export type BeforeProtocolDispatchHook<T> = ((effectiveParams: any, context: BeforeProtocolDispatchContext) => Promise<BeforeProtocolDispatchHookResult<T>>) & {};
|
|
88
90
|
/**
|
|
89
91
|
* Webhook manager for submitted tasks
|
|
90
92
|
*/
|
|
@@ -41,6 +41,8 @@ export declare function acknowledgeDeferredSettlement(result: TaskResult<any>):
|
|
|
41
41
|
export declare function rejectDeferredSettlement(result: TaskResult<any>): Promise<void>;
|
|
42
42
|
/** Supporting contract for the internal pre-dispatch boundary. */
|
|
43
43
|
export type BeforeProtocolDispatchHookResult<T> = {
|
|
44
|
+
action: 'dispatch_ready';
|
|
45
|
+
} | {
|
|
44
46
|
action: 'dispatch_committed';
|
|
45
47
|
/** Require the owning durable coordinator to authorize every seller-input continuation. */
|
|
46
48
|
requireDeferredSettlementResumeAuthorization?: boolean;
|
|
@@ -84,7 +86,7 @@ export interface ExternalTaskStatusResult {
|
|
|
84
86
|
error?: string;
|
|
85
87
|
}
|
|
86
88
|
/** Hook used by higher-level SDK coordinators at the final dispatch boundary. */
|
|
87
|
-
export type BeforeProtocolDispatchHook<T> = (effectiveParams: any, context: BeforeProtocolDispatchContext) => Promise<BeforeProtocolDispatchHookResult<T
|
|
89
|
+
export type BeforeProtocolDispatchHook<T> = ((effectiveParams: any, context: BeforeProtocolDispatchContext) => Promise<BeforeProtocolDispatchHookResult<T>>) & {};
|
|
88
90
|
/**
|
|
89
91
|
* Webhook manager for submitted tasks
|
|
90
92
|
*/
|
|
@@ -944,16 +944,19 @@ class TaskExecutor {
|
|
|
944
944
|
(0, import_abort.throwIfAborted)(options.signal);
|
|
945
945
|
if (beforeProtocolDispatch) {
|
|
946
946
|
let decision;
|
|
947
|
-
|
|
947
|
+
const ownsSettlement = beforeProtocolDispatch.terminalSettlement !== "executor";
|
|
948
|
+
dispatchBoundaryOwnsTerminalState = ownsSettlement;
|
|
948
949
|
try {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
950
|
+
if (ownsSettlement) {
|
|
951
|
+
this.compactClosedExternalTaskSettlementFences();
|
|
952
|
+
if (this.liveExternalTaskSettlementCount() + this.settlementCapacityReservations.size >= COMPACTED_TASK_STATE_LIMIT) {
|
|
953
|
+
throw new Error("The durable task-settlement capacity is exhausted; no mutation claim was attempted.");
|
|
954
|
+
}
|
|
955
|
+
this.settlementCapacityReservations.add(taskId);
|
|
956
|
+
if (webhookRegistrationPersisted) {
|
|
957
|
+
await this.config.onDurableSettlementRequired?.(taskId);
|
|
958
|
+
(0, import_abort.throwIfAborted)(options.signal);
|
|
959
|
+
}
|
|
957
960
|
}
|
|
958
961
|
decision = await beforeProtocolDispatch(preparedCall.args, {
|
|
959
962
|
operationId: taskId,
|
|
@@ -962,6 +965,7 @@ class TaskExecutor {
|
|
|
962
965
|
registerExternalTaskSettlement: (handler) => this.registerExternalTaskSettlement(taskId, handler)
|
|
963
966
|
});
|
|
964
967
|
if (decision.action === "dispatch_committed") {
|
|
968
|
+
if (!ownsSettlement) throw new Error("An executor-settled dispatch hook cannot claim durable settlement.");
|
|
965
969
|
if (decision.requireDeferredSettlementResumeAuthorization === true && this.config.deferredStorage !== void 0) {
|
|
966
970
|
this.requireDeferredSettlementOperationRouting(this.config.deferredStorage);
|
|
967
971
|
}
|
|
@@ -985,8 +989,8 @@ class TaskExecutor {
|
|
|
985
989
|
}
|
|
986
990
|
return (0, import_match.attachMatch)(earlyResult);
|
|
987
991
|
}
|
|
988
|
-
dispatchCommitted =
|
|
989
|
-
dispatchSettlement = decision;
|
|
992
|
+
dispatchCommitted = decision.action === "dispatch_committed";
|
|
993
|
+
dispatchSettlement = decision.action === "dispatch_committed" ? decision : void 0;
|
|
990
994
|
}
|
|
991
995
|
(0, import_abort.throwIfAborted)(options.signal);
|
|
992
996
|
const postDispatchOptions = dispatchCommitted ? { ...options, signal: void 0 } : options;
|
|
@@ -917,16 +917,19 @@ class TaskExecutor {
|
|
|
917
917
|
throwIfAborted(options.signal);
|
|
918
918
|
if (beforeProtocolDispatch) {
|
|
919
919
|
let decision;
|
|
920
|
-
|
|
920
|
+
const ownsSettlement = beforeProtocolDispatch.terminalSettlement !== "executor";
|
|
921
|
+
dispatchBoundaryOwnsTerminalState = ownsSettlement;
|
|
921
922
|
try {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
923
|
+
if (ownsSettlement) {
|
|
924
|
+
this.compactClosedExternalTaskSettlementFences();
|
|
925
|
+
if (this.liveExternalTaskSettlementCount() + this.settlementCapacityReservations.size >= COMPACTED_TASK_STATE_LIMIT) {
|
|
926
|
+
throw new Error("The durable task-settlement capacity is exhausted; no mutation claim was attempted.");
|
|
927
|
+
}
|
|
928
|
+
this.settlementCapacityReservations.add(taskId);
|
|
929
|
+
if (webhookRegistrationPersisted) {
|
|
930
|
+
await this.config.onDurableSettlementRequired?.(taskId);
|
|
931
|
+
throwIfAborted(options.signal);
|
|
932
|
+
}
|
|
930
933
|
}
|
|
931
934
|
decision = await beforeProtocolDispatch(preparedCall.args, {
|
|
932
935
|
operationId: taskId,
|
|
@@ -935,6 +938,7 @@ class TaskExecutor {
|
|
|
935
938
|
registerExternalTaskSettlement: (handler) => this.registerExternalTaskSettlement(taskId, handler)
|
|
936
939
|
});
|
|
937
940
|
if (decision.action === "dispatch_committed") {
|
|
941
|
+
if (!ownsSettlement) throw new Error("An executor-settled dispatch hook cannot claim durable settlement.");
|
|
938
942
|
if (decision.requireDeferredSettlementResumeAuthorization === true && this.config.deferredStorage !== void 0) {
|
|
939
943
|
this.requireDeferredSettlementOperationRouting(this.config.deferredStorage);
|
|
940
944
|
}
|
|
@@ -958,8 +962,8 @@ class TaskExecutor {
|
|
|
958
962
|
}
|
|
959
963
|
return attachMatch(earlyResult);
|
|
960
964
|
}
|
|
961
|
-
dispatchCommitted =
|
|
962
|
-
dispatchSettlement = decision;
|
|
965
|
+
dispatchCommitted = decision.action === "dispatch_committed";
|
|
966
|
+
dispatchSettlement = decision.action === "dispatch_committed" ? decision : void 0;
|
|
963
967
|
}
|
|
964
968
|
throwIfAborted(options.signal);
|
|
965
969
|
const postDispatchOptions = dispatchCommitted ? { ...options, signal: void 0 } : options;
|
|
@@ -5,6 +5,8 @@ export interface EnsureAccountOptions {
|
|
|
5
5
|
billing?: 'operator' | 'agent' | 'advertiser';
|
|
6
6
|
paymentTerms?: PaymentTerms;
|
|
7
7
|
billingEntity?: BusinessEntity;
|
|
8
|
+
/** Caller-owned retry identity. Settle ambiguous dispatches explicitly with this key; the registry never rotates it. */
|
|
9
|
+
idempotencyKey?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface ProvisionedAccount {
|
|
10
12
|
account: AccountReference;
|
|
@@ -15,13 +17,38 @@ export interface ProvisionedAccount {
|
|
|
15
17
|
setupTerms?: Partial<Record<keyof EnsureAccountOptions, string>>;
|
|
16
18
|
/** Stored reference aliases for authoritative repair after restart. */
|
|
17
19
|
aliases?: AccountReference[];
|
|
20
|
+
/** Monotonically increasing row revision when compareAndSet is implemented. */
|
|
21
|
+
revision?: number;
|
|
22
|
+
/** Durable claim. Reconcile an uncertain dispatch explicitly before provisioning again. */
|
|
23
|
+
dispatch?: {
|
|
24
|
+
idempotencyKey: string;
|
|
25
|
+
startedAt: string;
|
|
26
|
+
};
|
|
18
27
|
}
|
|
19
28
|
/** Partitioned by seller and caller scope. Implementations must provide read-your-writes. */
|
|
20
29
|
export interface BuyerAccountStorage {
|
|
21
30
|
get(key: string): Promise<ProvisionedAccount | undefined>;
|
|
22
31
|
set(key: string, account: ProvisionedAccount): Promise<void>;
|
|
32
|
+
/** Atomically insert (undefined revision) or replace. Store the supplied new revision. Required for multi-process safety. */
|
|
33
|
+
compareAndSet?(key: string, expectedRevision: number | undefined, account: ProvisionedAccount): Promise<boolean>;
|
|
34
|
+
}
|
|
35
|
+
export interface BuyerAccountDispatch {
|
|
36
|
+
storageKey: string;
|
|
37
|
+
account: AccountReference;
|
|
38
|
+
idempotencyKey: string;
|
|
39
|
+
}
|
|
40
|
+
export interface BuyerAccountProvisioningDispatch {
|
|
41
|
+
idempotencyKey: string;
|
|
42
|
+
/** Invoke immediately before the transport receives the mutation. */
|
|
43
|
+
beforeDispatch(): Promise<void>;
|
|
23
44
|
}
|
|
24
45
|
export interface BuyerAccountRegistryOptions {
|
|
46
|
+
/** Awaited before dispatch; rejection prevents the mutation. */
|
|
47
|
+
onDispatchStart?: (dispatch: BuyerAccountDispatch) => Promise<void>;
|
|
48
|
+
/** Awaited for each seller result before account writes. Rejection preserves the claim for caller reconciliation. */
|
|
49
|
+
onResult?: (dispatch: BuyerAccountDispatch & {
|
|
50
|
+
result: TaskResult<unknown>;
|
|
51
|
+
}) => Promise<void>;
|
|
25
52
|
maxEntries?: number;
|
|
26
53
|
normalizeOptions?: (options: EnsureAccountOptions, taskOptions?: TaskOptions) => Promise<EnsureAccountOptions>;
|
|
27
54
|
}
|
|
@@ -30,6 +57,7 @@ export declare class BuyerAccountRegistry {
|
|
|
30
57
|
private provision;
|
|
31
58
|
private storage?;
|
|
32
59
|
private repair?;
|
|
60
|
+
private readonly registryOptions;
|
|
33
61
|
private entries;
|
|
34
62
|
private pending;
|
|
35
63
|
private writes;
|
|
@@ -41,7 +69,7 @@ export declare class BuyerAccountRegistry {
|
|
|
41
69
|
private statusEpochs;
|
|
42
70
|
private readonly maxEntries;
|
|
43
71
|
private readonly normalizeOptions?;
|
|
44
|
-
constructor(scope: () => string, provision: (key: AccountReference, options: EnsureAccountOptions, taskOptions?: TaskOptions) => Promise<TaskResult<SyncAccountsResponse>>, storage?: BuyerAccountStorage | undefined, repair?: ((accountId: string, taskOptions?: TaskOptions) => Promise<readonly unknown[]>) | undefined,
|
|
72
|
+
constructor(scope: () => string, provision: (key: AccountReference, options: EnsureAccountOptions, taskOptions?: TaskOptions, dispatch?: BuyerAccountProvisioningDispatch) => Promise<TaskResult<SyncAccountsResponse>>, storage?: BuyerAccountStorage | undefined, repair?: ((accountId: string, taskOptions?: TaskOptions) => Promise<readonly unknown[]>) | undefined, registryOptions?: BuyerAccountRegistryOptions);
|
|
45
73
|
private key;
|
|
46
74
|
/** Capture before a seller request; observations older than a status repair are ignored. */
|
|
47
75
|
captureObservation(): number;
|
|
@@ -52,7 +80,7 @@ export declare class BuyerAccountRegistry {
|
|
|
52
80
|
private write;
|
|
53
81
|
private record;
|
|
54
82
|
private enqueue;
|
|
55
|
-
observeSync(refs: readonly AccountReference[], rows: readonly unknown[], dryRun?: boolean, observationEpoch?: number): Promise<void>;
|
|
83
|
+
observeSync(refs: readonly AccountReference[], rows: readonly unknown[], dryRun?: boolean, observationEpoch?: number, expectedRevision?: number): Promise<void>;
|
|
56
84
|
private reconcileId;
|
|
57
85
|
observeList(rows: readonly unknown[], queriedAccountId?: string, observationEpoch?: number): Promise<void>;
|
|
58
86
|
private observeListAtScope;
|
|
@@ -5,6 +5,8 @@ export interface EnsureAccountOptions {
|
|
|
5
5
|
billing?: 'operator' | 'agent' | 'advertiser';
|
|
6
6
|
paymentTerms?: PaymentTerms;
|
|
7
7
|
billingEntity?: BusinessEntity;
|
|
8
|
+
/** Caller-owned retry identity. Settle ambiguous dispatches explicitly with this key; the registry never rotates it. */
|
|
9
|
+
idempotencyKey?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface ProvisionedAccount {
|
|
10
12
|
account: AccountReference;
|
|
@@ -15,13 +17,38 @@ export interface ProvisionedAccount {
|
|
|
15
17
|
setupTerms?: Partial<Record<keyof EnsureAccountOptions, string>>;
|
|
16
18
|
/** Stored reference aliases for authoritative repair after restart. */
|
|
17
19
|
aliases?: AccountReference[];
|
|
20
|
+
/** Monotonically increasing row revision when compareAndSet is implemented. */
|
|
21
|
+
revision?: number;
|
|
22
|
+
/** Durable claim. Reconcile an uncertain dispatch explicitly before provisioning again. */
|
|
23
|
+
dispatch?: {
|
|
24
|
+
idempotencyKey: string;
|
|
25
|
+
startedAt: string;
|
|
26
|
+
};
|
|
18
27
|
}
|
|
19
28
|
/** Partitioned by seller and caller scope. Implementations must provide read-your-writes. */
|
|
20
29
|
export interface BuyerAccountStorage {
|
|
21
30
|
get(key: string): Promise<ProvisionedAccount | undefined>;
|
|
22
31
|
set(key: string, account: ProvisionedAccount): Promise<void>;
|
|
32
|
+
/** Atomically insert (undefined revision) or replace. Store the supplied new revision. Required for multi-process safety. */
|
|
33
|
+
compareAndSet?(key: string, expectedRevision: number | undefined, account: ProvisionedAccount): Promise<boolean>;
|
|
34
|
+
}
|
|
35
|
+
export interface BuyerAccountDispatch {
|
|
36
|
+
storageKey: string;
|
|
37
|
+
account: AccountReference;
|
|
38
|
+
idempotencyKey: string;
|
|
39
|
+
}
|
|
40
|
+
export interface BuyerAccountProvisioningDispatch {
|
|
41
|
+
idempotencyKey: string;
|
|
42
|
+
/** Invoke immediately before the transport receives the mutation. */
|
|
43
|
+
beforeDispatch(): Promise<void>;
|
|
23
44
|
}
|
|
24
45
|
export interface BuyerAccountRegistryOptions {
|
|
46
|
+
/** Awaited before dispatch; rejection prevents the mutation. */
|
|
47
|
+
onDispatchStart?: (dispatch: BuyerAccountDispatch) => Promise<void>;
|
|
48
|
+
/** Awaited for each seller result before account writes. Rejection preserves the claim for caller reconciliation. */
|
|
49
|
+
onResult?: (dispatch: BuyerAccountDispatch & {
|
|
50
|
+
result: TaskResult<unknown>;
|
|
51
|
+
}) => Promise<void>;
|
|
25
52
|
maxEntries?: number;
|
|
26
53
|
normalizeOptions?: (options: EnsureAccountOptions, taskOptions?: TaskOptions) => Promise<EnsureAccountOptions>;
|
|
27
54
|
}
|
|
@@ -30,6 +57,7 @@ export declare class BuyerAccountRegistry {
|
|
|
30
57
|
private provision;
|
|
31
58
|
private storage?;
|
|
32
59
|
private repair?;
|
|
60
|
+
private readonly registryOptions;
|
|
33
61
|
private entries;
|
|
34
62
|
private pending;
|
|
35
63
|
private writes;
|
|
@@ -41,7 +69,7 @@ export declare class BuyerAccountRegistry {
|
|
|
41
69
|
private statusEpochs;
|
|
42
70
|
private readonly maxEntries;
|
|
43
71
|
private readonly normalizeOptions?;
|
|
44
|
-
constructor(scope: () => string, provision: (key: AccountReference, options: EnsureAccountOptions, taskOptions?: TaskOptions) => Promise<TaskResult<SyncAccountsResponse>>, storage?: BuyerAccountStorage | undefined, repair?: ((accountId: string, taskOptions?: TaskOptions) => Promise<readonly unknown[]>) | undefined,
|
|
72
|
+
constructor(scope: () => string, provision: (key: AccountReference, options: EnsureAccountOptions, taskOptions?: TaskOptions, dispatch?: BuyerAccountProvisioningDispatch) => Promise<TaskResult<SyncAccountsResponse>>, storage?: BuyerAccountStorage | undefined, repair?: ((accountId: string, taskOptions?: TaskOptions) => Promise<readonly unknown[]>) | undefined, registryOptions?: BuyerAccountRegistryOptions);
|
|
45
73
|
private key;
|
|
46
74
|
/** Capture before a seller request; observations older than a status repair are ignored. */
|
|
47
75
|
captureObservation(): number;
|
|
@@ -52,7 +80,7 @@ export declare class BuyerAccountRegistry {
|
|
|
52
80
|
private write;
|
|
53
81
|
private record;
|
|
54
82
|
private enqueue;
|
|
55
|
-
observeSync(refs: readonly AccountReference[], rows: readonly unknown[], dryRun?: boolean, observationEpoch?: number): Promise<void>;
|
|
83
|
+
observeSync(refs: readonly AccountReference[], rows: readonly unknown[], dryRun?: boolean, observationEpoch?: number, expectedRevision?: number): Promise<void>;
|
|
56
84
|
private reconcileId;
|
|
57
85
|
observeList(rows: readonly unknown[], queriedAccountId?: string, observationEpoch?: number): Promise<void>;
|
|
58
86
|
private observeListAtScope;
|