@adcp/sdk 15.9.4 → 15.9.6
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/AgentClient.d.mts +4 -2
- package/dist/lib/core/AgentClient.d.ts +4 -2
- package/dist/lib/core/AgentClient.js +4 -2
- package/dist/lib/core/AgentClient.mjs +4 -2
- package/dist/lib/core/SingleAgentClient.d.mts +7 -3
- package/dist/lib/core/SingleAgentClient.d.ts +7 -3
- package/dist/lib/core/SingleAgentClient.js +204 -13
- package/dist/lib/core/SingleAgentClient.mjs +209 -13
- package/dist/lib/core/TaskExecutor.d.mts +1 -0
- package/dist/lib/core/TaskExecutor.d.ts +1 -0
- package/dist/lib/core/TaskExecutor.js +48 -34
- package/dist/lib/core/TaskExecutor.mjs +49 -35
- package/dist/lib/core/product-cache.d.mts +3 -1
- package/dist/lib/core/product-cache.d.ts +3 -1
- package/dist/lib/core/product-cache.js +2 -1
- package/dist/lib/core/product-cache.mjs +2 -1
- package/dist/lib/registry/types.d.mts +3 -2
- package/dist/lib/registry/types.d.ts +3 -2
- package/dist/lib/registry/types.generated.d.mts +21 -9
- package/dist/lib/registry/types.generated.d.ts +21 -9
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +6 -2
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +6 -2
- package/dist/lib/testing/client.js +3 -5
- package/dist/lib/testing/client.mjs +4 -6
- package/dist/lib/testing/compliance/comply.js +7 -2
- package/dist/lib/testing/compliance/comply.mjs +8 -3
- package/dist/lib/testing/index.d.mts +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.js +4 -2
- package/dist/lib/testing/index.mjs +8 -2
- package/dist/lib/testing/storyboard/runner.js +12 -12
- package/dist/lib/testing/storyboard/runner.mjs +14 -13
- 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 +23 -1
- package/dist/lib/testing/storyboard/validations.mjs +28 -2
- package/dist/lib/testing/types.d.mts +39 -0
- package/dist/lib/testing/types.d.ts +39 -0
- package/dist/lib/v2/projection/augment-response.js +6 -3
- package/dist/lib/v2/projection/augment-response.mjs +8 -5
- package/dist/lib/v2/projection/creative-delivery.d.mts +2 -0
- package/dist/lib/v2/projection/creative-delivery.d.ts +2 -0
- package/dist/lib/v2/projection/creative-delivery.js +36 -17
- package/dist/lib/v2/projection/creative-delivery.mjs +37 -18
- package/dist/lib/v2/projection/legacy-metadata.d.mts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.js +41 -1
- package/dist/lib/v2/projection/legacy-metadata.mjs +37 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.d.ts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.js +83 -2
- package/dist/lib/v2/projection/v1-to-v2.mjs +86 -1
- package/dist/lib/validation/index.d.mts +1 -1
- package/dist/lib/validation/index.d.ts +1 -1
- package/dist/lib/validation/index.js +4 -2
- package/dist/lib/validation/index.mjs +4 -2
- package/dist/lib/validation/schema-loader.d.mts +26 -0
- package/dist/lib/validation/schema-loader.d.ts +26 -0
- package/dist/lib/validation/schema-loader.js +98 -14
- package/dist/lib/validation/schema-loader.mjs +95 -13
- 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/CREATIVE-DELIVERY.md +45 -6
- package/docs/guides/VALIDATE-YOUR-AGENT.md +34 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -536,8 +536,10 @@ export declare class AgentClient {
|
|
|
536
536
|
/**
|
|
537
537
|
* Resolve the creative wire mode used by canonical writes without sending a
|
|
538
538
|
* mutation. Uses capabilities, this tool's input schema, and the client wire
|
|
539
|
-
* pin. Older peers with insufficient evidence return `unknown
|
|
540
|
-
*
|
|
539
|
+
* pin. Older peers with insufficient evidence return `unknown`; a matching
|
|
540
|
+
* seller-advertised product option can establish canonical delivery for an
|
|
541
|
+
* individual 3.1 write. Otherwise projection requires an unambiguous legacy
|
|
542
|
+
* reference. Conflicting evidence
|
|
541
543
|
* or unproven support with a 3.2+ buyer pin throws `CreativeFormatCapabilityError`.
|
|
542
544
|
*/
|
|
543
545
|
resolveCreativeFormatWireMode(taskType: 'sync_creatives' | 'create_media_buy' | 'update_media_buy', options?: Pick<TaskOptions, 'signal' | 'transport'>): Promise<CreativeFormatWireMode>;
|
|
@@ -536,8 +536,10 @@ export declare class AgentClient {
|
|
|
536
536
|
/**
|
|
537
537
|
* Resolve the creative wire mode used by canonical writes without sending a
|
|
538
538
|
* mutation. Uses capabilities, this tool's input schema, and the client wire
|
|
539
|
-
* pin. Older peers with insufficient evidence return `unknown
|
|
540
|
-
*
|
|
539
|
+
* pin. Older peers with insufficient evidence return `unknown`; a matching
|
|
540
|
+
* seller-advertised product option can establish canonical delivery for an
|
|
541
|
+
* individual 3.1 write. Otherwise projection requires an unambiguous legacy
|
|
542
|
+
* reference. Conflicting evidence
|
|
541
543
|
* or unproven support with a 3.2+ buyer pin throws `CreativeFormatCapabilityError`.
|
|
542
544
|
*/
|
|
543
545
|
resolveCreativeFormatWireMode(taskType: 'sync_creatives' | 'create_media_buy' | 'update_media_buy', options?: Pick<TaskOptions, 'signal' | 'transport'>): Promise<CreativeFormatWireMode>;
|
|
@@ -794,8 +794,10 @@ class AgentClient {
|
|
|
794
794
|
/**
|
|
795
795
|
* Resolve the creative wire mode used by canonical writes without sending a
|
|
796
796
|
* mutation. Uses capabilities, this tool's input schema, and the client wire
|
|
797
|
-
* pin. Older peers with insufficient evidence return `unknown
|
|
798
|
-
*
|
|
797
|
+
* pin. Older peers with insufficient evidence return `unknown`; a matching
|
|
798
|
+
* seller-advertised product option can establish canonical delivery for an
|
|
799
|
+
* individual 3.1 write. Otherwise projection requires an unambiguous legacy
|
|
800
|
+
* reference. Conflicting evidence
|
|
799
801
|
* or unproven support with a 3.2+ buyer pin throws `CreativeFormatCapabilityError`.
|
|
800
802
|
*/
|
|
801
803
|
async resolveCreativeFormatWireMode(taskType, options) {
|
|
@@ -762,8 +762,10 @@ class AgentClient {
|
|
|
762
762
|
/**
|
|
763
763
|
* Resolve the creative wire mode used by canonical writes without sending a
|
|
764
764
|
* mutation. Uses capabilities, this tool's input schema, and the client wire
|
|
765
|
-
* pin. Older peers with insufficient evidence return `unknown
|
|
766
|
-
*
|
|
765
|
+
* pin. Older peers with insufficient evidence return `unknown`; a matching
|
|
766
|
+
* seller-advertised product option can establish canonical delivery for an
|
|
767
|
+
* individual 3.1 write. Otherwise projection requires an unambiguous legacy
|
|
768
|
+
* reference. Conflicting evidence
|
|
767
769
|
* or unproven support with a 3.2+ buyer pin throws `CreativeFormatCapabilityError`.
|
|
768
770
|
*/
|
|
769
771
|
async resolveCreativeFormatWireMode(taskType, options) {
|
|
@@ -1012,14 +1012,18 @@ export declare class SingleAgentClient {
|
|
|
1012
1012
|
* sending a mutation. Discovers capabilities and the current tool's input
|
|
1013
1013
|
* schema, or reuses fresh cached/primed evidence, with this client's wire pin.
|
|
1014
1014
|
*
|
|
1015
|
-
* `unknown`
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1015
|
+
* This context-free check returns `unknown` when capabilities and schema do
|
|
1016
|
+
* not establish support. A write to a proven 3.1 seller can still select
|
|
1017
|
+
* canonical delivery from matching seller-advertised product options;
|
|
1018
|
+
* otherwise projection requires an unambiguous legacy reference.
|
|
1018
1019
|
* Conflicting evidence and unproven support with a 3.2+ buyer pin throw
|
|
1019
1020
|
* `CreativeFormatCapabilityError`, just as they do during a write.
|
|
1020
1021
|
*/
|
|
1021
1022
|
resolveCreativeFormatWireMode(taskType: 'sync_creatives' | 'create_media_buy' | 'update_media_buy', options?: ReadRequestOptions): Promise<CreativeFormatWireMode>;
|
|
1022
1023
|
private resolveCreativeWireMode;
|
|
1024
|
+
private usesScopedDiscoveryTransport;
|
|
1025
|
+
/** Product evidence applies to this request only; it must never prime a tool-wide capability. */
|
|
1026
|
+
private productOptionsSupportCanonicalWire;
|
|
1023
1027
|
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
1024
1028
|
private validateBeforeCreativeCapabilityProbe;
|
|
1025
1029
|
/**
|
|
@@ -1012,14 +1012,18 @@ export declare class SingleAgentClient {
|
|
|
1012
1012
|
* sending a mutation. Discovers capabilities and the current tool's input
|
|
1013
1013
|
* schema, or reuses fresh cached/primed evidence, with this client's wire pin.
|
|
1014
1014
|
*
|
|
1015
|
-
* `unknown`
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1015
|
+
* This context-free check returns `unknown` when capabilities and schema do
|
|
1016
|
+
* not establish support. A write to a proven 3.1 seller can still select
|
|
1017
|
+
* canonical delivery from matching seller-advertised product options;
|
|
1018
|
+
* otherwise projection requires an unambiguous legacy reference.
|
|
1018
1019
|
* Conflicting evidence and unproven support with a 3.2+ buyer pin throw
|
|
1019
1020
|
* `CreativeFormatCapabilityError`, just as they do during a write.
|
|
1020
1021
|
*/
|
|
1021
1022
|
resolveCreativeFormatWireMode(taskType: 'sync_creatives' | 'create_media_buy' | 'update_media_buy', options?: ReadRequestOptions): Promise<CreativeFormatWireMode>;
|
|
1022
1023
|
private resolveCreativeWireMode;
|
|
1024
|
+
private usesScopedDiscoveryTransport;
|
|
1025
|
+
/** Product evidence applies to this request only; it must never prime a tool-wide capability. */
|
|
1026
|
+
private productOptionsSupportCanonicalWire;
|
|
1023
1027
|
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
1024
1028
|
private validateBeforeCreativeCapabilityProbe;
|
|
1025
1029
|
/**
|
|
@@ -215,6 +215,56 @@ const RECORDLESS_HMAC_READ_ONLY_TASKS = /* @__PURE__ */ new Set([
|
|
|
215
215
|
]);
|
|
216
216
|
const TASK_SCOPED_STATE_LIMIT = 1e4;
|
|
217
217
|
const WEBHOOK_JWKS_RESOLVER_LIMIT = 1024;
|
|
218
|
+
function creativeMatchesProductOption(creative, declaration) {
|
|
219
|
+
const params = isPlainRecord(declaration.params) ? declaration.params : {};
|
|
220
|
+
const assets = isPlainRecord(creative.assets) ? creative.assets : {};
|
|
221
|
+
const slots = Array.isArray(params.slots) ? params.slots : [];
|
|
222
|
+
if (!slots.every((slot) => {
|
|
223
|
+
if (!isPlainRecord(slot) || typeof slot.asset_group_id !== "string") return false;
|
|
224
|
+
const value = assets[slot.asset_group_id];
|
|
225
|
+
const entries = value === void 0 ? [] : Array.isArray(value) ? value : [value];
|
|
226
|
+
const minimum = Math.max(typeof slot.min === "number" ? slot.min : 0, slot.required === true ? 1 : 0);
|
|
227
|
+
if (entries.length < minimum || typeof slot.max === "number" && entries.length > slot.max) return false;
|
|
228
|
+
return entries.every(
|
|
229
|
+
(asset) => isPlainRecord(asset) && (typeof slot.asset_type !== "string" || asset.asset_type === slot.asset_type)
|
|
230
|
+
);
|
|
231
|
+
}))
|
|
232
|
+
return false;
|
|
233
|
+
const formatParams = isPlainRecord(creative.format_parameters) ? creative.format_parameters : {};
|
|
234
|
+
const kind = String(creative.format_kind);
|
|
235
|
+
const mediaType = kind.startsWith("image") ? "image" : kind.startsWith("video") ? "video" : kind.startsWith("audio") ? "audio" : kind === "html5" ? "html" : void 0;
|
|
236
|
+
const assetTypes = mediaType === "video" ? ["video", "vast"] : mediaType === "audio" ? ["audio", "vast", "daast"] : mediaType === "html" ? ["html", "zip"] : mediaType ? [mediaType] : ["image", "video", "audio", "html", "zip", "vast", "daast"];
|
|
237
|
+
const requiredMediaSlots = slots.filter(
|
|
238
|
+
(slot) => isPlainRecord(slot) && (slot.required === true || typeof slot.min === "number" && slot.min > 0) && assetTypes.includes(String(slot.asset_type))
|
|
239
|
+
);
|
|
240
|
+
const preferredGroups = mediaType ? [`${mediaType}_main`, mediaType, kind, ...assetTypes] : [];
|
|
241
|
+
const primaryGroup = (requiredMediaSlots.length === 1 ? String(requiredMediaSlots[0].asset_group_id) : void 0) ?? preferredGroups.find((group) => assets[group] !== void 0);
|
|
242
|
+
const sourceAssets = primaryGroup ? [assets[primaryGroup]] : Object.values(assets);
|
|
243
|
+
const dimensionalAssets = sourceAssets.flatMap((value) => Array.isArray(value) ? value : [value]).filter(
|
|
244
|
+
(value) => isPlainRecord(value) && assetTypes.includes(String(value.asset_type))
|
|
245
|
+
);
|
|
246
|
+
return (dimensionalAssets.length > 0 ? dimensionalAssets : [{}]).every((asset) => {
|
|
247
|
+
const actual = { ...asset, ...formatParams };
|
|
248
|
+
for (const key of ["width", "height"]) {
|
|
249
|
+
if (typeof params[key] === "number" && actual[key] !== params[key]) return false;
|
|
250
|
+
const min = params[`min_${key}`];
|
|
251
|
+
const max = params[`max_${key}`];
|
|
252
|
+
if (typeof min === "number" && (typeof actual[key] !== "number" || actual[key] < min)) return false;
|
|
253
|
+
if (typeof max === "number" && (typeof actual[key] !== "number" || actual[key] > max)) return false;
|
|
254
|
+
}
|
|
255
|
+
if (Array.isArray(params.sizes) && !params.sizes.some((size) => isPlainRecord(size) && size.width === actual.width && size.height === actual.height))
|
|
256
|
+
return false;
|
|
257
|
+
const duration = actual.duration_ms ?? actual.duration_ms_exact;
|
|
258
|
+
const exact = params.duration_ms_exact ?? params.duration_ms;
|
|
259
|
+
if (typeof exact === "number" && duration !== exact) return false;
|
|
260
|
+
if (typeof exact !== "number" && Array.isArray(params.duration_ms_range)) {
|
|
261
|
+
const [min, max] = params.duration_ms_range;
|
|
262
|
+
if (typeof duration !== "number" || typeof min === "number" && duration < min || typeof max === "number" && duration > max)
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return true;
|
|
266
|
+
});
|
|
267
|
+
}
|
|
218
268
|
function isDeferredClientFinalizationContext(value) {
|
|
219
269
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
220
270
|
const context = value;
|
|
@@ -1347,7 +1397,7 @@ class SingleAgentClient {
|
|
|
1347
1397
|
}
|
|
1348
1398
|
}
|
|
1349
1399
|
}
|
|
1350
|
-
rememberCanonicalProductRoutes(products, account, authoritativeProducts) {
|
|
1400
|
+
rememberCanonicalProductRoutes(products, account, authoritativeProducts, evidence) {
|
|
1351
1401
|
this.invalidateCanonicalProductRoutes(authoritativeProducts ?? products, account);
|
|
1352
1402
|
const accountScope = this.canonicalAccountScope(account);
|
|
1353
1403
|
const declaredOptions = authoritativeProducts ? this.sellerDeclaredFormatOptions(authoritativeProducts) : void 0;
|
|
@@ -1367,12 +1417,15 @@ class SingleAgentClient {
|
|
|
1367
1417
|
const refs = (0, import_legacy_metadata.legacyFormatRefsForDeclaration)(option);
|
|
1368
1418
|
const declared = declaredOptions ? declaredOptions.get(product.product_id)?.some((declaredRef) => this.sameCanonicalOptionRef(declaredRef, ref)) : (0, import_legacy_metadata.sellerDeclaredFormatOption)(option);
|
|
1369
1419
|
if (declared !== void 0) (0, import_legacy_metadata.rememberSellerDeclaredFormatOption)(option, declared);
|
|
1420
|
+
if (declared === true && evidence)
|
|
1421
|
+
(0, import_legacy_metadata.rememberSellerFormatEvidence)(option, { ...evidence, productId: product.product_id });
|
|
1370
1422
|
this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
|
|
1371
1423
|
kind: "product",
|
|
1372
1424
|
accountScope,
|
|
1373
1425
|
productId: product.product_id,
|
|
1374
1426
|
optionRef: ref,
|
|
1375
1427
|
refs,
|
|
1428
|
+
...declared === true && (0, import_legacy_metadata.sellerFormatEvidence)(option) ? { declaration: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(option) } : {},
|
|
1376
1429
|
...declared === false ? { undeclaredSelector: (0, import_legacy_routes.undeclaredFormatOptionSelector)(option) } : {}
|
|
1377
1430
|
});
|
|
1378
1431
|
}
|
|
@@ -4582,6 +4635,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4582
4635
|
}
|
|
4583
4636
|
}
|
|
4584
4637
|
const conditionalSnapshot = skipCacheRead ? void 0 : cache?.read(cacheScope, cacheParams, true);
|
|
4638
|
+
const productEvidence = this.usesScopedDiscoveryTransport(
|
|
4639
|
+
effectiveOptions
|
|
4640
|
+
) ? void 0 : {
|
|
4641
|
+
scopeKey: this.getCapabilityEvidenceScope().scopeKey,
|
|
4642
|
+
accountScope: this.canonicalAccountScope(account),
|
|
4643
|
+
expiresAt: Date.now() + (0, import_agent_discovery_cache.resolveAgentDiscoveryTtlMs)(this.config.discoveryCache?.ttlMs)
|
|
4644
|
+
};
|
|
4585
4645
|
const result = await this.executeAndHandle(
|
|
4586
4646
|
"get_products",
|
|
4587
4647
|
"onGetProductsStatusChange",
|
|
@@ -4594,7 +4654,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4594
4654
|
projectionCatalogs: projectionCatalogs ?? this.config.projectionCatalogs
|
|
4595
4655
|
});
|
|
4596
4656
|
const authoritativeProducts = Array.isArray(data.products) ? data.products : response.products;
|
|
4597
|
-
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts);
|
|
4657
|
+
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts, productEvidence);
|
|
4598
4658
|
const { _message: _dropLegacyMessage, ...canonical } = response;
|
|
4599
4659
|
void _dropLegacyMessage;
|
|
4600
4660
|
return { ...canonical, projection: { diagnostics } };
|
|
@@ -4605,7 +4665,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4605
4665
|
);
|
|
4606
4666
|
const finishCache = async (completed) => {
|
|
4607
4667
|
if (!cache) return completed;
|
|
4608
|
-
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot)
|
|
4668
|
+
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot, (materialized) => {
|
|
4669
|
+
this.rememberCanonicalProductRoutes(materialized.data?.products ?? [], account, void 0, productEvidence);
|
|
4670
|
+
});
|
|
4609
4671
|
if (cachedResult.success && cachedResult.status === "completed") {
|
|
4610
4672
|
if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
|
|
4611
4673
|
return this.getProducts(params, inputHandler, {
|
|
@@ -4765,7 +4827,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4765
4827
|
if (hasCreativeFormatData) {
|
|
4766
4828
|
this.validateBeforeCreativeCapabilityProbe("create_media_buy", params, taskOptions);
|
|
4767
4829
|
}
|
|
4768
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
4830
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
4831
|
+
"create_media_buy",
|
|
4832
|
+
taskOptions,
|
|
4833
|
+
true,
|
|
4834
|
+
() => this.productOptionsSupportCanonicalWire("create_media_buy", params, [], options)
|
|
4835
|
+
) : "canonical";
|
|
4769
4836
|
const wireParams = params;
|
|
4770
4837
|
const result = await this.executeAndHandle(
|
|
4771
4838
|
"create_media_buy",
|
|
@@ -4853,7 +4920,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4853
4920
|
if (hasCreativeFormatData) {
|
|
4854
4921
|
this.validateBeforeCreativeCapabilityProbe("update_media_buy", params, taskOptions);
|
|
4855
4922
|
}
|
|
4856
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
4923
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
4924
|
+
"update_media_buy",
|
|
4925
|
+
taskOptions,
|
|
4926
|
+
true,
|
|
4927
|
+
() => this.productOptionsSupportCanonicalWire("update_media_buy", params, [], options)
|
|
4928
|
+
) : "canonical";
|
|
4857
4929
|
const result = await this.executeAndHandle(
|
|
4858
4930
|
"update_media_buy",
|
|
4859
4931
|
"onUpdateMediaBuyStatusChange",
|
|
@@ -4942,7 +5014,6 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4942
5014
|
projectionCatalogs ?? this.config.projectionCatalogs
|
|
4943
5015
|
);
|
|
4944
5016
|
this.validateBeforeCreativeCapabilityProbe("sync_creatives", params, taskOptions);
|
|
4945
|
-
const wireMode = await this.resolveCreativeFormatWireMode("sync_creatives", taskOptions);
|
|
4946
5017
|
const configuredSelectorContainers = [
|
|
4947
5018
|
...creativeFormatProjection?.selectorContainers ?? []
|
|
4948
5019
|
];
|
|
@@ -4954,10 +5025,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4954
5025
|
const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
|
|
4955
5026
|
(assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
|
|
4956
5027
|
) : [];
|
|
5028
|
+
const selectorContainers = [...configuredSelectorContainers, ...assignmentPackageContainers];
|
|
5029
|
+
const wireMode = await this.resolveCreativeWireMode(
|
|
5030
|
+
"sync_creatives",
|
|
5031
|
+
taskOptions,
|
|
5032
|
+
true,
|
|
5033
|
+
() => this.productOptionsSupportCanonicalWire("sync_creatives", params, selectorContainers, options)
|
|
5034
|
+
);
|
|
4957
5035
|
const wireParams = this.projectUndeclaredFormatOptions(
|
|
4958
5036
|
(0, import_creative_delivery.projectSyncCreativesForDelivery)(
|
|
4959
5037
|
params,
|
|
4960
|
-
|
|
5038
|
+
selectorContainers,
|
|
4961
5039
|
wireMode,
|
|
4962
5040
|
effectiveLegacyFormatConverter,
|
|
4963
5041
|
effectiveCanonicalFormatLegacyResolver
|
|
@@ -4997,16 +5075,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4997
5075
|
* sending a mutation. Discovers capabilities and the current tool's input
|
|
4998
5076
|
* schema, or reuses fresh cached/primed evidence, with this client's wire pin.
|
|
4999
5077
|
*
|
|
5000
|
-
* `unknown`
|
|
5001
|
-
*
|
|
5002
|
-
*
|
|
5078
|
+
* This context-free check returns `unknown` when capabilities and schema do
|
|
5079
|
+
* not establish support. A write to a proven 3.1 seller can still select
|
|
5080
|
+
* canonical delivery from matching seller-advertised product options;
|
|
5081
|
+
* otherwise projection requires an unambiguous legacy reference.
|
|
5003
5082
|
* Conflicting evidence and unproven support with a 3.2+ buyer pin throw
|
|
5004
5083
|
* `CreativeFormatCapabilityError`, just as they do during a write.
|
|
5005
5084
|
*/
|
|
5006
5085
|
async resolveCreativeFormatWireMode(taskType, options) {
|
|
5007
5086
|
return this.resolveCreativeWireMode(taskType, options, true);
|
|
5008
5087
|
}
|
|
5009
|
-
async resolveCreativeWireMode(taskType, options, canRediscover) {
|
|
5088
|
+
async resolveCreativeWireMode(taskType, options, canRediscover, matchingProductOptions) {
|
|
5010
5089
|
const discoveryContext = {};
|
|
5011
5090
|
const capabilities = await this.getCapabilities({
|
|
5012
5091
|
...options,
|
|
@@ -5025,13 +5104,16 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5025
5104
|
`Seller capability and ${taskType} input schema disagree about canonical creative support`
|
|
5026
5105
|
);
|
|
5027
5106
|
}
|
|
5028
|
-
|
|
5107
|
+
let resolved = declared !== "unknown" ? declared : schema;
|
|
5108
|
+
if (resolved === "unknown" && (0, import_creative_delivery.canUseProductOptionsForCreativeWire)(capabilities, wireRelease) && matchingProductOptions?.()) {
|
|
5109
|
+
resolved = "canonical";
|
|
5110
|
+
}
|
|
5029
5111
|
const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
|
|
5030
5112
|
const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
|
|
5031
5113
|
if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
|
|
5032
5114
|
if (canRediscover && !usesScopedFetch && this.normalizedAgent.protocol === "mcp" && this.capabilitiesFromSharedCache && toolSchemas?.has(taskType) && !toolInputSchemasByProperties.has(toolSchemas)) {
|
|
5033
5115
|
await this.invalidateDiscoveryCache(options);
|
|
5034
|
-
return this.resolveCreativeWireMode(taskType, options, false);
|
|
5116
|
+
return this.resolveCreativeWireMode(taskType, options, false, matchingProductOptions);
|
|
5035
5117
|
}
|
|
5036
5118
|
throw new import_creative_delivery.CreativeFormatCapabilityError(
|
|
5037
5119
|
`Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
|
|
@@ -5039,6 +5121,115 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5039
5121
|
}
|
|
5040
5122
|
return resolved;
|
|
5041
5123
|
}
|
|
5124
|
+
usesScopedDiscoveryTransport(options) {
|
|
5125
|
+
return (0, import_protocols.normalizeTransportOptions)(options?.transport ?? this.config.transport)?.trustedFetchFn !== void 0;
|
|
5126
|
+
}
|
|
5127
|
+
/** Product evidence applies to this request only; it must never prime a tool-wide capability. */
|
|
5128
|
+
productOptionsSupportCanonicalWire(taskType, request, selectorContainers = [], options) {
|
|
5129
|
+
if (!isPlainRecord(request) || this.usesScopedDiscoveryTransport(options)) return false;
|
|
5130
|
+
const scopeKey = this.getCapabilityEvidenceScope().scopeKey;
|
|
5131
|
+
const accountScope = this.canonicalAccountScope(request.account);
|
|
5132
|
+
const optionRef = (value) => {
|
|
5133
|
+
if (!isPlainRecord(value) || typeof value.format_option_id !== "string" || !value.format_option_id) {
|
|
5134
|
+
return void 0;
|
|
5135
|
+
}
|
|
5136
|
+
if (typeof value.publisher_domain === "string") {
|
|
5137
|
+
return {
|
|
5138
|
+
scope: "publisher",
|
|
5139
|
+
publisher_domain: value.publisher_domain,
|
|
5140
|
+
format_option_id: value.format_option_id
|
|
5141
|
+
};
|
|
5142
|
+
}
|
|
5143
|
+
if (value.scope !== void 0 && value.scope !== "product") return void 0;
|
|
5144
|
+
return { scope: "product", format_option_id: value.format_option_id };
|
|
5145
|
+
};
|
|
5146
|
+
const accepts = (container, creative, depth = 0) => {
|
|
5147
|
+
if (depth > 32) return false;
|
|
5148
|
+
if (Array.isArray(container.selector_containers)) {
|
|
5149
|
+
return container.selector_containers.length > 0 && container.selector_containers.every((nested) => accepts(nested, creative, depth + 1));
|
|
5150
|
+
}
|
|
5151
|
+
const refs = Array.isArray(container.format_option_refs) ? container.format_option_refs.map(optionRef) : [];
|
|
5152
|
+
if (refs.some((ref) => ref === void 0)) return false;
|
|
5153
|
+
const creativeRef = isPlainRecord(creative) ? optionRef(creative.format_option_ref) : void 0;
|
|
5154
|
+
if (isPlainRecord(creative) && creative.format_option_ref !== void 0 && !creativeRef) return false;
|
|
5155
|
+
const isSellerDeclaration = (value) => {
|
|
5156
|
+
if (!isPlainRecord(value) || (0, import_legacy_metadata.sellerDeclaredFormatOption)(value) !== true || (0, import_legacy_metadata.isSynthesizedFormatOption)(value)) {
|
|
5157
|
+
return false;
|
|
5158
|
+
}
|
|
5159
|
+
const evidence2 = (0, import_legacy_metadata.sellerFormatEvidence)(value);
|
|
5160
|
+
if (!evidence2 || evidence2.scopeKey !== scopeKey || typeof container.product_id === "string" && evidence2.productId !== container.product_id || evidence2.expiresAt <= Date.now() || evidence2.accountScope !== accountScope && evidence2.accountScope !== "none")
|
|
5161
|
+
return false;
|
|
5162
|
+
const ref = optionRef(value);
|
|
5163
|
+
if (ref && (0, import_legacy_routes.formatOptionOriginFromRoutes)(
|
|
5164
|
+
options?.canonicalFormatLegacyResolver,
|
|
5165
|
+
ref,
|
|
5166
|
+
typeof container.product_id === "string" ? container.product_id : void 0
|
|
5167
|
+
)?.seller_declared === false)
|
|
5168
|
+
return false;
|
|
5169
|
+
return !ref || typeof container.product_id !== "string" || this.cachedFormatOptionOrigin(request.account, ref, container.product_id)?.seller_declared !== false;
|
|
5170
|
+
};
|
|
5171
|
+
const declarations = [
|
|
5172
|
+
...(Array.isArray(container.format_options) ? container.format_options : []).filter(isSellerDeclaration),
|
|
5173
|
+
...(0, import_legacy_metadata.selectedFormatOptions)(container).filter(isSellerDeclaration)
|
|
5174
|
+
];
|
|
5175
|
+
if (typeof container.product_id === "string") {
|
|
5176
|
+
for (const ref of [...refs, ...creativeRef ? [creativeRef] : []]) {
|
|
5177
|
+
if (!ref) continue;
|
|
5178
|
+
const route = this.routeForOption(request.account, container.product_id, ref);
|
|
5179
|
+
if (route?.kind === "product" && route.declaration && isSellerDeclaration(route.declaration))
|
|
5180
|
+
declarations.push(route.declaration);
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
const available = declarations.filter((declaration) => declaration.experimental !== true);
|
|
5184
|
+
const matchesRef = (declaration, ref) => {
|
|
5185
|
+
const declaredRef = optionRef(declaration);
|
|
5186
|
+
return declaredRef !== void 0 && this.sameCanonicalOptionRef(declaredRef, ref);
|
|
5187
|
+
};
|
|
5188
|
+
if (!refs.every((ref) => available.some((declaration) => matchesRef(declaration, ref)))) return false;
|
|
5189
|
+
const selected = available.filter(
|
|
5190
|
+
(declaration) => refs.length === 0 || refs.some((ref) => matchesRef(declaration, ref))
|
|
5191
|
+
);
|
|
5192
|
+
if (creative === void 0) return refs.length > 0 && selected.length > 0;
|
|
5193
|
+
if (!isPlainRecord(creative) || typeof creative.format_kind !== "string" || creative.format_id !== void 0)
|
|
5194
|
+
return false;
|
|
5195
|
+
return selected.some(
|
|
5196
|
+
(declaration) => declaration.format_kind === creative.format_kind && (!creativeRef || matchesRef(declaration, creativeRef)) && creativeMatchesProductOption(creative, declaration)
|
|
5197
|
+
);
|
|
5198
|
+
};
|
|
5199
|
+
if (taskType === "sync_creatives") {
|
|
5200
|
+
if (!Array.isArray(request.creatives) || request.creatives.length === 0) return false;
|
|
5201
|
+
const creatives = request.creatives;
|
|
5202
|
+
const assignments = Array.isArray(request.assignments) ? request.assignments : [];
|
|
5203
|
+
if (!assignments.every(
|
|
5204
|
+
(value) => isPlainRecord(value) && typeof value.package_id === "string" && typeof value.creative_id === "string" && creatives.some((creative) => isPlainRecord(creative) && creative.creative_id === value.creative_id)
|
|
5205
|
+
))
|
|
5206
|
+
return false;
|
|
5207
|
+
return creatives.every((creative) => {
|
|
5208
|
+
if (!isPlainRecord(creative)) return false;
|
|
5209
|
+
const assigned = new Set(
|
|
5210
|
+
assignments.flatMap(
|
|
5211
|
+
(value) => isPlainRecord(value) && value.creative_id === creative.creative_id && typeof value.package_id === "string" ? [value.package_id] : []
|
|
5212
|
+
)
|
|
5213
|
+
);
|
|
5214
|
+
const relevant = assigned.size === 0 ? selectorContainers : selectorContainers.filter(
|
|
5215
|
+
(container) => typeof container.package_id === "string" && assigned.has(container.package_id)
|
|
5216
|
+
);
|
|
5217
|
+
return relevant.length > 0 && [...assigned].every((id) => relevant.some((container) => container.package_id === id)) && relevant.every((container) => accepts(container, creative));
|
|
5218
|
+
});
|
|
5219
|
+
}
|
|
5220
|
+
const packages = ["packages", "new_packages"].flatMap((key) => Array.isArray(request[key]) ? request[key] : []);
|
|
5221
|
+
let evidence = false;
|
|
5222
|
+
return packages.length > 0 && packages.every((pkg) => {
|
|
5223
|
+
if (!isPlainRecord(pkg)) return false;
|
|
5224
|
+
const creatives = Array.isArray(pkg.creatives) ? pkg.creatives : [];
|
|
5225
|
+
const hasSelectors = Array.isArray(pkg.format_option_refs) && pkg.format_option_refs.length > 0;
|
|
5226
|
+
if (!hasSelectors && creatives.length === 0) {
|
|
5227
|
+
return pkg.format_kind === void 0 && pkg.format_ids === void 0;
|
|
5228
|
+
}
|
|
5229
|
+
evidence = true;
|
|
5230
|
+
return (!hasSelectors || accepts(pkg)) && creatives.every((creative) => accepts(pkg, creative));
|
|
5231
|
+
}) && evidence;
|
|
5232
|
+
}
|
|
5042
5233
|
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
5043
5234
|
validateBeforeCreativeCapabilityProbe(taskType, params, options) {
|
|
5044
5235
|
if (options.skipIdempotencyAutoInject || options.skipAccountValidation || options.skipRequestValidation) return;
|