@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.
Files changed (150) hide show
  1. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  2. package/dist/lib/core/ConversationTypes.d.mts +8 -0
  3. package/dist/lib/core/ConversationTypes.d.ts +8 -0
  4. package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
  5. package/dist/lib/core/ConversationTypes.js.map +1 -1
  6. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  7. package/dist/lib/core/SingleAgentClient.js +30 -3
  8. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  9. package/dist/lib/core/SingleAgentClient.mjs +30 -3
  10. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  11. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  12. package/dist/lib/core/TaskExecutor.js +32 -5
  13. package/dist/lib/core/TaskExecutor.js.map +1 -1
  14. package/dist/lib/core/TaskExecutor.mjs +32 -5
  15. package/dist/lib/core/TaskExecutor.mjs.map +1 -1
  16. package/dist/lib/index.d.mts +2 -2
  17. package/dist/lib/index.d.ts +2 -2
  18. package/dist/lib/index.d.ts.map +1 -1
  19. package/dist/lib/index.js +2 -0
  20. package/dist/lib/index.js.map +1 -1
  21. package/dist/lib/index.mjs +2 -1
  22. package/dist/lib/index.mjs.map +1 -1
  23. package/dist/lib/schemas/index.d.mts +14 -0
  24. package/dist/lib/schemas/index.d.ts +14 -0
  25. package/dist/lib/schemas/index.d.ts.map +1 -1
  26. package/dist/lib/schemas/index.js +13 -1
  27. package/dist/lib/schemas/index.js.map +1 -1
  28. package/dist/lib/schemas/index.mjs +13 -1
  29. package/dist/lib/schemas/index.mjs.map +1 -1
  30. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  31. package/dist/lib/server/adcp-server.d.mts +1 -0
  32. package/dist/lib/server/adcp-server.d.ts +1 -0
  33. package/dist/lib/server/adcp-server.d.ts.map +1 -1
  34. package/dist/lib/server/adcp-server.js +1 -1
  35. package/dist/lib/server/adcp-server.js.map +1 -1
  36. package/dist/lib/server/adcp-server.mjs +1 -1
  37. package/dist/lib/server/adcp-server.mjs.map +1 -1
  38. package/dist/lib/server/create-adcp-server.d.mts +10 -2
  39. package/dist/lib/server/create-adcp-server.d.ts +10 -2
  40. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  41. package/dist/lib/server/create-adcp-server.js +26 -19
  42. package/dist/lib/server/create-adcp-server.js.map +1 -1
  43. package/dist/lib/server/create-adcp-server.mjs +26 -26
  44. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  45. package/dist/lib/server/decisioning/capabilities.d.mts +15 -1
  46. package/dist/lib/server/decisioning/capabilities.d.ts +15 -1
  47. package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -1
  48. package/dist/lib/server/decisioning/capabilities.js.map +1 -1
  49. package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
  50. package/dist/lib/server/decisioning/index.d.mts +2 -2
  51. package/dist/lib/server/decisioning/index.d.ts +2 -2
  52. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  53. package/dist/lib/server/decisioning/index.js +2 -0
  54. package/dist/lib/server/decisioning/index.js.map +1 -1
  55. package/dist/lib/server/decisioning/index.mjs +2 -0
  56. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  57. package/dist/lib/server/decisioning/proposal/types.d.mts +3 -2
  58. package/dist/lib/server/decisioning/proposal/types.d.ts +3 -2
  59. package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -1
  60. package/dist/lib/server/decisioning/proposal/types.js.map +1 -1
  61. package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
  62. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +14 -1
  63. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +14 -1
  64. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  65. package/dist/lib/server/decisioning/runtime/from-platform.js +402 -9
  66. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  67. package/dist/lib/server/decisioning/runtime/from-platform.mjs +405 -9
  68. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  69. package/dist/lib/server/decisioning/runtime/validate-platform.d.mts +1 -1
  70. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +1 -1
  71. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -1
  72. package/dist/lib/server/decisioning/runtime/validate-platform.js +2 -2
  73. package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -1
  74. package/dist/lib/server/decisioning/runtime/validate-platform.mjs +2 -2
  75. package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
  76. package/dist/lib/server/decisioning/specialisms/sales.d.mts +7 -1
  77. package/dist/lib/server/decisioning/specialisms/sales.d.ts +7 -1
  78. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
  79. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
  80. package/dist/lib/storage/interfaces.d.mts +2 -0
  81. package/dist/lib/storage/interfaces.d.ts +2 -0
  82. package/dist/lib/storage/interfaces.d.ts.map +1 -1
  83. package/dist/lib/storage/interfaces.js.map +1 -1
  84. package/dist/lib/testing/compliance/comply.d.mts +18 -0
  85. package/dist/lib/testing/compliance/comply.d.ts +18 -0
  86. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  87. package/dist/lib/testing/compliance/comply.js +30 -5
  88. package/dist/lib/testing/compliance/comply.js.map +1 -1
  89. package/dist/lib/testing/compliance/comply.mjs +28 -4
  90. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  91. package/dist/lib/testing/compliance/index.d.mts +1 -1
  92. package/dist/lib/testing/compliance/index.d.ts +1 -1
  93. package/dist/lib/testing/compliance/index.d.ts.map +1 -1
  94. package/dist/lib/testing/compliance/index.js +4 -2
  95. package/dist/lib/testing/compliance/index.js.map +1 -1
  96. package/dist/lib/testing/compliance/index.mjs +4 -2
  97. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  98. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  99. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  100. package/dist/lib/types/list-creatives.d.ts +129 -6
  101. package/dist/lib/types/schemas.generated.d.ts +411 -16
  102. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  103. package/dist/lib/types/schemas.generated.js +22 -6
  104. package/dist/lib/types/schemas.generated.js.map +1 -1
  105. package/dist/lib/types/schemas.generated.mjs +22 -6
  106. package/dist/lib/types/schemas.generated.mjs.map +1 -1
  107. package/dist/lib/types/tools.generated.d.mts +80 -6
  108. package/dist/lib/types/tools.generated.d.ts +80 -6
  109. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  110. package/dist/lib/types/tools.generated.js.map +1 -1
  111. package/dist/lib/utils/adcp-version-config.d.mts +12 -0
  112. package/dist/lib/utils/adcp-version-config.d.ts +12 -0
  113. package/dist/lib/utils/adcp-version-config.d.ts.map +1 -1
  114. package/dist/lib/utils/adcp-version-config.js +5 -3
  115. package/dist/lib/utils/adcp-version-config.js.map +1 -1
  116. package/dist/lib/utils/adcp-version-config.mjs +4 -3
  117. package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
  118. package/dist/lib/utils/pricing-adapter.d.mts +2 -0
  119. package/dist/lib/utils/pricing-adapter.d.ts +2 -0
  120. package/dist/lib/utils/pricing-adapter.d.ts.map +1 -1
  121. package/dist/lib/utils/pricing-adapter.js +68 -1
  122. package/dist/lib/utils/pricing-adapter.js.map +1 -1
  123. package/dist/lib/utils/pricing-adapter.mjs +67 -1
  124. package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
  125. package/dist/lib/v2/projection/index.d.mts +1 -1
  126. package/dist/lib/v2/projection/index.d.ts +1 -1
  127. package/dist/lib/v2/projection/index.d.ts.map +1 -1
  128. package/dist/lib/v2/projection/index.js.map +1 -1
  129. package/dist/lib/v2/projection/index.mjs.map +1 -1
  130. package/dist/lib/v2/projection/v1-to-v2.d.mts +17 -3
  131. package/dist/lib/v2/projection/v1-to-v2.d.ts +17 -3
  132. package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
  133. package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
  134. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  135. package/dist/lib/validation/schema-loader.d.mts +17 -0
  136. package/dist/lib/validation/schema-loader.d.ts +17 -0
  137. package/dist/lib/validation/schema-loader.d.ts.map +1 -1
  138. package/dist/lib/validation/schema-loader.js +24 -0
  139. package/dist/lib/validation/schema-loader.js.map +1 -1
  140. package/dist/lib/validation/schema-loader.mjs +23 -0
  141. package/dist/lib/validation/schema-loader.mjs.map +1 -1
  142. package/dist/lib/version.d.mts +3 -3
  143. package/dist/lib/version.d.ts +3 -3
  144. package/dist/lib/version.js +3 -3
  145. package/dist/lib/version.js.map +1 -1
  146. package/dist/lib/version.mjs +3 -3
  147. package/dist/lib/version.mjs.map +1 -1
  148. package/docs/llms.txt +2 -2
  149. package/docs/migration-13-to-14.md +59 -0
  150. package/package.json +1 -1
@@ -22,7 +22,8 @@ __export(from_platform_exports, {
22
22
  INTENTIONALLY_UNHYDRATED_ENTITIES: () => INTENTIONALLY_UNHYDRATED_ENTITIES,
23
23
  _resetMergeSeamDedupe: () => _resetMergeSeamDedupe,
24
24
  createAdcpServerFromPlatform: () => createAdcpServerFromPlatform,
25
- getAllAdcpMigrations: () => getAllAdcpMigrations
25
+ getAllAdcpMigrations: () => getAllAdcpMigrations,
26
+ getHydratedLegacyFormatIds: () => getHydratedLegacyFormatIds
26
27
  });
27
28
  module.exports = __toCommonJS(from_platform_exports);
28
29
  var import_node_crypto = require("node:crypto");
@@ -59,6 +60,7 @@ var import_normalize_errors = require('../../normalize-errors.js');
59
60
  var import_redact = require('../../redact.js');
60
61
  var import_creative_delivery = require('../../../v2/projection/creative-delivery.js');
61
62
  var import_v1_to_v2 = require('../../../v2/projection/v1-to-v2.js');
63
+ var import_catalog_snapshot = require('../../../v2/projection/catalog-snapshot.js');
62
64
  var import_augment_response = require('../../../v2/projection/augment-response.js');
63
65
  var import_v2_to_v1 = require('../../../v2/projection/v2-to-v1.js');
64
66
  var import_types2 = require('../../../v2/projection/types.js');
@@ -515,7 +517,7 @@ function asCanonicalListCreativesRequest(request, legacyFormatConverter, respons
515
517
  ];
516
518
  return { ...withLegacyFilter, fields };
517
519
  }
518
- function asCanonicalProductResponse(response, legacyFormatConverter) {
520
+ function assertSafeGetProductsResponse(response) {
519
521
  try {
520
522
  assertSafeSemanticPayload(response, "get_products");
521
523
  } catch (error) {
@@ -526,6 +528,9 @@ function asCanonicalProductResponse(response, legacyFormatConverter) {
526
528
  suggestion: "Return an acyclic data-only product response without enumerable accessors."
527
529
  });
528
530
  }
531
+ }
532
+ function asCanonicalProductResponse(response, legacyFormatConverter) {
533
+ assertSafeGetProductsResponse(response);
529
534
  validateDualProductFormatDeclarations(response, legacyFormatConverter);
530
535
  const projected = (0, import_augment_response.toCanonicalOnlyResponse)(response, {
531
536
  legacyFormatConverter
@@ -551,7 +556,323 @@ function asCanonicalProductResponse(response, legacyFormatConverter) {
551
556
  preserveAuthoredFormatIds(response, canonicalResponse);
552
557
  return canonicalResponse;
553
558
  }
559
+ function legacyFormatResolutionKey(context) {
560
+ const formatId = context.formatId;
561
+ return JSON.stringify([
562
+ context.productId,
563
+ context.field,
564
+ formatId.agent_url,
565
+ formatId.id,
566
+ formatId.width ?? null,
567
+ formatId.height ?? null,
568
+ formatId.duration_ms ?? null
569
+ ]);
570
+ }
571
+ function preparePerProductProjectionCatalogs(response, fallback) {
572
+ assertSafeGetProductsResponse(response);
573
+ if (!Array.isArray(response.products)) return { response, converter: fallback };
574
+ assertNoReservedLegacyRouteMetadata(response.products, "products");
575
+ const converters = /* @__PURE__ */ new Map();
576
+ const productIdCounts = /* @__PURE__ */ new Map();
577
+ for (const product of response.products) {
578
+ if (!product || typeof product !== "object" || Array.isArray(product)) continue;
579
+ const productId = product.product_id;
580
+ if (typeof productId === "string") productIdCounts.set(productId, (productIdCounts.get(productId) ?? 0) + 1);
581
+ }
582
+ let strippedCatalogMetadata = false;
583
+ const products = response.products.map((product) => {
584
+ if (!product || typeof product !== "object" || Array.isArray(product)) return product;
585
+ const record = product;
586
+ if (!Object.prototype.hasOwnProperty.call(record, "projectionCatalogs")) return product;
587
+ strippedCatalogMetadata = true;
588
+ const { projectionCatalogs, ...wireProduct } = record;
589
+ if (!Array.isArray(projectionCatalogs)) {
590
+ throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
591
+ message: "get_products projectionCatalogs must be an array of immutable catalog snapshots.",
592
+ field: `products[${String(record.product_id ?? "?")}].projectionCatalogs`
593
+ });
594
+ }
595
+ if (typeof record.product_id === "string" && (productIdCounts.get(record.product_id) ?? 0) > 1) {
596
+ throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
597
+ message: "get_products projection catalogs require unique product identifiers.",
598
+ field: `products[${record.product_id}].projectionCatalogs`
599
+ });
600
+ }
601
+ if (projectionCatalogs.length > 0 && typeof record.product_id === "string") {
602
+ if (converters.has(record.product_id)) {
603
+ throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
604
+ message: "get_products cannot attach different projection catalogs to duplicate product identifiers.",
605
+ field: `products[${record.product_id}].projectionCatalogs`
606
+ });
607
+ }
608
+ const converter2 = (0, import_catalog_snapshot.legacyFormatConverterFromCatalogSnapshots)(
609
+ projectionCatalogs
610
+ );
611
+ if (converter2) {
612
+ converters.set(record.product_id, converter2);
613
+ const placements = wireProduct.placements;
614
+ if (Array.isArray(placements)) {
615
+ for (let placementIndex = 0; placementIndex < placements.length; placementIndex++) {
616
+ const placement = placements[placementIndex];
617
+ if (!placement || typeof placement !== "object" || Array.isArray(placement)) continue;
618
+ const placementRecord = placement;
619
+ const placementId = typeof placementRecord.placement_id === "string" ? placementRecord.placement_id : String(placementIndex);
620
+ const projectionProductId = `${record.product_id}:placement:${placementId}`;
621
+ if (converters.has(projectionProductId)) {
622
+ throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
623
+ message: "get_products projection catalog scopes resolve to a duplicate product identifier.",
624
+ field: `products[${record.product_id}].placements[${placementIndex}]`
625
+ });
626
+ }
627
+ converters.set(projectionProductId, converter2);
628
+ }
629
+ }
630
+ }
631
+ }
632
+ return wireProduct;
633
+ });
634
+ const converter = converters.size === 0 ? fallback : (context) => {
635
+ const productConverter = converters.get(context.productId);
636
+ const resolved = productConverter?.(context);
637
+ return resolved === void 0 ? fallback?.(context) : resolved;
638
+ };
639
+ return {
640
+ response: strippedCatalogMetadata ? { ...response, products } : response,
641
+ converter
642
+ };
643
+ }
644
+ const DEFAULT_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS = 1e4;
645
+ const DEFAULT_LEGACY_FORMAT_RESOLVER_CONCURRENCY = 8;
646
+ const MAX_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS = 2147483647;
647
+ const MAX_LEGACY_FORMAT_RESOLVER_CONCURRENCY = 64;
648
+ function legacyFormatResolverLimit(value, fallback, field, maximum) {
649
+ if (value === void 0) return fallback;
650
+ if (!Number.isSafeInteger(value) || value <= 0 || maximum !== void 0 && value > maximum) {
651
+ const range = maximum === void 0 ? "a positive safe integer" : `an integer between 1 and ${maximum}`;
652
+ throw new import_validate_platform.PlatformConfigError(`${field} must be ${range}.`);
653
+ }
654
+ return value;
655
+ }
656
+ function legacyFormatResolverAbortError(signal) {
657
+ return signal.reason instanceof Error ? signal.reason : new Error("legacyCreativeFormatResolver was aborted before projection completed.");
658
+ }
659
+ function createLegacyFormatResolverSignal(requestSignal, timeoutMs) {
660
+ const controller = new AbortController();
661
+ const abortFromRequest = () => controller.abort(requestSignal?.reason);
662
+ if (requestSignal?.aborted) abortFromRequest();
663
+ else requestSignal?.addEventListener("abort", abortFromRequest, { once: true });
664
+ const timeout = controller.signal.aborted ? void 0 : setTimeout(
665
+ () => controller.abort(new Error(`legacyCreativeFormatResolver exceeded its ${timeoutMs}ms deadline.`)),
666
+ timeoutMs
667
+ );
668
+ return {
669
+ signal: controller.signal,
670
+ dispose() {
671
+ if (timeout !== void 0) clearTimeout(timeout);
672
+ requestSignal?.removeEventListener("abort", abortFromRequest);
673
+ }
674
+ };
675
+ }
676
+ async function invokeLegacyFormatResolver(resolver, context, signal) {
677
+ if (signal.aborted) throw legacyFormatResolverAbortError(signal);
678
+ let abortListener;
679
+ const aborted = new Promise((_resolve, reject) => {
680
+ abortListener = () => reject(legacyFormatResolverAbortError(signal));
681
+ signal.addEventListener("abort", abortListener, { once: true });
682
+ });
683
+ try {
684
+ return await Promise.race([Promise.resolve().then(() => resolver({ ...context, signal })), aborted]);
685
+ } finally {
686
+ if (abortListener) signal.removeEventListener("abort", abortListener);
687
+ }
688
+ }
689
+ async function resolveLegacyProductFormats(response, converter, resolver, requestContext) {
690
+ if (!resolver) return converter;
691
+ assertSafeGetProductsResponse(response);
692
+ if (!Array.isArray(response.products)) return converter;
693
+ const resolutions = /* @__PURE__ */ new Map();
694
+ const pending = [];
695
+ const scanScope = (projectionProduct, resolverProductId, resolverFieldPrefix) => {
696
+ if (Array.isArray(projectionProduct.format_options)) return;
697
+ for (let index = 0; index < projectionProduct.format_ids.length; index++) {
698
+ const formatId = projectionProduct.format_ids[index];
699
+ if (!formatId || typeof formatId !== "object" || Array.isArray(formatId)) continue;
700
+ const projectionField = `products[${projectionProduct.product_id}].format_ids[${index}]`;
701
+ const resolverField = `${resolverFieldPrefix}.format_ids[${index}]`;
702
+ const projectionContext = {
703
+ formatId,
704
+ productId: projectionProduct.product_id,
705
+ field: projectionField
706
+ };
707
+ const contextAwareConverter = converter ? (context) => converter({ ...context, field: projectionField }) : void 0;
708
+ const alreadyProjected = (0, import_v1_to_v2.projectV1ProductToV2)(
709
+ { ...projectionProduct, format_ids: [formatId] },
710
+ { legacyFormatConverter: contextAwareConverter }
711
+ );
712
+ if (alreadyProjected.diagnostics.length === 0) continue;
713
+ let resolverEligible = false;
714
+ (0, import_v1_to_v2.projectV1ProductToV2)(
715
+ { ...projectionProduct, format_ids: [formatId] },
716
+ {
717
+ legacyFormatConverter: () => {
718
+ resolverEligible = true;
719
+ return {
720
+ format_option_id: "__legacy_resolver_probe__",
721
+ format_kind: "custom",
722
+ format_shape: "__legacy_resolver_probe__",
723
+ format_schema: {
724
+ uri: "https://adcontextprotocol.org/schemas/legacy-resolver-probe.json",
725
+ digest: `sha256:${"0".repeat(64)}`
726
+ },
727
+ params: {}
728
+ };
729
+ }
730
+ }
731
+ );
732
+ if (!resolverEligible) continue;
733
+ const key = legacyFormatResolutionKey(projectionContext);
734
+ const frozenFormatId = Object.freeze({ ...formatId });
735
+ pending.push(async (signal) => {
736
+ try {
737
+ const value = await invokeLegacyFormatResolver(
738
+ resolver,
739
+ {
740
+ formatId: frozenFormatId,
741
+ productId: resolverProductId,
742
+ field: resolverField,
743
+ operation: "get_products",
744
+ ...requestContext.servedAdcpVersion !== void 0 && {
745
+ servedAdcpVersion: requestContext.servedAdcpVersion
746
+ },
747
+ ...requestContext.accountId !== void 0 && { accountId: requestContext.accountId }
748
+ },
749
+ signal
750
+ );
751
+ resolutions.set(key, value);
752
+ } catch (error) {
753
+ resolutions.set(key, { resolutionError: error });
754
+ }
755
+ });
756
+ }
757
+ };
758
+ for (const product of response.products) {
759
+ if (!(0, import_types2.isProjectionProductInput)(product)) continue;
760
+ if (Array.isArray(product.format_ids)) {
761
+ scanScope(product, product.product_id, `products[${product.product_id}]`);
762
+ }
763
+ const placements = product.placements;
764
+ if (!Array.isArray(placements)) continue;
765
+ for (let placementIndex = 0; placementIndex < placements.length; placementIndex++) {
766
+ const placement = placements[placementIndex];
767
+ if (!placement || typeof placement !== "object" || Array.isArray(placement)) continue;
768
+ const placementRecord = placement;
769
+ if (Array.isArray(placementRecord.format_options) || !Array.isArray(placementRecord.format_ids)) continue;
770
+ const placementId = typeof placementRecord.placement_id === "string" ? placementRecord.placement_id : String(placementIndex);
771
+ scanScope(
772
+ {
773
+ product_id: `${product.product_id}:placement:${placementId}`,
774
+ name: typeof placementRecord.name === "string" ? placementRecord.name : placementId,
775
+ description: `Nested placement ${placementId}`,
776
+ format_ids: placementRecord.format_ids
777
+ },
778
+ product.product_id,
779
+ `products[${product.product_id}].placements[${placementIndex}]`
780
+ );
781
+ }
782
+ }
783
+ const resolverSignal = createLegacyFormatResolverSignal(requestContext.signal, requestContext.timeoutMs);
784
+ try {
785
+ let nextJob = 0;
786
+ const workerCount = Math.min(requestContext.concurrency, pending.length);
787
+ await Promise.all(
788
+ Array.from({ length: workerCount }, async () => {
789
+ while (nextJob < pending.length) {
790
+ const job = pending[nextJob++];
791
+ if (job) await job(resolverSignal.signal);
792
+ }
793
+ })
794
+ );
795
+ } finally {
796
+ resolverSignal.dispose();
797
+ }
798
+ if (resolutions.size === 0) return converter;
799
+ return (context) => {
800
+ const resolved = resolutions.get(legacyFormatResolutionKey(context));
801
+ if (resolved !== void 0) {
802
+ if (typeof resolved === "object" && resolved !== null && "resolutionError" in resolved) {
803
+ throw resolved.resolutionError;
804
+ }
805
+ return resolved;
806
+ }
807
+ return converter?.(context);
808
+ };
809
+ }
554
810
  const authoredFormatIdsByOwner = /* @__PURE__ */ new WeakMap();
811
+ const STORED_LEGACY_FORMAT_ROUTES = "__adcp_private_legacy_format_routes";
812
+ function assertNoReservedLegacyRouteMetadata(value, path) {
813
+ const visited = /* @__PURE__ */ new WeakSet();
814
+ const visit = (current, currentPath) => {
815
+ if (current === null || typeof current !== "object" || visited.has(current)) return;
816
+ visited.add(current);
817
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(current))) {
818
+ if (!descriptor.enumerable || !("value" in descriptor)) continue;
819
+ const childPath = Array.isArray(current) ? `${currentPath}[${key}]` : `${currentPath}.${key}`;
820
+ if (key === STORED_LEGACY_FORMAT_ROUTES) {
821
+ throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
822
+ message: "get_products returned a field reserved for SDK-private route persistence.",
823
+ field: childPath
824
+ });
825
+ }
826
+ visit(descriptor.value, childPath);
827
+ }
828
+ };
829
+ visit(value, path);
830
+ }
831
+ function captureStoredLegacyFormatRoutes(value) {
832
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
833
+ const record = value;
834
+ const formatIds = authoredFormatIdsByOwner.get(record);
835
+ const placements = Array.isArray(record.placements) ? record.placements.map((placement) => captureStoredLegacyFormatRoutes(placement) ?? null) : void 0;
836
+ if (!formatIds && !placements?.some(Boolean)) return void 0;
837
+ return {
838
+ ...formatIds && { formatIds: formatIds.map((ref) => cloneWireData(ref)) },
839
+ ...placements?.some(Boolean) && { placements }
840
+ };
841
+ }
842
+ function restoreStoredLegacyFormatRoutes(value, routes) {
843
+ if (value === null || typeof value !== "object" || Array.isArray(value) || routes === null || typeof routes !== "object" || Array.isArray(routes)) {
844
+ return;
845
+ }
846
+ const record = value;
847
+ const routeRecord = routes;
848
+ if (Array.isArray(routeRecord.formatIds) && routeRecord.formatIds.length > 0 && routeRecord.formatIds.every((ref) => isValidStoredLegacyFormatRef(ref))) {
849
+ authoredFormatIdsByOwner.set(
850
+ record,
851
+ routeRecord.formatIds.map((ref) => cloneWireData(ref))
852
+ );
853
+ }
854
+ if (Array.isArray(record.placements) && Array.isArray(routeRecord.placements)) {
855
+ const count = Math.min(record.placements.length, routeRecord.placements.length);
856
+ for (let index = 0; index < count; index++) {
857
+ restoreStoredLegacyFormatRoutes(record.placements[index], routeRecord.placements[index]);
858
+ }
859
+ }
860
+ }
861
+ function isValidStoredLegacyFormatRef(value) {
862
+ if (legacyFormatRefKey(value) === void 0) return false;
863
+ const ref = value;
864
+ if (ref.agent_url === "" || ref.id === "") return false;
865
+ for (const field of ["width", "height", "duration_ms"]) {
866
+ const fieldValue = ref[field];
867
+ if (fieldValue !== void 0 && (!Number.isInteger(fieldValue) || fieldValue <= 0)) return false;
868
+ }
869
+ return true;
870
+ }
871
+ function getHydratedLegacyFormatIds(value) {
872
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
873
+ const refs = authoredFormatIdsByOwner.get(value);
874
+ return refs?.map((ref) => cloneWireData(ref));
875
+ }
555
876
  const resolvedLegacyDropDiagnosticsByResponse = /* @__PURE__ */ new WeakMap();
556
877
  function ownArrayDataValues(value) {
557
878
  const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
@@ -939,7 +1260,6 @@ function warnIfTruncatedMultiIdResponse(toolName, idFieldName, requestedIds, res
939
1260
  );
940
1261
  }
941
1262
  function createAdcpServerFromPlatform(platform, opts) {
942
- (0, import_validate_platform.validatePlatform)(platform);
943
1263
  const runtimeLegacyOptions = opts;
944
1264
  const legacyHandlers = {
945
1265
  mediaBuy: opts.legacyHandlers?.mediaBuy ?? runtimeLegacyOptions.mediaBuy,
@@ -947,9 +1267,21 @@ function createAdcpServerFromPlatform(platform, opts) {
947
1267
  governance: opts.legacyHandlers?.governance ?? runtimeLegacyOptions.governance,
948
1268
  brandRights: opts.legacyHandlers?.brandRights ?? runtimeLegacyOptions.brandRights
949
1269
  };
1270
+ (0, import_validate_platform.validatePlatform)(platform, {
1271
+ creative: legacyHandlers.creative,
1272
+ campaignGovernance: legacyHandlers.governance,
1273
+ brandRights: legacyHandlers.brandRights
1274
+ });
950
1275
  {
951
1276
  const specialisms = platform.capabilities.specialisms;
952
- const issues = (0, import_validate_specialisms.validateSpecialismRequiredTools)(platform, specialisms);
1277
+ const effectiveSpecialismSurface = {
1278
+ ...platform,
1279
+ mediaBuy: legacyHandlers.mediaBuy,
1280
+ creative: platform.creative ?? legacyHandlers.creative,
1281
+ governance: legacyHandlers.governance,
1282
+ brandRights: platform.brandRights ?? legacyHandlers.brandRights
1283
+ };
1284
+ const issues = (0, import_validate_specialisms.validateSpecialismRequiredTools)(effectiveSpecialismSurface, specialisms);
953
1285
  if (issues.length > 0) {
954
1286
  const messages = issues.map(import_validate_specialisms.formatSpecialismIssue);
955
1287
  if (opts.strictSpecialismValidation === true) {
@@ -1108,6 +1440,8 @@ function createAdcpServerFromPlatform(platform, opts) {
1108
1440
  };
1109
1441
  const adopterCreative = platform.capabilities.creative;
1110
1442
  const adopterAccount = platform.capabilities.account;
1443
+ const adopterExtensionsSupported = platform.capabilities.extensions_supported;
1444
+ const adopterCapabilityExt = platform.capabilities.ext;
1111
1445
  const adopterOverrides = platform.capabilities.overrides;
1112
1446
  const adopterSupportedVersions = platform.capabilities.supported_versions;
1113
1447
  const hasOverridesObject = hasOverridesProjection || adopterOverrides !== void 0;
@@ -1121,6 +1455,10 @@ function createAdcpServerFromPlatform(platform, opts) {
1121
1455
  },
1122
1456
  ...adopterCreative !== void 0 && { creative: adopterCreative },
1123
1457
  ...adopterAccount !== void 0 && { account: adopterAccount },
1458
+ ...adopterExtensionsSupported !== void 0 && {
1459
+ extensions_supported: [...adopterExtensionsSupported]
1460
+ },
1461
+ ...adopterCapabilityExt !== void 0 && { ext: adopterCapabilityExt },
1124
1462
  ...adopterSupportedVersions !== void 0 && {
1125
1463
  supported_versions: [...adopterSupportedVersions]
1126
1464
  },
@@ -1294,6 +1632,21 @@ function createAdcpServerFromPlatform(platform, opts) {
1294
1632
  opts.mediaBuyStore,
1295
1633
  opts.proposalStore,
1296
1634
  opts.legacyCreativeFormatConverter,
1635
+ opts.legacyCreativeFormatResolver,
1636
+ {
1637
+ timeoutMs: legacyFormatResolverLimit(
1638
+ opts.legacyCreativeFormatResolverTimeoutMs,
1639
+ DEFAULT_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS,
1640
+ "legacyCreativeFormatResolverTimeoutMs",
1641
+ MAX_LEGACY_FORMAT_RESOLVER_TIMEOUT_MS
1642
+ ),
1643
+ concurrency: legacyFormatResolverLimit(
1644
+ opts.legacyCreativeFormatResolverConcurrency,
1645
+ DEFAULT_LEGACY_FORMAT_RESOLVER_CONCURRENCY,
1646
+ "legacyCreativeFormatResolverConcurrency",
1647
+ MAX_LEGACY_FORMAT_RESOLVER_CONCURRENCY
1648
+ )
1649
+ },
1297
1650
  opts.canonicalFormatLegacyResolver,
1298
1651
  defaultCreativeWireMode
1299
1652
  ),
@@ -2365,8 +2718,15 @@ async function autoStoreResources(store, accountId, kind, resources, idField, lo
2365
2718
  continue;
2366
2719
  }
2367
2720
  const ctxMeta = obj["ctx_metadata"];
2368
- const { ctx_metadata: _stripped, ...wireResource } = obj;
2721
+ const {
2722
+ ctx_metadata: _stripped,
2723
+ [STORED_LEGACY_FORMAT_ROUTES]: _reservedRouteMetadata,
2724
+ ...wireResource
2725
+ } = obj;
2369
2726
  void _stripped;
2727
+ void _reservedRouteMetadata;
2728
+ const legacyFormatRoutes = kind === "product" ? captureStoredLegacyFormatRoutes(obj) : void 0;
2729
+ if (legacyFormatRoutes) wireResource[STORED_LEGACY_FORMAT_ROUTES] = legacyFormatRoutes;
2370
2730
  try {
2371
2731
  await store.setResource(accountId, kind, id, wireResource, ctxMeta);
2372
2732
  } catch (err) {
@@ -2440,7 +2800,10 @@ async function hydratePackagesWithProducts(store, accountId, packages, logger, l
2440
2800
  if (!entry?.resource || typeof entry.resource !== "object") continue;
2441
2801
  let hydrated;
2442
2802
  try {
2443
- hydrated = asCanonicalSemanticServerRequest(entry.resource, "hydrate_product", legacyFormatConverter);
2803
+ const storedResource = entry.resource;
2804
+ const { [STORED_LEGACY_FORMAT_ROUTES]: storedLegacyFormatRoutes, ...resource } = storedResource;
2805
+ hydrated = asCanonicalSemanticServerRequest(resource, "hydrate_product", legacyFormatConverter);
2806
+ restoreStoredLegacyFormatRoutes(hydrated, storedLegacyFormatRoutes);
2444
2807
  } catch {
2445
2808
  logger.warn(
2446
2809
  `[adcp/decisioning] auto-hydrate product:${productId} skipped: stored creative format has no canonical representation`
@@ -2793,7 +3156,7 @@ function buildProposalNegotiationHandlers(platform, taskRegistry, taskWebhookEmi
2793
3156
  }
2794
3157
  };
2795
3158
  }
2796
- function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observability, logger, pushOpts, ctxFor, ctxMetadataStore, mediaBuyStore, proposalStore, legacyFormatConverter, canonicalFormatLegacyResolver, creativeWireMode) {
3159
+ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observability, logger, pushOpts, ctxFor, ctxMetadataStore, mediaBuyStore, proposalStore, legacyFormatConverter, legacyFormatResolver, legacyFormatResolverOptions, canonicalFormatLegacyResolver, creativeWireMode) {
2797
3160
  const sales = platform.sales;
2798
3161
  const lifecycle = platform.mediaBuyLifecycle;
2799
3162
  const getMediaBuyDelivery = lifecycle?.getMediaBuyDelivery ?? sales?.getMediaBuyDelivery;
@@ -2952,7 +3315,22 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
2952
3315
  result = await sales.getProducts(canonicalParams, reqCtx);
2953
3316
  }
2954
3317
  const projectProducts = async (terminalResult) => {
2955
- const canonicalResult = asCanonicalProductResponse(terminalResult, legacyFormatConverter);
3318
+ const preparedProjection = preparePerProductProjectionCatalogs(terminalResult, legacyFormatConverter);
3319
+ const requestLegacyFormatConverter = await resolveLegacyProductFormats(
3320
+ preparedProjection.response,
3321
+ preparedProjection.converter,
3322
+ legacyFormatResolver,
3323
+ {
3324
+ ...ctx.servedAdcpVersion !== void 0 && { servedAdcpVersion: ctx.servedAdcpVersion },
3325
+ ...reqCtx.account?.id !== void 0 && { accountId: reqCtx.account.id },
3326
+ ...ctx.signal !== void 0 && { signal: ctx.signal },
3327
+ ...legacyFormatResolverOptions
3328
+ }
3329
+ );
3330
+ const canonicalResult = asCanonicalProductResponse(
3331
+ preparedProjection.response,
3332
+ requestLegacyFormatConverter
3333
+ );
2956
3334
  await autoStoreResources(
2957
3335
  ctxMetadataStore,
2958
3336
  reqCtx.account?.id,
@@ -3142,6 +3520,20 @@ function buildMediaBuyHandlers(platform, taskRegistry, taskWebhookEmit, observab
3142
3520
  logger,
3143
3521
  legacyFormatConverter
3144
3522
  );
3523
+ await hydratePackagesWithProducts(
3524
+ ctxMetadataStore,
3525
+ reqCtx.account?.id,
3526
+ params.packages,
3527
+ logger,
3528
+ legacyFormatConverter
3529
+ );
3530
+ await hydratePackagesWithProducts(
3531
+ ctxMetadataStore,
3532
+ reqCtx.account?.id,
3533
+ params.new_packages,
3534
+ logger,
3535
+ legacyFormatConverter
3536
+ );
3145
3537
  if (proposalStore) {
3146
3538
  const record = await (0, import_proposal.maybeHydrateRecipesForMediaBuyId)({
3147
3539
  mediaBuyId: media_buy_id,
@@ -4299,6 +4691,7 @@ function makeAutoSeedBridge(store) {
4299
4691
  INTENTIONALLY_UNHYDRATED_ENTITIES,
4300
4692
  _resetMergeSeamDedupe,
4301
4693
  createAdcpServerFromPlatform,
4302
- getAllAdcpMigrations
4694
+ getAllAdcpMigrations,
4695
+ getHydratedLegacyFormatIds
4303
4696
  });
4304
4697
  //# sourceMappingURL=from-platform.js.map