@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.
- package/README.md +45 -7
- package/dist/lib/compliance-fixtures/index.d.ts +1 -1
- package/dist/lib/compliance-fixtures/index.js +1 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +15 -0
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts +7 -0
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +9 -2
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +7 -8
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/schemas/index.d.ts +1 -1
- package/dist/lib/schemas/index.js +1 -1
- package/dist/lib/server/create-adcp-server.d.ts +129 -11
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +112 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.d.ts +27 -0
- package/dist/lib/server/ctx-metadata/backends/memory.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/memory.js +72 -0
- package/dist/lib/server/ctx-metadata/backends/memory.js.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/pg.d.ts +62 -0
- package/dist/lib/server/ctx-metadata/backends/pg.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/backends/pg.js +145 -0
- package/dist/lib/server/ctx-metadata/backends/pg.js.map +1 -0
- package/dist/lib/server/ctx-metadata/index.d.ts +15 -0
- package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/index.js +28 -0
- package/dist/lib/server/ctx-metadata/index.js.map +1 -0
- package/dist/lib/server/ctx-metadata/store.d.ts +177 -0
- package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/store.js +327 -0
- package/dist/lib/server/ctx-metadata/store.js.map +1 -0
- package/dist/lib/server/ctx-metadata/wire-shape.d.ts +55 -0
- package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -0
- package/dist/lib/server/ctx-metadata/wire-shape.js +121 -0
- package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -0
- package/dist/lib/server/decisioning/account.d.ts +309 -0
- package/dist/lib/server/decisioning/account.d.ts.map +1 -0
- package/dist/lib/server/decisioning/account.js +102 -0
- package/dist/lib/server/decisioning/account.js.map +1 -0
- package/dist/lib/server/decisioning/admin-router.d.ts +75 -0
- package/dist/lib/server/decisioning/admin-router.d.ts.map +1 -0
- package/dist/lib/server/decisioning/admin-router.js +120 -0
- package/dist/lib/server/decisioning/admin-router.js.map +1 -0
- package/dist/lib/server/decisioning/assembly-helpers.d.ts +204 -0
- package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/assembly-helpers.js +173 -0
- package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts +154 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -0
- package/dist/lib/server/decisioning/async-outcome.js +239 -0
- package/dist/lib/server/decisioning/async-outcome.js.map +1 -0
- package/dist/lib/server/decisioning/capabilities.d.ts +251 -0
- package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -0
- package/dist/lib/server/decisioning/capabilities.js +16 -0
- package/dist/lib/server/decisioning/capabilities.js.map +1 -0
- package/dist/lib/server/decisioning/context.d.ts +212 -0
- package/dist/lib/server/decisioning/context.d.ts.map +1 -0
- package/dist/lib/server/decisioning/context.js +26 -0
- package/dist/lib/server/decisioning/context.js.map +1 -0
- package/dist/lib/server/decisioning/errors-typed.d.ts +104 -0
- package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -0
- package/dist/lib/server/decisioning/errors-typed.js +304 -0
- package/dist/lib/server/decisioning/errors-typed.js.map +1 -0
- package/dist/lib/server/decisioning/helpers.d.ts +131 -0
- package/dist/lib/server/decisioning/helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/helpers.js +134 -0
- package/dist/lib/server/decisioning/helpers.js.map +1 -0
- package/dist/lib/server/decisioning/index.d.ts +46 -0
- package/dist/lib/server/decisioning/index.d.ts.map +1 -0
- package/dist/lib/server/decisioning/index.js +120 -0
- package/dist/lib/server/decisioning/index.js.map +1 -0
- package/dist/lib/server/decisioning/list-helpers.d.ts +53 -0
- package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/list-helpers.js +96 -0
- package/dist/lib/server/decisioning/list-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/manifest-helpers.d.ts +56 -0
- package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/manifest-helpers.js +78 -0
- package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -0
- package/dist/lib/server/decisioning/pagination.d.ts +21 -0
- package/dist/lib/server/decisioning/pagination.d.ts.map +1 -0
- package/dist/lib/server/decisioning/pagination.js +12 -0
- package/dist/lib/server/decisioning/pagination.js.map +1 -0
- package/dist/lib/server/decisioning/platform.d.ts +188 -0
- package/dist/lib/server/decisioning/platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/platform.js +19 -0
- package/dist/lib/server/decisioning/platform.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +510 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +2196 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +114 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +247 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts +32 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +127 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +105 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/task-registry.js +96 -0
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/to-context.d.ts +54 -0
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/to-context.js +166 -0
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +20 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.js +93 -0
- package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/audiences.d.ts +72 -0
- package/dist/lib/server/decisioning/specialisms/audiences.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/audiences.js +15 -0
- package/dist/lib/server/decisioning/specialisms/audiences.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +92 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.js +28 -0
- package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts +67 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.js +31 -0
- package/dist/lib/server/decisioning/specialisms/campaign-governance.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +78 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.js +35 -0
- package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +81 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js +28 -0
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +144 -0
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/creative.js +19 -0
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/lists.d.ts +61 -0
- package/dist/lib/server/decisioning/specialisms/lists.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/lists.js +30 -0
- package/dist/lib/server/decisioning/specialisms/lists.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +163 -0
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/sales.js +64 -0
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -0
- package/dist/lib/server/decisioning/specialisms/signals.d.ts +64 -0
- package/dist/lib/server/decisioning/specialisms/signals.d.ts.map +1 -0
- package/dist/lib/server/decisioning/specialisms/signals.js +28 -0
- package/dist/lib/server/decisioning/specialisms/signals.js.map +1 -0
- package/dist/lib/server/decisioning/start-time.d.ts +76 -0
- package/dist/lib/server/decisioning/start-time.d.ts.map +1 -0
- package/dist/lib/server/decisioning/start-time.js +81 -0
- package/dist/lib/server/decisioning/start-time.js.map +1 -0
- package/dist/lib/server/decisioning/status-changes.d.ts +165 -0
- package/dist/lib/server/decisioning/status-changes.d.ts.map +1 -0
- package/dist/lib/server/decisioning/status-changes.js +131 -0
- package/dist/lib/server/decisioning/status-changes.js.map +1 -0
- package/dist/lib/server/decisioning/status-mappers.d.ts +46 -0
- package/dist/lib/server/decisioning/status-mappers.d.ts.map +1 -0
- package/dist/lib/server/decisioning/status-mappers.js +46 -0
- package/dist/lib/server/decisioning/status-mappers.js.map +1 -0
- package/dist/lib/server/decisioning/tenant-registry.d.ts +289 -0
- package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -0
- package/dist/lib/server/decisioning/tenant-registry.js +503 -0
- package/dist/lib/server/decisioning/tenant-registry.js.map +1 -0
- package/dist/lib/server/express-adapter.d.ts +1 -1
- package/dist/lib/server/express-adapter.js +1 -1
- package/dist/lib/server/governance.d.ts +1 -1
- package/dist/lib/server/governance.js +1 -1
- package/dist/lib/server/idempotency/store.d.ts +1 -1
- package/dist/lib/server/idempotency/store.js +1 -1
- package/dist/lib/server/index.d.ts +9 -2
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +79 -4
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +38 -0
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -0
- package/dist/lib/server/legacy/v5/index.js +60 -0
- package/dist/lib/server/legacy/v5/index.js.map +1 -0
- package/dist/lib/server/normalize-errors.d.ts +88 -0
- package/dist/lib/server/normalize-errors.d.ts.map +1 -0
- package/dist/lib/server/normalize-errors.js +146 -0
- package/dist/lib/server/normalize-errors.js.map +1 -0
- package/dist/lib/server/pick-safe-details.d.ts +90 -0
- package/dist/lib/server/pick-safe-details.d.ts.map +1 -0
- package/dist/lib/server/pick-safe-details.js +148 -0
- package/dist/lib/server/pick-safe-details.js.map +1 -0
- package/dist/lib/server/postgres-state-store.d.ts +1 -1
- package/dist/lib/server/postgres-state-store.js +1 -1
- package/dist/lib/server/responses.d.ts +38 -0
- package/dist/lib/server/responses.d.ts.map +1 -1
- package/dist/lib/server/responses.js +38 -0
- package/dist/lib/server/responses.js.map +1 -1
- package/dist/lib/server/state-store.d.ts +1 -1
- package/dist/lib/server/state-store.js +1 -1
- package/dist/lib/server/test-controller.d.ts +10 -3
- package/dist/lib/server/test-controller.d.ts.map +1 -1
- package/dist/lib/server/test-controller.js +10 -3
- package/dist/lib/server/test-controller.js.map +1 -1
- package/dist/lib/testing/comply-controller.d.ts +47 -1
- package/dist/lib/testing/comply-controller.d.ts.map +1 -1
- package/dist/lib/testing/comply-controller.js +11 -4
- package/dist/lib/testing/comply-controller.js.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/personas/index.d.ts +143 -0
- package/dist/lib/testing/personas/index.d.ts.map +1 -0
- package/dist/lib/testing/personas/index.js +190 -0
- package/dist/lib/testing/personas/index.js.map +1 -0
- package/dist/lib/testing/storyboard/index.d.ts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js +3 -2
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts +13 -0
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +179 -7
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/types/asset-instances.d.ts +1 -0
- package/dist/lib/types/asset-instances.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +203 -98
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/schemas.generated.d.ts +599 -159
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +175 -94
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +315 -46
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.d.ts +1 -1
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +6 -0
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/dist/lib/validation/schema-validator.d.ts +13 -0
- package/dist/lib/validation/schema-validator.d.ts.map +1 -1
- package/dist/lib/validation/schema-validator.js +240 -3
- package/dist/lib/validation/schema-validator.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +30 -5
- package/docs/llms.txt +28 -17
- package/examples/README.md +3 -1
- package/examples/decisioning-platform-broadcast-tv.ts +300 -0
- package/examples/decisioning-platform-identity-graph.ts +214 -0
- package/examples/decisioning-platform-mock-seller.ts +332 -0
- package/examples/decisioning-platform-multi-tenant.ts +128 -0
- package/examples/decisioning-platform-programmatic.ts +254 -0
- package/examples/signals-agent.ts +1 -1
- package/package.json +13 -2
- package/skills/build-brand-rights-agent/SKILL.md +10 -3
- package/skills/build-creative-agent/SKILL.md +94 -64
- package/skills/build-decisioning-creative-template/SKILL.md +554 -0
- package/skills/build-decisioning-platform/SKILL.md +304 -0
- package/skills/build-decisioning-platform/advanced/BRAND-RIGHTS.md +25 -0
- package/skills/build-decisioning-platform/advanced/COMPLIANCE.md +23 -0
- package/skills/build-decisioning-platform/advanced/GOVERNANCE.md +24 -0
- package/skills/build-decisioning-platform/advanced/HITL.md +34 -0
- package/skills/build-decisioning-platform/advanced/IDEMPOTENCY.md +52 -0
- package/skills/build-decisioning-platform/advanced/MULTI-TENANT.md +47 -0
- package/skills/build-decisioning-platform/advanced/OAUTH.md +22 -0
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +991 -0
- package/skills/build-decisioning-platform/advanced/SANDBOX.md +24 -0
- package/skills/build-decisioning-platform/advanced/STATE-MACHINE.md +52 -0
- package/skills/build-decisioning-signal-marketplace/SKILL.md +269 -0
- package/skills/build-generative-seller-agent/SKILL.md +89 -53
- package/skills/build-governance-agent/SKILL.md +76 -45
- package/skills/build-retail-media-agent/SKILL.md +87 -62
- package/skills/build-seller-agent/SKILL.md +384 -255
- package/skills/build-seller-agent/deployment.md +5 -3
- package/skills/build-seller-agent/specialisms/audience-sync.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-broadcast-tv.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-guaranteed.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-proposal-mode.md +0 -2
- package/skills/build-seller-agent/specialisms/sales-social.md +0 -2
- package/skills/build-seller-agent/specialisms/signed-requests.md +0 -2
- package/skills/build-si-agent/SKILL.md +40 -32
- package/skills/build-signals-agent/SKILL.md +139 -92
- 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": "
|
|
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 {
|
|
259
|
-
|
|
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).
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
133
|
-
|
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `ctx.store.
|
|
139
|
-
| `ctx.store.
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
|
|
147
|
-
|
|
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 `
|
|
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 {
|
|
186
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
231
|
+
class MyCreative implements DecisioningPlatform {
|
|
232
|
+
capabilities = {
|
|
233
|
+
specialisms: ['creative-ad-server'] as const,
|
|
234
|
+
config: {},
|
|
235
|
+
};
|
|
225
236
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
232
|
-
|
|
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
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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 `
|
|
515
|
-
|
|
|
516
|
-
|
|
|
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 |
|