@adcp/sdk 16.5.0 → 16.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/dist/lib/adapters/version/3.0/brand-fields.d.mts +7 -1
  2. package/dist/lib/adapters/version/3.0/brand-fields.d.ts +7 -1
  3. package/dist/lib/adapters/version/3.0/brand-fields.js +139 -3
  4. package/dist/lib/adapters/version/3.0/brand-fields.mjs +136 -2
  5. package/dist/lib/adapters/version/3.0/index.js +6 -0
  6. package/dist/lib/adapters/version/3.0/index.mjs +7 -1
  7. package/dist/lib/adapters/version/3.1/bidding.js +1 -1
  8. package/dist/lib/adapters/version/3.1/bidding.mjs +1 -1
  9. package/dist/lib/adapters/version/types.d.mts +5 -0
  10. package/dist/lib/adapters/version/types.d.ts +5 -0
  11. package/dist/lib/canonical-references/index.js +2 -0
  12. package/dist/lib/canonical-references/index.mjs +2 -0
  13. package/dist/lib/client/account-changes.d.mts +3 -1
  14. package/dist/lib/client/account-changes.d.ts +3 -1
  15. package/dist/lib/client/account-changes.js +22 -2
  16. package/dist/lib/client/account-changes.mjs +22 -2
  17. package/dist/lib/conformance/oracle.js +3 -2
  18. package/dist/lib/conformance/oracle.mjs +3 -2
  19. package/dist/lib/core/AgentClient.d.mts +165 -1
  20. package/dist/lib/core/AgentClient.d.ts +165 -1
  21. package/dist/lib/core/AgentClient.js +446 -8
  22. package/dist/lib/core/AgentClient.mjs +446 -8
  23. package/dist/lib/core/ConversationTypes.d.mts +8 -0
  24. package/dist/lib/core/ConversationTypes.d.ts +8 -0
  25. package/dist/lib/core/ProtocolResponseParser.d.mts +1 -1
  26. package/dist/lib/core/ProtocolResponseParser.d.ts +1 -1
  27. package/dist/lib/core/ProtocolResponseParser.js +28 -18
  28. package/dist/lib/core/ProtocolResponseParser.mjs +11 -1
  29. package/dist/lib/core/ResponseValidator.js +1 -1
  30. package/dist/lib/core/ResponseValidator.mjs +1 -1
  31. package/dist/lib/core/SingleAgentClient.d.mts +116 -6
  32. package/dist/lib/core/SingleAgentClient.d.ts +116 -6
  33. package/dist/lib/core/SingleAgentClient.js +556 -84
  34. package/dist/lib/core/SingleAgentClient.mjs +545 -72
  35. package/dist/lib/core/TaskExecutor.d.mts +7 -0
  36. package/dist/lib/core/TaskExecutor.d.ts +7 -0
  37. package/dist/lib/core/TaskExecutor.js +23 -8
  38. package/dist/lib/core/TaskExecutor.mjs +23 -8
  39. package/dist/lib/core/task-status.d.mts +2 -0
  40. package/dist/lib/core/task-status.d.ts +2 -0
  41. package/dist/lib/core/task-status.js +11 -2
  42. package/dist/lib/core/task-status.mjs +9 -1
  43. package/dist/lib/errors/index.d.mts +22 -0
  44. package/dist/lib/errors/index.d.ts +22 -0
  45. package/dist/lib/errors/index.js +43 -0
  46. package/dist/lib/errors/index.mjs +42 -0
  47. package/dist/lib/identity-3.3/trust.d.mts +1 -4
  48. package/dist/lib/identity-3.3/trust.d.ts +1 -4
  49. package/dist/lib/identity-3.3/trust.js +34 -21
  50. package/dist/lib/identity-3.3/trust.mjs +34 -21
  51. package/dist/lib/identity-3.3/validation.js +5 -3
  52. package/dist/lib/identity-3.3/validation.mjs +6 -4
  53. package/dist/lib/index.d.mts +8 -54
  54. package/dist/lib/index.d.ts +8 -54
  55. package/dist/lib/index.js +15 -0
  56. package/dist/lib/index.mjs +11 -0
  57. package/dist/lib/media-buy/action-assessment.js +29 -3
  58. package/dist/lib/media-buy/action-assessment.mjs +32 -4
  59. package/dist/lib/media-buy/action-contracts.d.mts +3 -0
  60. package/dist/lib/media-buy/action-contracts.d.ts +3 -0
  61. package/dist/lib/media-buy/action-contracts.js +24 -1
  62. package/dist/lib/media-buy/action-contracts.mjs +22 -1
  63. package/dist/lib/media-buy/compatibility.js +6 -1
  64. package/dist/lib/media-buy/compatibility.mjs +6 -1
  65. package/dist/lib/media-buy/preflight.js +1 -1
  66. package/dist/lib/media-buy/preflight.mjs +3 -2
  67. package/dist/lib/media-buy/types.d.mts +6 -1
  68. package/dist/lib/media-buy/types.d.ts +6 -1
  69. package/dist/lib/protocols/mcp-modern.d.mts +2 -0
  70. package/dist/lib/protocols/mcp-modern.d.ts +2 -0
  71. package/dist/lib/protocols/mcp-modern.js +31 -5
  72. package/dist/lib/protocols/mcp-modern.mjs +31 -5
  73. package/dist/lib/protocols/mcp-scope.d.mts +6 -1
  74. package/dist/lib/protocols/mcp-scope.d.ts +6 -1
  75. package/dist/lib/protocols/mcp-scope.js +25 -3
  76. package/dist/lib/protocols/mcp-scope.mjs +24 -3
  77. package/dist/lib/protocols/mcp.js +12 -6
  78. package/dist/lib/protocols/mcp.mjs +13 -6
  79. package/dist/lib/reporting/inspection.js +1 -0
  80. package/dist/lib/reporting/inspection.mjs +1 -0
  81. package/dist/lib/schemas/browser.d.mts +2 -0
  82. package/dist/lib/schemas/browser.d.ts +2 -0
  83. package/dist/lib/schemas/browser.js +3 -0
  84. package/dist/lib/schemas/browser.mjs +2 -0
  85. package/dist/lib/schemas/index.d.mts +5 -2
  86. package/dist/lib/schemas/index.d.ts +5 -2
  87. package/dist/lib/schemas/index.js +5 -0
  88. package/dist/lib/schemas/index.mjs +4 -0
  89. package/dist/lib/server/account-response-identity.d.mts +17 -0
  90. package/dist/lib/server/account-response-identity.d.ts +17 -0
  91. package/dist/lib/server/account-response-identity.js +52 -0
  92. package/dist/lib/server/account-response-identity.mjs +28 -0
  93. package/dist/lib/server/account-sync-contract.js +1 -0
  94. package/dist/lib/server/account-sync-contract.mjs +1 -0
  95. package/dist/lib/server/create-adcp-server.js +32 -19
  96. package/dist/lib/server/create-adcp-server.mjs +36 -12
  97. package/dist/lib/server/decisioning/account.d.mts +13 -6
  98. package/dist/lib/server/decisioning/account.d.ts +13 -6
  99. package/dist/lib/server/decisioning/account.js +37 -15
  100. package/dist/lib/server/decisioning/account.mjs +37 -15
  101. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +5 -5
  102. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +5 -5
  103. package/dist/lib/server/decisioning/runtime/from-platform.js +6 -6
  104. package/dist/lib/server/decisioning/runtime/from-platform.mjs +6 -6
  105. package/dist/lib/server/index.d.mts +1 -1
  106. package/dist/lib/server/index.d.ts +1 -1
  107. package/dist/lib/server/index.js +2 -0
  108. package/dist/lib/server/index.mjs +2 -0
  109. package/dist/lib/server/media-buy-action-resolver.d.mts +3 -0
  110. package/dist/lib/server/media-buy-action-resolver.d.ts +3 -0
  111. package/dist/lib/server/media-buy-action-resolver.js +32 -0
  112. package/dist/lib/server/media-buy-action-resolver.mjs +32 -0
  113. package/dist/lib/server/media-buy-store.d.mts +26 -12
  114. package/dist/lib/server/media-buy-store.d.ts +26 -12
  115. package/dist/lib/server/media-buy-store.js +69 -21
  116. package/dist/lib/server/media-buy-store.mjs +69 -21
  117. package/dist/lib/server/responses.js +9 -1
  118. package/dist/lib/server/responses.mjs +9 -1
  119. package/dist/lib/server/state-machine.d.mts +10 -11
  120. package/dist/lib/server/state-machine.d.ts +10 -11
  121. package/dist/lib/server/state-machine.js +20 -5
  122. package/dist/lib/server/state-machine.mjs +19 -5
  123. package/dist/lib/signing/agent-fetch.d.mts +1 -1
  124. package/dist/lib/signing/agent-fetch.d.ts +1 -1
  125. package/dist/lib/signing/agent-fetch.js +3 -3
  126. package/dist/lib/signing/agent-fetch.mjs +3 -3
  127. package/dist/lib/testing/client.d.mts +1 -0
  128. package/dist/lib/testing/client.d.ts +1 -0
  129. package/dist/lib/testing/client.js +6 -5
  130. package/dist/lib/testing/client.mjs +6 -5
  131. package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +60 -14
  132. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +60 -14
  133. package/dist/lib/testing/storyboard/compliance.d.mts +2 -5
  134. package/dist/lib/testing/storyboard/compliance.d.ts +2 -5
  135. package/dist/lib/testing/storyboard/compliance.js +62 -13
  136. package/dist/lib/testing/storyboard/compliance.mjs +63 -14
  137. package/dist/lib/testing/storyboard/context.d.mts +13 -3
  138. package/dist/lib/testing/storyboard/context.d.ts +13 -3
  139. package/dist/lib/testing/storyboard/context.js +15 -10
  140. package/dist/lib/testing/storyboard/context.mjs +15 -10
  141. package/dist/lib/testing/storyboard/default-invariants.js +10 -8
  142. package/dist/lib/testing/storyboard/default-invariants.mjs +11 -9
  143. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +2 -0
  144. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +2 -0
  145. package/dist/lib/testing/storyboard/request-signing/vector-loader.js +11 -0
  146. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +10 -0
  147. package/dist/lib/testing/storyboard/runner.js +23 -10
  148. package/dist/lib/testing/storyboard/runner.mjs +23 -10
  149. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  150. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  151. package/dist/lib/testing/storyboard/validations.js +4 -1
  152. package/dist/lib/testing/storyboard/validations.mjs +4 -1
  153. package/dist/lib/testing/test-controller.js +3 -0
  154. package/dist/lib/testing/test-controller.mjs +3 -0
  155. package/dist/lib/types/asset-instances.d.mts +1 -1
  156. package/dist/lib/types/asset-instances.d.ts +1 -1
  157. package/dist/lib/types/index.d.mts +5 -0
  158. package/dist/lib/types/index.d.ts +5 -0
  159. package/dist/lib/types/index.js +6 -1
  160. package/dist/lib/types/index.mjs +4 -1
  161. package/dist/lib/types/inline-enums.generated.d.mts +30 -4
  162. package/dist/lib/types/inline-enums.generated.d.ts +30 -4
  163. package/dist/lib/types/inline-enums.generated.js +41 -2
  164. package/dist/lib/types/inline-enums.generated.mjs +28 -2
  165. package/dist/lib/types/media-buy-delivery-report.d.mts +4 -0
  166. package/dist/lib/types/media-buy-delivery-report.d.ts +4 -0
  167. package/dist/lib/types/media-buy-delivery-report.js +16 -0
  168. package/dist/lib/types/media-buy-delivery-report.mjs +0 -0
  169. package/dist/lib/types/schemas.generated.d.ts +20 -69
  170. package/dist/lib/types/schemas.generated.js +29 -46
  171. package/dist/lib/types/schemas.generated.mjs +29 -46
  172. package/dist/lib/types/targeting-keys.generated.d.mts +4 -0
  173. package/dist/lib/types/targeting-keys.generated.d.ts +4 -0
  174. package/dist/lib/types/targeting-keys.generated.js +105 -0
  175. package/dist/lib/types/targeting-keys.generated.mjs +80 -0
  176. package/dist/lib/utils/adcp-version-config.js +5 -2
  177. package/dist/lib/utils/adcp-version-config.mjs +5 -2
  178. package/dist/lib/utils/envelope-status-compat.d.mts +18 -1
  179. package/dist/lib/utils/envelope-status-compat.d.ts +18 -1
  180. package/dist/lib/utils/envelope-status-compat.js +11 -5
  181. package/dist/lib/utils/envelope-status-compat.mjs +11 -5
  182. package/dist/lib/utils/response-unwrapper.js +18 -10
  183. package/dist/lib/utils/response-unwrapper.mjs +18 -10
  184. package/dist/lib/v2/format-schema/resolver.js +1 -1
  185. package/dist/lib/v2/format-schema/resolver.mjs +1 -1
  186. package/dist/lib/v2/projection/creative-delivery.js +123 -30
  187. package/dist/lib/v2/projection/creative-delivery.mjs +127 -30
  188. package/dist/lib/v2/projection/index.d.mts +1 -0
  189. package/dist/lib/v2/projection/index.d.ts +1 -0
  190. package/dist/lib/v2/projection/index.js +3 -0
  191. package/dist/lib/v2/projection/index.mjs +2 -0
  192. package/dist/lib/v2/projection/legacy-metadata.d.mts +19 -0
  193. package/dist/lib/v2/projection/legacy-metadata.d.ts +19 -0
  194. package/dist/lib/v2/projection/legacy-metadata.js +91 -0
  195. package/dist/lib/v2/projection/legacy-metadata.mjs +86 -0
  196. package/dist/lib/validation/compact-schema.d.mts +27 -0
  197. package/dist/lib/validation/compact-schema.d.ts +27 -0
  198. package/dist/lib/validation/compact-schema.js +276 -0
  199. package/dist/lib/validation/compact-schema.mjs +250 -0
  200. package/dist/lib/validation/media-buy-delivery-report.d.mts +8 -0
  201. package/dist/lib/validation/media-buy-delivery-report.d.ts +8 -0
  202. package/dist/lib/validation/media-buy-delivery-report.js +31 -0
  203. package/dist/lib/validation/media-buy-delivery-report.mjs +7 -0
  204. package/dist/lib/validation/schema-diagnostic-origins.d.mts +21 -0
  205. package/dist/lib/validation/schema-diagnostic-origins.d.ts +21 -0
  206. package/dist/lib/validation/schema-diagnostic-origins.js +193 -0
  207. package/dist/lib/validation/schema-diagnostic-origins.mjs +169 -0
  208. package/dist/lib/validation/schema-loader.js +86 -16
  209. package/dist/lib/validation/schema-loader.mjs +82 -16
  210. package/dist/lib/validation/schema-validator.d.mts +10 -19
  211. package/dist/lib/validation/schema-validator.d.ts +10 -19
  212. package/dist/lib/validation/schema-validator.js +136 -43
  213. package/dist/lib/validation/schema-validator.mjs +140 -44
  214. package/dist/lib/version.d.mts +3 -3
  215. package/dist/lib/version.d.ts +3 -3
  216. package/dist/lib/version.js +3 -3
  217. package/dist/lib/version.mjs +3 -3
  218. package/dist/lib/webhooks/index.d.mts +3 -0
  219. package/dist/lib/webhooks/index.d.ts +3 -0
  220. package/dist/lib/webhooks/index.js +3 -0
  221. package/dist/lib/webhooks/index.mjs +2 -0
  222. package/dist/lib/webhooks/media-buy-delivery.d.mts +43 -0
  223. package/dist/lib/webhooks/media-buy-delivery.d.ts +43 -0
  224. package/dist/lib/webhooks/media-buy-delivery.js +119 -0
  225. package/dist/lib/webhooks/media-buy-delivery.mjs +94 -0
  226. package/docs/TYPE-SUMMARY.md +2 -2
  227. package/docs/guides/BUILD-AN-AGENT.md +9 -1
  228. package/docs/guides/DELIVERY-WEBHOOK-PARSING.md +135 -0
  229. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +15 -0
  230. package/docs/guides/TYPED-CLIENT-TOOLS.md +49 -0
  231. package/docs/llms.txt +3 -3
  232. package/docs/migration-14.x-rc-worksheet.md +4 -4
  233. package/docs/migration-6.6-to-6.7.md +14 -0
  234. package/docs/migration-account-change-feed.md +19 -0
  235. package/docs/releases/sdk-16.6-adoption-fixes.md +33 -0
  236. package/package.json +2 -2
@@ -34,6 +34,7 @@ var import_v2_to_v1 = require('./v2-to-v1.js');
34
34
  var import_legacy_metadata = require('./legacy-metadata.js');
35
35
  var import_jcs = require('../../utils/jcs.js');
36
36
  var import_catalog = require('./catalog.js');
37
+ var import_legacy_metadata2 = require('./legacy-metadata.js');
37
38
  function stripLegacyCreativeIdentity(value) {
38
39
  const legacyTokens = /* @__PURE__ */ new Set();
39
40
  const legacyUrlTokens = /* @__PURE__ */ new Set();
@@ -501,16 +502,38 @@ function creativeFormatParameterConstraints(creative) {
501
502
  if (width === void 0 && height === void 0 && durationMs === void 0) return void 0;
502
503
  return { width, height, durationMs };
503
504
  }
504
- function legacyRefParameterConstraints(ref) {
505
+ function primaryMediaConstraints(creative) {
506
+ const assetType = creative.format_kind === "image" ? "image" : creative.format_kind === "video_hosted" ? "video" : creative.format_kind === "audio_hosted" ? "audio" : void 0;
507
+ if (!assetType) return void 0;
508
+ const assets = Object.values(record(creative.assets) ?? {}).flatMap(
509
+ (value) => (Array.isArray(value) ? value : [value]).flatMap((item) => {
510
+ const asset2 = record(item);
511
+ return asset2?.asset_type === assetType ? [asset2] : [];
512
+ })
513
+ );
514
+ if (assets.length !== 1) return void 0;
515
+ const asset = assets[0];
516
+ const width = assetType === "audio" ? void 0 : positiveConstraint(asset.width);
517
+ const height = assetType === "audio" ? void 0 : positiveConstraint(asset.height);
518
+ const durationMs = assetType === "image" ? void 0 : positiveConstraint(asset.duration_ms);
519
+ return width === void 0 && height === void 0 && durationMs === void 0 ? void 0 : { width, height, durationMs };
520
+ }
521
+ function positiveConstraint(value) {
522
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
523
+ }
524
+ function legacyRefParameterConstraints(ref, selectorParams) {
505
525
  const params = typeof ref.width !== "number" || typeof ref.height !== "number" ? record((0, import_v1_to_v2.canonicalDeclarationFromBareId)(ref.id, { agentUrl: ref.agent_url })?.params) : void 0;
526
+ const selector = record(selectorParams);
527
+ const sizes = Array.isArray(selector?.sizes) ? selector.sizes : [];
528
+ const size = sizes.length === 1 ? record(sizes[0]) : void 0;
506
529
  return {
507
- width: typeof ref.width === "number" ? ref.width : typeof params?.width === "number" ? params.width : void 0,
508
- height: typeof ref.height === "number" ? ref.height : typeof params?.height === "number" ? params.height : void 0,
509
- durationMs: ref.duration_ms
530
+ width: typeof ref.width === "number" ? ref.width : typeof params?.width === "number" ? params.width : positiveConstraint(selector?.width) ?? positiveConstraint(size?.width),
531
+ height: typeof ref.height === "number" ? ref.height : typeof params?.height === "number" ? params.height : positiveConstraint(selector?.height) ?? positiveConstraint(size?.height),
532
+ durationMs: ref.duration_ms ?? positiveConstraint(selector?.duration_ms_exact) ?? positiveConstraint(selector?.duration_ms)
510
533
  };
511
534
  }
512
- function refContradictsConstraints(ref, constraints) {
513
- const refConstraints = legacyRefParameterConstraints(ref);
535
+ function refContradictsConstraints(ref, constraints, selectorParams) {
536
+ const refConstraints = legacyRefParameterConstraints(ref, selectorParams);
514
537
  if (constraints.width !== void 0 && refConstraints.width !== void 0 && refConstraints.width !== constraints.width) {
515
538
  return true;
516
539
  }
@@ -522,8 +545,8 @@ function refContradictsConstraints(ref, constraints) {
522
545
  }
523
546
  return false;
524
547
  }
525
- function refPinsConstraints(ref, constraints) {
526
- const refConstraints = legacyRefParameterConstraints(ref);
548
+ function refPinsConstraints(ref, constraints, selectorParams) {
549
+ const refConstraints = legacyRefParameterConstraints(ref, selectorParams);
527
550
  if (constraints.width !== void 0 && refConstraints.width === void 0) return false;
528
551
  if (constraints.height !== void 0 && refConstraints.height === void 0) return false;
529
552
  if (constraints.durationMs !== void 0 && typeof refConstraints.durationMs !== "number") return false;
@@ -535,8 +558,8 @@ function legacyIdPinsDimensions(ref) {
535
558
  const params = record(declaration.params) ?? {};
536
559
  return typeof params.width === "number" || typeof params.height === "number" || typeof params.duration_ms_exact === "number" || Array.isArray(params.sizes);
537
560
  }
538
- function refConstraintKey(ref) {
539
- const constraints = legacyRefParameterConstraints(ref);
561
+ function refConstraintKey(ref, selectorParams) {
562
+ const constraints = legacyRefParameterConstraints(ref, selectorParams);
540
563
  return [
541
564
  agentIdentity(ref.agent_url),
542
565
  constraints.width ?? "",
@@ -546,14 +569,21 @@ function refConstraintKey(ref) {
546
569
  }
547
570
  function preferMostConstrainedLegacyCandidates(candidates, creative) {
548
571
  let remaining = candidates;
549
- const constraints = creativeFormatParameterConstraints(creative);
572
+ const mediaKind = ["image", "video_hosted", "audio_hosted"].includes(String(creative.format_kind));
573
+ const constraints = creativeFormatParameterConstraints(creative) ?? (remaining.length > 1 ? primaryMediaConstraints(creative) : void 0);
550
574
  if (constraints) {
551
- remaining = remaining.filter((candidate) => !refContradictsConstraints(candidate.ref, constraints));
552
- const pinned = remaining.filter((candidate) => refPinsConstraints(candidate.ref, constraints));
575
+ remaining = remaining.filter(
576
+ (candidate) => !refContradictsConstraints(candidate.ref, constraints, mediaKind ? candidate.selectorParams : void 0)
577
+ );
578
+ const pinned = remaining.filter(
579
+ (candidate) => refPinsConstraints(candidate.ref, constraints, mediaKind ? candidate.selectorParams : void 0)
580
+ );
553
581
  if (pinned.length > 0) remaining = pinned;
554
582
  }
555
583
  if (remaining.length <= 1) return remaining;
556
- const constraintKeys = new Set(remaining.map((candidate) => refConstraintKey(candidate.ref)));
584
+ const constraintKeys = new Set(
585
+ remaining.map((candidate) => refConstraintKey(candidate.ref, mediaKind ? candidate.selectorParams : void 0))
586
+ );
557
587
  if (constraintKeys.size !== 1) return remaining;
558
588
  const specific = remaining.filter((candidate) => legacyIdPinsDimensions(candidate.ref) === true);
559
589
  return specific.length > 0 && specific.length < remaining.length ? specific : remaining;
@@ -592,43 +622,82 @@ function selectLegacyRef(creative, container, canonicalFormatLegacyResolver, ope
592
622
  matching = preferMostConstrainedLegacyCandidates(matching, creative);
593
623
  return matching.length === 1 ? matching[0].ref : void 0;
594
624
  }
625
+ function legacyUrlTrackerSlotMatches(slot, tracker) {
626
+ return slot.asset_type === "url" && slot.requirements?.url_type === "tracker_pixel" && (slot.asset_id === tracker.assetId || slot.requirements.role === tracker.assetId);
627
+ }
595
628
  function projectLegacyAssetKeys(assetsValue, definition) {
629
+ const unchanged = { assets: assetsValue, drifts: [] };
596
630
  const assets = record(assetsValue);
597
- if (!assets || !Array.isArray(definition?.assets)) return assetsValue;
631
+ if (!assets || !Array.isArray(definition?.assets)) return unchanged;
598
632
  const slots = definition.assets.filter((slot) => record(slot) !== void 0);
599
- if (slots.some((slot) => slot.item_type !== void 0 && slot.item_type !== "individual")) return assetsValue;
633
+ if (slots.some((slot) => slot.item_type !== void 0 && slot.item_type !== "individual")) return unchanged;
600
634
  const declaredIds = new Set(slots.map((slot) => slot.asset_id));
601
635
  const availableSlots = slots.filter(
602
- (slot) => (slot.item_type === void 0 || slot.item_type === "individual") && typeof slot.asset_id === "string" && slot.asset_id.length > 0 && !Object.hasOwn(assets, slot.asset_id)
636
+ (slot) => typeof slot.asset_id === "string" && slot.asset_id.length > 0 && !Object.hasOwn(assets, slot.asset_id)
603
637
  );
604
638
  const targetBySource = /* @__PURE__ */ new Map();
605
639
  const sourcesByTarget = /* @__PURE__ */ new Map();
640
+ const trackersBySource = /* @__PURE__ */ new Map();
606
641
  for (const [key, value] of Object.entries(assets)) {
607
- if (declaredIds.has(key)) continue;
642
+ const candidates = (Array.isArray(value) ? value : [value]).map(import_legacy_metadata2.downgradePixelTracker);
643
+ const trackers = candidates.length > 0 && candidates.every((tracker) => tracker !== void 0) ? candidates : void 0;
644
+ const trackerSlotMatches = (slot2) => trackers !== void 0 && trackers.every((tracker) => legacyUrlTrackerSlotMatches(slot2, tracker));
645
+ if (declaredIds.has(key)) {
646
+ const slot2 = slots.find((slot3) => slot3.asset_id === key);
647
+ if (trackers && slot2 && trackerSlotMatches(slot2)) trackersBySource.set(key, trackers);
648
+ continue;
649
+ }
608
650
  const asset = record(value);
609
- if (!asset || typeof asset.asset_type !== "string") continue;
610
- const matches = availableSlots.filter((slot) => {
611
- if (slot.asset_type !== asset.asset_type) return false;
651
+ if (!trackers && (!asset || typeof asset.asset_type !== "string")) continue;
652
+ const matches = availableSlots.filter((slot2) => {
653
+ if (trackerSlotMatches(slot2)) return true;
654
+ if (!asset || slot2.asset_type !== asset.asset_type) return false;
612
655
  if (asset.asset_type === "url") {
613
- return typeof asset.url_type === "string" && asset.url_type === slot.requirements?.url_type;
656
+ return typeof asset.url_type === "string" && asset.url_type === slot2.requirements?.url_type;
614
657
  }
615
658
  if (asset.asset_type === "pixel_tracker") {
616
- return typeof asset.event === "string" && asset.event === slot.event && (asset.event !== "custom" || typeof asset.custom_event_name === "string" && asset.custom_event_name === slot.custom_event_name);
659
+ return typeof asset.event === "string" && asset.event === slot2.event && (asset.event !== "custom" || typeof asset.custom_event_name === "string" && asset.custom_event_name === slot2.custom_event_name);
617
660
  }
618
661
  return true;
619
662
  });
620
663
  if (matches.length !== 1) continue;
621
- const target = matches[0].asset_id;
664
+ const slot = matches[0];
665
+ const target = slot.asset_id;
622
666
  targetBySource.set(key, target);
667
+ if (trackers && trackerSlotMatches(slot)) trackersBySource.set(key, trackers);
623
668
  const sources = sourcesByTarget.get(target) ?? [];
624
669
  sources.push(key);
625
670
  sourcesByTarget.set(target, sources);
626
671
  }
627
672
  for (const sources of sourcesByTarget.values()) {
628
- if (sources.length > 1) for (const source of sources) targetBySource.delete(source);
673
+ if (sources.length > 1) {
674
+ for (const source of sources) {
675
+ targetBySource.delete(source);
676
+ trackersBySource.delete(source);
677
+ }
678
+ }
629
679
  }
630
- if (targetBySource.size === 0) return assetsValue;
631
- return Object.fromEntries(Object.entries(assets).map(([key, value]) => [targetBySource.get(key) ?? key, value]));
680
+ if (targetBySource.size === 0 && trackersBySource.size === 0) return unchanged;
681
+ const drifts = [];
682
+ for (const [key, trackers] of trackersBySource) {
683
+ trackers.forEach((tracker, index) => {
684
+ const path = `assets.${key}${Array.isArray(assets[key]) ? `[${index}]` : ""}`;
685
+ const drift = (0, import_legacy_metadata2.pixelTrackerDrift)(path, tracker);
686
+ if (drift) drifts.push(drift);
687
+ });
688
+ }
689
+ return {
690
+ assets: Object.fromEntries(
691
+ Object.entries(assets).map(([key, value]) => {
692
+ const trackers = trackersBySource.get(key);
693
+ return [
694
+ targetBySource.get(key) ?? key,
695
+ trackers ? Array.isArray(value) ? trackers.map((tracker) => tracker.asset) : trackers[0].asset : value
696
+ ];
697
+ })
698
+ ),
699
+ drifts
700
+ };
632
701
  }
633
702
  function projectCreative(creative, formatId, legacyFormatDefinitions) {
634
703
  const next = { ...creative };
@@ -640,7 +709,12 @@ function projectCreative(creative, formatId, legacyFormatDefinitions) {
640
709
  return ref !== void 0 && sameLegacyIdentity(ref, formatId);
641
710
  });
642
711
  const definition = supplied?.length ? supplied.length === 1 ? supplied[0] : void 0 : (0, import_catalog.lookupV1Format)(formatId);
643
- if (Object.hasOwn(creative, "assets")) next.assets = projectLegacyAssetKeys(creative.assets, definition);
712
+ if (Object.hasOwn(creative, "assets")) {
713
+ const projected = projectLegacyAssetKeys(creative.assets, definition);
714
+ next.assets = projected.assets;
715
+ (0, import_legacy_metadata.transferLegacyCreativeMetadata)(creative, next);
716
+ (0, import_legacy_metadata2.rememberCreativeDeliveryDiagnostics)(next, projected.drifts);
717
+ }
644
718
  return next;
645
719
  }
646
720
  function dedupeLegacyRefs(refs) {
@@ -878,6 +952,7 @@ function projectCreativeForDelivery(creative, selectorContainer, wireMode = "can
878
952
  const inputRecord = creative;
879
953
  const originalLegacyRef = legacyRef(inputRecord.format_id);
880
954
  const creativeRecord = canonicalizeCreative(inputRecord, selectorContainer, operation, legacyFormatConverter);
955
+ (0, import_legacy_metadata.transferLegacyCreativeMetadata)(inputRecord, creativeRecord);
881
956
  if (wireMode === "canonical") return creativeRecord;
882
957
  if (originalLegacyRef) {
883
958
  const selectedOriginal = selectLegacyRef(inputRecord, selectorContainer, canonicalFormatLegacyResolver, operation);
@@ -949,14 +1024,32 @@ function projectCreativeForDelivery(creative, selectorContainer, wireMode = "can
949
1024
  throw new CreativeFormatProjectionError(
950
1025
  operation,
951
1026
  creativeId,
952
- `the seller advertised ${candidates.length} legacy refs for canonical kind ${creativeRecord.format_kind}`
1027
+ `the seller advertised ${candidates.length} legacy refs for canonical kind ${creativeRecord.format_kind}` + (candidates.some((candidate) => legacyIdPinsDimensions(candidate.ref) === true) ? "; set format_parameters.width/height or give the asset one rendered width/height to select one" : "")
953
1028
  );
954
1029
  }
955
- const reason = pinned ? "the creative is pinned to a format option that names none of the selected seller product legacy format references" : "the selected seller product did not provide one unambiguous legacy format reference";
1030
+ const reason = pinned ? "the creative is pinned to a format option that names none of the selected seller product legacy format references" : describeUnmatchedLegacyCandidates(creativeRecord, allCandidates);
956
1031
  throw new CreativeFormatProjectionError(operation, creativeId, reason);
957
1032
  }
958
1033
  return creative;
959
1034
  }
1035
+ function describeUnmatchedLegacyCandidates(creative, allCandidates) {
1036
+ const generic = "the selected seller product did not provide one unambiguous legacy format reference";
1037
+ const kind = String(creative.format_kind);
1038
+ if (allCandidates.length === 0) return generic;
1039
+ const sameKind = allCandidates.filter((candidate) => candidate.formatKind === kind);
1040
+ if (sameKind.length === 0) {
1041
+ const offered = [
1042
+ ...new Set(allCandidates.flatMap((candidate) => candidate.formatKind ? [candidate.formatKind] : []))
1043
+ ];
1044
+ if (offered.length === 0) return generic;
1045
+ return `the selected seller product offers legacy refs for canonical kind ${offered.join(", ")}, not ${kind}`;
1046
+ }
1047
+ const size = creativeFormatParameterConstraints(creative);
1048
+ if (size?.width !== void 0 && size.height !== void 0) {
1049
+ return `none of the seller's ${sameKind.length} ${kind} legacy refs matches the creative's ${size.width}x${size.height} size`;
1050
+ }
1051
+ return generic;
1052
+ }
960
1053
  function projectMediaBuyCreativesForDelivery(request, wireMode = "canonical", operation = "create_media_buy", legacyFormatConverter, canonicalFormatLegacyResolver, legacyFormatDefinitions) {
961
1054
  const requestRecord = record(request);
962
1055
  if (!requestRecord) return request;
@@ -13,6 +13,11 @@ import {
13
13
  } from "./legacy-metadata.mjs";
14
14
  import { canonicalize as canonicalizeJson } from "../../utils/jcs.mjs";
15
15
  import { lookupV1Format } from "./catalog.mjs";
16
+ import {
17
+ downgradePixelTracker,
18
+ pixelTrackerDrift,
19
+ rememberCreativeDeliveryDiagnostics
20
+ } from "./legacy-metadata.mjs";
16
21
  function stripLegacyCreativeIdentity(value) {
17
22
  const legacyTokens = /* @__PURE__ */ new Set();
18
23
  const legacyUrlTokens = /* @__PURE__ */ new Set();
@@ -480,16 +485,38 @@ function creativeFormatParameterConstraints(creative) {
480
485
  if (width === void 0 && height === void 0 && durationMs === void 0) return void 0;
481
486
  return { width, height, durationMs };
482
487
  }
483
- function legacyRefParameterConstraints(ref) {
488
+ function primaryMediaConstraints(creative) {
489
+ const assetType = creative.format_kind === "image" ? "image" : creative.format_kind === "video_hosted" ? "video" : creative.format_kind === "audio_hosted" ? "audio" : void 0;
490
+ if (!assetType) return void 0;
491
+ const assets = Object.values(record(creative.assets) ?? {}).flatMap(
492
+ (value) => (Array.isArray(value) ? value : [value]).flatMap((item) => {
493
+ const asset2 = record(item);
494
+ return asset2?.asset_type === assetType ? [asset2] : [];
495
+ })
496
+ );
497
+ if (assets.length !== 1) return void 0;
498
+ const asset = assets[0];
499
+ const width = assetType === "audio" ? void 0 : positiveConstraint(asset.width);
500
+ const height = assetType === "audio" ? void 0 : positiveConstraint(asset.height);
501
+ const durationMs = assetType === "image" ? void 0 : positiveConstraint(asset.duration_ms);
502
+ return width === void 0 && height === void 0 && durationMs === void 0 ? void 0 : { width, height, durationMs };
503
+ }
504
+ function positiveConstraint(value) {
505
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
506
+ }
507
+ function legacyRefParameterConstraints(ref, selectorParams) {
484
508
  const params = typeof ref.width !== "number" || typeof ref.height !== "number" ? record(canonicalDeclarationFromBareId(ref.id, { agentUrl: ref.agent_url })?.params) : void 0;
509
+ const selector = record(selectorParams);
510
+ const sizes = Array.isArray(selector?.sizes) ? selector.sizes : [];
511
+ const size = sizes.length === 1 ? record(sizes[0]) : void 0;
485
512
  return {
486
- width: typeof ref.width === "number" ? ref.width : typeof params?.width === "number" ? params.width : void 0,
487
- height: typeof ref.height === "number" ? ref.height : typeof params?.height === "number" ? params.height : void 0,
488
- durationMs: ref.duration_ms
513
+ width: typeof ref.width === "number" ? ref.width : typeof params?.width === "number" ? params.width : positiveConstraint(selector?.width) ?? positiveConstraint(size?.width),
514
+ height: typeof ref.height === "number" ? ref.height : typeof params?.height === "number" ? params.height : positiveConstraint(selector?.height) ?? positiveConstraint(size?.height),
515
+ durationMs: ref.duration_ms ?? positiveConstraint(selector?.duration_ms_exact) ?? positiveConstraint(selector?.duration_ms)
489
516
  };
490
517
  }
491
- function refContradictsConstraints(ref, constraints) {
492
- const refConstraints = legacyRefParameterConstraints(ref);
518
+ function refContradictsConstraints(ref, constraints, selectorParams) {
519
+ const refConstraints = legacyRefParameterConstraints(ref, selectorParams);
493
520
  if (constraints.width !== void 0 && refConstraints.width !== void 0 && refConstraints.width !== constraints.width) {
494
521
  return true;
495
522
  }
@@ -501,8 +528,8 @@ function refContradictsConstraints(ref, constraints) {
501
528
  }
502
529
  return false;
503
530
  }
504
- function refPinsConstraints(ref, constraints) {
505
- const refConstraints = legacyRefParameterConstraints(ref);
531
+ function refPinsConstraints(ref, constraints, selectorParams) {
532
+ const refConstraints = legacyRefParameterConstraints(ref, selectorParams);
506
533
  if (constraints.width !== void 0 && refConstraints.width === void 0) return false;
507
534
  if (constraints.height !== void 0 && refConstraints.height === void 0) return false;
508
535
  if (constraints.durationMs !== void 0 && typeof refConstraints.durationMs !== "number") return false;
@@ -514,8 +541,8 @@ function legacyIdPinsDimensions(ref) {
514
541
  const params = record(declaration.params) ?? {};
515
542
  return typeof params.width === "number" || typeof params.height === "number" || typeof params.duration_ms_exact === "number" || Array.isArray(params.sizes);
516
543
  }
517
- function refConstraintKey(ref) {
518
- const constraints = legacyRefParameterConstraints(ref);
544
+ function refConstraintKey(ref, selectorParams) {
545
+ const constraints = legacyRefParameterConstraints(ref, selectorParams);
519
546
  return [
520
547
  agentIdentity(ref.agent_url),
521
548
  constraints.width ?? "",
@@ -525,14 +552,21 @@ function refConstraintKey(ref) {
525
552
  }
526
553
  function preferMostConstrainedLegacyCandidates(candidates, creative) {
527
554
  let remaining = candidates;
528
- const constraints = creativeFormatParameterConstraints(creative);
555
+ const mediaKind = ["image", "video_hosted", "audio_hosted"].includes(String(creative.format_kind));
556
+ const constraints = creativeFormatParameterConstraints(creative) ?? (remaining.length > 1 ? primaryMediaConstraints(creative) : void 0);
529
557
  if (constraints) {
530
- remaining = remaining.filter((candidate) => !refContradictsConstraints(candidate.ref, constraints));
531
- const pinned = remaining.filter((candidate) => refPinsConstraints(candidate.ref, constraints));
558
+ remaining = remaining.filter(
559
+ (candidate) => !refContradictsConstraints(candidate.ref, constraints, mediaKind ? candidate.selectorParams : void 0)
560
+ );
561
+ const pinned = remaining.filter(
562
+ (candidate) => refPinsConstraints(candidate.ref, constraints, mediaKind ? candidate.selectorParams : void 0)
563
+ );
532
564
  if (pinned.length > 0) remaining = pinned;
533
565
  }
534
566
  if (remaining.length <= 1) return remaining;
535
- const constraintKeys = new Set(remaining.map((candidate) => refConstraintKey(candidate.ref)));
567
+ const constraintKeys = new Set(
568
+ remaining.map((candidate) => refConstraintKey(candidate.ref, mediaKind ? candidate.selectorParams : void 0))
569
+ );
536
570
  if (constraintKeys.size !== 1) return remaining;
537
571
  const specific = remaining.filter((candidate) => legacyIdPinsDimensions(candidate.ref) === true);
538
572
  return specific.length > 0 && specific.length < remaining.length ? specific : remaining;
@@ -571,43 +605,82 @@ function selectLegacyRef(creative, container, canonicalFormatLegacyResolver, ope
571
605
  matching = preferMostConstrainedLegacyCandidates(matching, creative);
572
606
  return matching.length === 1 ? matching[0].ref : void 0;
573
607
  }
608
+ function legacyUrlTrackerSlotMatches(slot, tracker) {
609
+ return slot.asset_type === "url" && slot.requirements?.url_type === "tracker_pixel" && (slot.asset_id === tracker.assetId || slot.requirements.role === tracker.assetId);
610
+ }
574
611
  function projectLegacyAssetKeys(assetsValue, definition) {
612
+ const unchanged = { assets: assetsValue, drifts: [] };
575
613
  const assets = record(assetsValue);
576
- if (!assets || !Array.isArray(definition?.assets)) return assetsValue;
614
+ if (!assets || !Array.isArray(definition?.assets)) return unchanged;
577
615
  const slots = definition.assets.filter((slot) => record(slot) !== void 0);
578
- if (slots.some((slot) => slot.item_type !== void 0 && slot.item_type !== "individual")) return assetsValue;
616
+ if (slots.some((slot) => slot.item_type !== void 0 && slot.item_type !== "individual")) return unchanged;
579
617
  const declaredIds = new Set(slots.map((slot) => slot.asset_id));
580
618
  const availableSlots = slots.filter(
581
- (slot) => (slot.item_type === void 0 || slot.item_type === "individual") && typeof slot.asset_id === "string" && slot.asset_id.length > 0 && !Object.hasOwn(assets, slot.asset_id)
619
+ (slot) => typeof slot.asset_id === "string" && slot.asset_id.length > 0 && !Object.hasOwn(assets, slot.asset_id)
582
620
  );
583
621
  const targetBySource = /* @__PURE__ */ new Map();
584
622
  const sourcesByTarget = /* @__PURE__ */ new Map();
623
+ const trackersBySource = /* @__PURE__ */ new Map();
585
624
  for (const [key, value] of Object.entries(assets)) {
586
- if (declaredIds.has(key)) continue;
625
+ const candidates = (Array.isArray(value) ? value : [value]).map(downgradePixelTracker);
626
+ const trackers = candidates.length > 0 && candidates.every((tracker) => tracker !== void 0) ? candidates : void 0;
627
+ const trackerSlotMatches = (slot2) => trackers !== void 0 && trackers.every((tracker) => legacyUrlTrackerSlotMatches(slot2, tracker));
628
+ if (declaredIds.has(key)) {
629
+ const slot2 = slots.find((slot3) => slot3.asset_id === key);
630
+ if (trackers && slot2 && trackerSlotMatches(slot2)) trackersBySource.set(key, trackers);
631
+ continue;
632
+ }
587
633
  const asset = record(value);
588
- if (!asset || typeof asset.asset_type !== "string") continue;
589
- const matches = availableSlots.filter((slot) => {
590
- if (slot.asset_type !== asset.asset_type) return false;
634
+ if (!trackers && (!asset || typeof asset.asset_type !== "string")) continue;
635
+ const matches = availableSlots.filter((slot2) => {
636
+ if (trackerSlotMatches(slot2)) return true;
637
+ if (!asset || slot2.asset_type !== asset.asset_type) return false;
591
638
  if (asset.asset_type === "url") {
592
- return typeof asset.url_type === "string" && asset.url_type === slot.requirements?.url_type;
639
+ return typeof asset.url_type === "string" && asset.url_type === slot2.requirements?.url_type;
593
640
  }
594
641
  if (asset.asset_type === "pixel_tracker") {
595
- return typeof asset.event === "string" && asset.event === slot.event && (asset.event !== "custom" || typeof asset.custom_event_name === "string" && asset.custom_event_name === slot.custom_event_name);
642
+ return typeof asset.event === "string" && asset.event === slot2.event && (asset.event !== "custom" || typeof asset.custom_event_name === "string" && asset.custom_event_name === slot2.custom_event_name);
596
643
  }
597
644
  return true;
598
645
  });
599
646
  if (matches.length !== 1) continue;
600
- const target = matches[0].asset_id;
647
+ const slot = matches[0];
648
+ const target = slot.asset_id;
601
649
  targetBySource.set(key, target);
650
+ if (trackers && trackerSlotMatches(slot)) trackersBySource.set(key, trackers);
602
651
  const sources = sourcesByTarget.get(target) ?? [];
603
652
  sources.push(key);
604
653
  sourcesByTarget.set(target, sources);
605
654
  }
606
655
  for (const sources of sourcesByTarget.values()) {
607
- if (sources.length > 1) for (const source of sources) targetBySource.delete(source);
656
+ if (sources.length > 1) {
657
+ for (const source of sources) {
658
+ targetBySource.delete(source);
659
+ trackersBySource.delete(source);
660
+ }
661
+ }
662
+ }
663
+ if (targetBySource.size === 0 && trackersBySource.size === 0) return unchanged;
664
+ const drifts = [];
665
+ for (const [key, trackers] of trackersBySource) {
666
+ trackers.forEach((tracker, index) => {
667
+ const path = `assets.${key}${Array.isArray(assets[key]) ? `[${index}]` : ""}`;
668
+ const drift = pixelTrackerDrift(path, tracker);
669
+ if (drift) drifts.push(drift);
670
+ });
608
671
  }
609
- if (targetBySource.size === 0) return assetsValue;
610
- return Object.fromEntries(Object.entries(assets).map(([key, value]) => [targetBySource.get(key) ?? key, value]));
672
+ return {
673
+ assets: Object.fromEntries(
674
+ Object.entries(assets).map(([key, value]) => {
675
+ const trackers = trackersBySource.get(key);
676
+ return [
677
+ targetBySource.get(key) ?? key,
678
+ trackers ? Array.isArray(value) ? trackers.map((tracker) => tracker.asset) : trackers[0].asset : value
679
+ ];
680
+ })
681
+ ),
682
+ drifts
683
+ };
611
684
  }
612
685
  function projectCreative(creative, formatId, legacyFormatDefinitions) {
613
686
  const next = { ...creative };
@@ -619,7 +692,12 @@ function projectCreative(creative, formatId, legacyFormatDefinitions) {
619
692
  return ref !== void 0 && sameLegacyIdentity(ref, formatId);
620
693
  });
621
694
  const definition = supplied?.length ? supplied.length === 1 ? supplied[0] : void 0 : lookupV1Format(formatId);
622
- if (Object.hasOwn(creative, "assets")) next.assets = projectLegacyAssetKeys(creative.assets, definition);
695
+ if (Object.hasOwn(creative, "assets")) {
696
+ const projected = projectLegacyAssetKeys(creative.assets, definition);
697
+ next.assets = projected.assets;
698
+ transferLegacyCreativeMetadata(creative, next);
699
+ rememberCreativeDeliveryDiagnostics(next, projected.drifts);
700
+ }
623
701
  return next;
624
702
  }
625
703
  function dedupeLegacyRefs(refs) {
@@ -857,6 +935,7 @@ function projectCreativeForDelivery(creative, selectorContainer, wireMode = "can
857
935
  const inputRecord = creative;
858
936
  const originalLegacyRef = legacyRef(inputRecord.format_id);
859
937
  const creativeRecord = canonicalizeCreative(inputRecord, selectorContainer, operation, legacyFormatConverter);
938
+ transferLegacyCreativeMetadata(inputRecord, creativeRecord);
860
939
  if (wireMode === "canonical") return creativeRecord;
861
940
  if (originalLegacyRef) {
862
941
  const selectedOriginal = selectLegacyRef(inputRecord, selectorContainer, canonicalFormatLegacyResolver, operation);
@@ -928,14 +1007,32 @@ function projectCreativeForDelivery(creative, selectorContainer, wireMode = "can
928
1007
  throw new CreativeFormatProjectionError(
929
1008
  operation,
930
1009
  creativeId,
931
- `the seller advertised ${candidates.length} legacy refs for canonical kind ${creativeRecord.format_kind}`
1010
+ `the seller advertised ${candidates.length} legacy refs for canonical kind ${creativeRecord.format_kind}` + (candidates.some((candidate) => legacyIdPinsDimensions(candidate.ref) === true) ? "; set format_parameters.width/height or give the asset one rendered width/height to select one" : "")
932
1011
  );
933
1012
  }
934
- const reason = pinned ? "the creative is pinned to a format option that names none of the selected seller product legacy format references" : "the selected seller product did not provide one unambiguous legacy format reference";
1013
+ const reason = pinned ? "the creative is pinned to a format option that names none of the selected seller product legacy format references" : describeUnmatchedLegacyCandidates(creativeRecord, allCandidates);
935
1014
  throw new CreativeFormatProjectionError(operation, creativeId, reason);
936
1015
  }
937
1016
  return creative;
938
1017
  }
1018
+ function describeUnmatchedLegacyCandidates(creative, allCandidates) {
1019
+ const generic = "the selected seller product did not provide one unambiguous legacy format reference";
1020
+ const kind = String(creative.format_kind);
1021
+ if (allCandidates.length === 0) return generic;
1022
+ const sameKind = allCandidates.filter((candidate) => candidate.formatKind === kind);
1023
+ if (sameKind.length === 0) {
1024
+ const offered = [
1025
+ ...new Set(allCandidates.flatMap((candidate) => candidate.formatKind ? [candidate.formatKind] : []))
1026
+ ];
1027
+ if (offered.length === 0) return generic;
1028
+ return `the selected seller product offers legacy refs for canonical kind ${offered.join(", ")}, not ${kind}`;
1029
+ }
1030
+ const size = creativeFormatParameterConstraints(creative);
1031
+ if (size?.width !== void 0 && size.height !== void 0) {
1032
+ return `none of the seller's ${sameKind.length} ${kind} legacy refs matches the creative's ${size.width}x${size.height} size`;
1033
+ }
1034
+ return generic;
1035
+ }
939
1036
  function projectMediaBuyCreativesForDelivery(request, wireMode = "canonical", operation = "create_media_buy", legacyFormatConverter, canonicalFormatLegacyResolver, legacyFormatDefinitions) {
940
1037
  const requestRecord = record(request);
941
1038
  if (!requestRecord) return request;
@@ -47,6 +47,7 @@ export { canonicalFormatLegacyResolverFromRoutes, carryFormatOptionOrigins, lega
47
47
  export { augmentProductWithFormatOptions, withFormatOptions, toCanonicalFormatOptionsWithRoutes, toAdditiveCanonicalProduct, withAdditiveCanonicalFormatOptions, toCanonicalOnlyProduct, toCanonicalOnlyResponse, type V2AugmentedProduct, type AdditiveCanonicalProduct, type CanonicalOnlyProduct, } from './augment-response.mjs';
48
48
  export { CanonicalFormat, audioDaastFormatDeclaration, audioHostedFormatDeclaration, audioVastFormatDeclaration, agentPlacementFormatDeclaration, canonicalFormatDeclaration, customFormatDeclaration, displayTagFormatDeclaration, legacyFormatRef, legacyFormatRefs, html5FormatDeclaration, imageCarouselFormatDeclaration, imageFormatDeclaration, nativeInFeedFormatDeclaration, productCard, productCardDetailed, responsiveCreativeFormatDeclaration, sellerRenderedStatefulDisplayFormatDeclaration, sponsoredPlacementFormatDeclaration, coordinatedPlacementsFormatDeclaration, videoHostedFormatDeclaration, videoVastFormatDeclaration, type CanonicalFormatDeclaration, type CanonicalFormatDeclarationFields, type CanonicalFormatKind, type CanonicalFormatParams, type FormatReferenceInput, type ProductCardDetailedFields, type ProductCardFields, } from './builders.mjs';
49
49
  export { packageRefsForFormatOptions, packageRefsForCapabilities, legacyFormatIdsFromOptions, tryLegacyFormatIdsFromOptions, legacyFormatIdsForFormatOption, legacyFormatIdsForCapability, lintPackageFormatSelectorDimensions, FormatOptionRefsLookupError, CapabilityIdsLookupError, type PackageFormatRefs, type PackageCapabilityRefs, type FormatOptionRef, type FormatOptionSelector, type FormatOptionRefsLookupErrorCode, type CapabilityIdsLookupErrorCode, type PackageFormatSelectorInput, type PackageFormatSelectorDimensionOptions, type FixedSizeDimensions, type PackageFormatSelectorDimensionDiagnosticCode, type PackageFormatSelectorDimensionDiagnostic, } from './write-side.mjs';
50
+ export { getCreativeDeliveryDiagnostics } from './legacy-metadata.mjs';
50
51
  export type { V1FormatId, V2ProductFormatDeclaration, V2ProductInput, V2Product, V1ProductInput, V1Product, ProjectionProductInput, ProjectionDiagnostic, } from './types.mjs';
51
52
  export { isProjectionProductInput } from './types.mjs';
52
53
  export { legacyFormatConverterFromCatalogSnapshots, canonicalFormatLegacyResolverFromCatalogSnapshots, projectionAdaptersFromCatalogSnapshots, type ProjectionCatalogAdapters, type ProjectionCatalogSnapshot, type ProjectionCatalogSource, } from './catalog-snapshot.mjs';
@@ -47,6 +47,7 @@ export { canonicalFormatLegacyResolverFromRoutes, carryFormatOptionOrigins, lega
47
47
  export { augmentProductWithFormatOptions, withFormatOptions, toCanonicalFormatOptionsWithRoutes, toAdditiveCanonicalProduct, withAdditiveCanonicalFormatOptions, toCanonicalOnlyProduct, toCanonicalOnlyResponse, type V2AugmentedProduct, type AdditiveCanonicalProduct, type CanonicalOnlyProduct, } from './augment-response';
48
48
  export { CanonicalFormat, audioDaastFormatDeclaration, audioHostedFormatDeclaration, audioVastFormatDeclaration, agentPlacementFormatDeclaration, canonicalFormatDeclaration, customFormatDeclaration, displayTagFormatDeclaration, legacyFormatRef, legacyFormatRefs, html5FormatDeclaration, imageCarouselFormatDeclaration, imageFormatDeclaration, nativeInFeedFormatDeclaration, productCard, productCardDetailed, responsiveCreativeFormatDeclaration, sellerRenderedStatefulDisplayFormatDeclaration, sponsoredPlacementFormatDeclaration, coordinatedPlacementsFormatDeclaration, videoHostedFormatDeclaration, videoVastFormatDeclaration, type CanonicalFormatDeclaration, type CanonicalFormatDeclarationFields, type CanonicalFormatKind, type CanonicalFormatParams, type FormatReferenceInput, type ProductCardDetailedFields, type ProductCardFields, } from './builders';
49
49
  export { packageRefsForFormatOptions, packageRefsForCapabilities, legacyFormatIdsFromOptions, tryLegacyFormatIdsFromOptions, legacyFormatIdsForFormatOption, legacyFormatIdsForCapability, lintPackageFormatSelectorDimensions, FormatOptionRefsLookupError, CapabilityIdsLookupError, type PackageFormatRefs, type PackageCapabilityRefs, type FormatOptionRef, type FormatOptionSelector, type FormatOptionRefsLookupErrorCode, type CapabilityIdsLookupErrorCode, type PackageFormatSelectorInput, type PackageFormatSelectorDimensionOptions, type FixedSizeDimensions, type PackageFormatSelectorDimensionDiagnosticCode, type PackageFormatSelectorDimensionDiagnostic, } from './write-side';
50
+ export { getCreativeDeliveryDiagnostics } from './legacy-metadata';
50
51
  export type { V1FormatId, V2ProductFormatDeclaration, V2ProductInput, V2Product, V1ProductInput, V1Product, ProjectionProductInput, ProjectionDiagnostic, } from './types';
51
52
  export { isProjectionProductInput } from './types';
52
53
  export { legacyFormatConverterFromCatalogSnapshots, canonicalFormatLegacyResolverFromCatalogSnapshots, projectionAdaptersFromCatalogSnapshots, type ProjectionCatalogAdapters, type ProjectionCatalogSnapshot, type ProjectionCatalogSource, } from './catalog-snapshot';
@@ -38,6 +38,7 @@ __export(projection_exports, {
38
38
  customFormatDeclaration: () => import_builders.customFormatDeclaration,
39
39
  displayTagFormatDeclaration: () => import_builders.displayTagFormatDeclaration,
40
40
  findCatalogEntryByCanonicalAndSize: () => import_catalog.findCatalogEntryByCanonicalAndSize,
41
+ getCreativeDeliveryDiagnostics: () => import_legacy_metadata.getCreativeDeliveryDiagnostics,
41
42
  html5FormatDeclaration: () => import_builders.html5FormatDeclaration,
42
43
  imageCarouselFormatDeclaration: () => import_builders.imageCarouselFormatDeclaration,
43
44
  imageFormatDeclaration: () => import_builders.imageFormatDeclaration,
@@ -89,6 +90,7 @@ var import_legacy_routes = require('./legacy-routes.js');
89
90
  var import_augment_response = require('./augment-response.js');
90
91
  var import_builders = require('./builders.js');
91
92
  var import_write_side = require('./write-side.js');
93
+ var import_legacy_metadata = require('./legacy-metadata.js');
92
94
  var import_types = require('./types.js');
93
95
  var import_catalog_snapshot = require('./catalog-snapshot.js');
94
96
  var import_catalog = require('./catalog.js');
@@ -117,6 +119,7 @@ var import_creative_delivery = require('./creative-delivery.js');
117
119
  customFormatDeclaration,
118
120
  displayTagFormatDeclaration,
119
121
  findCatalogEntryByCanonicalAndSize,
122
+ getCreativeDeliveryDiagnostics,
120
123
  html5FormatDeclaration,
121
124
  imageCarouselFormatDeclaration,
122
125
  imageFormatDeclaration,
@@ -49,6 +49,7 @@ import {
49
49
  FormatOptionRefsLookupError,
50
50
  CapabilityIdsLookupError
51
51
  } from "./write-side.mjs";
52
+ import { getCreativeDeliveryDiagnostics } from "./legacy-metadata.mjs";
52
53
  import { isProjectionProductInput } from "./types.mjs";
53
54
  import {
54
55
  legacyFormatConverterFromCatalogSnapshots,
@@ -94,6 +95,7 @@ export {
94
95
  customFormatDeclaration,
95
96
  displayTagFormatDeclaration,
96
97
  findCatalogEntryByCanonicalAndSize,
98
+ getCreativeDeliveryDiagnostics,
97
99
  html5FormatDeclaration,
98
100
  imageCarouselFormatDeclaration,
99
101
  imageFormatDeclaration,
@@ -1,5 +1,24 @@
1
1
  import type { ProductFormatDeclaration } from '../../types/tools.generated.mjs';
2
2
  import type { V1FormatId, V2ProductFormatDeclaration } from './types.mjs';
3
+ import type { VersionDrift } from '../../adapters/version/types.mjs';
4
+ type Json = Record<string, unknown>;
5
+ export interface LegacyPixelTracker {
6
+ asset: Json;
7
+ assetId: string;
8
+ lostFields: string[];
9
+ }
10
+ /** Apply the AdCP 3.1 pixel-tracker schema's normative 3.0 downgrade table. */
11
+ export declare function downgradePixelTracker(value: unknown): LegacyPixelTracker | undefined;
12
+ export declare function pixelTrackerDrift(path: string, tracker: LegacyPixelTracker): VersionDrift | undefined;
13
+ /** Keep delivery advisories out of creative JSON sent to the seller. */
14
+ export declare function rememberCreativeDeliveryDiagnostics(value: object, entries: readonly VersionDrift[]): void;
15
+ export declare function transferCreativeDeliveryDiagnostics(source: object, target: object): void;
16
+ /**
17
+ * Read advisories from a projected creative or a sync/create/update request.
18
+ * Pure projection callers can surface these alongside the returned wire object.
19
+ * SingleAgentClient includes them in the task's debug logs automatically.
20
+ */
21
+ export declare function getCreativeDeliveryDiagnostics(value: unknown): VersionDrift[];
3
22
  /**
4
23
  * SDK-private projection metadata held out-of-band. WeakMaps keep seller
5
24
  * origin evidence and legacy routing identifiers absent from canonical objects
@@ -1,5 +1,24 @@
1
1
  import type { ProductFormatDeclaration } from '../../types/tools.generated';
2
2
  import type { V1FormatId, V2ProductFormatDeclaration } from './types';
3
+ import type { VersionDrift } from '../../adapters/version/types';
4
+ type Json = Record<string, unknown>;
5
+ export interface LegacyPixelTracker {
6
+ asset: Json;
7
+ assetId: string;
8
+ lostFields: string[];
9
+ }
10
+ /** Apply the AdCP 3.1 pixel-tracker schema's normative 3.0 downgrade table. */
11
+ export declare function downgradePixelTracker(value: unknown): LegacyPixelTracker | undefined;
12
+ export declare function pixelTrackerDrift(path: string, tracker: LegacyPixelTracker): VersionDrift | undefined;
13
+ /** Keep delivery advisories out of creative JSON sent to the seller. */
14
+ export declare function rememberCreativeDeliveryDiagnostics(value: object, entries: readonly VersionDrift[]): void;
15
+ export declare function transferCreativeDeliveryDiagnostics(source: object, target: object): void;
16
+ /**
17
+ * Read advisories from a projected creative or a sync/create/update request.
18
+ * Pure projection callers can surface these alongside the returned wire object.
19
+ * SingleAgentClient includes them in the task's debug logs automatically.
20
+ */
21
+ export declare function getCreativeDeliveryDiagnostics(value: unknown): VersionDrift[];
3
22
  /**
4
23
  * SDK-private projection metadata held out-of-band. WeakMaps keep seller
5
24
  * origin evidence and legacy routing identifiers absent from canonical objects