@the_ro_show/agent-ads-sdk 0.1.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/LICENSE +21 -0
- package/README.md +376 -0
- package/SECURITY.md +50 -0
- package/dist/index.d.mts +300 -0
- package/dist/index.d.ts +300 -0
- package/dist/index.js +351 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +315 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AttentionMarket
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# AttentionMarket Agent Ads SDK
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for integrating agent-native sponsored units (Sponsored Suggestions and Sponsored Tools) into AI agents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @the_ro_show/agent-ads-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Store your credentials in environment variables:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export ATTENTIONMARKET_API_KEY=am_live_...
|
|
17
|
+
export ATTENTIONMARKET_AGENT_ID=agt_01HV...
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**⚠️ Never commit API keys to version control.** See [SECURITY.md](./SECURITY.md) for best practices.
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { AttentionMarketClient, createOpportunity, generateUUID } from '@the_ro_show/agent-ads-sdk';
|
|
26
|
+
|
|
27
|
+
const client = new AttentionMarketClient({ apiKey: process.env.ATTENTIONMARKET_API_KEY });
|
|
28
|
+
|
|
29
|
+
const opportunity = createOpportunity({
|
|
30
|
+
taxonomy: 'local_services.movers.quote',
|
|
31
|
+
country: 'US',
|
|
32
|
+
language: 'en',
|
|
33
|
+
platform: 'web',
|
|
34
|
+
query: 'Find movers in Brooklyn',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const unit = await client.decide({
|
|
38
|
+
request_id: generateUUID(),
|
|
39
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
40
|
+
placement: { type: 'sponsored_suggestion', surface: 'chat_response' },
|
|
41
|
+
opportunity,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (unit && unit.unit_type === 'sponsored_suggestion') {
|
|
45
|
+
console.log(`[${unit.disclosure.label}] ${unit.disclosure.sponsor_name}`);
|
|
46
|
+
console.log(unit.suggestion.title);
|
|
47
|
+
|
|
48
|
+
await client.trackImpression({
|
|
49
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
50
|
+
request_id: 'req_id',
|
|
51
|
+
decision_id: 'decision_id',
|
|
52
|
+
unit_id: unit.unit_id,
|
|
53
|
+
tracking_token: unit.tracking.token,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Agent Integration Examples
|
|
59
|
+
|
|
60
|
+
### Minimal Examples (< 80 lines)
|
|
61
|
+
|
|
62
|
+
Start here for a quick overview:
|
|
63
|
+
|
|
64
|
+
- **[Claude](./examples/claude-tool-use-minimal.ts)** - Minimal tool use integration
|
|
65
|
+
- **[OpenAI GPT](./examples/openai-function-calling-minimal.ts)** - Minimal function calling
|
|
66
|
+
- **[Google Gemini](./examples/gemini-function-calling-minimal.ts)** - Minimal function declarations
|
|
67
|
+
|
|
68
|
+
Each shows: `createOpportunity` → `decide` → render → track
|
|
69
|
+
|
|
70
|
+
### Full Examples (with detailed integration notes)
|
|
71
|
+
|
|
72
|
+
For production integrations:
|
|
73
|
+
|
|
74
|
+
- **[Claude (Anthropic)](./examples/claude-tool-use-full.ts)** - Complete tool use pattern with schemas and tracking
|
|
75
|
+
- **[OpenAI GPT](./examples/openai-function-calling-full.ts)** - Complete function calling with integration checklist
|
|
76
|
+
- **[Google Gemini](./examples/gemini-function-calling-full.ts)** - Complete function declarations with testing guide
|
|
77
|
+
|
|
78
|
+
Run any example with:
|
|
79
|
+
```bash
|
|
80
|
+
npx tsx examples/claude-tool-use-minimal.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Full Example with Raw Response
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
AttentionMarketClient,
|
|
88
|
+
createOpportunity,
|
|
89
|
+
generateUUID,
|
|
90
|
+
} from '@the_ro_show/agent-ads-sdk';
|
|
91
|
+
|
|
92
|
+
const client = new AttentionMarketClient({
|
|
93
|
+
apiKey: process.env.ATTENTIONMARKET_API_KEY,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Build opportunity
|
|
97
|
+
const opportunity = createOpportunity({
|
|
98
|
+
taxonomy: 'local_services.movers.quote',
|
|
99
|
+
country: 'US',
|
|
100
|
+
language: 'en',
|
|
101
|
+
platform: 'web',
|
|
102
|
+
query: 'Find movers in Brooklyn',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Get full response (includes status, ttl_ms, all units)
|
|
106
|
+
const response = await client.decideRaw({
|
|
107
|
+
request_id: generateUUID(),
|
|
108
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
109
|
+
placement: {
|
|
110
|
+
type: 'sponsored_suggestion',
|
|
111
|
+
surface: 'chat_response',
|
|
112
|
+
},
|
|
113
|
+
opportunity,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (response.status === 'filled') {
|
|
117
|
+
// Access all units and metadata
|
|
118
|
+
console.log(`TTL: ${response.ttl_ms}ms`);
|
|
119
|
+
console.log(`Units: ${response.units.length}`);
|
|
120
|
+
|
|
121
|
+
const unit = response.units[0];
|
|
122
|
+
|
|
123
|
+
// Render unit
|
|
124
|
+
if (unit && unit.unit_type === 'sponsored_suggestion') {
|
|
125
|
+
console.log(unit.suggestion.title);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Track impression after rendering
|
|
129
|
+
await client.trackImpression({
|
|
130
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
131
|
+
request_id: response.request_id,
|
|
132
|
+
decision_id: response.decision_id,
|
|
133
|
+
unit_id: unit.unit_id,
|
|
134
|
+
tracking_token: unit.tracking.token,
|
|
135
|
+
metadata: { surface: 'chat_response' },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Track click when user clicks
|
|
139
|
+
await client.trackClick({
|
|
140
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
141
|
+
request_id: response.request_id,
|
|
142
|
+
decision_id: response.decision_id,
|
|
143
|
+
unit_id: unit.unit_id,
|
|
144
|
+
tracking_token: unit.tracking.token,
|
|
145
|
+
href: unit.suggestion.action_url,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## API Methods
|
|
151
|
+
|
|
152
|
+
### `decide(request, options?): Promise<AdUnit | null>`
|
|
153
|
+
|
|
154
|
+
Convenience method that returns the first ad unit or `null` if no fill.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const unit = await client.decide({
|
|
158
|
+
request_id: generateUUID(),
|
|
159
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
160
|
+
placement: {
|
|
161
|
+
type: 'sponsored_suggestion',
|
|
162
|
+
surface: 'chat_response',
|
|
163
|
+
},
|
|
164
|
+
opportunity,
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `decideRaw(request, options?): Promise<DecideResponse>`
|
|
169
|
+
|
|
170
|
+
Returns the full response including status, ttl_ms, and all units.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const response = await client.decideRaw({
|
|
174
|
+
request_id: generateUUID(),
|
|
175
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
176
|
+
placement: { type: 'sponsored_suggestion', surface: 'chat_response' },
|
|
177
|
+
opportunity,
|
|
178
|
+
}, {
|
|
179
|
+
idempotencyKey: 'optional-idempotency-key',
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### `trackImpression(params): Promise<EventIngestResponse>`
|
|
184
|
+
|
|
185
|
+
Convenience method to track when a unit is rendered.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
await client.trackImpression({
|
|
189
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
190
|
+
request_id: 'req_123',
|
|
191
|
+
decision_id: 'dec_456',
|
|
192
|
+
unit_id: 'unit_789',
|
|
193
|
+
tracking_token: 'trk_abc',
|
|
194
|
+
metadata: { surface: 'chat_response' },
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### `trackClick(params): Promise<EventIngestResponse>`
|
|
199
|
+
|
|
200
|
+
Convenience method to track when a user clicks a unit.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
await client.trackClick({
|
|
204
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
205
|
+
request_id: 'req_123',
|
|
206
|
+
decision_id: 'dec_456',
|
|
207
|
+
unit_id: 'unit_789',
|
|
208
|
+
tracking_token: 'trk_abc',
|
|
209
|
+
href: 'https://example.com/action',
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### `track(event): Promise<EventIngestResponse>`
|
|
214
|
+
|
|
215
|
+
Low-level method to track any event type.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
await client.track({
|
|
219
|
+
event_id: generateUUID(),
|
|
220
|
+
occurred_at: new Date().toISOString(),
|
|
221
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
222
|
+
request_id: 'req_123',
|
|
223
|
+
decision_id: 'dec_456',
|
|
224
|
+
unit_id: 'unit_789',
|
|
225
|
+
event_type: 'impression',
|
|
226
|
+
tracking_token: 'trk_abc',
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### `getPolicy(): Promise<PolicyResponse>`
|
|
231
|
+
|
|
232
|
+
Fetch policy constraints and formatting requirements.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const policy = await client.getPolicy();
|
|
236
|
+
console.log(policy.defaults.max_units_per_response);
|
|
237
|
+
console.log(policy.disclosure.label);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### `signupAgent(request, options?): Promise<AgentSignupResponse>` (static)
|
|
241
|
+
|
|
242
|
+
Register a new agent (unauthenticated endpoint).
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const signup = await AttentionMarketClient.signupAgent({
|
|
246
|
+
owner_email: 'owner@company.com',
|
|
247
|
+
agent_name: 'My Agent',
|
|
248
|
+
sdk: 'typescript',
|
|
249
|
+
environment: 'test',
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
console.log(signup.agent_id);
|
|
253
|
+
console.log(signup.api_key);
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Helper Functions
|
|
257
|
+
|
|
258
|
+
### `createOpportunity(params): Opportunity`
|
|
259
|
+
|
|
260
|
+
Build a valid Opportunity object with safe defaults.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const opportunity = createOpportunity({
|
|
264
|
+
// Required
|
|
265
|
+
taxonomy: 'local_services.movers.quote',
|
|
266
|
+
country: 'US',
|
|
267
|
+
language: 'en',
|
|
268
|
+
platform: 'web',
|
|
269
|
+
|
|
270
|
+
// Optional
|
|
271
|
+
query: 'Find movers in Brooklyn',
|
|
272
|
+
region: 'NY',
|
|
273
|
+
city: 'New York',
|
|
274
|
+
|
|
275
|
+
// Optional overrides (with defaults shown)
|
|
276
|
+
constraints: {
|
|
277
|
+
max_units: 1,
|
|
278
|
+
allowed_unit_types: ['sponsored_suggestion'],
|
|
279
|
+
blocked_categories: ['adult'],
|
|
280
|
+
},
|
|
281
|
+
privacy: {
|
|
282
|
+
data_policy: 'coarse_only',
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### `createImpressionEvent(params): EventIngestRequest`
|
|
288
|
+
|
|
289
|
+
Build an impression event payload.
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import { createImpressionEvent } from '@the_ro_show/agent-ads-sdk';
|
|
293
|
+
|
|
294
|
+
const event = createImpressionEvent({
|
|
295
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
296
|
+
request_id: 'req_123',
|
|
297
|
+
decision_id: 'dec_456',
|
|
298
|
+
unit_id: 'unit_789',
|
|
299
|
+
tracking_token: 'trk_abc',
|
|
300
|
+
occurred_at: new Date().toISOString(), // optional, auto-generated
|
|
301
|
+
metadata: { surface: 'chat_response' }, // optional
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
await client.track(event);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### `createClickEvent(params): EventIngestRequest`
|
|
308
|
+
|
|
309
|
+
Build a click event payload.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { createClickEvent } from '@the_ro_show/agent-ads-sdk';
|
|
313
|
+
|
|
314
|
+
const event = createClickEvent({
|
|
315
|
+
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
316
|
+
request_id: 'req_123',
|
|
317
|
+
decision_id: 'dec_456',
|
|
318
|
+
unit_id: 'unit_789',
|
|
319
|
+
tracking_token: 'trk_abc',
|
|
320
|
+
href: 'https://example.com',
|
|
321
|
+
occurred_at: new Date().toISOString(), // optional, auto-generated
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
await client.track(event);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### `generateUUID(): string`
|
|
328
|
+
|
|
329
|
+
Generate a UUID v4 for request_id, event_id, etc.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
import { generateUUID } from '@the_ro_show/agent-ads-sdk';
|
|
333
|
+
|
|
334
|
+
const requestId = generateUUID();
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Features
|
|
338
|
+
|
|
339
|
+
- ✅ TypeScript support with full type definitions
|
|
340
|
+
- ✅ Automatic retries with exponential backoff
|
|
341
|
+
- ✅ Configurable timeouts (default 4000ms)
|
|
342
|
+
- ✅ Idempotency support
|
|
343
|
+
- ✅ Discriminated union types for type-safe ad units
|
|
344
|
+
- ✅ Helper functions for common operations
|
|
345
|
+
- ✅ No external runtime dependencies (Node.js 18+)
|
|
346
|
+
|
|
347
|
+
## Requirements
|
|
348
|
+
|
|
349
|
+
- Node.js 18 or higher
|
|
350
|
+
- TypeScript 5.3 or higher (for development)
|
|
351
|
+
|
|
352
|
+
## Error Handling
|
|
353
|
+
|
|
354
|
+
The SDK throws typed errors that include full API context:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { APIRequestError, NetworkError, TimeoutError } from '@the_ro_show/agent-ads-sdk';
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const unit = await client.decide(request);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
if (error instanceof APIRequestError) {
|
|
363
|
+
console.error(`API Error [${error.statusCode}]: ${error.errorCode}`);
|
|
364
|
+
console.error(`Message: ${error.message}`);
|
|
365
|
+
console.error(`Request ID: ${error.requestId}`);
|
|
366
|
+
} else if (error instanceof TimeoutError) {
|
|
367
|
+
console.error('Request timed out');
|
|
368
|
+
} else if (error instanceof NetworkError) {
|
|
369
|
+
console.error('Network error:', error.message);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## License
|
|
375
|
+
|
|
376
|
+
MIT
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## API Key Management
|
|
4
|
+
|
|
5
|
+
**IMPORTANT**: Never commit API keys to version control.
|
|
6
|
+
|
|
7
|
+
Your AttentionMarket API key (`am_live_...` or `am_test_...`) provides access to your agent's account and billing. Follow these best practices:
|
|
8
|
+
|
|
9
|
+
### Environment Variables
|
|
10
|
+
|
|
11
|
+
Store your API key in environment variables, not in code:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
export ATTENTIONMARKET_API_KEY=am_live_...
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then use it in your application:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const client = new AttentionMarketClient({
|
|
21
|
+
apiKey: process.env.ATTENTIONMARKET_API_KEY,
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### .gitignore
|
|
26
|
+
|
|
27
|
+
Ensure your `.gitignore` includes:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
.env
|
|
31
|
+
.env.local
|
|
32
|
+
.env.*.local
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Production Deployments
|
|
36
|
+
|
|
37
|
+
- Use secure secret management systems (AWS Secrets Manager, GitHub Secrets, etc.)
|
|
38
|
+
- Rotate API keys periodically
|
|
39
|
+
- Use `am_test_...` keys for development and testing
|
|
40
|
+
- Use `am_live_...` keys only in production environments
|
|
41
|
+
|
|
42
|
+
## Reporting Security Issues
|
|
43
|
+
|
|
44
|
+
If you discover a security vulnerability in this SDK, please email security@attentionmarket.com with:
|
|
45
|
+
|
|
46
|
+
- Description of the vulnerability
|
|
47
|
+
- Steps to reproduce
|
|
48
|
+
- Potential impact
|
|
49
|
+
|
|
50
|
+
Do not open public GitHub issues for security vulnerabilities.
|