@adcp/sdk 16.2.0 → 16.4.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 -0
- package/dist/lib/adapters/version/3.1/assignments.d.mts +12 -0
- package/dist/lib/adapters/version/3.1/assignments.d.ts +12 -0
- package/dist/lib/adapters/version/3.1/assignments.js +67 -0
- package/dist/lib/adapters/version/3.1/assignments.mjs +43 -0
- package/dist/lib/adapters/version/3.1/bidding.d.mts +3 -0
- package/dist/lib/adapters/version/3.1/bidding.d.ts +3 -0
- package/dist/lib/adapters/version/3.1/bidding.js +115 -0
- package/dist/lib/adapters/version/3.1/bidding.mjs +90 -0
- package/dist/lib/adapters/version/3.1/delivery.d.mts +7 -0
- package/dist/lib/adapters/version/3.1/delivery.d.ts +7 -0
- package/dist/lib/adapters/version/3.1/delivery.js +78 -0
- package/dist/lib/adapters/version/3.1/delivery.mjs +54 -0
- package/dist/lib/adapters/version/3.1/index.d.mts +3 -0
- package/dist/lib/adapters/version/3.1/index.d.ts +3 -0
- package/dist/lib/adapters/version/3.1/index.js +36 -0
- package/dist/lib/adapters/version/3.1/index.mjs +12 -0
- package/dist/lib/adapters/version/index.d.mts +59 -7
- package/dist/lib/adapters/version/index.d.ts +59 -7
- package/dist/lib/adapters/version/index.js +51 -2
- package/dist/lib/adapters/version/index.mjs +49 -1
- package/dist/lib/adapters/version/negotiate.d.mts +71 -0
- package/dist/lib/adapters/version/negotiate.d.ts +71 -0
- package/dist/lib/adapters/version/negotiate.js +101 -0
- package/dist/lib/adapters/version/negotiate.mjs +73 -0
- package/dist/lib/adapters/version/schema-projection.d.mts +33 -0
- package/dist/lib/adapters/version/schema-projection.d.ts +33 -0
- package/dist/lib/adapters/version/schema-projection.js +294 -0
- package/dist/lib/adapters/version/schema-projection.mjs +269 -0
- package/dist/lib/adapters/version/translate.d.mts +122 -0
- package/dist/lib/adapters/version/translate.d.ts +122 -0
- package/dist/lib/adapters/version/translate.js +169 -0
- package/dist/lib/adapters/version/translate.mjs +141 -0
- package/dist/lib/adapters/version/types.d.mts +51 -10
- package/dist/lib/adapters/version/types.d.ts +51 -10
- package/dist/lib/core/AgentClient.d.mts +1 -1
- package/dist/lib/core/AgentClient.d.ts +1 -1
- package/dist/lib/core/AgentClient.js +17 -1
- package/dist/lib/core/AgentClient.mjs +17 -1
- package/dist/lib/core/ConversationTypes.d.mts +7 -0
- package/dist/lib/core/ConversationTypes.d.ts +7 -0
- package/dist/lib/core/SingleAgentClient.d.mts +82 -0
- package/dist/lib/core/SingleAgentClient.d.ts +82 -0
- package/dist/lib/core/SingleAgentClient.js +336 -15
- package/dist/lib/core/SingleAgentClient.mjs +350 -17
- package/dist/lib/core/TaskExecutor.d.mts +1 -1
- package/dist/lib/core/TaskExecutor.d.ts +1 -1
- package/dist/lib/core/TaskExecutor.js +182 -31
- package/dist/lib/core/TaskExecutor.mjs +183 -32
- package/dist/lib/core/account-reduction.d.mts +36 -0
- package/dist/lib/core/account-reduction.d.ts +36 -0
- package/dist/lib/core/account-reduction.js +127 -0
- package/dist/lib/core/account-reduction.mjs +98 -0
- package/dist/lib/core/buyer-account-registry.d.mts +52 -0
- package/dist/lib/core/buyer-account-registry.d.ts +52 -0
- package/dist/lib/core/buyer-account-registry.js +142 -6
- package/dist/lib/core/buyer-account-registry.mjs +142 -6
- package/dist/lib/errors/index.d.mts +34 -0
- package/dist/lib/errors/index.d.ts +34 -0
- package/dist/lib/errors/index.js +11 -0
- package/dist/lib/errors/index.mjs +10 -0
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +2 -0
- package/dist/lib/media-buy/action-contracts.js +4 -4
- package/dist/lib/media-buy/action-contracts.mjs +4 -4
- package/dist/lib/media-buy/action-types.d.mts +3 -2
- package/dist/lib/media-buy/action-types.d.ts +3 -2
- package/dist/lib/media-buy/compatibility.d.mts +1 -0
- package/dist/lib/media-buy/compatibility.d.ts +1 -0
- package/dist/lib/media-buy/compatibility.js +33 -10
- package/dist/lib/media-buy/compatibility.mjs +32 -14
- package/dist/lib/media-buy/update-fields.generated.d.mts +3 -2
- package/dist/lib/media-buy/update-fields.generated.d.ts +3 -2
- package/dist/lib/negotiation/buyer.js +11 -5
- package/dist/lib/negotiation/buyer.mjs +11 -5
- package/dist/lib/negotiation/types.d.mts +4 -2
- package/dist/lib/negotiation/types.d.ts +4 -2
- package/dist/lib/negotiation/verification.d.mts +15 -6
- package/dist/lib/negotiation/verification.d.ts +15 -6
- package/dist/lib/negotiation/verification.js +146 -27
- package/dist/lib/negotiation/verification.mjs +146 -28
- package/dist/lib/negotiation/version.d.mts +6 -0
- package/dist/lib/negotiation/version.d.ts +6 -0
- package/dist/lib/negotiation/version.js +60 -0
- package/dist/lib/negotiation/version.mjs +33 -0
- package/dist/lib/registry/types.generated.d.mts +1 -1
- package/dist/lib/registry/types.generated.d.ts +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +21 -0
- package/dist/lib/server/create-adcp-server.d.ts +21 -0
- package/dist/lib/server/create-adcp-server.js +98 -16
- package/dist/lib/server/create-adcp-server.mjs +84 -2
- package/dist/lib/server/error-arm-tools.d.mts +10 -10
- package/dist/lib/server/error-arm-tools.d.ts +10 -10
- package/dist/lib/server/error-arm-tools.js +22 -58
- package/dist/lib/server/error-arm-tools.mjs +30 -65
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/storage/interfaces.d.mts +2 -0
- package/dist/lib/storage/interfaces.d.ts +2 -0
- package/dist/lib/testing/compliance/comply.js +17 -0
- package/dist/lib/testing/compliance/comply.mjs +17 -0
- package/dist/lib/testing/index.d.mts +3 -0
- package/dist/lib/testing/index.d.ts +3 -0
- package/dist/lib/testing/index.js +44 -2
- package/dist/lib/testing/index.mjs +42 -0
- package/dist/lib/testing/storyboard/collection-selection.d.mts +259 -0
- package/dist/lib/testing/storyboard/collection-selection.d.ts +259 -0
- package/dist/lib/testing/storyboard/collection-selection.js +384 -0
- package/dist/lib/testing/storyboard/collection-selection.mjs +348 -0
- package/dist/lib/testing/storyboard/context.js +12 -6
- package/dist/lib/testing/storyboard/context.mjs +12 -6
- package/dist/lib/testing/storyboard/fixture-resolution.d.mts +39 -1
- package/dist/lib/testing/storyboard/fixture-resolution.d.ts +39 -1
- package/dist/lib/testing/storyboard/fixture-resolution.js +216 -12
- package/dist/lib/testing/storyboard/fixture-resolution.mjs +218 -12
- package/dist/lib/testing/storyboard/index.d.mts +9 -2
- package/dist/lib/testing/storyboard/index.d.ts +9 -2
- package/dist/lib/testing/storyboard/index.js +51 -2
- package/dist/lib/testing/storyboard/index.mjs +49 -1
- package/dist/lib/testing/storyboard/prepared-fixtures.d.mts +471 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.d.ts +471 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.js +434 -0
- package/dist/lib/testing/storyboard/prepared-fixtures.mjs +389 -0
- package/dist/lib/testing/storyboard/protected-context.d.mts +127 -0
- package/dist/lib/testing/storyboard/protected-context.d.ts +127 -0
- package/dist/lib/testing/storyboard/protected-context.js +301 -0
- package/dist/lib/testing/storyboard/protected-context.mjs +267 -0
- package/dist/lib/testing/storyboard/rejection-hints.js +13 -4
- package/dist/lib/testing/storyboard/rejection-hints.mjs +13 -4
- package/dist/lib/testing/storyboard/runner.d.mts +24 -0
- package/dist/lib/testing/storyboard/runner.d.ts +24 -0
- package/dist/lib/testing/storyboard/runner.js +1061 -105
- package/dist/lib/testing/storyboard/runner.mjs +1075 -106
- package/dist/lib/testing/storyboard/seeding.d.mts +15 -1
- package/dist/lib/testing/storyboard/seeding.d.ts +15 -1
- package/dist/lib/testing/storyboard/seeding.js +272 -12
- package/dist/lib/testing/storyboard/seeding.mjs +274 -13
- package/dist/lib/testing/storyboard/types.d.mts +207 -10
- package/dist/lib/testing/storyboard/types.d.ts +207 -10
- package/dist/lib/testing/storyboard/types.js +1 -1
- package/dist/lib/testing/storyboard/types.mjs +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.js +95 -0
- package/dist/lib/testing/storyboard/validations.mjs +95 -0
- package/dist/lib/validation/bundled-schema-store.js +5 -0
- package/dist/lib/validation/bundled-schema-store.mjs +4 -0
- package/dist/lib/validation/schema-loader.js +19 -2
- package/dist/lib/validation/schema-loader.mjs +22 -3
- 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/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/COLLECTION-FIXTURE-FOUNDATION.md +850 -0
- package/docs/guides/PROPOSAL-TERMS-VERIFICATION.md +66 -0
- package/docs/llms.txt +4 -3
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { randomUUID, scryptSync } from "node:crypto";
|
|
22
22
|
const SKIP_PRODUCT_CACHE = /* @__PURE__ */ Symbol("adcp.skipProductCache");
|
|
23
23
|
const SKIP_ACCOUNT_REGISTRY_OBSERVATION = /* @__PURE__ */ Symbol("adcp.skipAccountRegistryObservation");
|
|
24
|
+
import { accountKeySites, naturalAccountKey, reducedFields, valueAt, withReducedKeyAt } from "./account-reduction.mjs";
|
|
24
25
|
import { ADCP_ENVELOPE_FIELDS } from "../types/adcp.mjs";
|
|
25
26
|
import { parseAdcpMajorVersion, toReleasePrecisionVersion } from "../version.mjs";
|
|
26
27
|
import {
|
|
@@ -31,8 +32,20 @@ import {
|
|
|
31
32
|
resolveAdcpVersion
|
|
32
33
|
} from "../utils/adcp-version-config.mjs";
|
|
33
34
|
import { beta6ReportingRequestIssue } from "../media-buy/reporting-version.mjs";
|
|
34
|
-
import {
|
|
35
|
-
|
|
35
|
+
import {
|
|
36
|
+
convertRequest,
|
|
37
|
+
convertResponse,
|
|
38
|
+
getVersionAdapter,
|
|
39
|
+
isNegotiationFailure,
|
|
40
|
+
negotiateAdcpRelease,
|
|
41
|
+
releaseDefinesTool,
|
|
42
|
+
resolveAdapterKey
|
|
43
|
+
} from "../adapters/version/index.mjs";
|
|
44
|
+
import {
|
|
45
|
+
isExternalSchemaRootActive,
|
|
46
|
+
schemaAllowsTopLevelField,
|
|
47
|
+
toReleasePrecisionWire
|
|
48
|
+
} from "../validation/schema-loader.mjs";
|
|
36
49
|
import { generateIdempotencyKey, requestUsesIdempotency } from "../utils/idempotency.mjs";
|
|
37
50
|
import { createA2AClientFromCardUrl } from "../protocols/a2a.mjs";
|
|
38
51
|
import {
|
|
@@ -372,8 +385,9 @@ function creativeMatchesProductOption(creative, declaration) {
|
|
|
372
385
|
function isDeferredClientFinalizationContext(value) {
|
|
373
386
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
374
387
|
const context = value;
|
|
375
|
-
return context.kind === "single-agent" && typeof context.taskType === "string" && typeof context.canonical === "boolean" && !!context.productPolicyRequest && typeof context.productPolicyRequest === "object" && !Array.isArray(context.productPolicyRequest) && (context.serverVersion === void 0 || context.serverVersion === "v2" || context.serverVersion === "v3") && (context.serverVersionSynthetic === void 0 || typeof context.serverVersionSynthetic === "boolean") && (context.projectionCatalogs === void 0 || Array.isArray(context.projectionCatalogs)) && (context.handlerName === void 0 || typeof context.handlerName === "string") && (context.skipStatusHandlers === void 0 || typeof context.skipStatusHandlers === "boolean");
|
|
388
|
+
return context.kind === "single-agent" && typeof context.taskType === "string" && typeof context.canonical === "boolean" && !!context.productPolicyRequest && typeof context.productPolicyRequest === "object" && !Array.isArray(context.productPolicyRequest) && (context.serverVersion === void 0 || context.serverVersion === "v2" || context.serverVersion === "v3") && (context.serverVersionSynthetic === void 0 || typeof context.serverVersionSynthetic === "boolean") && (context.negotiatedAdcpVersion === void 0 || typeof context.negotiatedAdcpVersion === "string") && (context.projectionCatalogs === void 0 || Array.isArray(context.projectionCatalogs)) && (context.handlerName === void 0 || typeof context.handlerName === "string") && (context.skipStatusHandlers === void 0 || typeof context.skipStatusHandlers === "boolean");
|
|
376
389
|
}
|
|
390
|
+
const MAX_REMEMBERED_NEGOTIATED_RELEASES = 1024;
|
|
377
391
|
const CANONICAL_PACKAGE_ROUTE_TASKS = /* @__PURE__ */ new Set(["create_media_buy", "update_media_buy", "get_media_buys"]);
|
|
378
392
|
const canonicalCreativeRoutingSnapshots = /* @__PURE__ */ new WeakSet();
|
|
379
393
|
function canonicalAccountRoutingSnapshot(value) {
|
|
@@ -919,6 +933,12 @@ class SingleAgentClient {
|
|
|
919
933
|
this.resolvedAdcpVersion = resolveAdcpVersion(
|
|
920
934
|
config.adcpVersion ?? (config.experimentalIdentity33 ? "3.3" : void 0)
|
|
921
935
|
);
|
|
936
|
+
if (config.accountIdentityDowngrade === "reduce" && typeof config.accountStorage?.compareAndSet !== "function") {
|
|
937
|
+
throw new ConfigurationError(
|
|
938
|
+
"accountIdentityDowngrade: 'reduce' requires accountStorage with compareAndSet. Reduced account keys are claimed in that storage so that no two buyer accounts reach one seller account, across instances and restarts. Configure durable accountStorage that implements compareAndSet, or use 'refuse'.",
|
|
939
|
+
"accountIdentityDowngrade"
|
|
940
|
+
);
|
|
941
|
+
}
|
|
922
942
|
this.webhookRegistrationStore = config.webhookRegistrationStore ?? new InMemoryWebhookRegistrationStore();
|
|
923
943
|
this.webhookReplayStore = config.webhookVerification?.replayStore ?? new InMemoryReplayStore();
|
|
924
944
|
this.webhookRevocationStore = config.webhookVerification?.revocationStore ?? new InMemoryRevocationStore();
|
|
@@ -1239,6 +1259,8 @@ class SingleAgentClient {
|
|
|
1239
1259
|
runAgentInfo;
|
|
1240
1260
|
cachedToolSchemas;
|
|
1241
1261
|
// inputSchema.properties per tool name
|
|
1262
|
+
/** Release negotiated per operation, for converting webhook completions up. */
|
|
1263
|
+
negotiatedReleaseByOperation = /* @__PURE__ */ new Map();
|
|
1242
1264
|
primedCapabilitiesExpiresAt;
|
|
1243
1265
|
// Freshness bound for application-owned evidence only
|
|
1244
1266
|
capabilityEvidenceScopeKey = randomUUID();
|
|
@@ -2002,6 +2024,19 @@ class SingleAgentClient {
|
|
|
2002
2024
|
getWireAdcpVersion() {
|
|
2003
2025
|
return this.config.wireAdcpVersion ?? this.resolvedAdcpVersion;
|
|
2004
2026
|
}
|
|
2027
|
+
/** @internal Read only current, auth-scoped actual discovery evidence; never fetch. */
|
|
2028
|
+
getCachedServedAdcpVersion(options) {
|
|
2029
|
+
this.synchronizeCapabilityEvidenceAuthorizationScope();
|
|
2030
|
+
if (this.usesScopedDiscoveryTransport(options)) return void 0;
|
|
2031
|
+
if (this.primedCapabilitiesExpiresAt !== void 0 && this.primedCapabilitiesExpiresAt <= Date.now())
|
|
2032
|
+
return void 0;
|
|
2033
|
+
if (this.config.discoveryCache && this.cachedCapabilities) {
|
|
2034
|
+
const key = this.sharedDiscoveryKey(options);
|
|
2035
|
+
if (this.sharedEvidenceKey !== key || key !== void 0 && this.sharedEvidenceEpoch !== void 0 && this.sharedEvidenceEpoch !== this.sharedInvalidationEpoch(key))
|
|
2036
|
+
return void 0;
|
|
2037
|
+
}
|
|
2038
|
+
return this.cachedCapabilities?._synthetic === false ? this.cachedCapabilities.servedVersion : void 0;
|
|
2039
|
+
}
|
|
2005
2040
|
/**
|
|
2006
2041
|
* Ensure MCP endpoint is discovered (lazy initialization)
|
|
2007
2042
|
*
|
|
@@ -3035,7 +3070,11 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3035
3070
|
let externalStatus;
|
|
3036
3071
|
let forgetPolicyState = false;
|
|
3037
3072
|
try {
|
|
3038
|
-
const canonicalResult = this.canonicalizeWebhookCreativeResult(
|
|
3073
|
+
const canonicalResult = this.canonicalizeWebhookCreativeResult(
|
|
3074
|
+
metadata,
|
|
3075
|
+
this.convertWebhookResultToClientRelease(parsed),
|
|
3076
|
+
canonicalCreativeTask
|
|
3077
|
+
);
|
|
3039
3078
|
const dedupResult = canonicalResult;
|
|
3040
3079
|
const dedupMetadata = { ...metadata };
|
|
3041
3080
|
let webhookResult = dedupResult;
|
|
@@ -3616,32 +3655,47 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3616
3655
|
};
|
|
3617
3656
|
const serverVersion = await this.detectServerVersion(detectionOptions);
|
|
3618
3657
|
throwIfAborted(options?.signal);
|
|
3658
|
+
const negotiatedRelease = this.negotiateCallRelease(capabilityDiscoveryContext.capabilities, options);
|
|
3659
|
+
this.assertToolAvailableAtRelease(taskType, negotiatedRelease, capabilityDiscoveryContext.toolSchemas);
|
|
3619
3660
|
this.assertRequestSupportedByTargetVersion(
|
|
3620
3661
|
taskType,
|
|
3621
3662
|
normalizedParams,
|
|
3622
3663
|
capabilityDiscoveryContext.capabilities,
|
|
3623
3664
|
canonicalCreativeInvocation,
|
|
3624
|
-
serverVersion
|
|
3665
|
+
serverVersion,
|
|
3666
|
+
negotiatedRelease
|
|
3625
3667
|
);
|
|
3626
|
-
const { options:
|
|
3668
|
+
const { options: webhookOptions, driftLog: webhookDriftLog } = this.suppressPre31DiscoveryWebhook(
|
|
3627
3669
|
taskType,
|
|
3628
3670
|
options,
|
|
3629
3671
|
capabilityDiscoveryContext.capabilities
|
|
3630
3672
|
);
|
|
3673
|
+
const effectiveOptions = this.withNegotiatedRelease(webhookOptions, negotiatedRelease);
|
|
3631
3674
|
const inputSchemaStripLogs = [];
|
|
3632
3675
|
if (options?.preserveGovernedPayload && serverVersion !== "v3") {
|
|
3633
3676
|
throw new ConfigurationError(
|
|
3634
3677
|
"Governed storyboard requests require a v3 seller to preserve the approved payload."
|
|
3635
3678
|
);
|
|
3636
3679
|
}
|
|
3637
|
-
const { params:
|
|
3680
|
+
const { params: convertedParams, driftLogs: adaptDriftLogs } = options?.preserveGovernedPayload ? { params: normalizedParams, driftLogs: [] } : this.adaptRequest(
|
|
3638
3681
|
taskType,
|
|
3639
3682
|
normalizedParams,
|
|
3640
3683
|
serverVersion,
|
|
3641
3684
|
inputSchemaStripLogs,
|
|
3642
3685
|
capabilityDiscoveryContext.toolSchemas,
|
|
3643
|
-
capabilityDiscoveryContext.capabilities
|
|
3686
|
+
capabilityDiscoveryContext.capabilities,
|
|
3687
|
+
negotiatedRelease
|
|
3688
|
+
);
|
|
3689
|
+
const adaptedParams = options?.preserveGovernedPayload ? convertedParams : await this.reconcileAccountKeyReductions(
|
|
3690
|
+
taskType,
|
|
3691
|
+
normalizedParams,
|
|
3692
|
+
convertedParams,
|
|
3693
|
+
negotiatedRelease,
|
|
3694
|
+
adaptDriftLogs
|
|
3644
3695
|
);
|
|
3696
|
+
if (negotiatedRelease?.downgraded && !options?.skipIdempotencyAutoInject && !options?.skipAccountValidation && !options?.skipRequestValidation) {
|
|
3697
|
+
this.executor.validateRequest(taskType, adaptedParams, inputSchemaStripLogs, negotiatedRelease.version);
|
|
3698
|
+
}
|
|
3645
3699
|
const adaptationLogs = [...adaptDriftLogs];
|
|
3646
3700
|
if (webhookDriftLog) adaptationLogs.push(webhookDriftLog);
|
|
3647
3701
|
const canonicalInputHandler = this.canonicalCreativeInputHandler(
|
|
@@ -3659,6 +3713,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3659
3713
|
...capabilityDiscoveryContext.capabilities?._synthetic !== void 0 && {
|
|
3660
3714
|
serverVersionSynthetic: capabilityDiscoveryContext.capabilities._synthetic
|
|
3661
3715
|
},
|
|
3716
|
+
...negotiatedRelease?.downgraded && { negotiatedAdcpVersion: negotiatedRelease.version },
|
|
3662
3717
|
productPolicyRequest: productPolicyRequestSnapshot(normalizedParams),
|
|
3663
3718
|
accountRegistry: this.accountRegistryContext(taskType, normalizedParams, effectiveOptions),
|
|
3664
3719
|
...projectionCatalogs !== void 0 && { projectionCatalogs },
|
|
@@ -3726,6 +3781,21 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3726
3781
|
}
|
|
3727
3782
|
};
|
|
3728
3783
|
}
|
|
3784
|
+
if (context.negotiatedAdcpVersion !== void 0) {
|
|
3785
|
+
result.metadata = { ...result.metadata, negotiatedAdcpVersion: context.negotiatedAdcpVersion };
|
|
3786
|
+
if (result.metadata.taskId) this.rememberNegotiatedRelease(result.metadata.taskId, context.negotiatedAdcpVersion);
|
|
3787
|
+
if (result.success && result.data) {
|
|
3788
|
+
const converted = this.convertResponseToClientRelease(
|
|
3789
|
+
context.taskType,
|
|
3790
|
+
result.data,
|
|
3791
|
+
context.negotiatedAdcpVersion
|
|
3792
|
+
);
|
|
3793
|
+
result.data = converted.data;
|
|
3794
|
+
if (converted.driftLogs.length > 0) {
|
|
3795
|
+
result.debug_logs = [...result.debug_logs ?? [], ...converted.driftLogs];
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3729
3799
|
const completionHandlerAlreadyPublished = hasCompletionHandlerAlreadyPublished(result);
|
|
3730
3800
|
const settlementAcknowledger = result[DEFERRED_SETTLEMENT_ACK];
|
|
3731
3801
|
const taskType = context.taskType;
|
|
@@ -4710,6 +4780,228 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4710
4780
|
suppressHandler: !policyResult.success
|
|
4711
4781
|
};
|
|
4712
4782
|
}
|
|
4783
|
+
get accountIdentityDowngrade() {
|
|
4784
|
+
return this.config.accountIdentityDowngrade ?? "refuse";
|
|
4785
|
+
}
|
|
4786
|
+
/**
|
|
4787
|
+
* Negotiate the AdCP release to speak with this seller for one call: the
|
|
4788
|
+
* highest release both sides support. Returns `undefined` when the call
|
|
4789
|
+
* keeps its configured wire version: an explicit `wireAdcpVersion`
|
|
4790
|
+
* override, a governed payload that must reach the seller byte-for-byte,
|
|
4791
|
+
* the identity 3.3 experiment, or no authoritative seller release
|
|
4792
|
+
* (synthetic capabilities, no release in common, or no release metadata at
|
|
4793
|
+
* all: AdCP 3.1 does not require `supported_versions`, so its absence does
|
|
4794
|
+
* not prove a 3.0 seller, and such sellers keep the 3.0 request adapters).
|
|
4795
|
+
*/
|
|
4796
|
+
negotiateCallRelease(capabilities, options) {
|
|
4797
|
+
if (this.config.wireAdcpVersion !== void 0 || options?.wireAdcpVersion !== void 0) return void 0;
|
|
4798
|
+
if (options?.preserveGovernedPayload || this.config.experimentalIdentity33) return void 0;
|
|
4799
|
+
const negotiated = negotiateAdcpRelease(this.resolvedAdcpVersion, capabilities);
|
|
4800
|
+
if (!negotiated || isNegotiationFailure(negotiated) || negotiated.source === "legacy_v3") return void 0;
|
|
4801
|
+
return negotiated;
|
|
4802
|
+
}
|
|
4803
|
+
/**
|
|
4804
|
+
* Per-call options carrying the negotiated release to the executor, which
|
|
4805
|
+
* stamps it on the version envelope and validates the response against it.
|
|
4806
|
+
*/
|
|
4807
|
+
withNegotiatedRelease(options, negotiated) {
|
|
4808
|
+
if (!negotiated?.downgraded) return options;
|
|
4809
|
+
return { ...options ?? {}, wireAdcpVersion: negotiated.version, negotiatedAdcpVersion: negotiated.version };
|
|
4810
|
+
}
|
|
4811
|
+
/**
|
|
4812
|
+
* Refuse a tool the negotiated release does not define (a 3.2-only task
|
|
4813
|
+
* sent to a 3.1 seller) with a typed error instead of a seller-side schema
|
|
4814
|
+
* or unknown-tool failure. Sellers that list the tool anyway are called.
|
|
4815
|
+
*/
|
|
4816
|
+
assertToolAvailableAtRelease(taskType, negotiated, toolSchemas) {
|
|
4817
|
+
if (!negotiated?.downgraded) return;
|
|
4818
|
+
if (isExternalSchemaRootActive(negotiated.version)) return;
|
|
4819
|
+
if (releaseDefinesTool(taskType, negotiated.version)) return;
|
|
4820
|
+
if (!releaseDefinesTool(taskType, this.resolvedAdcpVersion)) return;
|
|
4821
|
+
if ((toolSchemas ?? this.cachedToolSchemas)?.has(taskType)) return;
|
|
4822
|
+
const suggestion = `Call a task AdCP ${negotiated.version} defines, or reach this seller once it supports AdCP ${toReleasePrecisionWire(this.resolvedAdcpVersion)}.`;
|
|
4823
|
+
throw new ProtocolFeatureUnsupportedError([taskType], [], this.agent.agent_uri, {
|
|
4824
|
+
message: `${taskType} is not defined in AdCP ${negotiated.version}, the newest release this seller supports. No request was sent. ${suggestion}`,
|
|
4825
|
+
suggestion,
|
|
4826
|
+
details: {
|
|
4827
|
+
feature: taskType,
|
|
4828
|
+
required_version: toReleasePrecisionWire(this.resolvedAdcpVersion),
|
|
4829
|
+
capability_path: "adcp.supported_versions",
|
|
4830
|
+
current_version: negotiated.version,
|
|
4831
|
+
tool: taskType
|
|
4832
|
+
}
|
|
4833
|
+
});
|
|
4834
|
+
}
|
|
4835
|
+
/**
|
|
4836
|
+
* Account-key bookkeeping for `accountIdentityDowngrade: 'reduce'`.
|
|
4837
|
+
*
|
|
4838
|
+
* Converting down to an older seller release: claim each reduced key for
|
|
4839
|
+
* the buyer key it came from, and refuse the request when the reduced key
|
|
4840
|
+
* (or an unreduced key the request sends as is) already belongs to a
|
|
4841
|
+
* different buyer key. Without this, two buyer accounts would silently
|
|
4842
|
+
* share one seller account, with merged settings, spend and reads.
|
|
4843
|
+
*
|
|
4844
|
+
* Seller on the client's release: a buyer key that earlier reached this
|
|
4845
|
+
* seller reduced is still addressed by its reduced key, which is the key
|
|
4846
|
+
* the seller's account has, until the caller moves the account to the full
|
|
4847
|
+
* key and calls `client.accounts.clearReduction(key)`.
|
|
4848
|
+
*
|
|
4849
|
+
* Runs only once the account registry is in use or under `'reduce'`.
|
|
4850
|
+
*/
|
|
4851
|
+
async reconcileAccountKeyReductions(taskType, original, adapted, negotiated, driftLogs) {
|
|
4852
|
+
if (this.accountIdentityDowngrade !== "reduce" && !this._accounts) return adapted;
|
|
4853
|
+
const sites = accountKeySites(original);
|
|
4854
|
+
if (sites.length === 0) return adapted;
|
|
4855
|
+
const registry = this.getAccountRegistry();
|
|
4856
|
+
if (negotiated?.downgraded) {
|
|
4857
|
+
if (this.accountIdentityDowngrade !== "reduce") return adapted;
|
|
4858
|
+
const claims = sites.flatMap((site) => {
|
|
4859
|
+
const reduced = naturalAccountKey(valueAt(adapted, site.path));
|
|
4860
|
+
return reduced ? [{ site, account: site.key, reduced, adcpVersion: negotiated.version }] : [];
|
|
4861
|
+
});
|
|
4862
|
+
const conflict = await registry.claimReductions(claims);
|
|
4863
|
+
if (conflict) {
|
|
4864
|
+
this.throwAccountKeyCollision(taskType, claims[conflict.index].site.path, conflict.owner, negotiated.version);
|
|
4865
|
+
}
|
|
4866
|
+
return adapted;
|
|
4867
|
+
}
|
|
4868
|
+
let rewritten = adapted;
|
|
4869
|
+
const pending = [];
|
|
4870
|
+
for (const site of sites) {
|
|
4871
|
+
const reduction = await registry.reductionFor(site.key);
|
|
4872
|
+
if (!reduction) continue;
|
|
4873
|
+
rewritten = withReducedKeyAt(rewritten, site.path, reduction.account);
|
|
4874
|
+
pending.push({
|
|
4875
|
+
path: site.path.join("."),
|
|
4876
|
+
fields: reducedFields(site.key, reduction.account),
|
|
4877
|
+
adcpVersion: reduction.adcpVersion
|
|
4878
|
+
});
|
|
4879
|
+
}
|
|
4880
|
+
if (pending.length > 0) {
|
|
4881
|
+
const inPlace = pending.every((entry) => entry.fields.every((field) => field === "operator_unit"));
|
|
4882
|
+
driftLogs.push({
|
|
4883
|
+
type: "account_identity_migration_pending",
|
|
4884
|
+
message: `${taskType}: addressed ${pending.map((entry) => entry.path).join(", ")} by the reduced account key this seller has, without ${[...new Set(pending.flatMap((entry) => entry.fields))].join(", ")}. ` + (inPlace ? "Rekey the account in place with a sync_accounts settings update (account, operator_identity, revision), " : "currency, timezone and brand.countries cannot change on an existing account, so open a new account under the full key (and decide which key keeps the existing history), ") + "then call client.accounts.clearReduction(key).",
|
|
4885
|
+
accounts: pending,
|
|
4886
|
+
taskName: taskType,
|
|
4887
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4890
|
+
return rewritten;
|
|
4891
|
+
}
|
|
4892
|
+
throwAccountKeyCollision(taskType, path, owner, negotiatedVersion) {
|
|
4893
|
+
const field = path.join(".");
|
|
4894
|
+
const suggestion = `Reach this seller with one of the two account keys, address the account by account_id, or wait until the seller supports the release that tells them apart.`;
|
|
4895
|
+
throw new ProtocolFeatureUnsupportedError([`${taskType}.${field}`], [], this.agent.agent_uri, {
|
|
4896
|
+
message: `${taskType} ${field} would reach the same seller account as another of this buyer's account keys: AdCP ${negotiatedVersion} cannot tell them apart. No request was sent. ${suggestion}`,
|
|
4897
|
+
field,
|
|
4898
|
+
suggestion,
|
|
4899
|
+
details: {
|
|
4900
|
+
feature: `${taskType}.${field}`,
|
|
4901
|
+
reason: "account_identity_collision",
|
|
4902
|
+
current_version: negotiatedVersion,
|
|
4903
|
+
tool: taskType,
|
|
4904
|
+
field,
|
|
4905
|
+
conflicting_account: owner
|
|
4906
|
+
}
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
throwFieldsUnsupportedAtRelease(taskType, fields, negotiatedVersion) {
|
|
4910
|
+
const [first] = fields;
|
|
4911
|
+
const paths = fields.map((field) => field.path);
|
|
4912
|
+
const accountMove = paths.some((path) => /(?:^|\.)(?:operator_identity|revision)$/.test(path));
|
|
4913
|
+
const suggestion = accountMove ? `AdCP ${negotiatedVersion} cannot rekey an account or hand it to another operator (operator_identity, revision). Make the move once the seller supports AdCP ${first.introducedIn}; until then the account keeps its current key and operator.` : `Remove ${paths.join(", ")} for this seller, or reach it once it supports AdCP ${first.introducedIn}. Sending the request without them would change what the seller does.`;
|
|
4914
|
+
throw new ProtocolFeatureUnsupportedError(
|
|
4915
|
+
paths.map((path) => `${taskType}.${path}`),
|
|
4916
|
+
[],
|
|
4917
|
+
this.agent.agent_uri,
|
|
4918
|
+
{
|
|
4919
|
+
message: `${taskType} ${paths.join(", ")} ${paths.length === 1 ? "requires" : "require"} AdCP ${first.introducedIn}; this seller supports AdCP ${negotiatedVersion}. No request was sent. ${suggestion}`,
|
|
4920
|
+
field: first.path,
|
|
4921
|
+
suggestion,
|
|
4922
|
+
details: {
|
|
4923
|
+
feature: `${taskType}.${first.path}`,
|
|
4924
|
+
required_version: first.introducedIn,
|
|
4925
|
+
capability_path: "adcp.supported_versions",
|
|
4926
|
+
current_version: negotiatedVersion,
|
|
4927
|
+
tool: taskType,
|
|
4928
|
+
field: first.path,
|
|
4929
|
+
fields: paths
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
);
|
|
4933
|
+
}
|
|
4934
|
+
throwAccountIdentityUnsupported(taskType, fields, negotiatedVersion) {
|
|
4935
|
+
const [first] = fields;
|
|
4936
|
+
const paths = fields.map((field) => field.path);
|
|
4937
|
+
const suggestion = `Set accountIdentityDowngrade: 'reduce' to send the older account key (allowed while no other buyer key reaches the same seller account without ${paths.join(", ")}), or remove those fields for this seller.`;
|
|
4938
|
+
throw new ProtocolFeatureUnsupportedError(
|
|
4939
|
+
paths.map((path) => `${taskType}.${path}`),
|
|
4940
|
+
[],
|
|
4941
|
+
this.agent.agent_uri,
|
|
4942
|
+
{
|
|
4943
|
+
message: `${taskType} ${paths.join(", ")} ${paths.length === 1 ? "is" : "are"} part of the AdCP ${first.introducedIn} account key, which AdCP ${negotiatedVersion} cannot express. No request was sent. ${suggestion}`,
|
|
4944
|
+
field: first.path,
|
|
4945
|
+
suggestion,
|
|
4946
|
+
details: {
|
|
4947
|
+
feature: `${taskType}.${first.path}`,
|
|
4948
|
+
required_version: first.introducedIn,
|
|
4949
|
+
capability_path: "adcp.supported_versions",
|
|
4950
|
+
current_version: negotiatedVersion,
|
|
4951
|
+
tool: taskType,
|
|
4952
|
+
field: first.path,
|
|
4953
|
+
fields: paths
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4956
|
+
);
|
|
4957
|
+
}
|
|
4958
|
+
rememberNegotiatedRelease(operationId, version) {
|
|
4959
|
+
this.negotiatedReleaseByOperation.delete(operationId);
|
|
4960
|
+
this.negotiatedReleaseByOperation.set(operationId, version);
|
|
4961
|
+
if (this.negotiatedReleaseByOperation.size > MAX_REMEMBERED_NEGOTIATED_RELEASES) {
|
|
4962
|
+
const oldest = this.negotiatedReleaseByOperation.keys().next().value;
|
|
4963
|
+
if (oldest !== void 0) this.negotiatedReleaseByOperation.delete(oldest);
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
/**
|
|
4967
|
+
* Webhook completions bypass task finalization, so convert their result up
|
|
4968
|
+
* here. The seller's own `adcp_version` names the release it served; an
|
|
4969
|
+
* AdCP 3.0 seller sends none, so fall back to the release this client
|
|
4970
|
+
* negotiated for the operation.
|
|
4971
|
+
*/
|
|
4972
|
+
convertWebhookResultToClientRelease(parsed) {
|
|
4973
|
+
const served = [parsed.result, parsed.envelope].map(
|
|
4974
|
+
(value) => value && typeof value === "object" && typeof value.adcp_version === "string" ? value.adcp_version : void 0
|
|
4975
|
+
).find((version) => version !== void 0);
|
|
4976
|
+
const release = served ?? this.negotiatedReleaseByOperation.get(parsed.metadata.operationId);
|
|
4977
|
+
if (release === void 0 || parsed.result === void 0 || parsed.result === null) return parsed.result;
|
|
4978
|
+
return convertResponse(parsed.metadata.taskType, parsed.result, {
|
|
4979
|
+
fromVersion: release,
|
|
4980
|
+
toVersion: this.resolvedAdcpVersion
|
|
4981
|
+
}).data;
|
|
4982
|
+
}
|
|
4983
|
+
/**
|
|
4984
|
+
* Convert a response served at the negotiated release up to the client's
|
|
4985
|
+
* release. Returns drift entries for each conversion applied.
|
|
4986
|
+
*/
|
|
4987
|
+
convertResponseToClientRelease(taskType, data, negotiatedVersion) {
|
|
4988
|
+
if (negotiatedVersion === void 0 || data === void 0 || data === null) return { data, driftLogs: [] };
|
|
4989
|
+
const translation = convertResponse(taskType, data, {
|
|
4990
|
+
fromVersion: negotiatedVersion,
|
|
4991
|
+
toVersion: this.resolvedAdcpVersion
|
|
4992
|
+
});
|
|
4993
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4994
|
+
return {
|
|
4995
|
+
data: translation.data,
|
|
4996
|
+
driftLogs: translation.drifts.map((drift) => ({
|
|
4997
|
+
...drift,
|
|
4998
|
+
taskName: taskType,
|
|
4999
|
+
clientVersion: this.resolvedAdcpVersion,
|
|
5000
|
+
targetVersion: negotiatedVersion,
|
|
5001
|
+
timestamp
|
|
5002
|
+
}))
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
4713
5005
|
/**
|
|
4714
5006
|
* Adapt a request for the detected server wire version and the seller's
|
|
4715
5007
|
* AdCP protocol version. Applies protocol-version adapters (e.g. stripping
|
|
@@ -4719,7 +5011,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4719
5011
|
* Runs after `detectServerVersion` so capabilities are available and the
|
|
4720
5012
|
* current call's tool schemas can be supplied without cross-tenant caching.
|
|
4721
5013
|
*/
|
|
4722
|
-
adaptRequest(taskType, params, serverVersion, debugLogs, perCallToolSchemas, perCallCapabilities) {
|
|
5014
|
+
adaptRequest(taskType, params, serverVersion, debugLogs, perCallToolSchemas, perCallCapabilities, negotiated) {
|
|
4723
5015
|
if (serverVersion !== "v3") {
|
|
4724
5016
|
throw new VersionUnsupportedError(taskType, "version", "v2", this.agent.agent_uri);
|
|
4725
5017
|
}
|
|
@@ -4756,10 +5048,34 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4756
5048
|
}
|
|
4757
5049
|
adapted = filtered;
|
|
4758
5050
|
}
|
|
5051
|
+
if (negotiated?.downgraded) {
|
|
5052
|
+
const translation = convertRequest(taskType, adapted, {
|
|
5053
|
+
fromVersion: this.resolvedAdcpVersion,
|
|
5054
|
+
toVersion: negotiated.version,
|
|
5055
|
+
accountIdentity: this.accountIdentityDowngrade
|
|
5056
|
+
});
|
|
5057
|
+
if (translation.identityFields.length > 0 && this.accountIdentityDowngrade === "refuse") {
|
|
5058
|
+
this.throwAccountIdentityUnsupported(taskType, translation.identityFields, negotiated.version);
|
|
5059
|
+
}
|
|
5060
|
+
if (translation.refusedFields.length > 0) {
|
|
5061
|
+
this.throwFieldsUnsupportedAtRelease(taskType, translation.refusedFields, negotiated.version);
|
|
5062
|
+
}
|
|
5063
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
5064
|
+
for (const drift of translation.drifts) {
|
|
5065
|
+
driftLogs.push({
|
|
5066
|
+
...drift,
|
|
5067
|
+
taskName: taskType,
|
|
5068
|
+
clientVersion: this.resolvedAdcpVersion,
|
|
5069
|
+
targetVersion: negotiated.version,
|
|
5070
|
+
timestamp
|
|
5071
|
+
});
|
|
5072
|
+
}
|
|
5073
|
+
return { params: translation.params, driftLogs };
|
|
5074
|
+
}
|
|
4759
5075
|
const adapterKey = resolveAdapterKey(this.resolvedAdcpVersion, perCallCapabilities ?? this.cachedCapabilities);
|
|
4760
5076
|
if (adapterKey) {
|
|
4761
5077
|
const versionAdapter = getVersionAdapter(adapterKey, taskType);
|
|
4762
|
-
if (versionAdapter) {
|
|
5078
|
+
if (versionAdapter?.adaptRequest) {
|
|
4763
5079
|
const result = versionAdapter.adaptRequest(adapted);
|
|
4764
5080
|
adapted = result.params;
|
|
4765
5081
|
if (result.drift) {
|
|
@@ -6378,32 +6694,47 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
6378
6694
|
const serverVersion = await this.detectServerVersion(detectionOptions);
|
|
6379
6695
|
detectedServerVersion = serverVersion;
|
|
6380
6696
|
detectedServerVersionSynthetic = capabilityDiscoveryContext.capabilities?._synthetic;
|
|
6697
|
+
const negotiatedRelease = this.negotiateCallRelease(capabilityDiscoveryContext.capabilities, options);
|
|
6698
|
+
this.assertToolAvailableAtRelease(taskName, negotiatedRelease, capabilityDiscoveryContext.toolSchemas);
|
|
6381
6699
|
this.assertRequestSupportedByTargetVersion(
|
|
6382
6700
|
taskName,
|
|
6383
6701
|
normalizedParams,
|
|
6384
6702
|
capabilityDiscoveryContext.capabilities,
|
|
6385
6703
|
false,
|
|
6386
|
-
serverVersion
|
|
6704
|
+
serverVersion,
|
|
6705
|
+
negotiatedRelease
|
|
6387
6706
|
);
|
|
6388
|
-
const { options:
|
|
6707
|
+
const { options: webhookOptions, driftLog: webhookDriftLog } = this.suppressPre31DiscoveryWebhook(
|
|
6389
6708
|
taskName,
|
|
6390
6709
|
options,
|
|
6391
6710
|
capabilityDiscoveryContext.capabilities
|
|
6392
6711
|
);
|
|
6712
|
+
const effectiveOptions = this.withNegotiatedRelease(webhookOptions, negotiatedRelease);
|
|
6393
6713
|
const inputSchemaStripLogs = [];
|
|
6394
6714
|
if (options?.preserveGovernedPayload && serverVersion !== "v3") {
|
|
6395
6715
|
throw new ConfigurationError(
|
|
6396
6716
|
"Governed storyboard requests require a v3 seller to preserve the approved payload."
|
|
6397
6717
|
);
|
|
6398
6718
|
}
|
|
6399
|
-
const { params:
|
|
6719
|
+
const { params: convertedParams, driftLogs: adaptDriftLogs } = options?.preserveGovernedPayload ? { params: normalizedParams, driftLogs: [] } : this.adaptRequest(
|
|
6400
6720
|
taskName,
|
|
6401
6721
|
normalizedParams,
|
|
6402
6722
|
serverVersion,
|
|
6403
6723
|
inputSchemaStripLogs,
|
|
6404
6724
|
capabilityDiscoveryContext.toolSchemas,
|
|
6405
|
-
capabilityDiscoveryContext.capabilities
|
|
6725
|
+
capabilityDiscoveryContext.capabilities,
|
|
6726
|
+
negotiatedRelease
|
|
6727
|
+
);
|
|
6728
|
+
const adaptedParams = options?.preserveGovernedPayload ? convertedParams : await this.reconcileAccountKeyReductions(
|
|
6729
|
+
taskName,
|
|
6730
|
+
normalizedParams,
|
|
6731
|
+
convertedParams,
|
|
6732
|
+
negotiatedRelease,
|
|
6733
|
+
adaptDriftLogs
|
|
6406
6734
|
);
|
|
6735
|
+
if (negotiatedRelease?.downgraded && !options?.skipIdempotencyAutoInject && !options?.skipAccountValidation && !options?.skipRequestValidation) {
|
|
6736
|
+
this.executor.validateRequest(taskName, adaptedParams, inputSchemaStripLogs, negotiatedRelease.version);
|
|
6737
|
+
}
|
|
6407
6738
|
const adaptationLogs = [...adaptDriftLogs];
|
|
6408
6739
|
if (webhookDriftLog) adaptationLogs.push(webhookDriftLog);
|
|
6409
6740
|
const deferredClientContext = {
|
|
@@ -6415,6 +6746,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
6415
6746
|
...capabilityDiscoveryContext.capabilities?._synthetic !== void 0 && {
|
|
6416
6747
|
serverVersionSynthetic: capabilityDiscoveryContext.capabilities._synthetic
|
|
6417
6748
|
},
|
|
6749
|
+
...negotiatedRelease?.downgraded && { negotiatedAdcpVersion: negotiatedRelease.version },
|
|
6418
6750
|
productPolicyRequest: productPolicyRequestSnapshot(normalizedParams),
|
|
6419
6751
|
accountRegistry: this.accountRegistryContext(taskName, normalizedParams, effectiveOptions),
|
|
6420
6752
|
...effectiveOptions?.taskId !== void 0 && { optionTaskId: effectiveOptions.taskId },
|
|
@@ -8109,8 +8441,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
8109
8441
|
* first (cold-cache) call; the configured-version gate above still catches
|
|
8110
8442
|
* an explicitly pre-3.1 client before validation or network I/O.
|
|
8111
8443
|
*/
|
|
8112
|
-
assertRequestSupportedByTargetVersion(taskName, params, capabilities, canonicalCreativeInvocation = false, serverVersion) {
|
|
8113
|
-
|
|
8444
|
+
assertRequestSupportedByTargetVersion(taskName, params, capabilities, canonicalCreativeInvocation = false, serverVersion, negotiated) {
|
|
8445
|
+
const reducesAccountIdentity = this.accountIdentityDowngrade === "reduce" && negotiated?.downgraded === true;
|
|
8446
|
+
if (taskName === "sync_accounts" && !reducesAccountIdentity) {
|
|
8114
8447
|
const advertisedVersions2 = capabilities?.supportedVersions ?? [];
|
|
8115
8448
|
const servedVersion = capabilities?.servedVersion ?? capabilities?._raw?.adcp_version;
|
|
8116
8449
|
const supports32 = serverVersion !== "v2" && (typeof servedVersion === "string" ? isAdcpVersionAtLeast(servedVersion, "3.2.0-0") : advertisedVersions2.some((version) => isAdcpVersionAtLeast(version, "3.2.0-0")));
|
|
@@ -8280,7 +8613,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
8280
8613
|
}
|
|
8281
8614
|
const supportedVersions = capabilities.supportedVersions;
|
|
8282
8615
|
if (supportedVersions !== void 0 && supportedVersions.length > 0) {
|
|
8283
|
-
if (!isAdcpVersionSupported(this.resolvedAdcpVersion, supportedVersions)) {
|
|
8616
|
+
if (!isAdcpVersionSupported(this.resolvedAdcpVersion, supportedVersions) && this.negotiateCallRelease(capabilities, options) === void 0) {
|
|
8284
8617
|
throw new VersionUnsupportedError(taskType, "version", capabilities.version, this.agent.agent_uri);
|
|
8285
8618
|
}
|
|
8286
8619
|
} else {
|
|
@@ -226,7 +226,7 @@ export declare class TaskExecutor {
|
|
|
226
226
|
* adaptation runs, so the validator sees the same object the caller wrote.
|
|
227
227
|
* Throws in strict, logs to `debugLogs` in warn, no-ops in off.
|
|
228
228
|
*/
|
|
229
|
-
validateRequest(taskName: string, params: unknown, debugLogs?: any[]): void;
|
|
229
|
+
validateRequest(taskName: string, params: unknown, debugLogs?: any[], adcpVersion?: string): void;
|
|
230
230
|
/**
|
|
231
231
|
* Generate webhook URL for protocol-level webhook support
|
|
232
232
|
*/
|
|
@@ -226,7 +226,7 @@ export declare class TaskExecutor {
|
|
|
226
226
|
* adaptation runs, so the validator sees the same object the caller wrote.
|
|
227
227
|
* Throws in strict, logs to `debugLogs` in warn, no-ops in off.
|
|
228
228
|
*/
|
|
229
|
-
validateRequest(taskName: string, params: unknown, debugLogs?: any[]): void;
|
|
229
|
+
validateRequest(taskName: string, params: unknown, debugLogs?: any[], adcpVersion?: string): void;
|
|
230
230
|
/**
|
|
231
231
|
* Generate webhook URL for protocol-level webhook support
|
|
232
232
|
*/
|