@adcp/sdk 12.1.0 → 13.0.0-rc.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 (464) hide show
  1. package/README.md +19 -3
  2. package/bin/adcp-fuzz.js +3 -1
  3. package/dist/lib/adapters/content-standards-adapter.d.mts +9 -9
  4. package/dist/lib/adapters/content-standards-adapter.d.ts +9 -9
  5. package/dist/lib/adapters/content-standards-adapter.d.ts.map +1 -1
  6. package/dist/lib/adapters/content-standards-adapter.js +22 -22
  7. package/dist/lib/adapters/content-standards-adapter.js.map +1 -1
  8. package/dist/lib/adapters/content-standards-adapter.mjs +18 -18
  9. package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
  10. package/dist/lib/adapters/index.d.mts +2 -2
  11. package/dist/lib/adapters/index.d.ts +2 -2
  12. package/dist/lib/adapters/index.d.ts.map +1 -1
  13. package/dist/lib/adapters/index.js +10 -10
  14. package/dist/lib/adapters/index.js.map +1 -1
  15. package/dist/lib/adapters/index.mjs +9 -9
  16. package/dist/lib/adapters/index.mjs.map +1 -1
  17. package/dist/lib/auth/oauth/authorization-required.d.mts +3 -0
  18. package/dist/lib/auth/oauth/authorization-required.d.ts +3 -0
  19. package/dist/lib/auth/oauth/authorization-required.d.ts.map +1 -1
  20. package/dist/lib/auth/oauth/authorization-required.js +12 -9
  21. package/dist/lib/auth/oauth/authorization-required.js.map +1 -1
  22. package/dist/lib/auth/oauth/authorization-required.mjs +12 -9
  23. package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
  24. package/dist/lib/auth/oauth/provider-cache.d.mts +7 -0
  25. package/dist/lib/auth/oauth/provider-cache.d.ts +8 -0
  26. package/dist/lib/auth/oauth/provider-cache.d.ts.map +1 -0
  27. package/dist/lib/auth/oauth/provider-cache.js +44 -0
  28. package/dist/lib/auth/oauth/provider-cache.js.map +1 -0
  29. package/dist/lib/auth/oauth/provider-cache.mjs +19 -0
  30. package/dist/lib/auth/oauth/provider-cache.mjs.map +1 -0
  31. package/dist/lib/conformance/invariants/uniformError.js +1 -1
  32. package/dist/lib/conformance/invariants/uniformError.js.map +1 -1
  33. package/dist/lib/conformance/invariants/uniformError.mjs +1 -1
  34. package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
  35. package/dist/lib/conformance/runners.js +1 -1
  36. package/dist/lib/conformance/runners.js.map +1 -1
  37. package/dist/lib/conformance/runners.mjs +1 -1
  38. package/dist/lib/conformance/runners.mjs.map +1 -1
  39. package/dist/lib/conformance/seeder.js +5 -5
  40. package/dist/lib/conformance/seeder.js.map +1 -1
  41. package/dist/lib/conformance/seeder.mjs +5 -5
  42. package/dist/lib/conformance/seeder.mjs.map +1 -1
  43. package/dist/lib/core/ADCPMultiAgentClient.d.mts +26 -29
  44. package/dist/lib/core/ADCPMultiAgentClient.d.ts +26 -29
  45. package/dist/lib/core/ADCPMultiAgentClient.d.ts.map +1 -1
  46. package/dist/lib/core/ADCPMultiAgentClient.js +27 -19
  47. package/dist/lib/core/ADCPMultiAgentClient.js.map +1 -1
  48. package/dist/lib/core/ADCPMultiAgentClient.mjs +27 -19
  49. package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
  50. package/dist/lib/core/AgentClient.d.mts +148 -138
  51. package/dist/lib/core/AgentClient.d.ts +148 -138
  52. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  53. package/dist/lib/core/AgentClient.js +174 -85
  54. package/dist/lib/core/AgentClient.js.map +1 -1
  55. package/dist/lib/core/AgentClient.mjs +174 -85
  56. package/dist/lib/core/AgentClient.mjs.map +1 -1
  57. package/dist/lib/core/AsyncHandler.d.mts +18 -16
  58. package/dist/lib/core/AsyncHandler.d.ts +18 -16
  59. package/dist/lib/core/AsyncHandler.d.ts.map +1 -1
  60. package/dist/lib/core/AsyncHandler.js +22 -1
  61. package/dist/lib/core/AsyncHandler.js.map +1 -1
  62. package/dist/lib/core/AsyncHandler.mjs +22 -1
  63. package/dist/lib/core/AsyncHandler.mjs.map +1 -1
  64. package/dist/lib/core/ConversationTypes.d.mts +6 -2
  65. package/dist/lib/core/ConversationTypes.d.ts +6 -2
  66. package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
  67. package/dist/lib/core/ConversationTypes.js.map +1 -1
  68. package/dist/lib/core/CreativeAgentClient.d.mts +41 -17
  69. package/dist/lib/core/CreativeAgentClient.d.ts +41 -17
  70. package/dist/lib/core/CreativeAgentClient.d.ts.map +1 -1
  71. package/dist/lib/core/CreativeAgentClient.js +39 -12
  72. package/dist/lib/core/CreativeAgentClient.js.map +1 -1
  73. package/dist/lib/core/CreativeAgentClient.mjs +39 -12
  74. package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
  75. package/dist/lib/core/SingleAgentClient.d.mts +129 -52
  76. package/dist/lib/core/SingleAgentClient.d.ts +129 -52
  77. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  78. package/dist/lib/core/SingleAgentClient.js +1748 -218
  79. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  80. package/dist/lib/core/SingleAgentClient.mjs +1758 -218
  81. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  82. package/dist/lib/core/TaskExecutor.d.mts +9 -0
  83. package/dist/lib/core/TaskExecutor.d.ts +9 -0
  84. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  85. package/dist/lib/core/TaskExecutor.js +137 -44
  86. package/dist/lib/core/TaskExecutor.js.map +1 -1
  87. package/dist/lib/core/TaskExecutor.mjs +137 -44
  88. package/dist/lib/core/TaskExecutor.mjs.map +1 -1
  89. package/dist/lib/index.d.mts +111 -17
  90. package/dist/lib/index.d.ts +111 -17
  91. package/dist/lib/index.d.ts.map +1 -1
  92. package/dist/lib/index.js +94 -94
  93. package/dist/lib/index.js.map +1 -1
  94. package/dist/lib/index.mjs +93 -94
  95. package/dist/lib/index.mjs.map +1 -1
  96. package/dist/lib/net/ssrf-fetch.d.mts +13 -1
  97. package/dist/lib/net/ssrf-fetch.d.ts +13 -1
  98. package/dist/lib/net/ssrf-fetch.d.ts.map +1 -1
  99. package/dist/lib/net/ssrf-fetch.js +14 -7
  100. package/dist/lib/net/ssrf-fetch.js.map +1 -1
  101. package/dist/lib/net/ssrf-fetch.mjs +14 -7
  102. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  103. package/dist/lib/protocols/a2a.d.mts +2 -2
  104. package/dist/lib/protocols/a2a.d.ts +2 -2
  105. package/dist/lib/protocols/a2a.d.ts.map +1 -1
  106. package/dist/lib/protocols/a2a.js +14 -9
  107. package/dist/lib/protocols/a2a.js.map +1 -1
  108. package/dist/lib/protocols/a2a.mjs +14 -9
  109. package/dist/lib/protocols/a2a.mjs.map +1 -1
  110. package/dist/lib/protocols/index.d.mts +20 -3
  111. package/dist/lib/protocols/index.d.ts +20 -3
  112. package/dist/lib/protocols/index.d.ts.map +1 -1
  113. package/dist/lib/protocols/index.js +44 -31
  114. package/dist/lib/protocols/index.js.map +1 -1
  115. package/dist/lib/protocols/index.mjs +44 -32
  116. package/dist/lib/protocols/index.mjs.map +1 -1
  117. package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
  118. package/dist/lib/protocols/mcp-modern.js +87 -12
  119. package/dist/lib/protocols/mcp-modern.js.map +1 -1
  120. package/dist/lib/protocols/mcp-modern.mjs +89 -12
  121. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  122. package/dist/lib/protocols/mcp-tasks.d.mts +3 -0
  123. package/dist/lib/protocols/mcp-tasks.d.ts +3 -0
  124. package/dist/lib/protocols/mcp-tasks.d.ts.map +1 -1
  125. package/dist/lib/protocols/mcp-tasks.js +21 -11
  126. package/dist/lib/protocols/mcp-tasks.js.map +1 -1
  127. package/dist/lib/protocols/mcp-tasks.mjs +21 -11
  128. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  129. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  130. package/dist/lib/server/create-adcp-server.d.mts +6 -0
  131. package/dist/lib/server/create-adcp-server.d.ts +6 -0
  132. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  133. package/dist/lib/server/create-adcp-server.js +295 -48
  134. package/dist/lib/server/create-adcp-server.js.map +1 -1
  135. package/dist/lib/server/create-adcp-server.mjs +301 -50
  136. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  137. package/dist/lib/server/decisioning/assembly-helpers.d.mts +27 -13
  138. package/dist/lib/server/decisioning/assembly-helpers.d.ts +27 -13
  139. package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -1
  140. package/dist/lib/server/decisioning/assembly-helpers.js +136 -14
  141. package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -1
  142. package/dist/lib/server/decisioning/assembly-helpers.mjs +134 -13
  143. package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
  144. package/dist/lib/server/decisioning/index.d.mts +13 -12
  145. package/dist/lib/server/decisioning/index.d.ts +13 -12
  146. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  147. package/dist/lib/server/decisioning/index.js +6 -0
  148. package/dist/lib/server/decisioning/index.js.map +1 -1
  149. package/dist/lib/server/decisioning/index.mjs +9 -3
  150. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  151. package/dist/lib/server/decisioning/list-helpers.d.mts +13 -3
  152. package/dist/lib/server/decisioning/list-helpers.d.ts +13 -3
  153. package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -1
  154. package/dist/lib/server/decisioning/list-helpers.js +13 -3
  155. package/dist/lib/server/decisioning/list-helpers.js.map +1 -1
  156. package/dist/lib/server/decisioning/list-helpers.mjs +11 -2
  157. package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
  158. package/dist/lib/server/decisioning/manifest-helpers.d.mts +5 -3
  159. package/dist/lib/server/decisioning/manifest-helpers.d.ts +5 -3
  160. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -1
  161. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -1
  162. package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
  163. package/dist/lib/server/decisioning/proposal/dispatch.d.mts +2 -2
  164. package/dist/lib/server/decisioning/proposal/dispatch.d.ts +2 -2
  165. package/dist/lib/server/decisioning/proposal/dispatch.d.ts.map +1 -1
  166. package/dist/lib/server/decisioning/proposal/dispatch.js.map +1 -1
  167. package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
  168. package/dist/lib/server/decisioning/proposal/index.d.mts +1 -1
  169. package/dist/lib/server/decisioning/proposal/index.d.ts +1 -1
  170. package/dist/lib/server/decisioning/proposal/index.d.ts.map +1 -1
  171. package/dist/lib/server/decisioning/proposal/index.js.map +1 -1
  172. package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
  173. package/dist/lib/server/decisioning/proposal/lifecycle.d.mts +3 -2
  174. package/dist/lib/server/decisioning/proposal/lifecycle.d.ts +3 -2
  175. package/dist/lib/server/decisioning/proposal/lifecycle.d.ts.map +1 -1
  176. package/dist/lib/server/decisioning/proposal/lifecycle.js.map +1 -1
  177. package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
  178. package/dist/lib/server/decisioning/proposal/mock-manager.d.mts +3 -3
  179. package/dist/lib/server/decisioning/proposal/mock-manager.d.ts +3 -3
  180. package/dist/lib/server/decisioning/proposal/mock-manager.d.ts.map +1 -1
  181. package/dist/lib/server/decisioning/proposal/mock-manager.js.map +1 -1
  182. package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
  183. package/dist/lib/server/decisioning/proposal/types.d.mts +10 -6
  184. package/dist/lib/server/decisioning/proposal/types.d.ts +10 -6
  185. package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -1
  186. package/dist/lib/server/decisioning/proposal/types.js.map +1 -1
  187. package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
  188. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +21 -2
  189. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +21 -2
  190. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  191. package/dist/lib/server/decisioning/runtime/from-platform.js +754 -81
  192. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  193. package/dist/lib/server/decisioning/runtime/from-platform.mjs +763 -81
  194. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  195. package/dist/lib/server/decisioning/specialisms/brand-rights.d.mts +9 -9
  196. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +9 -9
  197. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -1
  198. package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -1
  199. package/dist/lib/server/decisioning/specialisms/content-standards.d.mts +16 -16
  200. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +16 -16
  201. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -1
  202. package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -1
  203. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +15 -13
  204. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +15 -13
  205. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
  206. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
  207. package/dist/lib/server/decisioning/specialisms/creative.d.mts +12 -11
  208. package/dist/lib/server/decisioning/specialisms/creative.d.ts +12 -11
  209. package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
  210. package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
  211. package/dist/lib/server/decisioning/specialisms/sales.d.mts +25 -15
  212. package/dist/lib/server/decisioning/specialisms/sales.d.ts +25 -15
  213. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
  214. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
  215. package/dist/lib/server/index.d.mts +3 -3
  216. package/dist/lib/server/index.d.ts +3 -3
  217. package/dist/lib/server/index.d.ts.map +1 -1
  218. package/dist/lib/server/index.js +72 -72
  219. package/dist/lib/server/index.js.map +1 -1
  220. package/dist/lib/server/index.mjs +36 -36
  221. package/dist/lib/server/index.mjs.map +1 -1
  222. package/dist/lib/server/legacy/v5/index.d.mts +1 -0
  223. package/dist/lib/server/legacy/v5/index.d.ts +1 -0
  224. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
  225. package/dist/lib/server/legacy/v5/index.js +74 -1
  226. package/dist/lib/server/legacy/v5/index.js.map +1 -1
  227. package/dist/lib/server/legacy/v5/index.mjs +75 -1
  228. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  229. package/dist/lib/server/responses.d.mts +2 -2
  230. package/dist/lib/server/responses.d.ts +2 -2
  231. package/dist/lib/server/responses.js.map +1 -1
  232. package/dist/lib/server/responses.mjs.map +1 -1
  233. package/dist/lib/testing/client.d.ts.map +1 -1
  234. package/dist/lib/testing/client.js +13 -5
  235. package/dist/lib/testing/client.js.map +1 -1
  236. package/dist/lib/testing/client.mjs +13 -5
  237. package/dist/lib/testing/client.mjs.map +1 -1
  238. package/dist/lib/testing/compliance/comply.d.mts +1 -1
  239. package/dist/lib/testing/compliance/comply.d.ts +1 -1
  240. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  241. package/dist/lib/testing/compliance/comply.js +16 -6
  242. package/dist/lib/testing/compliance/comply.js.map +1 -1
  243. package/dist/lib/testing/compliance/comply.mjs +16 -6
  244. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  245. package/dist/lib/testing/scenarios/brand-rights.js +6 -6
  246. package/dist/lib/testing/scenarios/brand-rights.js.map +1 -1
  247. package/dist/lib/testing/scenarios/brand-rights.mjs +6 -6
  248. package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
  249. package/dist/lib/testing/scenarios/creative.js +7 -7
  250. package/dist/lib/testing/scenarios/creative.js.map +1 -1
  251. package/dist/lib/testing/scenarios/creative.mjs +7 -7
  252. package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
  253. package/dist/lib/testing/scenarios/discovery.js +2 -2
  254. package/dist/lib/testing/scenarios/discovery.js.map +1 -1
  255. package/dist/lib/testing/scenarios/discovery.mjs +2 -2
  256. package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
  257. package/dist/lib/testing/scenarios/edge-cases.js +11 -11
  258. package/dist/lib/testing/scenarios/edge-cases.js.map +1 -1
  259. package/dist/lib/testing/scenarios/edge-cases.mjs +11 -11
  260. package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
  261. package/dist/lib/testing/scenarios/governance.d.ts.map +1 -1
  262. package/dist/lib/testing/scenarios/governance.js +16 -22
  263. package/dist/lib/testing/scenarios/governance.js.map +1 -1
  264. package/dist/lib/testing/scenarios/governance.mjs +16 -22
  265. package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
  266. package/dist/lib/testing/scenarios/media-buy.js +5 -5
  267. package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
  268. package/dist/lib/testing/scenarios/media-buy.mjs +5 -5
  269. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  270. package/dist/lib/testing/scenarios/schema-compliance.js +1 -1
  271. package/dist/lib/testing/scenarios/schema-compliance.js.map +1 -1
  272. package/dist/lib/testing/scenarios/schema-compliance.mjs +1 -1
  273. package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
  274. package/dist/lib/testing/scenarios/trusted-match.d.ts.map +1 -1
  275. package/dist/lib/testing/scenarios/trusted-match.js +4 -3
  276. package/dist/lib/testing/scenarios/trusted-match.js.map +1 -1
  277. package/dist/lib/testing/scenarios/trusted-match.mjs +4 -3
  278. package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
  279. package/dist/lib/testing/storyboard/probes.d.mts +6 -0
  280. package/dist/lib/testing/storyboard/probes.d.ts +6 -0
  281. package/dist/lib/testing/storyboard/probes.d.ts.map +1 -1
  282. package/dist/lib/testing/storyboard/probes.js +16 -5
  283. package/dist/lib/testing/storyboard/probes.js.map +1 -1
  284. package/dist/lib/testing/storyboard/probes.mjs +16 -5
  285. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  286. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  287. package/dist/lib/testing/storyboard/runner.js +6 -2
  288. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  289. package/dist/lib/testing/storyboard/runner.mjs +6 -2
  290. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  291. package/dist/lib/testing/storyboard/shape-drift-hints.d.mts +3 -4
  292. package/dist/lib/testing/storyboard/shape-drift-hints.d.ts +3 -4
  293. package/dist/lib/testing/storyboard/shape-drift-hints.d.ts.map +1 -1
  294. package/dist/lib/testing/storyboard/shape-drift-hints.js +27 -27
  295. package/dist/lib/testing/storyboard/shape-drift-hints.js.map +1 -1
  296. package/dist/lib/testing/storyboard/shape-drift-hints.mjs +27 -27
  297. package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
  298. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
  299. package/dist/lib/testing/storyboard/task-map.js +43 -5
  300. package/dist/lib/testing/storyboard/task-map.js.map +1 -1
  301. package/dist/lib/testing/storyboard/task-map.mjs +43 -5
  302. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  303. package/dist/lib/testing/test-helpers.d.mts +2 -2
  304. package/dist/lib/testing/test-helpers.d.ts +2 -2
  305. package/dist/lib/testing/test-helpers.js.map +1 -1
  306. package/dist/lib/testing/test-helpers.mjs.map +1 -1
  307. package/dist/lib/testing/types.d.mts +7 -1
  308. package/dist/lib/testing/types.d.ts +7 -1
  309. package/dist/lib/testing/types.d.ts.map +1 -1
  310. package/dist/lib/testing/types.js.map +1 -1
  311. package/dist/lib/types/adcp.d.mts +14 -14
  312. package/dist/lib/types/adcp.d.ts +14 -14
  313. package/dist/lib/types/adcp.d.ts.map +1 -1
  314. package/dist/lib/types/adcp.js.map +1 -1
  315. package/dist/lib/types/adcp.mjs.map +1 -1
  316. package/dist/lib/types/index.d.mts +2 -2
  317. package/dist/lib/types/index.d.ts +2 -2
  318. package/dist/lib/types/index.d.ts.map +1 -1
  319. package/dist/lib/types/index.js.map +1 -1
  320. package/dist/lib/types/index.mjs.map +1 -1
  321. package/dist/lib/utils/capabilities.d.mts +6 -0
  322. package/dist/lib/utils/capabilities.d.ts +6 -0
  323. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  324. package/dist/lib/utils/capabilities.js +4 -0
  325. package/dist/lib/utils/capabilities.js.map +1 -1
  326. package/dist/lib/utils/capabilities.mjs +4 -0
  327. package/dist/lib/utils/capabilities.mjs.map +1 -1
  328. package/dist/lib/utils/creative-delivery.d.mts +52 -10
  329. package/dist/lib/utils/creative-delivery.d.ts +52 -10
  330. package/dist/lib/utils/creative-delivery.d.ts.map +1 -1
  331. package/dist/lib/utils/creative-delivery.js +104 -9
  332. package/dist/lib/utils/creative-delivery.js.map +1 -1
  333. package/dist/lib/utils/creative-delivery.mjs +104 -8
  334. package/dist/lib/utils/creative-delivery.mjs.map +1 -1
  335. package/dist/lib/utils/format-assets.d.mts +41 -38
  336. package/dist/lib/utils/format-assets.d.ts +41 -38
  337. package/dist/lib/utils/format-assets.d.ts.map +1 -1
  338. package/dist/lib/utils/format-assets.js +3 -1
  339. package/dist/lib/utils/format-assets.js.map +1 -1
  340. package/dist/lib/utils/format-assets.mjs +3 -1
  341. package/dist/lib/utils/format-assets.mjs.map +1 -1
  342. package/dist/lib/utils/index.d.mts +8 -8
  343. package/dist/lib/utils/index.d.ts +8 -8
  344. package/dist/lib/utils/index.d.ts.map +1 -1
  345. package/dist/lib/utils/index.js +11 -9
  346. package/dist/lib/utils/index.js.map +1 -1
  347. package/dist/lib/utils/index.mjs +9 -8
  348. package/dist/lib/utils/index.mjs.map +1 -1
  349. package/dist/lib/utils/preview-utils.d.mts +11 -8
  350. package/dist/lib/utils/preview-utils.d.ts +11 -8
  351. package/dist/lib/utils/preview-utils.d.ts.map +1 -1
  352. package/dist/lib/utils/preview-utils.js +4 -4
  353. package/dist/lib/utils/preview-utils.js.map +1 -1
  354. package/dist/lib/utils/preview-utils.mjs +3 -3
  355. package/dist/lib/utils/preview-utils.mjs.map +1 -1
  356. package/dist/lib/utils/tool-request-schemas.d.mts +2 -2
  357. package/dist/lib/utils/tool-request-schemas.d.ts +2 -2
  358. package/dist/lib/v2/projection/aao-reference-formats.json +492 -0
  359. package/dist/lib/v2/projection/augment-response.d.mts +31 -11
  360. package/dist/lib/v2/projection/augment-response.d.ts +31 -11
  361. package/dist/lib/v2/projection/augment-response.d.ts.map +1 -1
  362. package/dist/lib/v2/projection/augment-response.js +233 -27
  363. package/dist/lib/v2/projection/augment-response.js.map +1 -1
  364. package/dist/lib/v2/projection/augment-response.mjs +232 -27
  365. package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
  366. package/dist/lib/v2/projection/builders.d.mts +7 -6
  367. package/dist/lib/v2/projection/builders.d.ts +7 -6
  368. package/dist/lib/v2/projection/builders.d.ts.map +1 -1
  369. package/dist/lib/v2/projection/builders.js +11 -8
  370. package/dist/lib/v2/projection/builders.js.map +1 -1
  371. package/dist/lib/v2/projection/builders.mjs +9 -6
  372. package/dist/lib/v2/projection/builders.mjs.map +1 -1
  373. package/dist/lib/v2/projection/catalog-snapshot.d.mts +47 -0
  374. package/dist/lib/v2/projection/catalog-snapshot.d.ts +48 -0
  375. package/dist/lib/v2/projection/catalog-snapshot.d.ts.map +1 -0
  376. package/dist/lib/v2/projection/catalog-snapshot.js +291 -0
  377. package/dist/lib/v2/projection/catalog-snapshot.js.map +1 -0
  378. package/dist/lib/v2/projection/catalog-snapshot.mjs +265 -0
  379. package/dist/lib/v2/projection/catalog-snapshot.mjs.map +1 -0
  380. package/dist/lib/v2/projection/catalog.d.mts +23 -2
  381. package/dist/lib/v2/projection/catalog.d.ts +23 -2
  382. package/dist/lib/v2/projection/catalog.d.ts.map +1 -1
  383. package/dist/lib/v2/projection/catalog.js +34 -10
  384. package/dist/lib/v2/projection/catalog.js.map +1 -1
  385. package/dist/lib/v2/projection/catalog.mjs +33 -10
  386. package/dist/lib/v2/projection/catalog.mjs.map +1 -1
  387. package/dist/lib/v2/projection/creative-delivery.d.mts +157 -0
  388. package/dist/lib/v2/projection/creative-delivery.d.ts +158 -0
  389. package/dist/lib/v2/projection/creative-delivery.d.ts.map +1 -0
  390. package/dist/lib/v2/projection/creative-delivery.js +967 -0
  391. package/dist/lib/v2/projection/creative-delivery.js.map +1 -0
  392. package/dist/lib/v2/projection/creative-delivery.mjs +941 -0
  393. package/dist/lib/v2/projection/creative-delivery.mjs.map +1 -0
  394. package/dist/lib/v2/projection/index.d.mts +8 -6
  395. package/dist/lib/v2/projection/index.d.ts +8 -6
  396. package/dist/lib/v2/projection/index.d.ts.map +1 -1
  397. package/dist/lib/v2/projection/index.js +26 -4
  398. package/dist/lib/v2/projection/index.js.map +1 -1
  399. package/dist/lib/v2/projection/index.mjs +28 -4
  400. package/dist/lib/v2/projection/index.mjs.map +1 -1
  401. package/dist/lib/v2/projection/legacy-metadata.d.mts +21 -0
  402. package/dist/lib/v2/projection/legacy-metadata.d.ts +22 -0
  403. package/dist/lib/v2/projection/legacy-metadata.d.ts.map +1 -0
  404. package/dist/lib/v2/projection/legacy-metadata.js +73 -0
  405. package/dist/lib/v2/projection/legacy-metadata.js.map +1 -0
  406. package/dist/lib/v2/projection/legacy-metadata.mjs +45 -0
  407. package/dist/lib/v2/projection/legacy-metadata.mjs.map +1 -0
  408. package/dist/lib/v2/projection/types.d.mts +29 -23
  409. package/dist/lib/v2/projection/types.d.ts +29 -23
  410. package/dist/lib/v2/projection/types.d.ts.map +1 -1
  411. package/dist/lib/v2/projection/types.js.map +1 -1
  412. package/dist/lib/v2/projection/v1-to-v2.d.mts +29 -6
  413. package/dist/lib/v2/projection/v1-to-v2.d.ts +29 -6
  414. package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
  415. package/dist/lib/v2/projection/v1-to-v2.js +218 -9
  416. package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
  417. package/dist/lib/v2/projection/v1-to-v2.mjs +219 -10
  418. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  419. package/dist/lib/v2/projection/v2-to-v1.d.mts +31 -2
  420. package/dist/lib/v2/projection/v2-to-v1.d.ts +31 -2
  421. package/dist/lib/v2/projection/v2-to-v1.d.ts.map +1 -1
  422. package/dist/lib/v2/projection/v2-to-v1.js +138 -7
  423. package/dist/lib/v2/projection/v2-to-v1.js.map +1 -1
  424. package/dist/lib/v2/projection/v2-to-v1.mjs +135 -6
  425. package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
  426. package/dist/lib/v2/projection/write-side.d.mts +12 -13
  427. package/dist/lib/v2/projection/write-side.d.ts +12 -13
  428. package/dist/lib/v2/projection/write-side.d.ts.map +1 -1
  429. package/dist/lib/v2/projection/write-side.js +16 -12
  430. package/dist/lib/v2/projection/write-side.js.map +1 -1
  431. package/dist/lib/v2/projection/write-side.mjs +16 -12
  432. package/dist/lib/v2/projection/write-side.mjs.map +1 -1
  433. package/dist/lib/version.d.mts +3 -3
  434. package/dist/lib/version.d.ts +3 -3
  435. package/dist/lib/version.d.ts.map +1 -1
  436. package/dist/lib/version.js +3 -3
  437. package/dist/lib/version.js.map +1 -1
  438. package/dist/lib/version.mjs +3 -3
  439. package/dist/lib/version.mjs.map +1 -1
  440. package/docs/guides/BUILD-AN-AGENT.md +7 -2
  441. package/docs/guides/PREVIEW-ASSET-DURABILITY.md +6 -2
  442. package/docs/llms.txt +1 -0
  443. package/examples/README.md +1 -1
  444. package/examples/batch-preview-test.ts +3 -3
  445. package/examples/conversation-client.ts +2 -2
  446. package/examples/debug-preview-response.ts +1 -1
  447. package/examples/decisioning-platform-broadcast-tv.ts +10 -4
  448. package/examples/decisioning-platform-mock-seller.ts +16 -9
  449. package/examples/decisioning-platform-programmatic.ts +18 -7
  450. package/examples/error-compliant-server.ts +26 -16
  451. package/examples/generative-creative-demo.ts +7 -19
  452. package/examples/hello_creative_adapter_ad_server.ts +37 -16
  453. package/examples/hello_creative_adapter_template.ts +12 -10
  454. package/examples/hello_seller_adapter_guaranteed.ts +52 -23
  455. package/examples/hello_seller_adapter_multi_tenant.ts +6 -3
  456. package/examples/hello_seller_adapter_non_guaranteed.ts +54 -26
  457. package/examples/hello_seller_adapter_proposal_mode.ts +40 -14
  458. package/examples/hello_seller_adapter_social.ts +2 -7
  459. package/examples/inspect-card-formats.ts +1 -1
  460. package/examples/simple-getting-started.ts +1 -1
  461. package/examples/test-helpers-demo.ts +1 -1
  462. package/package.json +2 -2
  463. package/skills/build-decisioning-creative-template/SKILL.md +11 -11
  464. package/skills/build-decisioning-platform/advanced/REFERENCE.md +8 -2
@@ -57,6 +57,7 @@ import {
57
57
  TASK_FEATURE_MAP
58
58
  } from "../utils/capabilities.mjs";
59
59
  import { normalizeRequestParams } from "../utils/request-normalizer.mjs";
60
+ import { globalAsyncLocalStorage } from "../utils/global-async-local-storage.mjs";
60
61
  import { validateUserAgent } from "../utils/validate-user-agent.mjs";
61
62
  import { resolveWebhookUrl, selectWebhookTemplate } from "./webhook-url.mjs";
62
63
  import { getV25Adapter } from "../adapters/legacy/v2-5/index.mjs";
@@ -65,6 +66,388 @@ import {
65
66
  validateProductsAgainstPropertyPolicy
66
67
  } from "../media-buy/property-policy.mjs";
67
68
  import { resolvePropertyList } from "../server/targeting-helpers.mjs";
69
+ import {
70
+ CreativeFormatCapabilityError,
71
+ CreativeFormatProjectionError,
72
+ projectMediaBuyCreativesForDelivery,
73
+ projectCreativeForDelivery,
74
+ projectSyncCreativesForDelivery,
75
+ resolveCreativeFormatWireMode,
76
+ stripLegacyCreativeIdentity
77
+ } from "../v2/projection/creative-delivery.mjs";
78
+ import {
79
+ legacyFormatConverterFromCatalogSnapshots
80
+ } from "../v2/projection/catalog-snapshot.mjs";
81
+ import { toCanonicalOnlyResponse } from "../v2/projection/augment-response.mjs";
82
+ import { legacyFormatRefsForDeclaration } from "../v2/projection/legacy-metadata.mjs";
83
+ import { canonicalize as canonicalizeJson } from "../utils/jcs.mjs";
84
+ const CAPABILITY_DISCOVERY_CONTEXT = /* @__PURE__ */ Symbol("capabilityDiscoveryContext");
85
+ function creativeSchemaSupport(value, depth = 0) {
86
+ if (depth > 24 || value === null || typeof value !== "object") return "unknown";
87
+ if (Array.isArray(value)) {
88
+ let legacy2 = false;
89
+ for (const item of value) {
90
+ const support = creativeSchemaSupport(item, depth + 1);
91
+ if (support === "canonical") return support;
92
+ if (support === "legacy") legacy2 = true;
93
+ }
94
+ return legacy2 ? "legacy" : "unknown";
95
+ }
96
+ const object = value;
97
+ const properties = object.properties;
98
+ if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
99
+ const keys = properties;
100
+ if ("creative_id" in keys && "format_kind" in keys) return "canonical";
101
+ if ("creative_id" in keys && "format_id" in keys) return "legacy";
102
+ }
103
+ let legacy = false;
104
+ for (const child of Object.values(object)) {
105
+ const support = creativeSchemaSupport(child, depth + 1);
106
+ if (support === "canonical") return support;
107
+ if (support === "legacy") legacy = true;
108
+ }
109
+ return legacy ? "legacy" : "unknown";
110
+ }
111
+ function hasMediaBuyCreativeFormatData(request) {
112
+ if (request === null || typeof request !== "object" || Array.isArray(request)) return false;
113
+ const record = request;
114
+ return ["packages", "new_packages"].some((key) => {
115
+ const packages = record[key];
116
+ return Array.isArray(packages) && packages.some((pkg) => {
117
+ if (pkg === null || typeof pkg !== "object" || Array.isArray(pkg)) return false;
118
+ const packageRecord = pkg;
119
+ return Array.isArray(packageRecord.creatives) || Array.isArray(packageRecord.format_option_refs) || Array.isArray(packageRecord.format_ids) || typeof packageRecord.format_kind === "string" || Object.getOwnPropertySymbols(packageRecord).length > 0;
120
+ });
121
+ });
122
+ }
123
+ const CANONICAL_CREATIVE_ACTIVITY_TASKS = /* @__PURE__ */ new Set([
124
+ "get_products",
125
+ "create_media_buy",
126
+ "update_media_buy",
127
+ "sync_creatives",
128
+ "list_creatives",
129
+ "get_media_buys",
130
+ "get_media_buy_delivery",
131
+ "get_creative_delivery"
132
+ ]);
133
+ const TASK_SCOPED_STATE_LIMIT = 1e4;
134
+ const CANONICAL_PACKAGE_ROUTE_TASKS = /* @__PURE__ */ new Set(["create_media_buy", "update_media_buy", "get_media_buys"]);
135
+ const canonicalCreativeRoutingSnapshots = /* @__PURE__ */ new WeakSet();
136
+ function canonicalAccountRoutingSnapshot(value) {
137
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
138
+ const account = value;
139
+ if (typeof account.account_id === "string") return Object.freeze({ account_id: account.account_id });
140
+ if (!account.brand || typeof account.brand !== "object" || Array.isArray(account.brand) || typeof account.operator !== "string") {
141
+ return void 0;
142
+ }
143
+ const sourceBrand = account.brand;
144
+ if (typeof sourceBrand.domain !== "string") return void 0;
145
+ const brand = Object.freeze({
146
+ domain: sourceBrand.domain,
147
+ ...typeof sourceBrand.brand_id === "string" ? { brand_id: sourceBrand.brand_id } : {}
148
+ });
149
+ return Object.freeze({
150
+ brand,
151
+ operator: account.operator,
152
+ ...typeof account.sandbox === "boolean" ? { sandbox: account.sandbox } : {}
153
+ });
154
+ }
155
+ function canonicalOptionRefRoutingSnapshot(value) {
156
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
157
+ const ref = value;
158
+ if (typeof ref.format_option_id !== "string") return void 0;
159
+ if (ref.scope === "publisher" || typeof ref.publisher_domain === "string") {
160
+ if (typeof ref.publisher_domain !== "string") return void 0;
161
+ return Object.freeze({
162
+ scope: "publisher",
163
+ publisher_domain: ref.publisher_domain,
164
+ format_option_id: ref.format_option_id
165
+ });
166
+ }
167
+ return Object.freeze({ scope: "product", format_option_id: ref.format_option_id });
168
+ }
169
+ function canonicalPackageRouteSelectorSnapshot(value) {
170
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
171
+ const selector = value;
172
+ const formatOptionRefs = Array.isArray(selector.format_option_refs) ? selector.format_option_refs.map(canonicalOptionRefRoutingSnapshot).filter((ref) => ref !== void 0) : [];
173
+ const snapshot = {
174
+ ...typeof selector.package_id === "string" ? { package_id: selector.package_id } : {},
175
+ ...typeof selector.product_id === "string" ? { product_id: selector.product_id } : {},
176
+ ...formatOptionRefs.length > 0 ? { format_option_refs: Object.freeze(formatOptionRefs) } : {}
177
+ };
178
+ return Object.keys(snapshot).length > 0 ? Object.freeze(snapshot) : void 0;
179
+ }
180
+ function canonicalCreativeRoutingSnapshot(taskType, request) {
181
+ if (!CANONICAL_PACKAGE_ROUTE_TASKS.has(taskType) || !request || typeof request !== "object" || Array.isArray(request)) {
182
+ return void 0;
183
+ }
184
+ if (canonicalCreativeRoutingSnapshots.has(request)) {
185
+ return request;
186
+ }
187
+ const record = request;
188
+ const account = canonicalAccountRoutingSnapshot(record.account);
189
+ if (!account) return void 0;
190
+ const packageSnapshots = (key) => Object.freeze(
191
+ (Array.isArray(record[key]) ? record[key] : []).map(canonicalPackageRouteSelectorSnapshot).filter((selector) => selector !== void 0)
192
+ );
193
+ const packages = packageSnapshots("packages");
194
+ const newPackages = packageSnapshots("new_packages");
195
+ const snapshot = Object.freeze({
196
+ account,
197
+ ...packages.length > 0 ? { packages } : {},
198
+ ...newPackages.length > 0 ? { new_packages: newPackages } : {}
199
+ });
200
+ canonicalCreativeRoutingSnapshots.add(snapshot);
201
+ return snapshot;
202
+ }
203
+ const canonicalCreativeExecutionStorage = globalAsyncLocalStorage("canonicalCreativeExecution");
204
+ function prepareCanonicalCreativePayload(value, taskType, active = /* @__PURE__ */ new WeakSet(), prepared = /* @__PURE__ */ new WeakMap()) {
205
+ if (value === null || typeof value !== "object") return value;
206
+ for (let owner = value; owner !== null; owner = Object.getPrototypeOf(owner)) {
207
+ const toJSON = Object.getOwnPropertyDescriptor(owner, "toJSON");
208
+ if (toJSON && (!("value" in toJSON) || typeof toJSON.value === "function")) {
209
+ throw new CreativeFormatProjectionError(
210
+ taskType,
211
+ "(response:toJSON)",
212
+ "custom or accessor toJSON hooks cannot cross the canonical creative boundary safely"
213
+ );
214
+ }
215
+ }
216
+ if (active.has(value)) {
217
+ throw new CreativeFormatProjectionError(
218
+ taskType,
219
+ "(response:cycle)",
220
+ "cyclic values cannot cross the canonical creative boundary"
221
+ );
222
+ }
223
+ const cached = prepared.get(value);
224
+ if (cached !== void 0) return cached;
225
+ active.add(value);
226
+ try {
227
+ const isArray = Array.isArray(value);
228
+ const prototype = Object.getPrototypeOf(value);
229
+ const plain = isArray ? prototype === Array.prototype : prototype === Object.prototype || prototype === null;
230
+ const output = isArray ? [] : Object.create(prototype === null ? null : Object.prototype);
231
+ prepared.set(value, output);
232
+ let changed = !plain;
233
+ for (const key of Reflect.ownKeys(value)) {
234
+ if (isArray && key === "length") continue;
235
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
236
+ if (!descriptor) continue;
237
+ if (!("value" in descriptor)) {
238
+ throw new CreativeFormatProjectionError(
239
+ taskType,
240
+ `(response:${String(key)})`,
241
+ "accessors cannot cross the canonical creative boundary safely"
242
+ );
243
+ }
244
+ if (!descriptor.enumerable) continue;
245
+ const safe = prepareCanonicalCreativePayload(descriptor.value, taskType, active, prepared);
246
+ if (safe !== descriptor.value) changed = true;
247
+ Object.defineProperty(output, key, { ...descriptor, value: safe });
248
+ }
249
+ if (!changed) {
250
+ prepared.set(value, value);
251
+ return value;
252
+ }
253
+ return output;
254
+ } finally {
255
+ active.delete(value);
256
+ }
257
+ }
258
+ function projectPreparedCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter, selectorContainer = {}) {
259
+ if (Array.isArray(value)) {
260
+ return value.map(
261
+ (item) => projectPreparedCanonicalCreativeResponseValue(item, taskType, legacyFormatConverter, selectorContainer)
262
+ );
263
+ }
264
+ if (!value || typeof value !== "object") return value;
265
+ let projected = value;
266
+ const isProduct = typeof projected.product_id === "string" && ("name" in projected || "description" in projected) && (Array.isArray(projected.format_ids) || Array.isArray(projected.format_options));
267
+ if (isProduct) {
268
+ const canonical = toCanonicalOnlyResponse(
269
+ { products: [projected] },
270
+ { legacyFormatConverter }
271
+ );
272
+ if (canonical.diagnostics.length > 0 || canonical.response.products.length !== 1) {
273
+ throw new CreativeFormatProjectionError(
274
+ taskType,
275
+ `(product:${String(projected.product_id)})`,
276
+ "legacy product formats in the response have no complete canonical representation"
277
+ );
278
+ }
279
+ projected = canonical.response.products[0];
280
+ } else if ((typeof projected.package_id === "string" || typeof projected.product_id === "string") && Array.isArray(projected.format_ids)) {
281
+ projected = projectMediaBuyCreativesForDelivery(
282
+ { packages: [projected] },
283
+ "canonical",
284
+ taskType === "update_media_buy" ? "update_media_buy" : "create_media_buy",
285
+ legacyFormatConverter
286
+ ).packages[0];
287
+ }
288
+ if (typeof projected.creative_id === "string" && (projected.format_id !== void 0 || typeof projected.format_kind === "string")) {
289
+ projected = projectCreativeForDelivery(
290
+ projected,
291
+ selectorContainer,
292
+ "canonical",
293
+ taskType,
294
+ legacyFormatConverter
295
+ );
296
+ }
297
+ const nextSelector = Array.isArray(projected.format_ids) || Array.isArray(projected.format_options) || Array.isArray(projected.format_option_refs) ? projected : selectorContainer;
298
+ let changed = projected !== value;
299
+ const next = { ...projected };
300
+ for (const [key, child] of Object.entries(projected)) {
301
+ const childProjected = projectPreparedCanonicalCreativeResponseValue(
302
+ child,
303
+ taskType,
304
+ legacyFormatConverter,
305
+ nextSelector
306
+ );
307
+ if (childProjected !== child) {
308
+ next[key] = childProjected;
309
+ changed = true;
310
+ }
311
+ }
312
+ return changed ? next : projected;
313
+ }
314
+ function projectCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter, selectorContainer = {}) {
315
+ return projectPreparedCanonicalCreativeResponseValue(
316
+ prepareCanonicalCreativePayload(value, taskType),
317
+ taskType,
318
+ legacyFormatConverter,
319
+ selectorContainer
320
+ );
321
+ }
322
+ function projectCanonicalCreativeAncillaryValue(value, taskType, legacyFormatConverter) {
323
+ try {
324
+ return stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter));
325
+ } catch (error) {
326
+ if (!(error instanceof CreativeFormatProjectionError)) throw error;
327
+ return { omitted: true, reason: "canonical creative payload unavailable" };
328
+ }
329
+ }
330
+ function canonicalCreativeActivity(activity) {
331
+ const active = canonicalCreativeExecutionStorage.getStore();
332
+ const effectiveTaskType = active?.taskType && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(active.taskType) ? active.taskType : activity.task_type;
333
+ if (!CANONICAL_CREATIVE_ACTIVITY_TASKS.has(effectiveTaskType) || activity.payload === void 0) {
334
+ return activity;
335
+ }
336
+ const converter = active?.taskType === effectiveTaskType ? active.legacyFormatConverter : void 0;
337
+ const source = activity.type === "protocol_request" && active?.taskType === effectiveTaskType && active.canonicalRequest !== void 0 ? { params: active.canonicalRequest } : activity.payload;
338
+ try {
339
+ return {
340
+ ...activity,
341
+ payload: stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(source, effectiveTaskType, converter))
342
+ };
343
+ } catch (error) {
344
+ if (!(error instanceof CreativeFormatProjectionError)) throw error;
345
+ return { ...activity, payload: { omitted: true, reason: "canonical creative payload unavailable" } };
346
+ }
347
+ }
348
+ function canonicalCreativeDiagnosticBody(body, taskType) {
349
+ if (body === void 0) return void 0;
350
+ try {
351
+ const active = canonicalCreativeExecutionStorage.getStore();
352
+ const converter = active?.taskType === taskType ? active.legacyFormatConverter : void 0;
353
+ return JSON.stringify(
354
+ stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(JSON.parse(body), taskType, converter))
355
+ );
356
+ } catch {
357
+ return "[canonical creative payload omitted]";
358
+ }
359
+ }
360
+ function canonicalCreativeTransportActivity(event) {
361
+ const active = canonicalCreativeExecutionStorage.getStore();
362
+ const taskType = active?.taskType && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(active.taskType) ? active.taskType : event.taskType ?? event.tool;
363
+ if (!taskType || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) return event;
364
+ return {
365
+ ...event,
366
+ ...event.requestBody !== void 0 && {
367
+ requestBody: canonicalCreativeDiagnosticBody(event.requestBody, taskType)
368
+ },
369
+ ...event.responseBody !== void 0 && {
370
+ responseBody: canonicalCreativeDiagnosticBody(event.responseBody, taskType)
371
+ }
372
+ };
373
+ }
374
+ function canonicalCreativeErrorInstance(error, legacySource) {
375
+ const own = {};
376
+ const descriptors = Object.getOwnPropertyDescriptors(error);
377
+ for (const [key, descriptor] of Object.entries(descriptors)) {
378
+ if ("value" in descriptor) own[key] = descriptor.value;
379
+ }
380
+ const { legacySource: _dropLegacySource, own: safeOwn } = stripLegacyCreativeIdentity({ own, legacySource });
381
+ void _dropLegacySource;
382
+ const clone = Object.create(Object.getPrototypeOf(error));
383
+ for (const [key, value] of Object.entries(safeOwn)) {
384
+ const descriptor = descriptors[key];
385
+ if (!descriptor || !("value" in descriptor)) continue;
386
+ Object.defineProperty(clone, key, { ...descriptor, value });
387
+ }
388
+ for (const symbol of Object.getOwnPropertySymbols(error)) {
389
+ const descriptor = Object.getOwnPropertyDescriptor(error, symbol);
390
+ if (!descriptor || !("value" in descriptor)) continue;
391
+ const safe = stripLegacyCreativeIdentity({ value: descriptor.value, legacySource });
392
+ Object.defineProperty(clone, symbol, { ...descriptor, value: safe.value });
393
+ }
394
+ return stripLegacyCreativeIdentity(clone);
395
+ }
396
+ const PRIMARY_ADCP_TASK_NAMES = {
397
+ get_products: true,
398
+ create_media_buy: true,
399
+ update_media_buy: true,
400
+ sync_creatives: true,
401
+ list_creatives: true,
402
+ get_media_buys: true,
403
+ get_media_buy_delivery: true,
404
+ get_creative_delivery: true,
405
+ provide_performance_feedback: true,
406
+ get_signals: true,
407
+ activate_signal: true,
408
+ get_adcp_capabilities: true,
409
+ list_accounts: true,
410
+ sync_accounts: true,
411
+ sync_audiences: true,
412
+ create_property_list: true,
413
+ get_property_list: true,
414
+ update_property_list: true,
415
+ list_property_lists: true,
416
+ delete_property_list: true,
417
+ si_get_offering: true,
418
+ si_initiate_session: true,
419
+ si_send_message: true,
420
+ si_terminate_session: true,
421
+ get_brand_identity: true,
422
+ sync_plans: true,
423
+ check_governance: true,
424
+ report_plan_outcome: true,
425
+ get_plan_audit_logs: true,
426
+ context_match: true,
427
+ identity_match: true
428
+ };
429
+ const STANDARD_ADCP_TASK_NAMES = /* @__PURE__ */ new Set([
430
+ ...Object.keys(PRIMARY_ADCP_TASK_NAMES),
431
+ "list_creative_formats",
432
+ "list_transformers",
433
+ "preview_creative",
434
+ "build_creative",
435
+ // These standard protocol tools still carry legacy creative `format_id`
436
+ // identity through artifacts, manifests, standards, or rights constraints.
437
+ // They are available only through explicitly named *Legacy APIs until a
438
+ // lossless canonical projection exists.
439
+ "list_content_standards",
440
+ "get_content_standards",
441
+ "create_content_standards",
442
+ "update_content_standards",
443
+ "calibrate_content",
444
+ "validate_content_delivery",
445
+ "get_media_buy_artifacts",
446
+ "get_creative_features",
447
+ "get_rights",
448
+ "acquire_rights",
449
+ "update_rights"
450
+ ]);
68
451
  class UnsupportedFeatureError extends Error {
69
452
  constructor(feature, serverVersion, message) {
70
453
  super(message || `Feature '${feature}' requires AdCP v3 but server is ${serverVersion}`);
@@ -135,6 +518,14 @@ function propertyListReferenceFromRequest(params) {
135
518
  ...typeof ref.auth_token === "string" ? { auth_token: ref.auth_token } : {}
136
519
  };
137
520
  }
521
+ function productPolicyRequestSnapshot(requestParams) {
522
+ const account = canonicalAccountRoutingSnapshot(requestParams.account);
523
+ const propertyList = propertyListReferenceFromRequest(requestParams);
524
+ return Object.freeze({
525
+ ...account ? { account } : {},
526
+ ...propertyList ? { property_list: Object.freeze(propertyList) } : {}
527
+ });
528
+ }
138
529
  function hasProductPropertyPolicyRules(policy) {
139
530
  return Boolean(
140
531
  policy.allowedDomains?.length || policy.allowedPropertyIdentifiers?.length || policy.requireAllowedPropertyMatch || policy.excludedDomains?.length || policy.excludedPropertyIds?.length || policy.strict || policy.unknownSelectorBehavior || policy.missingPublisherPropertiesBehavior
@@ -195,8 +586,8 @@ class SingleAgentClient {
195
586
  ...config.validation?.requests != null && { requests: config.validation.requests },
196
587
  ...config.validation?.responses != null && { responses: config.validation.responses }
197
588
  },
198
- onActivity: config.onActivity,
199
- onTransportActivity: config.onTransportActivity,
589
+ onActivity: config.onActivity ? (activity) => config.onActivity(canonicalCreativeActivity(activity)) : void 0,
590
+ onTransportActivity: config.onTransportActivity ? (event) => config.onTransportActivity(canonicalCreativeTransportActivity(event)) : void 0,
200
591
  governance: config.governance,
201
592
  adcpVersion: this.resolvedAdcpVersion,
202
593
  ...config.wireAdcpVersion !== void 0 && { wireAdcpVersion: config.wireAdcpVersion },
@@ -231,7 +622,237 @@ class SingleAgentClient {
231
622
  _syntheticV2WarningFired = false;
232
623
  // Gate: emit the synthetic-v2 warning once per client instance
233
624
  productPolicyRequestParamsByTask = /* @__PURE__ */ new Map();
625
+ canonicalCreativeTaskAssociations = /* @__PURE__ */ new Map();
626
+ canonicalLegacyRoutes = /* @__PURE__ */ new Map();
234
627
  resolvedAdcpVersion;
628
+ resolveLegacyFormatConverter(override, projectionCatalogs = this.config.projectionCatalogs) {
629
+ return legacyFormatConverterFromCatalogSnapshots(projectionCatalogs, override ?? this.config.legacyFormatConverter);
630
+ }
631
+ canonicalAccountScope(account) {
632
+ if (account === void 0) return "none";
633
+ return canonicalizeJson(canonicalAccountRoutingSnapshot(account) ?? account);
634
+ }
635
+ canonicalLegacyRouteKey(account, productId, ref) {
636
+ return canonicalizeJson([
637
+ this.canonicalAccountScope(account),
638
+ productId,
639
+ ref.scope,
640
+ ref.scope === "publisher" ? ref.publisher_domain.toLowerCase() : "",
641
+ ref.format_option_id
642
+ ]);
643
+ }
644
+ canonicalLegacyPackageRouteKey(account, packageId) {
645
+ return canonicalizeJson([this.canonicalAccountScope(account), "package", packageId]);
646
+ }
647
+ sameCanonicalOptionRef(left, right) {
648
+ return left.scope === right.scope && left.format_option_id === right.format_option_id && (left.scope !== "publisher" || right.scope === "publisher" && left.publisher_domain.toLowerCase() === right.publisher_domain.toLowerCase());
649
+ }
650
+ rememberCanonicalLegacyRoute(key, route) {
651
+ this.canonicalLegacyRoutes.delete(key);
652
+ this.canonicalLegacyRoutes.set(key, {
653
+ ...route,
654
+ refs: Object.freeze(route.refs.map((ref) => Object.freeze({ ...ref })))
655
+ });
656
+ while (this.canonicalLegacyRoutes.size > TASK_SCOPED_STATE_LIMIT) {
657
+ const oldest = this.canonicalLegacyRoutes.keys().next().value;
658
+ if (oldest === void 0) break;
659
+ this.canonicalLegacyRoutes.delete(oldest);
660
+ }
661
+ }
662
+ invalidateCanonicalProductRoutes(products, account) {
663
+ const accountScope = this.canonicalAccountScope(account);
664
+ const productIds = /* @__PURE__ */ new Set();
665
+ for (const value of products) {
666
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
667
+ const productId = value.product_id;
668
+ if (typeof productId === "string") productIds.add(productId);
669
+ }
670
+ if (productIds.size === 0) return;
671
+ for (const [key, route] of this.canonicalLegacyRoutes) {
672
+ if (route.kind === "product" && route.accountScope === accountScope && productIds.has(route.productId)) {
673
+ this.canonicalLegacyRoutes.delete(key);
674
+ }
675
+ }
676
+ }
677
+ rememberCanonicalProductRoutes(products, account, authoritativeProducts = products) {
678
+ this.invalidateCanonicalProductRoutes(authoritativeProducts, account);
679
+ const accountScope = this.canonicalAccountScope(account);
680
+ for (const value of products) {
681
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
682
+ const product = value;
683
+ if (typeof product.product_id !== "string" || !Array.isArray(product.format_options)) continue;
684
+ for (const optionValue of product.format_options) {
685
+ if (!optionValue || typeof optionValue !== "object" || Array.isArray(optionValue)) continue;
686
+ const option = optionValue;
687
+ if (typeof option.format_option_id !== "string") continue;
688
+ const ref = typeof option.publisher_domain === "string" ? {
689
+ scope: "publisher",
690
+ publisher_domain: option.publisher_domain,
691
+ format_option_id: option.format_option_id
692
+ } : { scope: "product", format_option_id: option.format_option_id };
693
+ const refs = legacyFormatRefsForDeclaration(option);
694
+ if (refs.length === 0) continue;
695
+ this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
696
+ kind: "product",
697
+ accountScope,
698
+ productId: product.product_id,
699
+ optionRef: ref,
700
+ refs
701
+ });
702
+ }
703
+ }
704
+ }
705
+ routeForOption(account, productId, optionRef) {
706
+ const accountScope = this.canonicalAccountScope(account);
707
+ const exactKey = this.canonicalLegacyRouteKey(account, productId, optionRef);
708
+ const exact = this.canonicalLegacyRoutes.get(exactKey);
709
+ if (exact) {
710
+ this.canonicalLegacyRoutes.delete(exactKey);
711
+ this.canonicalLegacyRoutes.set(exactKey, exact);
712
+ return exact;
713
+ }
714
+ const candidates = [...this.canonicalLegacyRoutes.entries()].filter(
715
+ ([, route]) => route.kind === "product" && route.productId === productId && this.sameCanonicalOptionRef(route.optionRef, optionRef)
716
+ );
717
+ if (candidates.length !== 1) return void 0;
718
+ const [key, candidate] = candidates[0];
719
+ if (accountScope === "none" || candidate.accountScope !== "none") return void 0;
720
+ this.canonicalLegacyRoutes.delete(key);
721
+ this.canonicalLegacyRoutes.set(key, candidate);
722
+ return candidate;
723
+ }
724
+ routeForPackage(account, packageId) {
725
+ const exactKey = this.canonicalLegacyPackageRouteKey(account, packageId);
726
+ const exact = this.canonicalLegacyRoutes.get(exactKey);
727
+ if (exact) {
728
+ this.canonicalLegacyRoutes.delete(exactKey);
729
+ this.canonicalLegacyRoutes.set(exactKey, exact);
730
+ return exact;
731
+ }
732
+ return void 0;
733
+ }
734
+ packageIdsFromSelector(selector) {
735
+ const ids = /* @__PURE__ */ new Set();
736
+ if (typeof selector.package_id === "string") ids.add(selector.package_id);
737
+ if (Array.isArray(selector.selector_containers)) {
738
+ for (const value of selector.selector_containers) {
739
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
740
+ for (const id of this.packageIdsFromSelector(value)) ids.add(id);
741
+ }
742
+ }
743
+ return [...ids];
744
+ }
745
+ cachedCanonicalLegacyRefs(context, account) {
746
+ const selector = context.source === "product" ? context.declaration : context.source === "creative" ? context.selector : context.selector;
747
+ const productId = context.source === "product" ? context.productId : typeof selector.product_id === "string" ? selector.product_id : void 0;
748
+ if (!productId) {
749
+ const packageIds = this.packageIdsFromSelector(selector);
750
+ if (packageIds.length === 0) return void 0;
751
+ const routes = packageIds.map((packageId) => this.routeForPackage(account, packageId));
752
+ if (routes.some((route) => route === void 0)) return void 0;
753
+ const normalized = routes.map(
754
+ (route) => canonicalizeJson(
755
+ route.refs.map((ref) => ({ ...ref })).sort((left, right) => canonicalizeJson(left).localeCompare(canonicalizeJson(right)))
756
+ )
757
+ );
758
+ if (!normalized.every((value) => value === normalized[0])) return void 0;
759
+ return routes[0].refs.map((value) => ({ ...value }));
760
+ }
761
+ const rawRefs = [];
762
+ if (context.source === "product") rawRefs.push(context.declaration);
763
+ if (context.source === "creative" && context.creative.format_option_ref !== void 0) {
764
+ rawRefs.push(context.creative.format_option_ref);
765
+ } else if (Array.isArray(selector.format_option_refs)) {
766
+ rawRefs.push(...selector.format_option_refs);
767
+ }
768
+ const optionRefs = [];
769
+ for (const value of rawRefs) {
770
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
771
+ const record = value;
772
+ if (typeof record.format_option_id !== "string") continue;
773
+ if (record.scope === "publisher" || typeof record.publisher_domain === "string") {
774
+ if (typeof record.publisher_domain !== "string") continue;
775
+ optionRefs.push({
776
+ scope: "publisher",
777
+ publisher_domain: record.publisher_domain,
778
+ format_option_id: record.format_option_id
779
+ });
780
+ } else {
781
+ optionRefs.push({ scope: "product", format_option_id: record.format_option_id });
782
+ }
783
+ }
784
+ if (optionRefs.length === 0) return void 0;
785
+ const resolved = [];
786
+ for (const ref of optionRefs) {
787
+ const route = this.routeForOption(account, productId, ref);
788
+ if (!route) return void 0;
789
+ resolved.push(...route.refs.map((value) => ({ ...value })));
790
+ }
791
+ return resolved;
792
+ }
793
+ rememberCanonicalPackageRoutes(response, request) {
794
+ if (!response || typeof response !== "object" || Array.isArray(response)) return;
795
+ const requestRecord = request && typeof request === "object" && !Array.isArray(request) ? request : void 0;
796
+ const account = requestRecord?.account;
797
+ if (account === void 0) return;
798
+ const accountScope = this.canonicalAccountScope(account);
799
+ const requestPackages = ["packages", "new_packages"].flatMap(
800
+ (key) => Array.isArray(requestRecord?.[key]) ? requestRecord[key].filter(
801
+ (value) => Boolean(value && typeof value === "object" && !Array.isArray(value))
802
+ ) : []
803
+ );
804
+ const responsePackages = [];
805
+ const visit = (value, depth = 0) => {
806
+ if (depth > 8 || !value || typeof value !== "object") return;
807
+ if (Array.isArray(value)) {
808
+ for (const item of value) visit(item, depth + 1);
809
+ return;
810
+ }
811
+ const record = value;
812
+ if (typeof record.package_id === "string") responsePackages.push(record);
813
+ for (const key of ["packages", "affected_packages", "media_buys"]) {
814
+ if (record[key] !== void 0) visit(record[key], depth + 1);
815
+ }
816
+ };
817
+ visit(response);
818
+ for (const pkg of responsePackages) {
819
+ const packageId = pkg.package_id;
820
+ let selector = pkg;
821
+ let refs = this.cachedCanonicalLegacyRefs(
822
+ { source: "selector", selector, operation: "package_route", field: packageId },
823
+ account
824
+ );
825
+ if (!refs) {
826
+ const byPackageId = requestPackages.filter((value) => value.package_id === packageId);
827
+ const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
828
+ const byProduct = productId ? requestPackages.filter((value) => value.product_id === productId) : [];
829
+ const matches = byPackageId.length === 1 ? byPackageId : byProduct.length === 1 ? byProduct : [];
830
+ selector = matches[0];
831
+ if (selector) {
832
+ refs = this.cachedCanonicalLegacyRefs(
833
+ { source: "selector", selector, operation: "package_route", field: packageId },
834
+ account
835
+ );
836
+ }
837
+ }
838
+ if (!refs || refs.length === 0) continue;
839
+ this.rememberCanonicalLegacyRoute(this.canonicalLegacyPackageRouteKey(account, packageId), {
840
+ kind: "package",
841
+ accountScope,
842
+ packageId,
843
+ refs
844
+ });
845
+ }
846
+ }
847
+ rememberCanonicalPackageRoutesForTask(taskType, response, request) {
848
+ if (taskType === "create_media_buy" || taskType === "update_media_buy" || taskType === "get_media_buys") {
849
+ this.rememberCanonicalPackageRoutes(response, request);
850
+ }
851
+ }
852
+ resolveCanonicalFormatLegacyResolver(override, account) {
853
+ const configured = this.config.canonicalFormatLegacyResolver;
854
+ return (context) => override?.(context) ?? this.cachedCanonicalLegacyRefs(context, account) ?? configured?.(context);
855
+ }
235
856
  /**
236
857
  * Returns the AdCP protocol version this client is configured to speak.
237
858
  *
@@ -255,25 +876,52 @@ class SingleAgentClient {
255
876
  async ensureEndpointDiscovered(options) {
256
877
  throwIfAborted(options?.signal);
257
878
  const needsDiscovery = this.normalizedAgent._needsDiscovery;
879
+ const transport = options?.transport ?? this.config.transport;
880
+ const usesScopedFetch = transport?.fetchFn !== void 0;
258
881
  if (!needsDiscovery) {
259
882
  return this.normalizedAgent;
260
883
  }
261
- if (this.discoveredAgent) {
884
+ if (!usesScopedFetch && this.discoveredAgent) {
262
885
  return this.discoveredAgent;
263
886
  }
264
- if (this.discoveredEndpoint) {
887
+ if (!usesScopedFetch && this.discoveredEndpoint) {
265
888
  this.discoveredAgent = {
266
889
  ...this.normalizedAgent,
267
890
  agent_uri: this.discoveredEndpoint
268
891
  };
892
+ if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
893
+ const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
894
+ shareNonInteractiveOAuthProvider(this.normalizedAgent, this.discoveredAgent);
895
+ }
269
896
  return this.discoveredAgent;
270
897
  }
271
- this.discoveredEndpoint = await this.discoverMCPEndpoint(this.normalizedAgent.agent_uri, options);
898
+ if (this.normalizedAgent.oauth_client_credentials) {
899
+ const { ensureClientCredentialsTokens, getAgentStorage } = await import("../auth/oauth/index.mjs");
900
+ await ensureClientCredentialsTokens(this.normalizedAgent, {
901
+ storage: getAgentStorage(this.normalizedAgent),
902
+ allowPrivateIp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri),
903
+ fetch: transport?.fetchFn
904
+ });
905
+ }
906
+ const discoveredEndpoint = await this.discoverMCPEndpoint(this.normalizedAgent.agent_uri, options);
907
+ if (usesScopedFetch) {
908
+ const discoveredAgent = { ...this.normalizedAgent, agent_uri: discoveredEndpoint };
909
+ if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
910
+ const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
911
+ shareNonInteractiveOAuthProvider(this.normalizedAgent, discoveredAgent);
912
+ }
913
+ return discoveredAgent;
914
+ }
915
+ this.discoveredEndpoint = discoveredEndpoint;
272
916
  this.canonicalBaseUrl = this.computeBaseUrl(this.discoveredEndpoint);
273
917
  this.discoveredAgent = {
274
918
  ...this.normalizedAgent,
275
919
  agent_uri: this.discoveredEndpoint
276
920
  };
921
+ if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
922
+ const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
923
+ shareNonInteractiveOAuthProvider(this.normalizedAgent, this.discoveredAgent);
924
+ }
277
925
  return this.discoveredAgent;
278
926
  }
279
927
  /**
@@ -285,17 +933,27 @@ class SingleAgentClient {
285
933
  async ensureCanonicalUrlResolved(options) {
286
934
  throwIfAborted(options?.signal);
287
935
  const needsCanonicalUrl = this.normalizedAgent._needsCanonicalUrl;
936
+ const transport = options?.transport ?? this.config.transport;
937
+ const usesScopedFetch = transport?.fetchFn !== void 0;
288
938
  if (!needsCanonicalUrl) {
289
939
  return this.normalizedAgent;
290
940
  }
291
- if (this.canonicalBaseUrl) {
941
+ if (!usesScopedFetch && this.canonicalBaseUrl) {
292
942
  return {
293
943
  ...this.normalizedAgent,
294
944
  agent_uri: this.canonicalBaseUrl
295
945
  };
296
946
  }
947
+ if (this.normalizedAgent.oauth_client_credentials) {
948
+ const { ensureClientCredentialsTokens, getAgentStorage } = await import("../auth/oauth/index.mjs");
949
+ await ensureClientCredentialsTokens(this.normalizedAgent, {
950
+ storage: getAgentStorage(this.normalizedAgent),
951
+ allowPrivateIp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri),
952
+ fetch: transport?.fetchFn
953
+ });
954
+ }
297
955
  const canonicalUrl = await this.fetchA2ACanonicalUrl(this.normalizedAgent.agent_uri, options);
298
- this.canonicalBaseUrl = canonicalUrl;
956
+ if (!usesScopedFetch) this.canonicalBaseUrl = canonicalUrl;
299
957
  return {
300
958
  ...this.normalizedAgent,
301
959
  agent_uri: canonicalUrl
@@ -313,8 +971,10 @@ class SingleAgentClient {
313
971
  const transport = readOptions?.transport ?? this.config.transport;
314
972
  const maxResponseBytes = transport?.maxResponseBytes;
315
973
  const requestTimeoutMs = resolveRequestTimeoutMs(transport?.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS);
316
- const sizeLimitedFetch = wrapFetchWithSizeLimit((input, init) => fetch(input, init));
317
- const authToken = this.normalizedAgent.auth_token;
974
+ const sizeLimitedFetch = wrapFetchWithSizeLimit(
975
+ (input, init) => transport?.fetchFn ? transport.fetchFn(input, init) : fetch(input, init)
976
+ );
977
+ const authToken = this.normalizedAgent.oauth_client_credentials ? this.normalizedAgent.oauth_tokens?.access_token : this.normalizedAgent.auth_token;
318
978
  let got401 = false;
319
979
  const fetchImpl = async (url, requestInit) => {
320
980
  const headers = {
@@ -362,13 +1022,17 @@ class SingleAgentClient {
362
1022
  } catch (error) {
363
1023
  if (is401Error(error, got401)) {
364
1024
  const requirements = await discoverAuthorizationRequirements(agentUri, {
365
- allowPrivateIp: isLikelyPrivateUrl(agentUri)
1025
+ allowPrivateIp: isLikelyPrivateUrl(agentUri),
1026
+ fetchFn: transport?.fetchFn
366
1027
  });
367
1028
  if (requirements) {
368
1029
  throw new NeedsAuthorizationError(requirements);
369
1030
  }
370
- const challenge = await probeAuthChallenge(agentUri, { allowPrivateIp: isLikelyPrivateUrl(agentUri) });
371
- const oauthMetadata = await discoverOAuthMetadata(agentUri);
1031
+ const challenge = await probeAuthChallenge(agentUri, {
1032
+ allowPrivateIp: isLikelyPrivateUrl(agentUri),
1033
+ fetchFn: transport?.fetchFn
1034
+ });
1035
+ const oauthMetadata = await discoverOAuthMetadata(agentUri, { fetch: transport?.fetchFn });
372
1036
  throw new AuthenticationRequiredError(agentUri, oauthMetadata || void 0, void 0, challenge ?? void 0);
373
1037
  }
374
1038
  throw error;
@@ -409,31 +1073,47 @@ class SingleAgentClient {
409
1073
  throwIfAborted(options?.signal);
410
1074
  const { connectMCPWithFallback } = await import("../protocols/mcp.mjs");
411
1075
  const { probeModernMCPConnection } = await import("../protocols/mcp-modern.mjs");
412
- const authToken = this.agent.auth_token;
1076
+ const usesScopedFetch = (options?.transport ?? this.config.transport)?.fetchFn !== void 0;
1077
+ const authToken = this.normalizedAgent.oauth_client_credentials ? this.normalizedAgent.oauth_tokens?.access_token : this.agent.auth_token;
413
1078
  const agentHeaders = this.agent.headers;
414
1079
  const authHeaders = { ...agentHeaders, ...createMCPAuthHeaders(authToken) };
415
- const authProvider = this.normalizedAgent.oauth_tokens ? (await import("../auth/oauth/index.mjs")).createNonInteractiveOAuthProvider(this.normalizedAgent, {
416
- agentHint: this.normalizedAgent.id
1080
+ const oauth = this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials ? await import("../auth/oauth/index.mjs") : void 0;
1081
+ const authProvider = oauth ? (await import("../auth/oauth/provider-cache.mjs")).getNonInteractiveOAuthProvider(this.normalizedAgent, {
1082
+ agentHint: this.normalizedAgent.id,
1083
+ storage: oauth.getAgentStorage(this.normalizedAgent),
1084
+ allowHttp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri)
417
1085
  }) : void 0;
418
1086
  const testEndpoint = async (url) => {
419
1087
  try {
420
1088
  const modern = await probeModernMCPConnection(url, authToken, agentHeaders, {
421
1089
  authProvider,
422
1090
  signal: options?.signal,
423
- requestTimeoutMs: options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs
1091
+ requestTimeoutMs: options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs,
1092
+ fetchFn: options?.transport?.fetchFn ?? this.config.transport?.fetchFn
424
1093
  });
425
1094
  if (modern.connected) {
426
- this.discoveredMcpEra = modern.era;
427
- this.discoveredMcpEraAt = Date.now();
1095
+ if (!usesScopedFetch) {
1096
+ this.discoveredMcpEra = modern.era;
1097
+ this.discoveredMcpEraAt = Date.now();
1098
+ }
428
1099
  return { success: true };
429
1100
  }
430
- const client = await connectMCPWithFallback(new URL(url), authHeaders, [], "endpoint discovery", void 0, {
431
- signal: options?.signal,
432
- requestTimeoutMs: options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs
433
- });
1101
+ const client = await connectMCPWithFallback(
1102
+ new URL(url),
1103
+ authHeaders,
1104
+ [],
1105
+ "endpoint discovery",
1106
+ options?.transport?.fetchFn ?? this.config.transport?.fetchFn,
1107
+ {
1108
+ signal: options?.signal,
1109
+ requestTimeoutMs: options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs
1110
+ }
1111
+ );
434
1112
  await client.close();
435
- this.discoveredMcpEra = "legacy";
436
- this.discoveredMcpEraAt = Date.now();
1113
+ if (!usesScopedFetch) {
1114
+ this.discoveredMcpEra = "legacy";
1115
+ this.discoveredMcpEraAt = Date.now();
1116
+ }
437
1117
  return { success: true };
438
1118
  } catch (error) {
439
1119
  if (isAbortOrTimeoutError(error)) {
@@ -475,13 +1155,19 @@ class SingleAgentClient {
475
1155
  }
476
1156
  if (got401) {
477
1157
  const requirements = await discoverAuthorizationRequirements(providedUri, {
478
- allowPrivateIp: isLikelyPrivateUrl(providedUri)
1158
+ allowPrivateIp: isLikelyPrivateUrl(providedUri),
1159
+ fetchFn: options?.transport?.fetchFn ?? this.config.transport?.fetchFn
479
1160
  });
480
1161
  if (requirements) {
481
1162
  throw new NeedsAuthorizationError(requirements);
482
1163
  }
483
- const challenge = await probeAuthChallenge(providedUri, { allowPrivateIp: isLikelyPrivateUrl(providedUri) });
484
- const oauthMetadata = await discoverOAuthMetadata(providedUri);
1164
+ const challenge = await probeAuthChallenge(providedUri, {
1165
+ allowPrivateIp: isLikelyPrivateUrl(providedUri),
1166
+ fetchFn: options?.transport?.fetchFn ?? this.config.transport?.fetchFn
1167
+ });
1168
+ const oauthMetadata = await discoverOAuthMetadata(providedUri, {
1169
+ fetch: options?.transport?.fetchFn ?? this.config.transport?.fetchFn
1170
+ });
485
1171
  throw new AuthenticationRequiredError(providedUri, oauthMetadata || void 0, void 0, challenge ?? void 0);
486
1172
  }
487
1173
  throw new Error(
@@ -592,8 +1278,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
592
1278
  * This is the lower-level receiver primitive for integrations that need to
593
1279
  * map malformed webhooks to precise HTTP responses. It verifies the legacy
594
1280
  * HMAC profile when `webhookSecret` is configured, parses raw JSON bodies,
595
- * validates the transport envelope shape, and returns the unwrapped AdCP
596
- * result plus routing metadata.
1281
+ * validates the transport envelope shape, and returns the canonicalized
1282
+ * AdCP result plus routing metadata. Legacy wire inspection is intentionally
1283
+ * confined to the transport adapter and is not returned by this primary API.
597
1284
  */
598
1285
  async verifyAndParseWebhook(options) {
599
1286
  const rawBody = options.rawBody ?? rawBodyFromUnknown(options.body);
@@ -625,37 +1312,107 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
625
1312
  if (!parsedPayload.ok) {
626
1313
  return parsedPayload;
627
1314
  }
1315
+ const parsedTaskType = isObjectRecord(parsedPayload.payload) && typeof parsedPayload.payload.task_type === "string" ? parsedPayload.payload.task_type : void 0;
1316
+ const payloadRecord = isObjectRecord(parsedPayload.payload) ? parsedPayload.payload : void 0;
1317
+ const associatedTaskTypes = new Set(
1318
+ [
1319
+ options.operationId,
1320
+ typeof payloadRecord?.operation_id === "string" ? payloadRecord.operation_id : void 0,
1321
+ typeof payloadRecord?.task_id === "string" ? payloadRecord.task_id : void 0,
1322
+ typeof payloadRecord?.context_id === "string" ? payloadRecord.context_id : void 0
1323
+ ].flatMap((id) => {
1324
+ const taskType = this.canonicalCreativeTaskAssociation(id)?.taskType;
1325
+ return taskType ? [taskType] : [];
1326
+ })
1327
+ );
1328
+ const associatedTaskType = associatedTaskTypes.size === 1 ? [...associatedTaskTypes][0] : void 0;
1329
+ const routedTaskType = options.taskType === "unknown" ? void 0 : options.taskType;
1330
+ const declaredTaskType = routedTaskType ?? parsedTaskType;
1331
+ if (associatedTaskTypes.size > 1 || associatedTaskType !== void 0 && declaredTaskType !== void 0 && associatedTaskType !== declaredTaskType) {
1332
+ return {
1333
+ ok: false,
1334
+ code: "webhook_envelope_invalid",
1335
+ message: "Webhook task_type does not match the locally tracked task association."
1336
+ };
1337
+ }
1338
+ let normalizedTaskType = associatedTaskType ?? declaredTaskType;
628
1339
  try {
629
1340
  const normalizedPayload = this.normalizeWebhookPayload(
630
1341
  parsedPayload.payload,
631
- options.taskType ?? "unknown",
1342
+ normalizedTaskType ?? "unknown",
632
1343
  options.operationId ?? "unknown"
633
1344
  );
1345
+ normalizedTaskType = normalizedPayload.task_type;
1346
+ if (associatedTaskType !== void 0 && normalizedPayload.task_type !== associatedTaskType) {
1347
+ return {
1348
+ ok: false,
1349
+ code: "webhook_envelope_invalid",
1350
+ message: "Webhook task_type does not match the locally tracked task association."
1351
+ };
1352
+ }
1353
+ const metadata = {
1354
+ operation_id: normalizedPayload.operation_id,
1355
+ context_id: normalizedPayload.context_id,
1356
+ task_id: normalizedPayload.task_id,
1357
+ agent_id: this.agent.id,
1358
+ task_type: normalizedPayload.task_type,
1359
+ status: normalizedPayload.status,
1360
+ message: normalizedPayload.message,
1361
+ timestamp: normalizedPayload.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
1362
+ idempotency_key: normalizedPayload.idempotency_key,
1363
+ protocol: normalizedPayload.protocol ?? "mcp"
1364
+ };
1365
+ const canonicalResult = this.canonicalizeWebhookCreativeResult(metadata, normalizedPayload.result);
1366
+ const canonicalCreativeTask = CANONICAL_CREATIVE_ACTIVITY_TASKS.has(normalizedPayload.task_type);
1367
+ const legacyFormatConverter = this.legacyFormatConverterForWebhook(metadata);
1368
+ const canonicalEnvelope = canonicalCreativeTask ? stripLegacyCreativeIdentity(
1369
+ projectCanonicalCreativeResponseValue(
1370
+ parsedPayload.payload,
1371
+ normalizedPayload.task_type,
1372
+ legacyFormatConverter
1373
+ )
1374
+ ) : parsedPayload.payload;
1375
+ const canonicalMessage = canonicalCreativeTask ? stripLegacyCreativeIdentity({
1376
+ message: normalizedPayload.message,
1377
+ legacySource: parsedPayload.payload
1378
+ }).message : normalizedPayload.message;
634
1379
  return {
635
1380
  ok: true,
636
1381
  protocol: normalizedPayload.protocol ?? "mcp",
637
- envelope: parsedPayload.payload,
638
- result: normalizedPayload.result,
1382
+ envelope: canonicalEnvelope,
1383
+ result: canonicalResult,
639
1384
  metadata: {
640
1385
  operationId: normalizedPayload.operation_id,
641
1386
  contextId: normalizedPayload.context_id,
642
1387
  taskId: normalizedPayload.task_id,
643
1388
  taskType: normalizedPayload.task_type,
644
1389
  status: normalizedPayload.status,
645
- message: normalizedPayload.message,
1390
+ message: canonicalMessage,
646
1391
  timestamp: normalizedPayload.timestamp,
647
1392
  idempotencyKey: normalizedPayload.idempotency_key
648
1393
  }
649
1394
  };
650
1395
  } catch (error) {
1396
+ const canonicalCreativeTask = normalizedTaskType !== void 0 && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(normalizedTaskType);
651
1397
  if (error instanceof WebhookDispatchError) {
652
- return { ok: false, code: error.code, message: error.message, cause: error.cause };
1398
+ if (!canonicalCreativeTask) {
1399
+ return { ok: false, code: error.code, message: error.message };
1400
+ }
1401
+ const safe = stripLegacyCreativeIdentity({
1402
+ message: error.message,
1403
+ legacySource: parsedPayload.payload
1404
+ });
1405
+ return { ok: false, code: error.code, message: safe.message };
1406
+ }
1407
+ const message = error instanceof Error ? error.message : "Webhook payload could not be normalized.";
1408
+ if (canonicalCreativeTask) {
1409
+ const safe = stripLegacyCreativeIdentity({ message, legacySource: parsedPayload.payload });
1410
+ return { ok: false, code: "webhook_result_invalid", message: safe.message };
653
1411
  }
654
1412
  return {
655
1413
  ok: false,
656
1414
  code: "webhook_result_invalid",
657
- message: error instanceof Error ? error.message : "Webhook payload could not be normalized.",
658
- cause: error
1415
+ message: "Webhook payload could not be normalized."
659
1416
  };
660
1417
  }
661
1418
  }
@@ -671,36 +1428,88 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
671
1428
  timestamp: parsed.metadata.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
672
1429
  idempotency_key: parsed.metadata.idempotencyKey,
673
1430
  protocol: parsed.protocol,
674
- rawHTTPPayload: parsed.envelope
1431
+ rawHTTPPayload: CANONICAL_CREATIVE_ACTIVITY_TASKS.has(parsed.metadata.taskType) ? stripLegacyCreativeIdentity(parsed.envelope) : parsed.envelope
675
1432
  };
676
- const policyDispatch = await this.applyProductPropertyPolicyToWebhookResult(
677
- parsed.result,
678
- metadata
679
- );
680
- const webhookResult = policyDispatch.result;
681
- metadata = policyDispatch.metadata;
682
- await this.config.onActivity?.({
683
- type: "webhook_received",
684
- operation_id: metadata.operation_id,
685
- agent_id: metadata.agent_id,
686
- context_id: metadata.context_id,
687
- task_id: metadata.task_id,
688
- task_type: metadata.task_type,
689
- status: metadata.status,
690
- payload: parsed.result,
691
- timestamp: metadata.timestamp
692
- });
693
- if (policyDispatch.suppressHandler) {
1433
+ this.rememberCanonicalCreativeWebhookContext(metadata);
1434
+ try {
1435
+ const canonicalResult = this.canonicalizeWebhookCreativeResult(metadata, parsed.result);
1436
+ const policyDispatch = await this.applyProductPropertyPolicyToWebhookResult(
1437
+ canonicalResult,
1438
+ metadata
1439
+ );
1440
+ const webhookResult = policyDispatch.result;
1441
+ metadata = policyDispatch.metadata;
1442
+ await this.config.onActivity?.(
1443
+ canonicalCreativeActivity({
1444
+ type: "webhook_received",
1445
+ operation_id: metadata.operation_id,
1446
+ agent_id: metadata.agent_id,
1447
+ context_id: metadata.context_id,
1448
+ task_id: metadata.task_id,
1449
+ task_type: metadata.task_type,
1450
+ status: metadata.status,
1451
+ payload: canonicalResult,
1452
+ timestamp: metadata.timestamp
1453
+ })
1454
+ );
1455
+ if (policyDispatch.suppressHandler) return true;
1456
+ if (this.asyncHandler) {
1457
+ await this.asyncHandler.handleWebhook({ result: webhookResult, metadata });
1458
+ return true;
1459
+ }
1460
+ return false;
1461
+ } finally {
1462
+ this.executor.observeExternalTaskStatus(
1463
+ metadata.operation_id,
1464
+ metadata.status,
1465
+ metadata.rawHTTPPayload
1466
+ );
694
1467
  this.forgetProductPolicyRequestParams(metadata);
695
- return true;
696
1468
  }
697
- if (this.asyncHandler) {
698
- await this.asyncHandler.handleWebhook({ result: webhookResult, metadata });
699
- this.forgetProductPolicyRequestParams(metadata);
700
- return true;
1469
+ }
1470
+ rememberCanonicalCreativeWebhookContext(metadata) {
1471
+ if (!metadata.context_id || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(metadata.task_type)) return;
1472
+ const association = this.canonicalCreativeTaskAssociation(metadata.operation_id) ?? this.canonicalCreativeTaskAssociation(metadata.task_id) ?? this.canonicalCreativeTaskAssociation(metadata.context_id);
1473
+ if (!association) return;
1474
+ this.rememberCanonicalCreativeTaskAssociation(
1475
+ metadata.context_id,
1476
+ association.taskType,
1477
+ association.legacyFormatConverter,
1478
+ association.routingSnapshot
1479
+ );
1480
+ }
1481
+ canonicalizeWebhookCreativeResult(metadata, result) {
1482
+ if (!result || typeof result !== "object" || Array.isArray(result)) return result;
1483
+ const taskType = metadata.task_type;
1484
+ const legacyFormatConverter = this.legacyFormatConverterForWebhook(metadata);
1485
+ const response = result;
1486
+ if (taskType === "get_products" && Array.isArray(response.products)) {
1487
+ const { response: canonical2, diagnostics } = toCanonicalOnlyResponse(
1488
+ response,
1489
+ { legacyFormatConverter }
1490
+ );
1491
+ const requestParams = this.productPolicyRequestParamsForWebhook(metadata);
1492
+ this.rememberCanonicalProductRoutes(canonical2.products, requestParams.account, response.products);
1493
+ const { _message: _dropLegacyMessage, ...safe } = canonical2;
1494
+ void _dropLegacyMessage;
1495
+ return stripLegacyCreativeIdentity({ ...safe, projection: { diagnostics } });
1496
+ }
1497
+ if (taskType === "list_creatives" && Array.isArray(response.creatives)) {
1498
+ const { _message: _dropLegacyMessage, ...safe } = response;
1499
+ void _dropLegacyMessage;
1500
+ return stripLegacyCreativeIdentity({
1501
+ ...safe,
1502
+ creatives: response.creatives.map(
1503
+ (creative) => projectCreativeForDelivery(creative, {}, "canonical", "list_creatives", legacyFormatConverter)
1504
+ )
1505
+ });
1506
+ }
1507
+ const canonical = CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType) ? stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(result, taskType, legacyFormatConverter)) : result;
1508
+ const association = this.canonicalCreativeTaskAssociation(metadata.operation_id) ?? this.canonicalCreativeTaskAssociation(metadata.task_id) ?? this.canonicalCreativeTaskAssociation(metadata.context_id);
1509
+ if (metadata.status === "completed") {
1510
+ this.rememberCanonicalPackageRoutesForTask(taskType, canonical, association?.routingSnapshot);
701
1511
  }
702
- this.forgetProductPolicyRequestParams(metadata);
703
- return false;
1512
+ return canonical;
704
1513
  }
705
1514
  /**
706
1515
  * Normalize webhook payload - handles both MCP and A2A webhook formats
@@ -739,7 +1548,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
739
1548
  if (typeof payload.status !== "string" || !WEBHOOK_TASK_STATUSES.has(payload.status)) {
740
1549
  throw new WebhookDispatchError(
741
1550
  "webhook_envelope_invalid",
742
- `Invalid MCP webhook envelope: unsupported top-level status ${JSON.stringify(payload.status)}. Expected one of ${Array.from(WEBHOOK_TASK_STATUSES).join(", ")}.`
1551
+ `Invalid MCP webhook envelope: unsupported top-level status. Expected one of ${Array.from(WEBHOOK_TASK_STATUSES).join(", ")}.`
743
1552
  );
744
1553
  }
745
1554
  if (typeof payload.timestamp !== "string" || Number.isNaN(Date.parse(payload.timestamp))) {
@@ -779,7 +1588,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
779
1588
  } catch (error) {
780
1589
  throw new WebhookDispatchError(
781
1590
  "webhook_result_invalid",
782
- `Failed to unwrap A2A webhook payload artifacts: ${error instanceof Error ? error.message : "unknown error"}`,
1591
+ "Failed to unwrap A2A webhook payload artifacts.",
783
1592
  error
784
1593
  );
785
1594
  }
@@ -811,7 +1620,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
811
1620
  }
812
1621
  throw new WebhookDispatchError(
813
1622
  "webhook_unsupported_payload",
814
- `Unsupported webhook payload format. Expected an MCP webhook envelope with top-level idempotency_key, operation_id, task_id, task_type, status, timestamp, and result, or an A2A Task/TaskStatusUpdateEvent with AdCP data nested in status.message.parts[].data or task artifacts. Received: ${safeJsonPreview(payload)}`
1623
+ "Unsupported webhook payload format. Expected an MCP webhook envelope with top-level idempotency_key, operation_id, task_id, task_type, status, timestamp, and result, or an A2A Task/TaskStatusUpdateEvent with AdCP data nested in status.message.parts[].data or task artifacts."
815
1624
  );
816
1625
  }
817
1626
  /**
@@ -952,7 +1761,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
952
1761
  *
953
1762
  * Automatically adapts requests for v2 servers and normalizes responses.
954
1763
  */
955
- async executeAndHandle(taskType, handlerName, params, inputHandler, options) {
1764
+ async executeAndHandle(taskType, handlerName, params, inputHandler, options, transformCompletedResponse, legacyFormatConverter, canonicalRequest) {
956
1765
  throwIfAborted(options?.signal);
957
1766
  let normalizedParams = normalizeRequestParams(taskType, params, {
958
1767
  skipIdempotencyAutoInject: options?.skipIdempotencyAutoInject,
@@ -981,26 +1790,36 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
981
1790
  if (!options?.skipIdempotencyAutoInject && !options?.skipAccountValidation) {
982
1791
  this.executor.validateRequest(taskType, normalizedParams);
983
1792
  }
984
- const serverVersion = await this.detectServerVersion(options);
1793
+ const capabilityDiscoveryContext = {};
1794
+ const detectionOptions = {
1795
+ ...options,
1796
+ [CAPABILITY_DISCOVERY_CONTEXT]: capabilityDiscoveryContext
1797
+ };
1798
+ const serverVersion = await this.detectServerVersion(detectionOptions);
985
1799
  const inputSchemaStripLogs = [];
986
1800
  const { params: adaptedParams, driftLogs: adaptDriftLogs } = this.adaptRequest(
987
1801
  taskType,
988
1802
  normalizedParams,
989
1803
  serverVersion,
990
- inputSchemaStripLogs
1804
+ inputSchemaStripLogs,
1805
+ capabilityDiscoveryContext.toolSchemas
991
1806
  );
992
1807
  const v25DriftLogs = [...adaptDriftLogs];
993
1808
  if (webhookDriftLog) v25DriftLogs.push(webhookDriftLog);
994
1809
  if (serverVersion === "v2") {
995
1810
  this.executor.validateAdaptedRequestAgainstV2(taskType, adaptedParams, v25DriftLogs);
996
1811
  }
997
- let result = await this.executor.executeTask(
998
- agent,
999
- taskType,
1000
- adaptedParams,
1001
- inputHandler,
1002
- effectiveOptions,
1003
- serverVersion
1812
+ const canonicalInputHandler = this.canonicalCreativeInputHandler(taskType, inputHandler);
1813
+ let result = await canonicalCreativeExecutionStorage.run(
1814
+ { taskType, legacyFormatConverter, canonicalRequest: canonicalRequest ?? normalizedParams },
1815
+ () => this.executor.executeTask(
1816
+ agent,
1817
+ taskType,
1818
+ adaptedParams,
1819
+ canonicalInputHandler,
1820
+ effectiveOptions,
1821
+ serverVersion
1822
+ )
1004
1823
  );
1005
1824
  const postAdapterLogs = [...inputSchemaStripLogs, ...v25DriftLogs];
1006
1825
  if (postAdapterLogs.length > 0) {
@@ -1009,9 +1828,26 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1009
1828
  if (result.success && result.data) {
1010
1829
  result.data = this.normalizeResponseToV3(taskType, result.data);
1011
1830
  }
1012
- result = this.wrapProductPolicySubmittedContinuation(result, taskType, normalizedParams);
1013
- this.rememberProductPolicyRequestParams(taskType, normalizedParams, result, options);
1831
+ result = this.wrapProductPolicySubmittedContinuation(result, taskType, normalizedParams, options);
1832
+ if (result.status === "working") {
1833
+ this.rememberProductPolicyRequestParams(taskType, normalizedParams, result, options);
1834
+ }
1835
+ this.rememberLegacyFormatConverter(taskType, legacyFormatConverter, result, options);
1014
1836
  result = await this.applyProductPropertyPolicy(result, taskType, normalizedParams);
1837
+ if (CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) {
1838
+ const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, canonicalRequest ?? normalizedParams);
1839
+ result = this.canonicalizeCreativeTaskResult(result, taskType, transformCompletedResponse, legacyFormatConverter);
1840
+ result = this.wrapCanonicalCreativeContinuations(
1841
+ result,
1842
+ taskType,
1843
+ transformCompletedResponse,
1844
+ legacyFormatConverter,
1845
+ routingSnapshot
1846
+ );
1847
+ this.rememberCanonicalCreativeTaskIds(result, taskType, legacyFormatConverter, routingSnapshot);
1848
+ } else if (result.status === "completed" && result.success && result.data && transformCompletedResponse) {
1849
+ result = { ...result, data: transformCompletedResponse(result.data) };
1850
+ }
1015
1851
  if (result.status === "completed" && result.success && this.asyncHandler) {
1016
1852
  const handler = this.config.handlers?.[handlerName];
1017
1853
  if (handler) {
@@ -1021,6 +1857,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1021
1857
  task_id: result.metadata.taskId,
1022
1858
  agent_id: this.agent.id,
1023
1859
  task_type: taskType,
1860
+ status: result.status,
1024
1861
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1025
1862
  };
1026
1863
  await handler(result.data, metadata);
@@ -1028,6 +1865,255 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1028
1865
  }
1029
1866
  return result;
1030
1867
  }
1868
+ canonicalCreativeInputHandler(taskType, inputHandler) {
1869
+ if (!inputHandler || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) return inputHandler;
1870
+ return async (context) => {
1871
+ const active = canonicalCreativeExecutionStorage.getStore();
1872
+ const converter = this.resolveLegacyFormatConverter(
1873
+ active?.taskType === taskType ? active.legacyFormatConverter : void 0
1874
+ );
1875
+ const project = (value) => projectCanonicalCreativeAncillaryValue(value, taskType, converter);
1876
+ const messages = context.messages.map((message) => ({
1877
+ ...message,
1878
+ content: project(message.content)
1879
+ }));
1880
+ const safeContext = {
1881
+ ...context,
1882
+ messages,
1883
+ inputRequest: project(context.inputRequest),
1884
+ getSummary: () => messages.map((message) => `${message.role}: ${JSON.stringify(message.content)}`).join("\n"),
1885
+ getPreviousResponse: (field) => project(context.getPreviousResponse(field))
1886
+ };
1887
+ return inputHandler(safeContext);
1888
+ };
1889
+ }
1890
+ projectCanonicalCreativeData(taskType, data, transform, legacyFormatConverter) {
1891
+ let projected = this.normalizeResponseToV3(taskType, data);
1892
+ const record = projected && typeof projected === "object" ? projected : void 0;
1893
+ const canProjectRead = taskType === "get_products" ? Array.isArray(record?.products) : taskType === "list_creatives" ? Array.isArray(record?.creatives) : true;
1894
+ if (transform && canProjectRead) {
1895
+ projected = transform(projected);
1896
+ } else if (canProjectRead && taskType === "get_products" && record) {
1897
+ const active = canonicalCreativeExecutionStorage.getStore();
1898
+ const { response, diagnostics } = toCanonicalOnlyResponse(record, {
1899
+ legacyFormatConverter: this.resolveLegacyFormatConverter(
1900
+ legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
1901
+ ),
1902
+ projectionCatalogs: this.config.projectionCatalogs
1903
+ });
1904
+ const { _message: _dropLegacyMessage, ...canonical } = response;
1905
+ void _dropLegacyMessage;
1906
+ projected = { ...canonical, projection: { diagnostics } };
1907
+ } else if (canProjectRead && taskType === "list_creatives" && record) {
1908
+ const active = canonicalCreativeExecutionStorage.getStore();
1909
+ const activeLegacyFormatConverter = this.resolveLegacyFormatConverter(
1910
+ legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
1911
+ );
1912
+ const { _message: _dropLegacyMessage, ...safe } = record;
1913
+ void _dropLegacyMessage;
1914
+ projected = {
1915
+ ...safe,
1916
+ creatives: record.creatives.map(
1917
+ (creative) => projectCreativeForDelivery(
1918
+ creative,
1919
+ {},
1920
+ "canonical",
1921
+ "list_creatives",
1922
+ activeLegacyFormatConverter
1923
+ )
1924
+ )
1925
+ };
1926
+ } else if (canProjectRead && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) {
1927
+ const active = canonicalCreativeExecutionStorage.getStore();
1928
+ projected = projectCanonicalCreativeResponseValue(
1929
+ projected,
1930
+ taskType,
1931
+ this.resolveLegacyFormatConverter(
1932
+ legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
1933
+ )
1934
+ );
1935
+ }
1936
+ return stripLegacyCreativeIdentity(projected);
1937
+ }
1938
+ canonicalizeCreativeTaskResult(result, taskType, transform, legacyFormatConverter) {
1939
+ const projectedData = result.data !== void 0 ? this.projectCanonicalCreativeData(taskType, result.data, transform, legacyFormatConverter) : void 0;
1940
+ const errorInstance = result.errorInstance;
1941
+ const converter = this.resolveLegacyFormatConverter(legacyFormatConverter);
1942
+ const metadataRecord = result.metadata;
1943
+ const semanticMetadata = {
1944
+ ...metadataRecord,
1945
+ ...metadataRecord.inputRequest !== void 0 && {
1946
+ inputRequest: projectCanonicalCreativeAncillaryValue(metadataRecord.inputRequest, taskType, converter)
1947
+ }
1948
+ };
1949
+ const semanticConversation = result.conversation?.map((message) => ({
1950
+ ...message,
1951
+ content: projectCanonicalCreativeAncillaryValue(message.content, taskType, converter)
1952
+ }));
1953
+ const safe = stripLegacyCreativeIdentity({
1954
+ data: projectedData,
1955
+ metadata: semanticMetadata,
1956
+ conversation: semanticConversation,
1957
+ debug_logs: result.debug_logs,
1958
+ adcpError: result.adcpError,
1959
+ error: result.error,
1960
+ governance: result.governance,
1961
+ governanceOutcome: result.governanceOutcome,
1962
+ governanceOutcomeError: result.governanceOutcomeError,
1963
+ deferredQuestion: result.deferred?.question,
1964
+ // Token source only: discarded below, but lets the sanitizer remove exact
1965
+ // legacy IDs/URLs when the seller repeats them in messages or diagnostics.
1966
+ legacySource: result.data
1967
+ });
1968
+ const safeErrorInstance = errorInstance ? canonicalCreativeErrorInstance(errorInstance, result.data) : void 0;
1969
+ const safeDeferred = result.deferred ? { ...result.deferred, ...result.deferred.question !== void 0 && { question: safe.deferredQuestion } } : void 0;
1970
+ return attachMatch({
1971
+ ...result,
1972
+ ...result.data !== void 0 && { data: safe.data },
1973
+ metadata: safe.metadata,
1974
+ ...result.conversation !== void 0 && { conversation: safe.conversation },
1975
+ ...result.debug_logs !== void 0 && { debug_logs: safe.debug_logs },
1976
+ ...result.adcpError !== void 0 && { adcpError: safe.adcpError },
1977
+ ...result.error !== void 0 && { error: safe.error },
1978
+ ...result.governance !== void 0 && { governance: safe.governance },
1979
+ ...result.governanceOutcome !== void 0 && { governanceOutcome: safe.governanceOutcome },
1980
+ ...result.governanceOutcomeError !== void 0 && { governanceOutcomeError: safe.governanceOutcomeError },
1981
+ ...safeDeferred !== void 0 && { deferred: safeDeferred },
1982
+ ...safeErrorInstance !== void 0 && { errorInstance: safeErrorInstance }
1983
+ });
1984
+ }
1985
+ canonicalizeCreativeTaskInfo(taskInfo, taskType, transform, legacyFormatConverter) {
1986
+ const source = taskInfo.result;
1987
+ const projected = source !== void 0 ? this.projectCanonicalCreativeData(taskType, source, transform, legacyFormatConverter) : void 0;
1988
+ const { legacySource: _dropLegacySource, ...safe } = stripLegacyCreativeIdentity({
1989
+ ...taskInfo,
1990
+ taskType,
1991
+ ...source !== void 0 && { result: projected },
1992
+ legacySource: source
1993
+ });
1994
+ void _dropLegacySource;
1995
+ return safe;
1996
+ }
1997
+ wrapCanonicalCreativeContinuations(result, taskType, transform, legacyFormatConverter, routingRequest) {
1998
+ const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, routingRequest);
1999
+ if (result.submitted) {
2000
+ const submitted = result.submitted;
2001
+ result = {
2002
+ ...result,
2003
+ submitted: {
2004
+ ...submitted,
2005
+ track: async (transport) => {
2006
+ const canonical = this.canonicalizeCreativeTaskInfo(
2007
+ await canonicalCreativeExecutionStorage.run(
2008
+ { taskType, legacyFormatConverter },
2009
+ () => submitted.track(transport)
2010
+ ),
2011
+ taskType,
2012
+ transform,
2013
+ legacyFormatConverter
2014
+ );
2015
+ if (canonical.status === "completed" && canonical.result !== void 0) {
2016
+ this.rememberCanonicalPackageRoutesForTask(taskType, canonical.result, routingSnapshot);
2017
+ }
2018
+ return canonical;
2019
+ },
2020
+ waitForCompletion: async (pollInterval, signal) => {
2021
+ const completed = await canonicalCreativeExecutionStorage.run(
2022
+ { taskType, legacyFormatConverter },
2023
+ () => submitted.waitForCompletion(pollInterval, signal)
2024
+ );
2025
+ const canonical = this.canonicalizeCreativeTaskResult(
2026
+ completed,
2027
+ taskType,
2028
+ transform,
2029
+ legacyFormatConverter
2030
+ );
2031
+ if (canonical.success && canonical.status === "completed" && canonical.data !== void 0) {
2032
+ this.rememberCanonicalPackageRoutesForTask(taskType, canonical.data, routingSnapshot);
2033
+ }
2034
+ this.rememberCanonicalCreativeTaskIds(canonical, taskType, legacyFormatConverter, routingSnapshot);
2035
+ return this.wrapCanonicalCreativeContinuations(
2036
+ canonical,
2037
+ taskType,
2038
+ transform,
2039
+ legacyFormatConverter,
2040
+ routingSnapshot
2041
+ );
2042
+ }
2043
+ }
2044
+ };
2045
+ }
2046
+ if (result.deferred) {
2047
+ const deferred = result.deferred;
2048
+ result = {
2049
+ ...result,
2050
+ deferred: {
2051
+ ...deferred,
2052
+ resume: async (input) => {
2053
+ const resumed = await canonicalCreativeExecutionStorage.run(
2054
+ { taskType, legacyFormatConverter },
2055
+ () => deferred.resume(input)
2056
+ );
2057
+ const canonical = this.canonicalizeCreativeTaskResult(resumed, taskType, transform, legacyFormatConverter);
2058
+ if (canonical.success && canonical.status === "completed" && canonical.data !== void 0) {
2059
+ this.rememberCanonicalPackageRoutesForTask(taskType, canonical.data, routingSnapshot);
2060
+ }
2061
+ this.rememberCanonicalCreativeTaskIds(canonical, taskType, legacyFormatConverter, routingSnapshot);
2062
+ return this.wrapCanonicalCreativeContinuations(
2063
+ canonical,
2064
+ taskType,
2065
+ transform,
2066
+ legacyFormatConverter,
2067
+ routingSnapshot
2068
+ );
2069
+ }
2070
+ }
2071
+ };
2072
+ }
2073
+ return attachMatch(result);
2074
+ }
2075
+ rememberCanonicalCreativeTaskIds(result, taskType, legacyFormatConverter, routingRequest) {
2076
+ const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, routingRequest);
2077
+ const keys = [
2078
+ result.metadata.taskId,
2079
+ result.metadata.contextId,
2080
+ result.metadata.serverTaskId,
2081
+ result.submitted?.taskId
2082
+ ];
2083
+ for (const key of keys) {
2084
+ if (!key) continue;
2085
+ this.rememberCanonicalCreativeTaskAssociation(key, taskType, legacyFormatConverter, routingSnapshot);
2086
+ }
2087
+ }
2088
+ rememberCanonicalCreativeTaskAssociation(key, taskType, legacyFormatConverter, canonicalRequest) {
2089
+ const previous = this.canonicalCreativeTaskAssociations.get(key);
2090
+ const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, canonicalRequest);
2091
+ const effectiveRoutingSnapshot = routingSnapshot ?? (previous?.taskType === taskType ? previous.routingSnapshot : void 0);
2092
+ this.canonicalCreativeTaskAssociations.delete(key);
2093
+ this.canonicalCreativeTaskAssociations.set(key, {
2094
+ taskType,
2095
+ legacyFormatConverter,
2096
+ ...effectiveRoutingSnapshot ? { routingSnapshot: effectiveRoutingSnapshot } : {}
2097
+ });
2098
+ while (this.canonicalCreativeTaskAssociations.size > TASK_SCOPED_STATE_LIMIT) {
2099
+ const oldest = this.canonicalCreativeTaskAssociations.keys().next().value;
2100
+ if (oldest === void 0) break;
2101
+ this.canonicalCreativeTaskAssociations.delete(oldest);
2102
+ }
2103
+ }
2104
+ canonicalCreativeTaskAssociation(key) {
2105
+ if (!key) return void 0;
2106
+ const association = this.canonicalCreativeTaskAssociations.get(key);
2107
+ if (!association) return void 0;
2108
+ this.canonicalCreativeTaskAssociations.delete(key);
2109
+ this.canonicalCreativeTaskAssociations.set(key, association);
2110
+ return association;
2111
+ }
2112
+ forgetCanonicalCreativeTaskAssociationKeys(keys) {
2113
+ for (const key of keys) {
2114
+ if (key) this.canonicalCreativeTaskAssociations.delete(key);
2115
+ }
2116
+ }
1031
2117
  /**
1032
2118
  * Drop products that arrive without a usable `pricing_options[]` array from a
1033
2119
  * completed `get_products` response. `pricing_options` is required and
@@ -1238,20 +2324,62 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1238
2324
  return result;
1239
2325
  }
1240
2326
  rememberProductPolicyRequestParams(taskType, requestParams, result, options) {
2327
+ this.rememberProductPolicyRequestState(
2328
+ taskType,
2329
+ { request: productPolicyRequestSnapshot(requestParams) },
2330
+ result,
2331
+ options
2332
+ );
2333
+ }
2334
+ rememberProductPolicyRequestState(taskType, requestState, result, options) {
1241
2335
  if (taskType !== "get_products") return;
1242
2336
  if (result.status !== "submitted" && result.status !== "working") return;
1243
2337
  const keys = /* @__PURE__ */ new Set();
1244
2338
  if (result.metadata.taskId) keys.add(result.metadata.taskId);
1245
2339
  if (result.metadata.contextId) keys.add(result.metadata.contextId);
1246
2340
  if (result.metadata.serverTaskId) keys.add(result.metadata.serverTaskId);
2341
+ if (result.submitted?.taskId) keys.add(result.submitted.taskId);
1247
2342
  if (options?.taskId) keys.add(options.taskId);
1248
2343
  if (options?.contextId) keys.add(options.contextId);
1249
2344
  for (const key of keys) {
1250
- this.productPolicyRequestParamsByTask.set(key, requestParams);
2345
+ this.productPolicyRequestParamsByTask.delete(key);
2346
+ this.productPolicyRequestParamsByTask.set(key, requestState);
2347
+ while (this.productPolicyRequestParamsByTask.size > TASK_SCOPED_STATE_LIMIT) {
2348
+ const oldest = this.productPolicyRequestParamsByTask.keys().next().value;
2349
+ if (oldest === void 0) break;
2350
+ this.productPolicyRequestParamsByTask.delete(oldest);
2351
+ }
1251
2352
  }
1252
2353
  }
2354
+ rememberLegacyFormatConverter(taskType, converter, result, options) {
2355
+ if (!converter || taskType !== "get_products" && taskType !== "list_creatives") return;
2356
+ const metadata = result.metadata;
2357
+ const keys = [
2358
+ metadata.operationId,
2359
+ metadata.taskId,
2360
+ metadata.contextId,
2361
+ metadata.serverTaskId,
2362
+ options?.taskId,
2363
+ options?.contextId
2364
+ ];
2365
+ for (const key of keys) {
2366
+ if (key) this.rememberCanonicalCreativeTaskAssociation(key, taskType, converter);
2367
+ }
2368
+ }
2369
+ legacyFormatConverterForWebhook(metadata) {
2370
+ return this.canonicalCreativeTaskAssociation(metadata.operation_id)?.legacyFormatConverter ?? this.canonicalCreativeTaskAssociation(metadata.task_id)?.legacyFormatConverter ?? this.canonicalCreativeTaskAssociation(metadata.context_id)?.legacyFormatConverter ?? this.resolveLegacyFormatConverter();
2371
+ }
1253
2372
  forgetProductPolicyRequestParams(metadata) {
1254
- this.forgetProductPolicyRequestParamKeys([metadata.operation_id, metadata.task_id, metadata.context_id]);
2373
+ const aliases = [metadata.operation_id, metadata.task_id, metadata.context_id];
2374
+ const states = new Set(
2375
+ aliases.filter((key) => key !== void 0).map((key) => this.productPolicyRequestParamsByTask.get(key)).filter((value) => value !== void 0)
2376
+ );
2377
+ for (const state of states) state.request = void 0;
2378
+ this.forgetProductPolicyRequestParamKeys(aliases);
2379
+ if (states.size === 0) return;
2380
+ for (const [key, state] of this.productPolicyRequestParamsByTask) {
2381
+ if (states.has(state)) this.productPolicyRequestParamsByTask.delete(key);
2382
+ }
1255
2383
  }
1256
2384
  forgetProductPolicyRequestParamKeys(keys) {
1257
2385
  for (const key of keys) {
@@ -1259,38 +2387,61 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1259
2387
  this.productPolicyRequestParamsByTask.delete(key);
1260
2388
  }
1261
2389
  }
1262
- wrapProductPolicySubmittedContinuation(result, taskType, requestParams) {
2390
+ wrapProductPolicySubmittedContinuation(result, taskType, requestParams, options) {
1263
2391
  if (taskType !== "get_products" || result.status !== "submitted" || !result.submitted) return result;
1264
2392
  const submitted = result.submitted;
2393
+ const policyState = {
2394
+ request: productPolicyRequestSnapshot(requestParams)
2395
+ };
2396
+ this.rememberProductPolicyRequestState(taskType, policyState, result, options);
2397
+ const retainedKeys = [
2398
+ result.metadata.taskId,
2399
+ result.metadata.contextId,
2400
+ result.metadata.serverTaskId,
2401
+ submitted.taskId,
2402
+ options?.taskId,
2403
+ options?.contextId
2404
+ ];
1265
2405
  result.submitted = {
1266
2406
  ...submitted,
1267
2407
  track: async (transport) => {
1268
2408
  const taskInfo = await submitted.track(transport);
1269
- const processed = await this.applyProductPropertyPolicyToTaskInfo(taskInfo, taskType, requestParams);
1270
- if (["completed", "failed", "rejected", "canceled"].includes(processed.status)) {
1271
- this.forgetProductPolicyRequestParamKeys([
1272
- result.metadata.taskId,
1273
- result.metadata.serverTaskId,
1274
- processed.taskId
1275
- ]);
2409
+ const terminal = ["completed", "failed", "rejected", "canceled"].includes(taskInfo.status);
2410
+ try {
2411
+ return await this.applyProductPropertyPolicyToTaskInfo(
2412
+ taskInfo,
2413
+ taskType,
2414
+ policyState.request ?? {}
2415
+ );
2416
+ } finally {
2417
+ if (terminal) {
2418
+ policyState.request = void 0;
2419
+ this.forgetProductPolicyRequestParamKeys([...retainedKeys, taskInfo.taskId]);
2420
+ }
1276
2421
  }
1277
- return processed;
1278
2422
  },
1279
2423
  waitForCompletion: async (pollInterval, signal) => {
1280
2424
  let completed = await submitted.waitForCompletion(pollInterval, signal);
1281
2425
  if (completed.success && completed.data) {
1282
2426
  completed.data = this.normalizeResponseToV3(taskType, completed.data);
1283
2427
  }
1284
- const processed = await this.applyProductPropertyPolicy(completed, taskType, requestParams);
1285
- if (processed.status === "completed" || processed.status === "failed") {
1286
- this.forgetProductPolicyRequestParamKeys([
1287
- result.metadata.taskId,
1288
- result.metadata.serverTaskId,
1289
- processed.metadata.taskId,
1290
- processed.metadata.serverTaskId
1291
- ]);
2428
+ const terminal = completed.status === "completed" || completed.status === "failed";
2429
+ try {
2430
+ return await this.applyProductPropertyPolicy(
2431
+ completed,
2432
+ taskType,
2433
+ policyState.request ?? {}
2434
+ );
2435
+ } finally {
2436
+ if (terminal) {
2437
+ policyState.request = void 0;
2438
+ this.forgetProductPolicyRequestParamKeys([
2439
+ ...retainedKeys,
2440
+ completed.metadata.taskId,
2441
+ completed.metadata.serverTaskId
2442
+ ]);
2443
+ }
1292
2444
  }
1293
- return processed;
1294
2445
  }
1295
2446
  };
1296
2447
  return result;
@@ -1328,7 +2479,15 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1328
2479
  };
1329
2480
  }
1330
2481
  productPolicyRequestParamsForWebhook(metadata) {
1331
- return this.executor.getRequestParams(metadata.operation_id) ?? this.executor.getRequestParams(metadata.task_id) ?? this.productPolicyRequestParamsByTask.get(metadata.operation_id) ?? this.productPolicyRequestParamsByTask.get(metadata.task_id) ?? (metadata.context_id ? this.productPolicyRequestParamsByTask.get(metadata.context_id) : void 0) ?? {};
2482
+ return this.executor.getRequestParams(metadata.operation_id) ?? this.executor.getRequestParams(metadata.task_id) ?? this.productPolicyRequestParamsForKey(metadata.operation_id) ?? this.productPolicyRequestParamsForKey(metadata.task_id) ?? this.productPolicyRequestParamsForKey(metadata.context_id) ?? {};
2483
+ }
2484
+ productPolicyRequestParamsForKey(key) {
2485
+ if (!key) return void 0;
2486
+ const state = this.productPolicyRequestParamsByTask.get(key);
2487
+ if (!state?.request) return void 0;
2488
+ this.productPolicyRequestParamsByTask.delete(key);
2489
+ this.productPolicyRequestParamsByTask.set(key, state);
2490
+ return state.request;
1332
2491
  }
1333
2492
  async applyProductPropertyPolicyToWebhookResult(result, metadata) {
1334
2493
  if (metadata.task_type !== "get_products" || metadata.status !== "completed" || !result) {
@@ -1373,17 +2532,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1373
2532
  * 3.1-only fields for a 3.0 seller). Returns the adapted params and any
1374
2533
  * drift log entries describing what was changed.
1375
2534
  *
1376
- * Runs after `detectServerVersion` so `cachedCapabilities` is populated
1377
- * and the protocol-version adapters see the seller's declared caps.
2535
+ * Runs after `detectServerVersion` so capabilities are available and the
2536
+ * current call's tool schemas can be supplied without cross-tenant caching.
1378
2537
  */
1379
- adaptRequest(taskType, params, serverVersion, debugLogs) {
2538
+ adaptRequest(taskType, params, serverVersion, debugLogs, perCallToolSchemas) {
1380
2539
  const driftLogs = [];
1381
2540
  let adapted = params;
1382
2541
  if (serverVersion !== "v3") {
1383
2542
  const pair = getV25Adapter(taskType);
1384
2543
  if (pair) adapted = pair.adaptRequest(adapted);
1385
2544
  }
1386
- const toolSchema = this.cachedToolSchemas?.get(taskType);
2545
+ const toolSchema = (perCallToolSchemas ?? this.cachedToolSchemas)?.get(taskType);
1387
2546
  if (toolSchema && Object.keys(toolSchema).length > 0) {
1388
2547
  const declaredFields = new Set(Object.keys(toolSchema));
1389
2548
  const adapterAliases = [["brand_manifest", "brand"]];
@@ -1523,30 +2682,57 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1523
2682
  * ```
1524
2683
  */
1525
2684
  async getProducts(params, inputHandler, options) {
2685
+ const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
2686
+ const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
2687
+ legacyFormatConverter,
2688
+ projectionCatalogs ?? this.config.projectionCatalogs
2689
+ );
2690
+ const account = canonicalAccountRoutingSnapshot(params.account);
1526
2691
  return this.executeAndHandle(
1527
2692
  "get_products",
1528
2693
  "onGetProductsStatusChange",
1529
2694
  params,
1530
2695
  inputHandler,
1531
- options
2696
+ taskOptions,
2697
+ (data) => {
2698
+ const { response, diagnostics } = toCanonicalOnlyResponse(data, {
2699
+ legacyFormatConverter: effectiveLegacyFormatConverter,
2700
+ projectionCatalogs: projectionCatalogs ?? this.config.projectionCatalogs
2701
+ });
2702
+ const authoritativeProducts = Array.isArray(data.products) ? data.products : response.products;
2703
+ this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts);
2704
+ const { _message: _dropLegacyMessage, ...canonical } = response;
2705
+ void _dropLegacyMessage;
2706
+ return { ...canonical, projection: { diagnostics } };
2707
+ },
2708
+ effectiveLegacyFormatConverter
1532
2709
  );
1533
2710
  }
2711
+ /** @deprecated Explicit raw-wire escape hatch for migration tooling. */
2712
+ async getProductsLegacy(params, inputHandler, options) {
2713
+ return this.executeTaskUnprojected("get_products", params, inputHandler, options);
2714
+ }
1534
2715
  /**
1535
- * List available creative formats
2716
+ * List a legacy named-format catalog for migration tooling.
1536
2717
  *
1537
2718
  * @param params - Format listing parameters
1538
2719
  * @param inputHandler - Handler for clarification requests
1539
2720
  * @param options - Task execution options
2721
+ * @deprecated Canonical applications discover `format_options[]` through `getProducts()`.
1540
2722
  */
1541
- async listCreativeFormats(params, inputHandler, options) {
2723
+ async listCreativeFormatsLegacy(params, inputHandler, options) {
1542
2724
  return this.executeAndHandle(
1543
2725
  "list_creative_formats",
1544
- "onListCreativeFormatsStatusChange",
2726
+ "onListCreativeFormatsLegacyStatusChange",
1545
2727
  params,
1546
2728
  inputHandler,
1547
2729
  options
1548
2730
  );
1549
2731
  }
2732
+ /** @deprecated Migration-only access to legacy creative transformer declarations. */
2733
+ async listTransformersLegacy(params, inputHandler, options) {
2734
+ return this.executeTaskUnprojected("list_transformers", params, inputHandler, options);
2735
+ }
1550
2736
  /**
1551
2737
  * Create a new media buy
1552
2738
  *
@@ -1555,6 +2741,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1555
2741
  * @param options - Task execution options
1556
2742
  */
1557
2743
  async createMediaBuy(params, inputHandler, options) {
2744
+ const { legacyFormatConverter, projectionCatalogs, canonicalFormatLegacyResolver, ...taskOptions } = options ?? {};
2745
+ const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
2746
+ legacyFormatConverter,
2747
+ projectionCatalogs ?? this.config.projectionCatalogs
2748
+ );
2749
+ const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
2750
+ canonicalFormatLegacyResolver,
2751
+ params.account
2752
+ );
2753
+ const hasCreativeFormatData = hasMediaBuyCreativeFormatData(params);
2754
+ if (hasCreativeFormatData) {
2755
+ this.validateBeforeCreativeCapabilityProbe("create_media_buy", params, taskOptions);
2756
+ }
2757
+ const wireMode = hasCreativeFormatData ? this.resolveCreativeFormatWireMode(
2758
+ "create_media_buy",
2759
+ await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
2760
+ ) : "canonical";
1558
2761
  if (this.config.webhookUrlTemplate && !options?.disableWebhook) {
1559
2762
  const now = /* @__PURE__ */ new Date();
1560
2763
  const year = now.getUTCFullYear();
@@ -1589,9 +2792,28 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1589
2792
  };
1590
2793
  }
1591
2794
  }
1592
- return this.executeAndHandle(
2795
+ const result = await this.executeAndHandle(
1593
2796
  "create_media_buy",
1594
2797
  "onCreateMediaBuyStatusChange",
2798
+ projectMediaBuyCreativesForDelivery(
2799
+ params,
2800
+ wireMode,
2801
+ "create_media_buy",
2802
+ effectiveLegacyFormatConverter,
2803
+ effectiveCanonicalFormatLegacyResolver
2804
+ ),
2805
+ inputHandler,
2806
+ taskOptions,
2807
+ void 0,
2808
+ effectiveLegacyFormatConverter,
2809
+ params
2810
+ );
2811
+ if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
2812
+ return result;
2813
+ }
2814
+ /** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
2815
+ async createMediaBuyLegacy(params, inputHandler, options) {
2816
+ return await this.createMediaBuy(
1595
2817
  params,
1596
2818
  inputHandler,
1597
2819
  options
@@ -1605,9 +2827,45 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1605
2827
  * @param options - Task execution options
1606
2828
  */
1607
2829
  async updateMediaBuy(params, inputHandler, options) {
1608
- return this.executeAndHandle(
2830
+ const { legacyFormatConverter, projectionCatalogs, canonicalFormatLegacyResolver, ...taskOptions } = options ?? {};
2831
+ const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
2832
+ legacyFormatConverter,
2833
+ projectionCatalogs ?? this.config.projectionCatalogs
2834
+ );
2835
+ const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
2836
+ canonicalFormatLegacyResolver,
2837
+ params.account
2838
+ );
2839
+ const hasCreativeFormatData = hasMediaBuyCreativeFormatData(params);
2840
+ if (hasCreativeFormatData) {
2841
+ this.validateBeforeCreativeCapabilityProbe("update_media_buy", params, taskOptions);
2842
+ }
2843
+ const wireMode = hasCreativeFormatData ? this.resolveCreativeFormatWireMode(
2844
+ "update_media_buy",
2845
+ await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
2846
+ ) : "canonical";
2847
+ const result = await this.executeAndHandle(
1609
2848
  "update_media_buy",
1610
2849
  "onUpdateMediaBuyStatusChange",
2850
+ projectMediaBuyCreativesForDelivery(
2851
+ params,
2852
+ wireMode,
2853
+ "update_media_buy",
2854
+ effectiveLegacyFormatConverter,
2855
+ effectiveCanonicalFormatLegacyResolver
2856
+ ),
2857
+ inputHandler,
2858
+ taskOptions,
2859
+ void 0,
2860
+ effectiveLegacyFormatConverter,
2861
+ params
2862
+ );
2863
+ if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
2864
+ return result;
2865
+ }
2866
+ /** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
2867
+ async updateMediaBuyLegacy(params, inputHandler, options) {
2868
+ return await this.updateMediaBuy(
1611
2869
  params,
1612
2870
  inputHandler,
1613
2871
  options
@@ -1621,41 +2879,149 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1621
2879
  * @param options - Task execution options
1622
2880
  */
1623
2881
  async syncCreatives(params, inputHandler, options) {
2882
+ const {
2883
+ creativeFormatProjection,
2884
+ legacyFormatConverter,
2885
+ projectionCatalogs,
2886
+ canonicalFormatLegacyResolver,
2887
+ ...taskOptions
2888
+ } = options ?? {};
2889
+ const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
2890
+ canonicalFormatLegacyResolver,
2891
+ params.account
2892
+ );
2893
+ const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
2894
+ creativeFormatProjection?.legacyFormatConverter ?? legacyFormatConverter,
2895
+ projectionCatalogs ?? this.config.projectionCatalogs
2896
+ );
2897
+ this.validateBeforeCreativeCapabilityProbe("sync_creatives", params, taskOptions);
2898
+ const wireMode = this.resolveCreativeFormatWireMode(
2899
+ "sync_creatives",
2900
+ await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
2901
+ );
2902
+ const configuredSelectorContainers = [
2903
+ ...creativeFormatProjection?.selectorContainers ?? []
2904
+ ];
2905
+ const configuredPackageIds = new Set(
2906
+ configuredSelectorContainers.flatMap(
2907
+ (container) => typeof container.package_id === "string" ? [container.package_id] : []
2908
+ )
2909
+ );
2910
+ const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
2911
+ (assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
2912
+ ) : [];
2913
+ const wireParams = projectSyncCreativesForDelivery(
2914
+ params,
2915
+ [...configuredSelectorContainers, ...assignmentPackageContainers],
2916
+ wireMode,
2917
+ effectiveLegacyFormatConverter,
2918
+ effectiveCanonicalFormatLegacyResolver
2919
+ );
1624
2920
  return this.executeAndHandle(
1625
2921
  "sync_creatives",
1626
2922
  "onSyncCreativesStatusChange",
2923
+ wireParams,
2924
+ inputHandler,
2925
+ taskOptions,
2926
+ void 0,
2927
+ effectiveLegacyFormatConverter,
2928
+ params
2929
+ );
2930
+ }
2931
+ /** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
2932
+ async syncCreativesLegacy(params, inputHandler, options) {
2933
+ return await this.syncCreatives(
1627
2934
  params,
1628
2935
  inputHandler,
1629
2936
  options
1630
2937
  );
1631
2938
  }
2939
+ resolveCreativeFormatWireMode(taskType, capabilities) {
2940
+ const wireRelease = this.config.wireAdcpVersion ?? this.resolvedAdcpVersion;
2941
+ const declared = resolveCreativeFormatWireMode(capabilities, wireRelease);
2942
+ const schema = creativeSchemaSupport(this.cachedToolSchemas?.get(taskType));
2943
+ if (declared !== "unknown" && schema !== "unknown" && declared !== schema) {
2944
+ throw new CreativeFormatCapabilityError(
2945
+ `Seller capability and ${taskType} input schema disagree about canonical creative support`
2946
+ );
2947
+ }
2948
+ const resolved = declared !== "unknown" ? declared : schema;
2949
+ const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
2950
+ const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
2951
+ if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
2952
+ throw new CreativeFormatCapabilityError(
2953
+ `Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
2954
+ );
2955
+ }
2956
+ return resolved;
2957
+ }
2958
+ /** Validate malformed creative payloads before capability discovery can perform I/O. */
2959
+ validateBeforeCreativeCapabilityProbe(taskType, params, options) {
2960
+ if (options.skipIdempotencyAutoInject || options.skipAccountValidation) return;
2961
+ let normalizedParams = normalizeRequestParams(taskType, params);
2962
+ if (isMutatingTask(taskType) && normalizedParams && typeof normalizedParams === "object" && !normalizedParams.idempotency_key) {
2963
+ normalizedParams = { ...normalizedParams, idempotency_key: generateIdempotencyKey() };
2964
+ }
2965
+ this.validateRequest(taskType, normalizedParams);
2966
+ }
1632
2967
  /**
1633
- * List creative assets
2968
+ * List creatives through the canonical SDK boundary.
2969
+ *
2970
+ * Legacy format filters are rejected and returned creative identities are
2971
+ * projected to `format_kind` / `format_option_ref`. Migration tooling that
2972
+ * needs the negotiated raw wire shape must call `listCreativesLegacy()`.
1634
2973
  *
1635
2974
  * @param params - Creative listing parameters
1636
2975
  * @param inputHandler - Handler for clarification requests
1637
2976
  * @param options - Task execution options
1638
2977
  */
1639
2978
  async listCreatives(params, inputHandler, options) {
2979
+ const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
2980
+ const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
2981
+ legacyFormatConverter,
2982
+ projectionCatalogs ?? this.config.projectionCatalogs
2983
+ );
1640
2984
  return this.executeAndHandle(
1641
2985
  "list_creatives",
1642
2986
  "onListCreativesStatusChange",
1643
2987
  params,
1644
2988
  inputHandler,
1645
- options
2989
+ taskOptions,
2990
+ (data) => {
2991
+ const { _message: _dropLegacyMessage, ...safe } = data;
2992
+ void _dropLegacyMessage;
2993
+ return {
2994
+ ...safe,
2995
+ creatives: data.creatives.map(
2996
+ (creative) => projectCreativeForDelivery(
2997
+ creative,
2998
+ {},
2999
+ "canonical",
3000
+ "list_creatives",
3001
+ effectiveLegacyFormatConverter
3002
+ )
3003
+ )
3004
+ };
3005
+ },
3006
+ effectiveLegacyFormatConverter
1646
3007
  );
1647
3008
  }
3009
+ /** @deprecated Explicit raw-wire escape hatch for migration tooling. */
3010
+ async listCreativesLegacy(params, inputHandler, options) {
3011
+ return this.executeTaskUnprojected("list_creatives", params, inputHandler, options);
3012
+ }
1648
3013
  /**
1649
- * Preview a creative
3014
+ * Preview a creative through the legacy named-format protocol.
1650
3015
  *
1651
3016
  * @param params - Preview creative parameters
1652
3017
  * @param inputHandler - Handler for clarification requests
1653
3018
  * @param options - Task execution options
3019
+ * @deprecated Migration-only access to `format_id`-based creative preview.
1654
3020
  */
1655
- async previewCreative(params, inputHandler, options) {
3021
+ async previewCreativeLegacy(params, inputHandler, options) {
1656
3022
  return this.executeAndHandle(
1657
3023
  "preview_creative",
1658
- "onPreviewCreativeStatusChange",
3024
+ "onPreviewCreativeLegacyStatusChange",
1659
3025
  params,
1660
3026
  inputHandler,
1661
3027
  options
@@ -1669,13 +3035,18 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1669
3035
  * @param options - Task execution options
1670
3036
  */
1671
3037
  async getMediaBuys(params, inputHandler, options) {
1672
- return this.executeAndHandle(
3038
+ const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
3039
+ const result = await this.executeAndHandle(
1673
3040
  "get_media_buys",
1674
3041
  "onGetMediaBuysStatusChange",
1675
3042
  params,
1676
3043
  inputHandler,
1677
- options
3044
+ taskOptions,
3045
+ void 0,
3046
+ this.resolveLegacyFormatConverter(legacyFormatConverter, projectionCatalogs ?? this.config.projectionCatalogs)
1678
3047
  );
3048
+ if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
3049
+ return result;
1679
3050
  }
1680
3051
  /**
1681
3052
  * Get media buy delivery information
@@ -1685,12 +3056,28 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1685
3056
  * @param options - Task execution options
1686
3057
  */
1687
3058
  async getMediaBuyDelivery(params, inputHandler, options) {
3059
+ const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
1688
3060
  return this.executeAndHandle(
1689
3061
  "get_media_buy_delivery",
1690
3062
  "onGetMediaBuyDeliveryStatusChange",
1691
3063
  params,
1692
3064
  inputHandler,
1693
- options
3065
+ taskOptions,
3066
+ void 0,
3067
+ this.resolveLegacyFormatConverter(legacyFormatConverter, projectionCatalogs ?? this.config.projectionCatalogs)
3068
+ );
3069
+ }
3070
+ /** Retrieve canonical creative-level and variant-level delivery metrics. */
3071
+ async getCreativeDelivery(params, inputHandler, options) {
3072
+ const { legacyFormatConverter, ...taskOptions } = options ?? {};
3073
+ return this.executeAndHandle(
3074
+ "get_creative_delivery",
3075
+ "onGetCreativeDeliveryStatusChange",
3076
+ params,
3077
+ inputHandler,
3078
+ taskOptions,
3079
+ void 0,
3080
+ legacyFormatConverter
1694
3081
  );
1695
3082
  }
1696
3083
  /**
@@ -1817,12 +3204,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1817
3204
  }
1818
3205
  // ====== CREATIVE BUILD TASKS ======
1819
3206
  /**
1820
- * Build a creative from a format and brand context
3207
+ * Build a creative through the legacy named-format protocol.
3208
+ * @deprecated Migration-only access to `target_format_id`-based creative building.
1821
3209
  */
1822
- async buildCreative(params, inputHandler, options) {
3210
+ async buildCreativeLegacy(params, inputHandler, options) {
1823
3211
  return this.executeAndHandle(
1824
3212
  "build_creative",
1825
- "onBuildCreativeStatusChange",
3213
+ "onBuildCreativeLegacyStatusChange",
1826
3214
  params,
1827
3215
  inputHandler,
1828
3216
  options
@@ -1929,10 +3317,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1929
3317
  /**
1930
3318
  * List content standards
1931
3319
  */
1932
- async listContentStandards(params, inputHandler, options) {
3320
+ async listContentStandardsLegacy(params, inputHandler, options) {
1933
3321
  return this.executeAndHandle(
1934
3322
  "list_content_standards",
1935
- "onListContentStandardsStatusChange",
3323
+ "onListContentStandardsLegacyStatusChange",
1936
3324
  params,
1937
3325
  inputHandler,
1938
3326
  options
@@ -1941,10 +3329,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1941
3329
  /**
1942
3330
  * Get content standards
1943
3331
  */
1944
- async getContentStandards(params, inputHandler, options) {
3332
+ async getContentStandardsLegacy(params, inputHandler, options) {
1945
3333
  return this.executeAndHandle(
1946
3334
  "get_content_standards",
1947
- "onGetContentStandardsStatusChange",
3335
+ "onGetContentStandardsLegacyStatusChange",
1948
3336
  params,
1949
3337
  inputHandler,
1950
3338
  options
@@ -1953,10 +3341,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1953
3341
  /**
1954
3342
  * Calibrate content against standards
1955
3343
  */
1956
- async calibrateContent(params, inputHandler, options) {
3344
+ async calibrateContentLegacy(params, inputHandler, options) {
1957
3345
  return this.executeAndHandle(
1958
3346
  "calibrate_content",
1959
- "onCalibrateContentStatusChange",
3347
+ "onCalibrateContentLegacyStatusChange",
1960
3348
  params,
1961
3349
  inputHandler,
1962
3350
  options
@@ -1965,10 +3353,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
1965
3353
  /**
1966
3354
  * Validate content delivery
1967
3355
  */
1968
- async validateContentDelivery(params, inputHandler, options) {
3356
+ async validateContentDeliveryLegacy(params, inputHandler, options) {
1969
3357
  return this.executeAndHandle(
1970
3358
  "validate_content_delivery",
1971
- "onValidateContentDeliveryStatusChange",
3359
+ "onValidateContentDeliveryLegacyStatusChange",
1972
3360
  params,
1973
3361
  inputHandler,
1974
3362
  options
@@ -2023,25 +3411,62 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2023
3411
  options
2024
3412
  );
2025
3413
  }
2026
- // ====== GENERIC TASK EXECUTION ======
3414
+ async executeTask(taskName, params, inputHandler, options) {
3415
+ switch (taskName) {
3416
+ case "get_products":
3417
+ return this.getProducts(params, inputHandler, options);
3418
+ case "create_media_buy":
3419
+ return await this.createMediaBuy(
3420
+ params,
3421
+ inputHandler,
3422
+ options
3423
+ );
3424
+ case "update_media_buy":
3425
+ return await this.updateMediaBuy(
3426
+ params,
3427
+ inputHandler,
3428
+ options
3429
+ );
3430
+ case "sync_creatives":
3431
+ return await this.syncCreatives(
3432
+ params,
3433
+ inputHandler,
3434
+ options
3435
+ );
3436
+ case "list_creatives":
3437
+ return this.listCreatives(params, inputHandler, options);
3438
+ case "get_media_buys":
3439
+ return this.getMediaBuys(params, inputHandler, options);
3440
+ case "get_media_buy_delivery":
3441
+ return this.getMediaBuyDelivery(params, inputHandler, options);
3442
+ case "get_creative_delivery":
3443
+ return this.getCreativeDelivery(params, inputHandler, options);
3444
+ }
3445
+ return this.executeTaskUnprojected(taskName, params, inputHandler, options);
3446
+ }
2027
3447
  /**
2028
- * Execute any task by name with type safety
2029
- *
2030
- * @param taskName - Name of the task to execute
2031
- * @param params - Task parameters
2032
- * @param inputHandler - Handler for clarification requests
2033
- * @param options - Task execution options
3448
+ * Execute an extension task that is not part of the standard AdCP task set.
2034
3449
  *
2035
- * @example
2036
- * ```typescript
2037
- * const result = await client.executeTask(
2038
- * 'get_products',
2039
- * { brief: 'Coffee brands' },
2040
- * handler
2041
- * );
2042
- * ```
3450
+ * Keeping custom tasks on an explicitly named API prevents a response-type
3451
+ * generic from weakening the canonical request types enforced by
3452
+ * `executeTask()` for standard creative-boundary tasks.
2043
3453
  */
2044
- async executeTask(taskName, params, inputHandler, options) {
3454
+ async executeCustomTask(taskName, params, inputHandler, options) {
3455
+ if (STANDARD_ADCP_TASK_NAMES.has(taskName)) {
3456
+ throw new Error(
3457
+ `executeCustomTask() cannot execute standard AdCP task "${taskName}". Use its typed primary method, or an explicitly named *Legacy method for legacy creative tools.`
3458
+ );
3459
+ }
3460
+ return this.executeTaskUnprojected(taskName, params, inputHandler, options);
3461
+ }
3462
+ /**
3463
+ * Explicit raw-task compatibility escape hatch for conformance and migration tooling.
3464
+ * @deprecated Application code should use typed primary methods or `executeTask()`.
3465
+ */
3466
+ async executeTaskLegacy(taskName, params, inputHandler, options) {
3467
+ return this.executeTaskUnprojected(taskName, params, inputHandler, options);
3468
+ }
3469
+ async executeTaskUnprojected(taskName, params, inputHandler, options) {
2045
3470
  throwIfAborted(options?.signal);
2046
3471
  const startTime = Date.now();
2047
3472
  try {
@@ -2062,13 +3487,19 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2062
3487
  if (!options?.skipIdempotencyAutoInject && !options?.skipAccountValidation) {
2063
3488
  this.executor.validateRequest(taskName, normalizedParams);
2064
3489
  }
2065
- const serverVersion = await this.detectServerVersion(options);
3490
+ const capabilityDiscoveryContext = {};
3491
+ const detectionOptions = {
3492
+ ...options,
3493
+ [CAPABILITY_DISCOVERY_CONTEXT]: capabilityDiscoveryContext
3494
+ };
3495
+ const serverVersion = await this.detectServerVersion(detectionOptions);
2066
3496
  const inputSchemaStripLogs = [];
2067
3497
  const { params: adaptedParams, driftLogs: adaptDriftLogs } = this.adaptRequest(
2068
3498
  taskName,
2069
3499
  normalizedParams,
2070
3500
  serverVersion,
2071
- inputSchemaStripLogs
3501
+ inputSchemaStripLogs,
3502
+ capabilityDiscoveryContext.toolSchemas
2072
3503
  );
2073
3504
  const v25DriftLogs = [...adaptDriftLogs];
2074
3505
  if (webhookDriftLog) v25DriftLogs.push(webhookDriftLog);
@@ -2090,8 +3521,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2090
3521
  if (result.success && result.data) {
2091
3522
  result.data = this.normalizeResponseToV3(taskName, result.data);
2092
3523
  }
2093
- result = this.wrapProductPolicySubmittedContinuation(result, taskName, normalizedParams);
2094
- this.rememberProductPolicyRequestParams(taskName, normalizedParams, result, options);
3524
+ result = this.wrapProductPolicySubmittedContinuation(result, taskName, normalizedParams, options);
3525
+ if (result.status === "working") {
3526
+ this.rememberProductPolicyRequestParams(taskName, normalizedParams, result, options);
3527
+ }
2095
3528
  result = await this.applyProductPropertyPolicy(result, taskName, normalizedParams);
2096
3529
  return result;
2097
3530
  } catch (error) {
@@ -2169,19 +3602,58 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2169
3602
  */
2170
3603
  async continueConversation(message, contextId, inputHandler) {
2171
3604
  const agent = await this.ensureEndpointDiscovered();
2172
- return this.executor.executeTask(agent, "continue_conversation", { message }, inputHandler, { contextId });
3605
+ const creativeAssociation = this.canonicalCreativeTaskAssociation(contextId);
3606
+ if (!creativeAssociation) {
3607
+ return this.executor.executeTask(agent, "continue_conversation", { message }, inputHandler, { contextId });
3608
+ }
3609
+ const { taskType: creativeTaskType } = creativeAssociation;
3610
+ const legacyFormatConverter = this.resolveLegacyFormatConverter(creativeAssociation.legacyFormatConverter);
3611
+ const result = await canonicalCreativeExecutionStorage.run(
3612
+ { taskType: creativeTaskType, legacyFormatConverter },
3613
+ () => this.executor.executeTask(
3614
+ agent,
3615
+ "continue_conversation",
3616
+ { message },
3617
+ this.canonicalCreativeInputHandler(creativeTaskType, inputHandler),
3618
+ { contextId }
3619
+ )
3620
+ );
3621
+ const canonical = this.canonicalizeCreativeTaskResult(result, creativeTaskType, void 0, legacyFormatConverter);
3622
+ this.rememberCanonicalCreativeTaskIds(
3623
+ canonical,
3624
+ creativeTaskType,
3625
+ legacyFormatConverter,
3626
+ creativeAssociation.routingSnapshot
3627
+ );
3628
+ return this.wrapCanonicalCreativeContinuations(
3629
+ canonical,
3630
+ creativeTaskType,
3631
+ void 0,
3632
+ legacyFormatConverter,
3633
+ creativeAssociation.routingSnapshot
3634
+ );
2173
3635
  }
2174
3636
  /**
2175
3637
  * Get conversation history for a task
2176
3638
  */
2177
3639
  getConversationHistory(taskId) {
2178
- return this.executor.getConversationHistory(taskId);
3640
+ const history = this.executor.getConversationHistory(taskId);
3641
+ const association = this.canonicalCreativeTaskAssociation(taskId);
3642
+ if (!association) return history;
3643
+ const { taskType } = association;
3644
+ const converter = this.resolveLegacyFormatConverter(association.legacyFormatConverter);
3645
+ return history?.map((message) => ({
3646
+ ...message,
3647
+ content: projectCanonicalCreativeAncillaryValue(message.content, taskType, converter)
3648
+ }));
2179
3649
  }
2180
3650
  /**
2181
3651
  * Clear conversation history for a task
2182
3652
  */
2183
3653
  clearConversationHistory(taskId) {
2184
3654
  this.executor.clearConversationHistory(taskId);
3655
+ this.forgetCanonicalCreativeTaskAssociationKeys([taskId]);
3656
+ this.productPolicyRequestParamsByTask.delete(taskId);
2185
3657
  }
2186
3658
  // ====== AGENT INFORMATION ======
2187
3659
  /**
@@ -2322,7 +3794,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2322
3794
  * Get active tasks for this agent
2323
3795
  */
2324
3796
  getActiveTasks() {
2325
- return this.executor.getActiveTasks().filter((task) => task.agent.id === this.agent.id);
3797
+ return this.executor.getActiveTasks().filter((task) => task.agent.id === this.agent.id).map((task) => {
3798
+ if (!CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskName)) return task;
3799
+ const converter = this.resolveLegacyFormatConverter(
3800
+ this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter
3801
+ );
3802
+ return stripLegacyCreativeIdentity({
3803
+ ...task,
3804
+ params: projectCanonicalCreativeAncillaryValue(task.params, task.taskName, converter),
3805
+ messages: task.messages.map((message) => ({
3806
+ ...message,
3807
+ content: projectCanonicalCreativeAncillaryValue(message.content, task.taskName, converter)
3808
+ })),
3809
+ ...task.pendingInput !== void 0 && {
3810
+ pendingInput: projectCanonicalCreativeAncillaryValue(task.pendingInput, task.taskName, converter)
3811
+ }
3812
+ });
3813
+ });
2326
3814
  }
2327
3815
  // ====== TASK MANAGEMENT & NOTIFICATIONS ======
2328
3816
  /**
@@ -2339,7 +3827,15 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2339
3827
  * ```
2340
3828
  */
2341
3829
  async listTasks() {
2342
- return this.executor.getTaskList(this.agent.id);
3830
+ const tasks = await this.executor.getTaskList(this.agent.id);
3831
+ return tasks.map(
3832
+ (task) => CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
3833
+ task,
3834
+ task.taskType,
3835
+ void 0,
3836
+ this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
3837
+ ) : task
3838
+ );
2343
3839
  }
2344
3840
  /**
2345
3841
  * Get detailed information about a specific task
@@ -2348,7 +3844,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2348
3844
  * @returns Promise resolving to task information
2349
3845
  */
2350
3846
  async getTaskInfo(taskId) {
2351
- return this.executor.getTaskInfo(taskId);
3847
+ const task = await this.executor.getTaskInfo(taskId);
3848
+ return task && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
3849
+ task,
3850
+ task.taskType,
3851
+ void 0,
3852
+ this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
3853
+ ) : task;
2352
3854
  }
2353
3855
  /**
2354
3856
  * Subscribe to task notifications for this agent
@@ -2370,7 +3872,19 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2370
3872
  * ```
2371
3873
  */
2372
3874
  onTaskUpdate(callback) {
2373
- return this.executor.onTaskUpdate(this.agent.id, callback);
3875
+ return this.executor.onTaskUpdate(
3876
+ this.agent.id,
3877
+ (task) => callback(
3878
+ CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
3879
+ task,
3880
+ task.taskType,
3881
+ void 0,
3882
+ this.resolveLegacyFormatConverter(
3883
+ this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter
3884
+ )
3885
+ ) : task
3886
+ )
3887
+ );
2374
3888
  }
2375
3889
  /**
2376
3890
  * Subscribe to all task events (create, update, complete, error)
@@ -2379,7 +3893,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2379
3893
  * @returns Unsubscribe function
2380
3894
  */
2381
3895
  onTaskEvents(callbacks) {
2382
- return this.executor.onTaskEvents(this.agent.id, callbacks);
3896
+ const safe = (task) => CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
3897
+ task,
3898
+ task.taskType,
3899
+ void 0,
3900
+ this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
3901
+ ) : task;
3902
+ return this.executor.onTaskEvents(this.agent.id, {
3903
+ ...callbacks.onTaskCreated && { onTaskCreated: (task) => callbacks.onTaskCreated(safe(task)) },
3904
+ ...callbacks.onTaskUpdated && { onTaskUpdated: (task) => callbacks.onTaskUpdated(safe(task)) },
3905
+ ...callbacks.onTaskCompleted && { onTaskCompleted: (task) => callbacks.onTaskCompleted(safe(task)) },
3906
+ ...callbacks.onTaskFailed && {
3907
+ onTaskFailed: (task, error) => {
3908
+ const safeTask = safe(task);
3909
+ callbacks.onTaskFailed(safeTask, safeTask.error ?? stripLegacyCreativeIdentity(error));
3910
+ }
3911
+ }
3912
+ });
2383
3913
  }
2384
3914
  /**
2385
3915
  * Register webhook URL for receiving task notifications
@@ -2443,6 +3973,16 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2443
3973
  ...options?.signal && { signal: options.signal },
2444
3974
  ...clientRequestTimeoutMs !== void 0 && { timeout: clientRequestTimeoutMs }
2445
3975
  };
3976
+ const ensureReadAuthToken = async () => {
3977
+ if (!this.normalizedAgent.oauth_client_credentials) return this.normalizedAgent.auth_token;
3978
+ const { ensureClientCredentialsTokens, getAgentStorage } = await import("../auth/oauth/index.mjs");
3979
+ await ensureClientCredentialsTokens(this.normalizedAgent, {
3980
+ storage: getAgentStorage(this.normalizedAgent),
3981
+ allowPrivateIp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri),
3982
+ fetch: transport?.fetchFn
3983
+ });
3984
+ return this.normalizedAgent.oauth_tokens?.access_token;
3985
+ };
2446
3986
  if (this.normalizedAgent.protocol === "mcp") {
2447
3987
  if (this.normalizedAgent._inProcessMcpClient) {
2448
3988
  const mcpClient2 = this.normalizedAgent._inProcessMcpClient;
@@ -2464,6 +4004,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2464
4004
  tools
2465
4005
  };
2466
4006
  }
4007
+ const readAuthToken = await ensureReadAuthToken();
2467
4008
  const agent = await this.ensureEndpointDiscovered(options);
2468
4009
  const { connectMCP } = await import("../protocols/mcp.mjs");
2469
4010
  const { tryListModernMCPTools } = await import("../protocols/mcp-modern.mjs");
@@ -2474,25 +4015,32 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2474
4015
  if (transport?.requestTimeoutMs !== void 0) {
2475
4016
  connectOptions.requestTimeoutMs = transport.requestTimeoutMs;
2476
4017
  }
4018
+ if (transport?.fetchFn) {
4019
+ connectOptions.fetchFn = transport.fetchFn;
4020
+ }
2477
4021
  if (this.normalizedAgent.headers && Object.keys(this.normalizedAgent.headers).length > 0) {
2478
4022
  connectOptions.customHeaders = this.normalizedAgent.headers;
2479
4023
  }
2480
4024
  let authProvider;
2481
- if (this.normalizedAgent.oauth_tokens) {
2482
- const { createNonInteractiveOAuthProvider } = await import("../auth/oauth/index.mjs");
2483
- authProvider = createNonInteractiveOAuthProvider(this.normalizedAgent, {
2484
- agentHint: this.normalizedAgent.id
4025
+ if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
4026
+ const { getAgentStorage } = await import("../auth/oauth/index.mjs");
4027
+ const { getNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
4028
+ authProvider = getNonInteractiveOAuthProvider(this.normalizedAgent, {
4029
+ agentHint: this.normalizedAgent.id,
4030
+ storage: getAgentStorage(this.normalizedAgent),
4031
+ allowHttp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri)
2485
4032
  });
2486
4033
  connectOptions.authProvider = authProvider;
2487
- } else if (this.normalizedAgent.auth_token) {
2488
- connectOptions.authToken = this.normalizedAgent.auth_token;
4034
+ } else if (readAuthToken) {
4035
+ connectOptions.authToken = readAuthToken;
2489
4036
  }
2490
- const modernTools = this.discoveredMcpEra === "legacy" && Date.now() - this.discoveredMcpEraAt < 5 * 60 * 1e3 ? { handled: false } : await withResponseSizeLimit(
4037
+ const modernTools = !transport?.fetchFn && this.discoveredMcpEra === "legacy" && Date.now() - this.discoveredMcpEraAt < 5 * 60 * 1e3 ? { handled: false } : await withResponseSizeLimit(
2491
4038
  maxResponseBytes,
2492
- () => tryListModernMCPTools(agent.agent_uri, this.normalizedAgent.auth_token, this.normalizedAgent.headers, {
4039
+ () => tryListModernMCPTools(agent.agent_uri, readAuthToken, this.normalizedAgent.headers, {
2493
4040
  authProvider,
2494
4041
  signal: options?.signal,
2495
- requestTimeoutMs: transport?.requestTimeoutMs
4042
+ requestTimeoutMs: transport?.requestTimeoutMs,
4043
+ fetchFn: transport?.fetchFn
2496
4044
  })
2497
4045
  );
2498
4046
  if (modernTools.handled) {
@@ -2537,9 +4085,11 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2537
4085
  }
2538
4086
  } else if (this.normalizedAgent.protocol === "a2a") {
2539
4087
  const { wrapFetchWithSizeLimit } = await import("../protocols/responseSizeLimit.mjs");
2540
- const authToken = this.normalizedAgent.auth_token;
4088
+ const authToken = await ensureReadAuthToken();
2541
4089
  const agentHeaders = this.normalizedAgent.headers ?? {};
2542
- const sizeLimitedFetch = wrapFetchWithSizeLimit((input, init) => fetch(input, init));
4090
+ const sizeLimitedFetch = wrapFetchWithSizeLimit(
4091
+ (input, init) => transport?.fetchFn ? transport.fetchFn(input, init) : fetch(input, init)
4092
+ );
2543
4093
  const normalizeHeaders = (headers) => {
2544
4094
  const normalized = {};
2545
4095
  if (!headers) return normalized;
@@ -2630,7 +4180,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2630
4180
  */
2631
4181
  async getCapabilities(options) {
2632
4182
  throwIfAborted(options?.signal);
2633
- if (this.cachedCapabilities) {
4183
+ const discoveryContext = options?.[CAPABILITY_DISCOVERY_CONTEXT];
4184
+ const usesScopedFetch = (options?.transport ?? this.config.transport)?.fetchFn !== void 0;
4185
+ if (!usesScopedFetch && this.cachedCapabilities) {
4186
+ if (discoveryContext) discoveryContext.toolSchemas = this.cachedToolSchemas;
2634
4187
  this.maybeWarnV2Sunset(this.cachedCapabilities);
2635
4188
  return this.cachedCapabilities;
2636
4189
  }
@@ -2639,10 +4192,14 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2639
4192
  name: t.name,
2640
4193
  description: t.description
2641
4194
  }));
2642
- this.cachedToolSchemas = new Map(
4195
+ const discoveredToolSchemas = new Map(
2643
4196
  agentInfo.tools.filter((t) => t.inputSchema?.properties).map((t) => [t.name, t.inputSchema.properties])
2644
4197
  );
2645
- const hasCapabilitiesTool = tools.some((t) => t.name === "get_adcp_capabilities");
4198
+ if (discoveryContext) discoveryContext.toolSchemas = discoveredToolSchemas;
4199
+ if (!usesScopedFetch) this.cachedToolSchemas = discoveredToolSchemas;
4200
+ const advertisesCapabilitiesTool = tools.some((t) => t.name === "get_adcp_capabilities");
4201
+ const officialA2ALifecycle = this.normalizedAgent.protocol === "a2a" && tools.some((tool) => ["tasks/get", "get_task_status", "list_tasks"].includes(tool.name));
4202
+ const hasCapabilitiesTool = advertisesCapabilitiesTool || officialA2ALifecycle;
2646
4203
  if (hasCapabilitiesTool) {
2647
4204
  try {
2648
4205
  const agent = await this.ensureEndpointDiscovered(options);
@@ -2655,9 +4212,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2655
4212
  throw createTimeoutError(requestTimeoutMs);
2656
4213
  }
2657
4214
  if (result.success && result.data) {
2658
- this.cachedCapabilities = augmentCapabilitiesFromTools(parseCapabilitiesResponse(result.data), tools);
2659
- this.maybeWarnV2Sunset(this.cachedCapabilities);
2660
- return this.cachedCapabilities;
4215
+ const capabilities2 = augmentCapabilitiesFromTools(parseCapabilitiesResponse(result.data), tools);
4216
+ if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
4217
+ this.maybeWarnV2Sunset(capabilities2);
4218
+ return capabilities2;
4219
+ }
4220
+ if (!advertisesCapabilitiesTool) {
4221
+ throw new Error("unadvertised official A2A capability probe was not supported");
2661
4222
  }
2662
4223
  if (result.data && looksLikeV3Capabilities(result.data)) {
2663
4224
  console.warn(
@@ -2670,9 +4231,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2670
4231
  version: "v3",
2671
4232
  majorVersions: parsed.majorVersions.includes(3) ? parsed.majorVersions : [3]
2672
4233
  };
2673
- this.cachedCapabilities = augmentCapabilitiesFromTools(v3Capabilities, tools);
2674
- this.maybeWarnV2Sunset(this.cachedCapabilities);
2675
- return this.cachedCapabilities;
4234
+ const capabilities2 = augmentCapabilitiesFromTools(v3Capabilities, tools);
4235
+ if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
4236
+ this.maybeWarnV2Sunset(capabilities2);
4237
+ return capabilities2;
2676
4238
  }
2677
4239
  console.warn(
2678
4240
  `[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call returned non-success and the response is not v3-shaped \u2014 treating as v3 (synthetic) since the agent has the v3-only discovery tool. This client routes to v3 adapters, but calls reading capability details (idempotency TTL, supported_versions, feature flags) will fail until the agent operator fixes the capabilities endpoint.`,
@@ -2686,19 +4248,25 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2686
4248
  if (error instanceof AuthenticationRequiredError || error instanceof TaskTimeoutError || isAbortOrTimeoutError(error)) {
2687
4249
  throw error;
2688
4250
  }
2689
- console.warn(
2690
- `[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call threw \u2014 treating as v3 (synthetic) since the agent has the v3-only discovery tool. This client routes to v3 adapters, but calls reading capability details (idempotency TTL, supported_versions, feature flags) will fail until the agent operator fixes the capabilities endpoint.`
2691
- );
4251
+ if (advertisesCapabilitiesTool) {
4252
+ console.warn(
4253
+ `[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call threw \u2014 treating as v3 (synthetic) since the agent has the v3-only discovery tool. This client routes to v3 adapters, but calls reading capability details (idempotency TTL, supported_versions, feature flags) will fail until the agent operator fixes the capabilities endpoint.`
4254
+ );
4255
+ }
4256
+ }
4257
+ if (advertisesCapabilitiesTool) {
4258
+ const capabilities2 = augmentCapabilitiesFromTools(buildSyntheticV3Capabilities(tools), tools);
4259
+ if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
4260
+ this.maybeWarnV2Sunset(capabilities2);
4261
+ return capabilities2;
2692
4262
  }
2693
- this.cachedCapabilities = augmentCapabilitiesFromTools(buildSyntheticV3Capabilities(tools), tools);
2694
- this.maybeWarnV2Sunset(this.cachedCapabilities);
2695
- return this.cachedCapabilities;
2696
4263
  }
2697
4264
  console.warn(
2698
4265
  `[AdCP] Agent "${this.agent.id}" detected as v2 (no get_adcp_capabilities tool). Tools: [${tools.map((t) => t.name).join(", ")}]`
2699
4266
  );
2700
- this.cachedCapabilities = buildSyntheticCapabilities(tools);
2701
- return this.cachedCapabilities;
4267
+ const capabilities = buildSyntheticCapabilities(tools);
4268
+ if (!usesScopedFetch) this.cachedCapabilities = capabilities;
4269
+ return capabilities;
2702
4270
  }
2703
4271
  /**
2704
4272
  * Emit a one-time warning when the agent reports v2 capabilities.
@@ -3011,38 +4579,18 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3011
4579
  }
3012
4580
  // ====== STATIC HELPER METHODS ======
3013
4581
  /**
3014
- * Query a creative agent to discover available creative formats
4582
+ * Query a legacy creative-agent named-format catalog.
3015
4583
  *
3016
- * This is a static utility method that allows you to query any creative agent
3017
- * (like creative.adcontextprotocol.org) to discover what formats are available
3018
- * before creating a media buy.
4584
+ * Canonical applications discover seller-supported declarations through
4585
+ * `AgentClient.getProducts()` and consume `format_options[]` instead.
3019
4586
  *
3020
4587
  * @param creativeAgentUrl - URL of the creative agent (e.g., 'https://creative.adcontextprotocol.org/mcp')
3021
4588
  * @param protocol - Protocol to use ('mcp' or 'a2a'), defaults to 'mcp'
3022
4589
  * @returns Promise resolving to the list of available formats
3023
4590
  *
3024
- * @example
3025
- * ```typescript
3026
- * // Discover formats from the standard creative agent
3027
- * const formats = await SingleAgentClient.discoverCreativeFormats(
3028
- * 'https://creative.adcontextprotocol.org/mcp'
3029
- * );
3030
- *
3031
- * // Find a specific format
3032
- * const banner = formats.find(f => f.format_id.id === 'display_300x250_image');
3033
- *
3034
- * // Use the format in a media buy
3035
- * await salesAgent.createMediaBuy({
3036
- * packages: [{
3037
- * format_ids: [{
3038
- * agent_url: banner.format_id.agent_url,
3039
- * id: banner.format_id.id
3040
- * }]
3041
- * }]
3042
- * });
3043
- * ```
4591
+ * @deprecated Migration-only helper for the legacy named-format protocol.
3044
4592
  */
3045
- static async discoverCreativeFormats(creativeAgentUrl, protocol = "mcp") {
4593
+ static async discoverCreativeFormatsLegacy(creativeAgentUrl, protocol = "mcp") {
3046
4594
  const client = new SingleAgentClient(
3047
4595
  {
3048
4596
  id: "creative_agent_discovery",
@@ -3052,7 +4600,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3052
4600
  },
3053
4601
  {}
3054
4602
  );
3055
- const result = await client.listCreativeFormats({});
4603
+ const result = await client.listCreativeFormatsLegacy({});
3056
4604
  if (!result.success || !result.data) {
3057
4605
  throw new Error(`Failed to discover creative formats: ${result.error || "Unknown error"}`);
3058
4606
  }
@@ -3132,12 +4680,11 @@ function parseWebhookBody(value) {
3132
4680
  const raw = Buffer.isBuffer(value) || value instanceof Uint8Array ? Buffer.from(value).toString("utf8") : value;
3133
4681
  try {
3134
4682
  return { ok: true, payload: JSON.parse(raw) };
3135
- } catch (error) {
4683
+ } catch {
3136
4684
  return {
3137
4685
  ok: false,
3138
4686
  code: "webhook_envelope_invalid",
3139
- message: "Webhook body must be valid JSON.",
3140
- cause: error
4687
+ message: "Webhook body must be valid JSON."
3141
4688
  };
3142
4689
  }
3143
4690
  }
@@ -3158,13 +4705,6 @@ function missingMcpWebhookFields(payload) {
3158
4705
  return typeof value !== "string" || value.length === 0;
3159
4706
  });
3160
4707
  }
3161
- function safeJsonPreview(value) {
3162
- try {
3163
- return JSON.stringify(value).substring(0, 200);
3164
- } catch {
3165
- return "[unserializable payload]";
3166
- }
3167
- }
3168
4708
  function webhookErrorHttpStatus(error) {
3169
4709
  if (error instanceof WebhookDispatchError) {
3170
4710
  if (error.code === "webhook_signature_invalid" || error.code === "webhook_timestamp_invalid") {