@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
@@ -0,0 +1,8 @@
1
+ import { createNonInteractiveOAuthProvider } from './index';
2
+ import type { MCPOAuthProvider } from './MCPOAuthProvider';
3
+ import type { AgentConfig } from './types';
4
+ /** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */
5
+ export declare function getNonInteractiveOAuthProvider(agent: AgentConfig, options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]): MCPOAuthProvider;
6
+ /** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */
7
+ export declare function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void;
8
+ //# sourceMappingURL=provider-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-cache.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,iCAAiC,CAAC,CAAC,CAAC,CAAC,GAChE,gBAAgB,CAOlB;AAED,+FAA+F;AAC/F,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAG/F"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var provider_cache_exports = {};
20
+ __export(provider_cache_exports, {
21
+ getNonInteractiveOAuthProvider: () => getNonInteractiveOAuthProvider,
22
+ shareNonInteractiveOAuthProvider: () => shareNonInteractiveOAuthProvider
23
+ });
24
+ module.exports = __toCommonJS(provider_cache_exports);
25
+ var import_index = require('./index.js');
26
+ const nonInteractiveOAuthProviderCache = /* @__PURE__ */ new WeakMap();
27
+ function getNonInteractiveOAuthProvider(agent, options) {
28
+ let provider = nonInteractiveOAuthProviderCache.get(agent);
29
+ if (!provider) {
30
+ provider = (0, import_index.createNonInteractiveOAuthProvider)(agent, options);
31
+ nonInteractiveOAuthProviderCache.set(agent, provider);
32
+ }
33
+ return provider;
34
+ }
35
+ function shareNonInteractiveOAuthProvider(source, target) {
36
+ const provider = nonInteractiveOAuthProviderCache.get(source);
37
+ if (provider) nonInteractiveOAuthProviderCache.set(target, provider);
38
+ }
39
+ // Annotate the CommonJS export names for ESM import in node:
40
+ 0 && (module.exports = {
41
+ getNonInteractiveOAuthProvider,
42
+ shareNonInteractiveOAuthProvider
43
+ });
44
+ //# sourceMappingURL=provider-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"sourcesContent":["import { createNonInteractiveOAuthProvider } from './index';\nimport type { MCPOAuthProvider } from './MCPOAuthProvider';\nimport type { AgentConfig } from './types';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<AgentConfig, MCPOAuthProvider>();\n\n/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */\nexport function getNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]\n): MCPOAuthProvider {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n provider = createNonInteractiveOAuthProvider(agent, options);\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */\nexport function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void {\n const provider = nonInteractiveOAuthProviderCache.get(source);\n if (provider) nonInteractiveOAuthProviderCache.set(target, provider);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkD;AAIlD,MAAM,mCAAmC,oBAAI,QAAuC;AAG7E,SAAS,+BACd,OACA,SACkB;AAClB,MAAI,WAAW,iCAAiC,IAAI,KAAK;AACzD,MAAI,CAAC,UAAU;AACb,mBAAW,gDAAkC,OAAO,OAAO;AAC3D,qCAAiC,IAAI,OAAO,QAAQ;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,iCAAiC,QAAqB,QAA2B;AAC/F,QAAM,WAAW,iCAAiC,IAAI,MAAM;AAC5D,MAAI,SAAU,kCAAiC,IAAI,QAAQ,QAAQ;AACrE;","names":[]}
@@ -0,0 +1,19 @@
1
+ import { createNonInteractiveOAuthProvider } from "./index.mjs";
2
+ const nonInteractiveOAuthProviderCache = /* @__PURE__ */ new WeakMap();
3
+ function getNonInteractiveOAuthProvider(agent, options) {
4
+ let provider = nonInteractiveOAuthProviderCache.get(agent);
5
+ if (!provider) {
6
+ provider = createNonInteractiveOAuthProvider(agent, options);
7
+ nonInteractiveOAuthProviderCache.set(agent, provider);
8
+ }
9
+ return provider;
10
+ }
11
+ function shareNonInteractiveOAuthProvider(source, target) {
12
+ const provider = nonInteractiveOAuthProviderCache.get(source);
13
+ if (provider) nonInteractiveOAuthProviderCache.set(target, provider);
14
+ }
15
+ export {
16
+ getNonInteractiveOAuthProvider,
17
+ shareNonInteractiveOAuthProvider
18
+ };
19
+ //# sourceMappingURL=provider-cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"sourcesContent":["import { createNonInteractiveOAuthProvider } from './index';\nimport type { MCPOAuthProvider } from './MCPOAuthProvider';\nimport type { AgentConfig } from './types';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<AgentConfig, MCPOAuthProvider>();\n\n/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */\nexport function getNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]\n): MCPOAuthProvider {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n provider = createNonInteractiveOAuthProvider(agent, options);\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */\nexport function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void {\n const provider = nonInteractiveOAuthProviderCache.get(source);\n if (provider) nonInteractiveOAuthProviderCache.set(target, provider);\n}\n"],"mappings":"AAAA,SAAS,yCAAyC;AAIlD,MAAM,mCAAmC,oBAAI,QAAuC;AAG7E,SAAS,+BACd,OACA,SACkB;AAClB,MAAI,WAAW,iCAAiC,IAAI,KAAK;AACzD,MAAI,CAAC,UAAU;AACb,eAAW,kCAAkC,OAAO,OAAO;AAC3D,qCAAiC,IAAI,OAAO,QAAQ;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,iCAAiC,QAAqB,QAA2B;AAC/F,QAAM,WAAW,iCAAiC,IAAI,MAAM;AAC5D,MAAI,SAAU,kCAAiC,IAAI,QAAQ,QAAQ;AACrE;","names":[]}
@@ -120,7 +120,7 @@ async function runUniformErrorInvariant(tool, options) {
120
120
  async function capturedProbe(agent, tool, request, options) {
121
121
  try {
122
122
  const { captures } = await (0, import_rawResponseCapture.withRawResponseCapture)(async () => {
123
- await agent.executeTask(tool, request);
123
+ await agent.executeTaskLegacy(tool, request);
124
124
  }, options);
125
125
  const toolCallCapture = lastPostCapture(captures);
126
126
  if (!toolCallCapture) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTask(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTaskLegacy(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
@@ -96,7 +96,7 @@ async function runUniformErrorInvariant(tool, options) {
96
96
  async function capturedProbe(agent, tool, request, options) {
97
97
  try {
98
98
  const { captures } = await withRawResponseCapture(async () => {
99
- await agent.executeTask(tool, request);
99
+ await agent.executeTaskLegacy(tool, request);
100
100
  }, options);
101
101
  const toolCallCapture = lastPostCapture(captures);
102
102
  if (!toolCallCapture) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTask(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTaskLegacy(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
@@ -60,7 +60,7 @@ async function runToolFuzz(tool, agent, options) {
60
60
  const probeRequest = "adcp_major_version" in request || "adcp_version" in request ? { ...request, adcp_major_version: import_version.ADCP_MAJOR_VERSION } : request;
61
61
  let result;
62
62
  try {
63
- result = await agent.executeTask(tool, probeRequest);
63
+ result = await agent.executeTaskLegacy(tool, probeRequest);
64
64
  } catch (err2) {
65
65
  const message = err2?.message ?? String(err2);
66
66
  if (err2?.name === "FeatureUnsupportedError" || /does not support/i.test(message)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTask(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err","fc"]}
1
+ {"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTaskLegacy(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err","fc"]}
@@ -27,7 +27,7 @@ async function runToolFuzz(tool, agent, options) {
27
27
  const probeRequest = "adcp_major_version" in request || "adcp_version" in request ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION } : request;
28
28
  let result;
29
29
  try {
30
- result = await agent.executeTask(tool, probeRequest);
30
+ result = await agent.executeTaskLegacy(tool, probeRequest);
31
31
  } catch (err2) {
32
32
  const message = err2?.message ?? String(err2);
33
33
  if (err2?.name === "FeatureUnsupportedError" || /does not support/i.test(message)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTask(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err"]}
1
+ {"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTaskLegacy(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err"]}
@@ -98,7 +98,7 @@ async function seedPropertyList({ agent }) {
98
98
  return { ids: { list_ids: [listId] }, warnings: [] };
99
99
  }
100
100
  async function seedContentStandards({ agent }) {
101
- const result = await agent.executeTask("create_content_standards", {
101
+ const result = await agent.executeTaskLegacy("create_content_standards", {
102
102
  idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
103
103
  scope: { languages_any: ["en"] },
104
104
  policies: [
@@ -126,7 +126,7 @@ async function seedContentStandards({ agent }) {
126
126
  }
127
127
  async function seedMediaBuy({ agent, brand }) {
128
128
  const warnings = [];
129
- const products = await agent.executeTask("get_products", {
129
+ const products = await agent.executeTaskLegacy("get_products", {
130
130
  brief: "Conformance fuzzer seed \u2014 any product acceptable"
131
131
  });
132
132
  if (!products.success || products.status !== "completed" || !products.data) {
@@ -155,7 +155,7 @@ async function seedMediaBuy({ agent, brand }) {
155
155
  const end = new Date(now.getTime() + 8 * 24 * 60 * 60 * 1e3);
156
156
  const brandRef = { domain: brand.domain };
157
157
  if (brand.brand_id) brandRef.brand_id = brand.brand_id;
158
- const result = await agent.executeTask("create_media_buy", {
158
+ const result = await agent.executeTaskLegacy("create_media_buy", {
159
159
  idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
160
160
  account: { brand: brandRef, operator: brand.domain },
161
161
  brand: brandRef,
@@ -197,7 +197,7 @@ function summarizeResult(result) {
197
197
  }
198
198
  async function seedSyncCreatives({ agent, brand }) {
199
199
  const warnings = [];
200
- const formatsResult = await agent.executeTask("list_creative_formats", {});
200
+ const formatsResult = await agent.executeTaskLegacy("list_creative_formats", {});
201
201
  if (!formatsResult.success || formatsResult.status !== "completed" || !formatsResult.data) {
202
202
  return {
203
203
  ids: {},
@@ -220,7 +220,7 @@ async function seedSyncCreatives({ agent, brand }) {
220
220
  const manifest = synthesizeManifestAssets(picked);
221
221
  const creativeId = `cf_creative_${UNIQUE_TAG()}`;
222
222
  const tag = UNIQUE_TAG();
223
- const result = await agent.executeTask("sync_creatives", {
223
+ const result = await agent.executeTaskLegacy("sync_creatives", {
224
224
  idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
225
225
  account: {
226
226
  brand: { domain: brand.domain, ...brand.brand_id ? { brand_id: brand.brand_id } : {} },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/conformance/seeder.ts"],"sourcesContent":["import { AgentClient } from '../core/AgentClient';\nimport type { AgentConfig } from '../types';\nimport { generateIdempotencyKey } from '../utils/idempotency';\nimport type { ConformanceFixtures } from './types';\n\nexport interface SeedOptions {\n /** Protocol. Default: 'mcp'. */\n protocol?: 'mcp' | 'a2a';\n /** Bearer token forwarded to the agent. */\n authToken?: string;\n /** Full AgentConfig override. `id`/`agent_uri`/`protocol` are filled in from the other options. */\n agentConfig?: Partial<AgentConfig>;\n /**\n * Subset of seeders to run. Default: all.\n * `'create_media_buy'` implicitly runs `get_products` first to discover\n * a real product_id. `'sync_creatives'` implicitly runs\n * `list_creative_formats` first to pick a usable format.\n */\n seeders?: readonly SeederName[];\n /**\n * Brand reference for mutating seeders that require one. Default\n * `{ domain: 'conformance.example' }`. Sellers that enforce brand\n * allowlists should override this with a domain they're configured to\n * accept — otherwise `create_media_buy` seeding warns and falls through.\n */\n brand?: { domain: string; brand_id?: string };\n}\n\nexport type SeederName = 'create_property_list' | 'create_content_standards' | 'create_media_buy' | 'sync_creatives';\n\nexport interface SeedResult {\n fixtures: ConformanceFixtures;\n warnings: SeedWarning[];\n}\n\nexport interface SeedWarning {\n seeder: SeederName;\n reason: string;\n}\n\n// Cosmetic tag for human-readable names/labels only. NOT used for\n// idempotency_key — that's minted by `generateIdempotencyKey()`. Two\n// seeders racing with the same random suffix would produce two distinct\n// entities with identical names, which is fine for a seeder.\nconst UNIQUE_TAG = (): string => 'cf_seed_' + Math.random().toString(36).slice(2, 10);\n\n/**\n * Seeds an agent with known entities so Tier-3 fuzzing has real IDs to\n * feed back into referential + update tools. Each seeder is best-effort:\n * failures degrade to a recorded warning and an empty pool, never a\n * thrown exception, so a partial seed still lets the fuzzer run against\n * every other tool.\n *\n * Inputs are minimal hand-crafted payloads rather than fast-check\n * outputs — seeding is about producing a known-good entity, not\n * exploring the schema space. That's the job of runConformance.\n *\n * WARNING: This mutates the target. Point at a sandbox / test tenant.\n */\nexport async function seedFixtures(agentUrl: string, options: SeedOptions = {}): Promise<SeedResult> {\n const agent = buildAgent(agentUrl, options);\n const seeders =\n options.seeders ??\n (['create_property_list', 'create_content_standards', 'create_media_buy', 'sync_creatives'] as const);\n\n const ctx: SeederContext = {\n agent,\n brand: options.brand ?? { domain: 'conformance.example' },\n };\n\n const fixtures: ConformanceFixtures = {};\n const warnings: SeedWarning[] = [];\n\n for (const name of seeders) {\n try {\n const runner = SEEDERS[name];\n if (!runner) {\n warnings.push({ seeder: name, reason: `no seeder registered for ${name}` });\n continue;\n }\n const out = await runner(ctx);\n mergePool(fixtures, out.ids);\n warnings.push(...out.warnings);\n } catch (err) {\n warnings.push({ seeder: name, reason: `seeder threw: ${(err as Error)?.message ?? String(err)}` });\n }\n }\n\n return { fixtures, warnings };\n}\n\ninterface SeederContext {\n agent: AgentClient;\n brand: { domain: string; brand_id?: string };\n}\n\nfunction buildAgent(agentUrl: string, options: SeedOptions): AgentClient {\n const config: AgentConfig = {\n id: options.agentConfig?.id ?? 'conformance-seeder',\n name: options.agentConfig?.name ?? 'AdCP Conformance Seeder',\n agent_uri: agentUrl,\n protocol: options.protocol ?? options.agentConfig?.protocol ?? 'mcp',\n auth_token: options.authToken ?? options.agentConfig?.auth_token,\n ...options.agentConfig,\n };\n // The seeder tries every seed-tool regardless of declared capabilities.\n // Two SDK preflights are explicitly disabled:\n // - `validateFeatures: false` — don't refuse tools that aren't\n // declared in `get_adcp_capabilities`. The seeder just tries; the\n // agent's rejection becomes a recorded warning.\n // - `validation.responses: 'warn'` — don't fail a seed just because\n // the agent's response drifts from the response schema. We want\n // the ID if it's present; the fuzzer itself will do the strict\n // validation on downstream tools that actually care.\n return new AgentClient(config, {\n validateFeatures: false,\n validation: { responses: 'warn' },\n });\n}\n\nfunction mergePool(dest: ConformanceFixtures, src: Partial<Record<keyof ConformanceFixtures, string[]>>): void {\n for (const [key, values] of Object.entries(src)) {\n if (!values || values.length === 0) continue;\n const k = key as keyof ConformanceFixtures;\n const existing = dest[k] ?? [];\n dest[k] = [...existing, ...values];\n }\n}\n\ninterface SeederOutput {\n ids: Partial<Record<keyof ConformanceFixtures, string[]>>;\n warnings: SeedWarning[];\n}\ntype Seeder = (ctx: SeederContext) => Promise<SeederOutput>;\n\nconst SEEDERS: Record<SeederName, Seeder> = {\n create_property_list: seedPropertyList,\n create_content_standards: seedContentStandards,\n create_media_buy: seedMediaBuy,\n sync_creatives: seedSyncCreatives,\n};\n\nasync function seedPropertyList({ agent }: SeederContext): Promise<SeederOutput> {\n const result = await agent.executeTask('create_property_list', {\n idempotency_key: generateIdempotencyKey(),\n name: `Conformance Seeder List ${UNIQUE_TAG()}`,\n });\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_property_list', reason: summarizeResult(result) }],\n };\n }\n const listId = (result.data as { list?: { list_id?: unknown } })?.list?.list_id;\n if (typeof listId !== 'string' || listId.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_property_list', reason: 'response missing list.list_id' }],\n };\n }\n return { ids: { list_ids: [listId] }, warnings: [] };\n}\n\nasync function seedContentStandards({ agent }: SeederContext): Promise<SeederOutput> {\n // Minimal payload that still satisfies the \"at least one of policy,\n // policies, or registry_policy_ids is required\" invariant some sellers\n // enforce beyond the raw schema. A single inline policy is the most\n // portable shape — registry_policy_ids require a pre-existing registry\n // entry on the seller, which we can't assume.\n const result = await agent.executeTask('create_content_standards', {\n idempotency_key: generateIdempotencyKey(),\n scope: { languages_any: ['en'] },\n policies: [\n {\n policy_id: `cf_policy_${UNIQUE_TAG()}`,\n enforcement: 'may',\n policy: 'Conformance seeder placeholder policy — advisory only.',\n },\n ],\n });\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_content_standards', reason: summarizeResult(result) }],\n };\n }\n const standardsId = (result.data as { standards_id?: unknown })?.standards_id;\n if (typeof standardsId !== 'string' || standardsId.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_content_standards', reason: 'response missing standards_id' }],\n };\n }\n return { ids: { standards_ids: [standardsId] }, warnings: [] };\n}\n\n/**\n * Creates a media buy by first discovering a product via `get_products`,\n * then calling `create_media_buy` against that product. Captures the\n * returned `media_buy_id` and any `package_id`s from the response.\n */\nasync function seedMediaBuy({ agent, brand }: SeederContext): Promise<SeederOutput> {\n const warnings: SeedWarning[] = [];\n const products = await agent.executeTask('get_products', {\n brief: 'Conformance fuzzer seed — any product acceptable',\n });\n if (!products.success || products.status !== 'completed' || !products.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'get_products preflight: ' + summarizeResult(products) }],\n };\n }\n const productList = (products.data as { products?: unknown })?.products;\n if (!Array.isArray(productList) || productList.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'get_products returned no products' }],\n };\n }\n const product = productList[0] as {\n product_id?: string;\n pricing_options?: Array<{ pricing_option_id?: string }>;\n };\n if (!product.product_id || !product.pricing_options?.[0]?.pricing_option_id) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'first product missing product_id or pricing_option_id' }],\n };\n }\n\n const tag = UNIQUE_TAG();\n const now = new Date();\n const start = new Date(now.getTime() + 24 * 60 * 60 * 1000); // +1 day\n const end = new Date(now.getTime() + 8 * 24 * 60 * 60 * 1000); // +8 days\n\n const brandRef: Record<string, string> = { domain: brand.domain };\n if (brand.brand_id) brandRef.brand_id = brand.brand_id;\n const result = await agent.executeTask('create_media_buy', {\n idempotency_key: generateIdempotencyKey(),\n account: { brand: brandRef, operator: brand.domain },\n brand: brandRef,\n start_time: start.toISOString(),\n end_time: end.toISOString(),\n total_budget: { amount: 100, currency: 'USD' },\n packages: [\n {\n buyer_ref: `cf_pkg_${tag}`,\n product_id: product.product_id,\n pricing_option_id: product.pricing_options[0].pricing_option_id,\n budget: 100,\n },\n ],\n });\n\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [...warnings, { seeder: 'create_media_buy', reason: summarizeResult(result) }],\n };\n }\n\n const data = result.data as {\n media_buy_id?: unknown;\n packages?: Array<{ package_id?: unknown }>;\n };\n const ids: Partial<Record<keyof ConformanceFixtures, string[]>> = {};\n if (typeof data.media_buy_id === 'string' && data.media_buy_id.length > 0) {\n ids.media_buy_ids = [data.media_buy_id];\n } else {\n warnings.push({ seeder: 'create_media_buy', reason: 'response missing media_buy_id (may be submitted async)' });\n }\n const packageIds = (data.packages ?? [])\n .map(p => p?.package_id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n if (packageIds.length > 0) ids.package_ids = packageIds;\n\n return { ids, warnings };\n}\n\nfunction summarizeResult(result: {\n success: boolean;\n status?: string;\n error?: string;\n adcpError?: { code?: string };\n}): string {\n if (result.success === false) {\n const code = result.adcpError?.code ? `${result.adcpError.code}: ` : '';\n return `agent rejected with ${code}${result.error ?? 'unknown error'}`;\n }\n return `unexpected status ${result.status ?? 'unknown'}`;\n}\n\n/**\n * Creates a single creative by first discovering formats via\n * `list_creative_formats`, picking the first format whose required\n * assets are all covered by our placeholder synthesis, then calling\n * `sync_creatives` with a minimal manifest. Captures returned\n * `creative_id`s into the pool.\n */\nasync function seedSyncCreatives({ agent, brand }: SeederContext): Promise<SeederOutput> {\n const warnings: SeedWarning[] = [];\n const formatsResult = await agent.executeTask('list_creative_formats', {});\n if (!formatsResult.success || formatsResult.status !== 'completed' || !formatsResult.data) {\n return {\n ids: {},\n warnings: [\n { seeder: 'sync_creatives', reason: 'list_creative_formats preflight: ' + summarizeResult(formatsResult) },\n ],\n };\n }\n const formats = (formatsResult.data as { formats?: unknown }).formats;\n if (!Array.isArray(formats) || formats.length === 0) {\n return { ids: {}, warnings: [{ seeder: 'sync_creatives', reason: 'list_creative_formats returned no formats' }] };\n }\n\n const picked = pickSimpleFormat(formats as FormatDef[]);\n if (!picked) {\n return {\n ids: {},\n warnings: [{ seeder: 'sync_creatives', reason: 'no format with a synthesizable required-asset set' }],\n };\n }\n\n const manifest = synthesizeManifestAssets(picked);\n const creativeId = `cf_creative_${UNIQUE_TAG()}`;\n const tag = UNIQUE_TAG();\n\n const result = await agent.executeTask('sync_creatives', {\n idempotency_key: generateIdempotencyKey(),\n account: {\n brand: { domain: brand.domain, ...(brand.brand_id ? { brand_id: brand.brand_id } : {}) },\n operator: brand.domain,\n },\n creatives: [\n {\n creative_id: creativeId,\n name: `Conformance Seeder Creative ${tag}`,\n format_id: { agent_url: picked.format_id.agent_url, id: picked.format_id.id },\n assets: manifest,\n },\n ],\n });\n\n if (!result.success || result.status !== 'completed' || !result.data) {\n return { ids: {}, warnings: [...warnings, { seeder: 'sync_creatives', reason: summarizeResult(result) }] };\n }\n\n const capturedIds = extractCreativeIds(result.data, creativeId);\n if (capturedIds.length === 0) {\n warnings.push({\n seeder: 'sync_creatives',\n reason: 'response did not surface a creative_id (may be pending review)',\n });\n return { ids: {}, warnings };\n }\n return { ids: { creative_ids: capturedIds }, warnings };\n}\n\n/**\n * Pick the first format whose required assets are all in the set of\n * types we know how to synthesize placeholder values for. Sorted by the\n * format's declared order — no clever heuristics.\n */\ninterface FormatDef {\n format_id: { agent_url: string; id: string };\n assets?: Array<{ asset_id: string; asset_type?: string; required?: boolean; item_type?: string }>;\n}\nfunction pickSimpleFormat(formats: FormatDef[]): FormatDef | null {\n for (const f of formats) {\n if (!f?.format_id?.agent_url || !f.format_id.id) continue;\n const required = (f.assets ?? []).filter(a => a?.required === true && a.item_type === 'individual');\n // Skip formats with zero required assets — sellers typically reject a\n // creative with an empty assets dict, so picking one would just\n // trade \"no format available\" for \"creative rejected\" downstream.\n if (required.length === 0) continue;\n if (required.every(a => ASSET_PLACEHOLDER[a.asset_type as keyof typeof ASSET_PLACEHOLDER])) return f;\n }\n return null;\n}\n\nfunction synthesizeManifestAssets(format: FormatDef): Record<string, unknown> {\n const manifest: Record<string, unknown> = {};\n for (const asset of format.assets ?? []) {\n if (asset?.required !== true || asset.item_type !== 'individual') continue;\n const placeholder = ASSET_PLACEHOLDER[asset.asset_type as keyof typeof ASSET_PLACEHOLDER];\n if (placeholder) manifest[asset.asset_id] = placeholder();\n }\n return manifest;\n}\n\n// Placeholder value per asset type. Kept intentionally small: the\n// seeder's job is to produce a creative the agent will accept, not to\n// fuzz the asset surface. We only cover types whose `required` fields\n// we can satisfy without format-specific knowledge (dimensions, codecs,\n// etc. use safe defaults).\nconst ASSET_PLACEHOLDER = {\n image: () => ({ asset_type: 'image', url: 'https://conformance.example/placeholder.png', width: 300, height: 250 }),\n video: () => ({ asset_type: 'video', url: 'https://conformance.example/placeholder.mp4', width: 640, height: 360 }),\n audio: () => ({ asset_type: 'audio', url: 'https://conformance.example/placeholder.mp3' }),\n text: () => ({ asset_type: 'text', content: 'Conformance seed text' }),\n url: () => ({ asset_type: 'url', url: 'https://conformance.example/' }),\n html: () => ({ asset_type: 'html', content: '<div>Conformance seed</div>' }),\n javascript: () => ({ asset_type: 'javascript', content: '/* conformance seed */' }),\n css: () => ({ asset_type: 'css', content: '/* conformance seed */' }),\n markdown: () => ({ asset_type: 'markdown', content: 'Conformance seed' }),\n} as const;\n\nfunction extractCreativeIds(data: unknown, fallbackId: string): string[] {\n const d = data as { creatives?: unknown; synced_creatives?: unknown };\n const items: unknown[] = [];\n if (Array.isArray(d.creatives)) items.push(...d.creatives);\n if (Array.isArray(d.synced_creatives)) items.push(...d.synced_creatives);\n const ids: string[] = [];\n for (const it of items) {\n const id = (it as { creative_id?: unknown })?.creative_id;\n if (typeof id === 'string' && id.length > 0) ids.push(id);\n }\n // Fall back to the id we supplied — spec allows sellers to echo back\n // buyer-supplied creative_ids on success.\n return ids.length > 0 ? ids : [fallbackId];\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/conformance/seeder.ts"],"sourcesContent":["import { AgentClient } from '../core/AgentClient';\nimport type { AgentConfig } from '../types';\nimport { generateIdempotencyKey } from '../utils/idempotency';\nimport type { ConformanceFixtures } from './types';\n\nexport interface SeedOptions {\n /** Protocol. Default: 'mcp'. */\n protocol?: 'mcp' | 'a2a';\n /** Bearer token forwarded to the agent. */\n authToken?: string;\n /** Full AgentConfig override. `id`/`agent_uri`/`protocol` are filled in from the other options. */\n agentConfig?: Partial<AgentConfig>;\n /**\n * Subset of seeders to run. Default: all.\n * `'create_media_buy'` implicitly runs `get_products` first to discover\n * a real product_id. `'sync_creatives'` implicitly runs\n * `list_creative_formats` first to pick a usable format.\n */\n seeders?: readonly SeederName[];\n /**\n * Brand reference for mutating seeders that require one. Default\n * `{ domain: 'conformance.example' }`. Sellers that enforce brand\n * allowlists should override this with a domain they're configured to\n * accept — otherwise `create_media_buy` seeding warns and falls through.\n */\n brand?: { domain: string; brand_id?: string };\n}\n\nexport type SeederName = 'create_property_list' | 'create_content_standards' | 'create_media_buy' | 'sync_creatives';\n\nexport interface SeedResult {\n fixtures: ConformanceFixtures;\n warnings: SeedWarning[];\n}\n\nexport interface SeedWarning {\n seeder: SeederName;\n reason: string;\n}\n\n// Cosmetic tag for human-readable names/labels only. NOT used for\n// idempotency_key — that's minted by `generateIdempotencyKey()`. Two\n// seeders racing with the same random suffix would produce two distinct\n// entities with identical names, which is fine for a seeder.\nconst UNIQUE_TAG = (): string => 'cf_seed_' + Math.random().toString(36).slice(2, 10);\n\n/**\n * Seeds an agent with known entities so Tier-3 fuzzing has real IDs to\n * feed back into referential + update tools. Each seeder is best-effort:\n * failures degrade to a recorded warning and an empty pool, never a\n * thrown exception, so a partial seed still lets the fuzzer run against\n * every other tool.\n *\n * Inputs are minimal hand-crafted payloads rather than fast-check\n * outputs — seeding is about producing a known-good entity, not\n * exploring the schema space. That's the job of runConformance.\n *\n * WARNING: This mutates the target. Point at a sandbox / test tenant.\n */\nexport async function seedFixtures(agentUrl: string, options: SeedOptions = {}): Promise<SeedResult> {\n const agent = buildAgent(agentUrl, options);\n const seeders =\n options.seeders ??\n (['create_property_list', 'create_content_standards', 'create_media_buy', 'sync_creatives'] as const);\n\n const ctx: SeederContext = {\n agent,\n brand: options.brand ?? { domain: 'conformance.example' },\n };\n\n const fixtures: ConformanceFixtures = {};\n const warnings: SeedWarning[] = [];\n\n for (const name of seeders) {\n try {\n const runner = SEEDERS[name];\n if (!runner) {\n warnings.push({ seeder: name, reason: `no seeder registered for ${name}` });\n continue;\n }\n const out = await runner(ctx);\n mergePool(fixtures, out.ids);\n warnings.push(...out.warnings);\n } catch (err) {\n warnings.push({ seeder: name, reason: `seeder threw: ${(err as Error)?.message ?? String(err)}` });\n }\n }\n\n return { fixtures, warnings };\n}\n\ninterface SeederContext {\n agent: AgentClient;\n brand: { domain: string; brand_id?: string };\n}\n\nfunction buildAgent(agentUrl: string, options: SeedOptions): AgentClient {\n const config: AgentConfig = {\n id: options.agentConfig?.id ?? 'conformance-seeder',\n name: options.agentConfig?.name ?? 'AdCP Conformance Seeder',\n agent_uri: agentUrl,\n protocol: options.protocol ?? options.agentConfig?.protocol ?? 'mcp',\n auth_token: options.authToken ?? options.agentConfig?.auth_token,\n ...options.agentConfig,\n };\n // The seeder tries every seed-tool regardless of declared capabilities.\n // Two SDK preflights are explicitly disabled:\n // - `validateFeatures: false` — don't refuse tools that aren't\n // declared in `get_adcp_capabilities`. The seeder just tries; the\n // agent's rejection becomes a recorded warning.\n // - `validation.responses: 'warn'` — don't fail a seed just because\n // the agent's response drifts from the response schema. We want\n // the ID if it's present; the fuzzer itself will do the strict\n // validation on downstream tools that actually care.\n return new AgentClient(config, {\n validateFeatures: false,\n validation: { responses: 'warn' },\n });\n}\n\nfunction mergePool(dest: ConformanceFixtures, src: Partial<Record<keyof ConformanceFixtures, string[]>>): void {\n for (const [key, values] of Object.entries(src)) {\n if (!values || values.length === 0) continue;\n const k = key as keyof ConformanceFixtures;\n const existing = dest[k] ?? [];\n dest[k] = [...existing, ...values];\n }\n}\n\ninterface SeederOutput {\n ids: Partial<Record<keyof ConformanceFixtures, string[]>>;\n warnings: SeedWarning[];\n}\ntype Seeder = (ctx: SeederContext) => Promise<SeederOutput>;\n\nconst SEEDERS: Record<SeederName, Seeder> = {\n create_property_list: seedPropertyList,\n create_content_standards: seedContentStandards,\n create_media_buy: seedMediaBuy,\n sync_creatives: seedSyncCreatives,\n};\n\nasync function seedPropertyList({ agent }: SeederContext): Promise<SeederOutput> {\n const result = await agent.executeTask('create_property_list', {\n idempotency_key: generateIdempotencyKey(),\n name: `Conformance Seeder List ${UNIQUE_TAG()}`,\n });\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_property_list', reason: summarizeResult(result) }],\n };\n }\n const listId = (result.data as { list?: { list_id?: unknown } })?.list?.list_id;\n if (typeof listId !== 'string' || listId.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_property_list', reason: 'response missing list.list_id' }],\n };\n }\n return { ids: { list_ids: [listId] }, warnings: [] };\n}\n\nasync function seedContentStandards({ agent }: SeederContext): Promise<SeederOutput> {\n // Minimal payload that still satisfies the \"at least one of policy,\n // policies, or registry_policy_ids is required\" invariant some sellers\n // enforce beyond the raw schema. A single inline policy is the most\n // portable shape — registry_policy_ids require a pre-existing registry\n // entry on the seller, which we can't assume.\n const result = await agent.executeTaskLegacy('create_content_standards', {\n idempotency_key: generateIdempotencyKey(),\n scope: { languages_any: ['en'] },\n policies: [\n {\n policy_id: `cf_policy_${UNIQUE_TAG()}`,\n enforcement: 'may',\n policy: 'Conformance seeder placeholder policy — advisory only.',\n },\n ],\n });\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_content_standards', reason: summarizeResult(result) }],\n };\n }\n const standardsId = (result.data as { standards_id?: unknown })?.standards_id;\n if (typeof standardsId !== 'string' || standardsId.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_content_standards', reason: 'response missing standards_id' }],\n };\n }\n return { ids: { standards_ids: [standardsId] }, warnings: [] };\n}\n\n/**\n * Creates a media buy by first discovering a product via `get_products`,\n * then calling `create_media_buy` against that product. Captures the\n * returned `media_buy_id` and any `package_id`s from the response.\n */\nasync function seedMediaBuy({ agent, brand }: SeederContext): Promise<SeederOutput> {\n const warnings: SeedWarning[] = [];\n const products = await agent.executeTaskLegacy('get_products', {\n brief: 'Conformance fuzzer seed — any product acceptable',\n });\n if (!products.success || products.status !== 'completed' || !products.data) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'get_products preflight: ' + summarizeResult(products) }],\n };\n }\n const productList = (products.data as { products?: unknown })?.products;\n if (!Array.isArray(productList) || productList.length === 0) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'get_products returned no products' }],\n };\n }\n const product = productList[0] as {\n product_id?: string;\n pricing_options?: Array<{ pricing_option_id?: string }>;\n };\n if (!product.product_id || !product.pricing_options?.[0]?.pricing_option_id) {\n return {\n ids: {},\n warnings: [{ seeder: 'create_media_buy', reason: 'first product missing product_id or pricing_option_id' }],\n };\n }\n\n const tag = UNIQUE_TAG();\n const now = new Date();\n const start = new Date(now.getTime() + 24 * 60 * 60 * 1000); // +1 day\n const end = new Date(now.getTime() + 8 * 24 * 60 * 60 * 1000); // +8 days\n\n const brandRef: Record<string, string> = { domain: brand.domain };\n if (brand.brand_id) brandRef.brand_id = brand.brand_id;\n const result = await agent.executeTaskLegacy('create_media_buy', {\n idempotency_key: generateIdempotencyKey(),\n account: { brand: brandRef, operator: brand.domain },\n brand: brandRef,\n start_time: start.toISOString(),\n end_time: end.toISOString(),\n total_budget: { amount: 100, currency: 'USD' },\n packages: [\n {\n buyer_ref: `cf_pkg_${tag}`,\n product_id: product.product_id,\n pricing_option_id: product.pricing_options[0].pricing_option_id,\n budget: 100,\n },\n ],\n });\n\n if (!result.success || result.status !== 'completed' || !result.data) {\n return {\n ids: {},\n warnings: [...warnings, { seeder: 'create_media_buy', reason: summarizeResult(result) }],\n };\n }\n\n const data = result.data as {\n media_buy_id?: unknown;\n packages?: Array<{ package_id?: unknown }>;\n };\n const ids: Partial<Record<keyof ConformanceFixtures, string[]>> = {};\n if (typeof data.media_buy_id === 'string' && data.media_buy_id.length > 0) {\n ids.media_buy_ids = [data.media_buy_id];\n } else {\n warnings.push({ seeder: 'create_media_buy', reason: 'response missing media_buy_id (may be submitted async)' });\n }\n const packageIds = (data.packages ?? [])\n .map(p => p?.package_id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n if (packageIds.length > 0) ids.package_ids = packageIds;\n\n return { ids, warnings };\n}\n\nfunction summarizeResult(result: {\n success: boolean;\n status?: string;\n error?: string;\n adcpError?: { code?: string };\n}): string {\n if (result.success === false) {\n const code = result.adcpError?.code ? `${result.adcpError.code}: ` : '';\n return `agent rejected with ${code}${result.error ?? 'unknown error'}`;\n }\n return `unexpected status ${result.status ?? 'unknown'}`;\n}\n\n/**\n * Creates a single creative by first discovering formats via\n * `list_creative_formats`, picking the first format whose required\n * assets are all covered by our placeholder synthesis, then calling\n * `sync_creatives` with a minimal manifest. Captures returned\n * `creative_id`s into the pool.\n */\nasync function seedSyncCreatives({ agent, brand }: SeederContext): Promise<SeederOutput> {\n const warnings: SeedWarning[] = [];\n const formatsResult = await agent.executeTaskLegacy('list_creative_formats', {});\n if (!formatsResult.success || formatsResult.status !== 'completed' || !formatsResult.data) {\n return {\n ids: {},\n warnings: [\n { seeder: 'sync_creatives', reason: 'list_creative_formats preflight: ' + summarizeResult(formatsResult) },\n ],\n };\n }\n const formats = (formatsResult.data as { formats?: unknown }).formats;\n if (!Array.isArray(formats) || formats.length === 0) {\n return { ids: {}, warnings: [{ seeder: 'sync_creatives', reason: 'list_creative_formats returned no formats' }] };\n }\n\n const picked = pickSimpleFormat(formats as FormatDef[]);\n if (!picked) {\n return {\n ids: {},\n warnings: [{ seeder: 'sync_creatives', reason: 'no format with a synthesizable required-asset set' }],\n };\n }\n\n const manifest = synthesizeManifestAssets(picked);\n const creativeId = `cf_creative_${UNIQUE_TAG()}`;\n const tag = UNIQUE_TAG();\n\n const result = await agent.executeTaskLegacy('sync_creatives', {\n idempotency_key: generateIdempotencyKey(),\n account: {\n brand: { domain: brand.domain, ...(brand.brand_id ? { brand_id: brand.brand_id } : {}) },\n operator: brand.domain,\n },\n creatives: [\n {\n creative_id: creativeId,\n name: `Conformance Seeder Creative ${tag}`,\n format_id: { agent_url: picked.format_id.agent_url, id: picked.format_id.id },\n assets: manifest,\n },\n ],\n });\n\n if (!result.success || result.status !== 'completed' || !result.data) {\n return { ids: {}, warnings: [...warnings, { seeder: 'sync_creatives', reason: summarizeResult(result) }] };\n }\n\n const capturedIds = extractCreativeIds(result.data, creativeId);\n if (capturedIds.length === 0) {\n warnings.push({\n seeder: 'sync_creatives',\n reason: 'response did not surface a creative_id (may be pending review)',\n });\n return { ids: {}, warnings };\n }\n return { ids: { creative_ids: capturedIds }, warnings };\n}\n\n/**\n * Pick the first format whose required assets are all in the set of\n * types we know how to synthesize placeholder values for. Sorted by the\n * format's declared order — no clever heuristics.\n */\ninterface FormatDef {\n format_id: { agent_url: string; id: string };\n assets?: Array<{ asset_id: string; asset_type?: string; required?: boolean; item_type?: string }>;\n}\nfunction pickSimpleFormat(formats: FormatDef[]): FormatDef | null {\n for (const f of formats) {\n if (!f?.format_id?.agent_url || !f.format_id.id) continue;\n const required = (f.assets ?? []).filter(a => a?.required === true && a.item_type === 'individual');\n // Skip formats with zero required assets — sellers typically reject a\n // creative with an empty assets dict, so picking one would just\n // trade \"no format available\" for \"creative rejected\" downstream.\n if (required.length === 0) continue;\n if (required.every(a => ASSET_PLACEHOLDER[a.asset_type as keyof typeof ASSET_PLACEHOLDER])) return f;\n }\n return null;\n}\n\nfunction synthesizeManifestAssets(format: FormatDef): Record<string, unknown> {\n const manifest: Record<string, unknown> = {};\n for (const asset of format.assets ?? []) {\n if (asset?.required !== true || asset.item_type !== 'individual') continue;\n const placeholder = ASSET_PLACEHOLDER[asset.asset_type as keyof typeof ASSET_PLACEHOLDER];\n if (placeholder) manifest[asset.asset_id] = placeholder();\n }\n return manifest;\n}\n\n// Placeholder value per asset type. Kept intentionally small: the\n// seeder's job is to produce a creative the agent will accept, not to\n// fuzz the asset surface. We only cover types whose `required` fields\n// we can satisfy without format-specific knowledge (dimensions, codecs,\n// etc. use safe defaults).\nconst ASSET_PLACEHOLDER = {\n image: () => ({ asset_type: 'image', url: 'https://conformance.example/placeholder.png', width: 300, height: 250 }),\n video: () => ({ asset_type: 'video', url: 'https://conformance.example/placeholder.mp4', width: 640, height: 360 }),\n audio: () => ({ asset_type: 'audio', url: 'https://conformance.example/placeholder.mp3' }),\n text: () => ({ asset_type: 'text', content: 'Conformance seed text' }),\n url: () => ({ asset_type: 'url', url: 'https://conformance.example/' }),\n html: () => ({ asset_type: 'html', content: '<div>Conformance seed</div>' }),\n javascript: () => ({ asset_type: 'javascript', content: '/* conformance seed */' }),\n css: () => ({ asset_type: 'css', content: '/* conformance seed */' }),\n markdown: () => ({ asset_type: 'markdown', content: 'Conformance seed' }),\n} as const;\n\nfunction extractCreativeIds(data: unknown, fallbackId: string): string[] {\n const d = data as { creatives?: unknown; synced_creatives?: unknown };\n const items: unknown[] = [];\n if (Array.isArray(d.creatives)) items.push(...d.creatives);\n if (Array.isArray(d.synced_creatives)) items.push(...d.synced_creatives);\n const ids: string[] = [];\n for (const it of items) {\n const id = (it as { creative_id?: unknown })?.creative_id;\n if (typeof id === 'string' && id.length > 0) ids.push(id);\n }\n // Fall back to the id we supplied — spec allows sellers to echo back\n // buyer-supplied creative_ids on success.\n return ids.length > 0 ? ids : [fallbackId];\n}\n"],"mappings":"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","names":[]}
@@ -75,7 +75,7 @@ async function seedPropertyList({ agent }) {
75
75
  return { ids: { list_ids: [listId] }, warnings: [] };
76
76
  }
77
77
  async function seedContentStandards({ agent }) {
78
- const result = await agent.executeTask("create_content_standards", {
78
+ const result = await agent.executeTaskLegacy("create_content_standards", {
79
79
  idempotency_key: generateIdempotencyKey(),
80
80
  scope: { languages_any: ["en"] },
81
81
  policies: [
@@ -103,7 +103,7 @@ async function seedContentStandards({ agent }) {
103
103
  }
104
104
  async function seedMediaBuy({ agent, brand }) {
105
105
  const warnings = [];
106
- const products = await agent.executeTask("get_products", {
106
+ const products = await agent.executeTaskLegacy("get_products", {
107
107
  brief: "Conformance fuzzer seed \u2014 any product acceptable"
108
108
  });
109
109
  if (!products.success || products.status !== "completed" || !products.data) {
@@ -132,7 +132,7 @@ async function seedMediaBuy({ agent, brand }) {
132
132
  const end = new Date(now.getTime() + 8 * 24 * 60 * 60 * 1e3);
133
133
  const brandRef = { domain: brand.domain };
134
134
  if (brand.brand_id) brandRef.brand_id = brand.brand_id;
135
- const result = await agent.executeTask("create_media_buy", {
135
+ const result = await agent.executeTaskLegacy("create_media_buy", {
136
136
  idempotency_key: generateIdempotencyKey(),
137
137
  account: { brand: brandRef, operator: brand.domain },
138
138
  brand: brandRef,
@@ -174,7 +174,7 @@ function summarizeResult(result) {
174
174
  }
175
175
  async function seedSyncCreatives({ agent, brand }) {
176
176
  const warnings = [];
177
- const formatsResult = await agent.executeTask("list_creative_formats", {});
177
+ const formatsResult = await agent.executeTaskLegacy("list_creative_formats", {});
178
178
  if (!formatsResult.success || formatsResult.status !== "completed" || !formatsResult.data) {
179
179
  return {
180
180
  ids: {},
@@ -197,7 +197,7 @@ async function seedSyncCreatives({ agent, brand }) {
197
197
  const manifest = synthesizeManifestAssets(picked);
198
198
  const creativeId = `cf_creative_${UNIQUE_TAG()}`;
199
199
  const tag = UNIQUE_TAG();
200
- const result = await agent.executeTask("sync_creatives", {
200
+ const result = await agent.executeTaskLegacy("sync_creatives", {
201
201
  idempotency_key: generateIdempotencyKey(),
202
202
  account: {
203
203
  brand: { domain: brand.domain, ...brand.brand_id ? { brand_id: brand.brand_id } : {} },