@the_ro_show/agent-ads-sdk 0.14.0 → 0.15.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 +180 -0
- package/dist/index.d.mts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +211 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -304,6 +304,172 @@ function sanitizeURL(url, options) {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
// src/utils/intent-detector.ts
|
|
308
|
+
var INTENT_PATTERNS = {
|
|
309
|
+
research: [
|
|
310
|
+
"what is",
|
|
311
|
+
"how does",
|
|
312
|
+
"explain",
|
|
313
|
+
"tell me about",
|
|
314
|
+
"learn about",
|
|
315
|
+
"understand",
|
|
316
|
+
"guide",
|
|
317
|
+
"tips",
|
|
318
|
+
"basics",
|
|
319
|
+
"introduction",
|
|
320
|
+
"overview",
|
|
321
|
+
"how to"
|
|
322
|
+
],
|
|
323
|
+
comparison: [
|
|
324
|
+
"vs",
|
|
325
|
+
"versus",
|
|
326
|
+
"compare",
|
|
327
|
+
"better than",
|
|
328
|
+
"difference",
|
|
329
|
+
"which",
|
|
330
|
+
"choose between",
|
|
331
|
+
"alternative",
|
|
332
|
+
"review",
|
|
333
|
+
"pros and cons",
|
|
334
|
+
"best",
|
|
335
|
+
"top",
|
|
336
|
+
"recommend"
|
|
337
|
+
],
|
|
338
|
+
ready_to_buy: [
|
|
339
|
+
"buy now",
|
|
340
|
+
"purchase",
|
|
341
|
+
"get quote",
|
|
342
|
+
"sign up",
|
|
343
|
+
"subscribe",
|
|
344
|
+
"order now",
|
|
345
|
+
"book now",
|
|
346
|
+
"reserve",
|
|
347
|
+
"apply now",
|
|
348
|
+
"start now",
|
|
349
|
+
"pricing",
|
|
350
|
+
"cost",
|
|
351
|
+
"how much",
|
|
352
|
+
"discount",
|
|
353
|
+
"deal",
|
|
354
|
+
"promo code",
|
|
355
|
+
"coupon",
|
|
356
|
+
"special offer",
|
|
357
|
+
"ready to buy",
|
|
358
|
+
"want to buy",
|
|
359
|
+
"where can i buy",
|
|
360
|
+
"how to purchase"
|
|
361
|
+
]
|
|
362
|
+
};
|
|
363
|
+
var INTEREST_PATTERNS = {
|
|
364
|
+
travel: ["travel", "trip", "vacation", "flight", "hotel", "destination", "tour", "cruise"],
|
|
365
|
+
fitness: ["fitness", "workout", "gym", "exercise", "health", "diet", "nutrition", "yoga"],
|
|
366
|
+
technology: ["tech", "software", "app", "computer", "phone", "gadget", "device", "AI"],
|
|
367
|
+
finance: ["finance", "money", "invest", "savings", "loan", "credit", "mortgage", "budget"],
|
|
368
|
+
insurance: ["insurance", "coverage", "policy", "claim", "premium", "deductible"],
|
|
369
|
+
automotive: ["car", "auto", "vehicle", "drive", "truck", "SUV", "motorcycle"],
|
|
370
|
+
education: ["learn", "course", "class", "school", "university", "degree", "certification"],
|
|
371
|
+
shopping: ["shop", "store", "buy", "sale", "discount", "deal", "online shopping"],
|
|
372
|
+
food: ["food", "restaurant", "cooking", "recipe", "meal", "dining", "cuisine"],
|
|
373
|
+
entertainment: ["movie", "show", "music", "game", "concert", "event", "streaming"],
|
|
374
|
+
home: ["home", "house", "apartment", "furniture", "decor", "renovation", "real estate"],
|
|
375
|
+
business: ["business", "company", "startup", "entrepreneur", "marketing", "sales"],
|
|
376
|
+
legal: ["legal", "lawyer", "attorney", "law", "contract", "lawsuit", "court"],
|
|
377
|
+
healthcare: ["health", "medical", "doctor", "hospital", "treatment", "therapy", "medicine"],
|
|
378
|
+
parenting: ["baby", "child", "parent", "family", "kids", "pregnancy", "school"],
|
|
379
|
+
wedding: ["wedding", "marriage", "engagement", "bride", "groom", "ceremony"],
|
|
380
|
+
pets: ["pet", "dog", "cat", "animal", "vet", "puppy", "kitten"],
|
|
381
|
+
beauty: ["beauty", "makeup", "skincare", "hair", "cosmetics", "salon", "spa"],
|
|
382
|
+
sports: ["sports", "game", "team", "player", "football", "basketball", "soccer"],
|
|
383
|
+
fashion: ["fashion", "clothing", "style", "outfit", "designer", "shoes", "accessories"]
|
|
384
|
+
};
|
|
385
|
+
function detectIntentStage(message, conversationHistory) {
|
|
386
|
+
const lowerMessage = message.toLowerCase();
|
|
387
|
+
const fullContext = conversationHistory ? [...conversationHistory, message].join(" ").toLowerCase() : lowerMessage;
|
|
388
|
+
for (const pattern of INTENT_PATTERNS.ready_to_buy) {
|
|
389
|
+
if (fullContext.includes(pattern)) {
|
|
390
|
+
return "ready_to_buy";
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
for (const pattern of INTENT_PATTERNS.comparison) {
|
|
394
|
+
if (fullContext.includes(pattern)) {
|
|
395
|
+
return "comparison";
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
for (const pattern of INTENT_PATTERNS.research) {
|
|
399
|
+
if (lowerMessage.includes(pattern)) {
|
|
400
|
+
return "research";
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return void 0;
|
|
404
|
+
}
|
|
405
|
+
function extractInterests(message, conversationHistory) {
|
|
406
|
+
const interests = /* @__PURE__ */ new Set();
|
|
407
|
+
const validHistory = (conversationHistory || []).filter((msg) => typeof msg === "string" && msg.trim().length > 0);
|
|
408
|
+
const fullContext = validHistory.length > 0 ? [...validHistory, message].join(" ").toLowerCase() : message.toLowerCase();
|
|
409
|
+
for (const [interest, keywords] of Object.entries(INTEREST_PATTERNS)) {
|
|
410
|
+
for (const keyword of keywords) {
|
|
411
|
+
if (fullContext.includes(keyword)) {
|
|
412
|
+
interests.add(interest);
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return Array.from(interests);
|
|
418
|
+
}
|
|
419
|
+
function extractTopics(conversationHistory) {
|
|
420
|
+
if (!conversationHistory || conversationHistory.length === 0) {
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
423
|
+
const topics = [];
|
|
424
|
+
const seen = /* @__PURE__ */ new Set();
|
|
425
|
+
for (const message of conversationHistory.slice(-5)) {
|
|
426
|
+
const lowerMessage = message.toLowerCase();
|
|
427
|
+
for (const [topic, keywords] of Object.entries(INTEREST_PATTERNS)) {
|
|
428
|
+
if (!seen.has(topic)) {
|
|
429
|
+
for (const keyword of keywords) {
|
|
430
|
+
if (lowerMessage.includes(keyword)) {
|
|
431
|
+
topics.push(topic);
|
|
432
|
+
seen.add(topic);
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return topics.slice(0, 3);
|
|
440
|
+
}
|
|
441
|
+
function generateSessionId() {
|
|
442
|
+
const timestamp = Date.now().toString(36);
|
|
443
|
+
const random = Math.random().toString(36).substring(2, 9);
|
|
444
|
+
return `sess_${timestamp}_${random}`;
|
|
445
|
+
}
|
|
446
|
+
function detectPurchaseIntent(message, intentStage) {
|
|
447
|
+
if (intentStage === "ready_to_buy") {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
const lowerMessage = message.toLowerCase();
|
|
451
|
+
const purchaseKeywords = [
|
|
452
|
+
"buy",
|
|
453
|
+
"purchase",
|
|
454
|
+
"order",
|
|
455
|
+
"get",
|
|
456
|
+
"subscribe",
|
|
457
|
+
"sign up",
|
|
458
|
+
"apply",
|
|
459
|
+
"book",
|
|
460
|
+
"reserve",
|
|
461
|
+
"quote",
|
|
462
|
+
"pricing",
|
|
463
|
+
"cost",
|
|
464
|
+
"how much",
|
|
465
|
+
"where can i"
|
|
466
|
+
];
|
|
467
|
+
return purchaseKeywords.some((keyword) => lowerMessage.includes(keyword));
|
|
468
|
+
}
|
|
469
|
+
function calculateMessageCount(conversationHistory) {
|
|
470
|
+
return (conversationHistory?.length || 0) + 1;
|
|
471
|
+
}
|
|
472
|
+
|
|
307
473
|
// src/client.ts
|
|
308
474
|
var DEFAULT_BASE_URL = "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1";
|
|
309
475
|
var DEFAULT_TIMEOUT_MS = 4e3;
|
|
@@ -449,6 +615,16 @@ var AttentionMarketClient = class {
|
|
|
449
615
|
const limitedHistory = history.slice(-historyLimit);
|
|
450
616
|
const contextParts = [...limitedHistory, params.userMessage];
|
|
451
617
|
const context = contextParts.join("\n");
|
|
618
|
+
const intentStage = params.session_context?.intent_stage || detectIntentStage(params.userMessage, limitedHistory);
|
|
619
|
+
let interests = params.user_context?.interests || extractInterests(params.userMessage, limitedHistory);
|
|
620
|
+
interests = interests.filter((interest) => typeof interest === "string" && interest.trim().length > 0).map((interest) => interest.trim().toLowerCase()).slice(0, 10);
|
|
621
|
+
let recentTopics = params.user_context?.recent_topics || extractTopics(limitedHistory);
|
|
622
|
+
recentTopics = recentTopics.filter((topic) => typeof topic === "string" && topic.trim().length > 0).map((topic) => topic.trim().toLowerCase()).slice(0, 5);
|
|
623
|
+
const purchaseIntent = params.user_context?.purchase_intent !== void 0 ? Boolean(params.user_context.purchase_intent) : detectPurchaseIntent(params.userMessage, intentStage);
|
|
624
|
+
const rawSessionId = params.session_context?.session_id;
|
|
625
|
+
const sessionId = typeof rawSessionId === "string" && rawSessionId.trim().length > 0 ? rawSessionId.trim().slice(0, 100) : generateSessionId();
|
|
626
|
+
const rawMessageCount = params.session_context?.message_count;
|
|
627
|
+
const messageCount = typeof rawMessageCount === "number" && rawMessageCount >= 0 ? Math.min(rawMessageCount, 1e3) : calculateMessageCount(limitedHistory);
|
|
452
628
|
const country = params.country || "US";
|
|
453
629
|
const language = params.language || "en";
|
|
454
630
|
const platform = params.platform || "web";
|
|
@@ -537,6 +713,23 @@ var AttentionMarketClient = class {
|
|
|
537
713
|
user_intent: params.userMessage,
|
|
538
714
|
// Use minimal response format by default for better performance
|
|
539
715
|
response_format: "minimal",
|
|
716
|
+
// === Smart Context Fields (v0.15.0) ===
|
|
717
|
+
// Include user context if we have any data
|
|
718
|
+
...(interests.length > 0 || recentTopics.length > 0 || purchaseIntent) && {
|
|
719
|
+
user_context: {
|
|
720
|
+
...interests.length > 0 && { interests },
|
|
721
|
+
...recentTopics.length > 0 && { recent_topics: recentTopics },
|
|
722
|
+
...purchaseIntent && { purchase_intent: purchaseIntent }
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
// Include session context
|
|
726
|
+
...sessionId && {
|
|
727
|
+
session_context: {
|
|
728
|
+
session_id: sessionId,
|
|
729
|
+
message_count: messageCount,
|
|
730
|
+
...intentStage && { intent_stage: intentStage }
|
|
731
|
+
}
|
|
732
|
+
},
|
|
540
733
|
// Developer controls (Phase 1: Quality & Brand Safety)
|
|
541
734
|
...params.minQualityScore !== void 0 && { minQualityScore: params.minQualityScore },
|
|
542
735
|
...params.allowedCategories && { allowedCategories: params.allowedCategories },
|
|
@@ -548,17 +741,22 @@ var AttentionMarketClient = class {
|
|
|
548
741
|
...params.optimizeFor && { optimizeFor: params.optimizeFor }
|
|
549
742
|
};
|
|
550
743
|
const response = await this.decideRaw(request, options);
|
|
551
|
-
if (response.creative) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
744
|
+
if (response && response.creative) {
|
|
745
|
+
if (response["_meta"]) {
|
|
746
|
+
try {
|
|
747
|
+
await this.track({
|
|
748
|
+
event_id: `evt_${generateUUID()}`,
|
|
749
|
+
event_type: "impression",
|
|
750
|
+
occurred_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
751
|
+
agent_id: this.agentId,
|
|
752
|
+
request_id: response["_meta"]["request_id"],
|
|
753
|
+
decision_id: response["_meta"]["decision_id"],
|
|
754
|
+
unit_id: response["_meta"]["unit_id"],
|
|
755
|
+
tracking_token: response.tracking_token
|
|
756
|
+
});
|
|
757
|
+
} catch (error) {
|
|
758
|
+
console.warn("[AttentionMarket] Failed to auto-track impression:", error);
|
|
759
|
+
}
|
|
562
760
|
}
|
|
563
761
|
const adResponse2 = {
|
|
564
762
|
request_id: request.request_id,
|
|
@@ -571,6 +769,7 @@ var AttentionMarketClient = class {
|
|
|
571
769
|
tracking_url: response.click_url || "",
|
|
572
770
|
// Same as click_url
|
|
573
771
|
tracking_token: response.tracking_token || "",
|
|
772
|
+
...response.relevance_score !== void 0 && { relevance_score: response.relevance_score },
|
|
574
773
|
disclosure: response.disclosure || {
|
|
575
774
|
label: "Sponsored",
|
|
576
775
|
explanation: "This is a paid advertisement",
|
|
@@ -584,7 +783,7 @@ var AttentionMarketClient = class {
|
|
|
584
783
|
};
|
|
585
784
|
return adResponse2;
|
|
586
785
|
}
|
|
587
|
-
if (response.status === "no_fill" || !response.units || response.units.length === 0) {
|
|
786
|
+
if (!response || response.status === "no_fill" || !response.units || response.units.length === 0) {
|
|
588
787
|
return null;
|
|
589
788
|
}
|
|
590
789
|
const adUnit = response.units[0];
|