@action-x/ad-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/README.md +678 -0
- package/dist/index.cjs +139 -0
- package/dist/index.d.ts +1552 -0
- package/dist/index.js +1478 -0
- package/dist/index.umd.js +139 -0
- package/dist/style.css +1 -0
- package/package.json +30 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1552 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Card Variant
|
|
3
|
+
*/
|
|
4
|
+
export declare type ActionCardVariant = 'horizontal' | 'vertical' | 'compact';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Analytics 信息(用于 SDK 内部传递)
|
|
8
|
+
*/
|
|
9
|
+
export declare interface AdAnalyticsInfo {
|
|
10
|
+
requestId: string;
|
|
11
|
+
slotId: string;
|
|
12
|
+
position: number;
|
|
13
|
+
totalAds: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Convert AdaptedAdContent to KoahAd format
|
|
18
|
+
* This allows using adapted ads with existing components
|
|
19
|
+
*/
|
|
20
|
+
export declare function adaptAdToKoahAd(adaptedAd: AdaptedAdContent): KoahAd;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Adapted Ad Content
|
|
24
|
+
* Backend adapts the ad content based on slot requirements
|
|
25
|
+
*/
|
|
26
|
+
export declare interface AdaptedAdContent {
|
|
27
|
+
original: {
|
|
28
|
+
id: string;
|
|
29
|
+
type: AdFormat;
|
|
30
|
+
score: number;
|
|
31
|
+
};
|
|
32
|
+
adapted: {
|
|
33
|
+
title: string;
|
|
34
|
+
body: string;
|
|
35
|
+
ctaText: string;
|
|
36
|
+
image?: AdaptedAdImage;
|
|
37
|
+
price?: AdaptedAdPrice;
|
|
38
|
+
rating?: number;
|
|
39
|
+
brand?: string;
|
|
40
|
+
styling?: AdaptedAdStyling;
|
|
41
|
+
/** Entity link content (for entity_link format) */
|
|
42
|
+
entityLinkContent?: EntityLinkAdContent;
|
|
43
|
+
};
|
|
44
|
+
tracking: {
|
|
45
|
+
impressionUrl: string;
|
|
46
|
+
clickUrl: string;
|
|
47
|
+
viewToken: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Adapted Ad Image
|
|
53
|
+
*/
|
|
54
|
+
export declare interface AdaptedAdImage {
|
|
55
|
+
url: string;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
aspectRatio: string;
|
|
59
|
+
fallbackColor?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Adapted Ad Price
|
|
64
|
+
*/
|
|
65
|
+
export declare interface AdaptedAdPrice {
|
|
66
|
+
display: string;
|
|
67
|
+
value: number;
|
|
68
|
+
currency: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Adapted Ad Styling Suggestions
|
|
73
|
+
*/
|
|
74
|
+
export declare interface AdaptedAdStyling {
|
|
75
|
+
backgroundColor?: string;
|
|
76
|
+
textColor?: string;
|
|
77
|
+
accentColor?: string;
|
|
78
|
+
borderRadius?: string;
|
|
79
|
+
padding?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Ad Format Types
|
|
84
|
+
* Supported native ad formats
|
|
85
|
+
*/
|
|
86
|
+
export declare type AdFormat = 'action_card' | 'suffix' | 'followup' | 'source' | 'static' | 'lead_gen' | 'entity_link';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* AdManager - Framework-agnostic ad management
|
|
90
|
+
*/
|
|
91
|
+
export declare class AdManager {
|
|
92
|
+
private config;
|
|
93
|
+
private slots;
|
|
94
|
+
private eventBus;
|
|
95
|
+
private isLoading;
|
|
96
|
+
private enabled;
|
|
97
|
+
private currentRequestId;
|
|
98
|
+
private adsAnalyticsMap;
|
|
99
|
+
constructor(config: AdManagerConfig);
|
|
100
|
+
/**
|
|
101
|
+
* Request ads for all configured slots
|
|
102
|
+
* ClientInfo is automatically collected and injected
|
|
103
|
+
*
|
|
104
|
+
* @param context - Conversation and user context
|
|
105
|
+
* @returns Promise resolving to ad response batch
|
|
106
|
+
*/
|
|
107
|
+
requestAds(context: {
|
|
108
|
+
conversationContext: ConversationContext;
|
|
109
|
+
userContext?: UserContext;
|
|
110
|
+
}): Promise<AdResponseBatch>;
|
|
111
|
+
/**
|
|
112
|
+
* Render a single ad from a slot into a container element
|
|
113
|
+
*
|
|
114
|
+
* @param slotId - Slot ID to render
|
|
115
|
+
* @param container - DOM element to render into
|
|
116
|
+
* @param options - Rendering options
|
|
117
|
+
* @returns Rendered HTMLElement or null if slot/ad not found
|
|
118
|
+
*/
|
|
119
|
+
render(slotId: string, container: HTMLElement, options?: {
|
|
120
|
+
adIndex?: number;
|
|
121
|
+
variant?: 'horizontal' | 'vertical' | 'compact' | 'block' | 'inline' | 'minimal' | 'card' | 'list-item';
|
|
122
|
+
onClick?: (ad: any) => void;
|
|
123
|
+
onImpression?: (ad: any) => void;
|
|
124
|
+
}): HTMLElement | null;
|
|
125
|
+
/**
|
|
126
|
+
* Get ad slots data
|
|
127
|
+
*/
|
|
128
|
+
getSlots(slotId?: string): Record<string, AdSlotResponse> | AdSlotResponse | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Check if a slot has ads
|
|
131
|
+
*/
|
|
132
|
+
hasAds(slotId: string): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Get ads for a specific slot
|
|
135
|
+
*/
|
|
136
|
+
getAds(slotId: string): any[];
|
|
137
|
+
/**
|
|
138
|
+
* Check if currently loading
|
|
139
|
+
*/
|
|
140
|
+
getLoadingStatus(): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Enable or disable ads
|
|
143
|
+
*/
|
|
144
|
+
setEnabled(enabled: boolean): void;
|
|
145
|
+
/**
|
|
146
|
+
* Update configuration
|
|
147
|
+
*/
|
|
148
|
+
updateConfig(config: Partial<AdManagerConfig>): void;
|
|
149
|
+
/**
|
|
150
|
+
* Clear all slot data
|
|
151
|
+
*/
|
|
152
|
+
clearSlots(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Register event listener
|
|
155
|
+
*/
|
|
156
|
+
on<K extends keyof AdManagerEvents>(event: K, callback: AdManagerEvents[K]): void;
|
|
157
|
+
/**
|
|
158
|
+
* Remove event listener
|
|
159
|
+
*/
|
|
160
|
+
off<K extends keyof AdManagerEvents>(event: K, callback: AdManagerEvents[K]): void;
|
|
161
|
+
/**
|
|
162
|
+
* Remove all event listeners
|
|
163
|
+
*/
|
|
164
|
+
removeAllListeners(event?: string): void;
|
|
165
|
+
/**
|
|
166
|
+
* Get current requestId
|
|
167
|
+
*/
|
|
168
|
+
getCurrentRequestId(): string | null;
|
|
169
|
+
/**
|
|
170
|
+
* Get analytics info for a single ad
|
|
171
|
+
*/
|
|
172
|
+
getAdAnalytics(adId: string): AdAnalyticsInfo | null;
|
|
173
|
+
/**
|
|
174
|
+
* Get analytics info for multiple ads
|
|
175
|
+
*/
|
|
176
|
+
getAdsAnalytics(adIds: string[]): Map<string, AdAnalyticsInfo>;
|
|
177
|
+
/**
|
|
178
|
+
* Track ad click using Analytics API
|
|
179
|
+
*/
|
|
180
|
+
trackAdClick(adId: string, destinationUrl: string, adData?: {
|
|
181
|
+
title?: string;
|
|
182
|
+
format?: string;
|
|
183
|
+
source?: string;
|
|
184
|
+
}): Promise<ClickResponse | null>;
|
|
185
|
+
/**
|
|
186
|
+
* Track ad impression using Analytics API
|
|
187
|
+
*/
|
|
188
|
+
trackAdImpressionAPI(adId: string, adData?: {
|
|
189
|
+
title?: string;
|
|
190
|
+
format?: string;
|
|
191
|
+
source?: string;
|
|
192
|
+
viewToken?: string;
|
|
193
|
+
}): Promise<ImpressionResponse | null>;
|
|
194
|
+
/**
|
|
195
|
+
* Destroy the manager and clean up
|
|
196
|
+
*/
|
|
197
|
+
destroy(): void;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Configuration for AdManager
|
|
202
|
+
*/
|
|
203
|
+
export declare interface AdManagerConfig {
|
|
204
|
+
/** Base URL for API requests */
|
|
205
|
+
apiBaseUrl: string;
|
|
206
|
+
/** API Key for authentication */
|
|
207
|
+
apiKey?: string;
|
|
208
|
+
/** Ad slot configurations */
|
|
209
|
+
slots: AdSlotRequest[];
|
|
210
|
+
/** Whether ads are enabled */
|
|
211
|
+
enabled?: boolean;
|
|
212
|
+
/** Enable debug logging */
|
|
213
|
+
debug?: boolean;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Events emitted by AdManager
|
|
218
|
+
*/
|
|
219
|
+
export declare type AdManagerEvents = {
|
|
220
|
+
'adsUpdated': (slots: Record<string, AdSlotResponse>) => void;
|
|
221
|
+
'adsLoading': () => void;
|
|
222
|
+
'adsError': (error: Error) => void;
|
|
223
|
+
'adClicked': (adId: string, slotId: string) => void;
|
|
224
|
+
'adImpression': (adId: string, slotId: string) => void;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Ad Request Batch
|
|
229
|
+
* Request multiple ad slots in one API call
|
|
230
|
+
*/
|
|
231
|
+
export declare interface AdRequestBatch {
|
|
232
|
+
conversationContext: ConversationContext;
|
|
233
|
+
userContext?: UserContext;
|
|
234
|
+
slots: AdSlotRequest[];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Ad Response Batch
|
|
239
|
+
*/
|
|
240
|
+
export declare interface AdResponseBatch {
|
|
241
|
+
requestId: string;
|
|
242
|
+
timestamp: number;
|
|
243
|
+
intent: IntentResult;
|
|
244
|
+
slots: AdSlotResponse[];
|
|
245
|
+
globalSuggestions?: GlobalSuggestions;
|
|
246
|
+
metadata?: ResponseMetadata;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Slot 信息
|
|
251
|
+
*/
|
|
252
|
+
export declare interface AdSlotInfo {
|
|
253
|
+
ads: any[];
|
|
254
|
+
count: number;
|
|
255
|
+
status: string;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Ad Slot Placement Context
|
|
260
|
+
*/
|
|
261
|
+
export declare interface AdSlotPlacement {
|
|
262
|
+
position: 'above_fold' | 'below_fold' | 'sidebar' | 'inline';
|
|
263
|
+
context: string;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Ad Slot Preferences
|
|
268
|
+
*/
|
|
269
|
+
export declare interface AdSlotPreferences {
|
|
270
|
+
maxTitleLength?: number;
|
|
271
|
+
maxBodyLength?: number;
|
|
272
|
+
requireImage?: boolean;
|
|
273
|
+
imageAspectRatio?: string;
|
|
274
|
+
showPrice?: boolean;
|
|
275
|
+
showRating?: boolean;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Ad Slot Request
|
|
280
|
+
* Frontend declares requirements for each ad slot
|
|
281
|
+
*/
|
|
282
|
+
export declare interface AdSlotRequest {
|
|
283
|
+
slotId: string;
|
|
284
|
+
slotName: string;
|
|
285
|
+
format: AdFormat;
|
|
286
|
+
variant?: string;
|
|
287
|
+
size: AdSlotSize;
|
|
288
|
+
count?: number;
|
|
289
|
+
preferences?: AdSlotPreferences;
|
|
290
|
+
placement: AdSlotPlacement;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Ad Slot Response
|
|
295
|
+
*/
|
|
296
|
+
export declare interface AdSlotResponse {
|
|
297
|
+
slotId: string;
|
|
298
|
+
status: 'filled' | 'no_fill' | 'error';
|
|
299
|
+
error?: string;
|
|
300
|
+
ads: AdaptedAdContent[];
|
|
301
|
+
suggestions?: AdSlotSuggestions;
|
|
302
|
+
metadata?: SlotDecisionMetadata;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Ad Slot Size Requirements
|
|
307
|
+
*/
|
|
308
|
+
export declare interface AdSlotSize {
|
|
309
|
+
width: number;
|
|
310
|
+
height: number;
|
|
311
|
+
minWidth?: number;
|
|
312
|
+
maxWidth?: number;
|
|
313
|
+
aspectRatio?: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Ad Slot Suggestions
|
|
318
|
+
*/
|
|
319
|
+
export declare interface AdSlotSuggestions {
|
|
320
|
+
layout?: 'horizontal' | 'vertical' | 'grid';
|
|
321
|
+
columns?: number;
|
|
322
|
+
spacing?: string;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Ad Source Types
|
|
327
|
+
* Where the ad originates from
|
|
328
|
+
*/
|
|
329
|
+
export declare type AdSource = 'internal' | 'affiliate' | 'programmatic' | 'mock';
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Ad Tracking Options
|
|
333
|
+
*/
|
|
334
|
+
export declare interface AdTrackingOptions {
|
|
335
|
+
intersectionThreshold?: number;
|
|
336
|
+
minViewTimeMs?: number;
|
|
337
|
+
onClick?: (ad: KoahAd) => void;
|
|
338
|
+
onImpression?: (ad: KoahAd) => void;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Analytics 错误类型
|
|
343
|
+
*/
|
|
344
|
+
export declare class AnalyticsError extends Error {
|
|
345
|
+
code: string;
|
|
346
|
+
originalError?: unknown | undefined;
|
|
347
|
+
constructor(message: string, code: string, originalError?: unknown | undefined);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Analytics 发送配置
|
|
352
|
+
*/
|
|
353
|
+
export declare interface AnalyticsSendConfig {
|
|
354
|
+
baseUrl?: string;
|
|
355
|
+
timeout?: number;
|
|
356
|
+
retryAttempts?: number;
|
|
357
|
+
retryDelay?: number;
|
|
358
|
+
debug?: boolean;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Analytics 发送器类
|
|
363
|
+
*/
|
|
364
|
+
export declare class AnalyticsSender {
|
|
365
|
+
private baseUrl;
|
|
366
|
+
private timeout;
|
|
367
|
+
private retryAttempts;
|
|
368
|
+
private retryDelay;
|
|
369
|
+
private debug;
|
|
370
|
+
constructor(config?: AnalyticsSendConfig);
|
|
371
|
+
/**
|
|
372
|
+
* 发送广告展示事件
|
|
373
|
+
*/
|
|
374
|
+
trackImpression(data: ImpressionEventData): Promise<ImpressionResponse | null>;
|
|
375
|
+
/**
|
|
376
|
+
* 发送广告点击事件
|
|
377
|
+
*/
|
|
378
|
+
trackClick(data: ClickEventData): Promise<ClickResponse | null>;
|
|
379
|
+
/**
|
|
380
|
+
* 通用请求发送方法(带重试)
|
|
381
|
+
* 自动添加 X-API-Key header
|
|
382
|
+
*/
|
|
383
|
+
private sendRequest;
|
|
384
|
+
/**
|
|
385
|
+
* 延迟辅助方法
|
|
386
|
+
*/
|
|
387
|
+
private delay;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* App Information (injected at build time)
|
|
392
|
+
*/
|
|
393
|
+
export declare interface AppInfo {
|
|
394
|
+
bundle: string;
|
|
395
|
+
ver: string;
|
|
396
|
+
name: string;
|
|
397
|
+
publisher: {
|
|
398
|
+
id: string;
|
|
399
|
+
domain?: string;
|
|
400
|
+
};
|
|
401
|
+
cat?: string[];
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Badge Style for Entity Links
|
|
406
|
+
* Controls how affiliate links are visually indicated to users
|
|
407
|
+
*/
|
|
408
|
+
export declare type BadgeStyle = 'hover' | 'subtle' | 'explicit' | 'none';
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Chat Completion Request
|
|
412
|
+
*/
|
|
413
|
+
export declare interface ChatCompletionRequest {
|
|
414
|
+
messages: ChatMessage[];
|
|
415
|
+
adEnabled?: boolean;
|
|
416
|
+
adFormats?: AdFormat[];
|
|
417
|
+
placement?: string;
|
|
418
|
+
stream?: boolean;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Chat Completion Response
|
|
423
|
+
*/
|
|
424
|
+
export declare interface ChatCompletionResponse {
|
|
425
|
+
message: ChatMessage;
|
|
426
|
+
intent?: IntentResult;
|
|
427
|
+
ads?: KoahAd[];
|
|
428
|
+
usage?: {
|
|
429
|
+
promptTokens: number;
|
|
430
|
+
completionTokens: number;
|
|
431
|
+
totalTokens: number;
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Chat Message
|
|
437
|
+
*/
|
|
438
|
+
export declare interface ChatMessage {
|
|
439
|
+
role: 'system' | 'user' | 'assistant';
|
|
440
|
+
content: string;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Clear client info cache
|
|
445
|
+
*
|
|
446
|
+
* Forces re-collection on next call. Useful when device state changes.
|
|
447
|
+
*/
|
|
448
|
+
export declare function clearClientInfoCache(): void;
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* 点击事件数据
|
|
452
|
+
*/
|
|
453
|
+
export declare interface ClickEventData {
|
|
454
|
+
requestId: string;
|
|
455
|
+
adId: string;
|
|
456
|
+
sessionId: string;
|
|
457
|
+
destinationUrl: string;
|
|
458
|
+
adTitle?: string;
|
|
459
|
+
slotId?: string;
|
|
460
|
+
format?: string;
|
|
461
|
+
source?: string;
|
|
462
|
+
userId?: string;
|
|
463
|
+
impressionEventId?: string;
|
|
464
|
+
timeToClickMs?: number;
|
|
465
|
+
viewToken?: string;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* 点击事件响应
|
|
470
|
+
*/
|
|
471
|
+
export declare interface ClickResponse {
|
|
472
|
+
success: boolean;
|
|
473
|
+
eventId: string;
|
|
474
|
+
redirectUrl: string;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Client Information (auto-collected by SDK)
|
|
479
|
+
* This complies with OpenRTB 2.5/2.6 specifications
|
|
480
|
+
*/
|
|
481
|
+
export declare interface ClientInfo {
|
|
482
|
+
device: DeviceInfo;
|
|
483
|
+
app: AppInfo;
|
|
484
|
+
user: UserInfo;
|
|
485
|
+
geo?: GeoInfo;
|
|
486
|
+
timestamp: number;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export declare class ClientInfoCollector {
|
|
490
|
+
private static instance;
|
|
491
|
+
private cachedStaticInfo;
|
|
492
|
+
private cacheTimestamp;
|
|
493
|
+
private readonly CACHE_TTL;
|
|
494
|
+
private inferAppInfo;
|
|
495
|
+
/**
|
|
496
|
+
* 自动推断bundle/domain
|
|
497
|
+
*/
|
|
498
|
+
private inferBundle;
|
|
499
|
+
/**
|
|
500
|
+
* 自动推断应用名称
|
|
501
|
+
*/
|
|
502
|
+
private inferAppName;
|
|
503
|
+
/**
|
|
504
|
+
* 自动推断应用版本
|
|
505
|
+
*/
|
|
506
|
+
private inferAppVersion;
|
|
507
|
+
/**
|
|
508
|
+
* 自动推断publisher ID
|
|
509
|
+
*/
|
|
510
|
+
private inferPublisherId;
|
|
511
|
+
private constructor();
|
|
512
|
+
/**
|
|
513
|
+
* Get singleton instance
|
|
514
|
+
*/
|
|
515
|
+
static getInstance(): ClientInfoCollector;
|
|
516
|
+
/**
|
|
517
|
+
* Collect all available client information
|
|
518
|
+
* @param options Optional overrides from app
|
|
519
|
+
* @returns ClientInfo object compliant with OpenRTB 2.5/2.6
|
|
520
|
+
*/
|
|
521
|
+
collect(options?: ClientInfoOptions): ClientInfo;
|
|
522
|
+
/**
|
|
523
|
+
* Collect static device information (cached)
|
|
524
|
+
* These values don't change during app lifecycle
|
|
525
|
+
*/
|
|
526
|
+
private collectStaticInfo;
|
|
527
|
+
/**
|
|
528
|
+
* Collect dynamic device information (not cached)
|
|
529
|
+
* These values may change during app lifecycle
|
|
530
|
+
*/
|
|
531
|
+
private collectDynamicInfo;
|
|
532
|
+
/**
|
|
533
|
+
* Collect user information
|
|
534
|
+
*/
|
|
535
|
+
private collectUserInfo;
|
|
536
|
+
/**
|
|
537
|
+
* Collect geographic information (inferred)
|
|
538
|
+
*/
|
|
539
|
+
private collectGeoInfo;
|
|
540
|
+
/**
|
|
541
|
+
* Detect Operating System
|
|
542
|
+
*/
|
|
543
|
+
private detectOS;
|
|
544
|
+
/**
|
|
545
|
+
* Detect OS Version
|
|
546
|
+
*/
|
|
547
|
+
private detectOSVersion;
|
|
548
|
+
/**
|
|
549
|
+
* Detect Device Type (OpenRTB standard)
|
|
550
|
+
* 0 = Unknown/Other
|
|
551
|
+
* 1 = Mobile/Phone
|
|
552
|
+
* 2 = Tablet
|
|
553
|
+
* 3 = Personal Computer
|
|
554
|
+
* 4 = Connected TV
|
|
555
|
+
* 5 = Set Top Box
|
|
556
|
+
*/
|
|
557
|
+
private detectDeviceType;
|
|
558
|
+
/**
|
|
559
|
+
* Detect Device Model
|
|
560
|
+
*/
|
|
561
|
+
private detectModel;
|
|
562
|
+
/**
|
|
563
|
+
* Detect Device Make
|
|
564
|
+
*/
|
|
565
|
+
private detectMake;
|
|
566
|
+
/**
|
|
567
|
+
* Get Network Connection Info
|
|
568
|
+
*/
|
|
569
|
+
private getConnectionInfo;
|
|
570
|
+
/**
|
|
571
|
+
* Map Network Information API type to OpenRTB
|
|
572
|
+
* 0 = Unknown
|
|
573
|
+
* 1 = Ethernet
|
|
574
|
+
* 2 = WiFi
|
|
575
|
+
* 3 = 2G
|
|
576
|
+
* 4 = 3G
|
|
577
|
+
* 5 = 4G
|
|
578
|
+
* 6 = 5G
|
|
579
|
+
*/
|
|
580
|
+
private mapConnectionType;
|
|
581
|
+
/**
|
|
582
|
+
* Infer country from language and timezone
|
|
583
|
+
*/
|
|
584
|
+
private inferCountry;
|
|
585
|
+
/**
|
|
586
|
+
* Generate UUID v4
|
|
587
|
+
*/
|
|
588
|
+
private generateUUID;
|
|
589
|
+
/**
|
|
590
|
+
* Get fallback info for SSR or restricted environments
|
|
591
|
+
*/
|
|
592
|
+
private getFallbackInfo;
|
|
593
|
+
/**
|
|
594
|
+
* Clear cache (call when device state changes)
|
|
595
|
+
*/
|
|
596
|
+
clearCache(): void;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Client Info Collection Options
|
|
601
|
+
* Allows app to override certain fields
|
|
602
|
+
*/
|
|
603
|
+
export declare interface ClientInfoOptions {
|
|
604
|
+
device?: Partial<DeviceInfo>;
|
|
605
|
+
app?: Partial<AppInfo>;
|
|
606
|
+
user?: Partial<UserInfo>;
|
|
607
|
+
geo?: Partial<GeoInfo>;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Conversation Context
|
|
612
|
+
*/
|
|
613
|
+
export declare interface ConversationContext {
|
|
614
|
+
query: string;
|
|
615
|
+
response?: string;
|
|
616
|
+
intent?: IntentResult;
|
|
617
|
+
conversationHistory?: ConversationMessage[];
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Conversation Message
|
|
622
|
+
* Individual message in conversation history
|
|
623
|
+
*/
|
|
624
|
+
export declare interface ConversationMessage {
|
|
625
|
+
role: 'user' | 'assistant' | 'system';
|
|
626
|
+
content: string;
|
|
627
|
+
timestamp?: number;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* 创建带配置的 Analytics 实例
|
|
632
|
+
*/
|
|
633
|
+
export declare function createAnalytics(config: AnalyticsSendConfig): {
|
|
634
|
+
trackImpression: (data: ImpressionEventData) => Promise<ImpressionResponse | null>;
|
|
635
|
+
trackClick: (data: ClickEventData) => Promise<ClickResponse | null>;
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* 创建带配置的 Session 实例
|
|
640
|
+
*/
|
|
641
|
+
export declare function createSession(config?: SessionConfig): {
|
|
642
|
+
getSessionId: () => string;
|
|
643
|
+
regenerateSessionId: () => string;
|
|
644
|
+
clearSessionId: () => void;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Decision Result
|
|
649
|
+
* Complete response from the ad decision engine
|
|
650
|
+
*/
|
|
651
|
+
export declare interface DecisionResult {
|
|
652
|
+
ads: KoahAd[];
|
|
653
|
+
intent: IntentResult;
|
|
654
|
+
routing: RoutingInfo;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Device Information (auto-collected by SDK)
|
|
659
|
+
*/
|
|
660
|
+
export declare interface DeviceInfo {
|
|
661
|
+
ua: string;
|
|
662
|
+
os: string;
|
|
663
|
+
osv: string;
|
|
664
|
+
devicetype: number;
|
|
665
|
+
model?: string;
|
|
666
|
+
make?: string;
|
|
667
|
+
language: string;
|
|
668
|
+
connectiontype: number;
|
|
669
|
+
bandwidth?: number;
|
|
670
|
+
ip?: string;
|
|
671
|
+
ifa?: string;
|
|
672
|
+
lmt?: number;
|
|
673
|
+
att?: number;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* DOM Renderer - Create DOM elements with event binding
|
|
678
|
+
*/
|
|
679
|
+
export declare class DOMRenderer {
|
|
680
|
+
/**
|
|
681
|
+
* Render Action Card ad into container
|
|
682
|
+
*/
|
|
683
|
+
static renderActionCard(ad: AdaptedAdContent, container: HTMLElement, options?: {
|
|
684
|
+
variant?: 'horizontal' | 'vertical' | 'compact';
|
|
685
|
+
analytics?: AdAnalyticsInfo;
|
|
686
|
+
onClick?: (ad: AdaptedAdContent) => void;
|
|
687
|
+
onImpression?: (ad: AdaptedAdContent) => void;
|
|
688
|
+
}): HTMLElement;
|
|
689
|
+
/**
|
|
690
|
+
* Render Suffix ad into container
|
|
691
|
+
*/
|
|
692
|
+
static renderSuffixAd(ad: AdaptedAdContent, container: HTMLElement, options?: {
|
|
693
|
+
variant?: 'block' | 'inline' | 'minimal';
|
|
694
|
+
analytics?: AdAnalyticsInfo;
|
|
695
|
+
onClick?: (ad: AdaptedAdContent) => void;
|
|
696
|
+
onImpression?: (ad: AdaptedAdContent) => void;
|
|
697
|
+
}): HTMLElement;
|
|
698
|
+
/**
|
|
699
|
+
* Render Sponsored Source ad into container
|
|
700
|
+
*/
|
|
701
|
+
static renderSponsoredSource(ad: AdaptedAdContent, container: HTMLElement, options?: {
|
|
702
|
+
variant?: 'card' | 'list-item' | 'minimal';
|
|
703
|
+
analytics?: AdAnalyticsInfo;
|
|
704
|
+
onClick?: (ad: AdaptedAdContent) => void;
|
|
705
|
+
onImpression?: (ad: AdaptedAdContent) => void;
|
|
706
|
+
}): HTMLElement;
|
|
707
|
+
/**
|
|
708
|
+
* Render Lead Gen ad into container
|
|
709
|
+
*/
|
|
710
|
+
static renderLeadGenAd(ad: AdaptedAdContent, container: HTMLElement, options?: {
|
|
711
|
+
analytics?: AdAnalyticsInfo;
|
|
712
|
+
onClick?: (ad: AdaptedAdContent) => void;
|
|
713
|
+
onImpression?: (ad: AdaptedAdContent) => void;
|
|
714
|
+
}): HTMLElement;
|
|
715
|
+
/**
|
|
716
|
+
* Render multiple ads into container
|
|
717
|
+
*/
|
|
718
|
+
static renderAds(ads: AdaptedAdContent[], container: HTMLElement, renderFn?: (ad: AdaptedAdContent, container: HTMLElement, options?: any) => void, options?: any): HTMLElement;
|
|
719
|
+
/**
|
|
720
|
+
* Handle ad click
|
|
721
|
+
* First tracks the click (async, non-blocking), then opens the URL.
|
|
722
|
+
*/
|
|
723
|
+
private static handleClick;
|
|
724
|
+
/**
|
|
725
|
+
* Track ad impression using IntersectionObserver (50% visible + 1000ms delay)
|
|
726
|
+
* Falls back to immediate tracking if IntersectionObserver is unavailable.
|
|
727
|
+
*/
|
|
728
|
+
private static trackImpression;
|
|
729
|
+
/**
|
|
730
|
+
* Generate HTML for Suffix Ad variants
|
|
731
|
+
*/
|
|
732
|
+
private static generateSuffixAdHTML;
|
|
733
|
+
/**
|
|
734
|
+
* Generate HTML for Sponsored Source Ad variants
|
|
735
|
+
*/
|
|
736
|
+
private static generateSponsoredSourceHTML;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Enhanced Content Props
|
|
741
|
+
* Props for the EnhancedContent component
|
|
742
|
+
*/
|
|
743
|
+
export declare interface EnhancedContentProps {
|
|
744
|
+
/** Original content text */
|
|
745
|
+
content: string;
|
|
746
|
+
/** Enhancement configuration */
|
|
747
|
+
enhancements: EnhancementOptions;
|
|
748
|
+
/** Custom class name */
|
|
749
|
+
className?: string;
|
|
750
|
+
/** Callback when entity link is clicked */
|
|
751
|
+
onEntityClick?: (entity: EntityInfo) => void;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Enhanced Entity Fragment
|
|
756
|
+
* Represents a single entity with its enhanced HTML and tracking data
|
|
757
|
+
*/
|
|
758
|
+
export declare interface EnhancedEntityFragment {
|
|
759
|
+
/** Original entity text (for replacement) */
|
|
760
|
+
originalText: string;
|
|
761
|
+
/** Enhanced HTML with tracking attributes */
|
|
762
|
+
enhancedHTML: string;
|
|
763
|
+
/** Entity information */
|
|
764
|
+
entity: EntityInfo;
|
|
765
|
+
/** Link replacement information */
|
|
766
|
+
replacement: LinkReplacement;
|
|
767
|
+
/** Tracking parameters */
|
|
768
|
+
tracking: {
|
|
769
|
+
/** Ad ID */
|
|
770
|
+
adId: string;
|
|
771
|
+
/** Request ID from useAiAds */
|
|
772
|
+
requestId: string;
|
|
773
|
+
/** Slot ID */
|
|
774
|
+
slotId: string;
|
|
775
|
+
/** Position in entities array */
|
|
776
|
+
position: number;
|
|
777
|
+
/** Unique entity ID for tracking */
|
|
778
|
+
entityId: string;
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Options for enhancing entity fragments
|
|
784
|
+
*/
|
|
785
|
+
export declare interface EnhanceFragmentsOptions {
|
|
786
|
+
/** Ad ID */
|
|
787
|
+
adId: string;
|
|
788
|
+
/** Request ID */
|
|
789
|
+
requestId: string;
|
|
790
|
+
/** Slot ID */
|
|
791
|
+
slotId: string;
|
|
792
|
+
/** Badge style for visual indicator */
|
|
793
|
+
badgeStyle?: BadgeStyle;
|
|
794
|
+
/** Minimum confidence threshold (default: 0.7) */
|
|
795
|
+
minConfidence?: number;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Enhancement Options
|
|
800
|
+
* Configuration options for content enhancement
|
|
801
|
+
*/
|
|
802
|
+
export declare interface EnhancementOptions {
|
|
803
|
+
/** List of entities to enhance */
|
|
804
|
+
entities: EntityInfo[];
|
|
805
|
+
/** Link replacements for entities */
|
|
806
|
+
replacements: LinkReplacement[];
|
|
807
|
+
/** Maximum number of links to add (default: 5) */
|
|
808
|
+
maxLinks?: number;
|
|
809
|
+
/** Minimum confidence threshold (default: 0.7) */
|
|
810
|
+
minConfidence?: number;
|
|
811
|
+
/** Visual badge style (default: 'subtle') */
|
|
812
|
+
badgeStyle?: BadgeStyle;
|
|
813
|
+
/** How to handle overlapping entities (default: 'longest') */
|
|
814
|
+
overlapStrategy?: OverlapStrategy;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Entity Information (Frontend)
|
|
819
|
+
* Matches backend EntityInfo structure
|
|
820
|
+
*/
|
|
821
|
+
export declare interface EntityInfo {
|
|
822
|
+
/** The exact text of the entity in the original content */
|
|
823
|
+
text: string;
|
|
824
|
+
/** Starting position in the original text (0-based) */
|
|
825
|
+
startPosition: number;
|
|
826
|
+
/** Ending position in the original text (exclusive) */
|
|
827
|
+
endPosition: number;
|
|
828
|
+
/** Type of the entity */
|
|
829
|
+
type: EntityType;
|
|
830
|
+
/** Confidence score from 0 to 1 */
|
|
831
|
+
confidence: number;
|
|
832
|
+
/** Product category (optional, inferred from context) */
|
|
833
|
+
category?: string;
|
|
834
|
+
/** Brand name (optional, if entity is a product) */
|
|
835
|
+
brand?: string;
|
|
836
|
+
/** Normalized entity name for matching */
|
|
837
|
+
normalizedName?: string;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* Entity Link Enhancement Content (Frontend)
|
|
842
|
+
* Content enhancement with entity-linked affiliate URLs
|
|
843
|
+
* Matches backend EntityLinkAdContent structure
|
|
844
|
+
*/
|
|
845
|
+
export declare interface EntityLinkAdContent {
|
|
846
|
+
/** Original text before enhancement */
|
|
847
|
+
originalText: string;
|
|
848
|
+
/** Processed text with entity links */
|
|
849
|
+
processedText: string;
|
|
850
|
+
/** List of all recognized entities */
|
|
851
|
+
entities: EntityInfo[];
|
|
852
|
+
/** List of applied link replacements */
|
|
853
|
+
replacements: LinkReplacement[];
|
|
854
|
+
/** Processing metadata */
|
|
855
|
+
metadata: {
|
|
856
|
+
/** Processing time in milliseconds */
|
|
857
|
+
processingTime: number;
|
|
858
|
+
/** Total number of entities recognized */
|
|
859
|
+
entityCount: number;
|
|
860
|
+
/** Number of entities successfully linked */
|
|
861
|
+
linkCount: number;
|
|
862
|
+
/** NER method used ('llm' | 'ner_model') */
|
|
863
|
+
nerMethod: 'llm' | 'ner_model';
|
|
864
|
+
/** Average confidence score */
|
|
865
|
+
avgConfidence: number;
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Entity Type for NER
|
|
871
|
+
* Types of entities that can be recognized and enhanced
|
|
872
|
+
*/
|
|
873
|
+
export declare type EntityType = 'product' | 'brand' | 'service' | 'category';
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Extended Ad Request Batch with Client Info
|
|
877
|
+
*/
|
|
878
|
+
export declare interface ExtendedAdRequestBatch extends AdRequestBatch {
|
|
879
|
+
clientInfo: ClientInfo;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* fetchAds - Unified ad fetching interface
|
|
884
|
+
*
|
|
885
|
+
* Supports all stages (pre-request and post-response) with intelligent decision making.
|
|
886
|
+
* The backend automatically detects the stage and returns appropriate ad formats based on context completeness.
|
|
887
|
+
* Automatically injects client information for OpenRTB compliance.
|
|
888
|
+
*
|
|
889
|
+
* @param params - Ad request parameters
|
|
890
|
+
* @param options - Additional options (apiBaseUrl, apiKey, etc.)
|
|
891
|
+
* @returns Promise resolving to ad response batch
|
|
892
|
+
*/
|
|
893
|
+
export declare function fetchAds(params: {
|
|
894
|
+
conversationContext: ConversationContext;
|
|
895
|
+
userContext?: UserContext;
|
|
896
|
+
slots: AdSlotRequest[];
|
|
897
|
+
}, options?: {
|
|
898
|
+
apiBaseUrl?: string;
|
|
899
|
+
apiKey?: string;
|
|
900
|
+
}): Promise<AdResponseBatch>;
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Follow-up Ad Content
|
|
904
|
+
* Ad mixed into suggested questions
|
|
905
|
+
*/
|
|
906
|
+
export declare interface FollowUpAdContent {
|
|
907
|
+
question_text: string;
|
|
908
|
+
is_ad: boolean;
|
|
909
|
+
ad_destination?: string;
|
|
910
|
+
icon?: string;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Follow-up Ad Variant
|
|
915
|
+
*/
|
|
916
|
+
export declare type FollowUpVariant = 'bubble' | 'pill' | 'underline';
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* 生成 View Token(用于展示去重)
|
|
920
|
+
*/
|
|
921
|
+
export declare function generateViewToken(adId: string, sessionId: string): string;
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Geographic Information (inferred)
|
|
925
|
+
*/
|
|
926
|
+
export declare interface GeoInfo {
|
|
927
|
+
country?: string;
|
|
928
|
+
timezone?: string;
|
|
929
|
+
lat?: number;
|
|
930
|
+
lon?: number;
|
|
931
|
+
region?: string;
|
|
932
|
+
city?: string;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Get app information only
|
|
937
|
+
*/
|
|
938
|
+
export declare function getAppInfo(): AppInfo;
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* Get current client information (convenience function)
|
|
942
|
+
*
|
|
943
|
+
* This is a shortcut for getClientInfoCollector().collect()
|
|
944
|
+
*
|
|
945
|
+
* @param options - Optional custom options
|
|
946
|
+
* @returns Complete client information
|
|
947
|
+
*/
|
|
948
|
+
export declare function getClientInfo(options?: ClientInfoOptions): ClientInfo;
|
|
949
|
+
|
|
950
|
+
export declare const getClientInfoCollector: () => ClientInfoCollector;
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* Get client info as JSON string
|
|
954
|
+
*
|
|
955
|
+
* Useful for logging or sending to APIs
|
|
956
|
+
*/
|
|
957
|
+
export declare function getClientInfoJSON(options?: ClientInfoOptions): string;
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Get client info summary (human-readable)
|
|
961
|
+
*
|
|
962
|
+
* Returns a simplified summary for debugging/display
|
|
963
|
+
*/
|
|
964
|
+
export declare function getClientInfoSummary(): string;
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Get device information only
|
|
968
|
+
*/
|
|
969
|
+
export declare function getDeviceInfo(): DeviceInfo;
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Get geo information only
|
|
973
|
+
*/
|
|
974
|
+
export declare function getGeoInfo(): GeoInfo | undefined;
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* 获取 Session ID(便捷方法)
|
|
978
|
+
*/
|
|
979
|
+
export declare const getSessionId: () => string;
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Get user ID (persistent across sessions)
|
|
983
|
+
*/
|
|
984
|
+
export declare function getUserId(): string;
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Get user information only
|
|
988
|
+
*/
|
|
989
|
+
export declare function getUserInfo(): UserInfo;
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Get or create the viewability tracker singleton
|
|
993
|
+
*/
|
|
994
|
+
export declare function getViewabilityTracker(config?: ViewabilityConfig, baseUrl?: string): ViewabilityTracker;
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Global Suggestions
|
|
998
|
+
*/
|
|
999
|
+
export declare interface GlobalSuggestions {
|
|
1000
|
+
priority?: string[];
|
|
1001
|
+
hideIfNoFill?: string[];
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* HTML Renderer - Generate ad HTML strings
|
|
1006
|
+
* CSS class names use ax-ad-* namespace
|
|
1007
|
+
*/
|
|
1008
|
+
export declare class HTMLRenderer {
|
|
1009
|
+
/**
|
|
1010
|
+
* Render Action Card ad as HTML string
|
|
1011
|
+
*
|
|
1012
|
+
* @param ad - Adapted ad content
|
|
1013
|
+
* @param options - Rendering options
|
|
1014
|
+
* @returns HTML string
|
|
1015
|
+
*/
|
|
1016
|
+
static renderActionCard(ad: AdaptedAdContent, options?: {
|
|
1017
|
+
variant?: 'horizontal' | 'vertical' | 'compact';
|
|
1018
|
+
includeWrapper?: boolean;
|
|
1019
|
+
}): string;
|
|
1020
|
+
/**
|
|
1021
|
+
* Render Suffix ad as HTML string
|
|
1022
|
+
*
|
|
1023
|
+
* @param ad - Adapted ad content
|
|
1024
|
+
* @returns HTML string
|
|
1025
|
+
*/
|
|
1026
|
+
static renderSuffixAd(ad: AdaptedAdContent): string;
|
|
1027
|
+
/**
|
|
1028
|
+
* Render Sponsored Source ad as HTML string
|
|
1029
|
+
*
|
|
1030
|
+
* @param ad - Adapted ad content
|
|
1031
|
+
* @returns HTML string
|
|
1032
|
+
*/
|
|
1033
|
+
static renderSponsoredSource(ad: AdaptedAdContent): string;
|
|
1034
|
+
/**
|
|
1035
|
+
* Render Lead Gen ad as HTML string
|
|
1036
|
+
*
|
|
1037
|
+
* @param ad - Adapted ad content
|
|
1038
|
+
* @returns HTML string
|
|
1039
|
+
*/
|
|
1040
|
+
static renderLeadGenAd(ad: AdaptedAdContent): string;
|
|
1041
|
+
/**
|
|
1042
|
+
* Render multiple ads
|
|
1043
|
+
*
|
|
1044
|
+
* @param ads - Array of adapted ads
|
|
1045
|
+
* @param renderFn - Render function to use
|
|
1046
|
+
* @returns HTML string with all ads
|
|
1047
|
+
*/
|
|
1048
|
+
static renderAds(ads: AdaptedAdContent[], renderFn?: (ad: AdaptedAdContent) => string): string;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Analytics API 事件类型定义
|
|
1053
|
+
*
|
|
1054
|
+
* 用于 Frontend SDK 与 Backend Analytics API 的交互
|
|
1055
|
+
* 兼容 React SDK 和 Universal SDK
|
|
1056
|
+
*/
|
|
1057
|
+
/**
|
|
1058
|
+
* 展示事件数据
|
|
1059
|
+
*/
|
|
1060
|
+
export declare interface ImpressionEventData {
|
|
1061
|
+
requestId: string;
|
|
1062
|
+
adId: string;
|
|
1063
|
+
position: number;
|
|
1064
|
+
totalAds: number;
|
|
1065
|
+
sessionId: string;
|
|
1066
|
+
adTitle?: string;
|
|
1067
|
+
slotId?: string;
|
|
1068
|
+
format?: string;
|
|
1069
|
+
source?: string;
|
|
1070
|
+
userId?: string;
|
|
1071
|
+
viewToken?: string;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* 展示事件响应
|
|
1076
|
+
*/
|
|
1077
|
+
export declare interface ImpressionResponse {
|
|
1078
|
+
success: boolean;
|
|
1079
|
+
eventId: string;
|
|
1080
|
+
impressionId: string;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Intent Recognition Result
|
|
1085
|
+
* Represents the output of intent analysis
|
|
1086
|
+
*/
|
|
1087
|
+
export declare interface IntentResult {
|
|
1088
|
+
type: IntentType;
|
|
1089
|
+
confidence: number;
|
|
1090
|
+
keywords: string[];
|
|
1091
|
+
reasoning?: string;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Intent Type Enumeration
|
|
1096
|
+
* Defines the primary intent categories for ad targeting
|
|
1097
|
+
*/
|
|
1098
|
+
export declare enum IntentType {
|
|
1099
|
+
SHOPPING = "shopping",
|
|
1100
|
+
LEAD_GEN = "lead_gen",
|
|
1101
|
+
SOFTWARE = "software",
|
|
1102
|
+
CONTENT = "content",
|
|
1103
|
+
GENERIC = "generic"
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Standardized Koah Ad Format
|
|
1108
|
+
* All adapters normalize to this format
|
|
1109
|
+
*/
|
|
1110
|
+
export declare interface KoahAd {
|
|
1111
|
+
id: string;
|
|
1112
|
+
type: AdFormat;
|
|
1113
|
+
score: number;
|
|
1114
|
+
source: AdSource;
|
|
1115
|
+
content: {
|
|
1116
|
+
title: string;
|
|
1117
|
+
body: string;
|
|
1118
|
+
image?: string;
|
|
1119
|
+
cta_text?: string;
|
|
1120
|
+
rating?: number;
|
|
1121
|
+
price?: string;
|
|
1122
|
+
brand?: string;
|
|
1123
|
+
suffix_content?: SuffixAdContent;
|
|
1124
|
+
followup_content?: FollowUpAdContent;
|
|
1125
|
+
source_content?: SponsoredSourceContent;
|
|
1126
|
+
entity_link_content?: EntityLinkAdContent;
|
|
1127
|
+
};
|
|
1128
|
+
tracking: {
|
|
1129
|
+
click_url: string;
|
|
1130
|
+
impression_url: string;
|
|
1131
|
+
};
|
|
1132
|
+
metadata?: {
|
|
1133
|
+
original_source?: string;
|
|
1134
|
+
category?: string;
|
|
1135
|
+
ecpm?: number;
|
|
1136
|
+
[key: string]: any;
|
|
1137
|
+
};
|
|
1138
|
+
/** Enhanced entity fragments (Mode A) - only for entity_link type */
|
|
1139
|
+
enhancedFragments?: EnhancedEntityFragment[];
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Link Replacement
|
|
1144
|
+
* Represents a link replacement for an entity or existing URL
|
|
1145
|
+
*/
|
|
1146
|
+
export declare interface LinkReplacement {
|
|
1147
|
+
/** The original text to be replaced/linked */
|
|
1148
|
+
originalText: string;
|
|
1149
|
+
/** Original URL if the text already had a link */
|
|
1150
|
+
originalUrl?: string;
|
|
1151
|
+
/** The affiliate URL to replace with */
|
|
1152
|
+
affiliateUrl: string;
|
|
1153
|
+
/** Associated entity information */
|
|
1154
|
+
entity?: EntityInfo;
|
|
1155
|
+
/** Unique tracking ID for this replacement */
|
|
1156
|
+
trackingId: string;
|
|
1157
|
+
/** Affiliate network identifier */
|
|
1158
|
+
affiliateNetwork: 'amazon' | 'wildfire' | 'other';
|
|
1159
|
+
/** Commission rate (optional, for analytics) */
|
|
1160
|
+
commissionRate?: number;
|
|
1161
|
+
/** Product price (optional, for display) */
|
|
1162
|
+
price?: string;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Overlap Strategy
|
|
1167
|
+
* How to handle overlapping entity mentions
|
|
1168
|
+
*/
|
|
1169
|
+
export declare type OverlapStrategy = 'longest' | 'first' | 'all';
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Placement Types
|
|
1173
|
+
* Where ads can be displayed in the UI
|
|
1174
|
+
*/
|
|
1175
|
+
export declare type PlacementType = RequestContext['placement'];
|
|
1176
|
+
|
|
1177
|
+
/**
|
|
1178
|
+
* Request Context for Ad Decision
|
|
1179
|
+
*/
|
|
1180
|
+
export declare interface RequestContext {
|
|
1181
|
+
query: string;
|
|
1182
|
+
response?: string;
|
|
1183
|
+
adFormats: AdFormat[];
|
|
1184
|
+
placement: 'post_response' | 'sidebar' | 'empty_state' | 'inline';
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Response Metadata
|
|
1189
|
+
* Provides transparency about the decision process
|
|
1190
|
+
*/
|
|
1191
|
+
export declare interface ResponseMetadata {
|
|
1192
|
+
detectedStage: 'pre_request' | 'post_response' | 'unknown';
|
|
1193
|
+
availableContext: {
|
|
1194
|
+
hasQuery: boolean;
|
|
1195
|
+
hasResponse: boolean;
|
|
1196
|
+
hasHistory: boolean;
|
|
1197
|
+
hasProfile: boolean;
|
|
1198
|
+
historyLength?: number;
|
|
1199
|
+
};
|
|
1200
|
+
reasoning?: string;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
* Routing Information
|
|
1205
|
+
* Tracks the decision process
|
|
1206
|
+
*/
|
|
1207
|
+
export declare interface RoutingInfo {
|
|
1208
|
+
primarySource: string;
|
|
1209
|
+
fallbackTriggered: boolean;
|
|
1210
|
+
log: RoutingLogEntry[];
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Routing Log Entry
|
|
1215
|
+
* Individual routing attempt log
|
|
1216
|
+
*/
|
|
1217
|
+
export declare interface RoutingLogEntry {
|
|
1218
|
+
strategy: string;
|
|
1219
|
+
adapter: string;
|
|
1220
|
+
adsFound: number;
|
|
1221
|
+
status: 'success' | 'no_fill' | 'error';
|
|
1222
|
+
error?: string;
|
|
1223
|
+
timestamp?: number;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
export declare const SDK_VERSION = "0.1.0";
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Session 管理配置
|
|
1230
|
+
*/
|
|
1231
|
+
export declare interface SessionConfig {
|
|
1232
|
+
sessionKey?: string;
|
|
1233
|
+
storage?: 'sessionStorage' | 'memory';
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Session 管理器
|
|
1238
|
+
*/
|
|
1239
|
+
export declare class SessionManager {
|
|
1240
|
+
private sessionKey;
|
|
1241
|
+
private storage;
|
|
1242
|
+
private memoryCache;
|
|
1243
|
+
constructor(config?: SessionConfig);
|
|
1244
|
+
/**
|
|
1245
|
+
* 获取 Session ID
|
|
1246
|
+
*/
|
|
1247
|
+
getSessionId(): string;
|
|
1248
|
+
/**
|
|
1249
|
+
* 重新生成 Session ID
|
|
1250
|
+
*/
|
|
1251
|
+
regenerateSessionId(): string;
|
|
1252
|
+
/**
|
|
1253
|
+
* 生成新的 Session ID
|
|
1254
|
+
*/
|
|
1255
|
+
private generateSessionId;
|
|
1256
|
+
/**
|
|
1257
|
+
* 清除 Session ID
|
|
1258
|
+
*/
|
|
1259
|
+
clearSessionId(): void;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Slot Decision Metadata
|
|
1264
|
+
* Per-slot decision reasoning and suggestions
|
|
1265
|
+
*/
|
|
1266
|
+
export declare interface SlotDecisionMetadata {
|
|
1267
|
+
reasoning?: Array<{
|
|
1268
|
+
reason: string;
|
|
1269
|
+
confidence: number;
|
|
1270
|
+
}>;
|
|
1271
|
+
suggestions?: {
|
|
1272
|
+
layout?: string;
|
|
1273
|
+
variant?: string;
|
|
1274
|
+
position?: number;
|
|
1275
|
+
timing?: {
|
|
1276
|
+
showAfter?: number;
|
|
1277
|
+
requiresInterest?: string[];
|
|
1278
|
+
};
|
|
1279
|
+
tone?: 'casual' | 'professional' | 'friendly' | 'technical';
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Source Ad Variant
|
|
1285
|
+
*/
|
|
1286
|
+
export declare type SourceVariant = 'card' | 'list-item' | 'minimal';
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
* Sponsored Source Content
|
|
1290
|
+
* Ad mixed into citation list
|
|
1291
|
+
*/
|
|
1292
|
+
export declare interface SponsoredSourceContent {
|
|
1293
|
+
source_name: string;
|
|
1294
|
+
source_url: string;
|
|
1295
|
+
favicon?: string;
|
|
1296
|
+
snippet?: string;
|
|
1297
|
+
is_ad: boolean;
|
|
1298
|
+
ad_destination?: string;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/**
|
|
1302
|
+
* Suffix Ad Content
|
|
1303
|
+
* Text appended after AI response
|
|
1304
|
+
*/
|
|
1305
|
+
export declare interface SuffixAdContent {
|
|
1306
|
+
prefix: string;
|
|
1307
|
+
text: string;
|
|
1308
|
+
product_name: string;
|
|
1309
|
+
cta_text?: string;
|
|
1310
|
+
cta_url?: string;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* TextWeaver Template
|
|
1315
|
+
*/
|
|
1316
|
+
export declare interface SuffixTemplate {
|
|
1317
|
+
id: string;
|
|
1318
|
+
template: string;
|
|
1319
|
+
emoji: string;
|
|
1320
|
+
tone: 'casual' | 'professional' | 'enthusiastic';
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Suffix Ad Variant
|
|
1325
|
+
*/
|
|
1326
|
+
export declare type SuffixVariant = 'inline' | 'block' | 'minimal';
|
|
1327
|
+
|
|
1328
|
+
/**
|
|
1329
|
+
* 发送广告点击事件(便捷方法)
|
|
1330
|
+
*/
|
|
1331
|
+
export declare const trackAdClick: (data: ClickEventData) => Promise<ClickResponse | null>;
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* 发送广告展示事件(便捷方法)
|
|
1335
|
+
*/
|
|
1336
|
+
export declare const trackAdImpression: (data: ImpressionEventData) => Promise<ImpressionResponse | null>;
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* 批量发送点击事件
|
|
1340
|
+
*/
|
|
1341
|
+
export declare function trackClicksBatch(events: ClickEventData[]): Promise<(ClickResponse | null)[]>;
|
|
1342
|
+
|
|
1343
|
+
/**
|
|
1344
|
+
* 批量发送展示事件
|
|
1345
|
+
*/
|
|
1346
|
+
export declare function trackImpressionsBatch(events: ImpressionEventData[]): Promise<(ImpressionResponse | null)[]>;
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* useAdSlots Hook Options
|
|
1350
|
+
*/
|
|
1351
|
+
export declare interface UseAdSlotsOptions {
|
|
1352
|
+
apiBaseUrl?: string;
|
|
1353
|
+
apiKey?: string;
|
|
1354
|
+
slots: AdSlotRequest[];
|
|
1355
|
+
enabled?: boolean;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* useAdSlots Hook Return
|
|
1360
|
+
*/
|
|
1361
|
+
export declare interface UseAdSlotsResult {
|
|
1362
|
+
slots: Record<string, AdSlotResponse>;
|
|
1363
|
+
isLoading: boolean;
|
|
1364
|
+
error: Error | null;
|
|
1365
|
+
requestAds: (context: {
|
|
1366
|
+
conversationContext: ConversationContext;
|
|
1367
|
+
userContext?: UserContext;
|
|
1368
|
+
}) => Promise<void>;
|
|
1369
|
+
clearSlots: () => void;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* User Context
|
|
1374
|
+
*/
|
|
1375
|
+
export declare interface UserContext {
|
|
1376
|
+
userId?: string;
|
|
1377
|
+
sessionId: string;
|
|
1378
|
+
demographics?: UserDemographics;
|
|
1379
|
+
profile?: UserProfile;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* User Demographics
|
|
1384
|
+
*/
|
|
1385
|
+
export declare interface UserDemographics {
|
|
1386
|
+
country?: string;
|
|
1387
|
+
language?: string;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/**
|
|
1391
|
+
* User Information (basic)
|
|
1392
|
+
*/
|
|
1393
|
+
export declare interface UserInfo {
|
|
1394
|
+
id: string;
|
|
1395
|
+
language: string;
|
|
1396
|
+
buyeruid?: string;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* User Profile
|
|
1401
|
+
* User interests and behavior patterns (optional, for personalization)
|
|
1402
|
+
*/
|
|
1403
|
+
export declare interface UserProfile {
|
|
1404
|
+
interests?: string[];
|
|
1405
|
+
behavior?: {
|
|
1406
|
+
preferredTopics?: string[];
|
|
1407
|
+
interactionStyle?: 'concise' | 'detailed' | 'technical' | 'casual';
|
|
1408
|
+
avgSessionLength?: number;
|
|
1409
|
+
};
|
|
1410
|
+
purchaseIntent?: {
|
|
1411
|
+
categories?: string[];
|
|
1412
|
+
priceRange?: string;
|
|
1413
|
+
timeline?: 'immediate' | 'within_week' | 'within_month' | 'researching';
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
export declare interface ViewabilityConfig {
|
|
1418
|
+
/** Minimum visible percentage to consider "in view" (default: 50) */
|
|
1419
|
+
minVisiblePercentage?: number;
|
|
1420
|
+
/** Minimum duration in ms to consider "viewable" (default: 1000) */
|
|
1421
|
+
minViewableDuration?: number;
|
|
1422
|
+
/** Maximum tracking duration in ms (default: 60000 = 1 minute) */
|
|
1423
|
+
maxTrackingDuration?: number;
|
|
1424
|
+
/** Batch events before sending (default: 5 events or 10 seconds) */
|
|
1425
|
+
batchConfig?: {
|
|
1426
|
+
maxBatchSize?: number;
|
|
1427
|
+
maxBatchWaitMs?: number;
|
|
1428
|
+
};
|
|
1429
|
+
/** Enable debug logging (default: false) */
|
|
1430
|
+
debug?: boolean;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
export declare interface ViewabilityEventData {
|
|
1434
|
+
adId: string;
|
|
1435
|
+
sessionId: string;
|
|
1436
|
+
requestId?: string;
|
|
1437
|
+
viewToken?: string;
|
|
1438
|
+
eventType: ViewabilityEventType;
|
|
1439
|
+
visiblePercentage: number;
|
|
1440
|
+
maxVisiblePercentage: number;
|
|
1441
|
+
totalVisibleTimeMs: number;
|
|
1442
|
+
isViewable: boolean;
|
|
1443
|
+
viewportWidth?: number;
|
|
1444
|
+
viewportHeight?: number;
|
|
1445
|
+
elementWidth?: number;
|
|
1446
|
+
elementHeight?: number;
|
|
1447
|
+
positionX?: number;
|
|
1448
|
+
positionY?: number;
|
|
1449
|
+
timestamp: number;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
/**
|
|
1453
|
+
* Viewability Tracking Module (IAB/MRC Compliant)
|
|
1454
|
+
*
|
|
1455
|
+
* IAB/MRC Standard:
|
|
1456
|
+
* - Viewable: >50% of ad pixels in view for >1 second
|
|
1457
|
+
* - Uses IntersectionObserver API for efficient tracking
|
|
1458
|
+
*
|
|
1459
|
+
* Event-driven approach: Only sends data on state changes, not periodic sampling
|
|
1460
|
+
*/
|
|
1461
|
+
export declare type ViewabilityEventType = 'enter_viewport' | 'become_viewable' | 'update_viewability' | 'exit_viewport' | 'end_tracking';
|
|
1462
|
+
|
|
1463
|
+
export declare interface ViewabilityMetrics {
|
|
1464
|
+
/** Current visible percentage (0-100) */
|
|
1465
|
+
visiblePercentage: number;
|
|
1466
|
+
/** Maximum visible percentage observed */
|
|
1467
|
+
maxVisiblePercentage: number;
|
|
1468
|
+
/** Total time visible in ms */
|
|
1469
|
+
totalVisibleTimeMs: number;
|
|
1470
|
+
/** Current continuous visible time in ms */
|
|
1471
|
+
currentVisibleTimeMs: number;
|
|
1472
|
+
/** Whether meets IAB/MRC viewable criteria */
|
|
1473
|
+
isViewable: boolean;
|
|
1474
|
+
/** Time when became viewable (null if not viewable yet) */
|
|
1475
|
+
viewableAt: number | null;
|
|
1476
|
+
/** Time when entered viewport (null if never entered) */
|
|
1477
|
+
enteredViewportAt: number | null;
|
|
1478
|
+
/** Total number of times entered viewport */
|
|
1479
|
+
enterCount: number;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
/**
|
|
1483
|
+
* ViewabilityTracker class for tracking ad viewability
|
|
1484
|
+
* Event-driven: Only sends data on state changes
|
|
1485
|
+
*/
|
|
1486
|
+
export declare class ViewabilityTracker {
|
|
1487
|
+
private observers;
|
|
1488
|
+
private metrics;
|
|
1489
|
+
private timers;
|
|
1490
|
+
private batchTimers;
|
|
1491
|
+
private eventQueue;
|
|
1492
|
+
private config;
|
|
1493
|
+
private baseUrl;
|
|
1494
|
+
private isTracking;
|
|
1495
|
+
constructor(config?: ViewabilityConfig, baseUrl?: string);
|
|
1496
|
+
/**
|
|
1497
|
+
* Start tracking viewability for an ad element
|
|
1498
|
+
*/
|
|
1499
|
+
startTracking(adId: string, element: HTMLElement, sessionId: string, requestId?: string, viewToken?: string): void;
|
|
1500
|
+
/**
|
|
1501
|
+
* Stop tracking an ad element
|
|
1502
|
+
*/
|
|
1503
|
+
stopTracking(adId: string): void;
|
|
1504
|
+
/**
|
|
1505
|
+
* Get current metrics for an ad
|
|
1506
|
+
*/
|
|
1507
|
+
getMetrics(adId: string): ViewabilityMetrics | undefined;
|
|
1508
|
+
/**
|
|
1509
|
+
* Handle IntersectionObserver callback
|
|
1510
|
+
* Event-driven: Only process when state actually changes
|
|
1511
|
+
*/
|
|
1512
|
+
private handleIntersection;
|
|
1513
|
+
/**
|
|
1514
|
+
* Start monitoring loop for tracking duration
|
|
1515
|
+
* Runs every 100ms to track continuous visible time
|
|
1516
|
+
*/
|
|
1517
|
+
private startMonitoring;
|
|
1518
|
+
/**
|
|
1519
|
+
* Queue an event to be sent (batched)
|
|
1520
|
+
*/
|
|
1521
|
+
private queueEvent;
|
|
1522
|
+
/**
|
|
1523
|
+
* Flush the event queue and send to server
|
|
1524
|
+
*/
|
|
1525
|
+
private flushQueue;
|
|
1526
|
+
/**
|
|
1527
|
+
* End tracking and send final metrics
|
|
1528
|
+
*/
|
|
1529
|
+
private endTracking;
|
|
1530
|
+
/**
|
|
1531
|
+
* Cleanup resources for an ad
|
|
1532
|
+
*/
|
|
1533
|
+
private cleanup;
|
|
1534
|
+
/**
|
|
1535
|
+
* Create thresholds for IntersectionObserver
|
|
1536
|
+
*/
|
|
1537
|
+
private createThresholds;
|
|
1538
|
+
/**
|
|
1539
|
+
* Stop all tracking
|
|
1540
|
+
*/
|
|
1541
|
+
stopAll(): void;
|
|
1542
|
+
/**
|
|
1543
|
+
* Debug logging
|
|
1544
|
+
*/
|
|
1545
|
+
private log;
|
|
1546
|
+
/**
|
|
1547
|
+
* Send any pending events before page unload
|
|
1548
|
+
*/
|
|
1549
|
+
setupBeforeUnload(): void;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
export { }
|