@adcp/sdk 16.3.0 → 16.4.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 (80) hide show
  1. package/dist/lib/adapters/version/3.1/assignments.d.mts +12 -0
  2. package/dist/lib/adapters/version/3.1/assignments.d.ts +12 -0
  3. package/dist/lib/adapters/version/3.1/assignments.js +67 -0
  4. package/dist/lib/adapters/version/3.1/assignments.mjs +43 -0
  5. package/dist/lib/adapters/version/3.1/bidding.d.mts +3 -0
  6. package/dist/lib/adapters/version/3.1/bidding.d.ts +3 -0
  7. package/dist/lib/adapters/version/3.1/bidding.js +115 -0
  8. package/dist/lib/adapters/version/3.1/bidding.mjs +90 -0
  9. package/dist/lib/adapters/version/3.1/delivery.d.mts +7 -0
  10. package/dist/lib/adapters/version/3.1/delivery.d.ts +7 -0
  11. package/dist/lib/adapters/version/3.1/delivery.js +78 -0
  12. package/dist/lib/adapters/version/3.1/delivery.mjs +54 -0
  13. package/dist/lib/adapters/version/3.1/index.d.mts +3 -0
  14. package/dist/lib/adapters/version/3.1/index.d.ts +3 -0
  15. package/dist/lib/adapters/version/3.1/index.js +36 -0
  16. package/dist/lib/adapters/version/3.1/index.mjs +12 -0
  17. package/dist/lib/adapters/version/index.d.mts +59 -7
  18. package/dist/lib/adapters/version/index.d.ts +59 -7
  19. package/dist/lib/adapters/version/index.js +51 -2
  20. package/dist/lib/adapters/version/index.mjs +49 -1
  21. package/dist/lib/adapters/version/negotiate.d.mts +71 -0
  22. package/dist/lib/adapters/version/negotiate.d.ts +71 -0
  23. package/dist/lib/adapters/version/negotiate.js +101 -0
  24. package/dist/lib/adapters/version/negotiate.mjs +73 -0
  25. package/dist/lib/adapters/version/schema-projection.d.mts +33 -0
  26. package/dist/lib/adapters/version/schema-projection.d.ts +33 -0
  27. package/dist/lib/adapters/version/schema-projection.js +294 -0
  28. package/dist/lib/adapters/version/schema-projection.mjs +269 -0
  29. package/dist/lib/adapters/version/translate.d.mts +122 -0
  30. package/dist/lib/adapters/version/translate.d.ts +122 -0
  31. package/dist/lib/adapters/version/translate.js +169 -0
  32. package/dist/lib/adapters/version/translate.mjs +141 -0
  33. package/dist/lib/adapters/version/types.d.mts +51 -10
  34. package/dist/lib/adapters/version/types.d.ts +51 -10
  35. package/dist/lib/core/AgentClient.d.mts +1 -1
  36. package/dist/lib/core/AgentClient.d.ts +1 -1
  37. package/dist/lib/core/ConversationTypes.d.mts +7 -0
  38. package/dist/lib/core/ConversationTypes.d.ts +7 -0
  39. package/dist/lib/core/SingleAgentClient.d.mts +82 -0
  40. package/dist/lib/core/SingleAgentClient.d.ts +82 -0
  41. package/dist/lib/core/SingleAgentClient.js +323 -15
  42. package/dist/lib/core/SingleAgentClient.mjs +337 -17
  43. package/dist/lib/core/TaskExecutor.d.mts +1 -1
  44. package/dist/lib/core/TaskExecutor.d.ts +1 -1
  45. package/dist/lib/core/TaskExecutor.js +97 -21
  46. package/dist/lib/core/TaskExecutor.mjs +97 -21
  47. package/dist/lib/core/account-reduction.d.mts +36 -0
  48. package/dist/lib/core/account-reduction.d.ts +36 -0
  49. package/dist/lib/core/account-reduction.js +127 -0
  50. package/dist/lib/core/account-reduction.mjs +98 -0
  51. package/dist/lib/core/buyer-account-registry.d.mts +52 -0
  52. package/dist/lib/core/buyer-account-registry.d.ts +52 -0
  53. package/dist/lib/core/buyer-account-registry.js +142 -6
  54. package/dist/lib/core/buyer-account-registry.mjs +142 -6
  55. package/dist/lib/media-buy/action-contracts.js +4 -4
  56. package/dist/lib/media-buy/action-contracts.mjs +4 -4
  57. package/dist/lib/media-buy/action-types.d.mts +3 -2
  58. package/dist/lib/media-buy/action-types.d.ts +3 -2
  59. package/dist/lib/media-buy/update-fields.generated.d.mts +3 -2
  60. package/dist/lib/media-buy/update-fields.generated.d.ts +3 -2
  61. package/dist/lib/registry/types.generated.d.mts +1 -1
  62. package/dist/lib/registry/types.generated.d.ts +1 -1
  63. package/dist/lib/server/create-adcp-server.d.mts +21 -0
  64. package/dist/lib/server/create-adcp-server.d.ts +21 -0
  65. package/dist/lib/server/create-adcp-server.js +97 -15
  66. package/dist/lib/server/create-adcp-server.mjs +83 -1
  67. package/dist/lib/server/index.d.mts +1 -1
  68. package/dist/lib/server/index.d.ts +1 -1
  69. package/dist/lib/storage/interfaces.d.mts +2 -0
  70. package/dist/lib/storage/interfaces.d.ts +2 -0
  71. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  72. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  73. package/dist/lib/version.d.mts +3 -3
  74. package/dist/lib/version.d.ts +3 -3
  75. package/dist/lib/version.js +3 -3
  76. package/dist/lib/version.mjs +3 -3
  77. package/docs/TYPE-SUMMARY.md +2 -2
  78. package/docs/llms.txt +3 -3
  79. package/docs/migration-14.x-rc-worksheet.md +4 -4
  80. package/package.json +1 -1
@@ -22,6 +22,10 @@ function isDefinitiveRejection(result) {
22
22
  result.adcpError && !result.adcpError.synthetic && !result.adcpError.code.startsWith("IDEMPOTENCY_") && ["terminal", "correctable"].includes(result.adcpError.recovery ?? "")
23
23
  );
24
24
  }
25
+ function rowMatchesReference(ref, row) {
26
+ if ("account_id" in ref) return row.account_id === ref.account_id;
27
+ return row.brand?.domain === ref.brand.domain && row.operator === ref.operator && (!ref.brand.brand_id || row.brand.brand_id === ref.brand.brand_id) && sameCountrySet(ref.brand.countries, row.brand.countries) && (!ref.operator_unit || row.operator_unit?.id === ref.operator_unit.id) && (!ref.currency || row.currency === ref.currency) && (!ref.timezone || row.timezone === ref.timezone) && (row.sandbox === void 0 || row.sandbox === true === (ref.sandbox === true));
28
+ }
25
29
  class BuyerAccountRegistry {
26
30
  constructor(scope, provision, storage, repair, registryOptions = {}) {
27
31
  this.scope = scope;
@@ -40,6 +44,8 @@ class BuyerAccountRegistry {
40
44
  repair;
41
45
  registryOptions;
42
46
  entries = /* @__PURE__ */ new Map();
47
+ /** Reduction bindings when no storage is configured (never evicted). */
48
+ reductions = /* @__PURE__ */ new Map();
43
49
  pending = /* @__PURE__ */ new Map();
44
50
  writes = Promise.resolve();
45
51
  repairs = /* @__PURE__ */ new Map();
@@ -421,12 +427,13 @@ class BuyerAccountRegistry {
421
427
  return this.enqueue(async () => {
422
428
  if (scope !== this.scope()) return;
423
429
  for (const ref of refs) {
424
- const candidates = rows.filter((value) => {
425
- if (!value || typeof value !== "object") return false;
426
- const row2 = value;
427
- if ("account_id" in ref) return row2.account_id === ref.account_id;
428
- return row2.brand?.domain === ref.brand.domain && row2.operator === ref.operator && (!ref.brand.brand_id || row2.brand.brand_id === ref.brand.brand_id) && sameCountrySet(ref.brand.countries, row2.brand.countries) && (!ref.operator_unit || row2.operator_unit?.id === ref.operator_unit.id) && (!ref.currency || row2.currency === ref.currency) && (!ref.timezone || row2.timezone === ref.timezone) && (row2.sandbox === void 0 || row2.sandbox === true === (ref.sandbox === true));
429
- });
430
+ const isRow = (value) => !!value && typeof value === "object";
431
+ let candidates = rows.filter((value) => isRow(value) && rowMatchesReference(ref, value));
432
+ if (candidates.length === 0 && !("account_id" in ref)) {
433
+ const reduction = (await this.reductionFor(ref))?.account;
434
+ if (scope !== this.scope()) return;
435
+ if (reduction) candidates = rows.filter((value) => isRow(value) && rowMatchesReference(reduction, value));
436
+ }
430
437
  if (candidates.length !== 1) continue;
431
438
  let row = candidates[0];
432
439
  if (row.action === "failed" || typeof row.status !== "string") continue;
@@ -591,6 +598,135 @@ class BuyerAccountRegistry {
591
598
  }
592
599
  }
593
600
  }
601
+ reductionKey(kind, account, scope = this.scope()) {
602
+ return `${scope}:${kind}:${accountReferenceKey(account)}`;
603
+ }
604
+ async readReduction(key) {
605
+ const entry = this.storage ? await this.storage.get(key) : this.reductions.get(key);
606
+ return entry && entry.status === "reduced" ? structuredClone(entry) : void 0;
607
+ }
608
+ /** Insert-if-absent; returns false when another writer already holds the key. */
609
+ async insertReduction(key, entry) {
610
+ const prior = this.storage ? await this.storage.get(key) : this.reductions.get(key);
611
+ if (prior && prior.status === "reduced") return false;
612
+ if (this.storage?.compareAndSet) {
613
+ return this.storage.compareAndSet(key, prior?.revision, { ...entry, revision: (prior?.revision ?? 0) + 1 });
614
+ }
615
+ if (this.storage) await this.storage.set(key, structuredClone(entry));
616
+ else this.reductions.set(key, structuredClone(entry));
617
+ return true;
618
+ }
619
+ async replaceReduction(key, entry) {
620
+ const prior = this.storage ? await this.storage.get(key) : this.reductions.get(key);
621
+ if (this.storage?.compareAndSet) {
622
+ const next = { ...entry, revision: (prior?.revision ?? 0) + 1 };
623
+ if (!await this.storage.compareAndSet(key, prior?.revision, next))
624
+ throw new AccountSetupRequiredError("Account storage revision changed. Reload and reconcile before retrying.");
625
+ } else if (this.storage) await this.storage.set(key, structuredClone(entry));
626
+ else this.reductions.set(key, structuredClone(entry));
627
+ }
628
+ /**
629
+ * Bind reduced account keys to the buyer keys they came from, before a
630
+ * request carrying them is sent to a seller on an older release. Each
631
+ * reduced key serves one buyer key only. A key sent unreduced claims itself
632
+ * (`account` and `reduced` equal), so a plain key and a reduced one can never
633
+ * land on the same seller account in either order.
634
+ *
635
+ * All-or-nothing: every claim is checked, against storage and against the
636
+ * other claims in the same request, before any is written. On a conflict
637
+ * nothing is written and the index and owner of the first conflicting claim
638
+ * are returned. A claim lost to a concurrent writer rolls back the claims
639
+ * this call already wrote.
640
+ */
641
+ async claimReductions(claims) {
642
+ const scope = this.scope();
643
+ let conflict;
644
+ await this.enqueue(async () => {
645
+ const pending = /* @__PURE__ */ new Map();
646
+ const toInsert = [];
647
+ for (const [index, claim] of claims.entries()) {
648
+ const reducedKey = accountReferenceKey(claim.reduced);
649
+ const inRequest = pending.get(reducedKey);
650
+ if (inRequest && accountReferenceKey(inRequest) !== accountReferenceKey(claim.account)) {
651
+ conflict = { index, owner: inRequest };
652
+ return;
653
+ }
654
+ pending.set(reducedKey, claim.account);
655
+ const owner = (await this.readReduction(this.reductionKey("reduced", claim.reduced, scope)))?.reducedFrom;
656
+ if (owner && accountReferenceKey(owner) !== accountReferenceKey(claim.account)) {
657
+ conflict = { index, owner };
658
+ return;
659
+ }
660
+ if (!owner && !inRequest) toInsert.push(index);
661
+ }
662
+ const inserted = [];
663
+ for (const index of toInsert) {
664
+ const claim = claims[index];
665
+ const reverseKey = this.reductionKey("reduced", claim.reduced, scope);
666
+ const ok = await this.insertReduction(reverseKey, {
667
+ account: structuredClone(claim.reduced),
668
+ status: "reduced",
669
+ reducedFrom: structuredClone(claim.account)
670
+ });
671
+ const winner = ok ? void 0 : (await this.readReduction(reverseKey))?.reducedFrom;
672
+ if (!ok && winner && accountReferenceKey(winner) !== accountReferenceKey(claim.account)) {
673
+ for (const done of inserted) {
674
+ const doneClaim = claims[done];
675
+ await this.replaceReduction(this.reductionKey("reduced", doneClaim.reduced, scope), {
676
+ account: structuredClone(doneClaim.reduced),
677
+ status: "released"
678
+ });
679
+ }
680
+ conflict = { index, owner: winner };
681
+ return;
682
+ }
683
+ if (ok) inserted.push(index);
684
+ }
685
+ for (const claim of claims) {
686
+ if (accountReferenceKey(claim.account) === accountReferenceKey(claim.reduced)) continue;
687
+ const forwardKey = this.reductionKey("reduction", claim.account, scope);
688
+ const current = await this.readReduction(forwardKey);
689
+ const reduction = { account: claim.reduced, adcpVersion: claim.adcpVersion };
690
+ if (current?.reduction && isDeepStrictEqual(current.reduction, reduction)) continue;
691
+ await this.replaceReduction(forwardKey, {
692
+ account: structuredClone(claim.account),
693
+ status: "reduced",
694
+ reduction: structuredClone(reduction)
695
+ });
696
+ }
697
+ });
698
+ return conflict;
699
+ }
700
+ /** The buyer key a reduced seller key was claimed for, if any. */
701
+ async reductionOwner(reduced) {
702
+ return (await this.readReduction(this.reductionKey("reduced", reduced)))?.reducedFrom;
703
+ }
704
+ /** The reduced key a buyer key reached an older seller with, if any. */
705
+ async reductionFor(account) {
706
+ return (await this.readReduction(this.reductionKey("reduction", account)))?.reduction;
707
+ }
708
+ /**
709
+ * Forget that `account` reached this seller under a reduced key. Call once
710
+ * the account has moved to its full key: after a `sync_accounts` settings
711
+ * update rekeys `operator_unit` in place, or after opening a new account
712
+ * under the full key when the reduced fields (`currency`, `timezone`,
713
+ * `brand.countries`) cannot change on an existing account. Until then the
714
+ * client keeps addressing the seller account by its reduced key.
715
+ */
716
+ async clearReduction(account) {
717
+ const scope = this.scope();
718
+ await this.enqueue(async () => {
719
+ const forwardKey = this.reductionKey("reduction", account, scope);
720
+ const forward = await this.readReduction(forwardKey);
721
+ if (!forward?.reduction) return;
722
+ const reverseKey = this.reductionKey("reduced", forward.reduction.account, scope);
723
+ const reverse = await this.readReduction(reverseKey);
724
+ if (reverse?.reducedFrom && accountReferenceKey(reverse.reducedFrom) === accountReferenceKey(account)) {
725
+ await this.replaceReduction(reverseKey, { account: reverse.account, status: "released" });
726
+ }
727
+ await this.replaceReduction(forwardKey, { account: forward.account, status: "released" });
728
+ });
729
+ }
594
730
  }
595
731
  export {
596
732
  BuyerAccountRegistry
@@ -45,6 +45,7 @@ var import_media_buy_helpers = require('../server/media-buy-helpers.js');
45
45
  var import_available_actions = require('./available-actions.js');
46
46
  const NON_TERMINAL_ACTION_STATUSES = ["pending_creatives", "pending_start", "active", "paused"];
47
47
  const MODES = ["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"];
48
+ const CANONICAL_TASKS = new Set(Object.values(import_action_metadata.CANONICAL_ACTION_TASKS).flat());
48
49
  const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
49
50
  const finite = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
50
51
  function mediaBuyActionTasks(action) {
@@ -137,7 +138,7 @@ function changeConstraintIssues(action, constraints, currency) {
137
138
  }
138
139
  function slaValid(sla) {
139
140
  return sla === void 0 || record(sla) && Object.entries(sla).every(
140
- ([k, v]) => ["response_max", "completion_max"].includes(k) && typeof v === "string" && /^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$/.test(v)
141
+ ([k, v]) => k === "clock" && v === "elapsed" || ["response_max", "completion_max"].includes(k) && typeof v === "string" && /^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$/.test(v)
141
142
  );
142
143
  }
143
144
  function changeTermIssues(terms, currency) {
@@ -211,7 +212,7 @@ function productTemplateIssues(templates, currency) {
211
212
  currency
212
213
  ).filter((issue) => issue !== "invalid or duplicate action identity")
213
214
  );
214
- if (![...import_action_metadata.CHANGE_TERM_ACTIONS, ...import_action_metadata.LEGACY_AVAILABLE_ACTIONS].includes(template.action))
215
+ if (!Object.hasOwn(import_action_metadata.CANONICAL_ACTION_TASKS, template.action) && !import_action_metadata.LEGACY_AVAILABLE_ACTIONS.includes(template.action))
215
216
  issues.push("invalid product action");
216
217
  if (template.allowed_statuses !== void 0 && (!Array.isArray(template.allowed_statuses) || !template.allowed_statuses.length || new Set(template.allowed_statuses).size !== template.allowed_statuses.length || template.allowed_statuses.some(
217
218
  (status) => ![...NON_TERMINAL_ACTION_STATUSES, "completed", "rejected", "canceled"].includes(status)
@@ -233,8 +234,7 @@ function liveActionIssues(entries) {
233
234
  if (!record(entry) || typeof entry.action !== "string" || !entry.action || typeof entry.mode !== "string" || !entry.mode || seen.has(entry.action))
234
235
  return ["invalid or duplicate live action"];
235
236
  seen.add(entry.action);
236
- if (entry.task !== void 0 && !["control_media_buy", "refine_proposals", "sync_creatives"].includes(String(entry.task)))
237
- return ["invalid live task"];
237
+ if (entry.task !== void 0 && !CANONICAL_TASKS.has(String(entry.task))) return ["invalid live task"];
238
238
  if (!slaValid(entry.sla)) return ["invalid live SLA"];
239
239
  if (entry.change_term_id !== void 0 && (typeof entry.change_term_id !== "string" || !/^[A-Za-z0-9_.:-]+$/.test(entry.change_term_id)))
240
240
  return ["invalid live term identity"];
@@ -9,6 +9,7 @@ import { validActionsForStatus } from "../server/media-buy-helpers.mjs";
9
9
  import { getRollupParent } from "./available-actions.mjs";
10
10
  const NON_TERMINAL_ACTION_STATUSES = ["pending_creatives", "pending_start", "active", "paused"];
11
11
  const MODES = ["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"];
12
+ const CANONICAL_TASKS = new Set(Object.values(CANONICAL_ACTION_TASKS).flat());
12
13
  const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
13
14
  const finite = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
14
15
  function mediaBuyActionTasks(action) {
@@ -101,7 +102,7 @@ function changeConstraintIssues(action, constraints, currency) {
101
102
  }
102
103
  function slaValid(sla) {
103
104
  return sla === void 0 || record(sla) && Object.entries(sla).every(
104
- ([k, v]) => ["response_max", "completion_max"].includes(k) && typeof v === "string" && /^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$/.test(v)
105
+ ([k, v]) => k === "clock" && v === "elapsed" || ["response_max", "completion_max"].includes(k) && typeof v === "string" && /^P(?!$)(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$/.test(v)
105
106
  );
106
107
  }
107
108
  function changeTermIssues(terms, currency) {
@@ -175,7 +176,7 @@ function productTemplateIssues(templates, currency) {
175
176
  currency
176
177
  ).filter((issue) => issue !== "invalid or duplicate action identity")
177
178
  );
178
- if (![...CHANGE_TERM_ACTIONS, ...LEGACY_AVAILABLE_ACTIONS].includes(template.action))
179
+ if (!Object.hasOwn(CANONICAL_ACTION_TASKS, template.action) && !LEGACY_AVAILABLE_ACTIONS.includes(template.action))
179
180
  issues.push("invalid product action");
180
181
  if (template.allowed_statuses !== void 0 && (!Array.isArray(template.allowed_statuses) || !template.allowed_statuses.length || new Set(template.allowed_statuses).size !== template.allowed_statuses.length || template.allowed_statuses.some(
181
182
  (status) => ![...NON_TERMINAL_ACTION_STATUSES, "completed", "rejected", "canceled"].includes(status)
@@ -197,8 +198,7 @@ function liveActionIssues(entries) {
197
198
  if (!record(entry) || typeof entry.action !== "string" || !entry.action || typeof entry.mode !== "string" || !entry.mode || seen.has(entry.action))
198
199
  return ["invalid or duplicate live action"];
199
200
  seen.add(entry.action);
200
- if (entry.task !== void 0 && !["control_media_buy", "refine_proposals", "sync_creatives"].includes(String(entry.task)))
201
- return ["invalid live task"];
201
+ if (entry.task !== void 0 && !CANONICAL_TASKS.has(String(entry.task))) return ["invalid live task"];
202
202
  if (!slaValid(entry.sla)) return ["invalid live SLA"];
203
203
  if (entry.change_term_id !== void 0 && (typeof entry.change_term_id !== "string" || !/^[A-Za-z0-9_.:-]+$/.test(entry.change_term_id)))
204
204
  return ["invalid live term identity"];
@@ -1,7 +1,8 @@
1
1
  import type { CanonicalProductAction, MediaBuyChangeTerm, MediaBuyChangeTermConstraints, MediaBuyStatus } from '../types/core.generated.mjs';
2
2
  import type { MediaBuyActionContext, MediaBuyActionId, MediaBuyActionMode, SLAWindow } from './types.mjs';
3
- /** Explicit task vocabulary; update_media_buy is the established 3.1 default. */
4
- export type MediaBuyTask = 'update_media_buy' | 'control_media_buy' | 'refine_proposals' | 'sync_creatives';
3
+ import type { CANONICAL_ACTION_TASKS } from './action-metadata.generated.mjs';
4
+ /** Canonical wire tasks plus the established 3.1 mutation facade. */
5
+ export type MediaBuyTask = 'update_media_buy' | (typeof CANONICAL_ACTION_TASKS)[keyof typeof CANONICAL_ACTION_TASKS][number];
5
6
  /** Alias of the shared, schema-derived action vocabulary. */
6
7
  export type MediaBuyAction = MediaBuyActionId;
7
8
  export type ProductActionTemplate = Pick<CanonicalProductAction, 'modes' | 'allowed_statuses' | 'sla' | 'constraints' | 'terms_ref'> & {
@@ -1,7 +1,8 @@
1
1
  import type { CanonicalProductAction, MediaBuyChangeTerm, MediaBuyChangeTermConstraints, MediaBuyStatus } from '../types/core.generated';
2
2
  import type { MediaBuyActionContext, MediaBuyActionId, MediaBuyActionMode, SLAWindow } from './types';
3
- /** Explicit task vocabulary; update_media_buy is the established 3.1 default. */
4
- export type MediaBuyTask = 'update_media_buy' | 'control_media_buy' | 'refine_proposals' | 'sync_creatives';
3
+ import type { CANONICAL_ACTION_TASKS } from './action-metadata.generated';
4
+ /** Canonical wire tasks plus the established 3.1 mutation facade. */
5
+ export type MediaBuyTask = 'update_media_buy' | (typeof CANONICAL_ACTION_TASKS)[keyof typeof CANONICAL_ACTION_TASKS][number];
5
6
  /** Alias of the shared, schema-derived action vocabulary. */
6
7
  export type MediaBuyAction = MediaBuyActionId;
7
8
  export type ProductActionTemplate = Pick<CanonicalProductAction, 'modes' | 'allowed_statuses' | 'sla' | 'constraints' | 'terms_ref'> & {
@@ -1,8 +1,9 @@
1
1
  import type { MediaBuyValidAction } from './types.mjs';
2
2
  /**
3
- * Actions that exist only on the structured `available_actions[].action`
4
- * surface (absent from the deprecated flat `valid_actions[]` enum). Their
3
+ * Update-binding actions that exist only on `available_actions[].action`
4
+ * (absent from the deprecated flat `valid_actions[]` enum). Their
5
5
  * field bindings come from `core/media-buy-available-action-id.json`.
6
+ * Actions routed exclusively to other tasks are excluded.
6
7
  * Empty when the schema cache predates that file.
7
8
  */
8
9
  export declare const STRUCTURED_ONLY_MEDIA_BUY_ACTIONS: readonly ["update_media_buy_frequency_cap"];
@@ -1,8 +1,9 @@
1
1
  import type { MediaBuyValidAction } from './types';
2
2
  /**
3
- * Actions that exist only on the structured `available_actions[].action`
4
- * surface (absent from the deprecated flat `valid_actions[]` enum). Their
3
+ * Update-binding actions that exist only on `available_actions[].action`
4
+ * (absent from the deprecated flat `valid_actions[]` enum). Their
5
5
  * field bindings come from `core/media-buy-available-action-id.json`.
6
+ * Actions routed exclusively to other tasks are excluded.
6
7
  * Empty when the schema cache predates that file.
7
8
  */
8
9
  export declare const STRUCTURED_ONLY_MEDIA_BUY_ACTIONS: readonly ["update_media_buy_frequency_cap"];
@@ -3612,7 +3612,7 @@ export interface components {
3612
3612
  } | {
3613
3613
  /** @enum {string} */
3614
3614
  kind: "targeting_restriction";
3615
- restricted_attributes?: ("racial_ethnic_origin" | "political_opinions" | "religious_beliefs" | "trade_union_membership" | "health_data" | "sex_life_sexual_orientation" | "genetic_data" | "biometric_data" | "age" | "familial_status")[];
3615
+ restricted_attributes?: ("racial_ethnic_origin" | "political_opinions" | "religious_beliefs" | "trade_union_membership" | "health_data" | "sex_life_sexual_orientation" | "genetic_data" | "biometric_data" | "age" | "familial_status" | "sex_gender")[];
3616
3616
  description?: string;
3617
3617
  } | {
3618
3618
  /** @enum {string} */
@@ -3612,7 +3612,7 @@ export interface components {
3612
3612
  } | {
3613
3613
  /** @enum {string} */
3614
3614
  kind: "targeting_restriction";
3615
- restricted_attributes?: ("racial_ethnic_origin" | "political_opinions" | "religious_beliefs" | "trade_union_membership" | "health_data" | "sex_life_sexual_orientation" | "genetic_data" | "biometric_data" | "age" | "familial_status")[];
3615
+ restricted_attributes?: ("racial_ethnic_origin" | "political_opinions" | "religious_beliefs" | "trade_union_membership" | "health_data" | "sex_life_sexual_orientation" | "genetic_data" | "biometric_data" | "age" | "familial_status" | "sex_gender")[];
3616
3616
  description?: string;
3617
3617
  } | {
3618
3618
  /** @enum {string} */
@@ -1,3 +1,4 @@
1
+ import { type VersionDrift } from '../adapters/version/index.mjs';
1
2
  /**
2
3
  * Declarative AdCP server builder.
3
4
  *
@@ -1198,6 +1199,17 @@ export type WebhooksConfig = Pick<WebhookEmitterOptions, 'signerKey' | 'signerPr
1198
1199
  /** Observability: receives failures isolated from attempt observers. */
1199
1200
  onAttemptObserverError?: WebhookEmitterOptions['onAttemptObserverError'];
1200
1201
  };
1202
+ /** One request or response conversion between the server's release and a buyer's. */
1203
+ export interface AdcpVersionTranslationEvent {
1204
+ tool: string;
1205
+ direction: 'request' | 'response';
1206
+ /** Release the payload was converted from. */
1207
+ fromVersion: string;
1208
+ /** Release the payload was converted to. */
1209
+ toVersion: string;
1210
+ /** What each conversion step removed or moved. */
1211
+ drifts: VersionDrift[];
1212
+ }
1201
1213
  export interface AdcpServerConfig<TAccount = unknown> {
1202
1214
  /** Experimental 3.3 authorization, invoked before idempotency and handler side effects. */
1203
1215
  identity33?: {
@@ -1258,6 +1270,15 @@ export interface AdcpServerConfig<TAccount = unknown> {
1258
1270
  * releases, and no newer than `adcpVersion`.
1259
1271
  */
1260
1272
  defaultAdcpVersion?: AdcpVersion | (string & {});
1273
+ /**
1274
+ * Called each time the framework converts a request up from, or a
1275
+ * handler's response down to, a buyer's older release. `drifts` lists every
1276
+ * field the conversion removed or moved, with JSON paths, so a seller can
1277
+ * record what an older buyer did not receive. The same events are logged
1278
+ * at `debug` (requests) and `info` (responses). A throwing callback is
1279
+ * logged and ignored.
1280
+ */
1281
+ onVersionTranslation?: (event: AdcpVersionTranslationEvent) => void;
1261
1282
  /**
1262
1283
  * Per-tool inclusive protocol-release availability. This narrows, but does
1263
1284
  * not replace, the server-wide releases declared through capabilities.
@@ -1,3 +1,4 @@
1
+ import { type VersionDrift } from '../adapters/version';
1
2
  /**
2
3
  * Declarative AdCP server builder.
3
4
  *
@@ -1198,6 +1199,17 @@ export type WebhooksConfig = Pick<WebhookEmitterOptions, 'signerKey' | 'signerPr
1198
1199
  /** Observability: receives failures isolated from attempt observers. */
1199
1200
  onAttemptObserverError?: WebhookEmitterOptions['onAttemptObserverError'];
1200
1201
  };
1202
+ /** One request or response conversion between the server's release and a buyer's. */
1203
+ export interface AdcpVersionTranslationEvent {
1204
+ tool: string;
1205
+ direction: 'request' | 'response';
1206
+ /** Release the payload was converted from. */
1207
+ fromVersion: string;
1208
+ /** Release the payload was converted to. */
1209
+ toVersion: string;
1210
+ /** What each conversion step removed or moved. */
1211
+ drifts: VersionDrift[];
1212
+ }
1201
1213
  export interface AdcpServerConfig<TAccount = unknown> {
1202
1214
  /** Experimental 3.3 authorization, invoked before idempotency and handler side effects. */
1203
1215
  identity33?: {
@@ -1258,6 +1270,15 @@ export interface AdcpServerConfig<TAccount = unknown> {
1258
1270
  * releases, and no newer than `adcpVersion`.
1259
1271
  */
1260
1272
  defaultAdcpVersion?: AdcpVersion | (string & {});
1273
+ /**
1274
+ * Called each time the framework converts a request up from, or a
1275
+ * handler's response down to, a buyer's older release. `drifts` lists every
1276
+ * field the conversion removed or moved, with JSON paths, so a seller can
1277
+ * record what an older buyer did not receive. The same events are logged
1278
+ * at `debug` (requests) and `info` (responses). A throwing callback is
1279
+ * logged and ignored.
1280
+ */
1281
+ onVersionTranslation?: (event: AdcpVersionTranslationEvent) => void;
1261
1282
  /**
1262
1283
  * Per-tool inclusive protocol-release availability. This narrows, but does
1263
1284
  * not replace, the server-wide releases declared through capabilities.
@@ -31,6 +31,7 @@ __export(create_adcp_server_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(create_adcp_server_exports);
33
33
  var import_web_bot_auth = require('../signing/web-bot-auth.js');
34
+ var import_version = require('../adapters/version/index.js');
34
35
  var import_schema_loader = require('../validation/schema-loader.js');
35
36
  var import_lifecycle = require('../identity-3.3/lifecycle.js');
36
37
  var import_server = require('../identity-3.3/server.js');
@@ -38,7 +39,7 @@ var import_web_bot_auth2 = require('../signing/web-bot-auth.js');
38
39
  var import_validation = require('../identity-3.3/validation.js');
39
40
  var import_trust = require('../identity-3.3/trust.js');
40
41
  var import_zod = require("zod");
41
- var import_version = require('../version.js');
42
+ var import_version2 = require('../version.js');
42
43
  var import_adcp_version_config = require('../utils/adcp-version-config.js');
43
44
  var import_errors = require('../errors/index.js');
44
45
  var import_schema_loader2 = require('../validation/schema-loader.js');
@@ -79,7 +80,7 @@ var import_middleware = require('../signing/middleware.js');
79
80
  var import_operation_resolution = require('../signing/operation-resolution.js');
80
81
  var import_account_mode = require('./account-mode.js');
81
82
  var import_test_controller_bridge = require('./test-controller-bridge.js');
82
- var import_version2 = require('../version.js');
83
+ var import_version3 = require('../version.js');
83
84
  var import_schemas2 = require('../types/schemas.generated.js');
84
85
  var import_error_codes = require('../types/error-codes.js');
85
86
  function hasIdempotencyClearAll(store) {
@@ -1406,7 +1407,7 @@ function normalizeMediaBuyStatusCollision(response, toolName) {
1406
1407
  }
1407
1408
  function injectVersionIntoResponse(response, servedVersion) {
1408
1409
  if (!servedVersion) return;
1409
- const wireVersion = (0, import_version.toReleasePrecisionVersion)(servedVersion);
1410
+ const wireVersion = (0, import_version2.toReleasePrecisionVersion)(servedVersion);
1410
1411
  const sc = response.structuredContent;
1411
1412
  if (sc && typeof sc === "object" && !("adcp_version" in sc)) {
1412
1413
  const mirrorsStructuredContent = contentTextMirrorsStructuredContent(response, sc);
@@ -1660,11 +1661,11 @@ function getAdvertisedSupportedMajors(capConfig, serverPin) {
1660
1661
  if (Number.isFinite(m)) out.add(m);
1661
1662
  }
1662
1663
  for (const v of capConfig?.supported_versions ?? []) {
1663
- const m = (0, import_version.parseAdcpMajorVersion)(v);
1664
+ const m = (0, import_version2.parseAdcpMajorVersion)(v);
1664
1665
  if (Number.isFinite(m)) out.add(m);
1665
1666
  }
1666
1667
  if (out.size === 0) {
1667
- const pinMajor = (0, import_version.parseAdcpMajorVersion)(serverPin);
1668
+ const pinMajor = (0, import_version2.parseAdcpMajorVersion)(serverPin);
1668
1669
  if (Number.isFinite(pinMajor)) out.add(pinMajor);
1669
1670
  }
1670
1671
  return out;
@@ -1676,7 +1677,7 @@ function buildSupportedVersionsList(capConfig, serverPin) {
1676
1677
  if (capConfig?.major_versions?.length) {
1677
1678
  return capConfig.major_versions.filter((m) => Number.isFinite(m)).map((m) => String(m));
1678
1679
  }
1679
- const pinMajor = (0, import_version.parseAdcpMajorVersion)(serverPin);
1680
+ const pinMajor = (0, import_version2.parseAdcpMajorVersion)(serverPin);
1680
1681
  return Number.isFinite(pinMajor) ? [String(pinMajor)] : [];
1681
1682
  }
1682
1683
  function withImmutableServedAdcpVersion(context, servedAdcpVersion) {
@@ -1695,7 +1696,7 @@ function parseAdcpRelease(value) {
1695
1696
  if (typeof value !== "string") return void 0;
1696
1697
  let wire;
1697
1698
  try {
1698
- wire = (0, import_version.toReleasePrecisionVersion)(value);
1699
+ wire = (0, import_version2.toReleasePrecisionVersion)(value);
1699
1700
  } catch {
1700
1701
  return void 0;
1701
1702
  }
@@ -1842,7 +1843,7 @@ let bundledCompatibleReleases;
1842
1843
  function bundledReleasesForMajors(majors, configured) {
1843
1844
  const acceptedMajors = new Set(majors);
1844
1845
  const releases = /* @__PURE__ */ new Map();
1845
- bundledCompatibleReleases ??= import_version.COMPATIBLE_ADCP_VERSIONS.flatMap((version) => {
1846
+ bundledCompatibleReleases ??= import_version2.COMPATIBLE_ADCP_VERSIONS.flatMap((version) => {
1846
1847
  if (!(0, import_schema_loader2.hasSchemaBundle)(version)) return [];
1847
1848
  const parsed = parseAdcpRelease(version);
1848
1849
  return parsed ? [parsed] : [];
@@ -1993,7 +1994,7 @@ function createAdcpServer(config) {
1993
1994
  responseEnhancer,
1994
1995
  structuredContentTextFallback = "always"
1995
1996
  } = config;
1996
- if (capConfig?.major_versions?.some((major) => major < 3) || capConfig?.supported_versions?.some((version2) => (0, import_version.parseAdcpMajorVersion)(version2) < 3)) {
1997
+ if (capConfig?.major_versions?.some((major) => major < 3) || capConfig?.supported_versions?.some((version2) => (0, import_version2.parseAdcpMajorVersion)(version2) < 3)) {
1997
1998
  throw new import_errors.ConfigurationError(
1998
1999
  "AdCP 2 reached end of life on 2026-08-01. Server capabilities must advertise AdCP 3 only.",
1999
2000
  "capabilities"
@@ -2058,14 +2059,14 @@ function createAdcpServer(config) {
2058
2059
  }
2059
2060
  const credentialPolicyPatterns = credentialPolicy === void 0 || typeof credentialPolicy === "string" ? void 0 : credentialPolicy.patterns;
2060
2061
  const adcpVersion = (0, import_adcp_version_config.resolveAdcpVersion)(
2061
- configuredAdcpVersion ?? (config.identity33 ? "3.3" : config.proposalNegotiation ? import_version2.ADCP_VERSION : void 0)
2062
+ configuredAdcpVersion ?? (config.identity33 ? "3.3" : config.proposalNegotiation ? import_version3.ADCP_VERSION : void 0)
2062
2063
  );
2063
2064
  const toolVersionRanges = parseToolVersionRanges(config.toolVersions);
2064
2065
  const toolAvailableForRelease = (toolName, release) => toolIsAvailableInRelease(toolVersionRanges, toolName, release);
2065
2066
  const movingSupportedVersion = capConfig?.supported_versions?.find(import_adcp_version_config.isMovingAdcpPrereleaseFamilyAlias);
2066
2067
  if (movingSupportedVersion) {
2067
2068
  throw new Error(
2068
- `createAdcpServer: capabilities.supported_versions contains moving prerelease-family alias ${JSON.stringify(movingSupportedVersion)}; pin ${JSON.stringify((0, import_version.toReleasePrecisionVersion)(import_version2.ADCP_VERSION))} instead`
2069
+ `createAdcpServer: capabilities.supported_versions contains moving prerelease-family alias ${JSON.stringify(movingSupportedVersion)}; pin ${JSON.stringify((0, import_version2.toReleasePrecisionVersion)(import_version3.ADCP_VERSION))} instead`
2069
2070
  );
2070
2071
  }
2071
2072
  const configuredDefaultVersion = configuredDefaultAdcpVersion === void 0 ? void 0 : (0, import_adcp_version_config.resolveAdcpVersion)(configuredDefaultAdcpVersion, "defaultAdcpVersion");
@@ -2351,6 +2352,43 @@ function createAdcpServer(config) {
2351
2352
  const selected = selectServedAdcpRelease(params, capConfig, adcpVersion, defaultAdcpVersion);
2352
2353
  return isMcpToolResponse(selected) ? void 0 : selected;
2353
2354
  };
2355
+ const downgradeTaskStatusResult = (toolName, response, servedVersion) => {
2356
+ if (toolName !== "get_task_status" || config.identity33) return response;
2357
+ if ((0, import_version.translationSteps)(adcpVersion, servedVersion).length === 0) return response;
2358
+ const body = response.structuredContent;
2359
+ if (!body || typeof body.task_type !== "string" || !body.result || typeof body.result !== "object") return response;
2360
+ const downgraded = (0, import_version.downgradeResponse)(body.task_type, body.result, {
2361
+ fromVersion: adcpVersion,
2362
+ toVersion: servedVersion
2363
+ });
2364
+ if (downgraded.drifts.length > 0) {
2365
+ reportVersionTranslation({
2366
+ tool: body.task_type,
2367
+ direction: "response",
2368
+ fromVersion: adcpVersion,
2369
+ toVersion: servedVersion,
2370
+ drifts: downgraded.drifts
2371
+ });
2372
+ }
2373
+ if (downgraded.data === body.result) return response;
2374
+ const mirrors = contentTextMirrorsStructuredContent(response, body);
2375
+ const next = cloneFormattedResponse(response);
2376
+ const nextBody = { ...next.structuredContent, result: downgraded.data };
2377
+ next.structuredContent = nextBody;
2378
+ syncContentJsonText(next, nextBody, mirrors);
2379
+ return next;
2380
+ };
2381
+ const reportVersionTranslation = (event) => {
2382
+ if (!config.onVersionTranslation) return;
2383
+ try {
2384
+ config.onVersionTranslation(event);
2385
+ } catch (err) {
2386
+ logger.warn("onVersionTranslation callback threw", {
2387
+ tool: event.tool,
2388
+ error: err instanceof Error ? err.message : String(err)
2389
+ });
2390
+ }
2391
+ };
2354
2392
  const releaseDefinesTool = (toolName, release) => {
2355
2393
  if (toolName === "refine_proposals") return true;
2356
2394
  try {
@@ -2367,6 +2405,7 @@ function createAdcpServer(config) {
2367
2405
  sanitizeAdcpErrorEnvelope(response);
2368
2406
  enrichErrorTwoLayer(response, toolName, (0, import_error_arm_tools.getToolsWithErrorArm)(release.validationVersion));
2369
2407
  if (!isErrorResponse(response)) {
2408
+ response = downgradeTaskStatusResult(toolName, response, release.validationVersion);
2370
2409
  normalizeMediaBuyStatusCollision(response, toolName);
2371
2410
  injectEnvelopeStatusIntoResponse(response, toolName);
2372
2411
  const validationError = protocolTaskResponseValidationError(toolName, response, params);
@@ -2726,6 +2765,7 @@ function createAdcpServer(config) {
2726
2765
  requestRelease = releaseSelection;
2727
2766
  }
2728
2767
  const requestErrorArms = (0, import_error_arm_tools.getToolsWithErrorArm)(requestRelease.validationVersion);
2768
+ const translatesRelease = !config.identity33 && toolName !== "get_adcp_capabilities" && (0, import_version.translationSteps)(adcpVersion, requestRelease.validationVersion).length > 0;
2729
2769
  const ctx = withImmutableServedAdcpVersion(
2730
2770
  {
2731
2771
  store: stateStore,
@@ -2868,7 +2908,7 @@ function createAdcpServer(config) {
2868
2908
  const reqAdcpMajorRaw = params.adcp_major_version;
2869
2909
  const reqAdcpMajor = typeof reqAdcpMajorRaw === "number" ? reqAdcpMajorRaw : typeof reqAdcpMajorRaw === "string" ? Number.parseInt(reqAdcpMajorRaw, 10) : void 0;
2870
2910
  if (typeof reqAdcpVersion === "string" && reqAdcpMajor !== void 0 && Number.isFinite(reqAdcpMajor)) {
2871
- const stringMajor = (0, import_version.parseAdcpMajorVersion)(reqAdcpVersion);
2911
+ const stringMajor = (0, import_version2.parseAdcpMajorVersion)(reqAdcpVersion);
2872
2912
  if (Number.isFinite(stringMajor) && stringMajor !== reqAdcpMajor) {
2873
2913
  return finalize(
2874
2914
  (0, import_errors2.adcpError)("VERSION_UNSUPPORTED", {
@@ -2878,7 +2918,7 @@ function createAdcpServer(config) {
2878
2918
  );
2879
2919
  }
2880
2920
  }
2881
- const effectiveReqMajor = reqAdcpMajor !== void 0 && Number.isFinite(reqAdcpMajor) ? reqAdcpMajor : typeof reqAdcpVersion === "string" ? (0, import_version.parseAdcpMajorVersion)(reqAdcpVersion) : void 0;
2921
+ const effectiveReqMajor = reqAdcpMajor !== void 0 && Number.isFinite(reqAdcpMajor) ? reqAdcpMajor : typeof reqAdcpVersion === "string" ? (0, import_version2.parseAdcpMajorVersion)(reqAdcpVersion) : void 0;
2882
2922
  if (effectiveReqMajor !== void 0 && Number.isFinite(effectiveReqMajor)) {
2883
2923
  const supportedMajors = getAdvertisedSupportedMajors(capConfig, adcpVersion);
2884
2924
  if (!supportedMajors.has(effectiveReqMajor)) {
@@ -3447,7 +3487,24 @@ function createAdcpServer(config) {
3447
3487
  (_entry, index) => !notificationFailureRows.has(index)
3448
3488
  )
3449
3489
  };
3450
- const result = notificationFailureRows.size > 0 && handlerParams.accounts.length === 0 ? { accounts: [], ...params.dry_run === true && { dry_run: true } } : await handler(handlerParams, ctx);
3490
+ const upgraded = translatesRelease ? (0, import_version.upgradeRequest)(toolName, handlerParams, {
3491
+ fromVersion: requestRelease.validationVersion,
3492
+ toVersion: adcpVersion
3493
+ }) : void 0;
3494
+ if (upgraded && upgraded.drifts.length > 0) {
3495
+ logger.debug(`Converted ${toolName} request up to AdCP ${adcpVersion}`, {
3496
+ tool: toolName,
3497
+ drifts: upgraded.drifts
3498
+ });
3499
+ reportVersionTranslation({
3500
+ tool: toolName,
3501
+ direction: "request",
3502
+ fromVersion: requestRelease.validationVersion,
3503
+ toVersion: adcpVersion,
3504
+ drifts: upgraded.drifts
3505
+ });
3506
+ }
3507
+ const result = notificationFailureRows.size > 0 && handlerParams.accounts.length === 0 ? { accounts: [], ...params.dry_run === true && { dry_run: true } } : await handler(upgraded ? upgraded.params : handlerParams, ctx);
3451
3508
  mutationHandlerCompleted = true;
3452
3509
  let formatted;
3453
3510
  if (isFormattedResponse(result)) {
@@ -3915,6 +3972,31 @@ function createAdcpServer(config) {
3915
3972
  injectEnvelopeStatusIntoResponse(formatted, toolName);
3916
3973
  }
3917
3974
  }
3975
+ if (translatesRelease && !isErrorResponse(formatted) && formatted.structuredContent) {
3976
+ const downgraded = (0, import_version.downgradeResponse)(toolName, formatted.structuredContent, {
3977
+ fromVersion: adcpVersion,
3978
+ toVersion: requestRelease.validationVersion
3979
+ });
3980
+ if (downgraded.data !== formatted.structuredContent) {
3981
+ const mirrors = contentTextMirrorsStructuredContent(formatted, formatted.structuredContent);
3982
+ formatted = cloneFormattedResponse(formatted);
3983
+ formatted.structuredContent = downgraded.data;
3984
+ syncContentJsonText(formatted, downgraded.data, mirrors);
3985
+ }
3986
+ if (downgraded.drifts.length > 0) {
3987
+ logger.info(`Converted ${toolName} response down to AdCP ${requestRelease.validationVersion}`, {
3988
+ tool: toolName,
3989
+ drifts: downgraded.drifts
3990
+ });
3991
+ reportVersionTranslation({
3992
+ tool: toolName,
3993
+ direction: "response",
3994
+ fromVersion: adcpVersion,
3995
+ toVersion: requestRelease.validationVersion,
3996
+ drifts: downgraded.drifts
3997
+ });
3998
+ }
3999
+ }
3918
4000
  if (responseValidationMode !== "off" && !isErrorResponse(formatted)) {
3919
4001
  const payload = formatted.structuredContent;
3920
4002
  const outcome = validateFrameworkPayload(
@@ -4630,7 +4712,7 @@ function createAdcpServer(config) {
4630
4712
  "measurement"
4631
4713
  ];
4632
4714
  }
4633
- capabilitiesData.library_version = `@adcp/client@${import_version2.LIBRARY_VERSION}`;
4715
+ capabilitiesData.library_version = `@adcp/client@${import_version3.LIBRARY_VERSION}`;
4634
4716
  async function authorizeAuxiliaryIdentityTool(toolName, params, extra) {
4635
4717
  const failure = (0, import_web_bot_auth2.getWebBotAuthAuthorizationFailure)(extra?.authInfo?.extra);
4636
4718
  if (failure) return (0, import_web_bot_auth2.webBotAuthToolFailure)(failure, servedAdcpVersion);