@adcp/sdk 5.25.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/README.md +45 -7
  2. package/dist/lib/compliance-fixtures/index.d.ts +1 -1
  3. package/dist/lib/compliance-fixtures/index.js +1 -1
  4. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  5. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  6. package/dist/lib/core/SingleAgentClient.js +15 -0
  7. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  8. package/dist/lib/core/TaskExecutor.d.ts +7 -0
  9. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  10. package/dist/lib/core/TaskExecutor.js +9 -2
  11. package/dist/lib/core/TaskExecutor.js.map +1 -1
  12. package/dist/lib/index.d.ts +1 -1
  13. package/dist/lib/index.d.ts.map +1 -1
  14. package/dist/lib/index.js +7 -8
  15. package/dist/lib/index.js.map +1 -1
  16. package/dist/lib/schemas/index.d.ts +1 -1
  17. package/dist/lib/schemas/index.js +1 -1
  18. package/dist/lib/server/create-adcp-server.d.ts +129 -11
  19. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  20. package/dist/lib/server/create-adcp-server.js +112 -2
  21. package/dist/lib/server/create-adcp-server.js.map +1 -1
  22. package/dist/lib/server/ctx-metadata/backends/memory.d.ts +27 -0
  23. package/dist/lib/server/ctx-metadata/backends/memory.d.ts.map +1 -0
  24. package/dist/lib/server/ctx-metadata/backends/memory.js +72 -0
  25. package/dist/lib/server/ctx-metadata/backends/memory.js.map +1 -0
  26. package/dist/lib/server/ctx-metadata/backends/pg.d.ts +62 -0
  27. package/dist/lib/server/ctx-metadata/backends/pg.d.ts.map +1 -0
  28. package/dist/lib/server/ctx-metadata/backends/pg.js +145 -0
  29. package/dist/lib/server/ctx-metadata/backends/pg.js.map +1 -0
  30. package/dist/lib/server/ctx-metadata/index.d.ts +15 -0
  31. package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -0
  32. package/dist/lib/server/ctx-metadata/index.js +28 -0
  33. package/dist/lib/server/ctx-metadata/index.js.map +1 -0
  34. package/dist/lib/server/ctx-metadata/store.d.ts +177 -0
  35. package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -0
  36. package/dist/lib/server/ctx-metadata/store.js +327 -0
  37. package/dist/lib/server/ctx-metadata/store.js.map +1 -0
  38. package/dist/lib/server/ctx-metadata/wire-shape.d.ts +55 -0
  39. package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -0
  40. package/dist/lib/server/ctx-metadata/wire-shape.js +121 -0
  41. package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -0
  42. package/dist/lib/server/decisioning/account.d.ts +309 -0
  43. package/dist/lib/server/decisioning/account.d.ts.map +1 -0
  44. package/dist/lib/server/decisioning/account.js +102 -0
  45. package/dist/lib/server/decisioning/account.js.map +1 -0
  46. package/dist/lib/server/decisioning/admin-router.d.ts +75 -0
  47. package/dist/lib/server/decisioning/admin-router.d.ts.map +1 -0
  48. package/dist/lib/server/decisioning/admin-router.js +120 -0
  49. package/dist/lib/server/decisioning/admin-router.js.map +1 -0
  50. package/dist/lib/server/decisioning/assembly-helpers.d.ts +204 -0
  51. package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -0
  52. package/dist/lib/server/decisioning/assembly-helpers.js +173 -0
  53. package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -0
  54. package/dist/lib/server/decisioning/async-outcome.d.ts +154 -0
  55. package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -0
  56. package/dist/lib/server/decisioning/async-outcome.js +239 -0
  57. package/dist/lib/server/decisioning/async-outcome.js.map +1 -0
  58. package/dist/lib/server/decisioning/capabilities.d.ts +251 -0
  59. package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -0
  60. package/dist/lib/server/decisioning/capabilities.js +16 -0
  61. package/dist/lib/server/decisioning/capabilities.js.map +1 -0
  62. package/dist/lib/server/decisioning/context.d.ts +212 -0
  63. package/dist/lib/server/decisioning/context.d.ts.map +1 -0
  64. package/dist/lib/server/decisioning/context.js +26 -0
  65. package/dist/lib/server/decisioning/context.js.map +1 -0
  66. package/dist/lib/server/decisioning/errors-typed.d.ts +104 -0
  67. package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -0
  68. package/dist/lib/server/decisioning/errors-typed.js +304 -0
  69. package/dist/lib/server/decisioning/errors-typed.js.map +1 -0
  70. package/dist/lib/server/decisioning/helpers.d.ts +131 -0
  71. package/dist/lib/server/decisioning/helpers.d.ts.map +1 -0
  72. package/dist/lib/server/decisioning/helpers.js +134 -0
  73. package/dist/lib/server/decisioning/helpers.js.map +1 -0
  74. package/dist/lib/server/decisioning/index.d.ts +46 -0
  75. package/dist/lib/server/decisioning/index.d.ts.map +1 -0
  76. package/dist/lib/server/decisioning/index.js +120 -0
  77. package/dist/lib/server/decisioning/index.js.map +1 -0
  78. package/dist/lib/server/decisioning/list-helpers.d.ts +53 -0
  79. package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -0
  80. package/dist/lib/server/decisioning/list-helpers.js +96 -0
  81. package/dist/lib/server/decisioning/list-helpers.js.map +1 -0
  82. package/dist/lib/server/decisioning/manifest-helpers.d.ts +56 -0
  83. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -0
  84. package/dist/lib/server/decisioning/manifest-helpers.js +78 -0
  85. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -0
  86. package/dist/lib/server/decisioning/pagination.d.ts +21 -0
  87. package/dist/lib/server/decisioning/pagination.d.ts.map +1 -0
  88. package/dist/lib/server/decisioning/pagination.js +12 -0
  89. package/dist/lib/server/decisioning/pagination.js.map +1 -0
  90. package/dist/lib/server/decisioning/platform.d.ts +188 -0
  91. package/dist/lib/server/decisioning/platform.d.ts.map +1 -0
  92. package/dist/lib/server/decisioning/platform.js +19 -0
  93. package/dist/lib/server/decisioning/platform.js.map +1 -0
  94. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +510 -0
  95. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -0
  96. package/dist/lib/server/decisioning/runtime/from-platform.js +2196 -0
  97. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -0
  98. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +114 -0
  99. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -0
  100. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +247 -0
  101. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -0
  102. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts +32 -0
  103. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts.map +1 -0
  104. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +127 -0
  105. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -0
  106. package/dist/lib/server/decisioning/runtime/task-registry.d.ts +105 -0
  107. package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -0
  108. package/dist/lib/server/decisioning/runtime/task-registry.js +96 -0
  109. package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -0
  110. package/dist/lib/server/decisioning/runtime/to-context.d.ts +54 -0
  111. package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -0
  112. package/dist/lib/server/decisioning/runtime/to-context.js +166 -0
  113. package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -0
  114. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +20 -0
  115. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -0
  116. package/dist/lib/server/decisioning/runtime/validate-platform.js +93 -0
  117. package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -0
  118. package/dist/lib/server/decisioning/specialisms/audiences.d.ts +72 -0
  119. package/dist/lib/server/decisioning/specialisms/audiences.d.ts.map +1 -0
  120. package/dist/lib/server/decisioning/specialisms/audiences.js +15 -0
  121. package/dist/lib/server/decisioning/specialisms/audiences.js.map +1 -0
  122. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +92 -0
  123. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -0
  124. package/dist/lib/server/decisioning/specialisms/brand-rights.js +28 -0
  125. package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -0
  126. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts +67 -0
  127. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts.map +1 -0
  128. package/dist/lib/server/decisioning/specialisms/campaign-governance.js +31 -0
  129. package/dist/lib/server/decisioning/specialisms/campaign-governance.js.map +1 -0
  130. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +78 -0
  131. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -0
  132. package/dist/lib/server/decisioning/specialisms/content-standards.js +35 -0
  133. package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -0
  134. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +81 -0
  135. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -0
  136. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js +28 -0
  137. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -0
  138. package/dist/lib/server/decisioning/specialisms/creative.d.ts +144 -0
  139. package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -0
  140. package/dist/lib/server/decisioning/specialisms/creative.js +19 -0
  141. package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -0
  142. package/dist/lib/server/decisioning/specialisms/lists.d.ts +61 -0
  143. package/dist/lib/server/decisioning/specialisms/lists.d.ts.map +1 -0
  144. package/dist/lib/server/decisioning/specialisms/lists.js +30 -0
  145. package/dist/lib/server/decisioning/specialisms/lists.js.map +1 -0
  146. package/dist/lib/server/decisioning/specialisms/sales.d.ts +163 -0
  147. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -0
  148. package/dist/lib/server/decisioning/specialisms/sales.js +64 -0
  149. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -0
  150. package/dist/lib/server/decisioning/specialisms/signals.d.ts +64 -0
  151. package/dist/lib/server/decisioning/specialisms/signals.d.ts.map +1 -0
  152. package/dist/lib/server/decisioning/specialisms/signals.js +28 -0
  153. package/dist/lib/server/decisioning/specialisms/signals.js.map +1 -0
  154. package/dist/lib/server/decisioning/start-time.d.ts +76 -0
  155. package/dist/lib/server/decisioning/start-time.d.ts.map +1 -0
  156. package/dist/lib/server/decisioning/start-time.js +81 -0
  157. package/dist/lib/server/decisioning/start-time.js.map +1 -0
  158. package/dist/lib/server/decisioning/status-changes.d.ts +165 -0
  159. package/dist/lib/server/decisioning/status-changes.d.ts.map +1 -0
  160. package/dist/lib/server/decisioning/status-changes.js +131 -0
  161. package/dist/lib/server/decisioning/status-changes.js.map +1 -0
  162. package/dist/lib/server/decisioning/status-mappers.d.ts +46 -0
  163. package/dist/lib/server/decisioning/status-mappers.d.ts.map +1 -0
  164. package/dist/lib/server/decisioning/status-mappers.js +46 -0
  165. package/dist/lib/server/decisioning/status-mappers.js.map +1 -0
  166. package/dist/lib/server/decisioning/tenant-registry.d.ts +289 -0
  167. package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -0
  168. package/dist/lib/server/decisioning/tenant-registry.js +503 -0
  169. package/dist/lib/server/decisioning/tenant-registry.js.map +1 -0
  170. package/dist/lib/server/express-adapter.d.ts +1 -1
  171. package/dist/lib/server/express-adapter.js +1 -1
  172. package/dist/lib/server/governance.d.ts +1 -1
  173. package/dist/lib/server/governance.js +1 -1
  174. package/dist/lib/server/idempotency/store.d.ts +1 -1
  175. package/dist/lib/server/idempotency/store.js +1 -1
  176. package/dist/lib/server/index.d.ts +9 -2
  177. package/dist/lib/server/index.d.ts.map +1 -1
  178. package/dist/lib/server/index.js +79 -4
  179. package/dist/lib/server/index.js.map +1 -1
  180. package/dist/lib/server/legacy/v5/index.d.ts +38 -0
  181. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -0
  182. package/dist/lib/server/legacy/v5/index.js +60 -0
  183. package/dist/lib/server/legacy/v5/index.js.map +1 -0
  184. package/dist/lib/server/normalize-errors.d.ts +88 -0
  185. package/dist/lib/server/normalize-errors.d.ts.map +1 -0
  186. package/dist/lib/server/normalize-errors.js +146 -0
  187. package/dist/lib/server/normalize-errors.js.map +1 -0
  188. package/dist/lib/server/pick-safe-details.d.ts +90 -0
  189. package/dist/lib/server/pick-safe-details.d.ts.map +1 -0
  190. package/dist/lib/server/pick-safe-details.js +148 -0
  191. package/dist/lib/server/pick-safe-details.js.map +1 -0
  192. package/dist/lib/server/postgres-state-store.d.ts +1 -1
  193. package/dist/lib/server/postgres-state-store.js +1 -1
  194. package/dist/lib/server/responses.d.ts +38 -0
  195. package/dist/lib/server/responses.d.ts.map +1 -1
  196. package/dist/lib/server/responses.js +38 -0
  197. package/dist/lib/server/responses.js.map +1 -1
  198. package/dist/lib/server/state-store.d.ts +1 -1
  199. package/dist/lib/server/state-store.js +1 -1
  200. package/dist/lib/server/test-controller.d.ts +10 -3
  201. package/dist/lib/server/test-controller.d.ts.map +1 -1
  202. package/dist/lib/server/test-controller.js +10 -3
  203. package/dist/lib/server/test-controller.js.map +1 -1
  204. package/dist/lib/testing/comply-controller.d.ts +47 -1
  205. package/dist/lib/testing/comply-controller.d.ts.map +1 -1
  206. package/dist/lib/testing/comply-controller.js +11 -4
  207. package/dist/lib/testing/comply-controller.js.map +1 -1
  208. package/dist/lib/testing/index.d.ts +1 -1
  209. package/dist/lib/testing/index.d.ts.map +1 -1
  210. package/dist/lib/testing/index.js.map +1 -1
  211. package/dist/lib/testing/personas/index.d.ts +143 -0
  212. package/dist/lib/testing/personas/index.d.ts.map +1 -0
  213. package/dist/lib/testing/personas/index.js +190 -0
  214. package/dist/lib/testing/personas/index.js.map +1 -0
  215. package/dist/lib/testing/storyboard/index.d.ts +1 -1
  216. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  217. package/dist/lib/testing/storyboard/index.js +3 -2
  218. package/dist/lib/testing/storyboard/index.js.map +1 -1
  219. package/dist/lib/testing/storyboard/runner.d.ts +13 -0
  220. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  221. package/dist/lib/testing/storyboard/runner.js +179 -7
  222. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  223. package/dist/lib/types/asset-instances.d.ts +1 -0
  224. package/dist/lib/types/asset-instances.d.ts.map +1 -1
  225. package/dist/lib/types/core.generated.d.ts +203 -98
  226. package/dist/lib/types/core.generated.d.ts.map +1 -1
  227. package/dist/lib/types/core.generated.js +1 -1
  228. package/dist/lib/types/index.d.ts +1 -0
  229. package/dist/lib/types/index.d.ts.map +1 -1
  230. package/dist/lib/types/index.js.map +1 -1
  231. package/dist/lib/types/schemas.generated.d.ts +599 -159
  232. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  233. package/dist/lib/types/schemas.generated.js +175 -94
  234. package/dist/lib/types/schemas.generated.js.map +1 -1
  235. package/dist/lib/types/tools.generated.d.ts +315 -46
  236. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  237. package/dist/lib/utils/capabilities.d.ts +1 -1
  238. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  239. package/dist/lib/utils/capabilities.js +6 -0
  240. package/dist/lib/utils/capabilities.js.map +1 -1
  241. package/dist/lib/validation/schema-validator.d.ts +13 -0
  242. package/dist/lib/validation/schema-validator.d.ts.map +1 -1
  243. package/dist/lib/validation/schema-validator.js +240 -3
  244. package/dist/lib/validation/schema-validator.js.map +1 -1
  245. package/dist/lib/version.d.ts +3 -3
  246. package/dist/lib/version.d.ts.map +1 -1
  247. package/dist/lib/version.js +3 -3
  248. package/dist/lib/version.js.map +1 -1
  249. package/docs/guides/BUILD-AN-AGENT.md +30 -5
  250. package/docs/llms.txt +28 -17
  251. package/examples/README.md +3 -1
  252. package/examples/decisioning-platform-broadcast-tv.ts +300 -0
  253. package/examples/decisioning-platform-identity-graph.ts +214 -0
  254. package/examples/decisioning-platform-mock-seller.ts +332 -0
  255. package/examples/decisioning-platform-multi-tenant.ts +128 -0
  256. package/examples/decisioning-platform-programmatic.ts +254 -0
  257. package/examples/signals-agent.ts +1 -1
  258. package/package.json +13 -2
  259. package/skills/build-brand-rights-agent/SKILL.md +10 -3
  260. package/skills/build-creative-agent/SKILL.md +94 -64
  261. package/skills/build-decisioning-creative-template/SKILL.md +554 -0
  262. package/skills/build-decisioning-platform/SKILL.md +304 -0
  263. package/skills/build-decisioning-platform/advanced/BRAND-RIGHTS.md +25 -0
  264. package/skills/build-decisioning-platform/advanced/COMPLIANCE.md +23 -0
  265. package/skills/build-decisioning-platform/advanced/GOVERNANCE.md +24 -0
  266. package/skills/build-decisioning-platform/advanced/HITL.md +34 -0
  267. package/skills/build-decisioning-platform/advanced/IDEMPOTENCY.md +52 -0
  268. package/skills/build-decisioning-platform/advanced/MULTI-TENANT.md +47 -0
  269. package/skills/build-decisioning-platform/advanced/OAUTH.md +22 -0
  270. package/skills/build-decisioning-platform/advanced/REFERENCE.md +991 -0
  271. package/skills/build-decisioning-platform/advanced/SANDBOX.md +24 -0
  272. package/skills/build-decisioning-platform/advanced/STATE-MACHINE.md +52 -0
  273. package/skills/build-decisioning-signal-marketplace/SKILL.md +269 -0
  274. package/skills/build-generative-seller-agent/SKILL.md +89 -53
  275. package/skills/build-governance-agent/SKILL.md +76 -45
  276. package/skills/build-retail-media-agent/SKILL.md +87 -62
  277. package/skills/build-seller-agent/SKILL.md +384 -255
  278. package/skills/build-seller-agent/deployment.md +5 -3
  279. package/skills/build-seller-agent/specialisms/audience-sync.md +0 -2
  280. package/skills/build-seller-agent/specialisms/sales-broadcast-tv.md +0 -2
  281. package/skills/build-seller-agent/specialisms/sales-guaranteed.md +0 -2
  282. package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +0 -2
  283. package/skills/build-seller-agent/specialisms/sales-proposal-mode.md +0 -2
  284. package/skills/build-seller-agent/specialisms/sales-social.md +0 -2
  285. package/skills/build-seller-agent/specialisms/signed-requests.md +0 -2
  286. package/skills/build-si-agent/SKILL.md +40 -32
  287. package/skills/build-signals-agent/SKILL.md +139 -92
  288. package/skills/call-adcp-agent.previous/SKILL.md +5 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * ProgrammaticSeller — worked example for `sales-non-guaranteed`.
3
+ *
4
+ * Programmatic non-guaranteed is the canonical sync case: buyer hits
5
+ * `create_media_buy`, gets a `media_buy_id` immediately, the SSP queues
6
+ * the line item for serving. Lifecycle changes (`pending_creatives` →
7
+ * `active` once creatives clear review; `active` → `completed` at
8
+ * end_time; pacing-driven `paused` events) flow via `publishStatusChange`.
9
+ *
10
+ * Demonstrates the v2.1 sync-first shape:
11
+ *
12
+ * - Sync `getProducts` (catalog read; no async ceremony).
13
+ * - Sync `createMediaBuy` (returns MediaBuy immediately on commit).
14
+ * - Sync `syncCreatives` (per-creative status; mixed approved/pending in
15
+ * one response — review continues async, status-change fires when
16
+ * review terminal).
17
+ * - `publishStatusChange` for everything that happens *after* the
18
+ * synchronous request returns.
19
+ *
20
+ * @see `docs/proposals/decisioning-platform-v2-hitl-split.md`
21
+ */
22
+
23
+ import {
24
+ AdcpError,
25
+ publishStatusChange,
26
+ type DecisioningPlatform,
27
+ type SalesPlatform,
28
+ type AccountStore,
29
+ } from '@adcp/sdk/server';
30
+ import type { SyncCreativesRow } from '@adcp/sdk/server';
31
+ import type {
32
+ GetProductsRequest,
33
+ GetProductsResponse,
34
+ CreateMediaBuyRequest,
35
+ CreateMediaBuySuccess,
36
+ UpdateMediaBuyRequest,
37
+ UpdateMediaBuySuccess,
38
+ GetMediaBuyDeliveryRequest,
39
+ GetMediaBuyDeliveryResponse,
40
+ CreativeAsset,
41
+ AccountReference,
42
+ } from '@adcp/sdk/types';
43
+
44
+ export interface ProgrammaticConfig {
45
+ /** SSP network identifier. */
46
+ networkId: string;
47
+ /** Floor CPM in USD. */
48
+ floorCpm: number;
49
+ /**
50
+ * Latency (ms) between sync `createMediaBuy` returning and the
51
+ * `pending_creatives` → `active` status-change firing. Demo simulates
52
+ * the time creative review takes after the buy is committed.
53
+ */
54
+ creativeReviewMs: number;
55
+ }
56
+
57
+ interface ProgrammaticMeta {
58
+ network_id: string;
59
+ advertiser_id: string;
60
+ [key: string]: unknown;
61
+ }
62
+
63
+ type ProgrammaticBuy = CreateMediaBuySuccess;
64
+
65
+ export class ProgrammaticSeller implements DecisioningPlatform<ProgrammaticConfig, ProgrammaticMeta> {
66
+ private mediaBuys = new Map<string, ProgrammaticBuy>();
67
+
68
+ capabilities = {
69
+ specialisms: ['sales-non-guaranteed'] as const,
70
+ creative_agents: [{ agent_url: 'https://example.com/programmatic-creative-agent/mcp' }],
71
+ channels: ['display', 'olv'] as const,
72
+ pricingModels: ['cpm'] as const,
73
+ config: {
74
+ networkId: 'NET_42',
75
+ floorCpm: 1.5,
76
+ creativeReviewMs: 60,
77
+ } satisfies ProgrammaticConfig,
78
+ };
79
+
80
+ statusMappers = {};
81
+
82
+ accounts: AccountStore<ProgrammaticMeta> = {
83
+ resolve: async (ref: AccountReference) => {
84
+ const id = 'account_id' in ref ? ref.account_id : 'prog_acc_1';
85
+ return {
86
+ id,
87
+ name: `Programmatic — ${id}`,
88
+ status: 'active',
89
+ operator: 'programmatic.example.com',
90
+ ctx_metadata: { network_id: this.capabilities.config.networkId, advertiser_id: 'adv_42' },
91
+ authInfo: { kind: 'api_key' },
92
+ };
93
+ },
94
+ };
95
+
96
+ sales: SalesPlatform<ProgrammaticMeta> = {
97
+ /** Sync discovery: catalog read; no async ceremony. */
98
+ getProducts: async (_req: GetProductsRequest): Promise<GetProductsResponse> => ({
99
+ products: [
100
+ {
101
+ product_id: 'prod_run_of_network_display',
102
+ name: 'RON Display',
103
+ description: 'Run-of-network display, 300x250 + 728x90',
104
+ format_ids: [{ id: 'display_300x250', agent_url: 'https://example.com/programmatic-creative-agent/mcp' }],
105
+ delivery_type: 'non_guaranteed',
106
+ publisher_properties: [{ publisher_domain: 'programmatic.example.com', selection_type: 'all' }],
107
+ reporting_capabilities: {
108
+ available_reporting_frequencies: ['daily'],
109
+ expected_delay_minutes: 60,
110
+ timezone: 'UTC',
111
+ supports_webhooks: false,
112
+ available_metrics: [],
113
+ date_range_support: 'date_range',
114
+ },
115
+ pricing_options: [
116
+ {
117
+ pricing_option_id: 'cpm_2_50',
118
+ pricing_model: 'cpm',
119
+ fixed_price: 2.5,
120
+ currency: 'USD',
121
+ },
122
+ ],
123
+ },
124
+ {
125
+ product_id: 'prod_premium_video_15s',
126
+ name: 'Premium Video 15s',
127
+ description: 'In-stream video on premium publishers',
128
+ format_ids: [{ id: 'video_15s', agent_url: 'https://example.com/programmatic-creative-agent/mcp' }],
129
+ delivery_type: 'non_guaranteed',
130
+ publisher_properties: [{ publisher_domain: 'programmatic.example.com', selection_type: 'all' }],
131
+ reporting_capabilities: {
132
+ available_reporting_frequencies: ['daily'],
133
+ expected_delay_minutes: 60,
134
+ timezone: 'UTC',
135
+ supports_webhooks: false,
136
+ available_metrics: [],
137
+ date_range_support: 'date_range',
138
+ },
139
+ pricing_options: [
140
+ {
141
+ pricing_option_id: 'cpm_18_00',
142
+ pricing_model: 'cpm',
143
+ fixed_price: 18.0,
144
+ currency: 'USD',
145
+ },
146
+ ],
147
+ },
148
+ ],
149
+ }),
150
+
151
+ /**
152
+ * Sync media-buy creation. Buyer gets media_buy_id immediately; status
153
+ * transitions out of `pending_creatives` flow via publishStatusChange.
154
+ */
155
+ createMediaBuy: async (req: CreateMediaBuyRequest) => {
156
+ const totalBudget =
157
+ typeof req.total_budget === 'number'
158
+ ? req.total_budget
159
+ : ((req.total_budget as { amount?: number })?.amount ?? 0);
160
+ if (totalBudget < this.capabilities.config.floorCpm * 1000) {
161
+ throw new AdcpError('BUDGET_TOO_LOW', {
162
+ recovery: 'correctable',
163
+ message: `total_budget below floor (${this.capabilities.config.floorCpm} CPM × 1000 imp)`,
164
+ field: 'total_budget',
165
+ suggestion: `Raise to at least ${this.capabilities.config.floorCpm * 1000}`,
166
+ });
167
+ }
168
+
169
+ const buyId = `mb_${this.capabilities.config.networkId}_${Date.now()}`;
170
+ const buy: ProgrammaticBuy = {
171
+ media_buy_id: buyId,
172
+ status: 'pending_creatives',
173
+ confirmed_at: new Date().toISOString(),
174
+ revision: 1,
175
+ packages: [],
176
+ };
177
+ this.mediaBuys.set(buyId, buy);
178
+ void totalBudget;
179
+
180
+ // Demo: schedule the pending_creatives → active transition once
181
+ // creative review clears. In production this fires from the SSP's
182
+ // creative-review webhook handler.
183
+ const account = (req as { account?: { account_id?: string } }).account;
184
+ const accountId = account?.account_id ?? 'prog_acc_1';
185
+ setTimeout(() => {
186
+ buy.status = 'active';
187
+ publishStatusChange({
188
+ account_id: accountId,
189
+ resource_type: 'media_buy',
190
+ resource_id: buyId,
191
+ payload: { status: 'active', activated_at: new Date().toISOString() },
192
+ });
193
+ }, this.capabilities.config.creativeReviewMs).unref?.();
194
+
195
+ return buy;
196
+ },
197
+
198
+ updateMediaBuy: async (buyId: string, patch: UpdateMediaBuyRequest): Promise<UpdateMediaBuySuccess> => {
199
+ const existing = this.mediaBuys.get(buyId);
200
+ if (!existing) {
201
+ throw new AdcpError('MEDIA_BUY_NOT_FOUND', {
202
+ recovery: 'terminal',
203
+ message: `media buy ${buyId} not found`,
204
+ field: 'media_buy_id',
205
+ });
206
+ }
207
+ if (patch.paused === true) existing.status = 'paused';
208
+ if (patch.paused === false && existing.status === 'paused') existing.status = 'active';
209
+ return { media_buy_id: existing.media_buy_id, status: existing.status, revision: existing.revision };
210
+ },
211
+
212
+ /**
213
+ * Sync per-creative review with mixed approved/pending rows. Review
214
+ * continues async — the seller's review pipeline pushes status changes
215
+ * via publishStatusChange when each creative reaches terminal state.
216
+ */
217
+ syncCreatives: async (creatives: CreativeAsset[]): Promise<SyncCreativesRow[]> => {
218
+ return creatives.map(c => {
219
+ const id = (c as { creative_id?: string }).creative_id ?? `cr_${Math.random()}`;
220
+ const formatId = (c as { format_id?: { id?: string } }).format_id?.id ?? '';
221
+ const needsReview = formatId.startsWith('video_');
222
+ if (needsReview) {
223
+ // Schedule the pending → approved transition for the demo
224
+ setTimeout(() => {
225
+ publishStatusChange({
226
+ account_id: 'prog_acc_1',
227
+ resource_type: 'creative',
228
+ resource_id: id,
229
+ payload: { status: 'approved', reviewed_at: new Date().toISOString() },
230
+ });
231
+ }, this.capabilities.config.creativeReviewMs).unref?.();
232
+ }
233
+ return {
234
+ creative_id: id,
235
+ action: 'created',
236
+ status: needsReview ? 'pending_review' : 'approved',
237
+ };
238
+ });
239
+ },
240
+
241
+ getMediaBuyDelivery: async (filter: GetMediaBuyDeliveryRequest): Promise<GetMediaBuyDeliveryResponse> => ({
242
+ currency: 'USD',
243
+ reporting_period: {
244
+ start: filter.start_date ?? '2026-04-01',
245
+ end: filter.end_date ?? '2026-04-30',
246
+ },
247
+ media_buy_deliveries: [],
248
+ }),
249
+
250
+ // Required on SalesPlatform — the example doesn't model persistent buys,
251
+ // so return empty array. Production adopters would query their store.
252
+ getMediaBuys: async () => ({ media_buys: [] }),
253
+ };
254
+ }
@@ -16,7 +16,7 @@
16
16
  * npx @adcp/sdk@latest http://localhost:3001/mcp get_signals '{"filters":{"catalog_types":["marketplace"]}}'
17
17
  */
18
18
 
19
- import { createAdcpServer, serve } from '@adcp/sdk';
19
+ import { createAdcpServer, serve } from '@adcp/sdk/server/legacy/v5';
20
20
  import { createIdempotencyStore, memoryBackend } from '@adcp/sdk/server';
21
21
  import type { GetSignalsResponse, ServeContext } from '@adcp/sdk';
22
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcp/sdk",
3
- "version": "5.25.1",
3
+ "version": "6.0.0",
4
4
  "description": "AdCP SDK — client, server, and compliance harnesses for the AdContext Protocol (MCP + A2A)",
5
5
  "workspaces": [
6
6
  ".",
@@ -40,6 +40,11 @@
40
40
  "require": "./dist/lib/testing/index.js",
41
41
  "types": "./dist/lib/testing/index.d.ts"
42
42
  },
43
+ "./testing/personas": {
44
+ "import": "./dist/lib/testing/personas/index.js",
45
+ "require": "./dist/lib/testing/personas/index.js",
46
+ "types": "./dist/lib/testing/personas/index.d.ts"
47
+ },
43
48
  "./auth": {
44
49
  "import": "./dist/lib/auth/index.js",
45
50
  "require": "./dist/lib/auth/index.js",
@@ -50,6 +55,11 @@
50
55
  "require": "./dist/lib/server/index.js",
51
56
  "types": "./dist/lib/server/index.d.ts"
52
57
  },
58
+ "./server/legacy/v5": {
59
+ "import": "./dist/lib/server/legacy/v5/index.js",
60
+ "require": "./dist/lib/server/legacy/v5/index.js",
61
+ "types": "./dist/lib/server/legacy/v5/index.d.ts"
62
+ },
53
63
  "./signing": {
54
64
  "import": "./dist/lib/signing/index.js",
55
65
  "require": "./dist/lib/signing/index.js",
@@ -261,7 +271,8 @@
261
271
  "@a2a-js/sdk": "^0.3.4",
262
272
  "@modelcontextprotocol/sdk": "^1.17.5",
263
273
  "@opentelemetry/api": "^1.0.0",
264
- "pg": "^8.0.0"
274
+ "pg": "^8.0.0",
275
+ "zod": "^4.1.0"
265
276
  },
266
277
  "peerDependenciesMeta": {
267
278
  "@opentelemetry/api": {
@@ -219,7 +219,9 @@ Every AdCP request may include a `context` field. The framework echoes it back o
219
219
  | `serve(() => createAdcpServer(...))` | Start HTTP server on `:3001/mcp` |
220
220
  | `adcpError(code, { message })` | Structured error (BRAND_NOT_FOUND, RIGHTS_UNAVAILABLE, etc.) |
221
221
 
222
- Import: `import { createAdcpServer, serve, adcpError } from '@adcp/sdk';`
222
+ Import: `import { createAdcpServer, serve, adcpError } from '@adcp/sdk/server/legacy/v5';`
223
+
224
+ > **v6 specialism status.** `brandRights` is wired via the v5 `createAdcpServer` handler bag today. A v6 `BrandRightsPlatform` interface ships at `src/lib/server/decisioning/specialisms/brand-rights.ts` but the dispatcher path through `createAdcpServerFromPlatform` is not yet documented for adopters — pin to the legacy subpath until that lands.
223
225
 
224
226
  ## Setup
225
227
 
@@ -255,8 +257,13 @@ Single `.ts` file, one `createAdcpServer` call with a `brandRights` domain group
255
257
  Creative-approval webhooks are implemented as a regular outbound HTTP call — outside the MCP server, after you accept `acquire_rights`.
256
258
 
257
259
  ```typescript
258
- import { createAdcpServer, serve, adcpError } from '@adcp/sdk';
259
- import { createIdempotencyStore, memoryBackend } from '@adcp/sdk/server';
260
+ import {
261
+ createAdcpServer,
262
+ serve,
263
+ adcpError,
264
+ createIdempotencyStore,
265
+ memoryBackend,
266
+ } from '@adcp/sdk/server/legacy/v5';
260
267
 
261
268
  // Idempotency — required for v3. `acquire_rights` is mutating (issues
262
269
  // credentials + may trigger billing); `get_brand_identity` and
@@ -37,7 +37,7 @@ The `interaction_model` in each specialism's `index.yaml` is the forcing functio
37
37
 
38
38
  Full treatment in `skills/build-seller-agent/SKILL.md` §Protocol-Wide Requirements and §Composing. Minimum viable pointers for a creative agent:
39
39
 
40
- - **`idempotency_key`** on every mutating request (`sync_creatives`, `build_creative`, `report_usage`, any `sync_*` you implement). Wire `createIdempotencyStore` into `createAdcpServer({ idempotency })`.
40
+ - **`idempotency_key`** on every mutating request (`sync_creatives`, `build_creative`, `report_usage`, any `sync_*` you implement). Pass `createIdempotencyStore` to `createAdcpServerFromPlatform(platform, { idempotency })`.
41
41
  - **Authentication** via `serve({ authenticate })` with `verifyApiKey`/`verifyBearer` from `@adcp/sdk/server`. Unauthenticated agents fail the universal `security_baseline` storyboard.
42
42
  - **Signature-header transparency**: accept requests with `Signature-Input`/`Signature` headers even if you don't claim `signed-requests`.
43
43
 
@@ -45,7 +45,7 @@ Full treatment in `skills/build-seller-agent/SKILL.md` §Protocol-Wide Requireme
45
45
 
46
46
  Creative review flows are naturally async — `sync_creatives` may return `pending_review` with a task envelope, and your review pipeline emits completion webhooks when the creative is approved, rejected, or transitions to a new state. `build_creative` for the ad-server archetype emits `report_usage` completion webhooks. Use `ctx.emitWebhook` — don't hand-roll `fetch` with HMAC signing.
47
47
 
48
- Wire `createAdcpServer({ webhooks: { signerKey } })` and call `ctx.emitWebhook({ url, payload, operation_id })` from any handler. The framework handles RFC 9421 signing, stable `idempotency_key` across retries, backoff + terminal error handling. Full pattern in [`skills/build-seller-agent/SKILL.md`](../build-seller-agent/SKILL.md) § Webhooks.
48
+ Pass `webhooks: { signerKey }` to `createAdcpServerFromPlatform(platform, { webhooks })` and call `ctx.emitWebhook({ url, payload, operation_id })` from any handler. The framework handles RFC 9421 signing, stable `idempotency_key` across retries, backoff + terminal error handling. Full pattern in [`skills/build-seller-agent/SKILL.md`](../build-seller-agent/SKILL.md) § Webhooks.
49
49
 
50
50
  **`operation_id` rules** (the top at-least-once-delivery bug): stable across retries. `creative_review.${creative_id}` or `report_usage.${report_batch_id}` — NOT a fresh UUID per retry.
51
51
 
@@ -92,7 +92,7 @@ What happens when a creative is synced:
92
92
  >
93
93
  > **Cross-cutting pitfalls matrix runs keep catching:**
94
94
  >
95
- > - **Declare `capabilities: { specialisms: ['creative-ad-server'] }` (or `'creative-template'` / `'creative-generative'`) on `createAdcpServer`.** Value is `string[]` of enum ids (not `[{id, version}]`). Agents that don't declare their specialism fail the grader with "No applicable tracks found" even if every tool works — tracks are gated on the specialism claim.
95
+ > - **Declare `capabilities.specialisms: ['creative-ad-server'] as const` (or `'creative-template'` / `'creative-generative'`) on the `DecisioningPlatform` you pass to `createAdcpServerFromPlatform`.** Value is `string[]` of enum ids (not `[{id, version}]`). Agents that don't declare their specialism fail the grader with "No applicable tracks found" even if every tool works — tracks are gated on the specialism claim.
96
96
  > - `build_creative` response is `{ creative_manifest: { format_id, assets } }` (single) or `{ creative_manifests: [...] }` (multi). Platform-native fields at the top level (`tag_url`, `creative_id`, `media_type`) are **invalid** — use `buildCreativeResponse({ creative_manifest })` / `buildCreativeMultiResponse({ creative_manifests })` from `@adcp/sdk/server` to lock the shape at compile time.
97
97
  > - Each asset in `creative_manifest.assets` requires an `asset_type` discriminator. Use the typed factories (`imageAsset`, `videoAsset`, `audioAsset`, `htmlAsset`, `urlAsset`, `textAsset`) so the discriminator is injected for you; a plain `{ serving_tag: { content: '<vast>...' } }` fails validation.
98
98
  > - `preview_creative` renders have the same pattern — each `renders[]` entry is a oneOf on `output_format`. Use `urlRender({...})`, `htmlRender({...})`, or `bothRender({...})` to inject the discriminator and require the matching `preview_url` / `preview_html` field automatically.
@@ -102,14 +102,14 @@ What happens when a creative is synced:
102
102
 
103
103
  **Handler bindings — read the Contract column entry before writing each return:**
104
104
 
105
- | Tool | Handler | Contract (field list) | Gotchas |
106
- | ----------------------- | ------------------------------ | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
- | `get_adcp_capabilities` | auto-generated | n/a | Do not register manually. |
108
- | `list_creative_formats` | `creative.listCreativeFormats` | [`#list_creative_formats`](../../docs/llms.txt#list_creative_formats) | Each `renders[]` entry MUST have `role` + exactly one of `dimensions` (object) OR `parameters_from_format_id: true`. `{width, height}` shorthand fails — wrap in `dimensions`. |
109
- | `sync_creatives` | `creative.syncCreatives` | [`#sync_creatives`](../../docs/llms.txt#sync_creatives) | Echo `creative_id`; `action` ∈ `created \| updated \| unchanged \| failed \| deleted`. |
110
- | `list_creatives` | `creative.listCreatives` | [`#list_creatives`](../../docs/llms.txt#list_creatives) | Honor `args.filters?.format_ids` when present. `created_date` + `updated_date` on each row are required ISO timestamps. |
105
+ | Tool | Handler | Contract (field list) | Gotchas |
106
+ | ----------------------- | ------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
107
+ | `get_adcp_capabilities` | auto-generated | n/a | Do not register manually. |
108
+ | `list_creative_formats` | `creative.listCreativeFormats` | [`#list_creative_formats`](../../docs/llms.txt#list_creative_formats) | Each `renders[]` entry MUST have `role` + exactly one of `dimensions` (object) OR `parameters_from_format_id: true`. `{width, height}` shorthand fails — wrap in `dimensions`. |
109
+ | `sync_creatives` | `creative.syncCreatives` | [`#sync_creatives`](../../docs/llms.txt#sync_creatives) | Echo `creative_id`; `action` ∈ `created \| updated \| unchanged \| failed \| deleted`. |
110
+ | `list_creatives` | `creative.listCreatives` | [`#list_creatives`](../../docs/llms.txt#list_creatives) | Honor `args.filters?.format_ids` when present. `created_date` + `updated_date` on each row are required ISO timestamps. |
111
111
  | `preview_creative` | `creative.previewCreative` | [`#preview_creative`](../../docs/llms.txt#preview_creative) | `renders[].output_format` is a discriminator — use `urlRender({...})`, `htmlRender({...})`, or `bothRender({...})` so the discriminator is injected and the required `preview_url`/`preview_html` field is enforced at compile time. |
112
- | `build_creative` | `creative.buildCreative` | [`#build_creative`](../../docs/llms.txt#build_creative) | Check `args.target_format_id` → library lookup; fall back to `args.creative_id`. Response requires `creative_manifest.format_id` + `creative_manifest.assets`. |
112
+ | `build_creative` | `creative.buildCreative` | [`#build_creative`](../../docs/llms.txt#build_creative) | Check `args.target_format_id` → library lookup; fall back to `args.creative_id`. Response requires `creative_manifest.format_id` + `creative_manifest.assets`. |
113
113
 
114
114
  Asset values use type-specific shapes, not a generic `asset_type` discriminator:
115
115
 
@@ -121,7 +121,7 @@ Asset values use type-specific shapes, not a generic `asset_type` discriminator:
121
121
 
122
122
  ### Context and Ext Passthrough
123
123
 
124
- `createAdcpServer` auto-echoes the request's `context` into every response from domain-grouped handlers — **do not set `context` yourself in your handler return values.** The framework injects it post-handler only when the field isn't already present.
124
+ The framework auto-echoes the request's `context` into every response from typed sub-platform handlers — **do not set `context` yourself in your handler return values.** It's injected post-handler only when the field isn't already present.
125
125
 
126
126
  **Crucial:** `context` is schema-typed as an object. If your handler hand-sets a string or narrative description, validation fails with `/context: must be object` and the framework does not overwrite. Leave the field out entirely.
127
127
 
@@ -129,22 +129,23 @@ Some schemas also define an `ext` field for vendor-namespaced extensions. If you
129
129
 
130
130
  ## SDK Quick Reference
131
131
 
132
- | SDK piece | Usage |
133
- | ------------------------------------------------------------------- | ------------------------------------------------------------------------- |
134
- | `createAdcpServer(config)` | Create server with domain-grouped handlers and auto-capabilities |
135
- | `serve(() => createAdcpServer(config))` | Start HTTP server on `:3001/mcp` |
136
- | `creative: { listCreativeFormats, syncCreatives, ... }` | Domain group register handlers by name |
137
- | `ctx.store.put(collection, id, data)` | Persist state (creative library) across requests |
138
- | `ctx.store.get(collection, id)` | Retrieve persisted state |
139
- | `ctx.store.list(collection)` | List all items in a collection (for `list_creatives`) |
140
- | `listCreativeFormatsResponse(data)` | Auto-applied response builder (don't call manually) |
141
- | `syncCreativesResponse(data)` | Auto-applied response builder (don't call manually) |
142
- | `listCreativesResponse(data)` | Auto-applied response builder (don't call manually) |
143
- | `buildCreativeResponse(data)` | Auto-applied response builder (don't call manually) |
144
- | `previewCreativeResponse(data)` | Auto-applied response builder (don't call manually) |
145
- | `adcpError(code, { message })` | Structured error |
146
-
147
- Import: `import { createAdcpServer, serve, adcpError } from '@adcp/sdk';`
132
+ | SDK piece | Usage |
133
+ | ------------------------------------------------------- | ---------------------------------------------------------------- |
134
+ | `createAdcpServerFromPlatform(platform, opts)` | Create server from a typed `DecisioningPlatform` — compile-time specialism enforcement, auto-capabilities |
135
+ | `createAdcpServer(config)` *(legacy)* | v5 handler-bag entry. Mid-migration / escape-hatch only; reach via `@adcp/sdk/server/legacy/v5` |
136
+ | `serve(() => createAdcpServerFromPlatform(platform, opts))` | Start HTTP server on `:3001/mcp` |
137
+ | `creative: { listCreativeFormats, syncCreatives, ... }` | Domain group register handlers by name |
138
+ | `ctx.store.put(collection, id, data)` | Persist state (creative library) across requests |
139
+ | `ctx.store.get(collection, id)` | Retrieve persisted state |
140
+ | `ctx.store.list(collection)` | List all items in a collection (for `list_creatives`) |
141
+ | `listCreativeFormatsResponse(data)` | Auto-applied response builder (don't call manually) |
142
+ | `syncCreativesResponse(data)` | Auto-applied response builder (don't call manually) |
143
+ | `listCreativesResponse(data)` | Auto-applied response builder (don't call manually) |
144
+ | `buildCreativeResponse(data)` | Auto-applied response builder (don't call manually) |
145
+ | `previewCreativeResponse(data)` | Auto-applied response builder (don't call manually) |
146
+ | `adcpError(code, { message })` | Structured error |
147
+
148
+ Import: `import { createAdcpServerFromPlatform, serve, adcpError } from '@adcp/sdk/server';`
148
149
 
149
150
  ## Setup
150
151
 
@@ -174,7 +175,7 @@ Minimal `tsconfig.json`:
174
175
  ## Implementation
175
176
 
176
177
  1. Single `.ts` file — all tools in one file
177
- 2. Use `createAdcpServer` with a `creative` domain group — `get_adcp_capabilities` is auto-generated
178
+ 2. Use `createAdcpServerFromPlatform` with `creative: CreativeAdServerPlatform` (or `CreativeBuilderPlatform`) on a `DecisioningPlatform` class — `get_adcp_capabilities` is auto-generated
178
179
  3. Handlers return raw data objects — response builders are auto-applied
179
180
  4. Use `ctx.store` for persisting the creative library across requests (InMemoryStateStore by default)
180
181
  5. Register `preview_creative` manually on the returned server (union schema not in domain group)
@@ -182,8 +183,17 @@ Minimal `tsconfig.json`:
182
183
  7. Context passthrough is handled by the framework — no need to manually echo `args.context`
183
184
 
184
185
  ```typescript
185
- import { createAdcpServer, serve, adcpError, urlRender } from '@adcp/sdk';
186
- import { createIdempotencyStore, memoryBackend } from '@adcp/sdk/server';
186
+ import {
187
+ createAdcpServerFromPlatform,
188
+ serve,
189
+ adcpError,
190
+ urlRender,
191
+ createIdempotencyStore,
192
+ memoryBackend,
193
+ type DecisioningPlatform,
194
+ type CreativeAdServerPlatform,
195
+ type AccountStore,
196
+ } from '@adcp/sdk/server';
187
197
 
188
198
  const formats = [
189
199
  {
@@ -218,18 +228,24 @@ const idempotency = createIdempotencyStore({
218
228
  ttlSeconds: 86400, // 24 hours (spec bounds: 1h–7d)
219
229
  });
220
230
 
221
- serve(() => createAdcpServer({
222
- name: 'My Creative Agent',
223
- version: '1.0.0',
224
- idempotency,
231
+ class MyCreative implements DecisioningPlatform {
232
+ capabilities = {
233
+ specialisms: ['creative-ad-server'] as const,
234
+ config: {},
235
+ };
225
236
 
226
- // Principal scoping for idempotency. MUST never return undefined —
227
- // every mutating request would reject as SERVICE_UNAVAILABLE. A
228
- // constant works for a demo; use ctx.account for multi-tenant prod.
229
- resolveSessionKey: () => 'default-principal',
237
+ accounts: AccountStore = {
238
+ resolve: async ref => ({
239
+ id: 'account_id' in ref ? ref.account_id : 'cr_acc_1',
240
+ operator: 'me',
241
+ ctx_metadata: {},
242
+ }),
243
+ upsert: async () => ({ ok: true, items: [] }),
244
+ list: async () => ({ items: [], nextCursor: null }),
245
+ };
230
246
 
231
- creative: {
232
- listCreativeFormats: async (params, ctx) => {
247
+ creative: CreativeAdServerPlatform = {
248
+ listCreativeFormats: async (params, ctx) => {
233
249
  return { formats };
234
250
  },
235
251
 
@@ -288,28 +304,41 @@ serve(() => createAdcpServer({
288
304
  };
289
305
  },
290
306
 
291
- previewCreative: async (params) => {
292
- return {
293
- response_type: 'single',
294
- previews: [
295
- {
296
- preview_id: `prev_${Date.now()}`,
297
- input: { name: params.creative_manifest?.name ?? 'Preview' },
298
- renders: [
299
- urlRender({
300
- render_id: `r_${Date.now()}`,
301
- preview_url: 'https://example.com/preview.png',
302
- role: 'primary',
303
- dimensions: { width: 300, height: 250 },
304
- }),
305
- ],
306
- },
307
- ],
308
- expires_at: new Date(Date.now() + 3600000).toISOString(),
309
- };
310
- },
307
+ previewCreative: async params => {
308
+ return {
309
+ response_type: 'single',
310
+ previews: [
311
+ {
312
+ preview_id: `prev_${Date.now()}`,
313
+ input: { name: params.creative_manifest?.name ?? 'Preview' },
314
+ renders: [
315
+ urlRender({
316
+ render_id: `r_${Date.now()}`,
317
+ preview_url: 'https://example.com/preview.png',
318
+ role: 'primary',
319
+ dimensions: { width: 300, height: 250 },
320
+ }),
321
+ ],
322
+ },
323
+ ],
324
+ expires_at: new Date(Date.now() + 3600000).toISOString(),
325
+ };
311
326
  },
312
- }));
327
+ };
328
+ }
329
+
330
+ const platform = new MyCreative();
331
+
332
+ serve(() =>
333
+ createAdcpServerFromPlatform(platform, {
334
+ name: 'My Creative Agent',
335
+ version: '1.0.0',
336
+ idempotency,
337
+ // Principal scoping for idempotency. MUST never return undefined —
338
+ // every mutating request would reject as SERVICE_UNAVAILABLE.
339
+ resolveSessionKey: () => 'default-principal',
340
+ })
341
+ );
313
342
  ```
314
343
 
315
344
  ### Key implementation detail: creative library
@@ -511,9 +540,10 @@ Common failure decoder:
511
540
 
512
541
  | Mistake | Fix |
513
542
  | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
514
- | Using `createTaskCapableServer` + `server.tool()` | Use `createAdcpServer` with `creative` domain group |
515
- | Manually registering `get_adcp_capabilities` | Auto-generated by `createAdcpServer` from registered handlers |
516
- | Calling `server.registerTool('preview_creative', ...)` | `AdcpServer` does not expose `registerTool` — put `previewCreative` in the `creative:` domain group like the other handlers |
543
+ | Using `createTaskCapableServer` + `server.tool()` | Use `createAdcpServerFromPlatform` with a typed `creative: CreativeAdServerPlatform` (or `CreativeBuilderPlatform`) field |
544
+ | Calling `createAdcpServer` directly in new code | Reach for `createAdcpServerFromPlatform`; `createAdcpServer` lives at `@adcp/sdk/server/legacy/v5` for mid-migration / escape-hatch only |
545
+ | Manually registering `get_adcp_capabilities` | Auto-generated by `createAdcpServerFromPlatform` from your typed `DecisioningPlatform` — do not register it |
546
+ | Calling `server.registerTool('preview_creative', ...)` | `AdcpServer` does not expose `registerTool` — put `previewCreative` in the `creative:` domain group like the other handlers |
517
547
  | Using module-level Maps for state | Use `ctx.store.put/get/list` — framework provides `InMemoryStateStore` by default |
518
548
  | Calling response builders manually in domain handlers | Handlers return raw data — response builders are auto-applied across the `creative:` group, including `preview_creative` |
519
549
  | `list_creatives` ignores format filter | Check `args.filters?.format_ids` and filter results |