@adcp/sdk 14.0.0-beta.8 → 14.0.0-beta.9
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.ts.map +1 -1
- package/dist/lib/core/ConversationTypes.d.mts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
- package/dist/lib/core/ConversationTypes.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +30 -3
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +30 -3
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +32 -5
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +32 -5
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/index.d.mts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +2 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/schemas/index.d.mts +14 -0
- package/dist/lib/schemas/index.d.ts +14 -0
- package/dist/lib/schemas/index.d.ts.map +1 -1
- package/dist/lib/schemas/index.js +13 -1
- package/dist/lib/schemas/index.js.map +1 -1
- package/dist/lib/schemas/index.mjs +13 -1
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/adcp-server.d.mts +1 -0
- package/dist/lib/server/adcp-server.d.ts +1 -0
- package/dist/lib/server/adcp-server.d.ts.map +1 -1
- package/dist/lib/server/adcp-server.js +1 -1
- package/dist/lib/server/adcp-server.js.map +1 -1
- package/dist/lib/server/adcp-server.mjs +1 -1
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +10 -2
- package/dist/lib/server/create-adcp-server.d.ts +10 -2
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +26 -19
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +26 -26
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.d.mts +15 -1
- package/dist/lib/server/decisioning/capabilities.d.ts +15 -1
- package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -1
- package/dist/lib/server/decisioning/capabilities.js.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +2 -2
- package/dist/lib/server/decisioning/index.d.ts +2 -2
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js +2 -0
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +2 -0
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.d.mts +3 -2
- package/dist/lib/server/decisioning/proposal/types.d.ts +3 -2
- package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +14 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +14 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +402 -9
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +405 -9
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.mts +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.js +2 -2
- package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +2 -2
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.mts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
- package/dist/lib/storage/interfaces.d.mts +2 -0
- package/dist/lib/storage/interfaces.d.ts +2 -0
- package/dist/lib/storage/interfaces.d.ts.map +1 -1
- package/dist/lib/storage/interfaces.js.map +1 -1
- package/dist/lib/testing/compliance/comply.d.mts +18 -0
- package/dist/lib/testing/compliance/comply.d.ts +18 -0
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +30 -5
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +28 -4
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.d.mts +1 -1
- package/dist/lib/testing/compliance/index.d.ts +1 -1
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js +4 -2
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +4 -2
- package/dist/lib/testing/compliance/index.mjs.map +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/types/list-creatives.d.ts +129 -6
- package/dist/lib/types/schemas.generated.d.ts +411 -16
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +22 -6
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +22 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +80 -6
- package/dist/lib/types/tools.generated.d.ts +80 -6
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/adcp-version-config.d.mts +12 -0
- package/dist/lib/utils/adcp-version-config.d.ts +12 -0
- package/dist/lib/utils/adcp-version-config.d.ts.map +1 -1
- package/dist/lib/utils/adcp-version-config.js +5 -3
- package/dist/lib/utils/adcp-version-config.js.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +4 -3
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.d.mts +2 -0
- package/dist/lib/utils/pricing-adapter.d.ts +2 -0
- package/dist/lib/utils/pricing-adapter.d.ts.map +1 -1
- package/dist/lib/utils/pricing-adapter.js +68 -1
- package/dist/lib/utils/pricing-adapter.js.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +67 -1
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/v2/projection/index.d.mts +1 -1
- package/dist/lib/v2/projection/index.d.ts +1 -1
- package/dist/lib/v2/projection/index.d.ts.map +1 -1
- package/dist/lib/v2/projection/index.js.map +1 -1
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +17 -3
- package/dist/lib/v2/projection/v1-to-v2.d.ts +17 -3
- package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.d.mts +17 -0
- package/dist/lib/validation/schema-loader.d.ts +17 -0
- package/dist/lib/validation/schema-loader.d.ts.map +1 -1
- package/dist/lib/validation/schema-loader.js +24 -0
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +23 -0
- package/dist/lib/validation/schema-loader.mjs.map +1 -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.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/llms.txt +2 -2
- package/docs/migration-13-to-14.md +59 -0
- package/package.json +1 -1
|
@@ -73,7 +73,12 @@ import {
|
|
|
73
73
|
projectMediaBuyCreativesForDelivery,
|
|
74
74
|
stripLegacyCreativeIdentity
|
|
75
75
|
} from "../../../v2/projection/creative-delivery.mjs";
|
|
76
|
-
import {
|
|
76
|
+
import {
|
|
77
|
+
projectV1ProductToV2
|
|
78
|
+
} from "../../../v2/projection/v1-to-v2.mjs";
|
|
79
|
+
import {
|
|
80
|
+
legacyFormatConverterFromCatalogSnapshots
|
|
81
|
+
} from "../../../v2/projection/catalog-snapshot.mjs";
|
|
77
82
|
import { toCanonicalOnlyResponse } from "../../../v2/projection/augment-response.mjs";
|
|
78
83
|
import {
|
|
79
84
|
CanonicalFormatLegacyResolutionError,
|
|
@@ -526,7 +531,7 @@ function asCanonicalListCreativesRequest(request, legacyFormatConverter, respons
|
|
|
526
531
|
];
|
|
527
532
|
return { ...withLegacyFilter, fields };
|
|
528
533
|
}
|
|
529
|
-
function
|
|
534
|
+
function assertSafeGetProductsResponse(response) {
|
|
530
535
|
try {
|
|
531
536
|
assertSafeSemanticPayload(response, "get_products");
|
|
532
537
|
} catch (error) {
|
|
@@ -537,6 +542,9 @@ function asCanonicalProductResponse(response, legacyFormatConverter) {
|
|
|
537
542
|
suggestion: "Return an acyclic data-only product response without enumerable accessors."
|
|
538
543
|
});
|
|
539
544
|
}
|
|
545
|
+
}
|
|
546
|
+
function asCanonicalProductResponse(response, legacyFormatConverter) {
|
|
547
|
+
assertSafeGetProductsResponse(response);
|
|
540
548
|
validateDualProductFormatDeclarations(response, legacyFormatConverter);
|
|
541
549
|
const projected = toCanonicalOnlyResponse(response, {
|
|
542
550
|
legacyFormatConverter
|
|
@@ -562,7 +570,323 @@ function asCanonicalProductResponse(response, legacyFormatConverter) {
|
|
|
562
570
|
preserveAuthoredFormatIds(response, canonicalResponse);
|
|
563
571
|
return canonicalResponse;
|
|
564
572
|
}
|
|
573
|
+
function legacyFormatResolutionKey(context) {
|
|
574
|
+
const formatId = context.formatId;
|
|
575
|
+
return JSON.stringify([
|
|
576
|
+
context.productId,
|
|
577
|
+
context.field,
|
|
578
|
+
formatId.agent_url,
|
|
579
|
+
formatId.id,
|
|
580
|
+
formatId.width ?? null,
|
|
581
|
+
formatId.height ?? null,
|
|
582
|
+
formatId.duration_ms ?? null
|
|
583
|
+
]);
|
|
584
|
+
}
|
|
585
|
+
function preparePerProductProjectionCatalogs(response, fallback) {
|
|
586
|
+
assertSafeGetProductsResponse(response);
|
|
587
|
+
if (!Array.isArray(response.products)) return { response, converter: fallback };
|
|
588
|
+
assertNoReservedLegacyRouteMetadata(response.products, "products");
|
|
589
|
+
const converters = /* @__PURE__ */ new Map();
|
|
590
|
+
const productIdCounts = /* @__PURE__ */ new Map();
|
|
591
|
+
for (const product of response.products) {
|
|
592
|
+
if (!product || typeof product !== "object" || Array.isArray(product)) continue;
|
|
593
|
+
const productId = product.product_id;
|
|
594
|
+
if (typeof productId === "string") productIdCounts.set(productId, (productIdCounts.get(productId) ?? 0) + 1);
|
|
595
|
+
}
|
|
596
|
+
let strippedCatalogMetadata = false;
|
|
597
|
+
const products = response.products.map((product) => {
|
|
598
|
+
if (!product || typeof product !== "object" || Array.isArray(product)) return product;
|
|
599
|
+
const record = product;
|
|
600
|
+
if (!Object.prototype.hasOwnProperty.call(record, "projectionCatalogs")) return product;
|
|
601
|
+
strippedCatalogMetadata = true;
|
|
602
|
+
const { projectionCatalogs, ...wireProduct } = record;
|
|
603
|
+
if (!Array.isArray(projectionCatalogs)) {
|
|
604
|
+
throw new AdcpError("INVALID_REQUEST", {
|
|
605
|
+
message: "get_products projectionCatalogs must be an array of immutable catalog snapshots.",
|
|
606
|
+
field: `products[${String(record.product_id ?? "?")}].projectionCatalogs`
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
if (typeof record.product_id === "string" && (productIdCounts.get(record.product_id) ?? 0) > 1) {
|
|
610
|
+
throw new AdcpError("INVALID_REQUEST", {
|
|
611
|
+
message: "get_products projection catalogs require unique product identifiers.",
|
|
612
|
+
field: `products[${record.product_id}].projectionCatalogs`
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
if (projectionCatalogs.length > 0 && typeof record.product_id === "string") {
|
|
616
|
+
if (converters.has(record.product_id)) {
|
|
617
|
+
throw new AdcpError("INVALID_REQUEST", {
|
|
618
|
+
message: "get_products cannot attach different projection catalogs to duplicate product identifiers.",
|
|
619
|
+
field: `products[${record.product_id}].projectionCatalogs`
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
const converter2 = legacyFormatConverterFromCatalogSnapshots(
|
|
623
|
+
projectionCatalogs
|
|
624
|
+
);
|
|
625
|
+
if (converter2) {
|
|
626
|
+
converters.set(record.product_id, converter2);
|
|
627
|
+
const placements = wireProduct.placements;
|
|
628
|
+
if (Array.isArray(placements)) {
|
|
629
|
+
for (let placementIndex = 0; placementIndex < placements.length; placementIndex++) {
|
|
630
|
+
const placement = placements[placementIndex];
|
|
631
|
+
if (!placement || typeof placement !== "object" || Array.isArray(placement)) continue;
|
|
632
|
+
const placementRecord = placement;
|
|
633
|
+
const placementId = typeof placementRecord.placement_id === "string" ? placementRecord.placement_id : String(placementIndex);
|
|
634
|
+
const projectionProductId = `${record.product_id}:placement:${placementId}`;
|
|
635
|
+
if (converters.has(projectionProductId)) {
|
|
636
|
+
throw new AdcpError("INVALID_REQUEST", {
|
|
637
|
+
message: "get_products projection catalog scopes resolve to a duplicate product identifier.",
|
|
638
|
+
field: `products[${record.product_id}].placements[${placementIndex}]`
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
converters.set(projectionProductId, converter2);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return wireProduct;
|
|
647
|
+
});
|
|
648
|
+
const converter = converters.size === 0 ? fallback : (context) => {
|
|
649
|
+
const productConverter = converters.get(context.productId);
|
|
650
|
+
const resolved = productConverter?.(context);
|
|
651
|
+
return resolved === void 0 ? fallback?.(context) : resolved;
|
|
652
|
+
};
|
|
653
|
+
return {
|
|
654
|
+
response: strippedCatalogMetadata ? { ...response, products } : response,
|
|
655
|
+
converter
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
const DEFAULT_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS = 1e4;
|
|
659
|
+
const DEFAULT_LEGACY_FORMAT_RESOLVER_CONCURRENCY = 8;
|
|
660
|
+
const MAX_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS = 2147483647;
|
|
661
|
+
const MAX_LEGACY_FORMAT_RESOLVER_CONCURRENCY = 64;
|
|
662
|
+
function legacyFormatResolverLimit(value, fallback, field, maximum) {
|
|
663
|
+
if (value === void 0) return fallback;
|
|
664
|
+
if (!Number.isSafeInteger(value) || value <= 0 || maximum !== void 0 && value > maximum) {
|
|
665
|
+
const range = maximum === void 0 ? "a positive safe integer" : `an integer between 1 and ${maximum}`;
|
|
666
|
+
throw new PlatformConfigError(`${field} must be ${range}.`);
|
|
667
|
+
}
|
|
668
|
+
return value;
|
|
669
|
+
}
|
|
670
|
+
function legacyFormatResolverAbortError(signal) {
|
|
671
|
+
return signal.reason instanceof Error ? signal.reason : new Error("legacyCreativeFormatResolver was aborted before projection completed.");
|
|
672
|
+
}
|
|
673
|
+
function createLegacyFormatResolverSignal(requestSignal, timeoutMs) {
|
|
674
|
+
const controller = new AbortController();
|
|
675
|
+
const abortFromRequest = () => controller.abort(requestSignal?.reason);
|
|
676
|
+
if (requestSignal?.aborted) abortFromRequest();
|
|
677
|
+
else requestSignal?.addEventListener("abort", abortFromRequest, { once: true });
|
|
678
|
+
const timeout = controller.signal.aborted ? void 0 : setTimeout(
|
|
679
|
+
() => controller.abort(new Error(`legacyCreativeFormatResolver exceeded its ${timeoutMs}ms deadline.`)),
|
|
680
|
+
timeoutMs
|
|
681
|
+
);
|
|
682
|
+
return {
|
|
683
|
+
signal: controller.signal,
|
|
684
|
+
dispose() {
|
|
685
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
686
|
+
requestSignal?.removeEventListener("abort", abortFromRequest);
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
async function invokeLegacyFormatResolver(resolver, context, signal) {
|
|
691
|
+
if (signal.aborted) throw legacyFormatResolverAbortError(signal);
|
|
692
|
+
let abortListener;
|
|
693
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
694
|
+
abortListener = () => reject(legacyFormatResolverAbortError(signal));
|
|
695
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
696
|
+
});
|
|
697
|
+
try {
|
|
698
|
+
return await Promise.race([Promise.resolve().then(() => resolver({ ...context, signal })), aborted]);
|
|
699
|
+
} finally {
|
|
700
|
+
if (abortListener) signal.removeEventListener("abort", abortListener);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function resolveLegacyProductFormats(response, converter, resolver, requestContext) {
|
|
704
|
+
if (!resolver) return converter;
|
|
705
|
+
assertSafeGetProductsResponse(response);
|
|
706
|
+
if (!Array.isArray(response.products)) return converter;
|
|
707
|
+
const resolutions = /* @__PURE__ */ new Map();
|
|
708
|
+
const pending = [];
|
|
709
|
+
const scanScope = (projectionProduct, resolverProductId, resolverFieldPrefix) => {
|
|
710
|
+
if (Array.isArray(projectionProduct.format_options)) return;
|
|
711
|
+
for (let index = 0; index < projectionProduct.format_ids.length; index++) {
|
|
712
|
+
const formatId = projectionProduct.format_ids[index];
|
|
713
|
+
if (!formatId || typeof formatId !== "object" || Array.isArray(formatId)) continue;
|
|
714
|
+
const projectionField = `products[${projectionProduct.product_id}].format_ids[${index}]`;
|
|
715
|
+
const resolverField = `${resolverFieldPrefix}.format_ids[${index}]`;
|
|
716
|
+
const projectionContext = {
|
|
717
|
+
formatId,
|
|
718
|
+
productId: projectionProduct.product_id,
|
|
719
|
+
field: projectionField
|
|
720
|
+
};
|
|
721
|
+
const contextAwareConverter = converter ? (context) => converter({ ...context, field: projectionField }) : void 0;
|
|
722
|
+
const alreadyProjected = projectV1ProductToV2(
|
|
723
|
+
{ ...projectionProduct, format_ids: [formatId] },
|
|
724
|
+
{ legacyFormatConverter: contextAwareConverter }
|
|
725
|
+
);
|
|
726
|
+
if (alreadyProjected.diagnostics.length === 0) continue;
|
|
727
|
+
let resolverEligible = false;
|
|
728
|
+
projectV1ProductToV2(
|
|
729
|
+
{ ...projectionProduct, format_ids: [formatId] },
|
|
730
|
+
{
|
|
731
|
+
legacyFormatConverter: () => {
|
|
732
|
+
resolverEligible = true;
|
|
733
|
+
return {
|
|
734
|
+
format_option_id: "__legacy_resolver_probe__",
|
|
735
|
+
format_kind: "custom",
|
|
736
|
+
format_shape: "__legacy_resolver_probe__",
|
|
737
|
+
format_schema: {
|
|
738
|
+
uri: "https://adcontextprotocol.org/schemas/legacy-resolver-probe.json",
|
|
739
|
+
digest: `sha256:${"0".repeat(64)}`
|
|
740
|
+
},
|
|
741
|
+
params: {}
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
);
|
|
746
|
+
if (!resolverEligible) continue;
|
|
747
|
+
const key = legacyFormatResolutionKey(projectionContext);
|
|
748
|
+
const frozenFormatId = Object.freeze({ ...formatId });
|
|
749
|
+
pending.push(async (signal) => {
|
|
750
|
+
try {
|
|
751
|
+
const value = await invokeLegacyFormatResolver(
|
|
752
|
+
resolver,
|
|
753
|
+
{
|
|
754
|
+
formatId: frozenFormatId,
|
|
755
|
+
productId: resolverProductId,
|
|
756
|
+
field: resolverField,
|
|
757
|
+
operation: "get_products",
|
|
758
|
+
...requestContext.servedAdcpVersion !== void 0 && {
|
|
759
|
+
servedAdcpVersion: requestContext.servedAdcpVersion
|
|
760
|
+
},
|
|
761
|
+
...requestContext.accountId !== void 0 && { accountId: requestContext.accountId }
|
|
762
|
+
},
|
|
763
|
+
signal
|
|
764
|
+
);
|
|
765
|
+
resolutions.set(key, value);
|
|
766
|
+
} catch (error) {
|
|
767
|
+
resolutions.set(key, { resolutionError: error });
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
for (const product of response.products) {
|
|
773
|
+
if (!isProjectionProductInput(product)) continue;
|
|
774
|
+
if (Array.isArray(product.format_ids)) {
|
|
775
|
+
scanScope(product, product.product_id, `products[${product.product_id}]`);
|
|
776
|
+
}
|
|
777
|
+
const placements = product.placements;
|
|
778
|
+
if (!Array.isArray(placements)) continue;
|
|
779
|
+
for (let placementIndex = 0; placementIndex < placements.length; placementIndex++) {
|
|
780
|
+
const placement = placements[placementIndex];
|
|
781
|
+
if (!placement || typeof placement !== "object" || Array.isArray(placement)) continue;
|
|
782
|
+
const placementRecord = placement;
|
|
783
|
+
if (Array.isArray(placementRecord.format_options) || !Array.isArray(placementRecord.format_ids)) continue;
|
|
784
|
+
const placementId = typeof placementRecord.placement_id === "string" ? placementRecord.placement_id : String(placementIndex);
|
|
785
|
+
scanScope(
|
|
786
|
+
{
|
|
787
|
+
product_id: `${product.product_id}:placement:${placementId}`,
|
|
788
|
+
name: typeof placementRecord.name === "string" ? placementRecord.name : placementId,
|
|
789
|
+
description: `Nested placement ${placementId}`,
|
|
790
|
+
format_ids: placementRecord.format_ids
|
|
791
|
+
},
|
|
792
|
+
product.product_id,
|
|
793
|
+
`products[${product.product_id}].placements[${placementIndex}]`
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
const resolverSignal = createLegacyFormatResolverSignal(requestContext.signal, requestContext.timeoutMs);
|
|
798
|
+
try {
|
|
799
|
+
let nextJob = 0;
|
|
800
|
+
const workerCount = Math.min(requestContext.concurrency, pending.length);
|
|
801
|
+
await Promise.all(
|
|
802
|
+
Array.from({ length: workerCount }, async () => {
|
|
803
|
+
while (nextJob < pending.length) {
|
|
804
|
+
const job = pending[nextJob++];
|
|
805
|
+
if (job) await job(resolverSignal.signal);
|
|
806
|
+
}
|
|
807
|
+
})
|
|
808
|
+
);
|
|
809
|
+
} finally {
|
|
810
|
+
resolverSignal.dispose();
|
|
811
|
+
}
|
|
812
|
+
if (resolutions.size === 0) return converter;
|
|
813
|
+
return (context) => {
|
|
814
|
+
const resolved = resolutions.get(legacyFormatResolutionKey(context));
|
|
815
|
+
if (resolved !== void 0) {
|
|
816
|
+
if (typeof resolved === "object" && resolved !== null && "resolutionError" in resolved) {
|
|
817
|
+
throw resolved.resolutionError;
|
|
818
|
+
}
|
|
819
|
+
return resolved;
|
|
820
|
+
}
|
|
821
|
+
return converter?.(context);
|
|
822
|
+
};
|
|
823
|
+
}
|
|
565
824
|
const authoredFormatIdsByOwner = /* @__PURE__ */ new WeakMap();
|
|
825
|
+
const STORED_LEGACY_FORMAT_ROUTES = "__adcp_private_legacy_format_routes";
|
|
826
|
+
function assertNoReservedLegacyRouteMetadata(value, path) {
|
|
827
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
828
|
+
const visit = (current, currentPath) => {
|
|
829
|
+
if (current === null || typeof current !== "object" || visited.has(current)) return;
|
|
830
|
+
visited.add(current);
|
|
831
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(current))) {
|
|
832
|
+
if (!descriptor.enumerable || !("value" in descriptor)) continue;
|
|
833
|
+
const childPath = Array.isArray(current) ? `${currentPath}[${key}]` : `${currentPath}.${key}`;
|
|
834
|
+
if (key === STORED_LEGACY_FORMAT_ROUTES) {
|
|
835
|
+
throw new AdcpError("INVALID_REQUEST", {
|
|
836
|
+
message: "get_products returned a field reserved for SDK-private route persistence.",
|
|
837
|
+
field: childPath
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
visit(descriptor.value, childPath);
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
visit(value, path);
|
|
844
|
+
}
|
|
845
|
+
function captureStoredLegacyFormatRoutes(value) {
|
|
846
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
847
|
+
const record = value;
|
|
848
|
+
const formatIds = authoredFormatIdsByOwner.get(record);
|
|
849
|
+
const placements = Array.isArray(record.placements) ? record.placements.map((placement) => captureStoredLegacyFormatRoutes(placement) ?? null) : void 0;
|
|
850
|
+
if (!formatIds && !placements?.some(Boolean)) return void 0;
|
|
851
|
+
return {
|
|
852
|
+
...formatIds && { formatIds: formatIds.map((ref) => cloneWireData(ref)) },
|
|
853
|
+
...placements?.some(Boolean) && { placements }
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
function restoreStoredLegacyFormatRoutes(value, routes) {
|
|
857
|
+
if (value === null || typeof value !== "object" || Array.isArray(value) || routes === null || typeof routes !== "object" || Array.isArray(routes)) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
const record = value;
|
|
861
|
+
const routeRecord = routes;
|
|
862
|
+
if (Array.isArray(routeRecord.formatIds) && routeRecord.formatIds.length > 0 && routeRecord.formatIds.every((ref) => isValidStoredLegacyFormatRef(ref))) {
|
|
863
|
+
authoredFormatIdsByOwner.set(
|
|
864
|
+
record,
|
|
865
|
+
routeRecord.formatIds.map((ref) => cloneWireData(ref))
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
if (Array.isArray(record.placements) && Array.isArray(routeRecord.placements)) {
|
|
869
|
+
const count = Math.min(record.placements.length, routeRecord.placements.length);
|
|
870
|
+
for (let index = 0; index < count; index++) {
|
|
871
|
+
restoreStoredLegacyFormatRoutes(record.placements[index], routeRecord.placements[index]);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
function isValidStoredLegacyFormatRef(value) {
|
|
876
|
+
if (legacyFormatRefKey(value) === void 0) return false;
|
|
877
|
+
const ref = value;
|
|
878
|
+
if (ref.agent_url === "" || ref.id === "") return false;
|
|
879
|
+
for (const field of ["width", "height", "duration_ms"]) {
|
|
880
|
+
const fieldValue = ref[field];
|
|
881
|
+
if (fieldValue !== void 0 && (!Number.isInteger(fieldValue) || fieldValue <= 0)) return false;
|
|
882
|
+
}
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
function getHydratedLegacyFormatIds(value) {
|
|
886
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
887
|
+
const refs = authoredFormatIdsByOwner.get(value);
|
|
888
|
+
return refs?.map((ref) => cloneWireData(ref));
|
|
889
|
+
}
|
|
566
890
|
const resolvedLegacyDropDiagnosticsByResponse = /* @__PURE__ */ new WeakMap();
|
|
567
891
|
function ownArrayDataValues(value) {
|
|
568
892
|
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
@@ -950,7 +1274,6 @@ function warnIfTruncatedMultiIdResponse(toolName, idFieldName, requestedIds, res
|
|
|
950
1274
|
);
|
|
951
1275
|
}
|
|
952
1276
|
function createAdcpServerFromPlatform(platform, opts) {
|
|
953
|
-
validatePlatform(platform);
|
|
954
1277
|
const runtimeLegacyOptions = opts;
|
|
955
1278
|
const legacyHandlers = {
|
|
956
1279
|
mediaBuy: opts.legacyHandlers?.mediaBuy ?? runtimeLegacyOptions.mediaBuy,
|
|
@@ -958,9 +1281,21 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
958
1281
|
governance: opts.legacyHandlers?.governance ?? runtimeLegacyOptions.governance,
|
|
959
1282
|
brandRights: opts.legacyHandlers?.brandRights ?? runtimeLegacyOptions.brandRights
|
|
960
1283
|
};
|
|
1284
|
+
validatePlatform(platform, {
|
|
1285
|
+
creative: legacyHandlers.creative,
|
|
1286
|
+
campaignGovernance: legacyHandlers.governance,
|
|
1287
|
+
brandRights: legacyHandlers.brandRights
|
|
1288
|
+
});
|
|
961
1289
|
{
|
|
962
1290
|
const specialisms = platform.capabilities.specialisms;
|
|
963
|
-
const
|
|
1291
|
+
const effectiveSpecialismSurface = {
|
|
1292
|
+
...platform,
|
|
1293
|
+
mediaBuy: legacyHandlers.mediaBuy,
|
|
1294
|
+
creative: platform.creative ?? legacyHandlers.creative,
|
|
1295
|
+
governance: legacyHandlers.governance,
|
|
1296
|
+
brandRights: platform.brandRights ?? legacyHandlers.brandRights
|
|
1297
|
+
};
|
|
1298
|
+
const issues = validateSpecialismRequiredTools(effectiveSpecialismSurface, specialisms);
|
|
964
1299
|
if (issues.length > 0) {
|
|
965
1300
|
const messages = issues.map(formatSpecialismIssue);
|
|
966
1301
|
if (opts.strictSpecialismValidation === true) {
|
|
@@ -1119,6 +1454,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1119
1454
|
};
|
|
1120
1455
|
const adopterCreative = platform.capabilities.creative;
|
|
1121
1456
|
const adopterAccount = platform.capabilities.account;
|
|
1457
|
+
const adopterExtensionsSupported = platform.capabilities.extensions_supported;
|
|
1458
|
+
const adopterCapabilityExt = platform.capabilities.ext;
|
|
1122
1459
|
const adopterOverrides = platform.capabilities.overrides;
|
|
1123
1460
|
const adopterSupportedVersions = platform.capabilities.supported_versions;
|
|
1124
1461
|
const hasOverridesObject = hasOverridesProjection || adopterOverrides !== void 0;
|
|
@@ -1132,6 +1469,10 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1132
1469
|
},
|
|
1133
1470
|
...adopterCreative !== void 0 && { creative: adopterCreative },
|
|
1134
1471
|
...adopterAccount !== void 0 && { account: adopterAccount },
|
|
1472
|
+
...adopterExtensionsSupported !== void 0 && {
|
|
1473
|
+
extensions_supported: [...adopterExtensionsSupported]
|
|
1474
|
+
},
|
|
1475
|
+
...adopterCapabilityExt !== void 0 && { ext: adopterCapabilityExt },
|
|
1135
1476
|
...adopterSupportedVersions !== void 0 && {
|
|
1136
1477
|
supported_versions: [...adopterSupportedVersions]
|
|
1137
1478
|
},
|
|
@@ -1305,6 +1646,21 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1305
1646
|
opts.mediaBuyStore,
|
|
1306
1647
|
opts.proposalStore,
|
|
1307
1648
|
opts.legacyCreativeFormatConverter,
|
|
1649
|
+
opts.legacyCreativeFormatResolver,
|
|
1650
|
+
{
|
|
1651
|
+
timeoutMs: legacyFormatResolverLimit(
|
|
1652
|
+
opts.legacyCreativeFormatResolverTimeoutMs,
|
|
1653
|
+
DEFAULT_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS,
|
|
1654
|
+
"legacyCreativeFormatResolverTimeoutMs",
|
|
1655
|
+
MAX_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS
|
|
1656
|
+
),
|
|
1657
|
+
concurrency: legacyFormatResolverLimit(
|
|
1658
|
+
opts.legacyCreativeFormatResolverConcurrency,
|
|
1659
|
+
DEFAULT_LEGACY_FORMAT_RESOLVER_CONCURRENCY,
|
|
1660
|
+
"legacyCreativeFormatResolverConcurrency",
|
|
1661
|
+
MAX_LEGACY_FORMAT_RESOLVER_CONCURRENCY
|
|
1662
|
+
)
|
|
1663
|
+
},
|
|
1308
1664
|
opts.canonicalFormatLegacyResolver,
|
|
1309
1665
|
defaultCreativeWireMode
|
|
1310
1666
|
),
|
|
@@ -2376,8 +2732,15 @@ async function autoStoreResources(store, accountId, kind, resources, idField, lo
|
|
|
2376
2732
|
continue;
|
|
2377
2733
|
}
|
|
2378
2734
|
const ctxMeta = obj["ctx_metadata"];
|
|
2379
|
-
const {
|
|
2735
|
+
const {
|
|
2736
|
+
ctx_metadata: _stripped,
|
|
2737
|
+
[STORED_LEGACY_FORMAT_ROUTES]: _reservedRouteMetadata,
|
|
2738
|
+
...wireResource
|
|
2739
|
+
} = obj;
|
|
2380
2740
|
void _stripped;
|
|
2741
|
+
void _reservedRouteMetadata;
|
|
2742
|
+
const legacyFormatRoutes = kind === "product" ? captureStoredLegacyFormatRoutes(obj) : void 0;
|
|
2743
|
+
if (legacyFormatRoutes) wireResource[STORED_LEGACY_FORMAT_ROUTES] = legacyFormatRoutes;
|
|
2381
2744
|
try {
|
|
2382
2745
|
await store.setResource(accountId, kind, id, wireResource, ctxMeta);
|
|
2383
2746
|
} catch (err) {
|
|
@@ -2451,7 +2814,10 @@ async function hydratePackagesWithProducts(store, accountId, packages, logger, l
|
|
|
2451
2814
|
if (!entry?.resource || typeof entry.resource !== "object") continue;
|
|
2452
2815
|
let hydrated;
|
|
2453
2816
|
try {
|
|
2454
|
-
|
|
2817
|
+
const storedResource = entry.resource;
|
|
2818
|
+
const { [STORED_LEGACY_FORMAT_ROUTES]: storedLegacyFormatRoutes, ...resource } = storedResource;
|
|
2819
|
+
hydrated = asCanonicalSemanticServerRequest(resource, "hydrate_product", legacyFormatConverter);
|
|
2820
|
+
restoreStoredLegacyFormatRoutes(hydrated, storedLegacyFormatRoutes);
|
|
2455
2821
|
} catch {
|
|
2456
2822
|
logger.warn(
|
|
2457
2823
|
`[adcp/decisioning] auto-hydrate product:${productId} skipped: stored creative format has no canonical representation`
|
|
@@ -2804,7 +3170,7 @@ function buildProposalNegotiationHandlers(platform, taskRegistry, taskWebhookEmi
|
|
|
2804
3170
|
}
|
|
2805
3171
|
};
|
|
2806
3172
|
}
|
|
2807
|
-
function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observability, logger, pushOpts, ctxFor, ctxMetadataStore, mediaBuyStore, proposalStore, legacyFormatConverter, canonicalFormatLegacyResolver, creativeWireMode) {
|
|
3173
|
+
function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observability, logger, pushOpts, ctxFor, ctxMetadataStore, mediaBuyStore, proposalStore, legacyFormatConverter, legacyFormatResolver, legacyFormatResolverOptions, canonicalFormatLegacyResolver, creativeWireMode) {
|
|
2808
3174
|
const sales = platform.sales;
|
|
2809
3175
|
const lifecycle = platform.mediaBuyLifecycle;
|
|
2810
3176
|
const getMediaBuyDelivery = lifecycle?.getMediaBuyDelivery ?? sales?.getMediaBuyDelivery;
|
|
@@ -2963,7 +3329,22 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
2963
3329
|
result = await sales.getProducts(canonicalParams, reqCtx);
|
|
2964
3330
|
}
|
|
2965
3331
|
const projectProducts = async (terminalResult) => {
|
|
2966
|
-
const
|
|
3332
|
+
const preparedProjection = preparePerProductProjectionCatalogs(terminalResult, legacyFormatConverter);
|
|
3333
|
+
const requestLegacyFormatConverter = await resolveLegacyProductFormats(
|
|
3334
|
+
preparedProjection.response,
|
|
3335
|
+
preparedProjection.converter,
|
|
3336
|
+
legacyFormatResolver,
|
|
3337
|
+
{
|
|
3338
|
+
...ctx.servedAdcpVersion !== void 0 && { servedAdcpVersion: ctx.servedAdcpVersion },
|
|
3339
|
+
...reqCtx.account?.id !== void 0 && { accountId: reqCtx.account.id },
|
|
3340
|
+
...ctx.signal !== void 0 && { signal: ctx.signal },
|
|
3341
|
+
...legacyFormatResolverOptions
|
|
3342
|
+
}
|
|
3343
|
+
);
|
|
3344
|
+
const canonicalResult = asCanonicalProductResponse(
|
|
3345
|
+
preparedProjection.response,
|
|
3346
|
+
requestLegacyFormatConverter
|
|
3347
|
+
);
|
|
2967
3348
|
await autoStoreResources(
|
|
2968
3349
|
ctxMetadataStore,
|
|
2969
3350
|
reqCtx.account?.id,
|
|
@@ -3153,6 +3534,20 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
|
|
|
3153
3534
|
logger,
|
|
3154
3535
|
legacyFormatConverter
|
|
3155
3536
|
);
|
|
3537
|
+
await hydratePackagesWithProducts(
|
|
3538
|
+
ctxMetadataStore,
|
|
3539
|
+
reqCtx.account?.id,
|
|
3540
|
+
params.packages,
|
|
3541
|
+
logger,
|
|
3542
|
+
legacyFormatConverter
|
|
3543
|
+
);
|
|
3544
|
+
await hydratePackagesWithProducts(
|
|
3545
|
+
ctxMetadataStore,
|
|
3546
|
+
reqCtx.account?.id,
|
|
3547
|
+
params.new_packages,
|
|
3548
|
+
logger,
|
|
3549
|
+
legacyFormatConverter
|
|
3550
|
+
);
|
|
3156
3551
|
if (proposalStore) {
|
|
3157
3552
|
const record = await maybeHydrateRecipesForMediaBuyId({
|
|
3158
3553
|
mediaBuyId: media_buy_id,
|
|
@@ -4309,6 +4704,7 @@ export {
|
|
|
4309
4704
|
INTENTIONALLY_UNHYDRATED_ENTITIES,
|
|
4310
4705
|
_resetMergeSeamDedupe,
|
|
4311
4706
|
createAdcpServerFromPlatform,
|
|
4312
|
-
getAllAdcpMigrations
|
|
4707
|
+
getAllAdcpMigrations,
|
|
4708
|
+
getHydratedLegacyFormatIds
|
|
4313
4709
|
};
|
|
4314
4710
|
//# sourceMappingURL=from-platform.mjs.map
|