@the_ro_show/agent-ads-sdk 0.4.2 → 0.5.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/dist/index.d.mts CHANGED
@@ -197,11 +197,189 @@ interface APIError {
197
197
  interface SDKConfig {
198
198
  apiKey: string;
199
199
  agentId?: string;
200
+ appId?: string;
200
201
  supabaseAnonKey?: string;
201
202
  baseUrl?: string;
202
203
  timeoutMs?: number;
203
204
  maxRetries?: number;
204
205
  }
206
+ /**
207
+ * Request an offer using explicit intent-key matching.
208
+ *
209
+ * This is the deterministic, high-confidence API for when you KNOW what
210
+ * the user wants. Use intentKey for exact matching instead of semantic search.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const offer = await client.requestOffer({
215
+ * placementId: 'chat_suggestion',
216
+ * intentKey: 'coffee.purchase.nearby',
217
+ * context: {
218
+ * geo: { city: 'NYC', country: 'US' }
219
+ * }
220
+ * });
221
+ * ```
222
+ */
223
+ interface RequestOfferParams {
224
+ /** Placement identifier (e.g., 'chat_suggestion', 'inline_card') */
225
+ placementId: string;
226
+ /**
227
+ * Intent key for matching (e.g., 'coffee', 'coffee.purchase', 'legal.estate_planning')
228
+ * Uses hierarchical matching: tries exact match, then walks up taxonomy.
229
+ */
230
+ intentKey: string;
231
+ /**
232
+ * PREVIEW: Source agent for revenue share tracking (optional)
233
+ *
234
+ * When another agent refers traffic to you, they can include their
235
+ * agent_id to track referrals. When revenue share is enabled (future),
236
+ * the source agent will receive the specified percentage.
237
+ *
238
+ * @experimental Revenue share not active yet - logs for analytics only
239
+ */
240
+ sourceAgentId?: string;
241
+ /**
242
+ * PREVIEW: Revenue share percentage for source agent (0-50)
243
+ * Only applies if sourceAgentId is provided.
244
+ *
245
+ * @experimental Revenue share not active yet
246
+ */
247
+ revenueSharePct?: number;
248
+ /** Context for targeting and personalization */
249
+ context?: {
250
+ /** Geographic context */
251
+ geo?: {
252
+ country?: string;
253
+ region?: string;
254
+ city?: string;
255
+ lat?: number;
256
+ lng?: number;
257
+ };
258
+ /** Locale for language/region targeting */
259
+ locale?: string;
260
+ /**
261
+ * Optional semantic context for fallback matching.
262
+ * If exact intent-key match fails, system will try semantic matching
263
+ * using this context within the intent-key category.
264
+ */
265
+ semanticContext?: string;
266
+ /**
267
+ * User context identifier for deduplication (optional)
268
+ * Use a session hash or similar - NO PII
269
+ */
270
+ userContextId?: string;
271
+ };
272
+ /** Constraints for filtering offers */
273
+ constraints?: {
274
+ /** Minimum CPC in micros (e.g., 1000000 = $1.00) */
275
+ minCpcMicros?: number;
276
+ /** Block specific campaigns from being returned */
277
+ blockCampaignIds?: string[];
278
+ };
279
+ }
280
+ /**
281
+ * Request an offer using semantic context matching.
282
+ *
283
+ * This is the fuzzy, discovery API for when you're NOT certain what
284
+ * the user wants. Pass conversation context and let semantic search
285
+ * figure out the best match.
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const offer = await client.requestOfferFromContext({
290
+ * placementId: 'chat_suggestion',
291
+ * userMessage: "I'm so tired, long day...",
292
+ * conversationHistory: ["How was work?", "Exhausting"],
293
+ * context: { geo: { city: 'NYC' } }
294
+ * });
295
+ * ```
296
+ */
297
+ interface RequestOfferFromContextParams {
298
+ /** Placement identifier */
299
+ placementId: string;
300
+ /** User's current message */
301
+ userMessage: string;
302
+ /**
303
+ * Optional conversation history for context.
304
+ * SDK automatically limits to last 5 messages.
305
+ */
306
+ conversationHistory?: string[];
307
+ /**
308
+ * PREVIEW: Source agent for revenue share tracking (optional)
309
+ * @experimental Revenue share not active yet
310
+ */
311
+ sourceAgentId?: string;
312
+ /**
313
+ * PREVIEW: Revenue share percentage (0-50)
314
+ * @experimental Revenue share not active yet
315
+ */
316
+ revenueSharePct?: number;
317
+ /** Context for targeting */
318
+ context?: {
319
+ geo?: {
320
+ country?: string;
321
+ region?: string;
322
+ city?: string;
323
+ };
324
+ locale?: string;
325
+ userContextId?: string;
326
+ };
327
+ /** Optional category hint as fallback */
328
+ suggestedCategory?: string;
329
+ }
330
+ /**
331
+ * Offer response (intent-key or semantic matching)
332
+ */
333
+ interface OfferResponse {
334
+ /** Unique offer identifier */
335
+ offer_id: string;
336
+ /** Request that generated this offer */
337
+ request_id: string;
338
+ /** Impression identifier for tracking */
339
+ impression_id: string;
340
+ /** Campaign that won the auction */
341
+ campaign_id: string;
342
+ /** Creative content */
343
+ creative: {
344
+ title: string;
345
+ body: string;
346
+ cta: string;
347
+ };
348
+ /** Click URL for tracking */
349
+ click_url: string;
350
+ /** Direct landing URL (no tracking) */
351
+ direct_url: string;
352
+ /** Disclosure information */
353
+ disclosure: {
354
+ label: string;
355
+ sponsor_name: string;
356
+ };
357
+ /**
358
+ * Tracking token for manual impression/click tracking.
359
+ * Only needed if you use direct_url instead of click_url.
360
+ */
361
+ tracking_token: string;
362
+ /** Match metadata */
363
+ match_info: {
364
+ /** How was this matched: 'intent_key' | 'semantic' | 'hybrid' */
365
+ match_method: 'intent_key' | 'semantic' | 'hybrid';
366
+ /** For semantic matches: similarity score (0-1) */
367
+ similarity?: number;
368
+ /** Intent key that matched (may differ from request if hierarchical) */
369
+ matched_intent_key?: string;
370
+ };
371
+ /**
372
+ * Revenue share information (preview)
373
+ * @experimental Not active yet
374
+ */
375
+ revenue_share?: {
376
+ status: 'preview' | 'active';
377
+ source_agent_id?: string;
378
+ source_agent_pct?: number;
379
+ };
380
+ /** Time-to-live in milliseconds */
381
+ ttl_ms: number;
382
+ }
205
383
 
206
384
  /**
207
385
  * Utility functions for the AttentionMarket SDK.
@@ -357,6 +535,7 @@ declare function sanitizeURL(url: string | null | undefined, options?: SanitizeU
357
535
  declare class AttentionMarketClient {
358
536
  private http;
359
537
  private agentId;
538
+ private appId;
360
539
  constructor(config: SDKConfig);
361
540
  /**
362
541
  * Validate SDK configuration for security
@@ -422,6 +601,91 @@ declare class AttentionMarketClient {
422
601
  static signupAgent(request: AgentSignupRequest, options?: {
423
602
  baseUrl?: string;
424
603
  }): Promise<AgentSignupResponse>;
604
+ /**
605
+ * Validate intent-key format.
606
+ * Format: vertical.category[.subcategory][.intent]
607
+ * Examples: "coffee", "coffee.purchase", "legal.estate_planning.wills"
608
+ */
609
+ private validateIntentKey;
610
+ /**
611
+ * Validate placement ID is not empty
612
+ */
613
+ private validatePlacementId;
614
+ /**
615
+ * Validate revenue share percentage (0-50)
616
+ */
617
+ private validateRevenueShare;
618
+ /**
619
+ * Normalize and validate locale string
620
+ */
621
+ private normalizeLocale;
622
+ /**
623
+ * Request an offer using explicit intent-key matching.
624
+ *
625
+ * Use this API when you have HIGH CONFIDENCE about user intent.
626
+ * Intent-keys enable deterministic matching and agent-to-agent coordination.
627
+ *
628
+ * **Current Limitations:**
629
+ * - Backend uses semantic matching (intentKey mapped to taxonomy field)
630
+ * - `campaign_id` not yet available from backend (returns `unit_id` as placeholder)
631
+ * - `click_url` equals `direct_url` (click redirector not implemented)
632
+ * - Revenue share tracked but payouts not active (preview mode)
633
+ *
634
+ * @example
635
+ * ```typescript
636
+ * // User explicitly said "order coffee for delivery"
637
+ * const offer = await client.requestOffer({
638
+ * placementId: 'order_card',
639
+ * intentKey: 'coffee.purchase.delivery',
640
+ * context: { geo: { city: 'SF', country: 'US' } }
641
+ * });
642
+ *
643
+ * if (offer) {
644
+ * // Use tracked click URL for attribution
645
+ * window.open(offer.click_url);
646
+ * }
647
+ * ```
648
+ *
649
+ * @throws {Error} If agentId or appId not provided in SDKConfig
650
+ * @throws {Error} If intentKey format is invalid
651
+ * @throws {Error} If revenueSharePct out of range (0-50)
652
+ */
653
+ requestOffer(params: RequestOfferParams, options?: {
654
+ idempotencyKey?: string;
655
+ }): Promise<OfferResponse | null>;
656
+ /**
657
+ * Request an offer using semantic context matching.
658
+ *
659
+ * This is the fuzzy, discovery API for when you're NOT certain what
660
+ * the user wants. Pass conversation context and let semantic search
661
+ * figure out the best match.
662
+ *
663
+ * **Current Limitations:**
664
+ * - `campaign_id` not yet available from backend (returns `unit_id` as placeholder)
665
+ * - `click_url` equals `direct_url` (click redirector not implemented)
666
+ * - Revenue share tracked but payouts not active (preview mode)
667
+ * - Conversation history auto-limited to last 5 messages
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * const offer = await client.requestOfferFromContext({
672
+ * placementId: 'chat_suggestion',
673
+ * userMessage: "I'm so tired, long day at work...",
674
+ * conversationHistory: ["How was your day?", "Exhausting"],
675
+ * context: { geo: { city: 'NYC' } }
676
+ * });
677
+ *
678
+ * if (offer) {
679
+ * console.log(`Maybe you'd like: ${offer.creative.title}`);
680
+ * }
681
+ * ```
682
+ *
683
+ * @throws {Error} If agentId was not provided in SDKConfig
684
+ * @throws {Error} If revenueSharePct out of range (0-50)
685
+ */
686
+ requestOfferFromContext(params: RequestOfferFromContextParams, options?: {
687
+ idempotencyKey?: string;
688
+ }): Promise<OfferResponse | null>;
425
689
  }
426
690
 
427
691
  /**
@@ -548,6 +812,127 @@ declare class TimeoutError extends AttentionMarketError {
548
812
  constructor(message?: string);
549
813
  }
550
814
 
815
+ /**
816
+ * Natural ad formatting utilities
817
+ *
818
+ * Transforms ad copy to feel more conversational while preserving
819
+ * all tracking data and disclosure requirements.
820
+ */
821
+
822
+ interface NaturalFormatOptions {
823
+ /**
824
+ * Tone/style for the formatted text
825
+ * - 'conversational': Friendly, natural language
826
+ * - 'helpful': Informative assistant tone
827
+ * - 'direct': Clear and concise
828
+ */
829
+ style?: 'conversational' | 'helpful' | 'direct';
830
+ /**
831
+ * Optional user context to make formatting more relevant
832
+ * Example: "User is looking for estate planning help"
833
+ */
834
+ userContext?: string;
835
+ /**
836
+ * Maximum length for formatted text (characters)
837
+ * Will truncate gracefully if needed
838
+ */
839
+ maxLength?: number;
840
+ /**
841
+ * Whether to include the disclosure inline
842
+ * Default: true (always show sponsored label)
843
+ */
844
+ includeDisclosure?: boolean;
845
+ }
846
+ interface FormattedAd {
847
+ /**
848
+ * Naturally formatted text suitable for conversation
849
+ */
850
+ text: string;
851
+ /**
852
+ * Call-to-action text
853
+ */
854
+ cta: string;
855
+ /**
856
+ * Action URL (preserved from original ad)
857
+ */
858
+ actionUrl: string;
859
+ /**
860
+ * Tracking data (preserved from original ad)
861
+ * IMPORTANT: Pass this to trackClick() when user clicks
862
+ */
863
+ tracking: {
864
+ eventId: string;
865
+ trackingToken: string;
866
+ decisionId: string;
867
+ };
868
+ /**
869
+ * Disclosure information (preserved from original ad)
870
+ */
871
+ disclosure: {
872
+ label: string;
873
+ sponsorName: string;
874
+ };
875
+ }
876
+ /**
877
+ * Format an ad unit into natural conversational text.
878
+ * Preserves all tracking data and disclosure requirements.
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * const ad = await client.decide({...});
883
+ * const formatted = formatNatural(ad, {
884
+ * style: 'conversational',
885
+ * userContext: "User needs estate planning help"
886
+ * });
887
+ *
888
+ * console.log(formatted.text);
889
+ * // "I found a service that might help: [Title]. [Body]"
890
+ *
891
+ * // When user clicks, tracking still works:
892
+ * await client.trackClick({
893
+ * event_id: formatted.tracking.eventId,
894
+ * tracking_token: formatted.tracking.trackingToken
895
+ * });
896
+ * ```
897
+ */
898
+ declare function formatNatural(ad: AdUnit, options?: NaturalFormatOptions): FormattedAd;
899
+ /**
900
+ * Extract just the essential info from an ad for inline mentions.
901
+ * Useful when you want to reference an ad without showing the full text.
902
+ *
903
+ * @example
904
+ * ```typescript
905
+ * const mention = formatInlineMention(ad);
906
+ * console.log(`You might want to check out ${mention.text}`);
907
+ * // "You might want to check out Estate Planning Services (Sponsored)"
908
+ * ```
909
+ */
910
+ declare function formatInlineMention(ad: AdUnit): FormattedAd;
911
+ /**
912
+ * Validate that an ad fits within UI constraints.
913
+ * Helps developers check if ad will display correctly before showing it.
914
+ *
915
+ * @example
916
+ * ```typescript
917
+ * const validation = validateAdFits(ad, {
918
+ * maxTitleChars: 60,
919
+ * maxBodyChars: 200
920
+ * });
921
+ *
922
+ * if (!validation.fits) {
923
+ * console.log('Ad too long:', validation.violations);
924
+ * }
925
+ * ```
926
+ */
927
+ declare function validateAdFits(ad: AdUnit, constraints: {
928
+ maxTitleChars?: number;
929
+ maxBodyChars?: number;
930
+ maxCtaChars?: number;
931
+ }): {
932
+ fits: boolean;
933
+ violations: string[];
934
+ };
935
+
551
936
  /**
552
937
  * Taxonomy helper utilities for AttentionMarket SDK
553
938
  * Helps with building, validating, and working with the 4-tier taxonomy system
@@ -705,4 +1090,4 @@ declare function getVertical(taxonomy: string): string | null;
705
1090
  */
706
1091
  declare function suggestTaxonomies(query: string): string[];
707
1092
 
708
- export { type APIError, APIRequestError, type AdScore, type AdUnit, type AgentSignupRequest, type AgentSignupResponse, AttentionMarketClient, AttentionMarketError, type Constraints, type Context, type CreateClickEventParams, type CreateImpressionEventParams, type CreateOpportunityParams, type DecideFromContextRequest, type DecideRequest, type DecideResponse, type Disclosure, type EventIngestRequest, type EventIngestResponse, type EventType, type Intent, MockAttentionMarketClient, type MockClientConfig, NetworkError, type Opportunity, type ParsedTaxonomy, type Placement, type PlacementType, type PolicyResponse, type Privacy, type SDKConfig, type SanitizeURLOptions, type SponsoredSuggestion, type SponsoredTool, type TaxonomyIntent, TimeoutError, type ToolCall, type Tracking, buildTaxonomy, createClickEvent, createImpressionEvent, createOpportunity, detectIntent, escapeHTML, generateTimestamp, generateUUID, getBaseTaxonomy, getVertical, isValidTaxonomy, matchesTaxonomy, parseTaxonomy, sanitizeURL, suggestTaxonomies };
1093
+ export { type APIError, APIRequestError, type AdScore, type AdUnit, type AgentSignupRequest, type AgentSignupResponse, AttentionMarketClient, AttentionMarketError, type Constraints, type Context, type CreateClickEventParams, type CreateImpressionEventParams, type CreateOpportunityParams, type DecideFromContextRequest, type DecideRequest, type DecideResponse, type Disclosure, type EventIngestRequest, type EventIngestResponse, type EventType, type FormattedAd, type Intent, MockAttentionMarketClient, type MockClientConfig, type NaturalFormatOptions, NetworkError, type OfferResponse, type Opportunity, type ParsedTaxonomy, type Placement, type PlacementType, type PolicyResponse, type Privacy, type RequestOfferFromContextParams, type RequestOfferParams, type SDKConfig, type SanitizeURLOptions, type SponsoredSuggestion, type SponsoredTool, type TaxonomyIntent, TimeoutError, type ToolCall, type Tracking, buildTaxonomy, createClickEvent, createImpressionEvent, createOpportunity, detectIntent, escapeHTML, formatInlineMention, formatNatural, generateTimestamp, generateUUID, getBaseTaxonomy, getVertical, isValidTaxonomy, matchesTaxonomy, parseTaxonomy, sanitizeURL, suggestTaxonomies, validateAdFits };