@adcp/sdk 15.7.1 → 15.8.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 (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 +314 -13
  24. package/dist/lib/reporting/ledger/postgres.mjs +314 -13
  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
@@ -159,6 +159,7 @@ import {
159
159
  projectMediaBuyCreativesForDelivery,
160
160
  projectCreativeForDelivery,
161
161
  projectSyncCreativesForDelivery,
162
+ projectUndeclaredFormatOptionSelectors,
162
163
  resolveCreativeFormatWireMode,
163
164
  stripLegacyCreativeIdentity
164
165
  } from "../v2/projection/creative-delivery.mjs";
@@ -168,10 +169,13 @@ import {
168
169
  import { toCanonicalOnlyResponse } from "../v2/projection/augment-response.mjs";
169
170
  import {
170
171
  legacyFormatRefsForDeclaration,
172
+ rememberSellerDeclaredFormatOption,
173
+ sellerDeclaredFormatOption,
171
174
  structuredCloneWithLegacyCreativeMetadata
172
175
  } from "../v2/projection/legacy-metadata.mjs";
173
176
  import { isProjectionProductInput } from "../v2/projection/types.mjs";
174
177
  import { canonicalize as canonicalizeJson } from "../utils/jcs.mjs";
178
+ const toolInputSchemasByProperties = /* @__PURE__ */ new WeakMap();
175
179
  const CAPABILITY_DISCOVERY_CONTEXT = /* @__PURE__ */ Symbol("capabilityDiscoveryContext");
176
180
  function a2aUrlString(input) {
177
181
  return typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
@@ -218,32 +222,6 @@ function selectA2AJsonRpcUrl(agentCard, protocolVersion, configuredAgentUrl) {
218
222
  }
219
223
  return resolved.toString();
220
224
  }
221
- function creativeSchemaSupport(value, depth = 0) {
222
- if (depth > 24 || value === null || typeof value !== "object") return "unknown";
223
- if (Array.isArray(value)) {
224
- let legacy2 = false;
225
- for (const item of value) {
226
- const support = creativeSchemaSupport(item, depth + 1);
227
- if (support === "canonical") return support;
228
- if (support === "legacy") legacy2 = true;
229
- }
230
- return legacy2 ? "legacy" : "unknown";
231
- }
232
- const object = value;
233
- const properties = object.properties;
234
- if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
235
- const keys = properties;
236
- if ("creative_id" in keys && "format_kind" in keys) return "canonical";
237
- if ("creative_id" in keys && "format_id" in keys) return "legacy";
238
- }
239
- let legacy = false;
240
- for (const child of Object.values(object)) {
241
- const support = creativeSchemaSupport(child, depth + 1);
242
- if (support === "canonical") return support;
243
- if (support === "legacy") legacy = true;
244
- }
245
- return legacy ? "legacy" : "unknown";
246
- }
247
225
  function hasMediaBuyCreativeFormatData(request) {
248
226
  if (request === null || typeof request !== "object" || Array.isArray(request)) return false;
249
227
  const record = request;
@@ -1404,9 +1382,10 @@ class SingleAgentClient {
1404
1382
  }
1405
1383
  }
1406
1384
  }
1407
- rememberCanonicalProductRoutes(products, account, authoritativeProducts = products) {
1408
- this.invalidateCanonicalProductRoutes(authoritativeProducts, account);
1385
+ rememberCanonicalProductRoutes(products, account, authoritativeProducts) {
1386
+ this.invalidateCanonicalProductRoutes(authoritativeProducts ?? products, account);
1409
1387
  const accountScope = this.canonicalAccountScope(account);
1388
+ const declaredOptions = authoritativeProducts ? this.sellerDeclaredFormatOptions(authoritativeProducts) : void 0;
1410
1389
  for (const value of products) {
1411
1390
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1412
1391
  const product = value;
@@ -1422,16 +1401,78 @@ class SingleAgentClient {
1422
1401
  } : { scope: "product", format_option_id: option.format_option_id };
1423
1402
  const refs = legacyFormatRefsForDeclaration(option);
1424
1403
  if (refs.length === 0) continue;
1404
+ const declared = declaredOptions ? declaredOptions.get(product.product_id)?.some((declaredRef) => this.sameCanonicalOptionRef(declaredRef, ref)) : sellerDeclaredFormatOption(option);
1405
+ if (declared !== void 0) rememberSellerDeclaredFormatOption(option, declared);
1425
1406
  this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
1426
1407
  kind: "product",
1427
1408
  accountScope,
1428
1409
  productId: product.product_id,
1429
1410
  optionRef: ref,
1430
- refs
1411
+ refs,
1412
+ ...declared === false ? {
1413
+ undeclaredSelector: {
1414
+ format_kind: typeof option.format_kind === "string" ? option.format_kind : "",
1415
+ ...option.params !== void 0 && { params: structuredClone(option.params) },
1416
+ ...(typeof option.format_kind !== "string" || option.format_kind === "custom" || option.format_shape !== void 0 || option.format_schema !== void 0) && { unrepresentable: true }
1417
+ }
1418
+ } : {}
1431
1419
  });
1432
1420
  }
1433
1421
  }
1434
1422
  }
1423
+ /**
1424
+ * Option refs each product declared in the seller's own response. A product
1425
+ * absent from the response yields no entry, so its options are treated as
1426
+ * declared rather than guessed undeclared.
1427
+ */
1428
+ sellerDeclaredFormatOptions(authoritativeProducts) {
1429
+ const declared = /* @__PURE__ */ new Map();
1430
+ for (const value of authoritativeProducts) {
1431
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1432
+ const product = value;
1433
+ if (typeof product.product_id !== "string") continue;
1434
+ const refs = [];
1435
+ for (const optionValue of Array.isArray(product.format_options) ? product.format_options : []) {
1436
+ if (!optionValue || typeof optionValue !== "object" || Array.isArray(optionValue)) continue;
1437
+ const option = optionValue;
1438
+ if (typeof option.format_option_id !== "string") continue;
1439
+ refs.push(
1440
+ typeof option.publisher_domain === "string" ? {
1441
+ scope: "publisher",
1442
+ publisher_domain: option.publisher_domain,
1443
+ format_option_id: option.format_option_id
1444
+ } : { scope: "product", format_option_id: option.format_option_id }
1445
+ );
1446
+ }
1447
+ declared.set(product.product_id, refs);
1448
+ }
1449
+ return declared;
1450
+ }
1451
+ /**
1452
+ * The direct selector for an option this client derived from the seller's
1453
+ * legacy `format_ids`. Without a product id, every remembered route for the
1454
+ * option must agree that the seller did not declare it.
1455
+ */
1456
+ undeclaredFormatOptionSelector(account, ref, productId) {
1457
+ if (productId !== void 0) {
1458
+ const route = this.routeForOption(account, productId, ref);
1459
+ return route?.kind === "product" ? route.undeclaredSelector : void 0;
1460
+ }
1461
+ const accountScope = this.canonicalAccountScope(account);
1462
+ const routes = [...this.canonicalLegacyRoutes.values()].filter(
1463
+ (route) => route.kind === "product" && (route.accountScope === accountScope || route.accountScope === "none") && this.sameCanonicalOptionRef(route.optionRef, ref)
1464
+ );
1465
+ if (routes.length === 0 || routes.some((route) => route.undeclaredSelector === void 0)) return void 0;
1466
+ return routes[0].undeclaredSelector;
1467
+ }
1468
+ projectUndeclaredFormatOptions(request, operation, wireMode, account) {
1469
+ if (wireMode !== "canonical") return request;
1470
+ return projectUndeclaredFormatOptionSelectors(
1471
+ request,
1472
+ operation,
1473
+ (ref, productId) => this.undeclaredFormatOptionSelector(account, ref, productId)
1474
+ );
1475
+ }
1435
1476
  rememberCanonicalProductRoutesForCompletion(taskType, data, legacyFormatConverter, account) {
1436
1477
  if (taskType !== "get_products" || !data || typeof data !== "object" || Array.isArray(data)) return;
1437
1478
  const authoritativeProducts = Array.isArray(data.products) ? data.products : [];
@@ -4560,7 +4601,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4560
4601
  if (hit) {
4561
4602
  throwIfAborted(effectiveOptions.signal);
4562
4603
  if (hit.success && hit.status === "completed")
4563
- this.rememberCanonicalProductRoutes(hit.data.products ?? [], account, hit.data.products ?? []);
4604
+ this.rememberCanonicalProductRoutes(hit.data.products ?? [], account);
4564
4605
  return attachMatch(
4565
4606
  await this.applyProductPropertyPolicy(
4566
4607
  hit,
@@ -4604,11 +4645,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4604
4645
  [SKIP_PRODUCT_CACHE]: true
4605
4646
  });
4606
4647
  }
4607
- this.rememberCanonicalProductRoutes(
4608
- cachedResult.data.products ?? [],
4609
- account,
4610
- cachedResult.data.products ?? []
4611
- );
4648
+ this.rememberCanonicalProductRoutes(cachedResult.data.products ?? [], account);
4612
4649
  }
4613
4650
  if (cachedResult.submitted) {
4614
4651
  const submitted = cachedResult.submitted;
@@ -4764,12 +4801,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4764
4801
  const result = await this.executeAndHandle(
4765
4802
  "create_media_buy",
4766
4803
  "onCreateMediaBuyStatusChange",
4767
- projectMediaBuyCreativesForDelivery(
4768
- wireParams,
4769
- wireMode,
4804
+ this.projectUndeclaredFormatOptions(
4805
+ projectMediaBuyCreativesForDelivery(
4806
+ wireParams,
4807
+ wireMode,
4808
+ "create_media_buy",
4809
+ effectiveLegacyFormatConverter,
4810
+ effectiveCanonicalFormatLegacyResolver
4811
+ ),
4770
4812
  "create_media_buy",
4771
- effectiveLegacyFormatConverter,
4772
- effectiveCanonicalFormatLegacyResolver
4813
+ wireMode,
4814
+ wireParams.account
4773
4815
  ),
4774
4816
  inputHandler,
4775
4817
  taskOptions,
@@ -4845,12 +4887,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4845
4887
  const result = await this.executeAndHandle(
4846
4888
  "update_media_buy",
4847
4889
  "onUpdateMediaBuyStatusChange",
4848
- projectMediaBuyCreativesForDelivery(
4849
- params,
4850
- wireMode,
4890
+ this.projectUndeclaredFormatOptions(
4891
+ projectMediaBuyCreativesForDelivery(
4892
+ params,
4893
+ wireMode,
4894
+ "update_media_buy",
4895
+ effectiveLegacyFormatConverter,
4896
+ effectiveCanonicalFormatLegacyResolver
4897
+ ),
4851
4898
  "update_media_buy",
4852
- effectiveLegacyFormatConverter,
4853
- effectiveCanonicalFormatLegacyResolver
4899
+ wireMode,
4900
+ params.account
4854
4901
  ),
4855
4902
  inputHandler,
4856
4903
  taskOptions,
@@ -4936,12 +4983,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4936
4983
  const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
4937
4984
  (assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
4938
4985
  ) : [];
4939
- const wireParams = projectSyncCreativesForDelivery(
4940
- params,
4941
- [...configuredSelectorContainers, ...assignmentPackageContainers],
4986
+ const wireParams = this.projectUndeclaredFormatOptions(
4987
+ projectSyncCreativesForDelivery(
4988
+ params,
4989
+ [...configuredSelectorContainers, ...assignmentPackageContainers],
4990
+ wireMode,
4991
+ effectiveLegacyFormatConverter,
4992
+ effectiveCanonicalFormatLegacyResolver
4993
+ ),
4994
+ "sync_creatives",
4942
4995
  wireMode,
4943
- effectiveLegacyFormatConverter,
4944
- effectiveCanonicalFormatLegacyResolver
4996
+ params.account
4945
4997
  );
4946
4998
  return this.executeAndHandle(
4947
4999
  "sync_creatives",
@@ -4980,6 +5032,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4980
5032
  * `CreativeFormatCapabilityError`, just as they do during a write.
4981
5033
  */
4982
5034
  async resolveCreativeFormatWireMode(taskType, options) {
5035
+ return this.resolveCreativeWireMode(taskType, options, true);
5036
+ }
5037
+ async resolveCreativeWireMode(taskType, options, canRediscover) {
4983
5038
  const discoveryContext = {};
4984
5039
  const capabilities = await this.getCapabilities({
4985
5040
  ...options,
@@ -4989,7 +5044,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4989
5044
  const toolSchemas = discoveryContext.toolSchemas ?? (usesScopedFetch ? void 0 : this.cachedToolSchemas);
4990
5045
  const wireRelease = this.config.wireAdcpVersion ?? this.resolvedAdcpVersion;
4991
5046
  const declared = resolveCreativeFormatWireMode(capabilities, wireRelease);
4992
- const schema = creativeSchemaSupport(toolSchemas?.get(taskType));
5047
+ const document = toolSchemas && toolInputSchemasByProperties.get(toolSchemas)?.get(taskType);
5048
+ const { creativeSchemaSupport } = await import("./creative-schema-support.mjs");
5049
+ throwIfAborted(options?.signal);
5050
+ const schema = creativeSchemaSupport(document ?? { properties: toolSchemas?.get(taskType) });
4993
5051
  if (declared !== "unknown" && schema !== "unknown" && declared !== schema) {
4994
5052
  throw new CreativeFormatCapabilityError(
4995
5053
  `Seller capability and ${taskType} input schema disagree about canonical creative support`
@@ -4999,6 +5057,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4999
5057
  const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
5000
5058
  const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
5001
5059
  if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
5060
+ if (canRediscover && !usesScopedFetch && this.normalizedAgent.protocol === "mcp" && this.capabilitiesFromSharedCache && toolSchemas?.has(taskType) && !toolInputSchemasByProperties.has(toolSchemas)) {
5061
+ await this.invalidateDiscoveryCache(options);
5062
+ return this.resolveCreativeWireMode(taskType, options, false);
5063
+ }
5002
5064
  throw new CreativeFormatCapabilityError(
5003
5065
  `Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
5004
5066
  );
@@ -6658,11 +6720,20 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
6658
6720
  if (toolSchemas !== void 0 && !isToolSchemaRecord(toolSchemas)) {
6659
6721
  return void 0;
6660
6722
  }
6723
+ if (entry.toolInputSchemas !== void 0 && (!toolSchemas || !isToolSchemaRecord(entry.toolInputSchemas))) {
6724
+ return void 0;
6725
+ }
6661
6726
  let installed;
6662
6727
  let schemas;
6663
6728
  try {
6664
6729
  installed = structuredClone(capabilities);
6665
6730
  schemas = toolSchemas ? new Map(Object.entries(toolSchemas).map(([tool, properties]) => [tool, structuredClone(properties)])) : void 0;
6731
+ if (schemas && entry.toolInputSchemas) {
6732
+ toolInputSchemasByProperties.set(
6733
+ schemas,
6734
+ new Map(Object.entries(entry.toolInputSchemas).map(([tool, schema]) => [tool, structuredClone(schema)]))
6735
+ );
6736
+ }
6666
6737
  } catch {
6667
6738
  return void 0;
6668
6739
  }
@@ -6683,9 +6754,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
6683
6754
  name: t.name,
6684
6755
  description: t.description
6685
6756
  }));
6757
+ const discoveredInputSchemas = new Map(
6758
+ agentInfo.tools.filter((t) => t.inputSchema).map((t) => [t.name, t.inputSchema])
6759
+ );
6686
6760
  const discoveredToolSchemas = new Map(
6687
- agentInfo.tools.filter((t) => t.inputSchema?.properties).map((t) => [t.name, t.inputSchema.properties])
6761
+ [...discoveredInputSchemas].map(([name, schema]) => [name, schema.properties ?? {}])
6688
6762
  );
6763
+ toolInputSchemasByProperties.set(discoveredToolSchemas, discoveredInputSchemas);
6689
6764
  if (discoveryContext) discoveryContext.toolSchemas = discoveredToolSchemas;
6690
6765
  if (!usesScopedFetch && !superseded()) this.cachedToolSchemas = discoveredToolSchemas;
6691
6766
  const advertisesCapabilitiesTool = tools.some((t) => t.name === "get_adcp_capabilities");
@@ -6728,7 +6803,8 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
6728
6803
  options,
6729
6804
  {
6730
6805
  capabilities: structuredClone(capabilities2),
6731
- toolSchemas: Object.fromEntries(discoveredToolSchemas)
6806
+ toolSchemas: Object.fromEntries(discoveredToolSchemas),
6807
+ toolInputSchemas: Object.fromEntries(discoveredInputSchemas)
6732
6808
  },
6733
6809
  false,
6734
6810
  startedAtEpoch
@@ -7126,7 +7202,11 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
7126
7202
  const key = this.sharedDiscoveryKey(options);
7127
7203
  if (!key) return void 0;
7128
7204
  if (patch.endpoint && !this.isDiscoverableEndpoint(patch.endpoint.agentUri)) {
7129
- patch = { capabilities: patch.capabilities, toolSchemas: patch.toolSchemas };
7205
+ patch = {
7206
+ capabilities: patch.capabilities,
7207
+ toolSchemas: patch.toolSchemas,
7208
+ toolInputSchemas: patch.toolInputSchemas
7209
+ };
7130
7210
  if (!patch.capabilities && !patch.toolSchemas) return void 0;
7131
7211
  }
7132
7212
  const config = this.config.discoveryCache;
@@ -7154,10 +7234,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
7154
7234
  const entry = {
7155
7235
  ...existing?.capabilities && { capabilities: existing.capabilities },
7156
7236
  ...existing?.toolSchemas && { toolSchemas: existing.toolSchemas },
7237
+ // Endpoint-only writes retain schema documents. Fresh tool evidence
7238
+ // replaces them together, including clearing older full documents
7239
+ // when the caller supplies only a property map.
7240
+ ...patch.toolSchemas === void 0 && existing?.toolInputSchemas && {
7241
+ toolInputSchemas: existing.toolInputSchemas
7242
+ },
7157
7243
  ...existing?.endpoint && { endpoint: existing.endpoint },
7158
7244
  ...patch.endpoint && { endpoint: { ...patch.endpoint, observedAt: now } },
7159
7245
  ...patch.capabilities && { capabilities: patch.capabilities },
7160
7246
  ...patch.toolSchemas && { toolSchemas: patch.toolSchemas },
7247
+ ...patch.toolInputSchemas && { toolInputSchemas: patch.toolInputSchemas },
7161
7248
  observedAt: restartsClock || !existing ? now : Math.min(existing.observedAt, now),
7162
7249
  expiresAt: restartsClock || !existing ? now + ttl : Math.min(existing.expiresAt, now + ttl)
7163
7250
  };
@@ -20,6 +20,8 @@ export interface AgentDiscoveryEntry {
20
20
  capabilities?: AdcpCapabilities;
21
21
  /** `tools/list` input-schema properties keyed by tool name. */
22
22
  toolSchemas?: Record<string, Record<string, unknown>>;
23
+ /** Complete listed input schemas, including local reference targets; absent in older entries. Backends must allow space for both these documents and their property maps. */
24
+ toolInputSchemas?: Record<string, Record<string, unknown>>;
23
25
  /** Epoch milliseconds when this evidence was observed. */
24
26
  observedAt: number;
25
27
  /** Epoch milliseconds after which the entry must not be used. Enforced by the SDK on read. */
@@ -20,6 +20,8 @@ export interface AgentDiscoveryEntry {
20
20
  capabilities?: AdcpCapabilities;
21
21
  /** `tools/list` input-schema properties keyed by tool name. */
22
22
  toolSchemas?: Record<string, Record<string, unknown>>;
23
+ /** Complete listed input schemas, including local reference targets; absent in older entries. Backends must allow space for both these documents and their property maps. */
24
+ toolInputSchemas?: Record<string, Record<string, unknown>>;
23
25
  /** Epoch milliseconds when this evidence was observed. */
24
26
  observedAt: number;
25
27
  /** Epoch milliseconds after which the entry must not be used. Enforced by the SDK on read. */
@@ -0,0 +1,3 @@
1
+ import type { CreativeFormatWireMode } from '../v2/projection/creative-delivery.mjs';
2
+ /** Inspect reachable input schemas without fetching references or treating unused definitions as evidence. */
3
+ export declare function creativeSchemaSupport(inputSchema: unknown): CreativeFormatWireMode;
@@ -0,0 +1,3 @@
1
+ import type { CreativeFormatWireMode } from '../v2/projection/creative-delivery';
2
+ /** Inspect reachable input schemas without fetching references or treating unused definitions as evidence. */
3
+ export declare function creativeSchemaSupport(inputSchema: unknown): CreativeFormatWireMode;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var creative_schema_support_exports = {};
20
+ __export(creative_schema_support_exports, {
21
+ creativeSchemaSupport: () => creativeSchemaSupport
22
+ });
23
+ module.exports = __toCommonJS(creative_schema_support_exports);
24
+ function creativeSchemaSupport(inputSchema) {
25
+ const visited = /* @__PURE__ */ new WeakSet();
26
+ let remaining = 1e4;
27
+ let truncated = false;
28
+ function resolvePointer(reference, root) {
29
+ if (!reference.startsWith("#")) return void 0;
30
+ let pointer;
31
+ try {
32
+ pointer = decodeURIComponent(reference.slice(1));
33
+ } catch {
34
+ return void 0;
35
+ }
36
+ if (pointer === "") return { value: root, root };
37
+ if (!pointer.startsWith("/") || /~(?![01])/.test(pointer)) return void 0;
38
+ let value = root;
39
+ for (const token of pointer.slice(1).split("/")) {
40
+ const key = token.replace(/~1/g, "/").replace(/~0/g, "~");
41
+ if (value === null || typeof value !== "object" || !Object.hasOwn(value, key)) return void 0;
42
+ const resource = value;
43
+ if (typeof resource.$id === "string" && resource.$id !== "" && !resource.$id.startsWith("#")) root = resource;
44
+ value = value[key];
45
+ }
46
+ return { value, root };
47
+ }
48
+ function visit(value, root, depth) {
49
+ if (value === null || typeof value !== "object" || visited.has(value)) {
50
+ return "unknown";
51
+ }
52
+ if (--remaining < 0 || depth > 64) {
53
+ truncated = true;
54
+ return "unknown";
55
+ }
56
+ visited.add(value);
57
+ let legacy = false;
58
+ const inspect = (child) => {
59
+ const mode2 = visit(child, root, depth + 1);
60
+ if (mode2 === "legacy") legacy = true;
61
+ return mode2 === "canonical";
62
+ };
63
+ if (Array.isArray(value)) {
64
+ for (const child of value) if (inspect(child)) return "canonical";
65
+ return legacy ? "legacy" : "unknown";
66
+ }
67
+ const schema = value;
68
+ if (typeof schema.$id === "string" && schema.$id !== "" && !schema.$id.startsWith("#")) root = schema;
69
+ const properties = schema.properties;
70
+ if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
71
+ const fields = properties;
72
+ if (Object.hasOwn(fields, "creative_id") && fields.creative_id !== false) {
73
+ if (Object.hasOwn(fields, "format_kind") && fields.format_kind !== false) return "canonical";
74
+ if (Object.hasOwn(fields, "format_id") && fields.format_id !== false) legacy = true;
75
+ }
76
+ }
77
+ if (typeof schema.$ref === "string") {
78
+ const target = resolvePointer(schema.$ref, root);
79
+ if (target) {
80
+ const mode2 = visit(target.value, target.root, depth + 1);
81
+ if (mode2 === "canonical") return mode2;
82
+ if (mode2 === "legacy") legacy = true;
83
+ }
84
+ }
85
+ for (const keyword of ["properties", "patternProperties", "dependentSchemas"]) {
86
+ const children = schema[keyword];
87
+ if (children !== null && typeof children === "object" && !Array.isArray(children)) {
88
+ for (const child of Object.values(children)) if (inspect(child)) return "canonical";
89
+ }
90
+ }
91
+ for (const keyword of [
92
+ "items",
93
+ "prefixItems",
94
+ "contains",
95
+ "additionalItems",
96
+ "additionalProperties",
97
+ "unevaluatedItems",
98
+ "unevaluatedProperties",
99
+ "allOf",
100
+ "anyOf",
101
+ "oneOf"
102
+ ]) {
103
+ if (inspect(schema[keyword])) return "canonical";
104
+ }
105
+ return legacy ? "legacy" : "unknown";
106
+ }
107
+ const mode = visit(inputSchema, inputSchema, 0);
108
+ return truncated ? "unknown" : mode;
109
+ }
110
+ // Annotate the CommonJS export names for ESM import in node:
111
+ 0 && (module.exports = {
112
+ creativeSchemaSupport
113
+ });
@@ -0,0 +1,89 @@
1
+ function creativeSchemaSupport(inputSchema) {
2
+ const visited = /* @__PURE__ */ new WeakSet();
3
+ let remaining = 1e4;
4
+ let truncated = false;
5
+ function resolvePointer(reference, root) {
6
+ if (!reference.startsWith("#")) return void 0;
7
+ let pointer;
8
+ try {
9
+ pointer = decodeURIComponent(reference.slice(1));
10
+ } catch {
11
+ return void 0;
12
+ }
13
+ if (pointer === "") return { value: root, root };
14
+ if (!pointer.startsWith("/") || /~(?![01])/.test(pointer)) return void 0;
15
+ let value = root;
16
+ for (const token of pointer.slice(1).split("/")) {
17
+ const key = token.replace(/~1/g, "/").replace(/~0/g, "~");
18
+ if (value === null || typeof value !== "object" || !Object.hasOwn(value, key)) return void 0;
19
+ const resource = value;
20
+ if (typeof resource.$id === "string" && resource.$id !== "" && !resource.$id.startsWith("#")) root = resource;
21
+ value = value[key];
22
+ }
23
+ return { value, root };
24
+ }
25
+ function visit(value, root, depth) {
26
+ if (value === null || typeof value !== "object" || visited.has(value)) {
27
+ return "unknown";
28
+ }
29
+ if (--remaining < 0 || depth > 64) {
30
+ truncated = true;
31
+ return "unknown";
32
+ }
33
+ visited.add(value);
34
+ let legacy = false;
35
+ const inspect = (child) => {
36
+ const mode2 = visit(child, root, depth + 1);
37
+ if (mode2 === "legacy") legacy = true;
38
+ return mode2 === "canonical";
39
+ };
40
+ if (Array.isArray(value)) {
41
+ for (const child of value) if (inspect(child)) return "canonical";
42
+ return legacy ? "legacy" : "unknown";
43
+ }
44
+ const schema = value;
45
+ if (typeof schema.$id === "string" && schema.$id !== "" && !schema.$id.startsWith("#")) root = schema;
46
+ const properties = schema.properties;
47
+ if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
48
+ const fields = properties;
49
+ if (Object.hasOwn(fields, "creative_id") && fields.creative_id !== false) {
50
+ if (Object.hasOwn(fields, "format_kind") && fields.format_kind !== false) return "canonical";
51
+ if (Object.hasOwn(fields, "format_id") && fields.format_id !== false) legacy = true;
52
+ }
53
+ }
54
+ if (typeof schema.$ref === "string") {
55
+ const target = resolvePointer(schema.$ref, root);
56
+ if (target) {
57
+ const mode2 = visit(target.value, target.root, depth + 1);
58
+ if (mode2 === "canonical") return mode2;
59
+ if (mode2 === "legacy") legacy = true;
60
+ }
61
+ }
62
+ for (const keyword of ["properties", "patternProperties", "dependentSchemas"]) {
63
+ const children = schema[keyword];
64
+ if (children !== null && typeof children === "object" && !Array.isArray(children)) {
65
+ for (const child of Object.values(children)) if (inspect(child)) return "canonical";
66
+ }
67
+ }
68
+ for (const keyword of [
69
+ "items",
70
+ "prefixItems",
71
+ "contains",
72
+ "additionalItems",
73
+ "additionalProperties",
74
+ "unevaluatedItems",
75
+ "unevaluatedProperties",
76
+ "allOf",
77
+ "anyOf",
78
+ "oneOf"
79
+ ]) {
80
+ if (inspect(schema[keyword])) return "canonical";
81
+ }
82
+ return legacy ? "legacy" : "unknown";
83
+ }
84
+ const mode = visit(inputSchema, inputSchema, 0);
85
+ return truncated ? "unknown" : mode;
86
+ }
87
+ export {
88
+ creativeSchemaSupport
89
+ };
@@ -23,6 +23,7 @@ __export(product_cache_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(product_cache_exports);
25
25
  var import_account_key = require('./account-key.js');
26
+ var import_legacy_metadata = require('../v2/projection/legacy-metadata.js');
26
27
  function stable(value) {
27
28
  if (Array.isArray(value)) return value.map(stable);
28
29
  if (value && typeof value === "object")
@@ -69,7 +70,7 @@ class ProductCache {
69
70
  if (!allowExpired && Date.now() - entry.storedAt >= ttl) return void 0;
70
71
  return {
71
72
  ...entry.result,
72
- data: structuredClone(entry.result.data),
73
+ data: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(entry.result.data),
73
74
  metadata: structuredClone(entry.result.metadata),
74
75
  ...entry.result.debug_logs && { debug_logs: structuredClone(entry.result.debug_logs) }
75
76
  };
@@ -107,14 +108,14 @@ class ProductCache {
107
108
  if (!old || old.scope !== data.cache_scope || !oldData || data.wholesale_feed_version !== oldData.wholesale_feed_version || data.pricing_version !== void 0 && data.pricing_version !== oldData.pricing_version)
108
109
  return result;
109
110
  if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
110
- completed = { ...result, data: structuredClone(oldData) };
111
+ completed = { ...result, data: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(oldData) };
111
112
  } else if (!Array.isArray(data.products)) return result;
112
113
  if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
113
114
  this.entries.delete(this.entries.keys().next().value);
114
115
  this.entries.set(key, {
115
116
  result: {
116
117
  ...completed,
117
- data: structuredClone(completed.data),
118
+ data: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(completed.data),
118
119
  metadata: structuredClone(completed.metadata),
119
120
  ...completed.debug_logs && { debug_logs: structuredClone(completed.debug_logs) }
120
121
  },
@@ -1,4 +1,5 @@
1
1
  import { accountReferenceKey } from "./account-key.mjs";
2
+ import { structuredCloneWithLegacyCreativeMetadata } from "../v2/projection/legacy-metadata.mjs";
2
3
  function stable(value) {
3
4
  if (Array.isArray(value)) return value.map(stable);
4
5
  if (value && typeof value === "object")
@@ -45,7 +46,7 @@ class ProductCache {
45
46
  if (!allowExpired && Date.now() - entry.storedAt >= ttl) return void 0;
46
47
  return {
47
48
  ...entry.result,
48
- data: structuredClone(entry.result.data),
49
+ data: structuredCloneWithLegacyCreativeMetadata(entry.result.data),
49
50
  metadata: structuredClone(entry.result.metadata),
50
51
  ...entry.result.debug_logs && { debug_logs: structuredClone(entry.result.debug_logs) }
51
52
  };
@@ -83,14 +84,14 @@ class ProductCache {
83
84
  if (!old || old.scope !== data.cache_scope || !oldData || data.wholesale_feed_version !== oldData.wholesale_feed_version || data.pricing_version !== void 0 && data.pricing_version !== oldData.pricing_version)
84
85
  return result;
85
86
  if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
86
- completed = { ...result, data: structuredClone(oldData) };
87
+ completed = { ...result, data: structuredCloneWithLegacyCreativeMetadata(oldData) };
87
88
  } else if (!Array.isArray(data.products)) return result;
88
89
  if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
89
90
  this.entries.delete(this.entries.keys().next().value);
90
91
  this.entries.set(key, {
91
92
  result: {
92
93
  ...completed,
93
- data: structuredClone(completed.data),
94
+ data: structuredCloneWithLegacyCreativeMetadata(completed.data),
94
95
  metadata: structuredClone(completed.metadata),
95
96
  ...completed.debug_logs && { debug_logs: structuredClone(completed.debug_logs) }
96
97
  },