@adcp/client 4.8.0 → 4.10.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/bin/adcp.js +346 -0
- package/dist/lib/adapters/governance-adapter.d.ts +88 -0
- package/dist/lib/adapters/governance-adapter.d.ts.map +1 -0
- package/dist/lib/adapters/governance-adapter.js +96 -0
- package/dist/lib/adapters/governance-adapter.js.map +1 -0
- package/dist/lib/adapters/index.d.ts +1 -0
- package/dist/lib/adapters/index.d.ts.map +1 -1
- package/dist/lib/adapters/index.js +7 -1
- package/dist/lib/adapters/index.js.map +1 -1
- package/dist/lib/agents/index.generated.d.ts +33 -1
- package/dist/lib/agents/index.generated.d.ts.map +1 -1
- package/dist/lib/agents/index.generated.js +48 -0
- package/dist/lib/agents/index.generated.js.map +1 -1
- package/dist/lib/core/AgentClient.d.ts +92 -1
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/AgentClient.js +237 -0
- package/dist/lib/core/AgentClient.js.map +1 -1
- package/dist/lib/core/AsyncHandler.d.ts +19 -2
- package/dist/lib/core/AsyncHandler.d.ts.map +1 -1
- package/dist/lib/core/AsyncHandler.js.map +1 -1
- package/dist/lib/core/ConversationTypes.d.ts +8 -2
- package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.d.ts +86 -0
- package/dist/lib/core/GovernanceMiddleware.d.ts.map +1 -0
- package/dist/lib/core/GovernanceMiddleware.js +289 -0
- package/dist/lib/core/GovernanceMiddleware.js.map +1 -0
- package/dist/lib/core/GovernanceTypes.d.ts +118 -0
- package/dist/lib/core/GovernanceTypes.d.ts.map +1 -0
- package/dist/lib/core/GovernanceTypes.js +69 -0
- package/dist/lib/core/GovernanceTypes.js.map +1 -0
- package/dist/lib/core/SingleAgentClient.d.ts +103 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +151 -0
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts +10 -0
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +95 -10
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/index.d.ts +6 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +22 -4
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/observability/index.d.ts +8 -0
- package/dist/lib/observability/index.d.ts.map +1 -0
- package/dist/lib/observability/index.js +17 -0
- package/dist/lib/observability/index.js.map +1 -0
- package/dist/lib/observability/tracing.d.ts +42 -0
- package/dist/lib/observability/tracing.d.ts.map +1 -0
- package/dist/lib/observability/tracing.js +126 -0
- package/dist/lib/observability/tracing.js.map +1 -0
- package/dist/lib/protocols/a2a.d.ts.map +1 -1
- package/dist/lib/protocols/a2a.js +16 -1
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +37 -29
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +21 -1
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/registry/types.generated.d.ts +754 -5
- package/dist/lib/registry/types.generated.d.ts.map +1 -1
- package/dist/lib/registry/types.generated.js +1 -1
- package/dist/lib/testing/agent-tester.d.ts +1 -1
- package/dist/lib/testing/agent-tester.d.ts.map +1 -1
- package/dist/lib/testing/agent-tester.js +36 -11
- package/dist/lib/testing/agent-tester.js.map +1 -1
- package/dist/lib/testing/client.d.ts +6 -1
- package/dist/lib/testing/client.d.ts.map +1 -1
- package/dist/lib/testing/client.js +36 -19
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/compliance/briefs.d.ts +12 -0
- package/dist/lib/testing/compliance/briefs.d.ts.map +1 -0
- package/dist/lib/testing/compliance/briefs.js +157 -0
- package/dist/lib/testing/compliance/briefs.js.map +1 -0
- package/dist/lib/testing/compliance/comply.d.ts +26 -0
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -0
- package/dist/lib/testing/compliance/comply.js +540 -0
- package/dist/lib/testing/compliance/comply.js.map +1 -0
- package/dist/lib/testing/compliance/convince.d.ts +27 -0
- package/dist/lib/testing/compliance/convince.d.ts.map +1 -0
- package/dist/lib/testing/compliance/convince.js +418 -0
- package/dist/lib/testing/compliance/convince.js.map +1 -0
- package/dist/lib/testing/compliance/index.d.ts +13 -0
- package/dist/lib/testing/compliance/index.d.ts.map +1 -0
- package/dist/lib/testing/compliance/index.js +22 -0
- package/dist/lib/testing/compliance/index.js.map +1 -0
- package/dist/lib/testing/compliance/types.d.ts +123 -0
- package/dist/lib/testing/compliance/types.d.ts.map +1 -0
- package/dist/lib/testing/compliance/types.js +9 -0
- package/dist/lib/testing/compliance/types.js.map +1 -0
- package/dist/lib/testing/index.d.ts +1 -0
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js +15 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/orchestrator.d.ts +0 -2
- package/dist/lib/testing/orchestrator.d.ts.map +1 -1
- package/dist/lib/testing/orchestrator.js +14 -3
- package/dist/lib/testing/orchestrator.js.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.js +70 -9
- package/dist/lib/testing/scenarios/capabilities.js.map +1 -1
- package/dist/lib/testing/scenarios/creative.d.ts +14 -0
- package/dist/lib/testing/scenarios/creative.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/creative.js +261 -55
- package/dist/lib/testing/scenarios/creative.js.map +1 -1
- package/dist/lib/testing/scenarios/discovery.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/discovery.js +7 -5
- package/dist/lib/testing/scenarios/discovery.js.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.js +90 -112
- package/dist/lib/testing/scenarios/edge-cases.js.map +1 -1
- package/dist/lib/testing/scenarios/governance.d.ts +48 -0
- package/dist/lib/testing/scenarios/governance.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/governance.js +725 -39
- package/dist/lib/testing/scenarios/governance.js.map +1 -1
- package/dist/lib/testing/scenarios/index.d.ts +3 -3
- package/dist/lib/testing/scenarios/index.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/index.js +8 -1
- package/dist/lib/testing/scenarios/index.js.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.d.ts +14 -5
- package/dist/lib/testing/scenarios/media-buy.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.js +358 -63
- package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.js +26 -22
- package/dist/lib/testing/scenarios/schema-compliance.js.map +1 -1
- package/dist/lib/testing/scenarios/signals.d.ts +4 -8
- package/dist/lib/testing/scenarios/signals.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/signals.js +17 -59
- package/dist/lib/testing/scenarios/signals.js.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.js +23 -19
- package/dist/lib/testing/scenarios/sponsored-intelligence.js.map +1 -1
- package/dist/lib/testing/types.d.ts +3 -2
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/types/core.generated.d.ts +629 -5
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js +1 -1
- package/dist/lib/types/schemas.generated.d.ts +13059 -11101
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +573 -107
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/tools.generated.d.ts +1827 -360
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.d.ts +17 -2
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +26 -2
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/package.json +13 -3
|
@@ -16,6 +16,7 @@ exports.testCreateMediaBuy = testCreateMediaBuy;
|
|
|
16
16
|
exports.testFullSalesFlow = testFullSalesFlow;
|
|
17
17
|
exports.testCreativeSync = testCreativeSync;
|
|
18
18
|
exports.testCreativeInline = testCreativeInline;
|
|
19
|
+
exports.testCreativeReference = testCreativeReference;
|
|
19
20
|
exports.resolveAccountForAudiences = resolveAccountForAudiences;
|
|
20
21
|
exports.testSyncAudiences = testSyncAudiences;
|
|
21
22
|
const client_1 = require("../client");
|
|
@@ -27,11 +28,11 @@ function selectProduct(products, options) {
|
|
|
27
28
|
// If channels specified, filter to matching products
|
|
28
29
|
let candidates = products;
|
|
29
30
|
if (options.channels?.length) {
|
|
30
|
-
candidates = products.filter(p => p.channels?.some(
|
|
31
|
+
candidates = products.filter(p => p.channels?.some(ch => options.channels.includes(ch)));
|
|
31
32
|
}
|
|
32
33
|
// If pricing models specified, filter further
|
|
33
34
|
if (options.pricing_models?.length) {
|
|
34
|
-
candidates = candidates.filter(p => p.pricing_options?.some((po) => options.pricing_models.includes(po.
|
|
35
|
+
candidates = candidates.filter(p => p.pricing_options?.some((po) => options.pricing_models.includes(po.pricing_model)));
|
|
35
36
|
}
|
|
36
37
|
// Return first matching or first product
|
|
37
38
|
return candidates[0] || products[0] || null;
|
|
@@ -42,7 +43,7 @@ function selectProduct(products, options) {
|
|
|
42
43
|
function selectPricingOption(product, preferredModels) {
|
|
43
44
|
const options = product.pricing_options || [];
|
|
44
45
|
if (preferredModels?.length) {
|
|
45
|
-
const preferred = options.find((po) => preferredModels.includes(po.
|
|
46
|
+
const preferred = options.find((po) => preferredModels.includes(po.pricing_model));
|
|
46
47
|
if (preferred)
|
|
47
48
|
return preferred;
|
|
48
49
|
}
|
|
@@ -52,11 +53,13 @@ function selectPricingOption(product, preferredModels) {
|
|
|
52
53
|
* Build a create_media_buy request
|
|
53
54
|
*/
|
|
54
55
|
function buildCreateMediaBuyRequest(product, pricingOption, options, extras = {}) {
|
|
55
|
-
const
|
|
56
|
+
const minSpend = pricingOption.min_spend_per_package || 0;
|
|
57
|
+
const budget = options.budget || Math.max(1000, minSpend);
|
|
56
58
|
const now = new Date();
|
|
57
59
|
const startTime = new Date(now.getTime() + 24 * 60 * 60 * 1000); // Tomorrow
|
|
58
60
|
const endTime = new Date(startTime.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days later
|
|
59
|
-
const isAuction =
|
|
61
|
+
const isAuction = !('fixed_price' in pricingOption) &&
|
|
62
|
+
(pricingOption.floor_price !== undefined || pricingOption.price_guidance !== undefined);
|
|
60
63
|
const packageRequest = {
|
|
61
64
|
buyer_ref: `pkg-test-${Date.now()}`,
|
|
62
65
|
product_id: product.product_id,
|
|
@@ -83,6 +86,56 @@ function buildCreateMediaBuyRequest(product, pricingOption, options, extras = {}
|
|
|
83
86
|
packages: [packageRequest],
|
|
84
87
|
};
|
|
85
88
|
}
|
|
89
|
+
function getDefaultFormatId() {
|
|
90
|
+
return { agent_url: 'https://creative.adcontextprotocol.org', id: 'display_300x250' };
|
|
91
|
+
}
|
|
92
|
+
function formatIdToString(formatId) {
|
|
93
|
+
return formatId.id;
|
|
94
|
+
}
|
|
95
|
+
function selectFormatId(product, fallback = getDefaultFormatId()) {
|
|
96
|
+
if (!product?.format_ids?.length) {
|
|
97
|
+
return fallback;
|
|
98
|
+
}
|
|
99
|
+
const format = product.format_ids[0];
|
|
100
|
+
if (typeof format === 'string') {
|
|
101
|
+
return { ...fallback, id: format };
|
|
102
|
+
}
|
|
103
|
+
const nested = format;
|
|
104
|
+
if (nested.format_id) {
|
|
105
|
+
return nested.format_id;
|
|
106
|
+
}
|
|
107
|
+
const direct = format;
|
|
108
|
+
if (typeof direct.agent_url === 'string' && typeof direct.id === 'string') {
|
|
109
|
+
return direct;
|
|
110
|
+
}
|
|
111
|
+
return fallback;
|
|
112
|
+
}
|
|
113
|
+
function buildStaticInlineCreative(formatId) {
|
|
114
|
+
return {
|
|
115
|
+
name: `Inline Test Creative ${Date.now()}`,
|
|
116
|
+
format_id: formatId,
|
|
117
|
+
assets: {
|
|
118
|
+
primary: {
|
|
119
|
+
url: 'https://via.placeholder.com/300x250?text=Inline+Creative',
|
|
120
|
+
width: 300,
|
|
121
|
+
height: 250,
|
|
122
|
+
format: 'png',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function extractCreativeManifest(data) {
|
|
128
|
+
return data?.creative_manifest || data?.creative_manifests?.[0];
|
|
129
|
+
}
|
|
130
|
+
function buildSyncCreativeFromManifest(manifest, fallbackFormatId) {
|
|
131
|
+
const creativeId = manifest?.creative_id || `test-creative-${Date.now()}`;
|
|
132
|
+
return {
|
|
133
|
+
creative_id: creativeId,
|
|
134
|
+
name: manifest?.name || `Generated Creative ${creativeId}`,
|
|
135
|
+
format_id: manifest?.format_id || fallbackFormatId,
|
|
136
|
+
assets: manifest?.assets || buildStaticInlineCreative(fallbackFormatId).assets,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
86
139
|
/**
|
|
87
140
|
* Test: Create Media Buy
|
|
88
141
|
* Discovers products, then creates a test media buy
|
|
@@ -104,12 +157,14 @@ async function testCreateMediaBuy(agentUrl, options) {
|
|
|
104
157
|
return { steps, profile };
|
|
105
158
|
}
|
|
106
159
|
// Get products
|
|
107
|
-
const { result: productsResult } = await (0, client_1.runStep)('Fetch products for media buy', 'get_products', async () => client.
|
|
160
|
+
const { result: productsResult } = await (0, client_1.runStep)('Fetch products for media buy', 'get_products', async () => client.getProducts({
|
|
108
161
|
buying_mode: 'brief',
|
|
109
162
|
brief: options.brief || 'Looking for display advertising products',
|
|
110
163
|
brand: (0, client_1.resolveBrand)(options),
|
|
164
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
111
165
|
}));
|
|
112
|
-
const
|
|
166
|
+
const productsData = productsResult?.data;
|
|
167
|
+
const products = productsData?.products;
|
|
113
168
|
if (!productsResult?.success || !products?.length) {
|
|
114
169
|
steps.push({
|
|
115
170
|
step: 'Create media buy',
|
|
@@ -121,6 +176,16 @@ async function testCreateMediaBuy(agentUrl, options) {
|
|
|
121
176
|
return { steps, profile };
|
|
122
177
|
}
|
|
123
178
|
const product = selectProduct(products, options);
|
|
179
|
+
if (!product) {
|
|
180
|
+
steps.push({
|
|
181
|
+
step: 'Create media buy',
|
|
182
|
+
task: 'create_media_buy',
|
|
183
|
+
passed: false,
|
|
184
|
+
duration_ms: 0,
|
|
185
|
+
error: 'No suitable product found',
|
|
186
|
+
});
|
|
187
|
+
return { steps, profile };
|
|
188
|
+
}
|
|
124
189
|
const pricingOption = selectPricingOption(product, options.pricing_models);
|
|
125
190
|
if (!pricingOption) {
|
|
126
191
|
steps.push({
|
|
@@ -134,20 +199,23 @@ async function testCreateMediaBuy(agentUrl, options) {
|
|
|
134
199
|
}
|
|
135
200
|
const createRequest = buildCreateMediaBuyRequest(product, pricingOption, options);
|
|
136
201
|
// Create the media buy
|
|
137
|
-
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create media buy', 'create_media_buy',
|
|
202
|
+
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create media buy', 'create_media_buy',
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
204
|
+
async () => client.createMediaBuy(createRequest));
|
|
138
205
|
let mediaBuyId;
|
|
139
206
|
if (createResult?.success && createResult?.data) {
|
|
140
207
|
const mediaBuy = createResult.data;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
208
|
+
const nested = mediaBuy.media_buy;
|
|
209
|
+
mediaBuyId = (mediaBuy.media_buy_id || nested?.media_buy_id);
|
|
210
|
+
const status = (mediaBuy.status || nested?.status);
|
|
211
|
+
const packages = (mediaBuy.packages || nested?.packages);
|
|
144
212
|
createStep.details = `Created media buy: ${mediaBuyId}, status: ${status}`;
|
|
145
213
|
createStep.created_id = mediaBuyId;
|
|
146
214
|
createStep.response_preview = JSON.stringify({
|
|
147
215
|
media_buy_id: mediaBuyId,
|
|
148
216
|
status,
|
|
149
217
|
packages_count: packages?.length,
|
|
150
|
-
pricing_model: pricingOption.
|
|
218
|
+
pricing_model: pricingOption.pricing_model,
|
|
151
219
|
product_name: product.name,
|
|
152
220
|
}, null, 2);
|
|
153
221
|
}
|
|
@@ -173,7 +241,7 @@ async function testFullSalesFlow(agentUrl, options) {
|
|
|
173
241
|
}
|
|
174
242
|
// Test update_media_buy if available
|
|
175
243
|
if (profile?.tools.includes('update_media_buy')) {
|
|
176
|
-
const { result: updateResult, step: updateStep } = await (0, client_1.runStep)('Update media buy (increase budget)', 'update_media_buy', async () => client.
|
|
244
|
+
const { result: updateResult, step: updateStep } = await (0, client_1.runStep)('Update media buy (increase budget)', 'update_media_buy', async () => client.updateMediaBuy({
|
|
177
245
|
media_buy_id: mediaBuyId,
|
|
178
246
|
packages: [
|
|
179
247
|
{
|
|
@@ -181,13 +249,15 @@ async function testFullSalesFlow(agentUrl, options) {
|
|
|
181
249
|
budget: (options.budget || 1000) * 1.5,
|
|
182
250
|
},
|
|
183
251
|
],
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
184
253
|
}));
|
|
185
254
|
if (updateResult?.success && updateResult?.data) {
|
|
186
255
|
const data = updateResult.data;
|
|
187
|
-
const
|
|
256
|
+
const nested = data.media_buy;
|
|
257
|
+
const status = (data.status || nested?.status);
|
|
188
258
|
updateStep.details = `Updated media buy, status: ${status}`;
|
|
189
259
|
updateStep.response_preview = JSON.stringify({
|
|
190
|
-
media_buy_id: data.media_buy_id ||
|
|
260
|
+
media_buy_id: (data.media_buy_id || nested?.media_buy_id),
|
|
191
261
|
status,
|
|
192
262
|
}, null, 2);
|
|
193
263
|
}
|
|
@@ -197,16 +267,61 @@ async function testFullSalesFlow(agentUrl, options) {
|
|
|
197
267
|
}
|
|
198
268
|
steps.push(updateStep);
|
|
199
269
|
}
|
|
270
|
+
if (profile?.tools.includes('get_media_buys')) {
|
|
271
|
+
const { result: snapshotResult, step: snapshotStep } = await (0, client_1.runStep)('Get media buy status with delivery snapshots', 'get_media_buys', async () => client.executeTask('get_media_buys', {
|
|
272
|
+
media_buy_ids: [mediaBuyId],
|
|
273
|
+
include_snapshot: true,
|
|
274
|
+
}));
|
|
275
|
+
if (snapshotResult?.success && snapshotResult?.data) {
|
|
276
|
+
const mediaBuys = snapshotResult.data.media_buys || [];
|
|
277
|
+
const mediaBuy = mediaBuys.find((item) => item.media_buy_id === mediaBuyId) || mediaBuys[0];
|
|
278
|
+
const packages = mediaBuy?.packages || [];
|
|
279
|
+
const invalidPackages = packages.filter((pkg) => {
|
|
280
|
+
if (pkg.snapshot) {
|
|
281
|
+
return !pkg.snapshot.as_of || pkg.snapshot.staleness_seconds === undefined;
|
|
282
|
+
}
|
|
283
|
+
return !pkg.snapshot_unavailable_reason;
|
|
284
|
+
});
|
|
285
|
+
if (!mediaBuy) {
|
|
286
|
+
snapshotStep.passed = false;
|
|
287
|
+
snapshotStep.error = 'get_media_buys did not return the created media buy';
|
|
288
|
+
}
|
|
289
|
+
else if (invalidPackages.length > 0) {
|
|
290
|
+
snapshotStep.passed = false;
|
|
291
|
+
snapshotStep.error =
|
|
292
|
+
'include_snapshot=true must return either snapshot data or snapshot_unavailable_reason for each package';
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
snapshotStep.details = `Retrieved ${packages.length} package snapshot(s)`;
|
|
296
|
+
snapshotStep.response_preview = JSON.stringify({
|
|
297
|
+
media_buy_id: mediaBuy.media_buy_id,
|
|
298
|
+
package_count: packages.length,
|
|
299
|
+
snapshots_returned: packages.filter((pkg) => !!pkg.snapshot).length,
|
|
300
|
+
snapshot_unavailable: packages
|
|
301
|
+
.filter((pkg) => !!pkg.snapshot_unavailable_reason)
|
|
302
|
+
.map((pkg) => ({ package_id: pkg.package_id, reason: pkg.snapshot_unavailable_reason })),
|
|
303
|
+
}, null, 2);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else if (snapshotResult && !snapshotResult.success) {
|
|
307
|
+
snapshotStep.passed = false;
|
|
308
|
+
snapshotStep.error = snapshotResult.error || 'get_media_buys returned unsuccessful result';
|
|
309
|
+
}
|
|
310
|
+
steps.push(snapshotStep);
|
|
311
|
+
}
|
|
200
312
|
// Test get_media_buy_delivery if available
|
|
201
313
|
if (profile?.tools.includes('get_media_buy_delivery')) {
|
|
202
|
-
const { result: deliveryResult, step: deliveryStep } = await (0, client_1.runStep)('Get delivery metrics', 'get_media_buy_delivery', async () => client.
|
|
314
|
+
const { result: deliveryResult, step: deliveryStep } = await (0, client_1.runStep)('Get delivery metrics', 'get_media_buy_delivery', async () => client.getMediaBuyDelivery({
|
|
203
315
|
media_buy_ids: [mediaBuyId],
|
|
316
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
204
317
|
}));
|
|
205
318
|
if (deliveryResult?.success && deliveryResult?.data) {
|
|
206
319
|
const delivery = deliveryResult.data;
|
|
320
|
+
const deliveries = delivery.deliveries;
|
|
321
|
+
const mediaBuys = delivery.media_buys;
|
|
207
322
|
deliveryStep.details = `Retrieved delivery metrics`;
|
|
208
323
|
deliveryStep.response_preview = JSON.stringify({
|
|
209
|
-
has_deliveries: !!(
|
|
324
|
+
has_deliveries: !!(deliveries?.length || mediaBuys?.length),
|
|
210
325
|
}, null, 2);
|
|
211
326
|
}
|
|
212
327
|
else if (deliveryResult && !deliveryResult.success) {
|
|
@@ -238,14 +353,25 @@ async function testCreativeSync(agentUrl, options) {
|
|
|
238
353
|
return { steps, profile };
|
|
239
354
|
}
|
|
240
355
|
// Get format info first
|
|
241
|
-
let formatId =
|
|
356
|
+
let formatId = {
|
|
357
|
+
agent_url: 'https://creative.adcontextprotocol.org',
|
|
358
|
+
id: 'display_300x250',
|
|
359
|
+
};
|
|
242
360
|
if (profile.tools.includes('list_creative_formats')) {
|
|
243
|
-
const { result: formatsResult } = await (0, client_1.runStep)('Get formats for creative', 'list_creative_formats', async () => client.
|
|
361
|
+
const { result: formatsResult } = await (0, client_1.runStep)('Get formats for creative', 'list_creative_formats', async () => client.listCreativeFormats({}));
|
|
244
362
|
if (formatsResult?.success && formatsResult?.data) {
|
|
245
363
|
const data = formatsResult.data;
|
|
246
|
-
const
|
|
364
|
+
const formatIds = data.format_ids;
|
|
365
|
+
const formats = data.formats;
|
|
366
|
+
const firstFormat = formatIds?.[0] || formats?.[0];
|
|
247
367
|
if (firstFormat) {
|
|
248
|
-
|
|
368
|
+
if (typeof firstFormat === 'string') {
|
|
369
|
+
formatId = { id: firstFormat };
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
const formatObj = firstFormat;
|
|
373
|
+
formatId = formatObj.format_id || formatObj;
|
|
374
|
+
}
|
|
249
375
|
}
|
|
250
376
|
}
|
|
251
377
|
}
|
|
@@ -264,18 +390,20 @@ async function testCreativeSync(agentUrl, options) {
|
|
|
264
390
|
},
|
|
265
391
|
},
|
|
266
392
|
};
|
|
267
|
-
const { result: syncResult, step: syncStep } = await (0, client_1.runStep)('Sync creative to library', 'sync_creatives', async () => client.
|
|
393
|
+
const { result: syncResult, step: syncStep } = await (0, client_1.runStep)('Sync creative to library', 'sync_creatives', async () => client.syncCreatives({
|
|
394
|
+
account: (0, client_1.resolveAccount)(options),
|
|
268
395
|
creatives: [testCreative],
|
|
396
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
269
397
|
}));
|
|
270
398
|
if (syncResult?.success && syncResult?.data) {
|
|
271
399
|
const data = syncResult.data;
|
|
272
400
|
const creatives = data.creatives || [];
|
|
273
|
-
const actions = creatives.map(
|
|
401
|
+
const actions = creatives.map(c => c.action);
|
|
274
402
|
syncStep.details = `Synced ${creatives.length} creative(s), actions: ${actions.join(', ')}`;
|
|
275
403
|
syncStep.response_preview = JSON.stringify({
|
|
276
404
|
creatives_count: creatives.length,
|
|
277
405
|
actions: actions,
|
|
278
|
-
creative_ids: creatives.map(
|
|
406
|
+
creative_ids: creatives.map(c => c.creative_id),
|
|
279
407
|
}, null, 2);
|
|
280
408
|
}
|
|
281
409
|
else if (syncResult && !syncResult.success) {
|
|
@@ -285,7 +413,7 @@ async function testCreativeSync(agentUrl, options) {
|
|
|
285
413
|
steps.push(syncStep);
|
|
286
414
|
// Test list_creatives if available
|
|
287
415
|
if (profile.tools.includes('list_creatives')) {
|
|
288
|
-
const { result: listResult, step: listStep } = await (0, client_1.runStep)('List creatives in library', 'list_creatives', async () => client.
|
|
416
|
+
const { result: listResult, step: listStep } = await (0, client_1.runStep)('List creatives in library', 'list_creatives', async () => client.listCreatives({}));
|
|
289
417
|
if (listResult?.success && listResult?.data) {
|
|
290
418
|
const data = listResult.data;
|
|
291
419
|
const creatives = data.creatives || [];
|
|
@@ -308,7 +436,7 @@ async function testCreativeSync(agentUrl, options) {
|
|
|
308
436
|
listStep.response_preview = JSON.stringify({
|
|
309
437
|
creatives_count: creatives.length,
|
|
310
438
|
total_matching: totalMatching,
|
|
311
|
-
statuses: Array.from(new Set(creatives.map(
|
|
439
|
+
statuses: Array.from(new Set(creatives.map(c => c.status))),
|
|
312
440
|
}, null, 2);
|
|
313
441
|
}
|
|
314
442
|
}
|
|
@@ -341,12 +469,14 @@ async function testCreativeInline(agentUrl, options) {
|
|
|
341
469
|
return { steps, profile };
|
|
342
470
|
}
|
|
343
471
|
// Get products
|
|
344
|
-
const { result: productsResult } = await (0, client_1.runStep)('Fetch products for inline creative test', 'get_products', async () => client.
|
|
472
|
+
const { result: productsResult } = await (0, client_1.runStep)('Fetch products for inline creative test', 'get_products', async () => client.getProducts({
|
|
345
473
|
buying_mode: 'brief',
|
|
346
474
|
brief: options.brief || 'Looking for display advertising products',
|
|
347
475
|
brand: (0, client_1.resolveBrand)(options),
|
|
476
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
348
477
|
}));
|
|
349
|
-
const
|
|
478
|
+
const inlineProductsData = productsResult?.data;
|
|
479
|
+
const products = inlineProductsData?.products;
|
|
350
480
|
if (!productsResult?.success || !products?.length) {
|
|
351
481
|
steps.push({
|
|
352
482
|
step: 'Create media buy with inline creatives',
|
|
@@ -358,6 +488,16 @@ async function testCreativeInline(agentUrl, options) {
|
|
|
358
488
|
return { steps, profile };
|
|
359
489
|
}
|
|
360
490
|
const product = selectProduct(products, options);
|
|
491
|
+
if (!product) {
|
|
492
|
+
steps.push({
|
|
493
|
+
step: 'Create media buy with inline creatives',
|
|
494
|
+
task: 'create_media_buy',
|
|
495
|
+
passed: false,
|
|
496
|
+
duration_ms: 0,
|
|
497
|
+
error: 'No suitable product found',
|
|
498
|
+
});
|
|
499
|
+
return { steps, profile };
|
|
500
|
+
}
|
|
361
501
|
const pricingOption = selectPricingOption(product, options.pricing_models);
|
|
362
502
|
if (!pricingOption) {
|
|
363
503
|
steps.push({
|
|
@@ -369,35 +509,53 @@ async function testCreativeInline(agentUrl, options) {
|
|
|
369
509
|
});
|
|
370
510
|
return { steps, profile };
|
|
371
511
|
}
|
|
372
|
-
|
|
373
|
-
let
|
|
374
|
-
if (
|
|
375
|
-
const
|
|
376
|
-
|
|
512
|
+
const formatId = selectFormatId(product);
|
|
513
|
+
let inlineCreative = buildStaticInlineCreative(formatId);
|
|
514
|
+
if (profile.tools.includes('build_creative')) {
|
|
515
|
+
const { result: buildResult, step: buildStep } = await (0, client_1.runStep)(`Build creative for inline flow (${formatIdToString(formatId)})`, 'build_creative', async () => client.executeTask('build_creative', {
|
|
516
|
+
target_format_id: formatId,
|
|
517
|
+
brand: (0, client_1.resolveBrand)(options),
|
|
518
|
+
message: `Create an ad creative for the ${formatIdToString(formatId)} format that can be attached to a media buy`,
|
|
519
|
+
quality: 'draft',
|
|
520
|
+
}));
|
|
521
|
+
if (buildResult?.success && buildResult?.data) {
|
|
522
|
+
const manifest = extractCreativeManifest(buildResult.data);
|
|
523
|
+
if (manifest?.assets) {
|
|
524
|
+
inlineCreative = buildSyncCreativeFromManifest(manifest, formatId);
|
|
525
|
+
buildStep.details = `Built creative manifest for ${inlineCreative.format_id}`;
|
|
526
|
+
buildStep.response_preview = JSON.stringify({
|
|
527
|
+
format_id: inlineCreative.format_id,
|
|
528
|
+
asset_keys: Object.keys(inlineCreative.assets || {}),
|
|
529
|
+
}, null, 2);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
buildStep.passed = false;
|
|
533
|
+
buildStep.error = 'build_creative succeeded but returned no creative_manifest';
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
else if (buildResult && !buildResult.success) {
|
|
537
|
+
buildStep.passed = false;
|
|
538
|
+
buildStep.error = buildResult.error || 'build_creative failed';
|
|
539
|
+
}
|
|
540
|
+
steps.push(buildStep);
|
|
377
541
|
}
|
|
378
|
-
// Build inline creative
|
|
379
|
-
const inlineCreative = {
|
|
380
|
-
name: `Inline Test Creative ${Date.now()}`,
|
|
381
|
-
format_id: formatId,
|
|
382
|
-
assets: {
|
|
383
|
-
primary: {
|
|
384
|
-
url: 'https://via.placeholder.com/300x250?text=Inline+Creative',
|
|
385
|
-
width: 300,
|
|
386
|
-
height: 250,
|
|
387
|
-
format: 'png',
|
|
388
|
-
},
|
|
389
|
-
},
|
|
390
|
-
};
|
|
391
542
|
const createRequest = buildCreateMediaBuyRequest(product, pricingOption, options, {
|
|
392
543
|
inline_creatives: [inlineCreative],
|
|
393
544
|
});
|
|
394
|
-
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create media buy with inline creative', 'create_media_buy',
|
|
545
|
+
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create media buy with inline creative', 'create_media_buy',
|
|
546
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
547
|
+
async () => client.createMediaBuy(createRequest));
|
|
395
548
|
if (createResult?.success && createResult?.data) {
|
|
396
549
|
const mediaBuy = createResult.data;
|
|
397
|
-
const
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
const
|
|
550
|
+
const nested = mediaBuy.media_buy;
|
|
551
|
+
const mediaBuyId = (mediaBuy.media_buy_id || nested?.media_buy_id);
|
|
552
|
+
const status = (mediaBuy.status || nested?.status);
|
|
553
|
+
const packages = (mediaBuy.packages || nested?.packages);
|
|
554
|
+
const hasCreatives = packages?.some(p => {
|
|
555
|
+
const creatives = p.creatives;
|
|
556
|
+
const creativeIds = p.creative_ids;
|
|
557
|
+
return creatives?.length || creativeIds?.length;
|
|
558
|
+
});
|
|
401
559
|
createStep.details = `Created media buy with inline creative: ${mediaBuyId}`;
|
|
402
560
|
createStep.created_id = mediaBuyId;
|
|
403
561
|
createStep.response_preview = JSON.stringify({
|
|
@@ -414,6 +572,131 @@ async function testCreativeInline(agentUrl, options) {
|
|
|
414
572
|
steps.push(createStep);
|
|
415
573
|
return { steps, profile };
|
|
416
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Test: Creative Reference Flow
|
|
577
|
+
* Builds a creative manifest, syncs it into the seller's library, then references it in create_media_buy.
|
|
578
|
+
*/
|
|
579
|
+
async function testCreativeReference(agentUrl, options) {
|
|
580
|
+
const steps = [];
|
|
581
|
+
const client = (0, client_1.createTestClient)(agentUrl, options.protocol || 'mcp', options);
|
|
582
|
+
const { steps: discoverySteps, profile } = await (0, discovery_1.testDiscovery)(agentUrl, options);
|
|
583
|
+
steps.push(...discoverySteps);
|
|
584
|
+
if (!profile?.tools.includes('build_creative') || !profile.tools.includes('sync_creatives')) {
|
|
585
|
+
steps.push({
|
|
586
|
+
step: 'Build and reference creative',
|
|
587
|
+
task: 'build_creative',
|
|
588
|
+
passed: false,
|
|
589
|
+
duration_ms: 0,
|
|
590
|
+
error: 'Agent must support both build_creative and sync_creatives',
|
|
591
|
+
});
|
|
592
|
+
return { steps, profile };
|
|
593
|
+
}
|
|
594
|
+
const { result: productsResult } = await (0, client_1.runStep)('Fetch products for creative reference test', 'get_products', async () => client.executeTask('get_products', {
|
|
595
|
+
buying_mode: 'brief',
|
|
596
|
+
brief: options.brief || 'Looking for products that support generated creative attachments',
|
|
597
|
+
brand: (0, client_1.resolveBrand)(options),
|
|
598
|
+
}));
|
|
599
|
+
const products = productsResult?.data?.products;
|
|
600
|
+
if (!productsResult?.success || !products?.length) {
|
|
601
|
+
steps.push({
|
|
602
|
+
step: 'Build and reference creative',
|
|
603
|
+
task: 'create_media_buy',
|
|
604
|
+
passed: false,
|
|
605
|
+
duration_ms: 0,
|
|
606
|
+
error: 'No products available to test creative references',
|
|
607
|
+
});
|
|
608
|
+
return { steps, profile };
|
|
609
|
+
}
|
|
610
|
+
const product = selectProduct(products, options);
|
|
611
|
+
if (!product) {
|
|
612
|
+
steps.push({
|
|
613
|
+
step: 'Build and reference creative',
|
|
614
|
+
task: 'create_media_buy',
|
|
615
|
+
passed: false,
|
|
616
|
+
duration_ms: 0,
|
|
617
|
+
error: 'No suitable product found for creative reference test',
|
|
618
|
+
});
|
|
619
|
+
return { steps, profile };
|
|
620
|
+
}
|
|
621
|
+
const pricingOption = selectPricingOption(product, options.pricing_models);
|
|
622
|
+
const formatId = selectFormatId(product);
|
|
623
|
+
if (!pricingOption) {
|
|
624
|
+
steps.push({
|
|
625
|
+
step: 'Build and reference creative',
|
|
626
|
+
task: 'create_media_buy',
|
|
627
|
+
passed: false,
|
|
628
|
+
duration_ms: 0,
|
|
629
|
+
error: `Product "${product.name}" has no pricing options`,
|
|
630
|
+
});
|
|
631
|
+
return { steps, profile };
|
|
632
|
+
}
|
|
633
|
+
const { result: buildResult, step: buildStep } = await (0, client_1.runStep)(`Build creative for reference flow (${formatIdToString(formatId)})`, 'build_creative', async () => client.executeTask('build_creative', {
|
|
634
|
+
target_format_id: formatId,
|
|
635
|
+
brand: (0, client_1.resolveBrand)(options),
|
|
636
|
+
message: `Create a reusable ad creative for the ${formatIdToString(formatId)} format`,
|
|
637
|
+
quality: 'draft',
|
|
638
|
+
}));
|
|
639
|
+
if (!buildResult?.success || !buildResult?.data) {
|
|
640
|
+
buildStep.passed = false;
|
|
641
|
+
buildStep.error = buildResult?.error || 'build_creative failed';
|
|
642
|
+
steps.push(buildStep);
|
|
643
|
+
return { steps, profile };
|
|
644
|
+
}
|
|
645
|
+
const manifest = extractCreativeManifest(buildResult.data);
|
|
646
|
+
if (!manifest?.assets) {
|
|
647
|
+
buildStep.passed = false;
|
|
648
|
+
buildStep.error = 'build_creative returned no creative_manifest';
|
|
649
|
+
steps.push(buildStep);
|
|
650
|
+
return { steps, profile };
|
|
651
|
+
}
|
|
652
|
+
const syncedCreative = buildSyncCreativeFromManifest(manifest, formatId);
|
|
653
|
+
buildStep.details = `Built creative manifest for ${syncedCreative.format_id}`;
|
|
654
|
+
buildStep.response_preview = JSON.stringify({
|
|
655
|
+
creative_id: syncedCreative.creative_id,
|
|
656
|
+
format_id: syncedCreative.format_id,
|
|
657
|
+
asset_keys: Object.keys(syncedCreative.assets || {}),
|
|
658
|
+
}, null, 2);
|
|
659
|
+
steps.push(buildStep);
|
|
660
|
+
const { result: syncResult, step: syncStep } = await (0, client_1.runStep)('Sync generated creative to library', 'sync_creatives', async () => client.executeTask('sync_creatives', {
|
|
661
|
+
creatives: [syncedCreative],
|
|
662
|
+
}));
|
|
663
|
+
if (!syncResult?.success || !syncResult?.data) {
|
|
664
|
+
syncStep.passed = false;
|
|
665
|
+
syncStep.error = syncResult?.error || 'sync_creatives failed';
|
|
666
|
+
steps.push(syncStep);
|
|
667
|
+
return { steps, profile };
|
|
668
|
+
}
|
|
669
|
+
syncStep.details = `Synced creative ${syncedCreative.creative_id} to seller library`;
|
|
670
|
+
syncStep.created_id = syncedCreative.creative_id;
|
|
671
|
+
syncStep.response_preview = JSON.stringify({
|
|
672
|
+
creative_id: syncedCreative.creative_id,
|
|
673
|
+
synced_count: (syncResult.data.creatives || []).length,
|
|
674
|
+
}, null, 2);
|
|
675
|
+
steps.push(syncStep);
|
|
676
|
+
const createRequest = buildCreateMediaBuyRequest(product, pricingOption, options, {
|
|
677
|
+
creative_ids: [syncedCreative.creative_id],
|
|
678
|
+
});
|
|
679
|
+
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create media buy with referenced creative', 'create_media_buy', async () => client.executeTask('create_media_buy', createRequest));
|
|
680
|
+
if (createResult?.success && createResult?.data) {
|
|
681
|
+
const mediaBuy = createResult.data;
|
|
682
|
+
const mediaBuyId = mediaBuy.media_buy_id || mediaBuy.media_buy?.media_buy_id;
|
|
683
|
+
const packages = mediaBuy.packages || mediaBuy.media_buy?.packages;
|
|
684
|
+
const referenced = packages?.some((pkg) => pkg.creative_ids?.includes(syncedCreative.creative_id));
|
|
685
|
+
createStep.details = `Created media buy with referenced creative ${syncedCreative.creative_id}`;
|
|
686
|
+
createStep.created_id = mediaBuyId;
|
|
687
|
+
createStep.response_preview = JSON.stringify({
|
|
688
|
+
media_buy_id: mediaBuyId,
|
|
689
|
+
creative_id: syncedCreative.creative_id,
|
|
690
|
+
referenced,
|
|
691
|
+
}, null, 2);
|
|
692
|
+
}
|
|
693
|
+
else if (createResult && !createResult.success) {
|
|
694
|
+
createStep.passed = false;
|
|
695
|
+
createStep.error = createResult.error || 'create_media_buy with creative_ids failed';
|
|
696
|
+
}
|
|
697
|
+
steps.push(createStep);
|
|
698
|
+
return { steps, profile };
|
|
699
|
+
}
|
|
417
700
|
// SHA-256 lookalike placeholder for test email/phone hashes (not a real hash)
|
|
418
701
|
const TEST_HASHED_EMAIL = 'a' + '0'.repeat(63);
|
|
419
702
|
const TEST_HASHED_PHONE = 'b' + '0'.repeat(63);
|
|
@@ -432,7 +715,10 @@ async function resolveAccountForAudiences(options, tools, listAccounts) {
|
|
|
432
715
|
if (options.sandbox && tools.includes('list_accounts')) {
|
|
433
716
|
// Sandbox with list_accounts: try explicit sandbox path first (discover pre-existing test accounts)
|
|
434
717
|
const { result: sandboxResult, step: sandboxStep } = await (0, client_1.runStep)('Discover sandbox accounts', 'list_accounts', async () => listAccounts({ sandbox: true }));
|
|
435
|
-
const
|
|
718
|
+
const sandboxData = sandboxResult?.success
|
|
719
|
+
? sandboxResult.data
|
|
720
|
+
: undefined;
|
|
721
|
+
const sandboxAccounts = sandboxData?.accounts ?? [];
|
|
436
722
|
if (sandboxAccounts[0]?.account_id) {
|
|
437
723
|
sandboxStep.details = `Using sandbox account: ${sandboxAccounts[0].account_id}`;
|
|
438
724
|
steps.push(sandboxStep);
|
|
@@ -459,7 +745,8 @@ async function resolveAccountForAudiences(options, tools, listAccounts) {
|
|
|
459
745
|
if (tools.includes('list_accounts')) {
|
|
460
746
|
const { result: accountsResult, step: accountsStep } = await (0, client_1.runStep)('Discover accounts for audience sync', 'list_accounts', async () => listAccounts({}));
|
|
461
747
|
if (accountsResult?.success && accountsResult?.data) {
|
|
462
|
-
const
|
|
748
|
+
const accountsData = accountsResult.data;
|
|
749
|
+
const accounts = accountsData.accounts ?? [];
|
|
463
750
|
if (accounts[0]?.account_id) {
|
|
464
751
|
accountsStep.details = `Using account: ${accounts[0].account_id}`;
|
|
465
752
|
steps.push(accountsStep);
|
|
@@ -497,7 +784,9 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
497
784
|
});
|
|
498
785
|
return { steps, profile };
|
|
499
786
|
}
|
|
500
|
-
const { accountRef, steps: accountSteps } = await resolveAccountForAudiences(options, profile.tools,
|
|
787
|
+
const { accountRef, steps: accountSteps } = await resolveAccountForAudiences(options, profile.tools,
|
|
788
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
789
|
+
async (params) => client.listAccounts(params));
|
|
501
790
|
steps.push(...accountSteps);
|
|
502
791
|
if (!accountRef) {
|
|
503
792
|
steps.push({
|
|
@@ -510,15 +799,17 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
510
799
|
return { steps, profile };
|
|
511
800
|
}
|
|
512
801
|
// Step 1: Discovery call — list existing audiences without modification
|
|
513
|
-
const { result: discoveryResult, step: discoveryStep } = await (0, client_1.runStep)('Discover existing audiences (discovery-only)', 'sync_audiences', async () => client.
|
|
802
|
+
const { result: discoveryResult, step: discoveryStep } = await (0, client_1.runStep)('Discover existing audiences (discovery-only)', 'sync_audiences', async () => client.syncAudiences({
|
|
514
803
|
account: accountRef,
|
|
804
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
515
805
|
}));
|
|
516
806
|
if (discoveryResult?.success && discoveryResult?.data) {
|
|
517
|
-
const
|
|
807
|
+
const discoveryData = discoveryResult.data;
|
|
808
|
+
const audiences = discoveryData.audiences ?? [];
|
|
518
809
|
discoveryStep.details = `Found ${audiences.length} existing audience(s)`;
|
|
519
810
|
discoveryStep.response_preview = JSON.stringify({
|
|
520
811
|
existing_audiences: audiences.length,
|
|
521
|
-
audience_ids: audiences.map(
|
|
812
|
+
audience_ids: audiences.map(a => a.audience_id).slice(0, 5),
|
|
522
813
|
}, null, 2);
|
|
523
814
|
}
|
|
524
815
|
else if (discoveryResult && !discoveryResult.success) {
|
|
@@ -531,7 +822,7 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
531
822
|
}
|
|
532
823
|
// Step 2: Create a test audience
|
|
533
824
|
const testAudienceId = `adcp-test-audience-${Date.now()}`;
|
|
534
|
-
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create test audience', 'sync_audiences', async () => client.
|
|
825
|
+
const { result: createResult, step: createStep } = await (0, client_1.runStep)('Create test audience', 'sync_audiences', async () => client.syncAudiences({
|
|
535
826
|
account: accountRef,
|
|
536
827
|
audiences: [
|
|
537
828
|
{
|
|
@@ -540,10 +831,12 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
540
831
|
add: [{ hashed_email: TEST_HASHED_EMAIL }, { hashed_phone: TEST_HASHED_PHONE }],
|
|
541
832
|
},
|
|
542
833
|
],
|
|
834
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
543
835
|
}));
|
|
544
836
|
if (createResult?.success && createResult?.data) {
|
|
545
|
-
const
|
|
546
|
-
const
|
|
837
|
+
const createData = createResult.data;
|
|
838
|
+
const audiences = createData.audiences ?? [];
|
|
839
|
+
const testAudience = audiences.find(a => a.audience_id === testAudienceId);
|
|
547
840
|
createStep.details = `Created audience "${testAudienceId}", action: ${testAudience?.action}, status: ${testAudience?.status ?? 'n/a'}`;
|
|
548
841
|
createStep.created_id = testAudienceId;
|
|
549
842
|
createStep.response_preview = JSON.stringify({
|
|
@@ -562,7 +855,7 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
562
855
|
return { steps, profile };
|
|
563
856
|
}
|
|
564
857
|
// Step 3: Delete the test audience
|
|
565
|
-
const { result: deleteResult, step: deleteStep } = await (0, client_1.runStep)('Delete test audience', 'sync_audiences', async () => client.
|
|
858
|
+
const { result: deleteResult, step: deleteStep } = await (0, client_1.runStep)('Delete test audience', 'sync_audiences', async () => client.syncAudiences({
|
|
566
859
|
account: accountRef,
|
|
567
860
|
audiences: [
|
|
568
861
|
{
|
|
@@ -570,10 +863,12 @@ async function testSyncAudiences(agentUrl, options) {
|
|
|
570
863
|
delete: true,
|
|
571
864
|
},
|
|
572
865
|
],
|
|
866
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentional: test request bypasses strict typing
|
|
573
867
|
}));
|
|
574
868
|
if (deleteResult?.success && deleteResult?.data) {
|
|
575
|
-
const
|
|
576
|
-
const
|
|
869
|
+
const deleteData = deleteResult.data;
|
|
870
|
+
const audiences = deleteData.audiences ?? [];
|
|
871
|
+
const deleted = audiences.find(a => a.audience_id === testAudienceId);
|
|
577
872
|
deleteStep.details = `Deleted audience "${testAudienceId}", action: ${deleted?.action}`;
|
|
578
873
|
deleteStep.response_preview = JSON.stringify({
|
|
579
874
|
audience_id: deleted?.audience_id,
|