@adcp/sdk 12.0.0 → 12.0.2

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 (959) hide show
  1. package/dist/lib/adapters/content-standards-adapter.mjs +0 -6
  2. package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
  3. package/dist/lib/adapters/derived-account-store.mjs +0 -6
  4. package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
  5. package/dist/lib/adapters/governance-adapter.mjs +0 -6
  6. package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
  7. package/dist/lib/adapters/implicit-account-store.mjs +0 -6
  8. package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
  9. package/dist/lib/adapters/index.mjs +0 -6
  10. package/dist/lib/adapters/index.mjs.map +1 -1
  11. package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
  12. package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
  13. package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
  14. package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
  15. package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
  16. package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
  17. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
  18. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
  19. package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
  20. package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
  21. package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
  22. package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
  23. package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
  24. package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
  25. package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
  26. package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
  27. package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
  28. package/dist/lib/adapters/property-list-adapter.mjs +0 -6
  29. package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
  30. package/dist/lib/adapters/roster-account-store.mjs +0 -6
  31. package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
  32. package/dist/lib/adapters/si-session-manager.mjs +0 -6
  33. package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
  34. package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
  35. package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
  36. package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
  37. package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
  38. package/dist/lib/adapters/version/3.0/index.mjs +0 -6
  39. package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
  40. package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
  41. package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
  42. package/dist/lib/adapters/version/index.mjs +0 -6
  43. package/dist/lib/adapters/version/index.mjs.map +1 -1
  44. package/dist/lib/adapters/version/types.mjs +0 -6
  45. package/dist/lib/advanced.mjs +0 -6
  46. package/dist/lib/advanced.mjs.map +1 -1
  47. package/dist/lib/agents/index.generated.mjs +0 -6
  48. package/dist/lib/agents/index.generated.mjs.map +1 -1
  49. package/dist/lib/auth/index.mjs +0 -6
  50. package/dist/lib/auth/index.mjs.map +1 -1
  51. package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
  52. package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
  53. package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
  54. package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
  55. package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
  56. package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
  57. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
  58. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
  59. package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
  60. package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
  61. package/dist/lib/auth/oauth/diagnose.mjs +0 -6
  62. package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
  63. package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
  64. package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
  65. package/dist/lib/auth/oauth/discovery.mjs +0 -6
  66. package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
  67. package/dist/lib/auth/oauth/file-storage.mjs +0 -6
  68. package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
  69. package/dist/lib/auth/oauth/index.mjs +0 -6
  70. package/dist/lib/auth/oauth/index.mjs.map +1 -1
  71. package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
  72. package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
  73. package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
  74. package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
  75. package/dist/lib/auth/oauth/types.mjs +0 -6
  76. package/dist/lib/auth/oauth/types.mjs.map +1 -1
  77. package/dist/lib/auth/oauth/web-flow.mjs +0 -6
  78. package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
  79. package/dist/lib/brand/index.mjs +0 -6
  80. package/dist/lib/brand/index.mjs.map +1 -1
  81. package/dist/lib/canonical-references/index.mjs +6 -7
  82. package/dist/lib/canonical-references/index.mjs.map +1 -1
  83. package/dist/lib/client/index.mjs +0 -6
  84. package/dist/lib/client/index.mjs.map +1 -1
  85. package/dist/lib/compliance/index.mjs +0 -6
  86. package/dist/lib/compliance/index.mjs.map +1 -1
  87. package/dist/lib/compliance-fixtures/index.mjs +0 -6
  88. package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
  89. package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
  90. package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
  91. package/dist/lib/conformance/index.mjs +0 -6
  92. package/dist/lib/conformance/index.mjs.map +1 -1
  93. package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
  94. package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
  95. package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
  96. package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
  97. package/dist/lib/conformance/oracle.mjs +0 -6
  98. package/dist/lib/conformance/oracle.mjs.map +1 -1
  99. package/dist/lib/conformance/runConformance.mjs +0 -6
  100. package/dist/lib/conformance/runConformance.mjs.map +1 -1
  101. package/dist/lib/conformance/runners.mjs +0 -6
  102. package/dist/lib/conformance/runners.mjs.map +1 -1
  103. package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
  104. package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
  105. package/dist/lib/conformance/schemaLoader.mjs +5 -6
  106. package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
  107. package/dist/lib/conformance/seeder.mjs +0 -6
  108. package/dist/lib/conformance/seeder.mjs.map +1 -1
  109. package/dist/lib/conformance/types.mjs +0 -6
  110. package/dist/lib/conformance/types.mjs.map +1 -1
  111. package/dist/lib/conformance/webhook.mjs +0 -6
  112. package/dist/lib/conformance/webhook.mjs.map +1 -1
  113. package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
  114. package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
  115. package/dist/lib/core/AgentClient.mjs +0 -6
  116. package/dist/lib/core/AgentClient.mjs.map +1 -1
  117. package/dist/lib/core/AsyncHandler.mjs +0 -6
  118. package/dist/lib/core/AsyncHandler.mjs.map +1 -1
  119. package/dist/lib/core/ConfigurationManager.mjs +0 -6
  120. package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
  121. package/dist/lib/core/ConversationTypes.mjs +0 -6
  122. package/dist/lib/core/CreativeAgentClient.mjs +0 -6
  123. package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
  124. package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
  125. package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
  126. package/dist/lib/core/GovernanceTypes.mjs +0 -6
  127. package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
  128. package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
  129. package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
  130. package/dist/lib/core/ResponseValidator.mjs +0 -6
  131. package/dist/lib/core/ResponseValidator.mjs.map +1 -1
  132. package/dist/lib/core/SingleAgentClient.mjs +0 -6
  133. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  134. package/dist/lib/core/TaskEventTypes.mjs +0 -6
  135. package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
  136. package/dist/lib/core/TaskExecutor.mjs +0 -6
  137. package/dist/lib/core/TaskExecutor.mjs.map +1 -1
  138. package/dist/lib/core/match.mjs +0 -6
  139. package/dist/lib/core/match.mjs.map +1 -1
  140. package/dist/lib/core/task-status.mjs +0 -6
  141. package/dist/lib/core/task-status.mjs.map +1 -1
  142. package/dist/lib/core/webhook-url.mjs +0 -6
  143. package/dist/lib/core/webhook-url.mjs.map +1 -1
  144. package/dist/lib/discovery/adagents-redirects.mjs +0 -6
  145. package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
  146. package/dist/lib/discovery/agent-directory.mjs +0 -6
  147. package/dist/lib/discovery/agent-directory.mjs.map +1 -1
  148. package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
  149. package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
  150. package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
  151. package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
  152. package/dist/lib/discovery/property-crawler.mjs +0 -6
  153. package/dist/lib/discovery/property-crawler.mjs.map +1 -1
  154. package/dist/lib/discovery/property-index.mjs +0 -6
  155. package/dist/lib/discovery/property-index.mjs.map +1 -1
  156. package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
  157. package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
  158. package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
  159. package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
  160. package/dist/lib/discovery/types.mjs +0 -6
  161. package/dist/lib/discovery/validate-adagents.mjs +0 -6
  162. package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
  163. package/dist/lib/enums.mjs +0 -6
  164. package/dist/lib/enums.mjs.map +1 -1
  165. package/dist/lib/errors/index.mjs +0 -6
  166. package/dist/lib/errors/index.mjs.map +1 -1
  167. package/dist/lib/express-mcp/index.mjs +0 -6
  168. package/dist/lib/express-mcp/index.mjs.map +1 -1
  169. package/dist/lib/governance/index.mjs +0 -6
  170. package/dist/lib/governance/index.mjs.map +1 -1
  171. package/dist/lib/handlers/types.mjs +0 -6
  172. package/dist/lib/handlers/types.mjs.map +1 -1
  173. package/dist/lib/index.d.mts +1 -1
  174. package/dist/lib/index.d.ts +1 -1
  175. package/dist/lib/index.d.ts.map +1 -1
  176. package/dist/lib/index.js.map +1 -1
  177. package/dist/lib/index.mjs +0 -6
  178. package/dist/lib/index.mjs.map +1 -1
  179. package/dist/lib/media-buy/available-actions.mjs +0 -6
  180. package/dist/lib/media-buy/available-actions.mjs.map +1 -1
  181. package/dist/lib/media-buy/index.mjs +0 -6
  182. package/dist/lib/media-buy/index.mjs.map +1 -1
  183. package/dist/lib/media-buy/preflight.mjs +0 -6
  184. package/dist/lib/media-buy/preflight.mjs.map +1 -1
  185. package/dist/lib/media-buy/property-policy.mjs +0 -6
  186. package/dist/lib/media-buy/property-policy.mjs.map +1 -1
  187. package/dist/lib/media-buy/types.mjs +0 -6
  188. package/dist/lib/media-buy/types.mjs.map +1 -1
  189. package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
  190. package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
  191. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
  192. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
  193. package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
  194. package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
  195. package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
  196. package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
  197. package/dist/lib/mock-server/creative-template/server.mjs +0 -6
  198. package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
  199. package/dist/lib/mock-server/index.mjs +0 -6
  200. package/dist/lib/mock-server/index.mjs.map +1 -1
  201. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
  202. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
  203. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
  204. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
  205. package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
  206. package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
  207. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
  208. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
  209. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
  210. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
  211. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
  212. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
  213. package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
  214. package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
  215. package/dist/lib/mock-server/sales-social/server.mjs +0 -6
  216. package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
  217. package/dist/lib/mock-server/scenario.mjs +0 -6
  218. package/dist/lib/mock-server/scenario.mjs.map +1 -1
  219. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
  220. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
  221. package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
  222. package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
  223. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
  224. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
  225. package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
  226. package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
  227. package/dist/lib/net/address-guards.mjs +0 -6
  228. package/dist/lib/net/address-guards.mjs.map +1 -1
  229. package/dist/lib/net/index.mjs +0 -6
  230. package/dist/lib/net/index.mjs.map +1 -1
  231. package/dist/lib/net/ssrf-fetch.mjs +0 -6
  232. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  233. package/dist/lib/observability/index.mjs +0 -6
  234. package/dist/lib/observability/index.mjs.map +1 -1
  235. package/dist/lib/observability/tracing.mjs +6 -7
  236. package/dist/lib/observability/tracing.mjs.map +1 -1
  237. package/dist/lib/protocols/a2a.mjs +0 -6
  238. package/dist/lib/protocols/a2a.mjs.map +1 -1
  239. package/dist/lib/protocols/abort.mjs +0 -6
  240. package/dist/lib/protocols/abort.mjs.map +1 -1
  241. package/dist/lib/protocols/index.mjs +0 -6
  242. package/dist/lib/protocols/index.mjs.map +1 -1
  243. package/dist/lib/protocols/mcp-modern.mjs +0 -6
  244. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  245. package/dist/lib/protocols/mcp-tasks.mjs +0 -6
  246. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  247. package/dist/lib/protocols/mcp.mjs +0 -6
  248. package/dist/lib/protocols/mcp.mjs.map +1 -1
  249. package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
  250. package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
  251. package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
  252. package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
  253. package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
  254. package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
  255. package/dist/lib/registry/cursor-store.mjs +0 -6
  256. package/dist/lib/registry/cursor-store.mjs.map +1 -1
  257. package/dist/lib/registry/feed-stream.mjs +0 -6
  258. package/dist/lib/registry/feed-stream.mjs.map +1 -1
  259. package/dist/lib/registry/index.mjs +0 -6
  260. package/dist/lib/registry/index.mjs.map +1 -1
  261. package/dist/lib/registry/property-registry.mjs +0 -6
  262. package/dist/lib/registry/property-registry.mjs.map +1 -1
  263. package/dist/lib/registry/sync.mjs +0 -6
  264. package/dist/lib/registry/sync.mjs.map +1 -1
  265. package/dist/lib/registry/types.generated.mjs +0 -6
  266. package/dist/lib/registry/types.mjs +0 -6
  267. package/dist/lib/schemas/index.mjs +0 -6
  268. package/dist/lib/schemas/index.mjs.map +1 -1
  269. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  270. package/dist/lib/server/a2a-adapter.mjs +0 -6
  271. package/dist/lib/server/a2a-adapter.mjs.map +1 -1
  272. package/dist/lib/server/account-mode.mjs +0 -6
  273. package/dist/lib/server/account-mode.mjs.map +1 -1
  274. package/dist/lib/server/adcp-server.mjs +0 -6
  275. package/dist/lib/server/adcp-server.mjs.map +1 -1
  276. package/dist/lib/server/auth-introspection.mjs +0 -6
  277. package/dist/lib/server/auth-introspection.mjs.map +1 -1
  278. package/dist/lib/server/auth-signature.mjs +0 -6
  279. package/dist/lib/server/auth-signature.mjs.map +1 -1
  280. package/dist/lib/server/auth.mjs +0 -6
  281. package/dist/lib/server/auth.mjs.map +1 -1
  282. package/dist/lib/server/create-adcp-server.d.mts +13 -0
  283. package/dist/lib/server/create-adcp-server.d.ts +13 -0
  284. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  285. package/dist/lib/server/create-adcp-server.js +3 -2
  286. package/dist/lib/server/create-adcp-server.js.map +1 -1
  287. package/dist/lib/server/create-adcp-server.mjs +3 -8
  288. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  289. package/dist/lib/server/credential-policy.mjs +0 -6
  290. package/dist/lib/server/credential-policy.mjs.map +1 -1
  291. package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
  292. package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
  293. package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
  294. package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
  295. package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
  296. package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
  297. package/dist/lib/server/ctx-metadata/index.mjs +0 -6
  298. package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
  299. package/dist/lib/server/ctx-metadata/store.mjs +0 -6
  300. package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
  301. package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
  302. package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
  303. package/dist/lib/server/decisioning/account.mjs +0 -6
  304. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  305. package/dist/lib/server/decisioning/admin-router.mjs +0 -6
  306. package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
  307. package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
  308. package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
  309. package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
  310. package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
  311. package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
  312. package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
  313. package/dist/lib/server/decisioning/capabilities.mjs +0 -6
  314. package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
  315. package/dist/lib/server/decisioning/compose.mjs +0 -6
  316. package/dist/lib/server/decisioning/compose.mjs.map +1 -1
  317. package/dist/lib/server/decisioning/context.mjs +0 -6
  318. package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
  319. package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
  320. package/dist/lib/server/decisioning/helpers.mjs +0 -6
  321. package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
  322. package/dist/lib/server/decisioning/index.mjs +0 -6
  323. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  324. package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
  325. package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
  326. package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
  327. package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
  328. package/dist/lib/server/decisioning/pagination.mjs +0 -6
  329. package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
  330. package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
  331. package/dist/lib/server/decisioning/platform.mjs +0 -6
  332. package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
  333. package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
  334. package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
  335. package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
  336. package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
  337. package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
  338. package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
  339. package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
  340. package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
  341. package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
  342. package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
  343. package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
  344. package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
  345. package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
  346. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
  347. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
  348. package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
  349. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  350. package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
  351. package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
  352. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
  353. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
  354. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
  355. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
  356. package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
  357. package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
  358. package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
  359. package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
  360. package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
  361. package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
  362. package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
  363. package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
  364. package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
  365. package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
  366. package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
  367. package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
  368. package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
  369. package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
  370. package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
  371. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
  372. package/dist/lib/server/decisioning/start-time.mjs +0 -6
  373. package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
  374. package/dist/lib/server/decisioning/status-changes.mjs +0 -6
  375. package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
  376. package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
  377. package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
  378. package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
  379. package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
  380. package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
  381. package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
  382. package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
  383. package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
  384. package/dist/lib/server/dynamic-registry.mjs +0 -6
  385. package/dist/lib/server/dynamic-registry.mjs.map +1 -1
  386. package/dist/lib/server/envelope-allowlist.mjs +0 -6
  387. package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
  388. package/dist/lib/server/error-arm-tools.mjs +5 -6
  389. package/dist/lib/server/error-arm-tools.mjs.map +1 -1
  390. package/dist/lib/server/errors.mjs +0 -6
  391. package/dist/lib/server/errors.mjs.map +1 -1
  392. package/dist/lib/server/example-tld-guard.mjs +0 -6
  393. package/dist/lib/server/example-tld-guard.mjs.map +1 -1
  394. package/dist/lib/server/express-adapter.mjs +0 -6
  395. package/dist/lib/server/express-adapter.mjs.map +1 -1
  396. package/dist/lib/server/governance.mjs +0 -6
  397. package/dist/lib/server/governance.mjs.map +1 -1
  398. package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
  399. package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
  400. package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
  401. package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
  402. package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
  403. package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
  404. package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
  405. package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
  406. package/dist/lib/server/idempotency/index.mjs +0 -6
  407. package/dist/lib/server/idempotency/index.mjs.map +1 -1
  408. package/dist/lib/server/idempotency/store.mjs +0 -6
  409. package/dist/lib/server/idempotency/store.mjs.map +1 -1
  410. package/dist/lib/server/index.d.mts +1 -1
  411. package/dist/lib/server/index.d.ts +1 -1
  412. package/dist/lib/server/index.d.ts.map +1 -1
  413. package/dist/lib/server/index.js.map +1 -1
  414. package/dist/lib/server/index.mjs +0 -6
  415. package/dist/lib/server/index.mjs.map +1 -1
  416. package/dist/lib/server/legacy/v5/index.d.mts +1 -1
  417. package/dist/lib/server/legacy/v5/index.d.ts +1 -1
  418. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
  419. package/dist/lib/server/legacy/v5/index.js.map +1 -1
  420. package/dist/lib/server/legacy/v5/index.mjs +0 -6
  421. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  422. package/dist/lib/server/mcp-modern-server.mjs +0 -6
  423. package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
  424. package/dist/lib/server/media-buy-actions.mjs +0 -6
  425. package/dist/lib/server/media-buy-actions.mjs.map +1 -1
  426. package/dist/lib/server/media-buy-helpers.mjs +0 -6
  427. package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
  428. package/dist/lib/server/media-buy-store.mjs +0 -6
  429. package/dist/lib/server/media-buy-store.mjs.map +1 -1
  430. package/dist/lib/server/normalize-errors.mjs +0 -6
  431. package/dist/lib/server/normalize-errors.mjs.map +1 -1
  432. package/dist/lib/server/operational-platform.mjs +0 -6
  433. package/dist/lib/server/operational-platform.mjs.map +1 -1
  434. package/dist/lib/server/pick-safe-details.mjs +0 -6
  435. package/dist/lib/server/pick-safe-details.mjs.map +1 -1
  436. package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
  437. package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
  438. package/dist/lib/server/postgres-state-store.mjs +0 -6
  439. package/dist/lib/server/postgres-state-store.mjs.map +1 -1
  440. package/dist/lib/server/postgres-task-store.mjs +0 -6
  441. package/dist/lib/server/postgres-task-store.mjs.map +1 -1
  442. package/dist/lib/server/product-defaults.mjs +0 -6
  443. package/dist/lib/server/product-defaults.mjs.map +1 -1
  444. package/dist/lib/server/redact.mjs +0 -6
  445. package/dist/lib/server/redact.mjs.map +1 -1
  446. package/dist/lib/server/responses.mjs +0 -6
  447. package/dist/lib/server/responses.mjs.map +1 -1
  448. package/dist/lib/server/serve.mjs +0 -6
  449. package/dist/lib/server/serve.mjs.map +1 -1
  450. package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
  451. package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
  452. package/dist/lib/server/socket-mode/index.mjs +0 -6
  453. package/dist/lib/server/socket-mode/index.mjs.map +1 -1
  454. package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
  455. package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
  456. package/dist/lib/server/state-machine.mjs +0 -6
  457. package/dist/lib/server/state-machine.mjs.map +1 -1
  458. package/dist/lib/server/state-store.mjs +0 -6
  459. package/dist/lib/server/state-store.mjs.map +1 -1
  460. package/dist/lib/server/structured-serialize.mjs +0 -6
  461. package/dist/lib/server/structured-serialize.mjs.map +1 -1
  462. package/dist/lib/server/targeting-helpers.mjs +0 -6
  463. package/dist/lib/server/targeting-helpers.mjs.map +1 -1
  464. package/dist/lib/server/tasks.mjs +0 -6
  465. package/dist/lib/server/tasks.mjs.map +1 -1
  466. package/dist/lib/server/test-controller-bridge.mjs +0 -6
  467. package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
  468. package/dist/lib/server/test-controller.mjs +0 -6
  469. package/dist/lib/server/test-controller.mjs.map +1 -1
  470. package/dist/lib/server/upstream-helpers.mjs +0 -6
  471. package/dist/lib/server/upstream-helpers.mjs.map +1 -1
  472. package/dist/lib/server/webhook-emitter.mjs +0 -6
  473. package/dist/lib/server/webhook-emitter.mjs.map +1 -1
  474. package/dist/lib/server/wire-safe.mjs +0 -6
  475. package/dist/lib/server/wire-safe.mjs.map +1 -1
  476. package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
  477. package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
  478. package/dist/lib/server/wrap-envelope.mjs +0 -6
  479. package/dist/lib/server/wrap-envelope.mjs.map +1 -1
  480. package/dist/lib/signing/agent-context.mjs +0 -6
  481. package/dist/lib/signing/agent-context.mjs.map +1 -1
  482. package/dist/lib/signing/agent-fetch.mjs +0 -6
  483. package/dist/lib/signing/agent-fetch.mjs.map +1 -1
  484. package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
  485. package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
  486. package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
  487. package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
  488. package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
  489. package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
  490. package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
  491. package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
  492. package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
  493. package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
  494. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
  495. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
  496. package/dist/lib/signing/agent-resolver/index.mjs +0 -6
  497. package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
  498. package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
  499. package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
  500. package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
  501. package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
  502. package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
  503. package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
  504. package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
  505. package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
  506. package/dist/lib/signing/brand-jwks.mjs +0 -6
  507. package/dist/lib/signing/brand-jwks.mjs.map +1 -1
  508. package/dist/lib/signing/canonicalize.mjs +0 -6
  509. package/dist/lib/signing/canonicalize.mjs.map +1 -1
  510. package/dist/lib/signing/capability-cache.mjs +0 -6
  511. package/dist/lib/signing/capability-cache.mjs.map +1 -1
  512. package/dist/lib/signing/capability-priming.mjs +0 -6
  513. package/dist/lib/signing/capability-priming.mjs.map +1 -1
  514. package/dist/lib/signing/client.mjs +0 -6
  515. package/dist/lib/signing/client.mjs.map +1 -1
  516. package/dist/lib/signing/content-digest.mjs +0 -6
  517. package/dist/lib/signing/content-digest.mjs.map +1 -1
  518. package/dist/lib/signing/crypto.mjs +0 -6
  519. package/dist/lib/signing/crypto.mjs.map +1 -1
  520. package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
  521. package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
  522. package/dist/lib/signing/errors.mjs +0 -6
  523. package/dist/lib/signing/errors.mjs.map +1 -1
  524. package/dist/lib/signing/fetch-async.mjs +0 -6
  525. package/dist/lib/signing/fetch-async.mjs.map +1 -1
  526. package/dist/lib/signing/fetch.mjs +0 -6
  527. package/dist/lib/signing/fetch.mjs.map +1 -1
  528. package/dist/lib/signing/index.mjs +0 -6
  529. package/dist/lib/signing/index.mjs.map +1 -1
  530. package/dist/lib/signing/jwks-helpers.mjs +0 -6
  531. package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
  532. package/dist/lib/signing/jwks-https.mjs +0 -6
  533. package/dist/lib/signing/jwks-https.mjs.map +1 -1
  534. package/dist/lib/signing/jwks.mjs +0 -6
  535. package/dist/lib/signing/jwks.mjs.map +1 -1
  536. package/dist/lib/signing/middleware.mjs +0 -6
  537. package/dist/lib/signing/middleware.mjs.map +1 -1
  538. package/dist/lib/signing/parser.mjs +0 -6
  539. package/dist/lib/signing/parser.mjs.map +1 -1
  540. package/dist/lib/signing/postgres-replay-store.mjs +0 -6
  541. package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
  542. package/dist/lib/signing/protocol-response.mjs +0 -6
  543. package/dist/lib/signing/protocol-response.mjs.map +1 -1
  544. package/dist/lib/signing/provider.mjs +0 -6
  545. package/dist/lib/signing/redis-replay-store.mjs +0 -6
  546. package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
  547. package/dist/lib/signing/replay.mjs +0 -6
  548. package/dist/lib/signing/replay.mjs.map +1 -1
  549. package/dist/lib/signing/request-context.mjs +0 -6
  550. package/dist/lib/signing/request-context.mjs.map +1 -1
  551. package/dist/lib/signing/revocation-https.mjs +0 -6
  552. package/dist/lib/signing/revocation-https.mjs.map +1 -1
  553. package/dist/lib/signing/revocation.mjs +0 -6
  554. package/dist/lib/signing/revocation.mjs.map +1 -1
  555. package/dist/lib/signing/server.mjs +0 -6
  556. package/dist/lib/signing/server.mjs.map +1 -1
  557. package/dist/lib/signing/signer-async.mjs +0 -6
  558. package/dist/lib/signing/signer-async.mjs.map +1 -1
  559. package/dist/lib/signing/signer.mjs +0 -6
  560. package/dist/lib/signing/signer.mjs.map +1 -1
  561. package/dist/lib/signing/testing.mjs +0 -6
  562. package/dist/lib/signing/testing.mjs.map +1 -1
  563. package/dist/lib/signing/types.mjs +0 -6
  564. package/dist/lib/signing/types.mjs.map +1 -1
  565. package/dist/lib/signing/verifier.mjs +0 -6
  566. package/dist/lib/signing/verifier.mjs.map +1 -1
  567. package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
  568. package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
  569. package/dist/lib/signing/webhook-verifier.mjs +0 -6
  570. package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
  571. package/dist/lib/storage/MemoryStorage.mjs +0 -6
  572. package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
  573. package/dist/lib/storage/interfaces.mjs +0 -6
  574. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
  575. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
  576. package/dist/lib/substitution/encoder/index.mjs +0 -6
  577. package/dist/lib/substitution/encoder/index.mjs.map +1 -1
  578. package/dist/lib/substitution/index.mjs +0 -6
  579. package/dist/lib/substitution/index.mjs.map +1 -1
  580. package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
  581. package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
  582. package/dist/lib/substitution/observer/alignment.mjs +0 -6
  583. package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
  584. package/dist/lib/substitution/observer/assertions.mjs +0 -6
  585. package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
  586. package/dist/lib/substitution/observer/html-parser.mjs +0 -6
  587. package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
  588. package/dist/lib/substitution/observer/index.mjs +0 -6
  589. package/dist/lib/substitution/observer/index.mjs.map +1 -1
  590. package/dist/lib/substitution/observer/ssrf.mjs +0 -6
  591. package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
  592. package/dist/lib/substitution/rfc3986.mjs +0 -6
  593. package/dist/lib/substitution/rfc3986.mjs.map +1 -1
  594. package/dist/lib/substitution/translate.mjs +0 -6
  595. package/dist/lib/substitution/translate.mjs.map +1 -1
  596. package/dist/lib/substitution/types.mjs +0 -6
  597. package/dist/lib/substitution/vectors.mjs +0 -6
  598. package/dist/lib/substitution/vectors.mjs.map +1 -1
  599. package/dist/lib/testing/agent-tester.mjs +0 -6
  600. package/dist/lib/testing/agent-tester.mjs.map +1 -1
  601. package/dist/lib/testing/client.mjs +0 -6
  602. package/dist/lib/testing/client.mjs.map +1 -1
  603. package/dist/lib/testing/compliance/briefs.mjs +0 -6
  604. package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
  605. package/dist/lib/testing/compliance/comply.mjs +0 -6
  606. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  607. package/dist/lib/testing/compliance/index.mjs +0 -6
  608. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  609. package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
  610. package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
  611. package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
  612. package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
  613. package/dist/lib/testing/compliance/summary.mjs +0 -6
  614. package/dist/lib/testing/compliance/summary.mjs.map +1 -1
  615. package/dist/lib/testing/compliance/types.mjs +0 -6
  616. package/dist/lib/testing/comply-controller.mjs +0 -6
  617. package/dist/lib/testing/comply-controller.mjs.map +1 -1
  618. package/dist/lib/testing/controller-assertions.mjs +0 -6
  619. package/dist/lib/testing/controller-assertions.mjs.map +1 -1
  620. package/dist/lib/testing/formatter.mjs +0 -6
  621. package/dist/lib/testing/formatter.mjs.map +1 -1
  622. package/dist/lib/testing/index.mjs +0 -6
  623. package/dist/lib/testing/index.mjs.map +1 -1
  624. package/dist/lib/testing/local-agent-runner.mjs +0 -6
  625. package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
  626. package/dist/lib/testing/orchestrator.mjs +0 -6
  627. package/dist/lib/testing/orchestrator.mjs.map +1 -1
  628. package/dist/lib/testing/personas/index.mjs +0 -6
  629. package/dist/lib/testing/personas/index.mjs.map +1 -1
  630. package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
  631. package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
  632. package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
  633. package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
  634. package/dist/lib/testing/scenarios/creative.mjs +0 -6
  635. package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
  636. package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
  637. package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
  638. package/dist/lib/testing/scenarios/discovery.mjs +0 -6
  639. package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
  640. package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
  641. package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
  642. package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
  643. package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
  644. package/dist/lib/testing/scenarios/governance.mjs +0 -6
  645. package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
  646. package/dist/lib/testing/scenarios/health.mjs +0 -6
  647. package/dist/lib/testing/scenarios/health.mjs.map +1 -1
  648. package/dist/lib/testing/scenarios/index.mjs +0 -6
  649. package/dist/lib/testing/scenarios/index.mjs.map +1 -1
  650. package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
  651. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  652. package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
  653. package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
  654. package/dist/lib/testing/scenarios/signals.mjs +0 -6
  655. package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
  656. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
  657. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
  658. package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
  659. package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
  660. package/dist/lib/testing/seed-merge.mjs +0 -6
  661. package/dist/lib/testing/seed-merge.mjs.map +1 -1
  662. package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
  663. package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
  664. package/dist/lib/testing/storyboard/assertions.mjs +0 -6
  665. package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
  666. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
  667. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
  668. package/dist/lib/testing/storyboard/compliance.mjs +5 -6
  669. package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
  670. package/dist/lib/testing/storyboard/context.mjs +0 -6
  671. package/dist/lib/testing/storyboard/context.mjs.map +1 -1
  672. package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
  673. package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
  674. package/dist/lib/testing/storyboard/index.mjs +0 -6
  675. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  676. package/dist/lib/testing/storyboard/junit.mjs +0 -6
  677. package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
  678. package/dist/lib/testing/storyboard/loader.mjs +0 -6
  679. package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
  680. package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
  681. package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
  682. package/dist/lib/testing/storyboard/path.mjs +0 -6
  683. package/dist/lib/testing/storyboard/path.mjs.map +1 -1
  684. package/dist/lib/testing/storyboard/probes.mjs +0 -6
  685. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  686. package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
  687. package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
  688. package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
  689. package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
  690. package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
  691. package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
  692. package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
  693. package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
  694. package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
  695. package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
  696. package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
  697. package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
  698. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
  699. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
  700. package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
  701. package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
  702. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
  703. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
  704. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
  705. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
  706. package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
  707. package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
  708. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
  709. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
  710. package/dist/lib/testing/storyboard/runner.mjs +0 -6
  711. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  712. package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
  713. package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
  714. package/dist/lib/testing/storyboard/seeding.mjs +0 -6
  715. package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
  716. package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
  717. package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
  718. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
  719. package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
  720. package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
  721. package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
  722. package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
  723. package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
  724. package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
  725. package/dist/lib/testing/storyboard/task-map.mjs +0 -6
  726. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  727. package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
  728. package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
  729. package/dist/lib/testing/storyboard/types.mjs +0 -6
  730. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  731. package/dist/lib/testing/storyboard/validations.mjs +0 -6
  732. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  733. package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
  734. package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
  735. package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
  736. package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
  737. package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
  738. package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
  739. package/dist/lib/testing/stubs/index.mjs +0 -6
  740. package/dist/lib/testing/stubs/index.mjs.map +1 -1
  741. package/dist/lib/testing/test-controller.mjs +0 -6
  742. package/dist/lib/testing/test-controller.mjs.map +1 -1
  743. package/dist/lib/testing/test-helpers.mjs +0 -6
  744. package/dist/lib/testing/test-helpers.mjs.map +1 -1
  745. package/dist/lib/testing/types.mjs +0 -6
  746. package/dist/lib/types/adcp.mjs +0 -6
  747. package/dist/lib/types/adcp.mjs.map +1 -1
  748. package/dist/lib/types/asset-instances.mjs +0 -6
  749. package/dist/lib/types/compat.mjs +0 -6
  750. package/dist/lib/types/compat.mjs.map +1 -1
  751. package/dist/lib/types/core.generated.mjs +0 -6
  752. package/dist/lib/types/enums.generated.mjs +0 -6
  753. package/dist/lib/types/enums.generated.mjs.map +1 -1
  754. package/dist/lib/types/error-codes.mjs +0 -6
  755. package/dist/lib/types/error-codes.mjs.map +1 -1
  756. package/dist/lib/types/error-details.aliases.mjs +0 -6
  757. package/dist/lib/types/error-details.aliases.mjs.map +1 -1
  758. package/dist/lib/types/format-asset-slots.mjs +0 -6
  759. package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
  760. package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
  761. package/dist/lib/types/index.mjs +0 -6
  762. package/dist/lib/types/index.mjs.map +1 -1
  763. package/dist/lib/types/inline-enums.aliases.mjs +0 -6
  764. package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
  765. package/dist/lib/types/inline-enums.generated.mjs +0 -6
  766. package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
  767. package/dist/lib/types/manifest.generated.mjs +0 -6
  768. package/dist/lib/types/manifest.generated.mjs.map +1 -1
  769. package/dist/lib/types/schemas.generated.mjs +0 -6
  770. package/dist/lib/types/schemas.generated.mjs.map +1 -1
  771. package/dist/lib/types/server-payload-aliases.mjs +0 -6
  772. package/dist/lib/types/server-payload.mjs +0 -6
  773. package/dist/lib/types/sync-rows.mjs +0 -6
  774. package/dist/lib/types/tools.generated.mjs +0 -6
  775. package/dist/lib/types/v2-5/index.mjs +0 -6
  776. package/dist/lib/types/v2-5/index.mjs.map +1 -1
  777. package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
  778. package/dist/lib/types/v3-1-beta/index.mjs +0 -6
  779. package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
  780. package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
  781. package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
  782. package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
  783. package/dist/lib/upstream-recorder/constants.mjs +0 -6
  784. package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
  785. package/dist/lib/upstream-recorder/index.mjs +0 -6
  786. package/dist/lib/upstream-recorder/index.mjs.map +1 -1
  787. package/dist/lib/upstream-recorder/recorder.mjs +0 -6
  788. package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
  789. package/dist/lib/upstream-recorder/types.mjs +0 -6
  790. package/dist/lib/upstream-recorder/types.mjs.map +1 -1
  791. package/dist/lib/utils/a2a-artifacts.mjs +0 -6
  792. package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
  793. package/dist/lib/utils/a2a-discovery.mjs +0 -6
  794. package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
  795. package/dist/lib/utils/activation-key-builders.mjs +0 -6
  796. package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
  797. package/dist/lib/utils/adcp-version-config.mjs +0 -6
  798. package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
  799. package/dist/lib/utils/asset-builders.mjs +0 -6
  800. package/dist/lib/utils/asset-builders.mjs.map +1 -1
  801. package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
  802. package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
  803. package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
  804. package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
  805. package/dist/lib/utils/capabilities.mjs +0 -6
  806. package/dist/lib/utils/capabilities.mjs.map +1 -1
  807. package/dist/lib/utils/capability-rollups.mjs +0 -6
  808. package/dist/lib/utils/capability-rollups.mjs.map +1 -1
  809. package/dist/lib/utils/creative-adapter.mjs +0 -6
  810. package/dist/lib/utils/creative-adapter.mjs.map +1 -1
  811. package/dist/lib/utils/creative-delivery.mjs +0 -6
  812. package/dist/lib/utils/creative-delivery.mjs.map +1 -1
  813. package/dist/lib/utils/deprecation.mjs +0 -6
  814. package/dist/lib/utils/deprecation.mjs.map +1 -1
  815. package/dist/lib/utils/envelope-status-compat.mjs +0 -6
  816. package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
  817. package/dist/lib/utils/error-extraction.mjs +0 -6
  818. package/dist/lib/utils/error-extraction.mjs.map +1 -1
  819. package/dist/lib/utils/extract-result.mjs +0 -6
  820. package/dist/lib/utils/extract-result.mjs.map +1 -1
  821. package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
  822. package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
  823. package/dist/lib/utils/format-assets.mjs +0 -6
  824. package/dist/lib/utils/format-assets.mjs.map +1 -1
  825. package/dist/lib/utils/format-render-builders.mjs +0 -6
  826. package/dist/lib/utils/format-render-builders.mjs.map +1 -1
  827. package/dist/lib/utils/format-renders.mjs +0 -6
  828. package/dist/lib/utils/format-renders.mjs.map +1 -1
  829. package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
  830. package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
  831. package/dist/lib/utils/glob.mjs +0 -6
  832. package/dist/lib/utils/glob.mjs.map +1 -1
  833. package/dist/lib/utils/global-async-local-storage.mjs +0 -6
  834. package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
  835. package/dist/lib/utils/idempotency.mjs +0 -6
  836. package/dist/lib/utils/idempotency.mjs.map +1 -1
  837. package/dist/lib/utils/index.mjs +0 -6
  838. package/dist/lib/utils/index.mjs.map +1 -1
  839. package/dist/lib/utils/jcs.mjs +0 -6
  840. package/dist/lib/utils/jcs.mjs.map +1 -1
  841. package/dist/lib/utils/json-depth.mjs +0 -6
  842. package/dist/lib/utils/json-depth.mjs.map +1 -1
  843. package/dist/lib/utils/logger.mjs +0 -6
  844. package/dist/lib/utils/logger.mjs.map +1 -1
  845. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
  846. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
  847. package/dist/lib/utils/media-buy-status.mjs +0 -6
  848. package/dist/lib/utils/media-buy-status.mjs.map +1 -1
  849. package/dist/lib/utils/pagination.mjs +0 -6
  850. package/dist/lib/utils/pagination.mjs.map +1 -1
  851. package/dist/lib/utils/preview-creative-builders.mjs +0 -6
  852. package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
  853. package/dist/lib/utils/preview-normalizer.mjs +0 -6
  854. package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
  855. package/dist/lib/utils/preview-utils.mjs +0 -6
  856. package/dist/lib/utils/preview-utils.mjs.map +1 -1
  857. package/dist/lib/utils/pricing-adapter.mjs +0 -6
  858. package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
  859. package/dist/lib/utils/probe-policy.mjs +0 -6
  860. package/dist/lib/utils/probe-policy.mjs.map +1 -1
  861. package/dist/lib/utils/protocol-detection.mjs +0 -6
  862. package/dist/lib/utils/protocol-detection.mjs.map +1 -1
  863. package/dist/lib/utils/redact-secrets.mjs +0 -6
  864. package/dist/lib/utils/redact-secrets.mjs.map +1 -1
  865. package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
  866. package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
  867. package/dist/lib/utils/render-builders.mjs +0 -6
  868. package/dist/lib/utils/render-builders.mjs.map +1 -1
  869. package/dist/lib/utils/request-normalizer.mjs +0 -6
  870. package/dist/lib/utils/request-normalizer.mjs.map +1 -1
  871. package/dist/lib/utils/response-schemas.mjs +0 -6
  872. package/dist/lib/utils/response-schemas.mjs.map +1 -1
  873. package/dist/lib/utils/response-unwrapper.mjs +0 -6
  874. package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
  875. package/dist/lib/utils/retry.mjs +0 -6
  876. package/dist/lib/utils/retry.mjs.map +1 -1
  877. package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
  878. package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
  879. package/dist/lib/utils/signal-id-builders.mjs +0 -6
  880. package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
  881. package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
  882. package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
  883. package/dist/lib/utils/task-state.mjs +0 -6
  884. package/dist/lib/utils/task-state.mjs.map +1 -1
  885. package/dist/lib/utils/tool-request-schemas.mjs +0 -6
  886. package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
  887. package/dist/lib/utils/typeGuards.mjs +0 -6
  888. package/dist/lib/utils/typeGuards.mjs.map +1 -1
  889. package/dist/lib/utils/union-errors.mjs +0 -6
  890. package/dist/lib/utils/union-errors.mjs.map +1 -1
  891. package/dist/lib/utils/validate-user-agent.mjs +0 -6
  892. package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
  893. package/dist/lib/v2/format-schema/fetch.mjs +0 -6
  894. package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
  895. package/dist/lib/v2/format-schema/index.mjs +0 -6
  896. package/dist/lib/v2/format-schema/index.mjs.map +1 -1
  897. package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
  898. package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
  899. package/dist/lib/v2/format-schema/resolver.mjs +7 -8
  900. package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
  901. package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
  902. package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
  903. package/dist/lib/v2/projection/augment-response.mjs +0 -6
  904. package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
  905. package/dist/lib/v2/projection/builders.mjs +0 -6
  906. package/dist/lib/v2/projection/builders.mjs.map +1 -1
  907. package/dist/lib/v2/projection/cache-versions.mjs +0 -6
  908. package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
  909. package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
  910. package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
  911. package/dist/lib/v2/projection/catalog.mjs +5 -6
  912. package/dist/lib/v2/projection/catalog.mjs.map +1 -1
  913. package/dist/lib/v2/projection/constants.mjs +0 -6
  914. package/dist/lib/v2/projection/constants.mjs.map +1 -1
  915. package/dist/lib/v2/projection/index.mjs +0 -6
  916. package/dist/lib/v2/projection/index.mjs.map +1 -1
  917. package/dist/lib/v2/projection/registry.mjs +5 -6
  918. package/dist/lib/v2/projection/registry.mjs.map +1 -1
  919. package/dist/lib/v2/projection/types.mjs +0 -6
  920. package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
  921. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  922. package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
  923. package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
  924. package/dist/lib/v2/projection/write-side.mjs +0 -6
  925. package/dist/lib/v2/projection/write-side.mjs.map +1 -1
  926. package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
  927. package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
  928. package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
  929. package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
  930. package/dist/lib/validation/client-hooks.mjs +0 -6
  931. package/dist/lib/validation/client-hooks.mjs.map +1 -1
  932. package/dist/lib/validation/hints.mjs +0 -6
  933. package/dist/lib/validation/hints.mjs.map +1 -1
  934. package/dist/lib/validation/index.mjs +0 -6
  935. package/dist/lib/validation/index.mjs.map +1 -1
  936. package/dist/lib/validation/schema-errors.mjs +0 -6
  937. package/dist/lib/validation/schema-errors.mjs.map +1 -1
  938. package/dist/lib/validation/schema-loader.mjs +5 -6
  939. package/dist/lib/validation/schema-loader.mjs.map +1 -1
  940. package/dist/lib/validation/schema-validator.mjs +0 -6
  941. package/dist/lib/validation/schema-validator.mjs.map +1 -1
  942. package/dist/lib/validation/sync-creatives.mjs +0 -6
  943. package/dist/lib/validation/sync-creatives.mjs.map +1 -1
  944. package/dist/lib/version.d.mts +3 -3
  945. package/dist/lib/version.d.ts +3 -3
  946. package/dist/lib/version.js +3 -3
  947. package/dist/lib/version.js.map +1 -1
  948. package/dist/lib/version.mjs +3 -9
  949. package/dist/lib/version.mjs.map +1 -1
  950. package/dist/lib/webhooks/index.mjs +0 -6
  951. package/dist/lib/webhooks/index.mjs.map +1 -1
  952. package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
  953. package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
  954. package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
  955. package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
  956. package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
  957. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
  958. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
  959. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/preview-utils.ts"],"sourcesContent":["// Preview utilities for rendering product/format cards with creative agent\n\nimport type { SingleAgentClient } from '../core/SingleAgentClient';\nimport type { Format, Product, FormatReferenceStructuredObject as FormatID } from '../types/tools.generated';\nimport type { PreviewCreativeRequest, PreviewCreativeResponse } from '../types/tools.generated';\n\n/**\n * Preview result for a single item (product or format)\n */\nexport interface PreviewResult {\n /** The item being previewed (Product or Format) */\n item: Product | Format;\n /** Preview URL for the rendered card */\n previewUrl?: string;\n /** Preview ID from the creative agent */\n previewId?: string;\n /** Error message if preview failed */\n error?: string;\n}\n\n/**\n * Options for batch preview generation\n */\nexport interface BatchPreviewOptions {\n /** Cache TTL in milliseconds (defaults to 1 hour) */\n cacheTtl?: number;\n /** Whether to skip cache and force fresh previews (defaults to false) */\n skipCache?: boolean;\n /**\n * Cache backend for preview results.\n *\n * The default backend is process-local memory. It is safe for tests,\n * local development, and single-process CLIs, but it is not shared\n * across pods and does not survive restarts. Production services that\n * cache preview URLs should provide a shared backend such as Redis or\n * Postgres, and the cached URL itself must still resolve to durable\n * storage rather than process-local assets.\n */\n cacheBackend?: PreviewCacheBackend;\n}\n\n/**\n * Cache entry for preview results\n */\nexport interface PreviewCacheEntry {\n previewUrl: string;\n previewId: string;\n timestamp: number;\n /** ISO 8601 timestamp from `preview_creative.expires_at`, when provided. */\n expiresAt?: string;\n}\n\n/**\n * Pluggable cache backend for preview results.\n *\n * This cache stores references returned by `preview_creative`; it is not\n * an asset store. Preview URLs placed in any cache must already be\n * durable across load-balancer hops, pod restarts, and later refinement\n * calls.\n */\nexport interface PreviewCacheBackend {\n get(cacheKey: string): PreviewCacheEntry | null | undefined | Promise<PreviewCacheEntry | null | undefined>;\n set(cacheKey: string, entry: PreviewCacheEntry): void | Promise<void>;\n delete?(cacheKey: string): void | Promise<void>;\n clear?(): void | Promise<void>;\n}\n\n/**\n * Process-local in-memory cache for preview results.\n *\n * Development-only default: this map is not multi-pod-safe and does not\n * survive process restarts. It must not be used as the backing store for\n * MCPUI preview assets in production.\n *\n * Key format: `${formatId.agent_url}:${formatId.id}:${manifestHash}`\n */\nconst previewCache = new Map<string, PreviewCacheEntry>();\n\nconst defaultPreviewCacheBackend: PreviewCacheBackend = {\n get(cacheKey) {\n return previewCache.get(cacheKey);\n },\n set(cacheKey, entry) {\n previewCache.set(cacheKey, entry);\n },\n delete(cacheKey) {\n previewCache.delete(cacheKey);\n },\n clear() {\n previewCache.clear();\n },\n};\n\n/**\n * Generate a cache key for a preview request\n */\nfunction getCacheKey(formatId: FormatID, manifest: any): string {\n // Simple hash of manifest for cache key\n const manifestStr = JSON.stringify(manifest);\n const manifestHash = Array.from(manifestStr)\n .reduce((hash, char) => (hash << 5) - hash + char.charCodeAt(0), 0)\n .toString(36);\n\n return `${formatId.agent_url}:${formatId.id}:${manifestHash}`;\n}\n\nfunction hasExpiredAt(expiresAt: string | undefined, now: number): boolean {\n if (!expiresAt) return false;\n const expiresAtMs = Date.parse(expiresAt);\n return Number.isNaN(expiresAtMs) ? false : expiresAtMs <= now;\n}\n\n/**\n * Get cached preview if available and not expired\n */\nasync function getCachedPreview(\n cacheBackend: PreviewCacheBackend,\n cacheKey: string,\n ttl: number\n): Promise<PreviewCacheEntry | null> {\n const entry = await cacheBackend.get(cacheKey);\n if (!entry) return null;\n\n const now = Date.now();\n if (now - entry.timestamp > ttl || hasExpiredAt(entry.expiresAt, now)) {\n await cacheBackend.delete?.(cacheKey);\n return null;\n }\n\n return entry;\n}\n\n/**\n * Set cached preview\n */\nasync function setCachedPreview(\n cacheBackend: PreviewCacheBackend,\n cacheKey: string,\n previewUrl: string,\n previewId: string,\n expiresAt?: string\n): Promise<void> {\n await cacheBackend.set(cacheKey, {\n previewUrl,\n previewId,\n expiresAt,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Clear all previews from the default process-local cache.\n */\nexport function clearPreviewCache(): void {\n defaultPreviewCacheBackend.clear?.();\n}\n\n/**\n * Extract preview URLs from products' `product_card` fields.\n *\n * AdCP 3.1.0-beta.2 changed `product_card` from a creative-agent-rendered\n * shape (`{ format_id, manifest }`) to a self-contained visual card\n * (`{ image, title, description, price_label, cta_label }`). The card IS\n * the preview — no creative-agent round-trip required. This function now\n * extracts the image URL directly from the inline card.\n *\n * Products with no `product_card`, or with a card that lacks an `image.url`,\n * return a result with no `previewUrl`. The function preserves its\n * `Promise<PreviewResult[]>` return shape so existing adopters' code paths\n * keep compiling and behaving correctly.\n *\n * @param products - Array of products to extract previews from\n * @param creativeAgentClient - Retained for signature compatibility; unused\n * under 3.1.0-beta.2's self-rendering card model. Will be removed in\n * 8.0 final (or 9.0 at the latest) — pass any value through during the\n * beta cycle.\n * @param options - Retained for signature compatibility. Cache fields\n * (`cacheTtl`, `skipCache`) are unused — there's no expensive call to\n * cache. Will be removed alongside `creativeAgentClient`.\n * @returns Array of preview results matching input products by index.\n *\n * @example\n * ```typescript\n * const previews = await batchPreviewProducts(products, creativeAgent);\n * previews.forEach(p => {\n * if (p.previewUrl) {\n * console.log(`${p.item.name}: ${p.previewUrl}`);\n * }\n * });\n * ```\n *\n * @deprecated Use `product.product_card?.image?.url` directly. This wrapper\n * only exists for 8.0-beta migration ergonomics and will be removed.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport async function batchPreviewProducts(\n products: Product[],\n _creativeAgentClient: SingleAgentClient,\n _options: BatchPreviewOptions = {}\n): Promise<PreviewResult[]> {\n return products.map(product => {\n const imageUrl = product.product_card?.image?.url;\n if (imageUrl) {\n return { item: product, previewUrl: imageUrl };\n }\n return { item: product };\n });\n}\n\n/**\n * Generate batch previews for formats with format_card manifests\n *\n * Formats with format_card fields will have their cards rendered via the creative agent.\n * Formats without format_card will be returned with no preview.\n *\n * @param formats - Array of formats to preview\n * @param creativeAgentClient - ADCP client configured for creative agent\n * @param options - Preview generation options\n * @returns Array of preview results matching input formats\n *\n * @example\n * ```typescript\n * const creativeAgent = new SingleAgentClient({\n * id: 'creative',\n * name: 'Creative Agent',\n * agent_uri: 'https://creative.adcontextprotocol.org/mcp',\n * protocol: 'mcp'\n * });\n *\n * const previews = await batchPreviewFormats(formats, creativeAgent);\n * previews.forEach(p => {\n * if (p.previewUrl) {\n * console.log(`${(p.item as Format).name}: ${p.previewUrl}`);\n * }\n * });\n * ```\n */\nexport async function batchPreviewFormats(\n formats: Format[],\n creativeAgentClient: SingleAgentClient,\n options: BatchPreviewOptions = {}\n): Promise<PreviewResult[]> {\n const cacheTtl = options.cacheTtl ?? 3600000; // 1 hour default\n const skipCache = options.skipCache ?? false;\n const cacheBackend = options.cacheBackend ?? defaultPreviewCacheBackend;\n\n // Collect all formats that have format_card manifests\n const previewRequests: {\n format: Format;\n formatId: FormatID;\n manifest: any;\n cacheKey: string;\n inputName: string;\n }[] = [];\n\n const results: PreviewResult[] = [];\n\n for (const format of formats) {\n if (format.format_card) {\n const cacheKey = getCacheKey(format.format_card.format_id, format.format_card.manifest);\n\n // Check cache first\n if (!skipCache) {\n let cached: PreviewCacheEntry | null = null;\n try {\n cached = await getCachedPreview(cacheBackend, cacheKey, cacheTtl);\n } catch {\n cached = null;\n }\n if (cached) {\n results.push({\n item: format,\n previewUrl: cached.previewUrl,\n previewId: cached.previewId,\n });\n continue;\n }\n }\n\n previewRequests.push({\n format,\n formatId: format.format_card.format_id,\n manifest: format.format_card.manifest,\n cacheKey,\n inputName: format.name || 'Format Card',\n });\n } else {\n // No format_card, return format with no preview\n results.push({\n item: format,\n });\n }\n }\n\n // If all were cached or none have format_card, return early\n if (previewRequests.length === 0) {\n return results;\n }\n\n // Batch preview using preview_creative with inputs array\n // Group by format_id since preview_creative takes one format_id\n const groupedByFormat = new Map<string, typeof previewRequests>();\n\n previewRequests.forEach(req => {\n const formatKey = `${req.formatId.agent_url}:${req.formatId.id}`;\n if (!groupedByFormat.has(formatKey)) {\n groupedByFormat.set(formatKey, []);\n }\n groupedByFormat.get(formatKey)!.push(req);\n });\n\n // Process each format individually\n // Note: Each format has different manifest data, so we can't truly batch them\n // We process them sequentially but could parallelize in the future\n for (const req of previewRequests) {\n try {\n // Build preview_creative request for this format\n // For format cards, the manifest typically contains the format object as JSON\n const previewRequest: PreviewCreativeRequest = {\n request_type: 'single',\n format_id: req.formatId,\n creative_manifest: {\n format_id: req.formatId,\n assets: req.manifest, // manifest contains the asset map (format, etc)\n },\n };\n\n // Call preview_creative\n const response = await creativeAgentClient.previewCreative(previewRequest);\n\n // Check for data even if validation failed (response.success may be false due to schema warnings)\n // Handle both single request (previews) and batch request (results) response formats\n const responseData = response.data;\n if (responseData && 'previews' in responseData && responseData.previews && responseData.previews.length > 0) {\n const preview = responseData.previews[0]!;\n if (preview.renders && preview.renders.length > 0) {\n const render = preview.renders[0]!;\n const previewUrl =\n render.output_format === 'url' || render.output_format === 'both' ? render.preview_url : undefined;\n const previewId = preview.preview_id;\n\n if (previewUrl) {\n results.push({\n item: req.format,\n previewUrl,\n previewId,\n });\n try {\n await setCachedPreview(cacheBackend, req.cacheKey, previewUrl, previewId, responseData.expires_at);\n } catch {\n // Preview cache is an accelerator; successful previews should still return on cache write failures.\n }\n } else {\n results.push({\n item: req.format,\n error: 'Preview render has no URL',\n });\n }\n } else {\n results.push({\n item: req.format,\n error: 'No renders in preview response',\n });\n }\n } else {\n // Only treat as error if we have no data at all\n results.push({\n item: req.format,\n error: response.error || 'Preview generation failed',\n });\n }\n } catch (error) {\n results.push({\n item: req.format,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n return results;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/preview-utils.ts"],"sourcesContent":["// Preview utilities for rendering product/format cards with creative agent\n\nimport type { SingleAgentClient } from '../core/SingleAgentClient';\nimport type { Format, Product, FormatReferenceStructuredObject as FormatID } from '../types/tools.generated';\nimport type { PreviewCreativeRequest, PreviewCreativeResponse } from '../types/tools.generated';\n\n/**\n * Preview result for a single item (product or format)\n */\nexport interface PreviewResult {\n /** The item being previewed (Product or Format) */\n item: Product | Format;\n /** Preview URL for the rendered card */\n previewUrl?: string;\n /** Preview ID from the creative agent */\n previewId?: string;\n /** Error message if preview failed */\n error?: string;\n}\n\n/**\n * Options for batch preview generation\n */\nexport interface BatchPreviewOptions {\n /** Cache TTL in milliseconds (defaults to 1 hour) */\n cacheTtl?: number;\n /** Whether to skip cache and force fresh previews (defaults to false) */\n skipCache?: boolean;\n /**\n * Cache backend for preview results.\n *\n * The default backend is process-local memory. It is safe for tests,\n * local development, and single-process CLIs, but it is not shared\n * across pods and does not survive restarts. Production services that\n * cache preview URLs should provide a shared backend such as Redis or\n * Postgres, and the cached URL itself must still resolve to durable\n * storage rather than process-local assets.\n */\n cacheBackend?: PreviewCacheBackend;\n}\n\n/**\n * Cache entry for preview results\n */\nexport interface PreviewCacheEntry {\n previewUrl: string;\n previewId: string;\n timestamp: number;\n /** ISO 8601 timestamp from `preview_creative.expires_at`, when provided. */\n expiresAt?: string;\n}\n\n/**\n * Pluggable cache backend for preview results.\n *\n * This cache stores references returned by `preview_creative`; it is not\n * an asset store. Preview URLs placed in any cache must already be\n * durable across load-balancer hops, pod restarts, and later refinement\n * calls.\n */\nexport interface PreviewCacheBackend {\n get(cacheKey: string): PreviewCacheEntry | null | undefined | Promise<PreviewCacheEntry | null | undefined>;\n set(cacheKey: string, entry: PreviewCacheEntry): void | Promise<void>;\n delete?(cacheKey: string): void | Promise<void>;\n clear?(): void | Promise<void>;\n}\n\n/**\n * Process-local in-memory cache for preview results.\n *\n * Development-only default: this map is not multi-pod-safe and does not\n * survive process restarts. It must not be used as the backing store for\n * MCPUI preview assets in production.\n *\n * Key format: `${formatId.agent_url}:${formatId.id}:${manifestHash}`\n */\nconst previewCache = new Map<string, PreviewCacheEntry>();\n\nconst defaultPreviewCacheBackend: PreviewCacheBackend = {\n get(cacheKey) {\n return previewCache.get(cacheKey);\n },\n set(cacheKey, entry) {\n previewCache.set(cacheKey, entry);\n },\n delete(cacheKey) {\n previewCache.delete(cacheKey);\n },\n clear() {\n previewCache.clear();\n },\n};\n\n/**\n * Generate a cache key for a preview request\n */\nfunction getCacheKey(formatId: FormatID, manifest: any): string {\n // Simple hash of manifest for cache key\n const manifestStr = JSON.stringify(manifest);\n const manifestHash = Array.from(manifestStr)\n .reduce((hash, char) => (hash << 5) - hash + char.charCodeAt(0), 0)\n .toString(36);\n\n return `${formatId.agent_url}:${formatId.id}:${manifestHash}`;\n}\n\nfunction hasExpiredAt(expiresAt: string | undefined, now: number): boolean {\n if (!expiresAt) return false;\n const expiresAtMs = Date.parse(expiresAt);\n return Number.isNaN(expiresAtMs) ? false : expiresAtMs <= now;\n}\n\n/**\n * Get cached preview if available and not expired\n */\nasync function getCachedPreview(\n cacheBackend: PreviewCacheBackend,\n cacheKey: string,\n ttl: number\n): Promise<PreviewCacheEntry | null> {\n const entry = await cacheBackend.get(cacheKey);\n if (!entry) return null;\n\n const now = Date.now();\n if (now - entry.timestamp > ttl || hasExpiredAt(entry.expiresAt, now)) {\n await cacheBackend.delete?.(cacheKey);\n return null;\n }\n\n return entry;\n}\n\n/**\n * Set cached preview\n */\nasync function setCachedPreview(\n cacheBackend: PreviewCacheBackend,\n cacheKey: string,\n previewUrl: string,\n previewId: string,\n expiresAt?: string\n): Promise<void> {\n await cacheBackend.set(cacheKey, {\n previewUrl,\n previewId,\n expiresAt,\n timestamp: Date.now(),\n });\n}\n\n/**\n * Clear all previews from the default process-local cache.\n */\nexport function clearPreviewCache(): void {\n defaultPreviewCacheBackend.clear?.();\n}\n\n/**\n * Extract preview URLs from products' `product_card` fields.\n *\n * AdCP 3.1.0-beta.2 changed `product_card` from a creative-agent-rendered\n * shape (`{ format_id, manifest }`) to a self-contained visual card\n * (`{ image, title, description, price_label, cta_label }`). The card IS\n * the preview — no creative-agent round-trip required. This function now\n * extracts the image URL directly from the inline card.\n *\n * Products with no `product_card`, or with a card that lacks an `image.url`,\n * return a result with no `previewUrl`. The function preserves its\n * `Promise<PreviewResult[]>` return shape so existing adopters' code paths\n * keep compiling and behaving correctly.\n *\n * @param products - Array of products to extract previews from\n * @param creativeAgentClient - Retained for signature compatibility; unused\n * under 3.1.0-beta.2's self-rendering card model. Will be removed in\n * 8.0 final (or 9.0 at the latest) — pass any value through during the\n * beta cycle.\n * @param options - Retained for signature compatibility. Cache fields\n * (`cacheTtl`, `skipCache`) are unused — there's no expensive call to\n * cache. Will be removed alongside `creativeAgentClient`.\n * @returns Array of preview results matching input products by index.\n *\n * @example\n * ```typescript\n * const previews = await batchPreviewProducts(products, creativeAgent);\n * previews.forEach(p => {\n * if (p.previewUrl) {\n * console.log(`${p.item.name}: ${p.previewUrl}`);\n * }\n * });\n * ```\n *\n * @deprecated Use `product.product_card?.image?.url` directly. This wrapper\n * only exists for 8.0-beta migration ergonomics and will be removed.\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport async function batchPreviewProducts(\n products: Product[],\n _creativeAgentClient: SingleAgentClient,\n _options: BatchPreviewOptions = {}\n): Promise<PreviewResult[]> {\n return products.map(product => {\n const imageUrl = product.product_card?.image?.url;\n if (imageUrl) {\n return { item: product, previewUrl: imageUrl };\n }\n return { item: product };\n });\n}\n\n/**\n * Generate batch previews for formats with format_card manifests\n *\n * Formats with format_card fields will have their cards rendered via the creative agent.\n * Formats without format_card will be returned with no preview.\n *\n * @param formats - Array of formats to preview\n * @param creativeAgentClient - ADCP client configured for creative agent\n * @param options - Preview generation options\n * @returns Array of preview results matching input formats\n *\n * @example\n * ```typescript\n * const creativeAgent = new SingleAgentClient({\n * id: 'creative',\n * name: 'Creative Agent',\n * agent_uri: 'https://creative.adcontextprotocol.org/mcp',\n * protocol: 'mcp'\n * });\n *\n * const previews = await batchPreviewFormats(formats, creativeAgent);\n * previews.forEach(p => {\n * if (p.previewUrl) {\n * console.log(`${(p.item as Format).name}: ${p.previewUrl}`);\n * }\n * });\n * ```\n */\nexport async function batchPreviewFormats(\n formats: Format[],\n creativeAgentClient: SingleAgentClient,\n options: BatchPreviewOptions = {}\n): Promise<PreviewResult[]> {\n const cacheTtl = options.cacheTtl ?? 3600000; // 1 hour default\n const skipCache = options.skipCache ?? false;\n const cacheBackend = options.cacheBackend ?? defaultPreviewCacheBackend;\n\n // Collect all formats that have format_card manifests\n const previewRequests: {\n format: Format;\n formatId: FormatID;\n manifest: any;\n cacheKey: string;\n inputName: string;\n }[] = [];\n\n const results: PreviewResult[] = [];\n\n for (const format of formats) {\n if (format.format_card) {\n const cacheKey = getCacheKey(format.format_card.format_id, format.format_card.manifest);\n\n // Check cache first\n if (!skipCache) {\n let cached: PreviewCacheEntry | null = null;\n try {\n cached = await getCachedPreview(cacheBackend, cacheKey, cacheTtl);\n } catch {\n cached = null;\n }\n if (cached) {\n results.push({\n item: format,\n previewUrl: cached.previewUrl,\n previewId: cached.previewId,\n });\n continue;\n }\n }\n\n previewRequests.push({\n format,\n formatId: format.format_card.format_id,\n manifest: format.format_card.manifest,\n cacheKey,\n inputName: format.name || 'Format Card',\n });\n } else {\n // No format_card, return format with no preview\n results.push({\n item: format,\n });\n }\n }\n\n // If all were cached or none have format_card, return early\n if (previewRequests.length === 0) {\n return results;\n }\n\n // Batch preview using preview_creative with inputs array\n // Group by format_id since preview_creative takes one format_id\n const groupedByFormat = new Map<string, typeof previewRequests>();\n\n previewRequests.forEach(req => {\n const formatKey = `${req.formatId.agent_url}:${req.formatId.id}`;\n if (!groupedByFormat.has(formatKey)) {\n groupedByFormat.set(formatKey, []);\n }\n groupedByFormat.get(formatKey)!.push(req);\n });\n\n // Process each format individually\n // Note: Each format has different manifest data, so we can't truly batch them\n // We process them sequentially but could parallelize in the future\n for (const req of previewRequests) {\n try {\n // Build preview_creative request for this format\n // For format cards, the manifest typically contains the format object as JSON\n const previewRequest: PreviewCreativeRequest = {\n request_type: 'single',\n format_id: req.formatId,\n creative_manifest: {\n format_id: req.formatId,\n assets: req.manifest, // manifest contains the asset map (format, etc)\n },\n };\n\n // Call preview_creative\n const response = await creativeAgentClient.previewCreative(previewRequest);\n\n // Check for data even if validation failed (response.success may be false due to schema warnings)\n // Handle both single request (previews) and batch request (results) response formats\n const responseData = response.data;\n if (responseData && 'previews' in responseData && responseData.previews && responseData.previews.length > 0) {\n const preview = responseData.previews[0]!;\n if (preview.renders && preview.renders.length > 0) {\n const render = preview.renders[0]!;\n const previewUrl =\n render.output_format === 'url' || render.output_format === 'both' ? render.preview_url : undefined;\n const previewId = preview.preview_id;\n\n if (previewUrl) {\n results.push({\n item: req.format,\n previewUrl,\n previewId,\n });\n try {\n await setCachedPreview(cacheBackend, req.cacheKey, previewUrl, previewId, responseData.expires_at);\n } catch {\n // Preview cache is an accelerator; successful previews should still return on cache write failures.\n }\n } else {\n results.push({\n item: req.format,\n error: 'Preview render has no URL',\n });\n }\n } else {\n results.push({\n item: req.format,\n error: 'No renders in preview response',\n });\n }\n } else {\n // Only treat as error if we have no data at all\n results.push({\n item: req.format,\n error: response.error || 'Preview generation failed',\n });\n }\n } catch (error) {\n results.push({\n item: req.format,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n\n return results;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  function usesV2PricingFields(option) {
8
2
  if (!option || typeof option !== "object") return false;
9
3
  return option.rate !== void 0 || option.is_fixed !== void 0 || option.price_guidance?.floor !== void 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/pricing-adapter.ts"],"sourcesContent":["/**\n * Pricing Option Adapter\n *\n * Handles conversion between v2.x and v3 pricing option field names.\n * The library exposes only v3 API (fixed_price, floor_price) to clients,\n * and internally adapts requests for v2.x servers.\n *\n * Field mappings:\n * - v3 fixed_price ↔ v2 rate (for fixed pricing)\n * - v3 floor_price ↔ v2 price_guidance.floor (for auction pricing)\n * - v3 presence of fixed_price ↔ v2 is_fixed: true/false\n */\n\n/**\n * v3 price guidance (percentiles only, floor moved to top level)\n */\nexport interface PriceGuidanceV3 {\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v2 price guidance (includes floor)\n */\nexport interface PriceGuidanceV2 {\n floor?: number;\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v3 pricing option structure\n */\nexport interface PricingOptionV3 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed price - if present, this is fixed pricing */\n fixed_price?: number;\n /** Floor price for auction - mutually exclusive with fixed_price */\n floor_price?: number;\n /** Percentile hints for auction bidding */\n price_guidance?: PriceGuidanceV3;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * v2 pricing option structure\n */\nexport interface PricingOptionV2 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed rate (v2 name for fixed_price) */\n rate?: number;\n /** Boolean discriminator for fixed vs auction */\n is_fixed?: boolean;\n /** Price guidance including floor */\n price_guidance?: PriceGuidanceV2;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Check if a pricing option uses v2 field names\n */\nexport function usesV2PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v2 uses 'rate' or 'is_fixed' or has floor inside price_guidance\n return option.rate !== undefined || option.is_fixed !== undefined || option.price_guidance?.floor !== undefined;\n}\n\n/**\n * Check if a pricing option uses v3 field names\n */\nexport function usesV3PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v3 uses fixed_price or floor_price at top level\n return option.fixed_price !== undefined || option.floor_price !== undefined;\n}\n\n/**\n * Detect if a pricing option is fixed pricing (works with v2 or v3)\n */\nexport function isFixedPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n // v3: presence of fixed_price indicates fixed pricing\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return true;\n }\n // v2: is_fixed boolean\n if ((option as PricingOptionV2).is_fixed !== undefined) {\n return (option as PricingOptionV2).is_fixed!;\n }\n // v2: presence of rate without is_fixed defaults to fixed\n if ((option as PricingOptionV2).rate !== undefined) {\n return true;\n }\n return false;\n}\n\n/**\n * Detect if a pricing option is CPA (cost per acquisition) pricing\n */\nexport function isCPAPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n return option?.pricing_model === 'cpa';\n}\n\n/**\n * Get the price value from a pricing option (works with v2 or v3)\n */\nexport function getPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return (option as PricingOptionV3).fixed_price;\n }\n // Fall back to v2 field\n return (option as PricingOptionV2).rate;\n}\n\n/**\n * Get the floor price from a pricing option (works with v2 or v3)\n */\nexport function getFloorPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).floor_price !== undefined) {\n return (option as PricingOptionV3).floor_price;\n }\n // Fall back to v2 field (inside price_guidance)\n return (option as PricingOptionV2).price_guidance?.floor;\n}\n\n/**\n * Adapt a v3-style pricing option for a v2 server.\n * Converts fixed_price → rate, floor_price → price_guidance.floor\n */\nexport function adaptPricingOptionForV2(option: PricingOptionV3): PricingOptionV2 {\n // Already v2 format or no v3 fields\n if (!usesV3PricingFields(option)) {\n return option as unknown as PricingOptionV2;\n }\n\n const { fixed_price, floor_price, price_guidance, ...rest } = option;\n\n const result: PricingOptionV2 = { ...rest } as PricingOptionV2;\n\n if (fixed_price !== undefined) {\n // Fixed pricing\n result.rate = fixed_price;\n result.is_fixed = true;\n } else {\n // Auction pricing\n result.is_fixed = false;\n\n // Build v2 price_guidance with floor inside\n if (floor_price !== undefined || price_guidance) {\n result.price_guidance = {\n ...(price_guidance || {}),\n };\n if (floor_price !== undefined) {\n result.price_guidance.floor = floor_price;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Normalize a v2-style pricing option to v3.\n * Converts rate → fixed_price, price_guidance.floor → floor_price\n */\nexport function normalizePricingOption(option: PricingOptionV2 | PricingOptionV3): PricingOptionV3 {\n // Already v3 format\n if (usesV3PricingFields(option) && !usesV2PricingFields(option)) {\n return option as PricingOptionV3;\n }\n\n const v2Option = option as PricingOptionV2;\n const { rate, is_fixed, price_guidance, ...rest } = v2Option;\n\n const result: PricingOptionV3 = { ...rest } as PricingOptionV3;\n\n // Convert rate → fixed_price (for fixed pricing)\n if (rate !== undefined && (is_fixed === true || is_fixed === undefined)) {\n result.fixed_price = rate;\n }\n\n // Convert price_guidance.floor → floor_price (for auction pricing)\n if (price_guidance) {\n const { floor, ...percentiles } = price_guidance;\n\n if (floor !== undefined) {\n result.floor_price = floor;\n }\n\n // Keep percentiles in price_guidance if any exist\n if (Object.keys(percentiles).length > 0) {\n result.price_guidance = percentiles;\n }\n }\n\n return result;\n}\n\n/**\n * Adapt all pricing options in a product for v2 server\n */\nexport function adaptProductPricingForV2(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(adaptPricingOptionForV2),\n };\n}\n\n/**\n * Normalize all pricing options in a product to v3\n */\nexport function normalizeProductPricing(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(normalizePricingOption),\n };\n}\n\n/**\n * Adapt a get_products request for a v2 server.\n *\n * Converts v3 fields to their v2 equivalents:\n * - brand (BrandReference) → brand_manifest (base domain URL string)\n * - catalog → promoted_offerings (type='offering') or promoted_offerings.product_selectors (type='product')\n * - channels in filters → v2 channel names\n *\n * Strips v3-only fields v2 agents don't understand:\n * - buying_mode, buyer_campaign_ref, property_list, account_id, pagination (top-level)\n * - filters: required_features, required_axe_integrations, required_geo_targeting,\n * signal_targeting, regions, metros\n */\nexport function adaptGetProductsRequestForV2(request: any): any {\n const adapted: any = { ...request };\n\n // Convert v3 brand (BrandReference) → v2 brand_manifest (bare domain URL).\n // v2 servers resolve brand info from the base domain URL.\n if (adapted.brand?.domain) {\n adapted.brand_manifest = `https://${adapted.brand.domain}`;\n delete adapted.brand;\n }\n\n // Convert v3 catalog → v2 promoted_offerings\n if (adapted.catalog) {\n const catalog = adapted.catalog;\n if (catalog.type === 'product') {\n adapted.promoted_offerings = {\n product_selectors: {\n ...(catalog.gtins?.length && { manifest_gtins: catalog.gtins }),\n ...(catalog.ids?.length && { manifest_skus: catalog.ids }),\n ...(catalog.tags?.length && { manifest_tags: catalog.tags }),\n ...(catalog.category && { manifest_category: catalog.category }),\n ...(catalog.query && { manifest_query: catalog.query }),\n },\n };\n } else if (catalog.type === 'offering') {\n adapted.promoted_offerings = {\n ...(catalog.items?.length && { offerings: catalog.items }),\n };\n }\n delete adapted.catalog;\n }\n\n // Map v3 channel names to v2 equivalents\n if (adapted.filters?.channels) {\n const v2ChannelMap: Record<string, string> = {\n olv: 'video',\n ctv: 'video',\n streaming_audio: 'audio',\n retail_media: 'retail',\n };\n // Deduplicate after mapping (e.g. olv+ctv both become 'video')\n const mapped = adapted.filters.channels.map((ch: string) => v2ChannelMap[ch] ?? ch);\n adapted.filters = {\n ...adapted.filters,\n channels: [...new Set(mapped)],\n };\n }\n\n // Strip v3-only filter fields (format_ids exists in both v2 and v3, keep it)\n if (adapted.filters) {\n const {\n required_features,\n required_axe_integrations,\n required_geo_targeting,\n signal_targeting,\n regions,\n metros,\n ...v2Filters\n } = adapted.filters;\n adapted.filters = v2Filters;\n }\n\n // Strip v3-only top-level fields\n delete adapted.buying_mode;\n delete adapted.buyer_campaign_ref;\n delete adapted.property_list;\n delete adapted.account;\n delete adapted.pagination;\n delete adapted.adcp_major_version;\n\n return adapted;\n}\n\n/**\n * Normalize v2 channel names on a product to v3.\n * v2 used coarser buckets; some map one-to-many (e.g. 'video' → ['olv', 'ctv']).\n */\nexport function normalizeProductChannels(product: any): any {\n if (!product?.channels || !Array.isArray(product.channels)) {\n return product;\n }\n\n const v3ChannelMap: Record<string, string[]> = {\n video: ['olv', 'ctv'],\n audio: ['streaming_audio'],\n native: ['display'],\n retail: ['retail_media'],\n };\n\n const normalized = product.channels.flatMap((ch: string) => v3ChannelMap[ch] ?? [ch]);\n return { ...product, channels: [...new Set(normalized)] };\n}\n\n/**\n * Normalize all products in a get_products response to v3\n */\nexport function normalizeGetProductsResponse(response: any): any {\n // If there's no products field at all, this may be an error response — pass through\n if (!('products' in (response ?? {}))) {\n return response;\n }\n\n // If products exists but isn't an array, the response is malformed\n if (!Array.isArray(response.products)) {\n return {\n errors: [\n {\n code: 'invalid_response',\n message: `Expected products to be an array, got ${typeof response.products}`,\n },\n ],\n };\n }\n\n return {\n ...response,\n products: response.products.map((p: any) => normalizeProductChannels(normalizeProductPricing(p))),\n };\n}\n\n/**\n * Adapt a package request's pricing option selection for v2 server.\n * This handles bid_price which references pricing option floor semantics.\n */\nexport function adaptPackagePricingForV2(pkg: any): any {\n // Package requests don't typically contain pricing_options,\n // but they do contain pricing_option_id which selects one.\n // No transformation needed for bid_price - it's the same in both versions.\n return pkg;\n}\n\n/**\n * Adapt a create_media_buy request for v2 server (pricing fields)\n */\nexport function adaptMediaBuyPricingForV2(request: any): any {\n // Media buy requests select pricing options by ID, not by defining them.\n // No pricing field transformation needed in requests.\n return request;\n}\n\n/**\n * Normalize a media buy response's package pricing to v3\n */\nexport function normalizeMediaBuyPricingResponse(response: any): any {\n // Media buy responses may include products with pricing_options\n if (response?.products && Array.isArray(response.products)) {\n return {\n ...response,\n products: response.products.map(normalizeProductPricing),\n };\n }\n return response;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/pricing-adapter.ts"],"sourcesContent":["/**\n * Pricing Option Adapter\n *\n * Handles conversion between v2.x and v3 pricing option field names.\n * The library exposes only v3 API (fixed_price, floor_price) to clients,\n * and internally adapts requests for v2.x servers.\n *\n * Field mappings:\n * - v3 fixed_price ↔ v2 rate (for fixed pricing)\n * - v3 floor_price ↔ v2 price_guidance.floor (for auction pricing)\n * - v3 presence of fixed_price ↔ v2 is_fixed: true/false\n */\n\n/**\n * v3 price guidance (percentiles only, floor moved to top level)\n */\nexport interface PriceGuidanceV3 {\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v2 price guidance (includes floor)\n */\nexport interface PriceGuidanceV2 {\n floor?: number;\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v3 pricing option structure\n */\nexport interface PricingOptionV3 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed price - if present, this is fixed pricing */\n fixed_price?: number;\n /** Floor price for auction - mutually exclusive with fixed_price */\n floor_price?: number;\n /** Percentile hints for auction bidding */\n price_guidance?: PriceGuidanceV3;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * v2 pricing option structure\n */\nexport interface PricingOptionV2 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed rate (v2 name for fixed_price) */\n rate?: number;\n /** Boolean discriminator for fixed vs auction */\n is_fixed?: boolean;\n /** Price guidance including floor */\n price_guidance?: PriceGuidanceV2;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Check if a pricing option uses v2 field names\n */\nexport function usesV2PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v2 uses 'rate' or 'is_fixed' or has floor inside price_guidance\n return option.rate !== undefined || option.is_fixed !== undefined || option.price_guidance?.floor !== undefined;\n}\n\n/**\n * Check if a pricing option uses v3 field names\n */\nexport function usesV3PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v3 uses fixed_price or floor_price at top level\n return option.fixed_price !== undefined || option.floor_price !== undefined;\n}\n\n/**\n * Detect if a pricing option is fixed pricing (works with v2 or v3)\n */\nexport function isFixedPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n // v3: presence of fixed_price indicates fixed pricing\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return true;\n }\n // v2: is_fixed boolean\n if ((option as PricingOptionV2).is_fixed !== undefined) {\n return (option as PricingOptionV2).is_fixed!;\n }\n // v2: presence of rate without is_fixed defaults to fixed\n if ((option as PricingOptionV2).rate !== undefined) {\n return true;\n }\n return false;\n}\n\n/**\n * Detect if a pricing option is CPA (cost per acquisition) pricing\n */\nexport function isCPAPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n return option?.pricing_model === 'cpa';\n}\n\n/**\n * Get the price value from a pricing option (works with v2 or v3)\n */\nexport function getPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return (option as PricingOptionV3).fixed_price;\n }\n // Fall back to v2 field\n return (option as PricingOptionV2).rate;\n}\n\n/**\n * Get the floor price from a pricing option (works with v2 or v3)\n */\nexport function getFloorPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).floor_price !== undefined) {\n return (option as PricingOptionV3).floor_price;\n }\n // Fall back to v2 field (inside price_guidance)\n return (option as PricingOptionV2).price_guidance?.floor;\n}\n\n/**\n * Adapt a v3-style pricing option for a v2 server.\n * Converts fixed_price → rate, floor_price → price_guidance.floor\n */\nexport function adaptPricingOptionForV2(option: PricingOptionV3): PricingOptionV2 {\n // Already v2 format or no v3 fields\n if (!usesV3PricingFields(option)) {\n return option as unknown as PricingOptionV2;\n }\n\n const { fixed_price, floor_price, price_guidance, ...rest } = option;\n\n const result: PricingOptionV2 = { ...rest } as PricingOptionV2;\n\n if (fixed_price !== undefined) {\n // Fixed pricing\n result.rate = fixed_price;\n result.is_fixed = true;\n } else {\n // Auction pricing\n result.is_fixed = false;\n\n // Build v2 price_guidance with floor inside\n if (floor_price !== undefined || price_guidance) {\n result.price_guidance = {\n ...(price_guidance || {}),\n };\n if (floor_price !== undefined) {\n result.price_guidance.floor = floor_price;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Normalize a v2-style pricing option to v3.\n * Converts rate → fixed_price, price_guidance.floor → floor_price\n */\nexport function normalizePricingOption(option: PricingOptionV2 | PricingOptionV3): PricingOptionV3 {\n // Already v3 format\n if (usesV3PricingFields(option) && !usesV2PricingFields(option)) {\n return option as PricingOptionV3;\n }\n\n const v2Option = option as PricingOptionV2;\n const { rate, is_fixed, price_guidance, ...rest } = v2Option;\n\n const result: PricingOptionV3 = { ...rest } as PricingOptionV3;\n\n // Convert rate → fixed_price (for fixed pricing)\n if (rate !== undefined && (is_fixed === true || is_fixed === undefined)) {\n result.fixed_price = rate;\n }\n\n // Convert price_guidance.floor → floor_price (for auction pricing)\n if (price_guidance) {\n const { floor, ...percentiles } = price_guidance;\n\n if (floor !== undefined) {\n result.floor_price = floor;\n }\n\n // Keep percentiles in price_guidance if any exist\n if (Object.keys(percentiles).length > 0) {\n result.price_guidance = percentiles;\n }\n }\n\n return result;\n}\n\n/**\n * Adapt all pricing options in a product for v2 server\n */\nexport function adaptProductPricingForV2(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(adaptPricingOptionForV2),\n };\n}\n\n/**\n * Normalize all pricing options in a product to v3\n */\nexport function normalizeProductPricing(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(normalizePricingOption),\n };\n}\n\n/**\n * Adapt a get_products request for a v2 server.\n *\n * Converts v3 fields to their v2 equivalents:\n * - brand (BrandReference) → brand_manifest (base domain URL string)\n * - catalog → promoted_offerings (type='offering') or promoted_offerings.product_selectors (type='product')\n * - channels in filters → v2 channel names\n *\n * Strips v3-only fields v2 agents don't understand:\n * - buying_mode, buyer_campaign_ref, property_list, account_id, pagination (top-level)\n * - filters: required_features, required_axe_integrations, required_geo_targeting,\n * signal_targeting, regions, metros\n */\nexport function adaptGetProductsRequestForV2(request: any): any {\n const adapted: any = { ...request };\n\n // Convert v3 brand (BrandReference) → v2 brand_manifest (bare domain URL).\n // v2 servers resolve brand info from the base domain URL.\n if (adapted.brand?.domain) {\n adapted.brand_manifest = `https://${adapted.brand.domain}`;\n delete adapted.brand;\n }\n\n // Convert v3 catalog → v2 promoted_offerings\n if (adapted.catalog) {\n const catalog = adapted.catalog;\n if (catalog.type === 'product') {\n adapted.promoted_offerings = {\n product_selectors: {\n ...(catalog.gtins?.length && { manifest_gtins: catalog.gtins }),\n ...(catalog.ids?.length && { manifest_skus: catalog.ids }),\n ...(catalog.tags?.length && { manifest_tags: catalog.tags }),\n ...(catalog.category && { manifest_category: catalog.category }),\n ...(catalog.query && { manifest_query: catalog.query }),\n },\n };\n } else if (catalog.type === 'offering') {\n adapted.promoted_offerings = {\n ...(catalog.items?.length && { offerings: catalog.items }),\n };\n }\n delete adapted.catalog;\n }\n\n // Map v3 channel names to v2 equivalents\n if (adapted.filters?.channels) {\n const v2ChannelMap: Record<string, string> = {\n olv: 'video',\n ctv: 'video',\n streaming_audio: 'audio',\n retail_media: 'retail',\n };\n // Deduplicate after mapping (e.g. olv+ctv both become 'video')\n const mapped = adapted.filters.channels.map((ch: string) => v2ChannelMap[ch] ?? ch);\n adapted.filters = {\n ...adapted.filters,\n channels: [...new Set(mapped)],\n };\n }\n\n // Strip v3-only filter fields (format_ids exists in both v2 and v3, keep it)\n if (adapted.filters) {\n const {\n required_features,\n required_axe_integrations,\n required_geo_targeting,\n signal_targeting,\n regions,\n metros,\n ...v2Filters\n } = adapted.filters;\n adapted.filters = v2Filters;\n }\n\n // Strip v3-only top-level fields\n delete adapted.buying_mode;\n delete adapted.buyer_campaign_ref;\n delete adapted.property_list;\n delete adapted.account;\n delete adapted.pagination;\n delete adapted.adcp_major_version;\n\n return adapted;\n}\n\n/**\n * Normalize v2 channel names on a product to v3.\n * v2 used coarser buckets; some map one-to-many (e.g. 'video' → ['olv', 'ctv']).\n */\nexport function normalizeProductChannels(product: any): any {\n if (!product?.channels || !Array.isArray(product.channels)) {\n return product;\n }\n\n const v3ChannelMap: Record<string, string[]> = {\n video: ['olv', 'ctv'],\n audio: ['streaming_audio'],\n native: ['display'],\n retail: ['retail_media'],\n };\n\n const normalized = product.channels.flatMap((ch: string) => v3ChannelMap[ch] ?? [ch]);\n return { ...product, channels: [...new Set(normalized)] };\n}\n\n/**\n * Normalize all products in a get_products response to v3\n */\nexport function normalizeGetProductsResponse(response: any): any {\n // If there's no products field at all, this may be an error response — pass through\n if (!('products' in (response ?? {}))) {\n return response;\n }\n\n // If products exists but isn't an array, the response is malformed\n if (!Array.isArray(response.products)) {\n return {\n errors: [\n {\n code: 'invalid_response',\n message: `Expected products to be an array, got ${typeof response.products}`,\n },\n ],\n };\n }\n\n return {\n ...response,\n products: response.products.map((p: any) => normalizeProductChannels(normalizeProductPricing(p))),\n };\n}\n\n/**\n * Adapt a package request's pricing option selection for v2 server.\n * This handles bid_price which references pricing option floor semantics.\n */\nexport function adaptPackagePricingForV2(pkg: any): any {\n // Package requests don't typically contain pricing_options,\n // but they do contain pricing_option_id which selects one.\n // No transformation needed for bid_price - it's the same in both versions.\n return pkg;\n}\n\n/**\n * Adapt a create_media_buy request for v2 server (pricing fields)\n */\nexport function adaptMediaBuyPricingForV2(request: any): any {\n // Media buy requests select pricing options by ID, not by defining them.\n // No pricing field transformation needed in requests.\n return request;\n}\n\n/**\n * Normalize a media buy response's package pricing to v3\n */\nexport function normalizeMediaBuyPricingResponse(response: any): any {\n // Media buy responses may include products with pricing_options\n if (response?.products && Array.isArray(response.products)) {\n return {\n ...response,\n products: response.products.map(normalizeProductPricing),\n };\n }\n return response;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { BlockList, isIP } from "node:net";
8
2
  import { isAlwaysBlocked, isPrivateIp } from "../net/address-guards.mjs";
9
3
  const loopbackBlock = new BlockList();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/probe-policy.ts"],"sourcesContent":["/**\n * Probe policy for buyer-side discovery (adcp-client#1618).\n *\n * Whether the SDK is willing to issue an outbound probe to a given URL\n * during agent discovery (`detectProtocol` well-known card fetches,\n * `createTestClient` agent URL acceptance). Sits one layer above the\n * `src/lib/net/address-guards.ts` IP classifiers and the `ssrfSafeFetch`\n * primitive — those operate on already-resolved addresses; this layer\n * applies a higher-level allow/deny decision keyed on the URL hostname\n * before anything reaches DNS.\n *\n * ## Default policy\n *\n * | Range | Default | Why |\n * | ------------------------------------------- | ------- | ------------------------------------------------------- |\n * | Loopback (`127.0.0.0/8`, `::1`, `localhost`)| allow | Local dev loops, mock-server tests, `npm run dev` |\n * | RFC 1918 / link-local / IPv6 ULA | deny | Internal subnets behind a server-side comply runner |\n * | Cloud metadata (`169.254.169.254`, `fe80::/10`) | deny | IMDS exfiltration is never a legitimate buyer use case |\n * | Public IPv4/IPv6 | allow | The whole point |\n *\n * ## Single opt-out\n *\n * `ADCP_ALLOW_INTERNAL_PROBES=1` (read once at module load) widens the\n * default to allow RFC-1918/link-local/ULA. IMDS stays blocked even with\n * this flag — cloud metadata reach is never legitimate.\n *\n * NOT controlled by `NODE_ENV`: a multi-tenant staging image with\n * `NODE_ENV=test` MUST NOT inherit looser SSRF posture than production.\n *\n * ## Known gap (TOCTOU) — adcp-client#1627\n *\n * `classifyProbeUrl` does NOT do DNS resolution — it inspects the\n * URL's hostname literal. A hostname like `evil.example.com` that\n * resolves to `169.254.169.254` will pass this gate; the per-IP block\n * inside `ssrfSafeFetch` (which DOES resolve and pin) catches it.\n * Use both: this gate refuses obvious literal attacks; `ssrfSafeFetch`\n * refuses DNS-based attacks. Routing `detectProtocol` through\n * `ssrfSafeFetch` for full TOCTOU defense is tracked under #1627.\n */\n\nimport { BlockList, isIP } from 'node:net';\nimport { isAlwaysBlocked, isPrivateIp } from '../net/address-guards';\n\n// Loopback canonicalization. Node's URL parser canonicalizes IPv4-mapped\n// IPv6 (`::ffff:127.0.0.1`) into binary form (`::ffff:7f00:1`), which\n// would slip past a textual regex. `BlockList` handles all canonical forms\n// natively, including IPv4-mapped IPv6 against the v4 subnet.\nconst loopbackBlock = new BlockList();\nloopbackBlock.addSubnet('127.0.0.0', 8, 'ipv4');\nloopbackBlock.addAddress('::1', 'ipv6');\n\n/**\n * Operator opt-in to allow RFC-1918 / link-local / ULA destinations.\n * Read once at module load — runtime mutation does not propagate. Operators\n * who flip this in CI should set it via the workflow `env:` block.\n *\n * IMDS stays refused regardless.\n */\nconst ALLOW_INTERNAL = process.env.ADCP_ALLOW_INTERNAL_PROBES === '1';\n\n/**\n * Match a host literal that resolves trivially to loopback. Allowed even\n * in strict mode because local dev loops are not an SSRF target — the\n * attacker would have to be on the buyer's own machine to reach them, at\n * which point they have strictly more powerful primitives.\n *\n * `localhost` is hardcoded rather than DNS-resolved so an attacker can't\n * point `localhost.attacker.example.com` at `169.254.169.254` and slip\n * past as \"loopback-named\". Hostname must be exactly `localhost` (case\n * insensitive). IP literals must be in 127/8 or `::1`.\n */\nfunction isLoopbackHost(host: string): boolean {\n if (host.toLowerCase() === 'localhost') return true;\n // Strip URL-style brackets in case the caller didn't (defensive — internal\n // callers strip first).\n let bare = host;\n if (bare.startsWith('[') && bare.endsWith(']')) bare = bare.slice(1, -1);\n const family = isIP(bare);\n if (family === 4) return loopbackBlock.check(bare, 'ipv4');\n if (family === 6) return loopbackBlock.check(bare, 'ipv6');\n return false;\n}\n\nexport type ProbePolicyResult =\n | { allowed: true }\n | { allowed: false; code: 'invalid_url' | 'always_blocked' | 'private_address'; reason: string };\n\n/**\n * Decide whether the SDK should issue a discovery probe to `url`. Returns\n * `{ allowed: true }` when the probe may proceed, otherwise a refusal\n * with a human-readable reason and a typed code for callers that want\n * to map the refusal into their own error envelope.\n *\n * Designed to be cheap and synchronous — call this BEFORE any try/catch\n * in the discovery loop so refusal can't be silently swallowed and\n * converted into \"host doesn't speak A2A, fall back to MCP\" (the\n * code-reviewer-flagged catch-swallow class from #1618 triage).\n *\n * **Error messages do NOT echo resolved IP addresses** — the `address`\n * field on the rejection carries them when present, but the user-visible\n * text names only the hostname so that compliance reports and log\n * aggregators don't leak internal network topology.\n */\nexport function classifyProbeUrl(url: string): ProbePolicyResult {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n // Don't refuse here — let the underlying call surface its own error\n // (it'll fail with a clearer \"Invalid URL\" downstream). This function\n // is not the URL validator, only the SSRF policy.\n return { allowed: true };\n }\n\n // `URL.hostname` returns IPv6 literals wrapped in brackets; the address\n // classifiers want the bare form.\n const host = parsed.hostname.replace(/^\\[|\\]$/g, '');\n\n // IMDS / IPv6 link-local: ALWAYS refused. Cloud metadata reach is never\n // a legitimate buyer-side use case — refuse even when the operator has\n // explicitly opted into private probes.\n if (isAlwaysBlocked(host)) {\n return {\n allowed: false,\n code: 'always_blocked',\n reason: `Refusing to probe '${host}': cloud-metadata or link-local address.`,\n };\n }\n\n // Loopback: ALWAYS allowed. CLI dev loops, mock-server tests, local\n // adapter integration tests all hit this path. Even in strict mode the\n // attacker would need to be on-host already to exploit it.\n if (isLoopbackHost(host)) {\n return { allowed: true };\n }\n\n // Private/RFC-1918/ULA: refused unless the operator opted in via env.\n // The opt-in is read once at module load — see ALLOW_INTERNAL above.\n if (isPrivateIp(host)) {\n if (ALLOW_INTERNAL) {\n return { allowed: true };\n }\n return {\n allowed: false,\n code: 'private_address',\n reason:\n `Refusing to probe '${host}': private/RFC-1918 address. ` +\n `Set ADCP_ALLOW_INTERNAL_PROBES=1 to allow private-network probes (operator-only).`,\n };\n }\n\n return { allowed: true };\n}\n\n/** Test-only accessor for the env flag — exported for unit-test reset semantics. */\nexport function isInternalProbesAllowed(): boolean {\n return ALLOW_INTERNAL;\n}\n"],"mappings":";;;;;;AAwCA,SAAS,WAAW,YAAY;AAChC,SAAS,iBAAiB,mBAAmB;AAM7C,MAAM,gBAAgB,IAAI,UAAU;AACpC,cAAc,UAAU,aAAa,GAAG,MAAM;AAC9C,cAAc,WAAW,OAAO,MAAM;AAStC,MAAM,iBAAiB,QAAQ,IAAI,+BAA+B;AAalE,SAAS,eAAe,MAAuB;AAC7C,MAAI,KAAK,YAAY,MAAM,YAAa,QAAO;AAG/C,MAAI,OAAO;AACX,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AACvE,QAAM,SAAS,KAAK,IAAI;AACxB,MAAI,WAAW,EAAG,QAAO,cAAc,MAAM,MAAM,MAAM;AACzD,MAAI,WAAW,EAAG,QAAO,cAAc,MAAM,MAAM,MAAM;AACzD,SAAO;AACT;AAsBO,SAAS,iBAAiB,KAAgC;AAC/D,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,GAAG;AAAA,EACtB,QAAQ;AAIN,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAIA,QAAM,OAAO,OAAO,SAAS,QAAQ,YAAY,EAAE;AAKnD,MAAI,gBAAgB,IAAI,GAAG;AACzB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ,sBAAsB,IAAI;AAAA,IACpC;AAAA,EACF;AAKA,MAAI,eAAe,IAAI,GAAG;AACxB,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAIA,MAAI,YAAY,IAAI,GAAG;AACrB,QAAI,gBAAgB;AAClB,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QACE,sBAAsB,IAAI;AAAA,IAE9B;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,KAAK;AACzB;AAGO,SAAS,0BAAmC;AACjD,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/probe-policy.ts"],"sourcesContent":["/**\n * Probe policy for buyer-side discovery (adcp-client#1618).\n *\n * Whether the SDK is willing to issue an outbound probe to a given URL\n * during agent discovery (`detectProtocol` well-known card fetches,\n * `createTestClient` agent URL acceptance). Sits one layer above the\n * `src/lib/net/address-guards.ts` IP classifiers and the `ssrfSafeFetch`\n * primitive — those operate on already-resolved addresses; this layer\n * applies a higher-level allow/deny decision keyed on the URL hostname\n * before anything reaches DNS.\n *\n * ## Default policy\n *\n * | Range | Default | Why |\n * | ------------------------------------------- | ------- | ------------------------------------------------------- |\n * | Loopback (`127.0.0.0/8`, `::1`, `localhost`)| allow | Local dev loops, mock-server tests, `npm run dev` |\n * | RFC 1918 / link-local / IPv6 ULA | deny | Internal subnets behind a server-side comply runner |\n * | Cloud metadata (`169.254.169.254`, `fe80::/10`) | deny | IMDS exfiltration is never a legitimate buyer use case |\n * | Public IPv4/IPv6 | allow | The whole point |\n *\n * ## Single opt-out\n *\n * `ADCP_ALLOW_INTERNAL_PROBES=1` (read once at module load) widens the\n * default to allow RFC-1918/link-local/ULA. IMDS stays blocked even with\n * this flag — cloud metadata reach is never legitimate.\n *\n * NOT controlled by `NODE_ENV`: a multi-tenant staging image with\n * `NODE_ENV=test` MUST NOT inherit looser SSRF posture than production.\n *\n * ## Known gap (TOCTOU) — adcp-client#1627\n *\n * `classifyProbeUrl` does NOT do DNS resolution — it inspects the\n * URL's hostname literal. A hostname like `evil.example.com` that\n * resolves to `169.254.169.254` will pass this gate; the per-IP block\n * inside `ssrfSafeFetch` (which DOES resolve and pin) catches it.\n * Use both: this gate refuses obvious literal attacks; `ssrfSafeFetch`\n * refuses DNS-based attacks. Routing `detectProtocol` through\n * `ssrfSafeFetch` for full TOCTOU defense is tracked under #1627.\n */\n\nimport { BlockList, isIP } from 'node:net';\nimport { isAlwaysBlocked, isPrivateIp } from '../net/address-guards';\n\n// Loopback canonicalization. Node's URL parser canonicalizes IPv4-mapped\n// IPv6 (`::ffff:127.0.0.1`) into binary form (`::ffff:7f00:1`), which\n// would slip past a textual regex. `BlockList` handles all canonical forms\n// natively, including IPv4-mapped IPv6 against the v4 subnet.\nconst loopbackBlock = new BlockList();\nloopbackBlock.addSubnet('127.0.0.0', 8, 'ipv4');\nloopbackBlock.addAddress('::1', 'ipv6');\n\n/**\n * Operator opt-in to allow RFC-1918 / link-local / ULA destinations.\n * Read once at module load — runtime mutation does not propagate. Operators\n * who flip this in CI should set it via the workflow `env:` block.\n *\n * IMDS stays refused regardless.\n */\nconst ALLOW_INTERNAL = process.env.ADCP_ALLOW_INTERNAL_PROBES === '1';\n\n/**\n * Match a host literal that resolves trivially to loopback. Allowed even\n * in strict mode because local dev loops are not an SSRF target — the\n * attacker would have to be on the buyer's own machine to reach them, at\n * which point they have strictly more powerful primitives.\n *\n * `localhost` is hardcoded rather than DNS-resolved so an attacker can't\n * point `localhost.attacker.example.com` at `169.254.169.254` and slip\n * past as \"loopback-named\". Hostname must be exactly `localhost` (case\n * insensitive). IP literals must be in 127/8 or `::1`.\n */\nfunction isLoopbackHost(host: string): boolean {\n if (host.toLowerCase() === 'localhost') return true;\n // Strip URL-style brackets in case the caller didn't (defensive — internal\n // callers strip first).\n let bare = host;\n if (bare.startsWith('[') && bare.endsWith(']')) bare = bare.slice(1, -1);\n const family = isIP(bare);\n if (family === 4) return loopbackBlock.check(bare, 'ipv4');\n if (family === 6) return loopbackBlock.check(bare, 'ipv6');\n return false;\n}\n\nexport type ProbePolicyResult =\n | { allowed: true }\n | { allowed: false; code: 'invalid_url' | 'always_blocked' | 'private_address'; reason: string };\n\n/**\n * Decide whether the SDK should issue a discovery probe to `url`. Returns\n * `{ allowed: true }` when the probe may proceed, otherwise a refusal\n * with a human-readable reason and a typed code for callers that want\n * to map the refusal into their own error envelope.\n *\n * Designed to be cheap and synchronous — call this BEFORE any try/catch\n * in the discovery loop so refusal can't be silently swallowed and\n * converted into \"host doesn't speak A2A, fall back to MCP\" (the\n * code-reviewer-flagged catch-swallow class from #1618 triage).\n *\n * **Error messages do NOT echo resolved IP addresses** — the `address`\n * field on the rejection carries them when present, but the user-visible\n * text names only the hostname so that compliance reports and log\n * aggregators don't leak internal network topology.\n */\nexport function classifyProbeUrl(url: string): ProbePolicyResult {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n // Don't refuse here — let the underlying call surface its own error\n // (it'll fail with a clearer \"Invalid URL\" downstream). This function\n // is not the URL validator, only the SSRF policy.\n return { allowed: true };\n }\n\n // `URL.hostname` returns IPv6 literals wrapped in brackets; the address\n // classifiers want the bare form.\n const host = parsed.hostname.replace(/^\\[|\\]$/g, '');\n\n // IMDS / IPv6 link-local: ALWAYS refused. Cloud metadata reach is never\n // a legitimate buyer-side use case — refuse even when the operator has\n // explicitly opted into private probes.\n if (isAlwaysBlocked(host)) {\n return {\n allowed: false,\n code: 'always_blocked',\n reason: `Refusing to probe '${host}': cloud-metadata or link-local address.`,\n };\n }\n\n // Loopback: ALWAYS allowed. CLI dev loops, mock-server tests, local\n // adapter integration tests all hit this path. Even in strict mode the\n // attacker would need to be on-host already to exploit it.\n if (isLoopbackHost(host)) {\n return { allowed: true };\n }\n\n // Private/RFC-1918/ULA: refused unless the operator opted in via env.\n // The opt-in is read once at module load — see ALLOW_INTERNAL above.\n if (isPrivateIp(host)) {\n if (ALLOW_INTERNAL) {\n return { allowed: true };\n }\n return {\n allowed: false,\n code: 'private_address',\n reason:\n `Refusing to probe '${host}': private/RFC-1918 address. ` +\n `Set ADCP_ALLOW_INTERNAL_PROBES=1 to allow private-network probes (operator-only).`,\n };\n }\n\n return { allowed: true };\n}\n\n/** Test-only accessor for the env flag — exported for unit-test reset semantics. */\nexport function isInternalProbesAllowed(): boolean {\n return ALLOW_INTERNAL;\n}\n"],"mappings":"AAwCA,SAAS,WAAW,YAAY;AAChC,SAAS,iBAAiB,mBAAmB;AAM7C,MAAM,gBAAgB,IAAI,UAAU;AACpC,cAAc,UAAU,aAAa,GAAG,MAAM;AAC9C,cAAc,WAAW,OAAO,MAAM;AAStC,MAAM,iBAAiB,QAAQ,IAAI,+BAA+B;AAalE,SAAS,eAAe,MAAuB;AAC7C,MAAI,KAAK,YAAY,MAAM,YAAa,QAAO;AAG/C,MAAI,OAAO;AACX,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AACvE,QAAM,SAAS,KAAK,IAAI;AACxB,MAAI,WAAW,EAAG,QAAO,cAAc,MAAM,MAAM,MAAM;AACzD,MAAI,WAAW,EAAG,QAAO,cAAc,MAAM,MAAM,MAAM;AACzD,SAAO;AACT;AAsBO,SAAS,iBAAiB,KAAgC;AAC/D,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,GAAG;AAAA,EACtB,QAAQ;AAIN,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAIA,QAAM,OAAO,OAAO,SAAS,QAAQ,YAAY,EAAE;AAKnD,MAAI,gBAAgB,IAAI,GAAG;AACzB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QAAQ,sBAAsB,IAAI;AAAA,IACpC;AAAA,EACF;AAKA,MAAI,eAAe,IAAI,GAAG;AACxB,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAIA,MAAI,YAAY,IAAI,GAAG;AACrB,QAAI,gBAAgB;AAClB,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,MACN,QACE,sBAAsB,IAAI;AAAA,IAE9B;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,KAAK;AACzB;AAGO,SAAS,0BAAmC;AACjD,SAAO;AACT;","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { A2A_CARD_PATHS } from "./a2a-discovery.mjs";
8
2
  import { classifyProbeUrl, isInternalProbesAllowed } from "./probe-policy.mjs";
9
3
  import { SsrfRefusedError, ssrfSafeFetch, SSRF_TRANSIENT_CODES } from "../net/ssrf-fetch.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/protocol-detection.ts"],"sourcesContent":["/**\n * Protocol Detection Utilities\n *\n * Auto-detects whether an agent endpoint uses MCP or A2A protocol\n */\n\nimport { A2A_CARD_PATHS } from './a2a-discovery';\nimport { classifyProbeUrl, isInternalProbesAllowed } from './probe-policy';\nimport { SsrfRefusedError, ssrfSafeFetch, SSRF_TRANSIENT_CODES } from '../net/ssrf-fetch';\n\n/**\n * Detect protocol for a given agent URL\n *\n * Uses a hybrid approach:\n * 1. Check URL patterns (fast heuristic)\n * 2. Try A2A discovery endpoints (authoritative)\n * 3. Default to MCP if A2A discovery fails\n *\n * @param url Agent URL to check\n * @returns Promise resolving to 'a2a' or 'mcp'\n */\nexport async function detectProtocol(url: string): Promise<'a2a' | 'mcp'> {\n return detectA2AOrMcp(url, 5000);\n}\n\n/**\n * Detect protocol with custom timeout\n *\n * @param url Agent URL to check\n * @param timeoutMs Timeout in milliseconds (default: 5000)\n * @returns Promise resolving to 'a2a' or 'mcp'\n */\nexport async function detectProtocolWithTimeout(url: string, timeoutMs: number = 5000): Promise<'a2a' | 'mcp'> {\n return detectA2AOrMcp(url, timeoutMs);\n}\n\nasync function detectA2AOrMcp(url: string, timeoutMs: number): Promise<'a2a' | 'mcp'> {\n if (url.endsWith('/mcp/') || url.endsWith('/mcp')) {\n return 'mcp';\n }\n\n // adcp-client#1618: SSRF policy gate. MUST run BEFORE the try/catch loop\n // below — placing this inside the loop would let `catch { suspect = true }`\n // silently convert a denied URL into `'a2a'`, defeating the whole point of\n // the policy. The hostname-literal check catches obvious attacks\n // (`http://169.254.169.254/`, `http://10.0.0.1/`); per-IP DNS-aware\n // protection lives one layer down (in callers that route through\n // `ssrfSafeFetch`).\n const policy = classifyProbeUrl(url);\n if (!policy.allowed) {\n // `classifyProbeUrl` already returned `{ allowed: true }` for any URL\n // that fails `new URL(...)`, so reaching the !allowed branch implies the\n // URL parses cleanly. Reparse here only to extract the bare hostname for\n // the `SsrfRefusedError` meta (the policy returned the human-readable\n // refusal reason but not the structured hostname).\n const hostname = new URL(url).hostname.replace(/^\\[|\\]$/g, '');\n throw new SsrfRefusedError(\n policy.code === 'always_blocked' ? 'always_blocked_address' : 'private_address',\n policy.reason,\n { url, hostname }\n );\n }\n\n // adcp-client#1612: classify each well-known card probe into one of three\n // signals so we can distinguish \"this is A2A but momentarily 503\" from\n // \"this is not A2A\":\n // - `confirm` : 200/3xx — A2A confirmed\n // - `suspect` : 5xx or transport error — host knows the path but can't\n // serve it right now; still strong evidence of A2A. Falling\n // back to MCP here is what produced the original #1612\n // symptom (425s of MCP retries against an A2A root).\n // - `negative` : 4xx (other than 401/403/429) — host doesn't recognize\n // the well-known path; MCP is the better default.\n // 401/403/429 are auth/rate signals on the well-known path itself, which\n // also indicate \"host knows the path\" → suspect.\n //\n // adcp-client#1627: route through `ssrfSafeFetch` to close the TOCTOU\n // rebind window left open in the #1618 hostname-literal gate. The\n // wrapper resolves DNS once, validates the full address set against\n // `address-guards`, and pins the connect to the first validated address\n // via undici's `Agent.connect.lookup`. A hostname like\n // `evil.example.com` that resolves to `169.254.169.254` rejects with\n // `SsrfRefusedError(always_blocked_address)` BEFORE the request hits\n // the wire. Counterparty-controlled `Location` headers are not followed\n // (`redirect: 'manual'` inside the wrapper) so a 302 to an SSRF target\n // can't bounce us either. The literal-hostname `classifyProbeUrl`\n // gate above remains as cheap synchronous defense in depth.\n const allowPrivateIp = isInternalProbesAllowed();\n\n let suspect = false;\n for (const path of A2A_CARD_PATHS) {\n const discoveryUrl = new URL(path, url).toString();\n try {\n const result = await ssrfSafeFetch(discoveryUrl, {\n method: 'GET',\n timeoutMs,\n allowPrivateIp,\n headers: { Accept: 'application/json, */*' },\n // The agent card is small (kB-scale) — cap tightly so a malicious\n // host can't pin our event loop on a slow body read.\n maxBodyBytes: 4 * 1024,\n });\n\n if (result.status >= 200 && result.status < 300) {\n return 'a2a';\n }\n // 5xx or auth-on-the-path: treat as A2A suspicion (host has this route\n // but couldn't return the card right now). Don't return immediately —\n // a later path might confirm with a 200.\n if (result.status >= 500 || result.status === 401 || result.status === 403 || result.status === 429) {\n suspect = true;\n }\n // 4xx (other than the above): negative evidence, leave suspect alone.\n } catch (err) {\n // Distinguish policy refusals (must propagate — caller is reaching\n // for SSRF targets) from runtime/network conditions (treat as\n // suspect — host is unreachable or non-conformant in a way that's\n // consistent with a slow / large A2A seller). The shared\n // `SSRF_TRANSIENT_CODES` set encodes which codes fall through —\n // see its JSDoc for the rationale on each. Silently downgrading a\n // policy refusal would reintroduce the catch-swallow class flagged\n // in #1618 review.\n if (err instanceof SsrfRefusedError) {\n if (SSRF_TRANSIENT_CODES.has(err.code)) {\n suspect = true;\n continue;\n }\n throw err;\n }\n // Other errors (timeout, remote reset, etc.) → suspect.\n suspect = true;\n }\n }\n\n return suspect ? 'a2a' : 'mcp';\n}\n"],"mappings":";;;;;;AAMA,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB,+BAA+B;AAC1D,SAAS,kBAAkB,eAAe,4BAA4B;AAatE,eAAsB,eAAe,KAAqC;AACxE,SAAO,eAAe,KAAK,GAAI;AACjC;AASA,eAAsB,0BAA0B,KAAa,YAAoB,KAA8B;AAC7G,SAAO,eAAe,KAAK,SAAS;AACtC;AAEA,eAAe,eAAe,KAAa,WAA2C;AACpF,MAAI,IAAI,SAAS,OAAO,KAAK,IAAI,SAAS,MAAM,GAAG;AACjD,WAAO;AAAA,EACT;AASA,QAAM,SAAS,iBAAiB,GAAG;AACnC,MAAI,CAAC,OAAO,SAAS;AAMnB,UAAM,WAAW,IAAI,IAAI,GAAG,EAAE,SAAS,QAAQ,YAAY,EAAE;AAC7D,UAAM,IAAI;AAAA,MACR,OAAO,SAAS,mBAAmB,2BAA2B;AAAA,MAC9D,OAAO;AAAA,MACP,EAAE,KAAK,SAAS;AAAA,IAClB;AAAA,EACF;AA0BA,QAAM,iBAAiB,wBAAwB;AAE/C,MAAI,UAAU;AACd,aAAW,QAAQ,gBAAgB;AACjC,UAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,SAAS;AACjD,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,cAAc;AAAA,QAC/C,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,SAAS,EAAE,QAAQ,wBAAwB;AAAA;AAAA;AAAA,QAG3C,cAAc,IAAI;AAAA,MACpB,CAAC;AAED,UAAI,OAAO,UAAU,OAAO,OAAO,SAAS,KAAK;AAC/C,eAAO;AAAA,MACT;AAIA,UAAI,OAAO,UAAU,OAAO,OAAO,WAAW,OAAO,OAAO,WAAW,OAAO,OAAO,WAAW,KAAK;AACnG,kBAAU;AAAA,MACZ;AAAA,IAEF,SAAS,KAAK;AASZ,UAAI,eAAe,kBAAkB;AACnC,YAAI,qBAAqB,IAAI,IAAI,IAAI,GAAG;AACtC,oBAAU;AACV;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAEA,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,UAAU,QAAQ;AAC3B;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/protocol-detection.ts"],"sourcesContent":["/**\n * Protocol Detection Utilities\n *\n * Auto-detects whether an agent endpoint uses MCP or A2A protocol\n */\n\nimport { A2A_CARD_PATHS } from './a2a-discovery';\nimport { classifyProbeUrl, isInternalProbesAllowed } from './probe-policy';\nimport { SsrfRefusedError, ssrfSafeFetch, SSRF_TRANSIENT_CODES } from '../net/ssrf-fetch';\n\n/**\n * Detect protocol for a given agent URL\n *\n * Uses a hybrid approach:\n * 1. Check URL patterns (fast heuristic)\n * 2. Try A2A discovery endpoints (authoritative)\n * 3. Default to MCP if A2A discovery fails\n *\n * @param url Agent URL to check\n * @returns Promise resolving to 'a2a' or 'mcp'\n */\nexport async function detectProtocol(url: string): Promise<'a2a' | 'mcp'> {\n return detectA2AOrMcp(url, 5000);\n}\n\n/**\n * Detect protocol with custom timeout\n *\n * @param url Agent URL to check\n * @param timeoutMs Timeout in milliseconds (default: 5000)\n * @returns Promise resolving to 'a2a' or 'mcp'\n */\nexport async function detectProtocolWithTimeout(url: string, timeoutMs: number = 5000): Promise<'a2a' | 'mcp'> {\n return detectA2AOrMcp(url, timeoutMs);\n}\n\nasync function detectA2AOrMcp(url: string, timeoutMs: number): Promise<'a2a' | 'mcp'> {\n if (url.endsWith('/mcp/') || url.endsWith('/mcp')) {\n return 'mcp';\n }\n\n // adcp-client#1618: SSRF policy gate. MUST run BEFORE the try/catch loop\n // below — placing this inside the loop would let `catch { suspect = true }`\n // silently convert a denied URL into `'a2a'`, defeating the whole point of\n // the policy. The hostname-literal check catches obvious attacks\n // (`http://169.254.169.254/`, `http://10.0.0.1/`); per-IP DNS-aware\n // protection lives one layer down (in callers that route through\n // `ssrfSafeFetch`).\n const policy = classifyProbeUrl(url);\n if (!policy.allowed) {\n // `classifyProbeUrl` already returned `{ allowed: true }` for any URL\n // that fails `new URL(...)`, so reaching the !allowed branch implies the\n // URL parses cleanly. Reparse here only to extract the bare hostname for\n // the `SsrfRefusedError` meta (the policy returned the human-readable\n // refusal reason but not the structured hostname).\n const hostname = new URL(url).hostname.replace(/^\\[|\\]$/g, '');\n throw new SsrfRefusedError(\n policy.code === 'always_blocked' ? 'always_blocked_address' : 'private_address',\n policy.reason,\n { url, hostname }\n );\n }\n\n // adcp-client#1612: classify each well-known card probe into one of three\n // signals so we can distinguish \"this is A2A but momentarily 503\" from\n // \"this is not A2A\":\n // - `confirm` : 200/3xx — A2A confirmed\n // - `suspect` : 5xx or transport error — host knows the path but can't\n // serve it right now; still strong evidence of A2A. Falling\n // back to MCP here is what produced the original #1612\n // symptom (425s of MCP retries against an A2A root).\n // - `negative` : 4xx (other than 401/403/429) — host doesn't recognize\n // the well-known path; MCP is the better default.\n // 401/403/429 are auth/rate signals on the well-known path itself, which\n // also indicate \"host knows the path\" → suspect.\n //\n // adcp-client#1627: route through `ssrfSafeFetch` to close the TOCTOU\n // rebind window left open in the #1618 hostname-literal gate. The\n // wrapper resolves DNS once, validates the full address set against\n // `address-guards`, and pins the connect to the first validated address\n // via undici's `Agent.connect.lookup`. A hostname like\n // `evil.example.com` that resolves to `169.254.169.254` rejects with\n // `SsrfRefusedError(always_blocked_address)` BEFORE the request hits\n // the wire. Counterparty-controlled `Location` headers are not followed\n // (`redirect: 'manual'` inside the wrapper) so a 302 to an SSRF target\n // can't bounce us either. The literal-hostname `classifyProbeUrl`\n // gate above remains as cheap synchronous defense in depth.\n const allowPrivateIp = isInternalProbesAllowed();\n\n let suspect = false;\n for (const path of A2A_CARD_PATHS) {\n const discoveryUrl = new URL(path, url).toString();\n try {\n const result = await ssrfSafeFetch(discoveryUrl, {\n method: 'GET',\n timeoutMs,\n allowPrivateIp,\n headers: { Accept: 'application/json, */*' },\n // The agent card is small (kB-scale) — cap tightly so a malicious\n // host can't pin our event loop on a slow body read.\n maxBodyBytes: 4 * 1024,\n });\n\n if (result.status >= 200 && result.status < 300) {\n return 'a2a';\n }\n // 5xx or auth-on-the-path: treat as A2A suspicion (host has this route\n // but couldn't return the card right now). Don't return immediately —\n // a later path might confirm with a 200.\n if (result.status >= 500 || result.status === 401 || result.status === 403 || result.status === 429) {\n suspect = true;\n }\n // 4xx (other than the above): negative evidence, leave suspect alone.\n } catch (err) {\n // Distinguish policy refusals (must propagate — caller is reaching\n // for SSRF targets) from runtime/network conditions (treat as\n // suspect — host is unreachable or non-conformant in a way that's\n // consistent with a slow / large A2A seller). The shared\n // `SSRF_TRANSIENT_CODES` set encodes which codes fall through —\n // see its JSDoc for the rationale on each. Silently downgrading a\n // policy refusal would reintroduce the catch-swallow class flagged\n // in #1618 review.\n if (err instanceof SsrfRefusedError) {\n if (SSRF_TRANSIENT_CODES.has(err.code)) {\n suspect = true;\n continue;\n }\n throw err;\n }\n // Other errors (timeout, remote reset, etc.) → suspect.\n suspect = true;\n }\n }\n\n return suspect ? 'a2a' : 'mcp';\n}\n"],"mappings":"AAMA,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB,+BAA+B;AAC1D,SAAS,kBAAkB,eAAe,4BAA4B;AAatE,eAAsB,eAAe,KAAqC;AACxE,SAAO,eAAe,KAAK,GAAI;AACjC;AASA,eAAsB,0BAA0B,KAAa,YAAoB,KAA8B;AAC7G,SAAO,eAAe,KAAK,SAAS;AACtC;AAEA,eAAe,eAAe,KAAa,WAA2C;AACpF,MAAI,IAAI,SAAS,OAAO,KAAK,IAAI,SAAS,MAAM,GAAG;AACjD,WAAO;AAAA,EACT;AASA,QAAM,SAAS,iBAAiB,GAAG;AACnC,MAAI,CAAC,OAAO,SAAS;AAMnB,UAAM,WAAW,IAAI,IAAI,GAAG,EAAE,SAAS,QAAQ,YAAY,EAAE;AAC7D,UAAM,IAAI;AAAA,MACR,OAAO,SAAS,mBAAmB,2BAA2B;AAAA,MAC9D,OAAO;AAAA,MACP,EAAE,KAAK,SAAS;AAAA,IAClB;AAAA,EACF;AA0BA,QAAM,iBAAiB,wBAAwB;AAE/C,MAAI,UAAU;AACd,aAAW,QAAQ,gBAAgB;AACjC,UAAM,eAAe,IAAI,IAAI,MAAM,GAAG,EAAE,SAAS;AACjD,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,cAAc;AAAA,QAC/C,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,SAAS,EAAE,QAAQ,wBAAwB;AAAA;AAAA;AAAA,QAG3C,cAAc,IAAI;AAAA,MACpB,CAAC;AAED,UAAI,OAAO,UAAU,OAAO,OAAO,SAAS,KAAK;AAC/C,eAAO;AAAA,MACT;AAIA,UAAI,OAAO,UAAU,OAAO,OAAO,WAAW,OAAO,OAAO,WAAW,OAAO,OAAO,WAAW,KAAK;AACnG,kBAAU;AAAA,MACZ;AAAA,IAEF,SAAS,KAAK;AASZ,UAAI,eAAe,kBAAkB;AACnC,YAAI,qBAAqB,IAAI,IAAI,IAAI,GAAG;AACtC,oBAAU;AACV;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAEA,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,UAAU,QAAQ;AAC3B;","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { MAX_JSON_DEPTH } from "./json-depth.mjs";
8
2
  const SECRET_KEY_PATTERN = /^(authorization|credentials?|token|api[_-]?key|password|secret|client[_-]secret|refresh[_-]token|access[_-]token|bearer|session[_-]token|session[_-]id|offering[_-]token|cookie|set[_-]cookie)$/i;
9
3
  function normalizeSecretKeyPattern(pattern) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/redact-secrets.ts"],"sourcesContent":["/**\n * Recursive secret-key redaction.\n *\n * The runner-output-contract.yaml security block (`payload_redaction`) and\n * the `comply-test-controller-response.json` `recorded_calls[].payload`\n * description both mandate the same recursive walk: any property whose\n * final-path-segment key matches the canonical pattern below has its scalar\n * value replaced with the literal string `\"[redacted]\"`. The walk is capped\n * at the same depth the upstream-recorder accepts for JSON canonicalization;\n * the recorder rejects deeper structured payloads after redaction so it does\n * not store subtrees beyond this cap.\n *\n * Spec: `static/compliance/source/universal/runner-output-contract.yaml`\n * (`payload_redaction.pattern`). The runner uses this to redact request /\n * response payloads on `validation_result.request` / `.response`. The\n * `@adcp/sdk/upstream-recorder` uses this at *recording* time so plaintext\n * secrets never sit in the recorded-calls buffer in memory, even briefly.\n *\n * Matching is case-insensitive and structural — the pattern matches against\n * the property KEY, not the value. Adopters MAY extend the pattern via the\n * recorder's `redactPattern` option, but MUST NOT narrow it.\n */\n\nimport { MAX_JSON_DEPTH } from './json-depth';\n\n/**\n * Canonical secret-key pattern from the AdCP runner-output contract. Mirrors\n * the spec block: `Authorization`, `Credentials`, tokens, API keys,\n * passwords, secrets, OAuth refresh / access bearers, session tokens,\n * cookies. Case-insensitive.\n */\nexport const SECRET_KEY_PATTERN =\n /^(authorization|credentials?|token|api[_-]?key|password|secret|client[_-]secret|refresh[_-]token|access[_-]token|bearer|session[_-]token|session[_-]id|offering[_-]token|cookie|set[_-]cookie)$/i;\n\nexport function normalizeSecretKeyPattern(pattern: RegExp): RegExp {\n if (!/[gy]/.test(pattern.flags)) return pattern;\n return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ''));\n}\n\nexport function secretKeyPatternMatches(pattern: RegExp, key: string): boolean {\n const lastIndex = pattern.lastIndex;\n pattern.lastIndex = 0;\n const matched = pattern.test(key);\n pattern.lastIndex = lastIndex;\n return matched;\n}\n\n/**\n * Maximum recursion depth for the redaction walk. Keep this aligned with the\n * upstream-recorder JSON canonicalization depth; recorder paths also run the\n * depth gate after redaction so structured payloads beyond the cap are\n * rejected instead of stored with unvisited subtrees.\n */\n/**\n * Recursively walk `value`, returning a structurally-identical clone with\n * scalar values at secret-shaped keys replaced by `\"[redacted]\"`. Pass an\n * optional `pattern` to override the canonical pattern (typically by\n * extending it — adopters MAY add internal vendor headers but MUST NOT\n * narrow the contract floor).\n *\n * Non-mutating — the input is never touched.\n */\nexport function redactSecrets(\n value: unknown,\n pattern: RegExp = SECRET_KEY_PATTERN,\n depth = 0,\n seen: WeakSet<object> = new WeakSet()\n): unknown {\n const effectivePattern = normalizeSecretKeyPattern(pattern);\n if (depth > MAX_JSON_DEPTH) return value;\n if (Array.isArray(value)) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const out = value.map(v => redactSecrets(v, effectivePattern, depth + 1, seen));\n seen.delete(value);\n return out;\n }\n if (value && typeof value === 'object') {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] =\n secretKeyPatternMatches(effectivePattern, k) && (typeof v === 'string' || typeof v === 'number')\n ? '[redacted]'\n : redactSecrets(v, effectivePattern, depth + 1, seen);\n }\n seen.delete(value);\n return out;\n }\n return value;\n}\n"],"mappings":";;;;;;AAuBA,SAAS,sBAAsB;AAQxB,MAAM,qBACX;AAEK,SAAS,0BAA0B,SAAyB;AACjE,MAAI,CAAC,OAAO,KAAK,QAAQ,KAAK,EAAG,QAAO;AACxC,SAAO,IAAI,OAAO,QAAQ,QAAQ,QAAQ,MAAM,QAAQ,SAAS,EAAE,CAAC;AACtE;AAEO,SAAS,wBAAwB,SAAiB,KAAsB;AAC7E,QAAM,YAAY,QAAQ;AAC1B,UAAQ,YAAY;AACpB,QAAM,UAAU,QAAQ,KAAK,GAAG;AAChC,UAAQ,YAAY;AACpB,SAAO;AACT;AAiBO,SAAS,cACd,OACA,UAAkB,oBAClB,QAAQ,GACR,OAAwB,oBAAI,QAAQ,GAC3B;AACT,QAAM,mBAAmB,0BAA0B,OAAO;AAC1D,MAAI,QAAQ,eAAgB,QAAO;AACnC,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,QAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,SAAK,IAAI,KAAK;AACd,UAAM,MAAM,MAAM,IAAI,OAAK,cAAc,GAAG,kBAAkB,QAAQ,GAAG,IAAI,CAAC;AAC9E,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,QAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,SAAK,IAAI,KAAK;AACd,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrE,UAAI,CAAC,IACH,wBAAwB,kBAAkB,CAAC,MAAM,OAAO,MAAM,YAAY,OAAO,MAAM,YACnF,eACA,cAAc,GAAG,kBAAkB,QAAQ,GAAG,IAAI;AAAA,IAC1D;AACA,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/redact-secrets.ts"],"sourcesContent":["/**\n * Recursive secret-key redaction.\n *\n * The runner-output-contract.yaml security block (`payload_redaction`) and\n * the `comply-test-controller-response.json` `recorded_calls[].payload`\n * description both mandate the same recursive walk: any property whose\n * final-path-segment key matches the canonical pattern below has its scalar\n * value replaced with the literal string `\"[redacted]\"`. The walk is capped\n * at the same depth the upstream-recorder accepts for JSON canonicalization;\n * the recorder rejects deeper structured payloads after redaction so it does\n * not store subtrees beyond this cap.\n *\n * Spec: `static/compliance/source/universal/runner-output-contract.yaml`\n * (`payload_redaction.pattern`). The runner uses this to redact request /\n * response payloads on `validation_result.request` / `.response`. The\n * `@adcp/sdk/upstream-recorder` uses this at *recording* time so plaintext\n * secrets never sit in the recorded-calls buffer in memory, even briefly.\n *\n * Matching is case-insensitive and structural — the pattern matches against\n * the property KEY, not the value. Adopters MAY extend the pattern via the\n * recorder's `redactPattern` option, but MUST NOT narrow it.\n */\n\nimport { MAX_JSON_DEPTH } from './json-depth';\n\n/**\n * Canonical secret-key pattern from the AdCP runner-output contract. Mirrors\n * the spec block: `Authorization`, `Credentials`, tokens, API keys,\n * passwords, secrets, OAuth refresh / access bearers, session tokens,\n * cookies. Case-insensitive.\n */\nexport const SECRET_KEY_PATTERN =\n /^(authorization|credentials?|token|api[_-]?key|password|secret|client[_-]secret|refresh[_-]token|access[_-]token|bearer|session[_-]token|session[_-]id|offering[_-]token|cookie|set[_-]cookie)$/i;\n\nexport function normalizeSecretKeyPattern(pattern: RegExp): RegExp {\n if (!/[gy]/.test(pattern.flags)) return pattern;\n return new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ''));\n}\n\nexport function secretKeyPatternMatches(pattern: RegExp, key: string): boolean {\n const lastIndex = pattern.lastIndex;\n pattern.lastIndex = 0;\n const matched = pattern.test(key);\n pattern.lastIndex = lastIndex;\n return matched;\n}\n\n/**\n * Maximum recursion depth for the redaction walk. Keep this aligned with the\n * upstream-recorder JSON canonicalization depth; recorder paths also run the\n * depth gate after redaction so structured payloads beyond the cap are\n * rejected instead of stored with unvisited subtrees.\n */\n/**\n * Recursively walk `value`, returning a structurally-identical clone with\n * scalar values at secret-shaped keys replaced by `\"[redacted]\"`. Pass an\n * optional `pattern` to override the canonical pattern (typically by\n * extending it — adopters MAY add internal vendor headers but MUST NOT\n * narrow the contract floor).\n *\n * Non-mutating — the input is never touched.\n */\nexport function redactSecrets(\n value: unknown,\n pattern: RegExp = SECRET_KEY_PATTERN,\n depth = 0,\n seen: WeakSet<object> = new WeakSet()\n): unknown {\n const effectivePattern = normalizeSecretKeyPattern(pattern);\n if (depth > MAX_JSON_DEPTH) return value;\n if (Array.isArray(value)) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const out = value.map(v => redactSecrets(v, effectivePattern, depth + 1, seen));\n seen.delete(value);\n return out;\n }\n if (value && typeof value === 'object') {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] =\n secretKeyPatternMatches(effectivePattern, k) && (typeof v === 'string' || typeof v === 'number')\n ? '[redacted]'\n : redactSecrets(v, effectivePattern, depth + 1, seen);\n }\n seen.delete(value);\n return out;\n }\n return value;\n}\n"],"mappings":"AAuBA,SAAS,sBAAsB;AAQxB,MAAM,qBACX;AAEK,SAAS,0BAA0B,SAAyB;AACjE,MAAI,CAAC,OAAO,KAAK,QAAQ,KAAK,EAAG,QAAO;AACxC,SAAO,IAAI,OAAO,QAAQ,QAAQ,QAAQ,MAAM,QAAQ,SAAS,EAAE,CAAC;AACtE;AAEO,SAAS,wBAAwB,SAAiB,KAAsB;AAC7E,QAAM,YAAY,QAAQ;AAC1B,UAAQ,YAAY;AACpB,QAAM,UAAU,QAAQ,KAAK,GAAG;AAChC,UAAQ,YAAY;AACpB,SAAO;AACT;AAiBO,SAAS,cACd,OACA,UAAkB,oBAClB,QAAQ,GACR,OAAwB,oBAAI,QAAQ,GAC3B;AACT,QAAM,mBAAmB,0BAA0B,OAAO;AAC1D,MAAI,QAAQ,eAAgB,QAAO;AACnC,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,QAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,SAAK,IAAI,KAAK;AACd,UAAM,MAAM,MAAM,IAAI,OAAK,cAAc,GAAG,kBAAkB,QAAQ,GAAG,IAAI,CAAC;AAC9E,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,QAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,SAAK,IAAI,KAAK;AACd,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrE,UAAI,CAAC,IACH,wBAAwB,kBAAkB,CAAC,MAAM,OAAO,MAAM,YAAY,OAAO,MAAM,YACnF,eACA,cAAc,GAAG,kBAAkB,QAAQ,GAAG,IAAI;AAAA,IAC1D;AACA,SAAK,OAAO,KAAK;AACjB,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  let hasWarnedAboutDefaultPrefix = false;
8
2
  function detectNodeRedisDbIndex(client) {
9
3
  if (!client || typeof client !== "object") return null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/redis-default-prefix-warn.ts"],"sourcesContent":["/**\n * Shared default-prefix-on-db-0 warning helper for Redis backends.\n *\n * Every Redis-backed SDK store (idempotency, ctx-metadata, replay)\n * prefixes its keys (`\"adcp:idem:\"`, `\"adcp:ctx_meta:\"`, `\"adcp:replay:\"`)\n * so a shared Redis instance can host multiple AdCP servers — or AdCP\n * alongside other apps — without collision. But two AdCP deployments\n * sharing the *same* db with the *same* default prefix collide on any\n * overlapping principal/account/keyid namespace.\n *\n * This helper emits a one-time `console.warn` at backend construction\n * when the default prefix meets a node-redis client we can confidently\n * identify as being on db 0 (the most likely signal of a shared,\n * non-dedicated Redis). Once per process across every backend that uses\n * it — operators standing up multiple Redis backends shouldn't see N\n * identical warnings.\n *\n * Best-effort: stays silent for escape-hatch clients (ioredis, Upstash,\n * test doubles) where we can't introspect the db index. Prefer\n * false-negative over a noisy false-positive warning.\n */\n\nlet hasWarnedAboutDefaultPrefix = false;\n\n/**\n * Detect the Redis db index when the client is a node-redis v4/v5\n * `RedisClientType`. Returns `null` for clients we can't introspect.\n *\n * Reads `client.options.database` (numeric, present when the client was\n * constructed with `createClient({ database: N })`) or parses the path\n * component of `client.options.url`. Escape-hatch clients (no `options`\n * object of the canonical shape) return `null` and skip the warn.\n */\nexport function detectNodeRedisDbIndex(client: unknown): number | null {\n if (!client || typeof client !== 'object') return null;\n const opts = (client as { options?: Record<string, unknown> }).options;\n if (!opts || typeof opts !== 'object') return null;\n if (typeof opts.database === 'number') return opts.database;\n if (typeof opts.url === 'string') {\n try {\n const u = new URL(opts.url);\n if (u.protocol !== 'redis:' && u.protocol !== 'rediss:') return null;\n const path = u.pathname.replace(/^\\//, '');\n if (path === '') return 0;\n const n = Number(path);\n return Number.isInteger(n) && n >= 0 ? n : null;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport interface WarnOnSharedRedisPrefixOptions {\n /** The Redis client passed to the backend constructor. */\n client: unknown;\n /** `options.keyPrefix` as the caller passed it — `undefined` means default. */\n callerKeyPrefix: string | undefined;\n /** The backend's own default prefix (e.g., `\"adcp:idem:\"`). */\n defaultKeyPrefix: string;\n /** Caller-supplied suppression switch. */\n suppress: boolean | undefined;\n /** Backend label for the warning text (e.g., `\"redisBackend\"`, `\"redisCtxMetadataStore\"`). */\n backendName: string;\n}\n\n/**\n * Emit the one-time warn if (a) the caller used the default `keyPrefix`,\n * (b) didn't pass `suppress`, (c) we can confidently see db 0 from the\n * client. Otherwise silent.\n *\n * **Once per process.** All Redis backends share the warn flag — an\n * adopter who configures three Redis-backed stores against the same\n * misconfigured Redis sees one warning total, not three.\n */\nexport function maybeWarnOnSharedRedisPrefix(options: WarnOnSharedRedisPrefixOptions): void {\n if (options.callerKeyPrefix !== undefined) return;\n if (options.suppress) return;\n if (hasWarnedAboutDefaultPrefix) return;\n if (detectNodeRedisDbIndex(options.client) !== 0) return;\n\n hasWarnedAboutDefaultPrefix = true;\n console.warn(\n `${options.backendName}: using the default keyPrefix \"${options.defaultKeyPrefix}\" against Redis db 0. ` +\n `If this Redis db is shared with another AdCP deployment (or other apps), the per-tenant scope ` +\n `segment alone is not enough to prevent cross-deployment collision. Set a deployment-unique ` +\n `keyPrefix (e.g., \"${options.defaultKeyPrefix}prod-eu:\") or use a dedicated Redis db. ` +\n `Pass { suppressDefaultPrefixWarning: true } to silence this once you've confirmed isolation.`\n );\n}\n\n/**\n * Test-only escape hatch to reset the once-warn flag between test runs.\n * Not exported through any public index — adopters can't reach it from\n * outside the SDK.\n */\nexport function __resetDefaultPrefixWarningForTests(): void {\n hasWarnedAboutDefaultPrefix = false;\n}\n"],"mappings":";;;;;;AAsBA,IAAI,8BAA8B;AAW3B,SAAS,uBAAuB,QAAgC;AACrE,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,OAAQ,OAAiD;AAC/D,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,MAAI,OAAO,KAAK,aAAa,SAAU,QAAO,KAAK;AACnD,MAAI,OAAO,KAAK,QAAQ,UAAU;AAChC,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,KAAK,GAAG;AAC1B,UAAI,EAAE,aAAa,YAAY,EAAE,aAAa,UAAW,QAAO;AAChE,YAAM,OAAO,EAAE,SAAS,QAAQ,OAAO,EAAE;AACzC,UAAI,SAAS,GAAI,QAAO;AACxB,YAAM,IAAI,OAAO,IAAI;AACrB,aAAO,OAAO,UAAU,CAAC,KAAK,KAAK,IAAI,IAAI;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAwBO,SAAS,6BAA6B,SAA+C;AAC1F,MAAI,QAAQ,oBAAoB,OAAW;AAC3C,MAAI,QAAQ,SAAU;AACtB,MAAI,4BAA6B;AACjC,MAAI,uBAAuB,QAAQ,MAAM,MAAM,EAAG;AAElD,gCAA8B;AAC9B,UAAQ;AAAA,IACN,GAAG,QAAQ,WAAW,kCAAkC,QAAQ,gBAAgB,oOAGzD,QAAQ,gBAAgB;AAAA,EAEjD;AACF;AAOO,SAAS,sCAA4C;AAC1D,gCAA8B;AAChC;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/redis-default-prefix-warn.ts"],"sourcesContent":["/**\n * Shared default-prefix-on-db-0 warning helper for Redis backends.\n *\n * Every Redis-backed SDK store (idempotency, ctx-metadata, replay)\n * prefixes its keys (`\"adcp:idem:\"`, `\"adcp:ctx_meta:\"`, `\"adcp:replay:\"`)\n * so a shared Redis instance can host multiple AdCP servers — or AdCP\n * alongside other apps — without collision. But two AdCP deployments\n * sharing the *same* db with the *same* default prefix collide on any\n * overlapping principal/account/keyid namespace.\n *\n * This helper emits a one-time `console.warn` at backend construction\n * when the default prefix meets a node-redis client we can confidently\n * identify as being on db 0 (the most likely signal of a shared,\n * non-dedicated Redis). Once per process across every backend that uses\n * it — operators standing up multiple Redis backends shouldn't see N\n * identical warnings.\n *\n * Best-effort: stays silent for escape-hatch clients (ioredis, Upstash,\n * test doubles) where we can't introspect the db index. Prefer\n * false-negative over a noisy false-positive warning.\n */\n\nlet hasWarnedAboutDefaultPrefix = false;\n\n/**\n * Detect the Redis db index when the client is a node-redis v4/v5\n * `RedisClientType`. Returns `null` for clients we can't introspect.\n *\n * Reads `client.options.database` (numeric, present when the client was\n * constructed with `createClient({ database: N })`) or parses the path\n * component of `client.options.url`. Escape-hatch clients (no `options`\n * object of the canonical shape) return `null` and skip the warn.\n */\nexport function detectNodeRedisDbIndex(client: unknown): number | null {\n if (!client || typeof client !== 'object') return null;\n const opts = (client as { options?: Record<string, unknown> }).options;\n if (!opts || typeof opts !== 'object') return null;\n if (typeof opts.database === 'number') return opts.database;\n if (typeof opts.url === 'string') {\n try {\n const u = new URL(opts.url);\n if (u.protocol !== 'redis:' && u.protocol !== 'rediss:') return null;\n const path = u.pathname.replace(/^\\//, '');\n if (path === '') return 0;\n const n = Number(path);\n return Number.isInteger(n) && n >= 0 ? n : null;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport interface WarnOnSharedRedisPrefixOptions {\n /** The Redis client passed to the backend constructor. */\n client: unknown;\n /** `options.keyPrefix` as the caller passed it — `undefined` means default. */\n callerKeyPrefix: string | undefined;\n /** The backend's own default prefix (e.g., `\"adcp:idem:\"`). */\n defaultKeyPrefix: string;\n /** Caller-supplied suppression switch. */\n suppress: boolean | undefined;\n /** Backend label for the warning text (e.g., `\"redisBackend\"`, `\"redisCtxMetadataStore\"`). */\n backendName: string;\n}\n\n/**\n * Emit the one-time warn if (a) the caller used the default `keyPrefix`,\n * (b) didn't pass `suppress`, (c) we can confidently see db 0 from the\n * client. Otherwise silent.\n *\n * **Once per process.** All Redis backends share the warn flag — an\n * adopter who configures three Redis-backed stores against the same\n * misconfigured Redis sees one warning total, not three.\n */\nexport function maybeWarnOnSharedRedisPrefix(options: WarnOnSharedRedisPrefixOptions): void {\n if (options.callerKeyPrefix !== undefined) return;\n if (options.suppress) return;\n if (hasWarnedAboutDefaultPrefix) return;\n if (detectNodeRedisDbIndex(options.client) !== 0) return;\n\n hasWarnedAboutDefaultPrefix = true;\n console.warn(\n `${options.backendName}: using the default keyPrefix \"${options.defaultKeyPrefix}\" against Redis db 0. ` +\n `If this Redis db is shared with another AdCP deployment (or other apps), the per-tenant scope ` +\n `segment alone is not enough to prevent cross-deployment collision. Set a deployment-unique ` +\n `keyPrefix (e.g., \"${options.defaultKeyPrefix}prod-eu:\") or use a dedicated Redis db. ` +\n `Pass { suppressDefaultPrefixWarning: true } to silence this once you've confirmed isolation.`\n );\n}\n\n/**\n * Test-only escape hatch to reset the once-warn flag between test runs.\n * Not exported through any public index — adopters can't reach it from\n * outside the SDK.\n */\nexport function __resetDefaultPrefixWarningForTests(): void {\n hasWarnedAboutDefaultPrefix = false;\n}\n"],"mappings":"AAsBA,IAAI,8BAA8B;AAW3B,SAAS,uBAAuB,QAAgC;AACrE,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,OAAQ,OAAiD;AAC/D,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,MAAI,OAAO,KAAK,aAAa,SAAU,QAAO,KAAK;AACnD,MAAI,OAAO,KAAK,QAAQ,UAAU;AAChC,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,KAAK,GAAG;AAC1B,UAAI,EAAE,aAAa,YAAY,EAAE,aAAa,UAAW,QAAO;AAChE,YAAM,OAAO,EAAE,SAAS,QAAQ,OAAO,EAAE;AACzC,UAAI,SAAS,GAAI,QAAO;AACxB,YAAM,IAAI,OAAO,IAAI;AACrB,aAAO,OAAO,UAAU,CAAC,KAAK,KAAK,IAAI,IAAI;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAwBO,SAAS,6BAA6B,SAA+C;AAC1F,MAAI,QAAQ,oBAAoB,OAAW;AAC3C,MAAI,QAAQ,SAAU;AACtB,MAAI,4BAA6B;AACjC,MAAI,uBAAuB,QAAQ,MAAM,MAAM,EAAG;AAElD,gCAA8B;AAC9B,UAAQ;AAAA,IACN,GAAG,QAAQ,WAAW,kCAAkC,QAAQ,gBAAgB,oOAGzD,QAAQ,gBAAgB;AAAA,EAEjD;AACF;AAOO,SAAS,sCAA4C;AAC1D,gCAA8B;AAChC;","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  function urlRender(fields) {
8
2
  return { ...fields, output_format: "url" };
9
3
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/render-builders.ts"],"sourcesContent":["// Typed factory helpers for `preview_creative` render objects.\n//\n// `PreviewRender` is a `oneOf` union on `output_format` — three variants:\n// `url` requires `preview_url`, `html` requires `preview_html`, `both`\n// requires both. The discriminator decides which field becomes required,\n// but nothing forces the caller to set it correctly. Matrix runs\n// repeatedly surfaced renders missing `preview_url` or `output_format`\n// because an agent wrote the object shape by hand.\n//\n// These builders mirror `imageAsset` / `videoAsset` / etc.: the caller\n// passes the payload fields and the helper injects the discriminator.\n// Spread order places the discriminator last so a runtime cast cannot\n// overwrite the canonical tag.\n\nimport type { PreviewRender } from '../types/core.generated';\n\ntype UrlRender = Extract<PreviewRender, { output_format: 'url' }>;\ntype HtmlRender = Extract<PreviewRender, { output_format: 'html' }>;\ntype BothRender = Extract<PreviewRender, { output_format: 'both' }>;\n\ntype Tagged<T, Tag extends string> = Omit<T, 'output_format'> & { output_format: Tag };\n\n/**\n * Build a url-variant `PreviewRender` with `output_format: 'url'` injected.\n *\n * Requires `preview_url` — you can't call this without the field the `url`\n * discriminator makes required, which is the whole point of the helper.\n */\nexport function urlRender(fields: Omit<UrlRender, 'output_format'>): Tagged<UrlRender, 'url'> {\n return { ...fields, output_format: 'url' };\n}\n\n/**\n * Build an html-variant `PreviewRender` with `output_format: 'html'` injected.\n */\nexport function htmlRender(fields: Omit<HtmlRender, 'output_format'>): Tagged<HtmlRender, 'html'> {\n return { ...fields, output_format: 'html' };\n}\n\n/**\n * Build a both-variant `PreviewRender` with `output_format: 'both'` injected.\n * Requires both `preview_url` and `preview_html`.\n */\nexport function bothRender(fields: Omit<BothRender, 'output_format'>): Tagged<BothRender, 'both'> {\n return { ...fields, output_format: 'both' };\n}\n\n/**\n * Grouped namespace over the same helpers, useful when constructing a\n * `renders[]` that mixes variants. Prefer the named exports at single\n * call sites; use `Render.url({...})` when building several types together.\n */\nexport const Render = {\n url: urlRender,\n html: htmlRender,\n both: bothRender,\n} as const;\n"],"mappings":";;;;;;AA4BO,SAAS,UAAU,QAAoE;AAC5F,SAAO,EAAE,GAAG,QAAQ,eAAe,MAAM;AAC3C;AAKO,SAAS,WAAW,QAAuE;AAChG,SAAO,EAAE,GAAG,QAAQ,eAAe,OAAO;AAC5C;AAMO,SAAS,WAAW,QAAuE;AAChG,SAAO,EAAE,GAAG,QAAQ,eAAe,OAAO;AAC5C;AAOO,MAAM,SAAS;AAAA,EACpB,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AACR;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/render-builders.ts"],"sourcesContent":["// Typed factory helpers for `preview_creative` render objects.\n//\n// `PreviewRender` is a `oneOf` union on `output_format` — three variants:\n// `url` requires `preview_url`, `html` requires `preview_html`, `both`\n// requires both. The discriminator decides which field becomes required,\n// but nothing forces the caller to set it correctly. Matrix runs\n// repeatedly surfaced renders missing `preview_url` or `output_format`\n// because an agent wrote the object shape by hand.\n//\n// These builders mirror `imageAsset` / `videoAsset` / etc.: the caller\n// passes the payload fields and the helper injects the discriminator.\n// Spread order places the discriminator last so a runtime cast cannot\n// overwrite the canonical tag.\n\nimport type { PreviewRender } from '../types/core.generated';\n\ntype UrlRender = Extract<PreviewRender, { output_format: 'url' }>;\ntype HtmlRender = Extract<PreviewRender, { output_format: 'html' }>;\ntype BothRender = Extract<PreviewRender, { output_format: 'both' }>;\n\ntype Tagged<T, Tag extends string> = Omit<T, 'output_format'> & { output_format: Tag };\n\n/**\n * Build a url-variant `PreviewRender` with `output_format: 'url'` injected.\n *\n * Requires `preview_url` — you can't call this without the field the `url`\n * discriminator makes required, which is the whole point of the helper.\n */\nexport function urlRender(fields: Omit<UrlRender, 'output_format'>): Tagged<UrlRender, 'url'> {\n return { ...fields, output_format: 'url' };\n}\n\n/**\n * Build an html-variant `PreviewRender` with `output_format: 'html'` injected.\n */\nexport function htmlRender(fields: Omit<HtmlRender, 'output_format'>): Tagged<HtmlRender, 'html'> {\n return { ...fields, output_format: 'html' };\n}\n\n/**\n * Build a both-variant `PreviewRender` with `output_format: 'both'` injected.\n * Requires both `preview_url` and `preview_html`.\n */\nexport function bothRender(fields: Omit<BothRender, 'output_format'>): Tagged<BothRender, 'both'> {\n return { ...fields, output_format: 'both' };\n}\n\n/**\n * Grouped namespace over the same helpers, useful when constructing a\n * `renders[]` that mixes variants. Prefer the named exports at single\n * call sites; use `Render.url({...})` when building several types together.\n */\nexport const Render = {\n url: urlRender,\n html: htmlRender,\n both: bothRender,\n} as const;\n"],"mappings":"AA4BO,SAAS,UAAU,QAAoE;AAC5F,SAAO,EAAE,GAAG,QAAQ,eAAe,MAAM;AAC3C;AAKO,SAAS,WAAW,QAAuE;AAChG,SAAO,EAAE,GAAG,QAAQ,eAAe,OAAO;AAC5C;AAMO,SAAS,WAAW,QAAuE;AAChG,SAAO,EAAE,GAAG,QAAQ,eAAe,OAAO;AAC5C;AAOO,MAAM,SAAS;AAAA,EACpB,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AACR;","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { ValidationError } from "../errors/index.mjs";
8
2
  import { brandManifestToBrandReference, promotedProductsToCatalog } from "../types/compat.mjs";
9
3
  import { warnOnce } from "./deprecation.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/request-normalizer.ts"],"sourcesContent":["/**\n * Request parameter normalization for backward compatibility.\n *\n * Converts deprecated field names and shapes so callers written against\n * earlier schema versions keep working. Each conversion emits a one-time\n * deprecation warning via warnOnce().\n */\n\nimport { ValidationError } from '../errors';\nimport { brandManifestToBrandReference, promotedProductsToCatalog } from '../types/compat';\nimport { warnOnce } from './deprecation';\nimport { MUTATING_TASKS, generateIdempotencyKey } from './idempotency';\n\n/**\n * Normalize a single package's params for backward compatibility.\n *\n * Handles:\n * - optimization_goal (scalar) → optimization_goals (array)\n * - catalog (scalar object) → catalogs (array)\n *\n * Does NOT copy `context.buyer_ref` up to a top-level `buyer_ref`. The top-level\n * field was removed from the package schema in AdCP 3.0 and strict v3 receivers\n * reject it. When a request routes to a v2.5 seller, the v2 adapter in\n * `creative-adapter.ts` derives `buyer_ref` (from a caller-supplied value,\n * `context.buyer_ref`, `idempotency_key`, or parent/index) — that adapter is\n * gated on `serverVersion !== 'v3'`, so the field only lands on the wire for\n * sellers that still expect it.\n */\nexport function normalizePackageParams(pkg: any): any {\n if (!pkg || typeof pkg !== 'object') return pkg;\n\n const normalized = { ...pkg };\n\n // Fail-closed on pre-3.0 shapes that cannot be translated without data loss.\n // product_ids[] → product_id: which id wins? No safe answer.\n // budget: {total, currency} → budget: number: which currency? No safe answer.\n // v2 sunset: unsupported as of 3.0 GA (April 2026).\n //\n // Intentional asymmetry vs get_products.product_ids (lines below), which uses\n // warnOnce+delete because that field is a query filter that can simply be dropped.\n // PackageRequest.product_id and .budget are required identifiers — dropping them\n // produces a different invalid request; throwing early is strictly better.\n //\n // This error is thrown at the client boundary before any network call and must not\n // be forwarded on the wire. It uses ValidationError (VALIDATION_ERROR) as the\n // nearest semantic fit in the client error hierarchy.\n if (Array.isArray(normalized.product_ids) && normalized.product_ids.length > 0) {\n throw new ValidationError(\n 'packages[].product_ids',\n normalized.product_ids,\n 'pre-3.0 shape not supported in AdCP 3.0. Use product_id (singular string) instead.'\n );\n }\n if (normalized.budget !== null && typeof normalized.budget === 'object') {\n throw new ValidationError(\n 'packages[].budget',\n normalized.budget,\n 'pre-3.0 shape not supported in AdCP 3.0. Use budget as a number instead.'\n );\n }\n\n // optimization_goal (scalar) → optimization_goals (array)\n if (normalized.optimization_goal && !normalized.optimization_goals?.length) {\n warnOnce(\n 'optimization_goal',\n 'PackageRequest.optimization_goal is deprecated. Use optimization_goals (array) instead.'\n );\n normalized.optimization_goals = [normalized.optimization_goal];\n }\n delete normalized.optimization_goal;\n\n // catalog (scalar) → catalogs (array)\n if (normalized.catalog && !normalized.catalogs?.length) {\n warnOnce('catalog', 'PackageRequest.catalog is deprecated. Use catalogs (array) instead.');\n normalized.catalogs = [normalized.catalog];\n }\n delete normalized.catalog;\n\n return normalized;\n}\n\n/**\n * Normalize request params for backward compatibility.\n *\n * Infers missing fields that can be derived from deprecated params so callers\n * written against older schema versions keep working.\n */\nexport function normalizeRequestParams(\n taskType: string,\n params: any,\n opts: { skipIdempotencyAutoInject?: boolean; skipAccountValidation?: boolean } = {}\n): any {\n if (!params) {\n return params;\n }\n\n const normalized = { ...params };\n\n // ── idempotency_key auto-generation ──\n // Tasks that mutate state require a caller-supplied idempotency_key per\n // AdCP spec. When the caller omits one, mint a fresh UUID v4. Most buyer\n // code never needs to track keys of its own — retries via a kept-around\n // key are the less-common path, and those callers supply their own.\n // `opts.skipIdempotencyAutoInject` disables this for compliance testing.\n // MUTATING_TASKS is derived from the Zod request schemas at module load\n // so this stays in sync with the upstream spec — no hand-maintained list.\n if (\n !opts.skipIdempotencyAutoInject &&\n MUTATING_TASKS.has(taskType) &&\n (typeof normalized.idempotency_key !== 'string' || normalized.idempotency_key.length === 0)\n ) {\n normalized.idempotency_key = generateIdempotencyKey();\n }\n\n // ── Universal shims (all tools) ──\n // Always delete deprecated fields, even when the new field already exists,\n // to prevent Zod strict validation failures on unknown keys.\n\n // account_id (bare string) → account: { account_id }\n if (typeof normalized.account_id === 'string' && !normalized.account) {\n warnOnce('account_id', 'account_id is deprecated. Use account: { account_id } instead.');\n normalized.account = { account_id: normalized.account_id };\n }\n delete normalized.account_id;\n\n // campaign_ref → buyer_campaign_ref\n if (normalized.campaign_ref && !normalized.buyer_campaign_ref) {\n warnOnce('campaign_ref', 'campaign_ref is deprecated. Use buyer_campaign_ref instead.');\n normalized.buyer_campaign_ref = normalized.campaign_ref;\n }\n delete normalized.campaign_ref;\n\n // ── brand_manifest → brand (get_products, create_media_buy) ──\n // update_media_buy has no brand field in either v2 or v3 — excluded deliberately.\n // Derive brand from brand_manifest when only the manifest is supplied.\n // brand takes precedence if both are supplied.\n // brand_manifest is preserved — agents may still require it.\n if (taskType === 'get_products' || taskType === 'create_media_buy') {\n if (normalized.brand_manifest && !normalized.brand) {\n const brand = brandManifestToBrandReference(normalized.brand_manifest);\n if (brand) {\n normalized.brand = brand;\n }\n }\n }\n\n // ── account validation (create_media_buy) ──\n // account is required per AdCP 3.0 spec. The v2 shim that inferred\n // operator = brand.domain was removed with the v2 sunset (April 2026):\n // the fabricated operator value was semantically wrong for any caller\n // with a buying-side intermediary, and it caused the compliance harness\n // to issue badges against requests with fabricated account data.\n // Callers must pass account as { account_id } or { brand, operator, sandbox? }.\n // Use list_accounts to discover an existing account_id, or sync_accounts\n // to register a new natural-key account.\n if (taskType === 'create_media_buy' && !normalized.account && !opts.skipAccountValidation) {\n throw new ValidationError(\n 'account',\n undefined,\n 'create_media_buy: account is required. ' +\n 'Pass account as { account_id } or { brand, operator, sandbox? }. ' +\n 'Use list_accounts to discover an existing account_id; ' +\n 'implicit-account sellers also support sync_accounts to register a new one.'\n );\n }\n\n // Top-level `buyer_ref` on create_media_buy / update_media_buy was removed\n // from the AdCP request schema in 3.0. It is NOT derived from `context.buyer_ref`\n // here — strict v3 receivers reject it as an unknown field. The v2.5 adapter in\n // `creative-adapter.ts` performs the derivation for legacy servers only, gated\n // on `serverVersion !== 'v3'`.\n\n // ── Package normalization (create_media_buy, update_media_buy) ──\n if ((taskType === 'create_media_buy' || taskType === 'update_media_buy') && Array.isArray(normalized.packages)) {\n normalized.packages = normalized.packages.map(normalizePackageParams);\n }\n\n // ── activate_signal: field normalization ──\n if (taskType === 'activate_signal') {\n if (normalized.deployments && !normalized.destinations) {\n warnOnce('deployments', 'deployments is deprecated. Use destinations instead.');\n normalized.destinations = normalized.deployments;\n }\n delete normalized.deployments;\n\n if (normalized.signal_id && !normalized.signal_agent_segment_id) {\n warnOnce('signal_id', 'signal_id is deprecated. Use signal_agent_segment_id instead.');\n normalized.signal_agent_segment_id = normalized.signal_id;\n }\n delete normalized.signal_id;\n\n if (normalized.destination && !normalized.destinations) {\n warnOnce('destination', 'destination (singular) is deprecated. Use destinations (array) instead.');\n normalized.destinations = [normalized.destination];\n }\n delete normalized.destination;\n\n if (normalized.options) {\n warnOnce('activate_signal.options', 'activate_signal: options is not part of the AdCP spec and will be removed.');\n }\n delete normalized.options;\n }\n\n // ── get_signals: deliver_to → destinations ──\n if (taskType === 'get_signals') {\n if (normalized.deliver_to && !normalized.destinations) {\n warnOnce('deliver_to', 'deliver_to is deprecated. Use destinations and countries instead.');\n normalized.destinations = normalized.deliver_to;\n }\n delete normalized.deliver_to;\n }\n\n // ── get_products-specific normalization ──\n if (taskType === 'get_products') {\n // Infer buying_mode from brief presence if not supplied\n if (!normalized.buying_mode) {\n normalized.buying_mode = normalized.brief ? 'brief' : 'wholesale';\n }\n\n // Strip removed v2 fields that would fail strict validation\n for (const removed of ['feedback', 'product_ids', 'proposal_id'] as const) {\n if (removed in normalized) {\n warnOnce(`get_products.${removed}`, `GetProductsRequest.${removed} has been removed in v3.`);\n delete (normalized as Record<string, unknown>)[removed];\n }\n }\n\n // Convert legacy product_selectors (v3 beta / v2 era) → catalog so strict validation passes.\n // catalog takes precedence if both are supplied.\n if (normalized.product_selectors && !normalized.catalog) {\n normalized.catalog = promotedProductsToCatalog(normalized.product_selectors);\n }\n delete normalized.product_selectors;\n }\n\n return normalized;\n}\n"],"mappings":";;;;;;AAQA,SAAS,uBAAuB;AAChC,SAAS,+BAA+B,iCAAiC;AACzE,SAAS,gBAAgB;AACzB,SAAS,gBAAgB,8BAA8B;AAiBhD,SAAS,uBAAuB,KAAe;AACpD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAE5C,QAAM,aAAa,EAAE,GAAG,IAAI;AAe5B,MAAI,MAAM,QAAQ,WAAW,WAAW,KAAK,WAAW,YAAY,SAAS,GAAG;AAC9E,UAAM,IAAI;AAAA,MACR;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,WAAW,QAAQ,OAAO,WAAW,WAAW,UAAU;AACvE,UAAM,IAAI;AAAA,MACR;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAAW,qBAAqB,CAAC,WAAW,oBAAoB,QAAQ;AAC1E;AAAA,MACE;AAAA,MACA;AAAA,IACF;AACA,eAAW,qBAAqB,CAAC,WAAW,iBAAiB;AAAA,EAC/D;AACA,SAAO,WAAW;AAGlB,MAAI,WAAW,WAAW,CAAC,WAAW,UAAU,QAAQ;AACtD,aAAS,WAAW,qEAAqE;AACzF,eAAW,WAAW,CAAC,WAAW,OAAO;AAAA,EAC3C;AACA,SAAO,WAAW;AAElB,SAAO;AACT;AAQO,SAAS,uBACd,UACA,QACA,OAAiF,CAAC,GAC7E;AACL,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,EAAE,GAAG,OAAO;AAU/B,MACE,CAAC,KAAK,6BACN,eAAe,IAAI,QAAQ,MAC1B,OAAO,WAAW,oBAAoB,YAAY,WAAW,gBAAgB,WAAW,IACzF;AACA,eAAW,kBAAkB,uBAAuB;AAAA,EACtD;AAOA,MAAI,OAAO,WAAW,eAAe,YAAY,CAAC,WAAW,SAAS;AACpE,aAAS,cAAc,gEAAgE;AACvF,eAAW,UAAU,EAAE,YAAY,WAAW,WAAW;AAAA,EAC3D;AACA,SAAO,WAAW;AAGlB,MAAI,WAAW,gBAAgB,CAAC,WAAW,oBAAoB;AAC7D,aAAS,gBAAgB,6DAA6D;AACtF,eAAW,qBAAqB,WAAW;AAAA,EAC7C;AACA,SAAO,WAAW;AAOlB,MAAI,aAAa,kBAAkB,aAAa,oBAAoB;AAClE,QAAI,WAAW,kBAAkB,CAAC,WAAW,OAAO;AAClD,YAAM,QAAQ,8BAA8B,WAAW,cAAc;AACrE,UAAI,OAAO;AACT,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAWA,MAAI,aAAa,sBAAsB,CAAC,WAAW,WAAW,CAAC,KAAK,uBAAuB;AACzF,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAIF;AAAA,EACF;AASA,OAAK,aAAa,sBAAsB,aAAa,uBAAuB,MAAM,QAAQ,WAAW,QAAQ,GAAG;AAC9G,eAAW,WAAW,WAAW,SAAS,IAAI,sBAAsB;AAAA,EACtE;AAGA,MAAI,aAAa,mBAAmB;AAClC,QAAI,WAAW,eAAe,CAAC,WAAW,cAAc;AACtD,eAAS,eAAe,sDAAsD;AAC9E,iBAAW,eAAe,WAAW;AAAA,IACvC;AACA,WAAO,WAAW;AAElB,QAAI,WAAW,aAAa,CAAC,WAAW,yBAAyB;AAC/D,eAAS,aAAa,+DAA+D;AACrF,iBAAW,0BAA0B,WAAW;AAAA,IAClD;AACA,WAAO,WAAW;AAElB,QAAI,WAAW,eAAe,CAAC,WAAW,cAAc;AACtD,eAAS,eAAe,yEAAyE;AACjG,iBAAW,eAAe,CAAC,WAAW,WAAW;AAAA,IACnD;AACA,WAAO,WAAW;AAElB,QAAI,WAAW,SAAS;AACtB,eAAS,2BAA2B,4EAA4E;AAAA,IAClH;AACA,WAAO,WAAW;AAAA,EACpB;AAGA,MAAI,aAAa,eAAe;AAC9B,QAAI,WAAW,cAAc,CAAC,WAAW,cAAc;AACrD,eAAS,cAAc,mEAAmE;AAC1F,iBAAW,eAAe,WAAW;AAAA,IACvC;AACA,WAAO,WAAW;AAAA,EACpB;AAGA,MAAI,aAAa,gBAAgB;AAE/B,QAAI,CAAC,WAAW,aAAa;AAC3B,iBAAW,cAAc,WAAW,QAAQ,UAAU;AAAA,IACxD;AAGA,eAAW,WAAW,CAAC,YAAY,eAAe,aAAa,GAAY;AACzE,UAAI,WAAW,YAAY;AACzB,iBAAS,gBAAgB,OAAO,IAAI,sBAAsB,OAAO,0BAA0B;AAC3F,eAAQ,WAAuC,OAAO;AAAA,MACxD;AAAA,IACF;AAIA,QAAI,WAAW,qBAAqB,CAAC,WAAW,SAAS;AACvD,iBAAW,UAAU,0BAA0B,WAAW,iBAAiB;AAAA,IAC7E;AACA,WAAO,WAAW;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/request-normalizer.ts"],"sourcesContent":["/**\n * Request parameter normalization for backward compatibility.\n *\n * Converts deprecated field names and shapes so callers written against\n * earlier schema versions keep working. Each conversion emits a one-time\n * deprecation warning via warnOnce().\n */\n\nimport { ValidationError } from '../errors';\nimport { brandManifestToBrandReference, promotedProductsToCatalog } from '../types/compat';\nimport { warnOnce } from './deprecation';\nimport { MUTATING_TASKS, generateIdempotencyKey } from './idempotency';\n\n/**\n * Normalize a single package's params for backward compatibility.\n *\n * Handles:\n * - optimization_goal (scalar) → optimization_goals (array)\n * - catalog (scalar object) → catalogs (array)\n *\n * Does NOT copy `context.buyer_ref` up to a top-level `buyer_ref`. The top-level\n * field was removed from the package schema in AdCP 3.0 and strict v3 receivers\n * reject it. When a request routes to a v2.5 seller, the v2 adapter in\n * `creative-adapter.ts` derives `buyer_ref` (from a caller-supplied value,\n * `context.buyer_ref`, `idempotency_key`, or parent/index) — that adapter is\n * gated on `serverVersion !== 'v3'`, so the field only lands on the wire for\n * sellers that still expect it.\n */\nexport function normalizePackageParams(pkg: any): any {\n if (!pkg || typeof pkg !== 'object') return pkg;\n\n const normalized = { ...pkg };\n\n // Fail-closed on pre-3.0 shapes that cannot be translated without data loss.\n // product_ids[] → product_id: which id wins? No safe answer.\n // budget: {total, currency} → budget: number: which currency? No safe answer.\n // v2 sunset: unsupported as of 3.0 GA (April 2026).\n //\n // Intentional asymmetry vs get_products.product_ids (lines below), which uses\n // warnOnce+delete because that field is a query filter that can simply be dropped.\n // PackageRequest.product_id and .budget are required identifiers — dropping them\n // produces a different invalid request; throwing early is strictly better.\n //\n // This error is thrown at the client boundary before any network call and must not\n // be forwarded on the wire. It uses ValidationError (VALIDATION_ERROR) as the\n // nearest semantic fit in the client error hierarchy.\n if (Array.isArray(normalized.product_ids) && normalized.product_ids.length > 0) {\n throw new ValidationError(\n 'packages[].product_ids',\n normalized.product_ids,\n 'pre-3.0 shape not supported in AdCP 3.0. Use product_id (singular string) instead.'\n );\n }\n if (normalized.budget !== null && typeof normalized.budget === 'object') {\n throw new ValidationError(\n 'packages[].budget',\n normalized.budget,\n 'pre-3.0 shape not supported in AdCP 3.0. Use budget as a number instead.'\n );\n }\n\n // optimization_goal (scalar) → optimization_goals (array)\n if (normalized.optimization_goal && !normalized.optimization_goals?.length) {\n warnOnce(\n 'optimization_goal',\n 'PackageRequest.optimization_goal is deprecated. Use optimization_goals (array) instead.'\n );\n normalized.optimization_goals = [normalized.optimization_goal];\n }\n delete normalized.optimization_goal;\n\n // catalog (scalar) → catalogs (array)\n if (normalized.catalog && !normalized.catalogs?.length) {\n warnOnce('catalog', 'PackageRequest.catalog is deprecated. Use catalogs (array) instead.');\n normalized.catalogs = [normalized.catalog];\n }\n delete normalized.catalog;\n\n return normalized;\n}\n\n/**\n * Normalize request params for backward compatibility.\n *\n * Infers missing fields that can be derived from deprecated params so callers\n * written against older schema versions keep working.\n */\nexport function normalizeRequestParams(\n taskType: string,\n params: any,\n opts: { skipIdempotencyAutoInject?: boolean; skipAccountValidation?: boolean } = {}\n): any {\n if (!params) {\n return params;\n }\n\n const normalized = { ...params };\n\n // ── idempotency_key auto-generation ──\n // Tasks that mutate state require a caller-supplied idempotency_key per\n // AdCP spec. When the caller omits one, mint a fresh UUID v4. Most buyer\n // code never needs to track keys of its own — retries via a kept-around\n // key are the less-common path, and those callers supply their own.\n // `opts.skipIdempotencyAutoInject` disables this for compliance testing.\n // MUTATING_TASKS is derived from the Zod request schemas at module load\n // so this stays in sync with the upstream spec — no hand-maintained list.\n if (\n !opts.skipIdempotencyAutoInject &&\n MUTATING_TASKS.has(taskType) &&\n (typeof normalized.idempotency_key !== 'string' || normalized.idempotency_key.length === 0)\n ) {\n normalized.idempotency_key = generateIdempotencyKey();\n }\n\n // ── Universal shims (all tools) ──\n // Always delete deprecated fields, even when the new field already exists,\n // to prevent Zod strict validation failures on unknown keys.\n\n // account_id (bare string) → account: { account_id }\n if (typeof normalized.account_id === 'string' && !normalized.account) {\n warnOnce('account_id', 'account_id is deprecated. Use account: { account_id } instead.');\n normalized.account = { account_id: normalized.account_id };\n }\n delete normalized.account_id;\n\n // campaign_ref → buyer_campaign_ref\n if (normalized.campaign_ref && !normalized.buyer_campaign_ref) {\n warnOnce('campaign_ref', 'campaign_ref is deprecated. Use buyer_campaign_ref instead.');\n normalized.buyer_campaign_ref = normalized.campaign_ref;\n }\n delete normalized.campaign_ref;\n\n // ── brand_manifest → brand (get_products, create_media_buy) ──\n // update_media_buy has no brand field in either v2 or v3 — excluded deliberately.\n // Derive brand from brand_manifest when only the manifest is supplied.\n // brand takes precedence if both are supplied.\n // brand_manifest is preserved — agents may still require it.\n if (taskType === 'get_products' || taskType === 'create_media_buy') {\n if (normalized.brand_manifest && !normalized.brand) {\n const brand = brandManifestToBrandReference(normalized.brand_manifest);\n if (brand) {\n normalized.brand = brand;\n }\n }\n }\n\n // ── account validation (create_media_buy) ──\n // account is required per AdCP 3.0 spec. The v2 shim that inferred\n // operator = brand.domain was removed with the v2 sunset (April 2026):\n // the fabricated operator value was semantically wrong for any caller\n // with a buying-side intermediary, and it caused the compliance harness\n // to issue badges against requests with fabricated account data.\n // Callers must pass account as { account_id } or { brand, operator, sandbox? }.\n // Use list_accounts to discover an existing account_id, or sync_accounts\n // to register a new natural-key account.\n if (taskType === 'create_media_buy' && !normalized.account && !opts.skipAccountValidation) {\n throw new ValidationError(\n 'account',\n undefined,\n 'create_media_buy: account is required. ' +\n 'Pass account as { account_id } or { brand, operator, sandbox? }. ' +\n 'Use list_accounts to discover an existing account_id; ' +\n 'implicit-account sellers also support sync_accounts to register a new one.'\n );\n }\n\n // Top-level `buyer_ref` on create_media_buy / update_media_buy was removed\n // from the AdCP request schema in 3.0. It is NOT derived from `context.buyer_ref`\n // here — strict v3 receivers reject it as an unknown field. The v2.5 adapter in\n // `creative-adapter.ts` performs the derivation for legacy servers only, gated\n // on `serverVersion !== 'v3'`.\n\n // ── Package normalization (create_media_buy, update_media_buy) ──\n if ((taskType === 'create_media_buy' || taskType === 'update_media_buy') && Array.isArray(normalized.packages)) {\n normalized.packages = normalized.packages.map(normalizePackageParams);\n }\n\n // ── activate_signal: field normalization ──\n if (taskType === 'activate_signal') {\n if (normalized.deployments && !normalized.destinations) {\n warnOnce('deployments', 'deployments is deprecated. Use destinations instead.');\n normalized.destinations = normalized.deployments;\n }\n delete normalized.deployments;\n\n if (normalized.signal_id && !normalized.signal_agent_segment_id) {\n warnOnce('signal_id', 'signal_id is deprecated. Use signal_agent_segment_id instead.');\n normalized.signal_agent_segment_id = normalized.signal_id;\n }\n delete normalized.signal_id;\n\n if (normalized.destination && !normalized.destinations) {\n warnOnce('destination', 'destination (singular) is deprecated. Use destinations (array) instead.');\n normalized.destinations = [normalized.destination];\n }\n delete normalized.destination;\n\n if (normalized.options) {\n warnOnce('activate_signal.options', 'activate_signal: options is not part of the AdCP spec and will be removed.');\n }\n delete normalized.options;\n }\n\n // ── get_signals: deliver_to → destinations ──\n if (taskType === 'get_signals') {\n if (normalized.deliver_to && !normalized.destinations) {\n warnOnce('deliver_to', 'deliver_to is deprecated. Use destinations and countries instead.');\n normalized.destinations = normalized.deliver_to;\n }\n delete normalized.deliver_to;\n }\n\n // ── get_products-specific normalization ──\n if (taskType === 'get_products') {\n // Infer buying_mode from brief presence if not supplied\n if (!normalized.buying_mode) {\n normalized.buying_mode = normalized.brief ? 'brief' : 'wholesale';\n }\n\n // Strip removed v2 fields that would fail strict validation\n for (const removed of ['feedback', 'product_ids', 'proposal_id'] as const) {\n if (removed in normalized) {\n warnOnce(`get_products.${removed}`, `GetProductsRequest.${removed} has been removed in v3.`);\n delete (normalized as Record<string, unknown>)[removed];\n }\n }\n\n // Convert legacy product_selectors (v3 beta / v2 era) → catalog so strict validation passes.\n // catalog takes precedence if both are supplied.\n if (normalized.product_selectors && !normalized.catalog) {\n normalized.catalog = promotedProductsToCatalog(normalized.product_selectors);\n }\n delete normalized.product_selectors;\n }\n\n return normalized;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { z } from "zod";
8
2
  import * as schemas from "../types/schemas.generated.mjs";
9
3
  import { SyncCreativesResponseStrictSchema } from "../validation/sync-creatives.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/response-schemas.ts"],"sourcesContent":["/**\n * Canonical map of AdCP tool names to their Zod response schemas.\n *\n * Shared by response-unwrapper (runtime parsing) and testing/client\n * (compliance validation) so the two never diverge.\n */\n\nimport { z } from 'zod';\nimport * as schemas from '../types/schemas.generated';\nimport { SyncCreativesResponseStrictSchema } from '../validation/sync-creatives';\nimport { isPre31AdcpVersion } from './adcp-version-config';\n\nfunction declaresLegacy30xPayload(response: Record<string, unknown>): boolean {\n const adcpVersion = response.adcp_version;\n if (typeof adcpVersion === 'string') {\n return (\n adcpVersion === '3' || adcpVersion === '3.0' || adcpVersion.startsWith('3.0.') || adcpVersion.startsWith('3.0-')\n );\n }\n return response.adcp_major_version === 3;\n}\n\nexport function prepareResponseForSchemaValidation(\n toolName: string,\n data: unknown,\n responseAdcpVersion?: string\n): unknown {\n if (toolName !== 'get_products') return data;\n if (!isPre31AdcpVersion(responseAdcpVersion)) return data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) return data;\n\n const response = data as Record<string, unknown>;\n if (response.adcp_version !== undefined || response.adcp_major_version !== undefined) return data;\n return { ...response, adcp_version: '3.0' };\n}\n\nconst GetProductsResponseStrictSchema = schemas.GetProductsResponseSchema.superRefine((value, ctx) => {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) return;\n const response = value as { products?: unknown; cache_scope?: unknown; unchanged?: unknown };\n if (declaresLegacy30xPayload(response)) return;\n if ((Array.isArray(response.products) || response.unchanged === true) && response.cache_scope === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['cache_scope'],\n message: '`cache_scope` is required when `products` is present or `unchanged` is true',\n });\n }\n});\n\nexport const TOOL_RESPONSE_SCHEMAS: Partial<Record<string, z.ZodType>> = {\n // Product discovery & media buy\n get_products: GetProductsResponseStrictSchema,\n create_media_buy: schemas.CreateMediaBuyResponseSchema,\n update_media_buy: schemas.UpdateMediaBuyResponseSchema,\n get_media_buys: schemas.GetMediaBuysResponseSchema,\n get_media_buy_delivery: schemas.GetMediaBuyDeliveryResponseSchema,\n provide_performance_feedback: schemas.ProvidePerformanceFeedbackResponseSchema,\n\n // Creative\n list_creative_formats: schemas.ListCreativeFormatsResponseSchema,\n list_transformers: schemas.ListTransformersResponseSchema,\n build_creative: schemas.BuildCreativeResponseSchema,\n validate_input: schemas.ValidateInputResponseSchema,\n preview_creative: schemas.PreviewCreativeResponseSchema,\n // Override the generated schema — it degrades creatives[] to a bare\n // record because the JSON Schema inlines the item shape. The strict\n // variant carries the per-item validator so the pipeline catches drift.\n sync_creatives: SyncCreativesResponseStrictSchema,\n list_creatives: schemas.ListCreativesResponseSchema,\n get_creative_delivery: schemas.GetCreativeDeliveryResponseSchema,\n\n // Signals\n get_signals: schemas.GetSignalsResponseSchema,\n activate_signal: schemas.ActivateSignalResponseSchema,\n\n // Trusted Match\n context_match: schemas.ContextMatchResponseSchema,\n identity_match: schemas.IdentityMatchResponseSchema,\n\n // Account & audience\n sync_accounts: schemas.SyncAccountsResponseSchema,\n list_accounts: schemas.ListAccountsResponseSchema,\n sync_governance: schemas.SyncGovernanceResponseSchema,\n sync_audiences: schemas.SyncAudiencesResponseSchema,\n report_usage: schemas.ReportUsageResponseSchema,\n get_account_financials: schemas.GetAccountFinancialsResponseSchema,\n\n // Catalogs & events\n sync_catalogs: schemas.SyncCatalogsResponseSchema,\n sync_event_sources: schemas.SyncEventSourcesResponseSchema,\n log_event: schemas.LogEventResponseSchema,\n get_media_buy_artifacts: schemas.GetMediaBuyArtifactsResponseSchema,\n\n // Creative (additional)\n get_creative_features: schemas.GetCreativeFeaturesResponseSchema,\n\n // Governance — property lists & content standards\n create_property_list: schemas.CreatePropertyListResponseSchema,\n get_property_list: schemas.GetPropertyListResponseSchema,\n update_property_list: schemas.UpdatePropertyListResponseSchema,\n list_property_lists: schemas.ListPropertyListsResponseSchema,\n delete_property_list: schemas.DeletePropertyListResponseSchema,\n list_content_standards: schemas.ListContentStandardsResponseSchema,\n get_content_standards: schemas.GetContentStandardsResponseSchema,\n create_content_standards: schemas.CreateContentStandardsResponseSchema,\n update_content_standards: schemas.UpdateContentStandardsResponseSchema,\n calibrate_content: schemas.CalibrateContentResponseSchema,\n validate_content_delivery: schemas.ValidateContentDeliveryResponseSchema,\n\n // Collection lists\n create_collection_list: schemas.CreateCollectionListResponseSchema,\n update_collection_list: schemas.UpdateCollectionListResponseSchema,\n get_collection_list: schemas.GetCollectionListResponseSchema,\n list_collection_lists: schemas.ListCollectionListsResponseSchema,\n delete_collection_list: schemas.DeleteCollectionListResponseSchema,\n\n // Campaign governance\n sync_plans: schemas.SyncPlansResponseSchema,\n check_governance: schemas.CheckGovernanceResponseSchema,\n report_plan_outcome: schemas.ReportPlanOutcomeResponseSchema,\n get_plan_audit_logs: schemas.GetPlanAuditLogsResponseSchema,\n\n // Sponsored Intelligence\n si_get_offering: schemas.SIGetOfferingResponseSchema,\n si_initiate_session: schemas.SIInitiateSessionResponseSchema,\n si_send_message: schemas.SISendMessageResponseSchema,\n si_terminate_session: schemas.SITerminateSessionResponseSchema,\n\n // Capabilities\n get_adcp_capabilities: schemas.GetAdCPCapabilitiesResponseSchema,\n get_task_status: schemas.GetTaskStatusResponseSchema,\n list_tasks: schemas.ListTasksResponseSchema,\n\n // Test controller\n comply_test_controller: schemas.ComplyTestControllerResponseSchema,\n\n // Property governance\n validate_property_delivery: schemas.ValidatePropertyDeliveryResponseSchema,\n\n // Brand rights\n get_brand_identity: schemas.GetBrandIdentityResponseSchema,\n verify_brand_claim: schemas.VerifyBrandClaimResponseSchema,\n get_rights: schemas.GetRightsResponseSchema,\n acquire_rights: schemas.AcquireRightsResponseSchema,\n\n // Brand rights — no schema definitions yet for these tools\n update_rights: z.union([\n z.object({ rights_id: z.string() }).passthrough(),\n z.object({ errors: z.array(schemas.ErrorSchema) }).passthrough(),\n ]),\n creative_approval: z.union([\n z.object({ decision: z.string() }).passthrough(),\n z.object({ errors: z.array(schemas.ErrorSchema) }).passthrough(),\n ]),\n verify_brand_claims: schemas.VerifyBrandClaimsResponseBulkSchema,\n search_brands: schemas.SearchBrandsResponseSchema,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils/response-schemas.ts"],"sourcesContent":["/**\n * Canonical map of AdCP tool names to their Zod response schemas.\n *\n * Shared by response-unwrapper (runtime parsing) and testing/client\n * (compliance validation) so the two never diverge.\n */\n\nimport { z } from 'zod';\nimport * as schemas from '../types/schemas.generated';\nimport { SyncCreativesResponseStrictSchema } from '../validation/sync-creatives';\nimport { isPre31AdcpVersion } from './adcp-version-config';\n\nfunction declaresLegacy30xPayload(response: Record<string, unknown>): boolean {\n const adcpVersion = response.adcp_version;\n if (typeof adcpVersion === 'string') {\n return (\n adcpVersion === '3' || adcpVersion === '3.0' || adcpVersion.startsWith('3.0.') || adcpVersion.startsWith('3.0-')\n );\n }\n return response.adcp_major_version === 3;\n}\n\nexport function prepareResponseForSchemaValidation(\n toolName: string,\n data: unknown,\n responseAdcpVersion?: string\n): unknown {\n if (toolName !== 'get_products') return data;\n if (!isPre31AdcpVersion(responseAdcpVersion)) return data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) return data;\n\n const response = data as Record<string, unknown>;\n if (response.adcp_version !== undefined || response.adcp_major_version !== undefined) return data;\n return { ...response, adcp_version: '3.0' };\n}\n\nconst GetProductsResponseStrictSchema = schemas.GetProductsResponseSchema.superRefine((value, ctx) => {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) return;\n const response = value as { products?: unknown; cache_scope?: unknown; unchanged?: unknown };\n if (declaresLegacy30xPayload(response)) return;\n if ((Array.isArray(response.products) || response.unchanged === true) && response.cache_scope === undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['cache_scope'],\n message: '`cache_scope` is required when `products` is present or `unchanged` is true',\n });\n }\n});\n\nexport const TOOL_RESPONSE_SCHEMAS: Partial<Record<string, z.ZodType>> = {\n // Product discovery & media buy\n get_products: GetProductsResponseStrictSchema,\n create_media_buy: schemas.CreateMediaBuyResponseSchema,\n update_media_buy: schemas.UpdateMediaBuyResponseSchema,\n get_media_buys: schemas.GetMediaBuysResponseSchema,\n get_media_buy_delivery: schemas.GetMediaBuyDeliveryResponseSchema,\n provide_performance_feedback: schemas.ProvidePerformanceFeedbackResponseSchema,\n\n // Creative\n list_creative_formats: schemas.ListCreativeFormatsResponseSchema,\n list_transformers: schemas.ListTransformersResponseSchema,\n build_creative: schemas.BuildCreativeResponseSchema,\n validate_input: schemas.ValidateInputResponseSchema,\n preview_creative: schemas.PreviewCreativeResponseSchema,\n // Override the generated schema — it degrades creatives[] to a bare\n // record because the JSON Schema inlines the item shape. The strict\n // variant carries the per-item validator so the pipeline catches drift.\n sync_creatives: SyncCreativesResponseStrictSchema,\n list_creatives: schemas.ListCreativesResponseSchema,\n get_creative_delivery: schemas.GetCreativeDeliveryResponseSchema,\n\n // Signals\n get_signals: schemas.GetSignalsResponseSchema,\n activate_signal: schemas.ActivateSignalResponseSchema,\n\n // Trusted Match\n context_match: schemas.ContextMatchResponseSchema,\n identity_match: schemas.IdentityMatchResponseSchema,\n\n // Account & audience\n sync_accounts: schemas.SyncAccountsResponseSchema,\n list_accounts: schemas.ListAccountsResponseSchema,\n sync_governance: schemas.SyncGovernanceResponseSchema,\n sync_audiences: schemas.SyncAudiencesResponseSchema,\n report_usage: schemas.ReportUsageResponseSchema,\n get_account_financials: schemas.GetAccountFinancialsResponseSchema,\n\n // Catalogs & events\n sync_catalogs: schemas.SyncCatalogsResponseSchema,\n sync_event_sources: schemas.SyncEventSourcesResponseSchema,\n log_event: schemas.LogEventResponseSchema,\n get_media_buy_artifacts: schemas.GetMediaBuyArtifactsResponseSchema,\n\n // Creative (additional)\n get_creative_features: schemas.GetCreativeFeaturesResponseSchema,\n\n // Governance — property lists & content standards\n create_property_list: schemas.CreatePropertyListResponseSchema,\n get_property_list: schemas.GetPropertyListResponseSchema,\n update_property_list: schemas.UpdatePropertyListResponseSchema,\n list_property_lists: schemas.ListPropertyListsResponseSchema,\n delete_property_list: schemas.DeletePropertyListResponseSchema,\n list_content_standards: schemas.ListContentStandardsResponseSchema,\n get_content_standards: schemas.GetContentStandardsResponseSchema,\n create_content_standards: schemas.CreateContentStandardsResponseSchema,\n update_content_standards: schemas.UpdateContentStandardsResponseSchema,\n calibrate_content: schemas.CalibrateContentResponseSchema,\n validate_content_delivery: schemas.ValidateContentDeliveryResponseSchema,\n\n // Collection lists\n create_collection_list: schemas.CreateCollectionListResponseSchema,\n update_collection_list: schemas.UpdateCollectionListResponseSchema,\n get_collection_list: schemas.GetCollectionListResponseSchema,\n list_collection_lists: schemas.ListCollectionListsResponseSchema,\n delete_collection_list: schemas.DeleteCollectionListResponseSchema,\n\n // Campaign governance\n sync_plans: schemas.SyncPlansResponseSchema,\n check_governance: schemas.CheckGovernanceResponseSchema,\n report_plan_outcome: schemas.ReportPlanOutcomeResponseSchema,\n get_plan_audit_logs: schemas.GetPlanAuditLogsResponseSchema,\n\n // Sponsored Intelligence\n si_get_offering: schemas.SIGetOfferingResponseSchema,\n si_initiate_session: schemas.SIInitiateSessionResponseSchema,\n si_send_message: schemas.SISendMessageResponseSchema,\n si_terminate_session: schemas.SITerminateSessionResponseSchema,\n\n // Capabilities\n get_adcp_capabilities: schemas.GetAdCPCapabilitiesResponseSchema,\n get_task_status: schemas.GetTaskStatusResponseSchema,\n list_tasks: schemas.ListTasksResponseSchema,\n\n // Test controller\n comply_test_controller: schemas.ComplyTestControllerResponseSchema,\n\n // Property governance\n validate_property_delivery: schemas.ValidatePropertyDeliveryResponseSchema,\n\n // Brand rights\n get_brand_identity: schemas.GetBrandIdentityResponseSchema,\n verify_brand_claim: schemas.VerifyBrandClaimResponseSchema,\n get_rights: schemas.GetRightsResponseSchema,\n acquire_rights: schemas.AcquireRightsResponseSchema,\n\n // Brand rights — no schema definitions yet for these tools\n update_rights: z.union([\n z.object({ rights_id: z.string() }).passthrough(),\n z.object({ errors: z.array(schemas.ErrorSchema) }).passthrough(),\n ]),\n creative_approval: z.union([\n z.object({ decision: z.string() }).passthrough(),\n z.object({ errors: z.array(schemas.ErrorSchema) }).passthrough(),\n ]),\n verify_brand_claims: schemas.VerifyBrandClaimsResponseBulkSchema,\n search_brands: schemas.SearchBrandsResponseSchema,\n};\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { z } from "zod";
8
2
  import { getBestUnionErrors } from "./union-errors.mjs";
9
3
  const ERROR_CODES = {