@adcp/sdk 15.7.1 → 15.8.1

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 (63) hide show
  1. package/dist/lib/core/SingleAgentClient.d.mts +14 -0
  2. package/dist/lib/core/SingleAgentClient.d.ts +14 -0
  3. package/dist/lib/core/SingleAgentClient.js +138 -54
  4. package/dist/lib/core/SingleAgentClient.mjs +141 -54
  5. package/dist/lib/core/agent-discovery-cache.d.mts +2 -0
  6. package/dist/lib/core/agent-discovery-cache.d.ts +2 -0
  7. package/dist/lib/core/creative-schema-support.d.mts +3 -0
  8. package/dist/lib/core/creative-schema-support.d.ts +3 -0
  9. package/dist/lib/core/creative-schema-support.js +113 -0
  10. package/dist/lib/core/creative-schema-support.mjs +89 -0
  11. package/dist/lib/core/product-cache.js +4 -3
  12. package/dist/lib/core/product-cache.mjs +4 -3
  13. package/dist/lib/reporting/ledger/handler.d.mts +10 -3
  14. package/dist/lib/reporting/ledger/handler.d.ts +10 -3
  15. package/dist/lib/reporting/ledger/handler.js +17 -4
  16. package/dist/lib/reporting/ledger/handler.mjs +17 -4
  17. package/dist/lib/reporting/ledger/managed.d.mts +3 -1
  18. package/dist/lib/reporting/ledger/managed.d.ts +3 -1
  19. package/dist/lib/reporting/ledger/managed.js +4 -1
  20. package/dist/lib/reporting/ledger/managed.mjs +4 -1
  21. package/dist/lib/reporting/ledger/postgres.d.mts +87 -0
  22. package/dist/lib/reporting/ledger/postgres.d.ts +87 -0
  23. package/dist/lib/reporting/ledger/postgres.js +316 -15
  24. package/dist/lib/reporting/ledger/postgres.mjs +316 -15
  25. package/dist/lib/reporting/ledger/row-storage.d.mts +23 -0
  26. package/dist/lib/reporting/ledger/row-storage.d.ts +23 -0
  27. package/dist/lib/reporting/ledger/row-storage.js +56 -0
  28. package/dist/lib/reporting/ledger/row-storage.mjs +56 -0
  29. package/dist/lib/reporting/ledger/types.d.mts +26 -0
  30. package/dist/lib/reporting/ledger/types.d.ts +26 -0
  31. package/dist/lib/reporting/service/index.d.mts +33 -3
  32. package/dist/lib/reporting/service/index.d.ts +33 -3
  33. package/dist/lib/reporting/service/index.js +20 -2
  34. package/dist/lib/reporting/service/index.mjs +20 -2
  35. package/dist/lib/reporting/service/maintenance.d.mts +20 -1
  36. package/dist/lib/reporting/service/maintenance.d.ts +20 -1
  37. package/dist/lib/reporting/service/maintenance.js +25 -2
  38. package/dist/lib/reporting/service/maintenance.mjs +25 -2
  39. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  40. package/dist/lib/testing/storyboard/request-builder.js +14 -16
  41. package/dist/lib/testing/storyboard/request-builder.mjs +14 -16
  42. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  43. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  44. package/dist/lib/v2/projection/creative-delivery.d.mts +22 -0
  45. package/dist/lib/v2/projection/creative-delivery.d.ts +22 -0
  46. package/dist/lib/v2/projection/creative-delivery.js +92 -0
  47. package/dist/lib/v2/projection/creative-delivery.mjs +91 -0
  48. package/dist/lib/v2/projection/legacy-metadata.d.mts +6 -3
  49. package/dist/lib/v2/projection/legacy-metadata.d.ts +6 -3
  50. package/dist/lib/v2/projection/legacy-metadata.js +17 -0
  51. package/dist/lib/v2/projection/legacy-metadata.mjs +15 -0
  52. package/dist/lib/version.d.mts +3 -3
  53. package/dist/lib/version.d.ts +3 -3
  54. package/dist/lib/version.js +3 -3
  55. package/dist/lib/version.mjs +3 -3
  56. package/docs/TYPE-SUMMARY.md +2 -2
  57. package/docs/guides/CREATIVE-DELIVERY.md +16 -0
  58. package/docs/guides/REPORTING-LEDGER-CUTOVER.md +405 -0
  59. package/docs/guides/REPORTING-LEDGER.md +130 -0
  60. package/docs/guides/REPORTING-OPERATIONS.md +12 -0
  61. package/docs/llms.txt +3 -2
  62. package/docs/migration-14.x-rc-worksheet.md +4 -4
  63. package/package.json +1 -1
@@ -6,25 +6,25 @@ const UNKNOWN_FORMAT_ID = Object.freeze({ agent_url: "https://unknown.example.co
6
6
  const FALLBACK_CALLER_AGENT_URL = "https://e2e-orchestrator.adcontextprotocol.org/";
7
7
  const FIXTURE_AWARE_ENRICHERS = /* @__PURE__ */ new Set([
8
8
  "create_media_buy",
9
- // merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]
9
+ // preserves authored accounts and merges discovered identifiers INTO fixture packages[0]
10
10
  "comply_test_controller",
11
11
  // forces account.sandbox: true regardless of fixture
12
12
  "check_governance",
13
13
  // preserves the authored intent-vs-delivery request shape
14
14
  "get_products",
15
- // preserves wholesale fixture fields while keeping resolved account scope authoritative
15
+ // preserves discovery fields and authored account identities
16
16
  "get_signals",
17
- // preserves discovery fields while keeping async task account scope authoritative
17
+ // preserves discovery fields and authored account identities
18
18
  "get_task_status",
19
- // preserves task filters while keeping resolved account scope authoritative
19
+ // preserves task filters and authored account identities
20
20
  "list_tasks",
21
- // preserves reconciliation filters while keeping resolved account scope authoritative
21
+ // preserves reconciliation filters and authored account identities
22
22
  "update_media_buy",
23
- // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy
23
+ // fills missing account identity and carries sandbox routing into authored natural keys
24
24
  "get_media_buys",
25
- // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy
25
+ // fills missing account identity and carries sandbox routing into authored natural keys
26
26
  "get_media_buy_delivery"
27
- // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy
27
+ // fills missing account identity and carries sandbox routing into authored natural keys
28
28
  ]);
29
29
  function hasUnresolvedContextReference(value) {
30
30
  if (typeof value === "string") return /^\$context\.\w+$/.test(value);
@@ -67,23 +67,21 @@ function runClockMs(runnerVars) {
67
67
  return runnerVars?.runStartMs ?? Date.now();
68
68
  }
69
69
  function resolveMediaBuyAccount(fixtureAccount, contextAccount, options) {
70
- const resolvedAccount = contextAccount ?? resolveAccount(options);
71
- if (contextAccount === void 0 && fixtureAccount !== null && typeof fixtureAccount === "object" && !Array.isArray(fixtureAccount) && typeof fixtureAccount.operator === "string" && typeof fixtureAccount.account_id !== "string") {
72
- const sandbox = resolvedAccount.sandbox;
70
+ if (hasAuthoredAccountIdentity(fixtureAccount)) {
71
+ if (hasUnresolvedContextReference(fixtureAccount)) return fixtureAccount;
72
+ if (typeof fixtureAccount.account_id === "string") return fixtureAccount;
73
+ const sandbox = contextAccount?.sandbox ?? resolveAccount(options).sandbox;
73
74
  return {
74
75
  ...fixtureAccount,
75
76
  ...sandbox !== void 0 && { sandbox }
76
77
  };
77
78
  }
78
- return resolvedAccount;
79
+ return contextAccount ?? resolveAccount(options);
79
80
  }
80
81
  function resolveDiscoveryAccount(task, fixtureAccount, contextAccount, options) {
81
- if (ACCOUNT_FREE_DISCOVERY_TASKS.has(task) && contextAccount === void 0 && hasUnresolvedContextReference(fixtureAccount))
82
- return void 0;
82
+ if (ACCOUNT_FREE_DISCOVERY_TASKS.has(task) && hasUnresolvedContextReference(fixtureAccount)) return contextAccount;
83
83
  if (ACCOUNT_FREE_DISCOVERY_TASKS.has(task) && fixtureAccount === void 0 && contextAccount === void 0)
84
84
  return void 0;
85
- if (contextAccount === void 0 && fixtureAccount && typeof fixtureAccount === "object" && "account_id" in fixtureAccount)
86
- return fixtureAccount;
87
85
  return resolveMediaBuyAccount(fixtureAccount, contextAccount, options);
88
86
  }
89
87
  const OPERATION_SCOPED_CONTROLLER_SCENARIOS = /* @__PURE__ */ new Set([
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "15.7.1";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "15.8.1";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "15.7.1";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "15.8.1";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -258,5 +258,27 @@ export declare function projectMediaBuyCreativesForDelivery<T>(request: T, wireM
258
258
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: 'canonical', legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'canonical'>;
259
259
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: 'legacy' | 'unknown', legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'legacy'>;
260
260
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: CreativeFormatWireMode, legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'canonical'> | ProjectedSyncCreativeRequest<T, 'legacy'>;
261
+ /** The direct canonical selector for a format option the seller did not declare. */
262
+ export interface UndeclaredFormatOptionSelector {
263
+ format_kind: string;
264
+ params?: unknown;
265
+ /** Custom/schema-backed formats cannot retain identity in a direct selector. */
266
+ unrepresentable?: true;
267
+ }
268
+ /**
269
+ * Looks up a format option the SDK derived from a seller's legacy `format_ids`.
270
+ * Returns undefined for options the seller declared in its own `format_options[]`.
271
+ */
272
+ export type UndeclaredFormatOptionLookup = (ref: FormatOptionReference, productId: string | undefined) => UndeclaredFormatOptionSelector | undefined;
273
+ /**
274
+ * Canonical-wire counterpart to legacy downgrade for format options the seller
275
+ * never declared. AdCP 3.x products may carry only legacy `format_ids`; the SDK
276
+ * upgrades them for the buyer and mints the option ids itself. A seller only
277
+ * resolves `format_option_refs` against its own `format_options[]`, so a
278
+ * package selecting such options is sent as the equivalent `format_kind` +
279
+ * `params` selector, and creative pins to them are dropped. A selection that
280
+ * one direct selector cannot express fails closed before dispatch.
281
+ */
282
+ export declare function projectUndeclaredFormatOptionSelectors<T>(request: T, operation: 'create_media_buy' | 'update_media_buy' | 'sync_creatives', lookup: UndeclaredFormatOptionLookup): T;
261
283
  export declare function resolveCreativeFormatWireMode(capabilities: unknown, negotiatedVersion?: string): CreativeFormatWireMode;
262
284
  export {};
@@ -258,5 +258,27 @@ export declare function projectMediaBuyCreativesForDelivery<T>(request: T, wireM
258
258
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: 'canonical', legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'canonical'>;
259
259
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: 'legacy' | 'unknown', legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'legacy'>;
260
260
  export declare function projectSyncCreativesForDelivery<T>(request: T, selectorContainers: ReadonlyArray<CreativeFormatSelectorContainer>, wireMode: CreativeFormatWireMode, legacyFormatConverter?: LegacyFormatConverter, canonicalFormatLegacyResolver?: CanonicalFormatLegacyResolver): ProjectedSyncCreativeRequest<T, 'canonical'> | ProjectedSyncCreativeRequest<T, 'legacy'>;
261
+ /** The direct canonical selector for a format option the seller did not declare. */
262
+ export interface UndeclaredFormatOptionSelector {
263
+ format_kind: string;
264
+ params?: unknown;
265
+ /** Custom/schema-backed formats cannot retain identity in a direct selector. */
266
+ unrepresentable?: true;
267
+ }
268
+ /**
269
+ * Looks up a format option the SDK derived from a seller's legacy `format_ids`.
270
+ * Returns undefined for options the seller declared in its own `format_options[]`.
271
+ */
272
+ export type UndeclaredFormatOptionLookup = (ref: FormatOptionReference, productId: string | undefined) => UndeclaredFormatOptionSelector | undefined;
273
+ /**
274
+ * Canonical-wire counterpart to legacy downgrade for format options the seller
275
+ * never declared. AdCP 3.x products may carry only legacy `format_ids`; the SDK
276
+ * upgrades them for the buyer and mints the option ids itself. A seller only
277
+ * resolves `format_option_refs` against its own `format_options[]`, so a
278
+ * package selecting such options is sent as the equivalent `format_kind` +
279
+ * `params` selector, and creative pins to them are dropped. A selection that
280
+ * one direct selector cannot express fails closed before dispatch.
281
+ */
282
+ export declare function projectUndeclaredFormatOptionSelectors<T>(request: T, operation: 'create_media_buy' | 'update_media_buy' | 'sync_creatives', lookup: UndeclaredFormatOptionLookup): T;
261
283
  export declare function resolveCreativeFormatWireMode(capabilities: unknown, negotiatedVersion?: string): CreativeFormatWireMode;
262
284
  export {};
@@ -23,6 +23,7 @@ __export(creative_delivery_exports, {
23
23
  projectCreativeForDelivery: () => projectCreativeForDelivery,
24
24
  projectMediaBuyCreativesForDelivery: () => projectMediaBuyCreativesForDelivery,
25
25
  projectSyncCreativesForDelivery: () => projectSyncCreativesForDelivery,
26
+ projectUndeclaredFormatOptionSelectors: () => projectUndeclaredFormatOptionSelectors,
26
27
  resolveCreativeFormatWireMode: () => resolveCreativeFormatWireMode,
27
28
  stripLegacyCreativeIdentity: () => stripLegacyCreativeIdentity
28
29
  });
@@ -30,6 +31,7 @@ module.exports = __toCommonJS(creative_delivery_exports);
30
31
  var import_v1_to_v2 = require('./v1-to-v2.js');
31
32
  var import_v2_to_v1 = require('./v2-to-v1.js');
32
33
  var import_legacy_metadata = require('./legacy-metadata.js');
34
+ var import_jcs = require('../../utils/jcs.js');
33
35
  function stripLegacyCreativeIdentity(value) {
34
36
  const legacyTokens = /* @__PURE__ */ new Set();
35
37
  const legacyUrlTokens = /* @__PURE__ */ new Set();
@@ -941,6 +943,95 @@ function projectSyncCreativesForDelivery(request, selectorContainers, wireMode =
941
943
  });
942
944
  return changed ? { ...requestRecord, creatives } : request;
943
945
  }
946
+ function stripUndeclaredCreativeOptionRef(creativeValue, productId, operation, lookup) {
947
+ const creative = record(creativeValue);
948
+ const ref = creative ? optionReference(creative.format_option_ref) : void 0;
949
+ if (!creative || !ref) return creativeValue;
950
+ const selector = lookup(ref, productId);
951
+ if (!selector) return creativeValue;
952
+ if (selector.unrepresentable || creative.format_kind === "custom") {
953
+ throw new CreativeFormatProjectionError(
954
+ operation,
955
+ typeof creative.creative_id === "string" ? creative.creative_id : "(unknown)",
956
+ "the seller did not declare this format option and its schema identity cannot be expressed without a seller-declared format_option_ref"
957
+ );
958
+ }
959
+ const next = { ...creative };
960
+ delete next.format_option_ref;
961
+ return next;
962
+ }
963
+ function directSelectorForUndeclaredOptions(pkg, operation, lookup) {
964
+ const refs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs.flatMap((value) => {
965
+ const ref = optionReference(value);
966
+ return ref ? [ref] : [];
967
+ }) : [];
968
+ const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
969
+ const selectors = refs.map((ref) => lookup(ref, productId));
970
+ if (!selectors.some((selector2) => selector2 !== void 0)) return pkg;
971
+ if (refs.length !== pkg.format_option_refs.length || selectors.some((selector2) => selector2?.unrepresentable)) {
972
+ throw new CreativeFormatProjectionError(
973
+ operation,
974
+ "(package selector)",
975
+ "the selected undeclared format options cannot be expressed as a direct selector; custom formats require a seller-declared format option"
976
+ );
977
+ }
978
+ const distinct = [
979
+ ...new Map(
980
+ selectors.map((selector2) => [
981
+ selector2 ? (0, import_jcs.canonicalize)({ format_kind: selector2.format_kind, params: selector2.params ?? null }) : "",
982
+ selector2
983
+ ])
984
+ ).values()
985
+ ];
986
+ const selector = distinct.length === 1 ? distinct[0] : void 0;
987
+ if (!selector || pkg.format_kind !== void 0 || pkg.params !== void 0) {
988
+ throw new CreativeFormatProjectionError(
989
+ operation,
990
+ "(package selector)",
991
+ "the seller did not declare the selected format options in its product format_options; select options that one format_kind + params selector can express"
992
+ );
993
+ }
994
+ const next = { ...pkg, format_kind: selector.format_kind };
995
+ delete next.format_option_refs;
996
+ if (selector.params !== void 0) next.params = structuredClone(selector.params);
997
+ return next;
998
+ }
999
+ function projectUndeclaredFormatOptionSelectors(request, operation, lookup) {
1000
+ const requestRecord = record(request);
1001
+ if (!requestRecord) return request;
1002
+ let changed = false;
1003
+ const next = { ...requestRecord };
1004
+ for (const key of ["packages", "new_packages"]) {
1005
+ const packages = requestRecord[key];
1006
+ if (!Array.isArray(packages)) continue;
1007
+ next[key] = packages.map((packageValue) => {
1008
+ const pkg = record(packageValue);
1009
+ if (!pkg) return packageValue;
1010
+ const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
1011
+ let projected = directSelectorForUndeclaredOptions(pkg, operation, lookup);
1012
+ if (Array.isArray(pkg.creatives)) {
1013
+ const creatives = pkg.creatives.map(
1014
+ (creative) => stripUndeclaredCreativeOptionRef(creative, productId, operation, lookup)
1015
+ );
1016
+ if (creatives.some((creative, index) => creative !== pkg.creatives[index])) {
1017
+ projected = { ...projected, creatives };
1018
+ }
1019
+ }
1020
+ if (projected !== pkg) changed = true;
1021
+ return projected;
1022
+ });
1023
+ }
1024
+ if (Array.isArray(requestRecord.creatives)) {
1025
+ const creatives = requestRecord.creatives.map(
1026
+ (creative) => stripUndeclaredCreativeOptionRef(creative, void 0, operation, lookup)
1027
+ );
1028
+ if (creatives.some((creative, index) => creative !== requestRecord.creatives[index])) {
1029
+ next.creatives = creatives;
1030
+ changed = true;
1031
+ }
1032
+ }
1033
+ return changed ? next : request;
1034
+ }
944
1035
  function release(value) {
945
1036
  if (typeof value !== "string") return void 0;
946
1037
  const match = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(value.trim());
@@ -1022,6 +1113,7 @@ function resolveCreativeFormatWireMode(capabilities, negotiatedVersion) {
1022
1113
  projectCreativeForDelivery,
1023
1114
  projectMediaBuyCreativesForDelivery,
1024
1115
  projectSyncCreativesForDelivery,
1116
+ projectUndeclaredFormatOptionSelectors,
1025
1117
  resolveCreativeFormatWireMode,
1026
1118
  stripLegacyCreativeIdentity
1027
1119
  });
@@ -10,6 +10,7 @@ import {
10
10
  selectedFormatOptions,
11
11
  transferLegacyCreativeMetadata
12
12
  } from "./legacy-metadata.mjs";
13
+ import { canonicalize as canonicalizeJson } from "../../utils/jcs.mjs";
13
14
  function stripLegacyCreativeIdentity(value) {
14
15
  const legacyTokens = /* @__PURE__ */ new Set();
15
16
  const legacyUrlTokens = /* @__PURE__ */ new Set();
@@ -921,6 +922,95 @@ function projectSyncCreativesForDelivery(request, selectorContainers, wireMode =
921
922
  });
922
923
  return changed ? { ...requestRecord, creatives } : request;
923
924
  }
925
+ function stripUndeclaredCreativeOptionRef(creativeValue, productId, operation, lookup) {
926
+ const creative = record(creativeValue);
927
+ const ref = creative ? optionReference(creative.format_option_ref) : void 0;
928
+ if (!creative || !ref) return creativeValue;
929
+ const selector = lookup(ref, productId);
930
+ if (!selector) return creativeValue;
931
+ if (selector.unrepresentable || creative.format_kind === "custom") {
932
+ throw new CreativeFormatProjectionError(
933
+ operation,
934
+ typeof creative.creative_id === "string" ? creative.creative_id : "(unknown)",
935
+ "the seller did not declare this format option and its schema identity cannot be expressed without a seller-declared format_option_ref"
936
+ );
937
+ }
938
+ const next = { ...creative };
939
+ delete next.format_option_ref;
940
+ return next;
941
+ }
942
+ function directSelectorForUndeclaredOptions(pkg, operation, lookup) {
943
+ const refs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs.flatMap((value) => {
944
+ const ref = optionReference(value);
945
+ return ref ? [ref] : [];
946
+ }) : [];
947
+ const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
948
+ const selectors = refs.map((ref) => lookup(ref, productId));
949
+ if (!selectors.some((selector2) => selector2 !== void 0)) return pkg;
950
+ if (refs.length !== pkg.format_option_refs.length || selectors.some((selector2) => selector2?.unrepresentable)) {
951
+ throw new CreativeFormatProjectionError(
952
+ operation,
953
+ "(package selector)",
954
+ "the selected undeclared format options cannot be expressed as a direct selector; custom formats require a seller-declared format option"
955
+ );
956
+ }
957
+ const distinct = [
958
+ ...new Map(
959
+ selectors.map((selector2) => [
960
+ selector2 ? canonicalizeJson({ format_kind: selector2.format_kind, params: selector2.params ?? null }) : "",
961
+ selector2
962
+ ])
963
+ ).values()
964
+ ];
965
+ const selector = distinct.length === 1 ? distinct[0] : void 0;
966
+ if (!selector || pkg.format_kind !== void 0 || pkg.params !== void 0) {
967
+ throw new CreativeFormatProjectionError(
968
+ operation,
969
+ "(package selector)",
970
+ "the seller did not declare the selected format options in its product format_options; select options that one format_kind + params selector can express"
971
+ );
972
+ }
973
+ const next = { ...pkg, format_kind: selector.format_kind };
974
+ delete next.format_option_refs;
975
+ if (selector.params !== void 0) next.params = structuredClone(selector.params);
976
+ return next;
977
+ }
978
+ function projectUndeclaredFormatOptionSelectors(request, operation, lookup) {
979
+ const requestRecord = record(request);
980
+ if (!requestRecord) return request;
981
+ let changed = false;
982
+ const next = { ...requestRecord };
983
+ for (const key of ["packages", "new_packages"]) {
984
+ const packages = requestRecord[key];
985
+ if (!Array.isArray(packages)) continue;
986
+ next[key] = packages.map((packageValue) => {
987
+ const pkg = record(packageValue);
988
+ if (!pkg) return packageValue;
989
+ const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
990
+ let projected = directSelectorForUndeclaredOptions(pkg, operation, lookup);
991
+ if (Array.isArray(pkg.creatives)) {
992
+ const creatives = pkg.creatives.map(
993
+ (creative) => stripUndeclaredCreativeOptionRef(creative, productId, operation, lookup)
994
+ );
995
+ if (creatives.some((creative, index) => creative !== pkg.creatives[index])) {
996
+ projected = { ...projected, creatives };
997
+ }
998
+ }
999
+ if (projected !== pkg) changed = true;
1000
+ return projected;
1001
+ });
1002
+ }
1003
+ if (Array.isArray(requestRecord.creatives)) {
1004
+ const creatives = requestRecord.creatives.map(
1005
+ (creative) => stripUndeclaredCreativeOptionRef(creative, void 0, operation, lookup)
1006
+ );
1007
+ if (creatives.some((creative, index) => creative !== requestRecord.creatives[index])) {
1008
+ next.creatives = creatives;
1009
+ changed = true;
1010
+ }
1011
+ }
1012
+ return changed ? next : request;
1013
+ }
924
1014
  function release(value) {
925
1015
  if (typeof value !== "string") return void 0;
926
1016
  const match = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(value.trim());
@@ -1001,6 +1091,7 @@ export {
1001
1091
  projectCreativeForDelivery,
1002
1092
  projectMediaBuyCreativesForDelivery,
1003
1093
  projectSyncCreativesForDelivery,
1094
+ projectUndeclaredFormatOptionSelectors,
1004
1095
  resolveCreativeFormatWireMode,
1005
1096
  stripLegacyCreativeIdentity
1006
1097
  };
@@ -1,9 +1,9 @@
1
1
  import type { ProductFormatDeclaration } from '../../types/tools.generated.mjs';
2
2
  import type { V1FormatId, V2ProductFormatDeclaration } from './types.mjs';
3
3
  /**
4
- * SDK-private downgrade metadata held out-of-band. WeakMaps keep legacy
5
- * routing identifiers absent from canonical objects even under reflective
6
- * inspection while still allowing object-spread package authoring.
4
+ * SDK-private projection metadata held out-of-band. WeakMaps keep seller
5
+ * origin evidence and legacy routing identifiers absent from canonical objects
6
+ * even under reflective inspection while still allowing object-spread package authoring.
7
7
  */
8
8
  export type CanonicalFormatDeclaration = Omit<V2ProductFormatDeclaration, 'v1_format_ref'> & {
9
9
  v1_format_ref?: never;
@@ -12,6 +12,9 @@ type DeclarationWithMetadata = CanonicalFormatDeclaration;
12
12
  export type PackageSelectionMetadata = {
13
13
  format_option_refs?: readonly unknown[];
14
14
  };
15
+ /** Keep seller-origin evidence private while canonical products pass through the cache. */
16
+ export declare function rememberSellerDeclaredFormatOption(declaration: object, declared: boolean): void;
17
+ export declare function sellerDeclaredFormatOption(declaration: object): boolean | undefined;
15
18
  export declare function concealLegacyFormatRefs(declaration: ProductFormatDeclaration | V2ProductFormatDeclaration | CanonicalFormatDeclaration): DeclarationWithMetadata;
16
19
  export declare function legacyFormatRefsForDeclaration(value: unknown): readonly V1FormatId[];
17
20
  export declare function selectedFormatOptions(value: unknown): readonly DeclarationWithMetadata[];
@@ -1,9 +1,9 @@
1
1
  import type { ProductFormatDeclaration } from '../../types/tools.generated';
2
2
  import type { V1FormatId, V2ProductFormatDeclaration } from './types';
3
3
  /**
4
- * SDK-private downgrade metadata held out-of-band. WeakMaps keep legacy
5
- * routing identifiers absent from canonical objects even under reflective
6
- * inspection while still allowing object-spread package authoring.
4
+ * SDK-private projection metadata held out-of-band. WeakMaps keep seller
5
+ * origin evidence and legacy routing identifiers absent from canonical objects
6
+ * even under reflective inspection while still allowing object-spread package authoring.
7
7
  */
8
8
  export type CanonicalFormatDeclaration = Omit<V2ProductFormatDeclaration, 'v1_format_ref'> & {
9
9
  v1_format_ref?: never;
@@ -12,6 +12,9 @@ type DeclarationWithMetadata = CanonicalFormatDeclaration;
12
12
  export type PackageSelectionMetadata = {
13
13
  format_option_refs?: readonly unknown[];
14
14
  };
15
+ /** Keep seller-origin evidence private while canonical products pass through the cache. */
16
+ export declare function rememberSellerDeclaredFormatOption(declaration: object, declared: boolean): void;
17
+ export declare function sellerDeclaredFormatOption(declaration: object): boolean | undefined;
15
18
  export declare function concealLegacyFormatRefs(declaration: ProductFormatDeclaration | V2ProductFormatDeclaration | CanonicalFormatDeclaration): DeclarationWithMetadata;
16
19
  export declare function legacyFormatRefsForDeclaration(value: unknown): readonly V1FormatId[];
17
20
  export declare function selectedFormatOptions(value: unknown): readonly DeclarationWithMetadata[];
@@ -21,17 +21,28 @@ __export(legacy_metadata_exports, {
21
21
  concealLegacyFormatRefs: () => concealLegacyFormatRefs,
22
22
  concealSelectedFormatOptions: () => concealSelectedFormatOptions,
23
23
  legacyFormatRefsForDeclaration: () => legacyFormatRefsForDeclaration,
24
+ rememberSellerDeclaredFormatOption: () => rememberSellerDeclaredFormatOption,
24
25
  selectedFormatOptions: () => selectedFormatOptions,
26
+ sellerDeclaredFormatOption: () => sellerDeclaredFormatOption,
25
27
  structuredCloneWithLegacyCreativeMetadata: () => structuredCloneWithLegacyCreativeMetadata,
26
28
  transferLegacyCreativeMetadata: () => transferLegacyCreativeMetadata
27
29
  });
28
30
  module.exports = __toCommonJS(legacy_metadata_exports);
29
31
  const legacyRefsByDeclaration = /* @__PURE__ */ new WeakMap();
30
32
  const selectedOptionsByRefs = /* @__PURE__ */ new WeakMap();
33
+ const sellerDeclaredByDeclaration = /* @__PURE__ */ new WeakMap();
34
+ function rememberSellerDeclaredFormatOption(declaration, declared) {
35
+ sellerDeclaredByDeclaration.set(declaration, declared);
36
+ }
37
+ function sellerDeclaredFormatOption(declaration) {
38
+ return sellerDeclaredByDeclaration.get(declaration);
39
+ }
31
40
  function concealLegacyFormatRefs(declaration) {
32
41
  const { v1_format_ref: refs, ...canonical } = declaration;
33
42
  const existingHidden = legacyRefsByDeclaration.get(declaration);
34
43
  const refsToConceal = Array.isArray(existingHidden) && existingHidden.length > 0 ? existingHidden : refs;
44
+ const declared = sellerDeclaredByDeclaration.get(declaration);
45
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(canonical, declared);
35
46
  if (Array.isArray(refsToConceal) && refsToConceal.length > 0) {
36
47
  legacyRefsByDeclaration.set(
37
48
  canonical,
@@ -62,11 +73,15 @@ function transferLegacyCreativeMetadata(source, target) {
62
73
  if (refs) legacyRefsByDeclaration.set(target, refs);
63
74
  const selected = selectedOptionsByRefs.get(source);
64
75
  if (selected) selectedOptionsByRefs.set(target, selected);
76
+ const declared = sellerDeclaredByDeclaration.get(source);
77
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(target, declared);
65
78
  }
66
79
  function structuredCloneWithLegacyCreativeMetadata(value) {
67
80
  const clone = structuredClone(value);
68
81
  const visited = /* @__PURE__ */ new WeakMap();
69
82
  const snapshotMetadata = (source, target) => {
83
+ const declared = sellerDeclaredByDeclaration.get(source);
84
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(target, declared);
70
85
  const refs = legacyRefsByDeclaration.get(source);
71
86
  if (refs) legacyRefsByDeclaration.set(target, structuredClone(refs));
72
87
  const selected = selectedOptionsByRefs.get(source);
@@ -105,7 +120,9 @@ function structuredCloneWithLegacyCreativeMetadata(value) {
105
120
  concealLegacyFormatRefs,
106
121
  concealSelectedFormatOptions,
107
122
  legacyFormatRefsForDeclaration,
123
+ rememberSellerDeclaredFormatOption,
108
124
  selectedFormatOptions,
125
+ sellerDeclaredFormatOption,
109
126
  structuredCloneWithLegacyCreativeMetadata,
110
127
  transferLegacyCreativeMetadata
111
128
  });
@@ -1,9 +1,18 @@
1
1
  const legacyRefsByDeclaration = /* @__PURE__ */ new WeakMap();
2
2
  const selectedOptionsByRefs = /* @__PURE__ */ new WeakMap();
3
+ const sellerDeclaredByDeclaration = /* @__PURE__ */ new WeakMap();
4
+ function rememberSellerDeclaredFormatOption(declaration, declared) {
5
+ sellerDeclaredByDeclaration.set(declaration, declared);
6
+ }
7
+ function sellerDeclaredFormatOption(declaration) {
8
+ return sellerDeclaredByDeclaration.get(declaration);
9
+ }
3
10
  function concealLegacyFormatRefs(declaration) {
4
11
  const { v1_format_ref: refs, ...canonical } = declaration;
5
12
  const existingHidden = legacyRefsByDeclaration.get(declaration);
6
13
  const refsToConceal = Array.isArray(existingHidden) && existingHidden.length > 0 ? existingHidden : refs;
14
+ const declared = sellerDeclaredByDeclaration.get(declaration);
15
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(canonical, declared);
7
16
  if (Array.isArray(refsToConceal) && refsToConceal.length > 0) {
8
17
  legacyRefsByDeclaration.set(
9
18
  canonical,
@@ -34,11 +43,15 @@ function transferLegacyCreativeMetadata(source, target) {
34
43
  if (refs) legacyRefsByDeclaration.set(target, refs);
35
44
  const selected = selectedOptionsByRefs.get(source);
36
45
  if (selected) selectedOptionsByRefs.set(target, selected);
46
+ const declared = sellerDeclaredByDeclaration.get(source);
47
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(target, declared);
37
48
  }
38
49
  function structuredCloneWithLegacyCreativeMetadata(value) {
39
50
  const clone = structuredClone(value);
40
51
  const visited = /* @__PURE__ */ new WeakMap();
41
52
  const snapshotMetadata = (source, target) => {
53
+ const declared = sellerDeclaredByDeclaration.get(source);
54
+ if (declared !== void 0) sellerDeclaredByDeclaration.set(target, declared);
42
55
  const refs = legacyRefsByDeclaration.get(source);
43
56
  if (refs) legacyRefsByDeclaration.set(target, structuredClone(refs));
44
57
  const selected = selectedOptionsByRefs.get(source);
@@ -76,7 +89,9 @@ export {
76
89
  concealLegacyFormatRefs,
77
90
  concealSelectedFormatOptions,
78
91
  legacyFormatRefsForDeclaration,
92
+ rememberSellerDeclaredFormatOption,
79
93
  selectedFormatOptions,
94
+ sellerDeclaredFormatOption,
80
95
  structuredCloneWithLegacyCreativeMetadata,
81
96
  transferLegacyCreativeMetadata
82
97
  };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "15.7.1";
4
+ export declare const LIBRARY_VERSION = "15.8.1";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "15.7.1";
36
+ readonly library: "15.8.1";
37
37
  readonly adcp: "3.2.3";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
39
- readonly generatedAt: "2026-10-10T00:48:09.224Z";
39
+ readonly generatedAt: "2026-10-11T16:14:38.709Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "15.7.1";
4
+ export declare const LIBRARY_VERSION = "15.8.1";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "15.7.1";
36
+ readonly library: "15.8.1";
37
37
  readonly adcp: "3.2.3";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
39
- readonly generatedAt: "2026-10-10T00:48:09.224Z";
39
+ readonly generatedAt: "2026-10-11T16:14:38.709Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -31,7 +31,7 @@ __export(version_exports, {
31
31
  toReleasePrecisionVersion: () => toReleasePrecisionVersion
32
32
  });
33
33
  module.exports = __toCommonJS(version_exports);
34
- const LIBRARY_VERSION = "15.7.1";
34
+ const LIBRARY_VERSION = "15.8.1";
35
35
  const ADCP_VERSION = "3.2.3";
36
36
  const ADCP_MAJOR_VERSION = 3;
37
37
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -97,10 +97,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
97
97
  "3.2.3"
98
98
  ];
99
99
  const VERSION_INFO = {
100
- library: "15.7.1",
100
+ library: "15.8.1",
101
101
  adcp: "3.2.3",
102
102
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
103
- generatedAt: "2026-10-10T00:48:09.224Z"
103
+ generatedAt: "2026-10-11T16:14:38.709Z"
104
104
  };
105
105
  function getAdcpVersion() {
106
106
  return ADCP_VERSION;
@@ -1,4 +1,4 @@
1
- const LIBRARY_VERSION = "15.7.1";
1
+ const LIBRARY_VERSION = "15.8.1";
2
2
  const ADCP_VERSION = "3.2.3";
3
3
  const ADCP_MAJOR_VERSION = 3;
4
4
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -64,10 +64,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
64
64
  "3.2.3"
65
65
  ];
66
66
  const VERSION_INFO = {
67
- library: "15.7.1",
67
+ library: "15.8.1",
68
68
  adcp: "3.2.3",
69
69
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
70
- generatedAt: "2026-10-10T00:48:09.224Z"
70
+ generatedAt: "2026-10-11T16:14:38.709Z"
71
71
  };
72
72
  function getAdcpVersion() {
73
73
  return ADCP_VERSION;
@@ -1,7 +1,7 @@
1
1
  # AdCP Type Summary
2
2
 
3
- > Generated at: 2026-10-10
4
- > @adcp/sdk v15.7.1
3
+ > Generated at: 2026-10-11
4
+ > @adcp/sdk v15.8.1
5
5
 
6
6
  Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
7
7