@gravity-ai/api 0.0.1 → 0.1.1
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 +207 -28
- package/dist/index.d.mts +261 -11
- package/dist/index.d.ts +261 -11
- package/dist/index.js +98 -18
- package/dist/index.mjs +98 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @gravity-ai/api
|
|
2
2
|
|
|
3
|
-
The official Node.js/TypeScript SDK for the Gravity API.
|
|
3
|
+
The official Node.js/TypeScript SDK for the Gravity AI advertising API. Fetch contextually relevant ads based on conversation content.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,61 +8,240 @@ The official Node.js/TypeScript SDK for the Gravity API.
|
|
|
8
8
|
npm install @gravity-ai/api
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> **Note:** Requires Node.js 18+
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Quick Start
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
import { Client } from '@gravity-ai/api';
|
|
17
17
|
|
|
18
|
-
const client = new Client('
|
|
18
|
+
const client = new Client('your-api-key');
|
|
19
|
+
|
|
20
|
+
const ad = await client.getAd({
|
|
21
|
+
messages: [
|
|
22
|
+
{ role: 'user', content: 'What are some good hiking trails?' },
|
|
23
|
+
{ role: 'assistant', content: 'Here are some popular trails...' }
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (ad) {
|
|
28
|
+
console.log(ad.adText);
|
|
29
|
+
}
|
|
19
30
|
```
|
|
20
31
|
|
|
21
|
-
|
|
32
|
+
## Client Configuration
|
|
22
33
|
|
|
23
|
-
|
|
34
|
+
### Basic Initialization
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Client } from '@gravity-ai/api';
|
|
38
|
+
|
|
39
|
+
const client = new Client('your-api-key');
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Advanced Configuration
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Client } from '@gravity-ai/api';
|
|
46
|
+
|
|
47
|
+
const client = new Client('your-api-key', {
|
|
48
|
+
// Topics to exclude globally (optional)
|
|
49
|
+
excludedTopics: ['politics', 'religion'],
|
|
50
|
+
|
|
51
|
+
// Minimum relevancy threshold 0-1 (optional)
|
|
52
|
+
relevancy: 0.8,
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Configuration Options
|
|
57
|
+
|
|
58
|
+
| Option | Type | Default | Description |
|
|
59
|
+
|--------|------|---------|-------------|
|
|
60
|
+
| `endpoint` | `string` | `'https://server.trygravity.ai'` | API endpoint URL |
|
|
61
|
+
| `excludedTopics` | `string[]` | `[]` | Topics to exclude from ad matching |
|
|
62
|
+
| `relevancy` | `number \| null` | `null` | Minimum relevancy score (0-1) |
|
|
63
|
+
|
|
64
|
+
## Fetching Ads
|
|
65
|
+
|
|
66
|
+
### Basic Request
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const ad = await client.getAd({
|
|
70
|
+
messages: [
|
|
71
|
+
{ role: 'user', content: 'I need help finding a new laptop.' },
|
|
72
|
+
{ role: 'assistant', content: 'What is your budget?' }
|
|
73
|
+
]
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Full Request with All Options
|
|
24
78
|
|
|
25
79
|
```typescript
|
|
26
80
|
const ad = await client.getAd({
|
|
81
|
+
// Required: conversation messages
|
|
27
82
|
messages: [
|
|
28
83
|
{ role: 'user', content: 'I need help finding a new laptop.' },
|
|
29
84
|
{ role: 'assistant', content: 'What is your budget?' }
|
|
30
85
|
],
|
|
31
|
-
|
|
86
|
+
|
|
87
|
+
// Optional: user information for targeting
|
|
32
88
|
user: {
|
|
33
|
-
|
|
34
|
-
|
|
89
|
+
uid: 'user-123', // Unique user identifier
|
|
90
|
+
gender: 'male', // 'male' | 'female' | 'other'
|
|
91
|
+
age: '25-34', // Age range string
|
|
92
|
+
keywords: 'tech,gadgets', // User interest keywords
|
|
35
93
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
94
|
+
|
|
95
|
+
// Optional: device information
|
|
96
|
+
device: {
|
|
97
|
+
ip: '1.2.3.4', // User IP address
|
|
98
|
+
country: 'US', // ISO country code
|
|
99
|
+
ua: 'Mozilla/5.0...', // User agent string
|
|
100
|
+
os: 'macOS', // Operating system
|
|
101
|
+
ifa: 'device-ad-id', // Advertising identifier
|
|
41
102
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
103
|
+
|
|
104
|
+
// Optional: additional targeting context
|
|
105
|
+
excludedTopics: ['politics'], // Override client-level exclusions
|
|
106
|
+
relevancy: 0.8, // Override client-level relevancy
|
|
107
|
+
|
|
108
|
+
// Optional: custom fields (open-ended)
|
|
109
|
+
interests: ['coding', 'apple', 'software development'],
|
|
110
|
+
summary: 'User wants a laptop for software development',
|
|
45
111
|
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Request Parameters
|
|
115
|
+
|
|
116
|
+
| Parameter | Type | Required | Description |
|
|
117
|
+
|-----------|------|----------|-------------|
|
|
118
|
+
| `messages` | `MessageObject[]` | ✅ | Conversation history |
|
|
119
|
+
| `user` | `UserObject` | - | User targeting info |
|
|
120
|
+
| `device` | `DeviceObject` | - | Device/location info |
|
|
121
|
+
| `excludedTopics` | `string[]` | - | Topics to exclude |
|
|
122
|
+
| `relevancy` | `number` | - | Min relevancy (0-1) |
|
|
123
|
+
| `apiKey` | `string` | - | Override client API key |
|
|
124
|
+
| `[key: string]` | `any` | - | Custom fields allowed |
|
|
125
|
+
|
|
126
|
+
### Message Object
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface MessageObject {
|
|
130
|
+
role: 'user' | 'assistant';
|
|
131
|
+
content: string;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### User Object
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface UserObject {
|
|
139
|
+
uid?: string; // Unique user ID
|
|
140
|
+
gender?: 'male' | 'female' | 'other'; // User gender
|
|
141
|
+
age?: string; // Age range (e.g., '25-34')
|
|
142
|
+
keywords?: string; // Interest keywords
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Device Object
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface DeviceObject {
|
|
150
|
+
ip: string; // IP address
|
|
151
|
+
country: string; // ISO country code
|
|
152
|
+
ua: string; // User agent
|
|
153
|
+
os?: string; // Operating system
|
|
154
|
+
ifa?: string; // Advertising ID
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Ad Response
|
|
159
|
+
|
|
160
|
+
The `getAd` method returns an `AdResponse` object or `null` if no relevant ad is found.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
interface AdResponse {
|
|
164
|
+
adText: string; // The ad copy to display
|
|
165
|
+
impUrl?: string; // Impression tracking URL (fire on view)
|
|
166
|
+
clickUrl?: string; // Click-through URL
|
|
167
|
+
payout?: number; // Payout amount
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Handling the Response
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const ad = await client.getAd({ messages });
|
|
46
175
|
|
|
47
176
|
if (ad) {
|
|
48
|
-
|
|
49
|
-
console.log('
|
|
50
|
-
|
|
51
|
-
|
|
177
|
+
// Display the ad
|
|
178
|
+
console.log('Ad:', ad.adText);
|
|
179
|
+
|
|
180
|
+
// Track impression (fire pixel)
|
|
181
|
+
if (ad.impUrl) {
|
|
182
|
+
fetch(ad.impUrl); // or use an image beacon
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Handle clicks
|
|
186
|
+
if (ad.clickUrl) {
|
|
187
|
+
// Navigate user to ad.clickUrl on click
|
|
188
|
+
}
|
|
52
189
|
} else {
|
|
53
|
-
|
|
190
|
+
// No relevant ad found - show fallback or nothing
|
|
191
|
+
console.log('No ad available');
|
|
54
192
|
}
|
|
55
193
|
```
|
|
56
194
|
|
|
57
|
-
|
|
195
|
+
## Error Handling
|
|
58
196
|
|
|
59
|
-
|
|
197
|
+
The client handles errors gracefully and returns `null` on failure. Errors are logged to the console.
|
|
60
198
|
|
|
61
199
|
```typescript
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
200
|
+
const ad = await client.getAd({ messages });
|
|
201
|
+
|
|
202
|
+
// Returns null on:
|
|
203
|
+
// - Network errors
|
|
204
|
+
// - API errors (4xx, 5xx)
|
|
205
|
+
// - No relevant ad (204)
|
|
206
|
+
// - Invalid response data
|
|
207
|
+
|
|
208
|
+
if (!ad) {
|
|
209
|
+
// Handle gracefully - don't break the user experience
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## TypeScript
|
|
214
|
+
|
|
215
|
+
Full TypeScript support with exported types:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { Client, ClientParams } from '@gravity-ai/api';
|
|
219
|
+
import type { AdParams, AdResponse, MessageObject, DeviceObject, UserObject } from '@gravity-ai/api';
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Using with React
|
|
223
|
+
|
|
224
|
+
For React applications, consider using the companion package `@gravity-ai/react` which provides ready-to-use components with automatic tracking:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
npm install @gravity-ai/api @gravity-ai/react
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { Client } from '@gravity-ai/api';
|
|
232
|
+
import { AdBanner } from '@gravity-ai/react';
|
|
233
|
+
|
|
234
|
+
const client = new Client('your-api-key');
|
|
235
|
+
|
|
236
|
+
function ChatApp() {
|
|
237
|
+
const [ad, setAd] = useState(null);
|
|
238
|
+
|
|
239
|
+
useEffect(() => {
|
|
240
|
+
client.getAd({ messages }).then(setAd);
|
|
241
|
+
}, [messages]);
|
|
242
|
+
|
|
243
|
+
return <AdBanner ad={ad} theme="dark" />;
|
|
244
|
+
}
|
|
66
245
|
```
|
|
67
246
|
|
|
68
247
|
## License
|
package/dist/index.d.mts
CHANGED
|
@@ -1,68 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role type for conversation messages
|
|
3
|
+
* @description Indicates whether a message is from the user or the AI assistant
|
|
4
|
+
*/
|
|
1
5
|
type Role = 'user' | 'assistant';
|
|
6
|
+
/**
|
|
7
|
+
* Gender type for user targeting
|
|
8
|
+
* @description Used for demographic targeting of advertisements
|
|
9
|
+
*/
|
|
2
10
|
type Gender = 'male' | 'female' | 'other';
|
|
11
|
+
/**
|
|
12
|
+
* Represents a single message in a conversation
|
|
13
|
+
* @description Used to provide conversation context for contextual ad targeting
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const message: MessageObject = {
|
|
17
|
+
* role: 'user',
|
|
18
|
+
* content: 'I need help finding a new laptop.'
|
|
19
|
+
* };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
3
22
|
interface MessageObject {
|
|
23
|
+
/** The role of the message sender - either 'user' or 'assistant' */
|
|
4
24
|
role: Role;
|
|
25
|
+
/** The text content of the message */
|
|
5
26
|
content: string;
|
|
6
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Device and location information for ad targeting
|
|
30
|
+
* @description Provides device-level context for better ad relevance and compliance
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const device: DeviceObject = {
|
|
34
|
+
* ip: '192.168.1.1',
|
|
35
|
+
* country: 'US',
|
|
36
|
+
* ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
|
|
37
|
+
* os: 'macOS'
|
|
38
|
+
* };
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
7
41
|
interface DeviceObject {
|
|
42
|
+
/** User's IP address for geo-targeting */
|
|
8
43
|
ip: string;
|
|
44
|
+
/** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
|
|
9
45
|
country: string;
|
|
46
|
+
/** User agent string from the browser */
|
|
10
47
|
ua: string;
|
|
48
|
+
/** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
|
|
11
49
|
os?: string;
|
|
50
|
+
/** Identifier for Advertisers (mobile advertising ID) */
|
|
12
51
|
ifa?: string;
|
|
13
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* User profile information for ad targeting
|
|
55
|
+
* @description Demographic and interest data for personalized ad delivery
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const user: UserObject = {
|
|
59
|
+
* uid: 'user-123',
|
|
60
|
+
* gender: 'male',
|
|
61
|
+
* age: '25-34',
|
|
62
|
+
* keywords: 'technology,programming,gaming'
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
14
66
|
interface UserObject {
|
|
67
|
+
/** Unique user identifier for frequency capping and tracking */
|
|
15
68
|
uid?: string;
|
|
69
|
+
/** User's gender for demographic targeting */
|
|
16
70
|
gender?: Gender;
|
|
71
|
+
/** Age range string (e.g., '18-24', '25-34', '35-44', '45-54', '55-64', '65+') */
|
|
17
72
|
age?: string;
|
|
73
|
+
/** Comma-separated keywords representing user interests */
|
|
18
74
|
keywords?: string;
|
|
19
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Parameters for requesting an advertisement
|
|
78
|
+
* @description The complete request payload for the getAd() method
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const params: AdParams = {
|
|
82
|
+
* messages: [
|
|
83
|
+
* { role: 'user', content: 'What laptop should I buy?' },
|
|
84
|
+
* { role: 'assistant', content: 'What is your budget?' }
|
|
85
|
+
* ],
|
|
86
|
+
* user: { gender: 'male', age: '25-34' },
|
|
87
|
+
* device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
|
|
88
|
+
* excludedTopics: ['politics'],
|
|
89
|
+
* relevancy: 0.5
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
20
93
|
interface AdParams {
|
|
94
|
+
/** Override the client's API key for this request */
|
|
21
95
|
apiKey?: string;
|
|
96
|
+
/** Array of conversation messages for contextual targeting (required) */
|
|
22
97
|
messages: MessageObject[];
|
|
98
|
+
/** Device and location information */
|
|
23
99
|
device?: DeviceObject;
|
|
100
|
+
/** User demographic and interest data */
|
|
24
101
|
user?: UserObject;
|
|
102
|
+
/** Topics to exclude from ad matching (e.g., ['politics', 'religion']) */
|
|
25
103
|
excludedTopics?: string[];
|
|
26
|
-
|
|
104
|
+
/** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
|
|
105
|
+
relevancy?: number | null;
|
|
106
|
+
/**
|
|
107
|
+
* Additional custom fields for publisher-specific targeting
|
|
108
|
+
* @description Any additional key-value pairs will be passed to the API
|
|
109
|
+
*/
|
|
110
|
+
[key: string]: unknown;
|
|
27
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Response from the Gravity API containing ad data
|
|
114
|
+
* @description Returned by getAd() when a relevant advertisement is found
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const ad: AdResponse = {
|
|
118
|
+
* adText: 'Check out our amazing laptops!',
|
|
119
|
+
* impUrl: 'https://tracking.example.com/imp?id=123',
|
|
120
|
+
* clickUrl: 'https://example.com/laptops',
|
|
121
|
+
* payout: 0.50
|
|
122
|
+
* };
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
28
125
|
interface AdResponse {
|
|
126
|
+
/** The advertisement copy text to display to the user */
|
|
29
127
|
adText: string;
|
|
128
|
+
/**
|
|
129
|
+
* Impression tracking URL - fire this when the ad is viewed
|
|
130
|
+
* @description Should be loaded (e.g., via image beacon) when ad becomes visible
|
|
131
|
+
*/
|
|
30
132
|
impUrl?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Click-through URL - navigate user here when ad is clicked
|
|
135
|
+
* @description The destination page when the user clicks the ad
|
|
136
|
+
*/
|
|
31
137
|
clickUrl?: string;
|
|
138
|
+
/**
|
|
139
|
+
* Payout amount in USD for this ad impression
|
|
140
|
+
* @description The revenue earned for displaying this ad
|
|
141
|
+
*/
|
|
32
142
|
payout?: number;
|
|
33
143
|
}
|
|
34
144
|
/**
|
|
35
|
-
*
|
|
145
|
+
* Error response structure from the Gravity API
|
|
146
|
+
* @description Returned when the API encounters an error processing the request
|
|
36
147
|
*/
|
|
37
148
|
interface ApiErrorResponse {
|
|
149
|
+
/** Error code or type identifier */
|
|
38
150
|
error: string;
|
|
151
|
+
/** Human-readable error description */
|
|
39
152
|
message?: string;
|
|
153
|
+
/** HTTP status code */
|
|
40
154
|
statusCode?: number;
|
|
41
155
|
}
|
|
42
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Configuration options for the Gravity API Client
|
|
159
|
+
* @description Pass these options when creating a new Client instance
|
|
160
|
+
* @example
|
|
161
|
+
* ```typescript
|
|
162
|
+
* const params: ClientParams = {
|
|
163
|
+
* endpoint: 'https://custom.gravity.server',
|
|
164
|
+
* excludedTopics: ['politics', 'religion'],
|
|
165
|
+
* relevancy: 0.5
|
|
166
|
+
* };
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
43
169
|
interface ClientParams {
|
|
170
|
+
/**
|
|
171
|
+
* Custom API endpoint URL
|
|
172
|
+
* @default 'https://server.trygravity.ai'
|
|
173
|
+
*/
|
|
44
174
|
endpoint?: string;
|
|
175
|
+
/**
|
|
176
|
+
* Topics to exclude from all ad requests
|
|
177
|
+
* @description These exclusions apply to all getAd() calls unless overridden
|
|
178
|
+
* @example ['politics', 'religion', 'adult']
|
|
179
|
+
*/
|
|
45
180
|
excludedTopics?: string[];
|
|
181
|
+
/**
|
|
182
|
+
* Default minimum relevancy threshold (0-1)
|
|
183
|
+
* @description Higher values return more relevant ads but may reduce fill rate
|
|
184
|
+
* @default null (no threshold)
|
|
185
|
+
*/
|
|
186
|
+
relevancy?: number | null;
|
|
46
187
|
}
|
|
47
188
|
/**
|
|
48
|
-
*
|
|
189
|
+
* Gravity API Client
|
|
190
|
+
*
|
|
191
|
+
* @description The main client for interacting with the Gravity AI advertising API.
|
|
192
|
+
* Use this client to fetch contextually relevant advertisements based on conversation content.
|
|
193
|
+
*
|
|
194
|
+
* @example Basic usage
|
|
195
|
+
* ```typescript
|
|
196
|
+
* import { Client } from '@gravity-ai/api';
|
|
197
|
+
*
|
|
198
|
+
* const client = new Client('your-api-key');
|
|
199
|
+
*
|
|
200
|
+
* const ad = await client.getAd({
|
|
201
|
+
* messages: [
|
|
202
|
+
* { role: 'user', content: 'What laptop should I buy?' }
|
|
203
|
+
* ]
|
|
204
|
+
* });
|
|
205
|
+
*
|
|
206
|
+
* if (ad) {
|
|
207
|
+
* console.log(ad.adText);
|
|
208
|
+
* }
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @example With configuration options
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const client = new Client('your-api-key', {
|
|
214
|
+
* endpoint: 'https://custom.server.com',
|
|
215
|
+
* excludedTopics: ['politics'],
|
|
216
|
+
* relevancy: 0.7
|
|
217
|
+
* });
|
|
218
|
+
* ```
|
|
49
219
|
*/
|
|
50
220
|
declare class Client {
|
|
221
|
+
/** The API key used for authentication */
|
|
51
222
|
private apiKey;
|
|
52
|
-
|
|
53
|
-
private
|
|
223
|
+
/** The API endpoint URL */
|
|
224
|
+
private endpoint;
|
|
225
|
+
/** Topics to exclude from ad matching */
|
|
226
|
+
private excludedTopics;
|
|
227
|
+
/** Minimum relevancy threshold */
|
|
228
|
+
private relevancy;
|
|
229
|
+
/** Axios HTTP client instance */
|
|
54
230
|
private axios;
|
|
231
|
+
/**
|
|
232
|
+
* Create a new Gravity API client
|
|
233
|
+
*
|
|
234
|
+
* @param apiKey - Your Gravity API key (required)
|
|
235
|
+
* @param params - Optional configuration parameters
|
|
236
|
+
*
|
|
237
|
+
* @throws Will not throw - invalid API key errors occur on first request
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* // Basic initialization
|
|
242
|
+
* const client = new Client('your-api-key');
|
|
243
|
+
*
|
|
244
|
+
* // With custom options
|
|
245
|
+
* const client = new Client('your-api-key', {
|
|
246
|
+
* excludedTopics: ['gambling', 'alcohol'],
|
|
247
|
+
* relevancy: 0.6
|
|
248
|
+
* });
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
55
251
|
constructor(apiKey: string, params?: ClientParams);
|
|
56
252
|
/**
|
|
57
|
-
* Request a
|
|
58
|
-
*
|
|
59
|
-
* @
|
|
253
|
+
* Request a contextually relevant advertisement
|
|
254
|
+
*
|
|
255
|
+
* @description Fetches an ad based on the provided conversation context and targeting parameters.
|
|
256
|
+
* Returns `null` if no relevant ad is available or if an error occurs.
|
|
257
|
+
*
|
|
258
|
+
* @param params - Ad request parameters including conversation messages
|
|
259
|
+
* @returns Promise resolving to AdResponse or null if no ad available
|
|
260
|
+
*
|
|
261
|
+
* @example Basic request
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const ad = await client.getAd({
|
|
264
|
+
* messages: [
|
|
265
|
+
* { role: 'user', content: 'I need a new laptop for programming' },
|
|
266
|
+
* { role: 'assistant', content: 'What is your budget range?' }
|
|
267
|
+
* ]
|
|
268
|
+
* });
|
|
269
|
+
* ```
|
|
270
|
+
*
|
|
271
|
+
* @example Full request with targeting
|
|
272
|
+
* ```typescript
|
|
273
|
+
* const ad = await client.getAd({
|
|
274
|
+
* messages: [...],
|
|
275
|
+
* user: {
|
|
276
|
+
* uid: 'user-123',
|
|
277
|
+
* gender: 'male',
|
|
278
|
+
* age: '25-34'
|
|
279
|
+
* },
|
|
280
|
+
* device: {
|
|
281
|
+
* ip: '192.168.1.1',
|
|
282
|
+
* country: 'US',
|
|
283
|
+
* ua: navigator.userAgent
|
|
284
|
+
* },
|
|
285
|
+
* excludedTopics: ['gambling'],
|
|
286
|
+
* relevancy: 0.8
|
|
287
|
+
* });
|
|
288
|
+
* ```
|
|
289
|
+
*
|
|
290
|
+
* @example Handling the response
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const ad = await client.getAd({ messages });
|
|
293
|
+
*
|
|
294
|
+
* if (ad) {
|
|
295
|
+
* // Display the ad
|
|
296
|
+
* showAd(ad.adText);
|
|
297
|
+
*
|
|
298
|
+
* // Track impression
|
|
299
|
+
* if (ad.impUrl) {
|
|
300
|
+
* new Image().src = ad.impUrl;
|
|
301
|
+
* }
|
|
302
|
+
* }
|
|
303
|
+
* ```
|
|
60
304
|
*/
|
|
61
305
|
getAd(params: AdParams): Promise<AdResponse | null>;
|
|
62
306
|
/**
|
|
63
|
-
* Handle API errors
|
|
64
|
-
*
|
|
65
|
-
* @
|
|
307
|
+
* Handle and log API errors
|
|
308
|
+
*
|
|
309
|
+
* @description Processes errors from API calls and logs appropriate messages.
|
|
310
|
+
* Distinguishes between network errors, server errors, and unexpected errors.
|
|
311
|
+
*
|
|
312
|
+
* @param error - The error object from the failed request
|
|
313
|
+
* @param method - The name of the method where the error occurred
|
|
314
|
+
*
|
|
315
|
+
* @internal This method is for internal use only
|
|
66
316
|
*/
|
|
67
317
|
private handleError;
|
|
68
318
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,68 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role type for conversation messages
|
|
3
|
+
* @description Indicates whether a message is from the user or the AI assistant
|
|
4
|
+
*/
|
|
1
5
|
type Role = 'user' | 'assistant';
|
|
6
|
+
/**
|
|
7
|
+
* Gender type for user targeting
|
|
8
|
+
* @description Used for demographic targeting of advertisements
|
|
9
|
+
*/
|
|
2
10
|
type Gender = 'male' | 'female' | 'other';
|
|
11
|
+
/**
|
|
12
|
+
* Represents a single message in a conversation
|
|
13
|
+
* @description Used to provide conversation context for contextual ad targeting
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const message: MessageObject = {
|
|
17
|
+
* role: 'user',
|
|
18
|
+
* content: 'I need help finding a new laptop.'
|
|
19
|
+
* };
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
3
22
|
interface MessageObject {
|
|
23
|
+
/** The role of the message sender - either 'user' or 'assistant' */
|
|
4
24
|
role: Role;
|
|
25
|
+
/** The text content of the message */
|
|
5
26
|
content: string;
|
|
6
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Device and location information for ad targeting
|
|
30
|
+
* @description Provides device-level context for better ad relevance and compliance
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const device: DeviceObject = {
|
|
34
|
+
* ip: '192.168.1.1',
|
|
35
|
+
* country: 'US',
|
|
36
|
+
* ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
|
|
37
|
+
* os: 'macOS'
|
|
38
|
+
* };
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
7
41
|
interface DeviceObject {
|
|
42
|
+
/** User's IP address for geo-targeting */
|
|
8
43
|
ip: string;
|
|
44
|
+
/** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
|
|
9
45
|
country: string;
|
|
46
|
+
/** User agent string from the browser */
|
|
10
47
|
ua: string;
|
|
48
|
+
/** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
|
|
11
49
|
os?: string;
|
|
50
|
+
/** Identifier for Advertisers (mobile advertising ID) */
|
|
12
51
|
ifa?: string;
|
|
13
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* User profile information for ad targeting
|
|
55
|
+
* @description Demographic and interest data for personalized ad delivery
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const user: UserObject = {
|
|
59
|
+
* uid: 'user-123',
|
|
60
|
+
* gender: 'male',
|
|
61
|
+
* age: '25-34',
|
|
62
|
+
* keywords: 'technology,programming,gaming'
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
14
66
|
interface UserObject {
|
|
67
|
+
/** Unique user identifier for frequency capping and tracking */
|
|
15
68
|
uid?: string;
|
|
69
|
+
/** User's gender for demographic targeting */
|
|
16
70
|
gender?: Gender;
|
|
71
|
+
/** Age range string (e.g., '18-24', '25-34', '35-44', '45-54', '55-64', '65+') */
|
|
17
72
|
age?: string;
|
|
73
|
+
/** Comma-separated keywords representing user interests */
|
|
18
74
|
keywords?: string;
|
|
19
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Parameters for requesting an advertisement
|
|
78
|
+
* @description The complete request payload for the getAd() method
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const params: AdParams = {
|
|
82
|
+
* messages: [
|
|
83
|
+
* { role: 'user', content: 'What laptop should I buy?' },
|
|
84
|
+
* { role: 'assistant', content: 'What is your budget?' }
|
|
85
|
+
* ],
|
|
86
|
+
* user: { gender: 'male', age: '25-34' },
|
|
87
|
+
* device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
|
|
88
|
+
* excludedTopics: ['politics'],
|
|
89
|
+
* relevancy: 0.5
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
20
93
|
interface AdParams {
|
|
94
|
+
/** Override the client's API key for this request */
|
|
21
95
|
apiKey?: string;
|
|
96
|
+
/** Array of conversation messages for contextual targeting (required) */
|
|
22
97
|
messages: MessageObject[];
|
|
98
|
+
/** Device and location information */
|
|
23
99
|
device?: DeviceObject;
|
|
100
|
+
/** User demographic and interest data */
|
|
24
101
|
user?: UserObject;
|
|
102
|
+
/** Topics to exclude from ad matching (e.g., ['politics', 'religion']) */
|
|
25
103
|
excludedTopics?: string[];
|
|
26
|
-
|
|
104
|
+
/** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
|
|
105
|
+
relevancy?: number | null;
|
|
106
|
+
/**
|
|
107
|
+
* Additional custom fields for publisher-specific targeting
|
|
108
|
+
* @description Any additional key-value pairs will be passed to the API
|
|
109
|
+
*/
|
|
110
|
+
[key: string]: unknown;
|
|
27
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Response from the Gravity API containing ad data
|
|
114
|
+
* @description Returned by getAd() when a relevant advertisement is found
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const ad: AdResponse = {
|
|
118
|
+
* adText: 'Check out our amazing laptops!',
|
|
119
|
+
* impUrl: 'https://tracking.example.com/imp?id=123',
|
|
120
|
+
* clickUrl: 'https://example.com/laptops',
|
|
121
|
+
* payout: 0.50
|
|
122
|
+
* };
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
28
125
|
interface AdResponse {
|
|
126
|
+
/** The advertisement copy text to display to the user */
|
|
29
127
|
adText: string;
|
|
128
|
+
/**
|
|
129
|
+
* Impression tracking URL - fire this when the ad is viewed
|
|
130
|
+
* @description Should be loaded (e.g., via image beacon) when ad becomes visible
|
|
131
|
+
*/
|
|
30
132
|
impUrl?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Click-through URL - navigate user here when ad is clicked
|
|
135
|
+
* @description The destination page when the user clicks the ad
|
|
136
|
+
*/
|
|
31
137
|
clickUrl?: string;
|
|
138
|
+
/**
|
|
139
|
+
* Payout amount in USD for this ad impression
|
|
140
|
+
* @description The revenue earned for displaying this ad
|
|
141
|
+
*/
|
|
32
142
|
payout?: number;
|
|
33
143
|
}
|
|
34
144
|
/**
|
|
35
|
-
*
|
|
145
|
+
* Error response structure from the Gravity API
|
|
146
|
+
* @description Returned when the API encounters an error processing the request
|
|
36
147
|
*/
|
|
37
148
|
interface ApiErrorResponse {
|
|
149
|
+
/** Error code or type identifier */
|
|
38
150
|
error: string;
|
|
151
|
+
/** Human-readable error description */
|
|
39
152
|
message?: string;
|
|
153
|
+
/** HTTP status code */
|
|
40
154
|
statusCode?: number;
|
|
41
155
|
}
|
|
42
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Configuration options for the Gravity API Client
|
|
159
|
+
* @description Pass these options when creating a new Client instance
|
|
160
|
+
* @example
|
|
161
|
+
* ```typescript
|
|
162
|
+
* const params: ClientParams = {
|
|
163
|
+
* endpoint: 'https://custom.gravity.server',
|
|
164
|
+
* excludedTopics: ['politics', 'religion'],
|
|
165
|
+
* relevancy: 0.5
|
|
166
|
+
* };
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
43
169
|
interface ClientParams {
|
|
170
|
+
/**
|
|
171
|
+
* Custom API endpoint URL
|
|
172
|
+
* @default 'https://server.trygravity.ai'
|
|
173
|
+
*/
|
|
44
174
|
endpoint?: string;
|
|
175
|
+
/**
|
|
176
|
+
* Topics to exclude from all ad requests
|
|
177
|
+
* @description These exclusions apply to all getAd() calls unless overridden
|
|
178
|
+
* @example ['politics', 'religion', 'adult']
|
|
179
|
+
*/
|
|
45
180
|
excludedTopics?: string[];
|
|
181
|
+
/**
|
|
182
|
+
* Default minimum relevancy threshold (0-1)
|
|
183
|
+
* @description Higher values return more relevant ads but may reduce fill rate
|
|
184
|
+
* @default null (no threshold)
|
|
185
|
+
*/
|
|
186
|
+
relevancy?: number | null;
|
|
46
187
|
}
|
|
47
188
|
/**
|
|
48
|
-
*
|
|
189
|
+
* Gravity API Client
|
|
190
|
+
*
|
|
191
|
+
* @description The main client for interacting with the Gravity AI advertising API.
|
|
192
|
+
* Use this client to fetch contextually relevant advertisements based on conversation content.
|
|
193
|
+
*
|
|
194
|
+
* @example Basic usage
|
|
195
|
+
* ```typescript
|
|
196
|
+
* import { Client } from '@gravity-ai/api';
|
|
197
|
+
*
|
|
198
|
+
* const client = new Client('your-api-key');
|
|
199
|
+
*
|
|
200
|
+
* const ad = await client.getAd({
|
|
201
|
+
* messages: [
|
|
202
|
+
* { role: 'user', content: 'What laptop should I buy?' }
|
|
203
|
+
* ]
|
|
204
|
+
* });
|
|
205
|
+
*
|
|
206
|
+
* if (ad) {
|
|
207
|
+
* console.log(ad.adText);
|
|
208
|
+
* }
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @example With configuration options
|
|
212
|
+
* ```typescript
|
|
213
|
+
* const client = new Client('your-api-key', {
|
|
214
|
+
* endpoint: 'https://custom.server.com',
|
|
215
|
+
* excludedTopics: ['politics'],
|
|
216
|
+
* relevancy: 0.7
|
|
217
|
+
* });
|
|
218
|
+
* ```
|
|
49
219
|
*/
|
|
50
220
|
declare class Client {
|
|
221
|
+
/** The API key used for authentication */
|
|
51
222
|
private apiKey;
|
|
52
|
-
|
|
53
|
-
private
|
|
223
|
+
/** The API endpoint URL */
|
|
224
|
+
private endpoint;
|
|
225
|
+
/** Topics to exclude from ad matching */
|
|
226
|
+
private excludedTopics;
|
|
227
|
+
/** Minimum relevancy threshold */
|
|
228
|
+
private relevancy;
|
|
229
|
+
/** Axios HTTP client instance */
|
|
54
230
|
private axios;
|
|
231
|
+
/**
|
|
232
|
+
* Create a new Gravity API client
|
|
233
|
+
*
|
|
234
|
+
* @param apiKey - Your Gravity API key (required)
|
|
235
|
+
* @param params - Optional configuration parameters
|
|
236
|
+
*
|
|
237
|
+
* @throws Will not throw - invalid API key errors occur on first request
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* // Basic initialization
|
|
242
|
+
* const client = new Client('your-api-key');
|
|
243
|
+
*
|
|
244
|
+
* // With custom options
|
|
245
|
+
* const client = new Client('your-api-key', {
|
|
246
|
+
* excludedTopics: ['gambling', 'alcohol'],
|
|
247
|
+
* relevancy: 0.6
|
|
248
|
+
* });
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
55
251
|
constructor(apiKey: string, params?: ClientParams);
|
|
56
252
|
/**
|
|
57
|
-
* Request a
|
|
58
|
-
*
|
|
59
|
-
* @
|
|
253
|
+
* Request a contextually relevant advertisement
|
|
254
|
+
*
|
|
255
|
+
* @description Fetches an ad based on the provided conversation context and targeting parameters.
|
|
256
|
+
* Returns `null` if no relevant ad is available or if an error occurs.
|
|
257
|
+
*
|
|
258
|
+
* @param params - Ad request parameters including conversation messages
|
|
259
|
+
* @returns Promise resolving to AdResponse or null if no ad available
|
|
260
|
+
*
|
|
261
|
+
* @example Basic request
|
|
262
|
+
* ```typescript
|
|
263
|
+
* const ad = await client.getAd({
|
|
264
|
+
* messages: [
|
|
265
|
+
* { role: 'user', content: 'I need a new laptop for programming' },
|
|
266
|
+
* { role: 'assistant', content: 'What is your budget range?' }
|
|
267
|
+
* ]
|
|
268
|
+
* });
|
|
269
|
+
* ```
|
|
270
|
+
*
|
|
271
|
+
* @example Full request with targeting
|
|
272
|
+
* ```typescript
|
|
273
|
+
* const ad = await client.getAd({
|
|
274
|
+
* messages: [...],
|
|
275
|
+
* user: {
|
|
276
|
+
* uid: 'user-123',
|
|
277
|
+
* gender: 'male',
|
|
278
|
+
* age: '25-34'
|
|
279
|
+
* },
|
|
280
|
+
* device: {
|
|
281
|
+
* ip: '192.168.1.1',
|
|
282
|
+
* country: 'US',
|
|
283
|
+
* ua: navigator.userAgent
|
|
284
|
+
* },
|
|
285
|
+
* excludedTopics: ['gambling'],
|
|
286
|
+
* relevancy: 0.8
|
|
287
|
+
* });
|
|
288
|
+
* ```
|
|
289
|
+
*
|
|
290
|
+
* @example Handling the response
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const ad = await client.getAd({ messages });
|
|
293
|
+
*
|
|
294
|
+
* if (ad) {
|
|
295
|
+
* // Display the ad
|
|
296
|
+
* showAd(ad.adText);
|
|
297
|
+
*
|
|
298
|
+
* // Track impression
|
|
299
|
+
* if (ad.impUrl) {
|
|
300
|
+
* new Image().src = ad.impUrl;
|
|
301
|
+
* }
|
|
302
|
+
* }
|
|
303
|
+
* ```
|
|
60
304
|
*/
|
|
61
305
|
getAd(params: AdParams): Promise<AdResponse | null>;
|
|
62
306
|
/**
|
|
63
|
-
* Handle API errors
|
|
64
|
-
*
|
|
65
|
-
* @
|
|
307
|
+
* Handle and log API errors
|
|
308
|
+
*
|
|
309
|
+
* @description Processes errors from API calls and logs appropriate messages.
|
|
310
|
+
* Distinguishes between network errors, server errors, and unexpected errors.
|
|
311
|
+
*
|
|
312
|
+
* @param error - The error object from the failed request
|
|
313
|
+
* @param method - The name of the method where the error occurred
|
|
314
|
+
*
|
|
315
|
+
* @internal This method is for internal use only
|
|
66
316
|
*/
|
|
67
317
|
private handleError;
|
|
68
318
|
}
|
package/dist/index.js
CHANGED
|
@@ -36,14 +36,37 @@ module.exports = __toCommonJS(index_exports);
|
|
|
36
36
|
|
|
37
37
|
// client.ts
|
|
38
38
|
var import_axios = __toESM(require("axios"));
|
|
39
|
+
var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
|
|
40
|
+
var REQUEST_TIMEOUT = 1e4;
|
|
39
41
|
var Client = class {
|
|
42
|
+
/**
|
|
43
|
+
* Create a new Gravity API client
|
|
44
|
+
*
|
|
45
|
+
* @param apiKey - Your Gravity API key (required)
|
|
46
|
+
* @param params - Optional configuration parameters
|
|
47
|
+
*
|
|
48
|
+
* @throws Will not throw - invalid API key errors occur on first request
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // Basic initialization
|
|
53
|
+
* const client = new Client('your-api-key');
|
|
54
|
+
*
|
|
55
|
+
* // With custom options
|
|
56
|
+
* const client = new Client('your-api-key', {
|
|
57
|
+
* excludedTopics: ['gambling', 'alcohol'],
|
|
58
|
+
* relevancy: 0.6
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
40
62
|
constructor(apiKey, params = {}) {
|
|
41
63
|
this.apiKey = apiKey;
|
|
42
|
-
this.endpoint = params.endpoint ||
|
|
64
|
+
this.endpoint = params.endpoint || DEFAULT_ENDPOINT;
|
|
43
65
|
this.excludedTopics = params.excludedTopics || [];
|
|
66
|
+
this.relevancy = params.relevancy ?? null;
|
|
44
67
|
this.axios = import_axios.default.create({
|
|
45
68
|
baseURL: this.endpoint,
|
|
46
|
-
timeout:
|
|
69
|
+
timeout: REQUEST_TIMEOUT,
|
|
47
70
|
headers: {
|
|
48
71
|
"Authorization": `Bearer ${this.apiKey}`,
|
|
49
72
|
"Content-Type": "application/json"
|
|
@@ -51,40 +74,97 @@ var Client = class {
|
|
|
51
74
|
});
|
|
52
75
|
}
|
|
53
76
|
/**
|
|
54
|
-
* Request a
|
|
55
|
-
*
|
|
56
|
-
* @
|
|
77
|
+
* Request a contextually relevant advertisement
|
|
78
|
+
*
|
|
79
|
+
* @description Fetches an ad based on the provided conversation context and targeting parameters.
|
|
80
|
+
* Returns `null` if no relevant ad is available or if an error occurs.
|
|
81
|
+
*
|
|
82
|
+
* @param params - Ad request parameters including conversation messages
|
|
83
|
+
* @returns Promise resolving to AdResponse or null if no ad available
|
|
84
|
+
*
|
|
85
|
+
* @example Basic request
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const ad = await client.getAd({
|
|
88
|
+
* messages: [
|
|
89
|
+
* { role: 'user', content: 'I need a new laptop for programming' },
|
|
90
|
+
* { role: 'assistant', content: 'What is your budget range?' }
|
|
91
|
+
* ]
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @example Full request with targeting
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const ad = await client.getAd({
|
|
98
|
+
* messages: [...],
|
|
99
|
+
* user: {
|
|
100
|
+
* uid: 'user-123',
|
|
101
|
+
* gender: 'male',
|
|
102
|
+
* age: '25-34'
|
|
103
|
+
* },
|
|
104
|
+
* device: {
|
|
105
|
+
* ip: '192.168.1.1',
|
|
106
|
+
* country: 'US',
|
|
107
|
+
* ua: navigator.userAgent
|
|
108
|
+
* },
|
|
109
|
+
* excludedTopics: ['gambling'],
|
|
110
|
+
* relevancy: 0.8
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @example Handling the response
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const ad = await client.getAd({ messages });
|
|
117
|
+
*
|
|
118
|
+
* if (ad) {
|
|
119
|
+
* // Display the ad
|
|
120
|
+
* showAd(ad.adText);
|
|
121
|
+
*
|
|
122
|
+
* // Track impression
|
|
123
|
+
* if (ad.impUrl) {
|
|
124
|
+
* new Image().src = ad.impUrl;
|
|
125
|
+
* }
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
57
128
|
*/
|
|
58
129
|
async getAd(params) {
|
|
59
130
|
try {
|
|
60
131
|
const body = {
|
|
61
132
|
...params,
|
|
62
|
-
//
|
|
133
|
+
// Prefer explicit apiKey in params, else use client's apiKey
|
|
63
134
|
apiKey: params.apiKey ?? this.apiKey,
|
|
64
|
-
//
|
|
65
|
-
excludedTopics: params.excludedTopics ?? this.excludedTopics
|
|
135
|
+
// Use request-level excludedTopics, or fall back to client-level
|
|
136
|
+
excludedTopics: params.excludedTopics ?? this.excludedTopics,
|
|
137
|
+
// Use request-level relevancy, or fall back to client-level
|
|
138
|
+
relevancy: params.relevancy ?? this.relevancy
|
|
66
139
|
};
|
|
67
140
|
const response = await this.axios.post("/ad", body);
|
|
68
|
-
if (response.status === 204)
|
|
141
|
+
if (response.status === 204) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
69
144
|
if (response.data && response.data.adText) {
|
|
70
|
-
const payload = response.data;
|
|
71
145
|
return {
|
|
72
|
-
adText:
|
|
73
|
-
impUrl:
|
|
74
|
-
clickUrl:
|
|
75
|
-
payout:
|
|
146
|
+
adText: response.data.adText,
|
|
147
|
+
impUrl: response.data.impUrl,
|
|
148
|
+
clickUrl: response.data.clickUrl,
|
|
149
|
+
payout: response.data.payout
|
|
76
150
|
};
|
|
77
151
|
}
|
|
152
|
+
return null;
|
|
78
153
|
} catch (error) {
|
|
79
154
|
this.handleError(error, "getAd");
|
|
80
155
|
return null;
|
|
81
156
|
}
|
|
82
|
-
return null;
|
|
83
157
|
}
|
|
84
158
|
/**
|
|
85
|
-
* Handle API errors
|
|
86
|
-
*
|
|
87
|
-
* @
|
|
159
|
+
* Handle and log API errors
|
|
160
|
+
*
|
|
161
|
+
* @description Processes errors from API calls and logs appropriate messages.
|
|
162
|
+
* Distinguishes between network errors, server errors, and unexpected errors.
|
|
163
|
+
*
|
|
164
|
+
* @param error - The error object from the failed request
|
|
165
|
+
* @param method - The name of the method where the error occurred
|
|
166
|
+
*
|
|
167
|
+
* @internal This method is for internal use only
|
|
88
168
|
*/
|
|
89
169
|
handleError(error, method) {
|
|
90
170
|
if (import_axios.default.isAxiosError(error)) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
// client.ts
|
|
2
2
|
import axios from "axios";
|
|
3
|
+
var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
|
|
4
|
+
var REQUEST_TIMEOUT = 1e4;
|
|
3
5
|
var Client = class {
|
|
6
|
+
/**
|
|
7
|
+
* Create a new Gravity API client
|
|
8
|
+
*
|
|
9
|
+
* @param apiKey - Your Gravity API key (required)
|
|
10
|
+
* @param params - Optional configuration parameters
|
|
11
|
+
*
|
|
12
|
+
* @throws Will not throw - invalid API key errors occur on first request
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Basic initialization
|
|
17
|
+
* const client = new Client('your-api-key');
|
|
18
|
+
*
|
|
19
|
+
* // With custom options
|
|
20
|
+
* const client = new Client('your-api-key', {
|
|
21
|
+
* excludedTopics: ['gambling', 'alcohol'],
|
|
22
|
+
* relevancy: 0.6
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
4
26
|
constructor(apiKey, params = {}) {
|
|
5
27
|
this.apiKey = apiKey;
|
|
6
|
-
this.endpoint = params.endpoint ||
|
|
28
|
+
this.endpoint = params.endpoint || DEFAULT_ENDPOINT;
|
|
7
29
|
this.excludedTopics = params.excludedTopics || [];
|
|
30
|
+
this.relevancy = params.relevancy ?? null;
|
|
8
31
|
this.axios = axios.create({
|
|
9
32
|
baseURL: this.endpoint,
|
|
10
|
-
timeout:
|
|
33
|
+
timeout: REQUEST_TIMEOUT,
|
|
11
34
|
headers: {
|
|
12
35
|
"Authorization": `Bearer ${this.apiKey}`,
|
|
13
36
|
"Content-Type": "application/json"
|
|
@@ -15,40 +38,97 @@ var Client = class {
|
|
|
15
38
|
});
|
|
16
39
|
}
|
|
17
40
|
/**
|
|
18
|
-
* Request a
|
|
19
|
-
*
|
|
20
|
-
* @
|
|
41
|
+
* Request a contextually relevant advertisement
|
|
42
|
+
*
|
|
43
|
+
* @description Fetches an ad based on the provided conversation context and targeting parameters.
|
|
44
|
+
* Returns `null` if no relevant ad is available or if an error occurs.
|
|
45
|
+
*
|
|
46
|
+
* @param params - Ad request parameters including conversation messages
|
|
47
|
+
* @returns Promise resolving to AdResponse or null if no ad available
|
|
48
|
+
*
|
|
49
|
+
* @example Basic request
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const ad = await client.getAd({
|
|
52
|
+
* messages: [
|
|
53
|
+
* { role: 'user', content: 'I need a new laptop for programming' },
|
|
54
|
+
* { role: 'assistant', content: 'What is your budget range?' }
|
|
55
|
+
* ]
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example Full request with targeting
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const ad = await client.getAd({
|
|
62
|
+
* messages: [...],
|
|
63
|
+
* user: {
|
|
64
|
+
* uid: 'user-123',
|
|
65
|
+
* gender: 'male',
|
|
66
|
+
* age: '25-34'
|
|
67
|
+
* },
|
|
68
|
+
* device: {
|
|
69
|
+
* ip: '192.168.1.1',
|
|
70
|
+
* country: 'US',
|
|
71
|
+
* ua: navigator.userAgent
|
|
72
|
+
* },
|
|
73
|
+
* excludedTopics: ['gambling'],
|
|
74
|
+
* relevancy: 0.8
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example Handling the response
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const ad = await client.getAd({ messages });
|
|
81
|
+
*
|
|
82
|
+
* if (ad) {
|
|
83
|
+
* // Display the ad
|
|
84
|
+
* showAd(ad.adText);
|
|
85
|
+
*
|
|
86
|
+
* // Track impression
|
|
87
|
+
* if (ad.impUrl) {
|
|
88
|
+
* new Image().src = ad.impUrl;
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
21
92
|
*/
|
|
22
93
|
async getAd(params) {
|
|
23
94
|
try {
|
|
24
95
|
const body = {
|
|
25
96
|
...params,
|
|
26
|
-
//
|
|
97
|
+
// Prefer explicit apiKey in params, else use client's apiKey
|
|
27
98
|
apiKey: params.apiKey ?? this.apiKey,
|
|
28
|
-
//
|
|
29
|
-
excludedTopics: params.excludedTopics ?? this.excludedTopics
|
|
99
|
+
// Use request-level excludedTopics, or fall back to client-level
|
|
100
|
+
excludedTopics: params.excludedTopics ?? this.excludedTopics,
|
|
101
|
+
// Use request-level relevancy, or fall back to client-level
|
|
102
|
+
relevancy: params.relevancy ?? this.relevancy
|
|
30
103
|
};
|
|
31
104
|
const response = await this.axios.post("/ad", body);
|
|
32
|
-
if (response.status === 204)
|
|
105
|
+
if (response.status === 204) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
33
108
|
if (response.data && response.data.adText) {
|
|
34
|
-
const payload = response.data;
|
|
35
109
|
return {
|
|
36
|
-
adText:
|
|
37
|
-
impUrl:
|
|
38
|
-
clickUrl:
|
|
39
|
-
payout:
|
|
110
|
+
adText: response.data.adText,
|
|
111
|
+
impUrl: response.data.impUrl,
|
|
112
|
+
clickUrl: response.data.clickUrl,
|
|
113
|
+
payout: response.data.payout
|
|
40
114
|
};
|
|
41
115
|
}
|
|
116
|
+
return null;
|
|
42
117
|
} catch (error) {
|
|
43
118
|
this.handleError(error, "getAd");
|
|
44
119
|
return null;
|
|
45
120
|
}
|
|
46
|
-
return null;
|
|
47
121
|
}
|
|
48
122
|
/**
|
|
49
|
-
* Handle API errors
|
|
50
|
-
*
|
|
51
|
-
* @
|
|
123
|
+
* Handle and log API errors
|
|
124
|
+
*
|
|
125
|
+
* @description Processes errors from API calls and logs appropriate messages.
|
|
126
|
+
* Distinguishes between network errors, server errors, and unexpected errors.
|
|
127
|
+
*
|
|
128
|
+
* @param error - The error object from the failed request
|
|
129
|
+
* @param method - The name of the method where the error occurred
|
|
130
|
+
*
|
|
131
|
+
* @internal This method is for internal use only
|
|
52
132
|
*/
|
|
53
133
|
handleError(error, method) {
|
|
54
134
|
if (axios.isAxiosError(error)) {
|