@adcp/sdk 6.1.0 → 6.2.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 (117) hide show
  1. package/dist/lib/adapters/legacy/v2-5/create_media_buy.d.ts +4 -0
  2. package/dist/lib/adapters/legacy/v2-5/create_media_buy.d.ts.map +1 -0
  3. package/dist/lib/adapters/legacy/v2-5/create_media_buy.js +10 -0
  4. package/dist/lib/adapters/legacy/v2-5/create_media_buy.js.map +1 -0
  5. package/dist/lib/adapters/legacy/v2-5/get_products.d.ts +9 -0
  6. package/dist/lib/adapters/legacy/v2-5/get_products.d.ts.map +1 -0
  7. package/dist/lib/adapters/legacy/v2-5/get_products.js +15 -0
  8. package/dist/lib/adapters/legacy/v2-5/get_products.js.map +1 -0
  9. package/dist/lib/adapters/legacy/v2-5/index.d.ts +35 -0
  10. package/dist/lib/adapters/legacy/v2-5/index.d.ts.map +1 -0
  11. package/dist/lib/adapters/legacy/v2-5/index.js +56 -0
  12. package/dist/lib/adapters/legacy/v2-5/index.js.map +1 -0
  13. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.d.ts +9 -0
  14. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.d.ts.map +1 -0
  15. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.js +15 -0
  16. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.js.map +1 -0
  17. package/dist/lib/adapters/legacy/v2-5/preview_creative.d.ts +4 -0
  18. package/dist/lib/adapters/legacy/v2-5/preview_creative.d.ts.map +1 -0
  19. package/dist/lib/adapters/legacy/v2-5/preview_creative.js +10 -0
  20. package/dist/lib/adapters/legacy/v2-5/preview_creative.js.map +1 -0
  21. package/dist/lib/adapters/legacy/v2-5/sync_creatives.d.ts +11 -0
  22. package/dist/lib/adapters/legacy/v2-5/sync_creatives.d.ts.map +1 -0
  23. package/dist/lib/adapters/legacy/v2-5/sync_creatives.js +16 -0
  24. package/dist/lib/adapters/legacy/v2-5/sync_creatives.js.map +1 -0
  25. package/dist/lib/adapters/legacy/v2-5/types.d.ts +40 -0
  26. package/dist/lib/adapters/legacy/v2-5/types.d.ts.map +1 -0
  27. package/dist/lib/adapters/legacy/v2-5/types.js +25 -0
  28. package/dist/lib/adapters/legacy/v2-5/types.js.map +1 -0
  29. package/dist/lib/adapters/legacy/v2-5/update_media_buy.d.ts +4 -0
  30. package/dist/lib/adapters/legacy/v2-5/update_media_buy.d.ts.map +1 -0
  31. package/dist/lib/adapters/legacy/v2-5/update_media_buy.js +12 -0
  32. package/dist/lib/adapters/legacy/v2-5/update_media_buy.js.map +1 -0
  33. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  34. package/dist/lib/core/ConversationTypes.d.ts +7 -0
  35. package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
  36. package/dist/lib/core/SingleAgentClient.d.ts +9 -14
  37. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  38. package/dist/lib/core/SingleAgentClient.js +96 -40
  39. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  40. package/dist/lib/core/TaskExecutor.d.ts +5 -0
  41. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  42. package/dist/lib/core/TaskExecutor.js +12 -1
  43. package/dist/lib/core/TaskExecutor.js.map +1 -1
  44. package/dist/lib/errors/index.d.ts +30 -0
  45. package/dist/lib/errors/index.d.ts.map +1 -1
  46. package/dist/lib/errors/index.js +36 -1
  47. package/dist/lib/errors/index.js.map +1 -1
  48. package/dist/lib/index.d.ts +4 -2
  49. package/dist/lib/index.d.ts.map +1 -1
  50. package/dist/lib/index.js +12 -8
  51. package/dist/lib/index.js.map +1 -1
  52. package/dist/lib/protocols/a2a.d.ts.map +1 -1
  53. package/dist/lib/protocols/a2a.js +5 -1
  54. package/dist/lib/protocols/a2a.js.map +1 -1
  55. package/dist/lib/protocols/index.d.ts +53 -3
  56. package/dist/lib/protocols/index.d.ts.map +1 -1
  57. package/dist/lib/protocols/index.js +19 -8
  58. package/dist/lib/protocols/index.js.map +1 -1
  59. package/dist/lib/protocols/mcp.d.ts.map +1 -1
  60. package/dist/lib/protocols/mcp.js +13 -5
  61. package/dist/lib/protocols/mcp.js.map +1 -1
  62. package/dist/lib/protocols/responseSizeLimit.d.ts +25 -0
  63. package/dist/lib/protocols/responseSizeLimit.d.ts.map +1 -0
  64. package/dist/lib/protocols/responseSizeLimit.js +141 -0
  65. package/dist/lib/protocols/responseSizeLimit.js.map +1 -0
  66. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  67. package/dist/lib/server/decisioning/async-outcome.d.ts +16 -10
  68. package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -1
  69. package/dist/lib/server/decisioning/async-outcome.js +15 -56
  70. package/dist/lib/server/decisioning/async-outcome.js.map +1 -1
  71. package/dist/lib/server/decisioning/errors-typed.d.ts +10 -4
  72. package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -1
  73. package/dist/lib/server/decisioning/errors-typed.js +13 -29
  74. package/dist/lib/server/decisioning/errors-typed.js.map +1 -1
  75. package/dist/lib/server/decisioning/helpers.d.ts.map +1 -1
  76. package/dist/lib/server/decisioning/helpers.js +0 -2
  77. package/dist/lib/server/decisioning/helpers.js.map +1 -1
  78. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -1
  79. package/dist/lib/server/decisioning/manifest-helpers.js +0 -2
  80. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -1
  81. package/dist/lib/server/decisioning/runtime/from-platform.js +0 -9
  82. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  83. package/dist/lib/server/decisioning/start-time.d.ts.map +1 -1
  84. package/dist/lib/server/decisioning/start-time.js +0 -2
  85. package/dist/lib/server/decisioning/start-time.js.map +1 -1
  86. package/dist/lib/types/error-codes.d.ts +196 -9
  87. package/dist/lib/types/error-codes.d.ts.map +1 -1
  88. package/dist/lib/types/error-codes.js +104 -26
  89. package/dist/lib/types/error-codes.js.map +1 -1
  90. package/dist/lib/types/v2-5/index.d.ts +2 -0
  91. package/dist/lib/types/v2-5/index.d.ts.map +1 -0
  92. package/dist/lib/types/v2-5/index.js +30 -0
  93. package/dist/lib/types/v2-5/index.js.map +1 -0
  94. package/dist/lib/types/v2-5/tools.generated.d.ts +3507 -0
  95. package/dist/lib/types/v2-5/tools.generated.d.ts.map +1 -0
  96. package/dist/lib/types/v2-5/tools.generated.js +6 -0
  97. package/dist/lib/types/v2-5/tools.generated.js.map +1 -0
  98. package/dist/lib/utils/buyer-retry-policy.d.ts +136 -0
  99. package/dist/lib/utils/buyer-retry-policy.d.ts.map +1 -0
  100. package/dist/lib/utils/buyer-retry-policy.js +247 -0
  101. package/dist/lib/utils/buyer-retry-policy.js.map +1 -0
  102. package/dist/lib/utils/sync-creatives-adapter.d.ts +18 -8
  103. package/dist/lib/utils/sync-creatives-adapter.d.ts.map +1 -1
  104. package/dist/lib/utils/sync-creatives-adapter.js +70 -17
  105. package/dist/lib/utils/sync-creatives-adapter.js.map +1 -1
  106. package/dist/lib/validation/client-hooks.d.ts +13 -8
  107. package/dist/lib/validation/client-hooks.d.ts.map +1 -1
  108. package/dist/lib/validation/client-hooks.js +12 -12
  109. package/dist/lib/validation/client-hooks.js.map +1 -1
  110. package/dist/lib/version.d.ts +3 -3
  111. package/dist/lib/version.js +3 -3
  112. package/docs/guides/BUILD-AN-AGENT.md +2 -0
  113. package/docs/llms.txt +39 -22
  114. package/package.json +11 -1
  115. package/skills/build-seller-agent/SKILL.md +38 -5
  116. package/skills/build-seller-agent/specialisms/sales-guaranteed.md +4 -3
  117. package/skills/call-adcp-agent.previous/SKILL.md +83 -4
@@ -2,44 +2,97 @@
2
2
  /**
3
3
  * Sync Creatives Adapter
4
4
  *
5
- * Handles conversion between v2 and v3 sync_creatives requests.
6
- * The library exposes only the v3 API to clients and internally adapts
7
- * requests for v2 servers.
5
+ * Adapts v3 `sync_creatives` request payloads for v2.5 servers. The public
6
+ * surface (`adaptSyncCreativesRequestForV2`) is unchanged; all conversions
7
+ * are transparent to callers.
8
8
  *
9
- * Key v3 → v2 differences:
10
- * - `account` field is required in v3 but absent in v2 — stripped on send
11
- * - `catalogs` array on each creative is v3-only — stripped on send
12
- * - `status` enum ('approved' | 'rejected') replaces v2 `approved` boolean
9
+ * v3 → v2 field mappings applied here:
10
+ * - `account` / `adcp_major_version` stripped (v3-only top-level fields)
11
+ * - `catalogs` per creative stripped (v3-only)
12
+ * - `status` enum ('approved' | 'rejected') `approved` boolean
13
+ * - `assets` as a role-keyed manifest ({ video: { asset_type, url, … } })
14
+ * → flattened to a single v2 asset payload (`oneOf` discriminated by
15
+ * `asset_type`). The primary (first) role is forwarded; remaining roles
16
+ * are dropped with a console.warn naming the discarded roles. To preserve
17
+ * all roles, connect to a v3 server.
18
+ * - `assets` already flat (has `asset_type` at top level) — passed through
19
+ * unchanged.
20
+ * - No `assets` field — omitted.
21
+ *
22
+ * @internal Not part of the public @adcp/sdk API surface.
13
23
  */
14
24
  Object.defineProperty(exports, "__esModule", { value: true });
15
25
  exports.adaptSyncCreativesRequestForV2 = adaptSyncCreativesRequestForV2;
16
26
  /**
17
- * Adapt a single creative asset for a v2 server.
18
- * Strips v3-only fields and converts `status` enum `approved` boolean.
27
+ * Returns true for a v3 role-keyed manifest ({ role: AssetInstance, … }).
28
+ * Returns false for a flat v2 asset payload (has top-level `asset_type`),
29
+ * for an empty object, or for any non-plain-object value.
30
+ */
31
+ function isManifestShape(assets) {
32
+ if (typeof assets !== 'object' || assets === null || Array.isArray(assets))
33
+ return false;
34
+ if ('asset_type' in assets)
35
+ return false; // already a flat single-asset payload
36
+ const values = Object.values(assets);
37
+ // Empty object is not a manifest — treat as pass-through
38
+ return values.some(v => typeof v === 'object' && v !== null && 'asset_type' in v);
39
+ }
40
+ /**
41
+ * Adapt a single creative for a v2 server.
42
+ * Strips v3-only fields, converts `status` enum → `approved` boolean,
43
+ * and flattens a manifest-shaped `assets` to a single v2 asset payload.
19
44
  */
20
- function adaptCreativeAssetForV2(creative) {
21
- const { catalogs, status, ...rest } = creative;
22
- const adapted = { ...rest };
45
+ function adaptCreativeForV2(creative) {
46
+ const { catalogs, status, assets, ...rest } = creative;
47
+ const base = { ...rest };
23
48
  // Convert v3 status enum → v2 approved boolean
24
49
  if (status === 'approved') {
25
- adapted.approved = true;
50
+ base.approved = true;
26
51
  }
27
52
  else if (status === 'rejected') {
28
- adapted.approved = false;
53
+ base.approved = false;
29
54
  }
30
55
  // Any other status value (or absent) — omit approved entirely
31
- return adapted;
56
+ if (assets === undefined) {
57
+ // v3 schema marks assets as required, but guard defensively for any
58
+ // typed as any that arrives without the field
59
+ return base;
60
+ }
61
+ if (!isManifestShape(assets)) {
62
+ // Already a flat asset payload (has asset_type at top level), an empty
63
+ // object, or an unrecognised shape — pass through verbatim and let the
64
+ // server's response validation surface any mismatch
65
+ return { ...base, assets };
66
+ }
67
+ // Manifest: { role: AssetInstance, … }
68
+ // isManifestShape guarantees at least one entry with asset_type, but the first
69
+ // entry may be a non-asset role (e.g. metadata). Pick the first entry whose
70
+ // value actually carries asset_type so the forwarded payload is always valid.
71
+ const entries = Object.entries(assets);
72
+ const primary = entries.find(([, v]) => typeof v === 'object' && v !== null && 'asset_type' in v);
73
+ if (!primary) {
74
+ // All roles are malformed — pass through verbatim, let the server reject
75
+ return { ...base, assets };
76
+ }
77
+ const [primaryRole, primaryAsset] = primary;
78
+ const assetRoles = entries.map(([r]) => r);
79
+ if (assetRoles.length > 1) {
80
+ console.warn(`[AdCP] sync_creatives: creative "${base.creative_id}" has multiple asset roles ` +
81
+ `(${assetRoles.join(', ')}); only "${primaryRole}" will be sent to v2 server. ` +
82
+ `Upgrade to a v3 server to preserve all roles.`);
83
+ }
84
+ return { ...base, assets: primaryAsset };
32
85
  }
33
86
  /**
34
87
  * Adapt a sync_creatives request for a v2 server.
35
- * Strips v3-only top-level fields and adapts each creative asset.
88
+ * Strips v3-only top-level fields and adapts each creative.
36
89
  */
37
90
  function adaptSyncCreativesRequestForV2(request) {
38
91
  const { account, adcp_major_version, ...rest } = request;
39
92
  return {
40
93
  ...rest,
41
94
  ...(rest.creatives && {
42
- creatives: rest.creatives.map(adaptCreativeAssetForV2),
95
+ creatives: rest.creatives.map(adaptCreativeForV2),
43
96
  }),
44
97
  };
45
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sync-creatives-adapter.js","sourceRoot":"","sources":["../../../src/lib/utils/sync-creatives-adapter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AA0BH,wEASC;AAjCD;;;GAGG;AACH,SAAS,uBAAuB,CAAC,QAAa;IAC5C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE/C,MAAM,OAAO,GAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;IAEjC,+CAA+C;IAC/C,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1B,CAAC;SAAM,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC3B,CAAC;IACD,8DAA8D;IAE9D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAgB,8BAA8B,CAAC,OAAY;IACzD,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzD,OAAO;QACL,GAAG,IAAI;QACP,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI;YACpB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,uBAAuB,CAAC;SACvD,CAAC;KACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sync-creatives-adapter.js","sourceRoot":"","sources":["../../../src/lib/utils/sync-creatives-adapter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;AA4EH,wEASC;AAnFD;;;;GAIG;AACH,SAAS,eAAe,CAAC,MAAe;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACzF,IAAI,YAAY,IAAI,MAAM;QAAE,OAAO,KAAK,CAAC,CAAC,sCAAsC;IAChF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC;IAC/C,yDAAyD;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,QAAa;IACvC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IAEvD,MAAM,IAAI,GAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;IAE9B,+CAA+C;IAC/C,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;SAAM,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,8DAA8D;IAE9D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,oEAAoE;QACpE,8CAA8C;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,uEAAuE;QACvE,uEAAuE;QACvE,oDAAoD;QACpD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,uCAAuC;IACvC,+EAA+E;IAC/E,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC;IAElG,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,yEAAyE;QACzE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,OAAO,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CACV,oCAAoC,IAAI,CAAC,WAAW,6BAA6B;YAC/E,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,WAAW,+BAA+B;YAC/E,+CAA+C,CAClD,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,SAAgB,8BAA8B,CAAC,OAAY;IACzD,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzD,OAAO;QACL,GAAG,IAAI;QACP,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI;YACpB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC;SAClD,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -6,21 +6,26 @@
6
6
  import { type ValidationOutcome } from './schema-validator';
7
7
  export type ValidationMode = 'strict' | 'warn' | 'off';
8
8
  export interface ValidationHookConfig {
9
- /** Validate outgoing requests. Default: strict in dev/test, warn in prod. */
9
+ /** Validate outgoing requests. Default: `warn` everywhere. */
10
10
  requests?: ValidationMode;
11
- /** Validate incoming responses. Default: strict in dev/test, warn in prod. */
11
+ /** Validate incoming responses. Default: `warn` everywhere. */
12
12
  responses?: ValidationMode;
13
13
  }
14
14
  /**
15
15
  * Resolve the effective request/response modes.
16
16
  *
17
- * Response default: strict in dev/test, warn in prod (preserves the
18
- * existing `strictSchemaValidation` contract).
17
+ * Both default to `warn` everywhere buyers get drift surfaced through
18
+ * `result.debug_logs` without losing the response payload to a strict
19
+ * rejection. v2.5 sellers in particular ship enough legacy drift
20
+ * (envelope nulls, optional-required fields, enum mismatches) that
21
+ * strict-by-default leaves callers staring at "0 products" with no
22
+ * useful signal. Buyers and harnesses that want hard-stop behavior
23
+ * (conformance suites, third-party validators) opt into strict via
24
+ * `validation: { responses: 'strict' }` — explicit config always wins.
19
25
  *
20
- * Request default: `warn` everywhere. Strict-by-default would break
21
- * existing callers that intentionally send partial payloads (error-path
22
- * tests, exploratory probes) storyboards and third-party clients that
23
- * want hard-stop enforcement should set `requests: 'strict'` explicitly.
26
+ * This is the **client-side** default. `createAdcpServer` keeps its
27
+ * stricter dev/test handler-validation contract that catches our own
28
+ * handler bugs, which strict mode is genuinely good at.
24
29
  */
25
30
  export declare function resolveValidationModes(config?: ValidationHookConfig): Required<ValidationHookConfig>;
26
31
  export interface DebugLogEntry {
@@ -1 +1 @@
1
- {"version":3,"file":"client-hooks.d.ts","sourceRoot":"","sources":["../../../src/lib/validation/client-hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAmD,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG7G,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,8EAA8E;IAC9E,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAKpG;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAaD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,aAAa,EAAE,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,GAAG,SAAS,CAS/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,aAAa,EAAE,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAOnB"}
1
+ {"version":3,"file":"client-hooks.d.ts","sourceRoot":"","sources":["../../../src/lib/validation/client-hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAmD,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG7G,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,+DAA+D;IAC/D,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAKpG;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAaD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,aAAa,EAAE,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,GAAG,SAAS,CAS/B;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,aAAa,EAAE,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAOnB"}
@@ -10,26 +10,26 @@ exports.validateOutgoingRequest = validateOutgoingRequest;
10
10
  exports.validateIncomingResponse = validateIncomingResponse;
11
11
  const schema_validator_1 = require("./schema-validator");
12
12
  const schema_errors_1 = require("./schema-errors");
13
- function defaultResponseMode() {
14
- // Responses have been validated strictly by default since the SDK shipped
15
- // Zod validation; preserve that in dev/test and soften to warn in prod.
16
- return process.env.NODE_ENV === 'production' ? 'warn' : 'strict';
17
- }
18
13
  /**
19
14
  * Resolve the effective request/response modes.
20
15
  *
21
- * Response default: strict in dev/test, warn in prod (preserves the
22
- * existing `strictSchemaValidation` contract).
16
+ * Both default to `warn` everywhere buyers get drift surfaced through
17
+ * `result.debug_logs` without losing the response payload to a strict
18
+ * rejection. v2.5 sellers in particular ship enough legacy drift
19
+ * (envelope nulls, optional-required fields, enum mismatches) that
20
+ * strict-by-default leaves callers staring at "0 products" with no
21
+ * useful signal. Buyers and harnesses that want hard-stop behavior
22
+ * (conformance suites, third-party validators) opt into strict via
23
+ * `validation: { responses: 'strict' }` — explicit config always wins.
23
24
  *
24
- * Request default: `warn` everywhere. Strict-by-default would break
25
- * existing callers that intentionally send partial payloads (error-path
26
- * tests, exploratory probes) storyboards and third-party clients that
27
- * want hard-stop enforcement should set `requests: 'strict'` explicitly.
25
+ * This is the **client-side** default. `createAdcpServer` keeps its
26
+ * stricter dev/test handler-validation contract that catches our own
27
+ * handler bugs, which strict mode is genuinely good at.
28
28
  */
29
29
  function resolveValidationModes(config) {
30
30
  return {
31
31
  requests: config?.requests ?? 'warn',
32
- responses: config?.responses ?? defaultResponseMode(),
32
+ responses: config?.responses ?? 'warn',
33
33
  };
34
34
  }
35
35
  function logWarning(debugLogs, taskName, outcome) {
@@ -1 +1 @@
1
- {"version":3,"file":"client-hooks.js","sourceRoot":"","sources":["../../../src/lib/validation/client-hooks.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AA+BH,wDAKC;AA8BD,0DAeC;AAWD,4DAaC;AAvGD,yDAA6G;AAC7G,mDAAuD;AAWvD,SAAS,mBAAmB;IAC1B,0EAA0E;IAC1E,wEAAwE;IACxE,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnE,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,sBAAsB,CAAC,MAA6B;IAClE,OAAO;QACL,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,MAAM;QACpC,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,mBAAmB,EAAE;KACtD,CAAC;AACJ,CAAC;AASD,SAAS,UAAU,CAAC,SAAsC,EAAE,QAAgB,EAAE,OAA0B;IACtG,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,iCAAiC,QAAQ,KAAK,IAAA,+BAAY,EAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACrF,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,aAAa,EAAE,OAAO,CAAC,OAAO;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,uBAAuB,CACrC,QAAgB,EAChB,MAAe,EACf,IAAoB,EACpB,SAA2B,EAC3B,OAAgB;IAEhB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,OAAO,GAAG,IAAA,kCAAe,EAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAClC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,IAAA,oCAAoB,EAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CACtC,QAAgB,EAChB,IAAa,EACb,IAAoB,EACpB,SAA2B,EAC3B,OAAgB;IAEhB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACxE,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACtC,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"client-hooks.js","sourceRoot":"","sources":["../../../src/lib/validation/client-hooks.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AA8BH,wDAKC;AA8BD,0DAeC;AAWD,4DAaC;AAtGD,yDAA6G;AAC7G,mDAAuD;AAWvD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,sBAAsB,CAAC,MAA6B;IAClE,OAAO;QACL,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,MAAM;QACpC,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,MAAM;KACvC,CAAC;AACJ,CAAC;AASD,SAAS,UAAU,CAAC,SAAsC,EAAE,QAAgB,EAAE,OAA0B;IACtG,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,iCAAiC,QAAQ,KAAK,IAAA,+BAAY,EAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACrF,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,aAAa,EAAE,OAAO,CAAC,OAAO;QAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,uBAAuB,CACrC,QAAgB,EAChB,MAAe,EACf,IAAoB,EACpB,SAA2B,EAC3B,OAAgB;IAEhB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,OAAO,GAAG,IAAA,kCAAe,EAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAClC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,IAAA,oCAAoB,EAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CACtC,QAAgB,EAChB,IAAa,EACb,IAAoB,EACpB,SAA2B,EAC3B,OAAgB;IAEhB,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACxE,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACtC,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "6.1.0";
4
+ export declare const LIBRARY_VERSION = "6.2.0";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -29,10 +29,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
29
29
  * Full version information
30
30
  */
31
31
  export declare const VERSION_INFO: {
32
- readonly library: "6.1.0";
32
+ readonly library: "6.2.0";
33
33
  readonly adcp: "3.0.1";
34
34
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0-beta.1", "3.0.0-beta.3", "3.0.0", "3.0.1"];
35
- readonly generatedAt: "2026-05-01T01:08:59.054Z";
35
+ readonly generatedAt: "2026-05-01T11:45:44.010Z";
36
36
  };
37
37
  /**
38
38
  * Get the AdCP specification version this library is built for
@@ -11,7 +11,7 @@ exports.parseAdcpMajorVersion = parseAdcpMajorVersion;
11
11
  /**
12
12
  * AdCP SDK library version
13
13
  */
14
- exports.LIBRARY_VERSION = '6.1.0';
14
+ exports.LIBRARY_VERSION = '6.2.0';
15
15
  /**
16
16
  * AdCP specification version this library is built for
17
17
  */
@@ -38,10 +38,10 @@ exports.COMPATIBLE_ADCP_VERSIONS = [
38
38
  * Full version information
39
39
  */
40
40
  exports.VERSION_INFO = {
41
- library: '6.1.0',
41
+ library: '6.2.0',
42
42
  adcp: '3.0.1',
43
43
  compatibleVersions: exports.COMPATIBLE_ADCP_VERSIONS,
44
- generatedAt: '2026-05-01T01:08:59.054Z',
44
+ generatedAt: '2026-05-01T11:45:44.010Z',
45
45
  };
46
46
  /**
47
47
  * Get the AdCP specification version this library is built for
@@ -522,6 +522,8 @@ return adcpError('SERVICE_UNAVAILABLE', 'Try again in 30 seconds');
522
522
  return adcpError('ACCOUNT_SUSPENDED', 'Contact support');
523
523
  ```
524
524
 
525
+ > **Heads-up for buyer-agent authors**: four codes are spec-`correctable` but operator-semantically human-escalate — don't auto-mutate-and-retry on `POLICY_VIOLATION`, `COMPLIANCE_UNSATISFIED`, `GOVERNANCE_DENIED`, or `AUTH_REQUIRED`. Surface to the user. (`AUTH_REQUIRED` conflates missing-creds with revoked-creds; until [adcontextprotocol/adcp#3730](https://github.com/adcontextprotocol/adcp/issues/3730) splits these, treat as escalate.) See `skills/call-adcp-agent/SKILL.md` for the full callout.
526
+
525
527
  See `docs/llms.txt` for the full error code table with recovery classifications.
526
528
 
527
529
  ### Storyboards
package/docs/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ad Context Protocol (AdCP)
2
2
 
3
- > Generated at: 2026-04-30
4
- > Library: @adcp/sdk v5.25.1
3
+ > Generated at: 2026-05-01
4
+ > Library: @adcp/sdk v6.1.0
5
5
  > AdCP major version: 3
6
6
  > Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
7
7
 
@@ -1063,34 +1063,51 @@ Agents use the `recovery` classification to decide what to do: `transient` → r
1063
1063
 
1064
1064
  | Code | Recovery | Description |
1065
1065
  |------|----------|-------------|
1066
- | `INVALID_REQUEST` | correctable | The request is malformed or contains invalid parameters |
1067
- | `AUTH_REQUIRED` | correctable | Authentication is required or the provided credentials are invalid |
1068
- | `RATE_LIMITED` | transient | Too many requests; retry after the specified delay |
1069
- | `SERVICE_UNAVAILABLE` | transient | The service is temporarily unavailable |
1070
- | `POLICY_VIOLATION` | correctable | The request violates a platform or advertiser policy |
1071
- | `PRODUCT_NOT_FOUND` | correctable | The requested product does not exist |
1072
- | `PRODUCT_UNAVAILABLE` | transient | The product exists but is not currently available |
1073
- | `PROPOSAL_EXPIRED` | correctable | The proposal has expired and is no longer valid |
1074
- | `BUDGET_TOO_LOW` | correctable | The specified budget is below the minimum threshold |
1075
- | `CREATIVE_REJECTED` | correctable | One or more creatives failed review or validation |
1076
- | `UNSUPPORTED_FEATURE` | terminal | The requested feature is not supported by this seller |
1077
- | `AUDIENCE_TOO_SMALL` | correctable | The target audience is too small to deliver against |
1078
- | `ACCOUNT_NOT_FOUND` | terminal | The specified account does not exist |
1079
- | `ACCOUNT_SETUP_REQUIRED` | terminal | The account requires additional setup before use |
1080
- | `ACCOUNT_AMBIGUOUS` | correctable | Multiple accounts match; provide a more specific identifier |
1081
- | `ACCOUNT_PAYMENT_REQUIRED` | terminal | The account has an outstanding payment issue |
1082
- | `ACCOUNT_SUSPENDED` | terminal | The account has been suspended |
1083
- | `COMPLIANCE_UNSATISFIED` | correctable | Compliance requirements have not been met |
1084
- | `BUDGET_EXHAUSTED` | terminal | The budget has been fully spent |
1066
+ | `INVALID_REQUEST` | correctable | Request is malformed, missing required fields, or violates schema constraints |
1067
+ | `AUTH_REQUIRED` | correctable | Authentication is required to access this resource |
1068
+ | `RATE_LIMITED` | transient | Request rate exceeded; retry after the retry_after interval |
1069
+ | `SERVICE_UNAVAILABLE` | transient | Seller service is temporarily unavailable |
1070
+ | `POLICY_VIOLATION` | correctable | Request violates the seller's content or advertising policies |
1071
+ | `PRODUCT_NOT_FOUND` | correctable | One or more referenced product IDs are unknown or expired |
1072
+ | `PRODUCT_UNAVAILABLE` | correctable | The requested product is sold out or no longer available |
1073
+ | `PROPOSAL_EXPIRED` | correctable | A referenced proposal ID has passed its expires_at timestamp |
1074
+ | `BUDGET_TOO_LOW` | correctable | Budget is below the seller's minimum |
1075
+ | `CREATIVE_REJECTED` | correctable | Creative failed content policy review |
1076
+ | `UNSUPPORTED_FEATURE` | correctable | A requested feature or field is not supported by this seller |
1077
+ | `AUDIENCE_TOO_SMALL` | correctable | Audience segment is below the minimum required size for targeting |
1078
+ | `ACCOUNT_NOT_FOUND` | terminal | The account reference could not be resolved |
1079
+ | `ACCOUNT_SETUP_REQUIRED` | correctable | Natural key resolved but the account needs setup before use |
1080
+ | `ACCOUNT_AMBIGUOUS` | correctable | Natural key resolves to multiple accounts |
1081
+ | `ACCOUNT_PAYMENT_REQUIRED` | terminal | Account has an outstanding balance requiring payment before new buys |
1082
+ | `ACCOUNT_SUSPENDED` | terminal | Account has been suspended |
1083
+ | `COMPLIANCE_UNSATISFIED` | correctable | A required disclosure from the brief's compliance section cannot be satisfied by the target format |
1084
+ | `GOVERNANCE_DENIED` | correctable | A registered governance agent denied the transaction |
1085
+ | `BUDGET_EXHAUSTED` | terminal | Account or campaign budget has been fully spent |
1085
1086
  | `BUDGET_EXCEEDED` | correctable | Operation would exceed the allocated budget for the media buy or package |
1086
- | `CONFLICT` | correctable | The request conflicts with the current state of the resource |
1087
+ | `CONFLICT` | transient | Concurrent modification detected; the resource was modified between read and write |
1087
1088
  | `IDEMPOTENCY_CONFLICT` | correctable | An earlier request with the same idempotency_key was processed with a different canonical payload. Use a fresh UUID v4 for the new request, or resend the exact original payload to get the cached response. |
1088
1089
  | `IDEMPOTENCY_EXPIRED` | correctable | The idempotency_key is past the seller's replay window. If the prior call succeeded, look up the resource by natural key before retrying; otherwise mint a fresh UUID v4. |
1090
+ | `CREATIVE_DEADLINE_EXCEEDED` | correctable | Creative change submitted after the package's creative_deadline |
1089
1091
  | `INVALID_STATE` | correctable | Operation is not permitted for the resource's current status |
1090
1092
  | `MEDIA_BUY_NOT_FOUND` | correctable | Referenced media buy does not exist or is not accessible |
1091
1093
  | `NOT_CANCELLABLE` | correctable | The media buy or package cannot be canceled in its current state |
1092
1094
  | `PACKAGE_NOT_FOUND` | correctable | Referenced package does not exist within the specified media buy |
1095
+ | `CREATIVE_NOT_FOUND` | correctable | Referenced creative does not exist in the agent's creative library |
1096
+ | `SIGNAL_NOT_FOUND` | correctable | Referenced signal does not exist in the agent's catalog |
1097
+ | `SESSION_NOT_FOUND` | correctable | SI session ID is invalid, expired, or does not exist |
1098
+ | `PLAN_NOT_FOUND` | correctable | Referenced governance plan does not exist or is not accessible |
1099
+ | `REFERENCE_NOT_FOUND` | correctable | Generic fallback for a referenced identifier, grant, session, or other resource that does not exist or is not accessible by the caller |
1100
+ | `SESSION_TERMINATED` | correctable | SI session has already been terminated and cannot accept further messages |
1093
1101
  | `VALIDATION_ERROR` | correctable | Request contains invalid field values or violates business rules beyond schema validation |
1102
+ | `PRODUCT_EXPIRED` | correctable | One or more referenced products have passed their expires_at timestamp |
1103
+ | `PROPOSAL_NOT_COMMITTED` | correctable | The referenced proposal has proposal_status 'draft' and cannot be used to create a media buy |
1104
+ | `IO_REQUIRED` | correctable | The committed proposal requires a signed insertion order but no io_acceptance was provided |
1105
+ | `TERMS_REJECTED` | correctable | Buyer-proposed measurement_terms were rejected by the seller |
1106
+ | `REQUOTE_REQUIRED` | correctable | An update_media_buy request changes the parameter envelope (budget, flight dates, volume, targeting) the original quote was priced against |
1107
+ | `VERSION_UNSUPPORTED` | correctable | The declared adcp_major_version is not supported by this seller |
1108
+ | `CAMPAIGN_SUSPENDED` | transient | Campaign governance has been suspended pending human review |
1109
+ | `GOVERNANCE_UNAVAILABLE` | transient | A registered governance agent is unreachable and the seller cannot obtain a governance decision |
1110
+ | `PERMISSION_DENIED` | correctable | The authenticated caller is not authorized for the requested action under the seller's policies, or a required signed credential is missing or invalid |
1094
1111
 
1095
1112
  Unknown codes: fall back to the HTTP status code (4xx = correctable, 5xx = transient).
1096
1113
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcp/sdk",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "AdCP SDK — client, server, and compliance harnesses for the AdContext Protocol (MCP + A2A)",
5
5
  "workspaces": [
6
6
  ".",
@@ -35,6 +35,11 @@
35
35
  "require": "./dist/lib/types/index.js",
36
36
  "types": "./dist/lib/types/index.d.ts"
37
37
  },
38
+ "./types/v2-5": {
39
+ "import": "./dist/lib/types/v2-5/index.js",
40
+ "require": "./dist/lib/types/v2-5/index.js",
41
+ "types": "./dist/lib/types/v2-5/index.d.ts"
42
+ },
38
43
  "./testing": {
39
44
  "import": "./dist/lib/testing/index.js",
40
45
  "require": "./dist/lib/testing/index.js",
@@ -121,6 +126,9 @@
121
126
  "types": [
122
127
  "dist/lib/types/index.d.ts"
123
128
  ],
129
+ "types/v2-5": [
130
+ "dist/lib/types/v2-5/index.d.ts"
131
+ ],
124
132
  "testing": [
125
133
  "dist/lib/testing/index.d.ts"
126
134
  ],
@@ -200,6 +208,8 @@
200
208
  "sync-schemas:all": "npm run sync-schemas && npm run sync-schemas:v2.5",
201
209
  "schema-diff": "tsx scripts/schema-diff.ts",
202
210
  "generate-types": "tsx scripts/generate-types.ts && tsx scripts/generate-enum-arrays.ts",
211
+ "generate-types:v2.5": "tsx scripts/generate-v2-5-types.ts",
212
+ "generate-types:all": "npm run generate-types && npm run generate-types:v2.5",
203
213
  "generate-registry-types": "tsx scripts/generate-registry-types.ts",
204
214
  "generate-enum-arrays": "tsx scripts/generate-enum-arrays.ts",
205
215
  "generate-inline-enum-arrays": "tsx scripts/generate-inline-enum-arrays.ts",
@@ -41,6 +41,11 @@ Every sales-_ specialism (including `sales-social`, `sales-broadcast-tv`, `sales
41
41
  | `list_creatives` | Read the creative library back with pagination | `sales.listCreatives` |
42
42
  | `get_media_buy_delivery` | Delivery + spend reporting with `reporting_period`, per-package billing rows | `sales.getMediaBuyDelivery` |
43
43
 
44
+ > **`sales-guaranteed` minimum tool surface** — register ALL of these or storyboard scenarios will cascade-skip with `skip_reason: missing_tool`:
45
+ > `get_adcp_capabilities`, `sync_accounts`, `list_accounts`, `get_products`, `list_creative_formats`, `create_media_buy`, `update_media_buy`, `get_media_buys`, `sync_creatives`, `get_media_buy_delivery`
46
+ >
47
+ > (`list_creatives` is optional — only required if the seller hosts its own creative library; creative-agent delegates omit it)
48
+
44
49
  **Minimum platform skeleton** — every sales-\* seller starts here, then adds specialism-specific behavior on top:
45
50
 
46
51
  ```ts
@@ -522,7 +527,17 @@ productsResponse({
522
527
 
523
528
  **`create_media_buy`** — `CreateMediaBuyRequestSchema.shape`
524
529
 
525
- Validate the request before creating the buy. Return an error response (not `adcpError`) when business validation fails:
530
+ Return `adcpError(...)` for all business validation failures. Error-code matrix all spec-defined rejections on `create_media_buy` / `update_media_buy`:
531
+
532
+ | Tool | Condition | Code |
533
+ | --- | --- | --- |
534
+ | `create_media_buy` | `performance_standards` or `measurement_terms` on a package are unacceptable | `adcpError('TERMS_REJECTED', { message: '...' })` |
535
+ | `create_media_buy` | `product_id` on a package not in catalog | `adcpError('PRODUCT_NOT_FOUND', { field: 'packages[N].product_id' })` |
536
+ | `create_media_buy` | product exists but inventory sold out / unavailable for the requested flight | `adcpError('PRODUCT_UNAVAILABLE', { field: 'packages[N].product_id' })` |
537
+ | `create_media_buy` | budget below the product's floor price | `adcpError('BUDGET_TOO_LOW', { message: '...' })` |
538
+ | `create_media_buy` | reversed dates, schema violation | `adcpError('INVALID_REQUEST', { message: '...' })` |
539
+ | `update_media_buy` | `media_buy_id` not found | `adcpError('MEDIA_BUY_NOT_FOUND', { field: 'media_buy_id' })` |
540
+ | `update_media_buy` | `package_id` within a valid buy not found | `adcpError('PACKAGE_NOT_FOUND', { field: 'package_id' })` |
526
541
 
527
542
  ```
528
543
  // Success — revision, confirmed_at, and valid_actions are auto-set:
@@ -900,7 +915,7 @@ import {
900
915
  type SalesPlatform,
901
916
  type AccountStore,
902
917
  } from '@adcp/sdk/server';
903
- import type { ServeContext } from '@adcp/sdk';
918
+ import type { ServeContext, MediaBuyStatus } from '@adcp/sdk';
904
919
 
905
920
  // Publisher-typed metadata blob round-tripped via Account.ctx_metadata.
906
921
  // Whatever shape your adapter wants — the SDK doesn't inspect it.
@@ -1032,11 +1047,28 @@ class MySeller implements DecisioningPlatform<{}, MySellerMeta> {
1032
1047
  // wholesale. The patch carries envelope fields (idempotency_key,
1033
1048
  // context) that have no business in your domain state. Spreading
1034
1049
  // them pollutes `get_media_buys` responses and breaks dedup.
1035
- const updated = { ...existing, status: patch.paused === true ? 'paused' : 'active' };
1050
+
1051
+ // State machine: creative_assignments arriving advances pending_creatives.
1052
+ // pending_creatives → pending_start (start_time in future) or active (start_time now/past).
1053
+ let status = existing.status as MediaBuyStatus;
1054
+ if (patch.paused === true) {
1055
+ status = 'paused';
1056
+ } else if (
1057
+ status === 'pending_creatives' &&
1058
+ (patch.packages ?? []).some((p: { creative_assignments?: unknown[] }) =>
1059
+ (p.creative_assignments ?? []).length > 0)
1060
+ ) {
1061
+ const startTime = existing.start_time ? new Date(existing.start_time as string) : null;
1062
+ status = startTime && startTime > new Date() ? 'pending_start' : 'active';
1063
+ } else if (patch.paused === false && status === 'paused') {
1064
+ status = 'active';
1065
+ }
1066
+
1067
+ const updated = { ...existing, status };
1036
1068
  await ctx.store.put('media_buys', mediaBuyId, updated);
1037
1069
  return {
1038
1070
  media_buy_id: mediaBuyId,
1039
- status: updated.status as 'paused' | 'active',
1071
+ status: updated.status as MediaBuyStatus,
1040
1072
  // `affected_packages` is `Package[]` (per `/schemas/latest/core/package.json`)
1041
1073
  // — objects with at minimum `package_id`. Don't return bare strings;
1042
1074
  // the update-media-buy-response oneOf discriminates against them and
@@ -1103,8 +1135,9 @@ Key points:
1103
1135
  3. Response builders are auto-applied — just return the data
1104
1136
  4. Use `ctx.store` for state — persists across stateless HTTP requests
1105
1137
  5. Set `sandbox: true` on all mock/demo responses
1106
- 6. Use `adcpError()` for business validation failures
1138
+ 6. Use `adcpError()` for business validation failures — see the error-code matrix in § create_media_buy above
1107
1139
  7. Use `as const` on string literal arrays and union-typed fields in product definitions — TypeScript infers `string[]` from `['display', 'olv']` but the SDK requires specific union types like `MediaChannel[]`. Apply `as const` to `channels`, `delivery_type`, `selection_type`, and `pricing_model` values.
1140
+ 8. `pending_creatives` is a transient state — `update_media_buy` MUST advance it to `pending_start` or `active` when `creative_assignments` arrive (see state-machine logic in § update_media_buy above)
1108
1141
 
1109
1142
  ## Governance
1110
1143
 
@@ -30,8 +30,7 @@ createMediaBuy: async (params, ctx) => {
30
30
  product_id: pkg.product_id,
31
31
  pricing_option_id: pkg.pricing_option_id,
32
32
  budget: pkg.budget,
33
- property_list: pkg.property_list, // persist inventory-list refs verbatim
34
- collection_list: pkg.collection_list,
33
+ targeting_overlay: pkg.targeting_overlay, // persists property_list / collection_list verbatim
35
34
  creative_assignments: pkg.creative_assignments ?? [],
36
35
  }));
37
36
  const buy = {
@@ -45,7 +44,9 @@ createMediaBuy: async (params, ctx) => {
45
44
  },
46
45
  ```
47
46
 
48
- **`get_media_buys` must echo `packages[].property_list` / `collection_list`.** The `inventory_list_targeting` baseline scenarios call `create_media_buy` with list references, then call `get_media_buys` expecting those same `list_id` values to appear at `media_buys[].packages[].property_list.list_id` / `.collection_list.list_id`. Persist verbatim, echo verbatim. `update_media_buy` should merge new list refs without dropping prior ones.
47
+ **`get_media_buys` must echo `packages[].targeting_overlay.property_list` / `.collection_list`.** Per the AdCP types, `property_list` and `collection_list` live inside `TargetingOverlay`, not directly on `Package` (see `/schemas/latest/core/package.json` and `/schemas/latest/core/targeting.json`). The `inventory_list_targeting` baseline scenarios send list refs at `packages[].targeting_overlay.{property_list,collection_list}`; `get_media_buys` must echo them back at the same nested path. Persist the full `targeting_overlay` verbatim; echo verbatim. `update_media_buy` should merge new targeting overlays without dropping prior refs.
48
+
49
+ **State transition: `pending_creatives → pending_start / active`.** When `update_media_buy` attaches `creative_assignments` to a buy in `pending_creatives` status, the buy MUST advance: `pending_start` if `start_time` is in the future, `active` if `start_time` is now or past. See the `updateMediaBuy` state-machine logic in `../SKILL.md` § update_media_buy.
49
50
 
50
51
  **Task envelope — when IO signing is required.** Use `registerAdcpTaskTool` from `@adcp/sdk/server` so `tasks/get` returns the completion artifact:
51
52
 
@@ -233,14 +233,93 @@ Quick lookup before reading the full envelope. Match what you see in `adcp_error
233
233
  | `keyword: 'enum'` at `/destinations/*/type` | Made-up destination type | Use `'platform'` (with `platform`) or `'agent'` (with `agent_url`). |
234
234
  | Response carries `status: 'submitted'` and `task_id` | Async — work is queued, NOT done | Poll via `tasks/get` (A2A) or the MCP async task extension using `task_id`. |
235
235
  | `recovery: 'transient'` (rate limit, 5xx, timeout) | Server-side, retry-safe | Retry with the **same** `idempotency_key`. |
236
- <<<<<<< Updated upstream
237
236
  | `406 Not Acceptable` before any AdCP framing | Hand-rolled HTTP without `Accept: text/event-stream` (MCP transport) | Use `@modelcontextprotocol/sdk` client; it sets the right Accept header. |
238
- =======
239
- >>>>>>> Stashed changes
240
- | `recovery: 'correctable'` | Buyer-side fix | Read `issues[]`, patch the pointers, resend. Most cases close in one attempt. |
237
+ | `recovery: 'correctable'` | Buyer-side fix | Read `issues[]`, patch the pointers, resend. Most cases close in one attempt. (See exceptions below — four codes are technically `correctable` but operator-semantically human-escalate.) |
241
238
  | `recovery: 'terminal'` (account suspended, payment required, …) | Requires human action | Don't retry. Surface to the user. |
242
239
  | HTTP 401 with `WWW-Authenticate` header | Missing or expired credential | Add `Authorization` per the agent's auth spec; re-auth if applicable. |
243
240
 
241
+ > **⚠️ Four codes are technically `correctable` but operator-semantically human-escalate. Don't auto-tweak.**
242
+ >
243
+ > - **`POLICY_VIOLATION`** — buyer's content/targeting violates seller policy. Auto-mutating creative or targeting and resubmitting **looks like evasion** to the seller's governance reviewer. Surface to a human.
244
+ > - **`COMPLIANCE_UNSATISFIED`** — required disclosure can't be satisfied by the chosen format. Auto-relaxing the compliance section IS the compliance failure. Surface to a human.
245
+ > - **`GOVERNANCE_DENIED`** — registered governance agent rejected the spend. Auto-shrinking budget and retrying looks like governance evasion. Surface to the plan operator.
246
+ > - **`AUTH_REQUIRED`** — conflates missing creds (genuinely correctable) with revoked / expired creds (operator must rotate). Until [adcontextprotocol/adcp#3730](https://github.com/adcontextprotocol/adcp/issues/3730) splits this into `auth_missing` + `auth_invalid`, treat as escalate-after-one-attempt.
247
+ >
248
+ > Spec recovery on these is `correctable`; operator behavior is human-in-loop. The pattern: read `error.message` + `error.suggestion`, surface to the user, **don't loop**.
249
+
250
+ ### Operationalize the recovery rules — `decideRetry`
251
+
252
+ `@adcp/sdk` exports `decideRetry(error, ctx?)` which encodes the operator-grade defaults from the table above plus this section. It returns a discriminated `RetryDecision` so the type system enforces the same-vs-fresh `idempotency_key` rule:
253
+
254
+ ```typescript
255
+ import { decideRetry } from '@adcp/sdk';
256
+ import { randomUUID } from 'node:crypto';
257
+
258
+ async function callWithRetry(toolName: string, params: Record<string, unknown>): Promise<unknown> {
259
+ let attempt = 1;
260
+ let idempotencyKey = randomUUID();
261
+
262
+ while (true) {
263
+ try {
264
+ return await agent.call(toolName, { ...params, idempotency_key: idempotencyKey });
265
+ } catch (e) {
266
+ const error = extractAdcpError(e); // your SDK's error extractor
267
+ if (!error) throw e; // not an AdCP-shaped failure — let it bubble
268
+
269
+ const decision = decideRetry(error, { attempt });
270
+
271
+ if (decision.action === 'retry') {
272
+ // Server-side transient (RATE_LIMITED, SERVICE_UNAVAILABLE, CONFLICT).
273
+ // Replay with the SAME idempotency_key after the suggested delay.
274
+ await sleep(decision.delayMs);
275
+ attempt++;
276
+ continue;
277
+ }
278
+
279
+ if (decision.action === 'mutate-and-retry') {
280
+ // Buyer-fixable. Apply the seller's correction (decision.field /
281
+ // decision.suggestion) and mint a FRESH idempotency_key — payload
282
+ // changed, so the seller's replay-window must NOT dedupe.
283
+ params = applyCorrection(params, error, decision); // your domain logic
284
+ idempotencyKey = randomUUID();
285
+ await sleep(decision.delayMs); // small jitter (~125-250ms by default)
286
+ attempt++;
287
+ continue;
288
+ }
289
+
290
+ // 'escalate' — stop the loop and surface to a human. Includes
291
+ // commercial-relationship signals (POLICY_VIOLATION etc.), auth
292
+ // failures, IDEMPOTENCY_EXPIRED (do a natural-key check first!),
293
+ // attempt-cap exhaustion, and unknown vendor codes.
294
+ throw new EscalationRequired(decision.reason, decision.message);
295
+ }
296
+ }
297
+ }
298
+ ```
299
+
300
+ The discriminated union means TypeScript narrows correctly in each branch — `decision.delayMs` is only available on retry/mutate-and-retry, `decision.field` only on mutate-and-retry, `decision.message` only on escalate.
301
+
302
+ For per-vertical overrides (e.g., a creative-template platform that legitimately auto-fixes `CREATIVE_REJECTED` format mismatches), instantiate `BuyerRetryPolicy` directly:
303
+
304
+ ```typescript
305
+ import { BuyerRetryPolicy } from '@adcp/sdk';
306
+
307
+ const policy = new BuyerRetryPolicy({
308
+ overrides: {
309
+ CREATIVE_REJECTED: (error) => {
310
+ if (error.field === 'creative.format' && /unsupported_format/.test(error.message)) {
311
+ return { action: 'mutate-and-retry', delayMs: 0, attemptCap: 2, sameIdempotencyKey: false, reason: 'capability' };
312
+ }
313
+ return null; // fall through to default (escalate as commercial)
314
+ },
315
+ },
316
+ });
317
+
318
+ const decision = policy.decide(error, { attempt });
319
+ ```
320
+
321
+ Default policy is intentionally conservative — see the source comments in `src/lib/utils/buyer-retry-policy.ts` for per-code reasoning.
322
+
244
323
  If your symptom isn't here, fall through to the next section.
245
324
 
246
325
  ## If you get stuck