@admesh/weave-node
Version:
AdMesh Backend SDK for Node.js - Subscribe to and weave recommendations into LLM responses
588 lines (464 loc) • 17.3 kB
Markdown
# @admesh/weave-node
Lightweight backend SDK for Node.js that fetches recommendations from the AdMesh Protocol service. This SDK enables AI platforms to integrate AdMesh's **Weave Ad Format** into their LLM responses.
## Overview
The `@admesh/weave-node` SDK is a thin client wrapper that:
- **Fetches recommendations** directly from admesh-protocol's `/agent/recommend` endpoint via HTTP POST
- **Uses database-backed caching** for instant retrieval of previously generated recommendations
- **Formats recommendations** for seamless integration into LLM prompts
- **Falls back gracefully** if no recommendations are available
### Architecture (v0.2.4+)
```
Your Application
↓ (calls SDK)
@admesh/weave-node SDK
↓ (HTTP POST)
admesh-protocol /agent/recommend
↓ (checks database cache)
Database Cache Hit? → Return Cached Recommendations
↓ (cache miss)
Generate New Recommendations → Save to Database → Return
```
The SDK uses a **simplified database-backed architecture** (as of v0.2.4):
- **No Pub/Sub**: Direct HTTP calls to `/agent/recommend` endpoint
- **No SSE**: Synchronous request/response pattern
- **Database caching**: Recommendations are cached in Firestore with 60-second TTL
- **Fast cache hits**: Second call returns instantly from database (< 100ms)
- **Simple integration**: Single HTTP POST, no complex subscription management
## Installation
```bash
npm install @admesh/weave-node
```
## Quick Start
```typescript
import { AdMeshClient } from '@admesh/weave-node';
// Initialize the SDK with your API key
const client = new AdMeshClient({
apiKey: process.env.ADMESH_API_KEY
});
// Get recommendations for Weave
const result = await client.getRecommendationsForWeave({
sessionId: 'sess_123',
messageId: 'msg_1',
query: 'best laptops for programming',
timeoutMs: 30000
});
if (result.found) {
console.log('Recommendations:', result.recommendations);
console.log('Query:', result.query);
} else {
console.log('No recommendations found:', result.error);
}
```
## API Reference
### AdMeshClient
Main client for consuming recommendations from the AdMesh Protocol service.
#### Constructor
```typescript
const client = new AdMeshClient({
apiKey: string; // Required: Your AdMesh API key
});
```
All other settings (API endpoint, debug mode, timeouts) are configured internally for optimal performance.
#### Methods
##### `getRecommendationsForWeave(options)`
Get recommendations for Weave format from admesh-protocol. This method makes a direct HTTP POST to `/agent/recommend` which either returns cached recommendations from the database or generates new ones.
```typescript
const result = await client.getRecommendationsForWeave({
sessionId: string; // Required: Session ID
messageId: string; // Required: Message ID for this conversation message
query: string; // Required: User query for contextual recommendations
timeoutMs?: number; // Optional: Max wait time (default: 12000ms)
});
// Returns:
{
found: boolean; // Whether recommendations were found
recommendations?: WeaveRecommendation[]; // Array of recommendations
query?: string; // Original query
requestId?: string; // Request ID
error?: string; // Error message if not found
}
```
**Example:**
```typescript
const result = await client.getRecommendationsForWeave({
sessionId: 'sess_123',
messageId: 'msg_1',
query: 'best project management tools',
timeoutMs: 30000
});
if (result.found) {
console.log('Recommendations found:', result.recommendations);
console.log('Original query:', result.query);
// Use recommendations in your application
for (const rec of result.recommendations) {
console.log(`- ${rec.product_title}`);
console.log(` ${rec.weave_summary}`);
console.log(` Click: ${rec.click_url}`);
console.log(` Exposure: ${rec.exposure_url}`);
}
} else {
console.log('No recommendations available:', result.error);
}
```
## Configuration
### Environment Variables
```bash
# Required
ADMESH_API_KEY=your_api_key_here
# Optional - Enable debug logging in development
NODE_ENV=development
```
### Initialization
The AdMeshClient requires only your API key:
```typescript
const client = new AdMeshClient({
apiKey: process.env.ADMESH_API_KEY
});
```
### How It Works
- **API Endpoint:** Automatically configured to `https://api.useadmesh.com`
- **Debug Mode:** Automatically enabled when `NODE_ENV === 'development'`
- **Timeouts & Retries:** Configured internally with sensible defaults
## Integration Guide
### Step 1: Initialize the SDK
```typescript
import { AdMeshClient } from '@admesh/weave-node';
const client = new AdMeshClient({
apiKey: process.env.ADMESH_API_KEY
});
```
### Step 2: Get Recommendations for Weave
```typescript
async function handleUserQuery(sessionId, messageId, userQuery) {
// Get recommendations for Weave (direct HTTP call to /agent/recommend)
const result = await client.getRecommendationsForWeave({
sessionId,
messageId,
query: userQuery,
timeoutMs: 30000 // 30 second timeout for generation
});
if (result.found) {
// Recommendations available (either from cache or freshly generated)
console.log('Found', result.recommendations.length, 'recommendations');
return result.recommendations;
}
// No recommendations available
console.log('No recommendations:', result.error);
return null;
}
```
### Step 3: Use Recommendations
```typescript
const recommendations = await handleUserQuery(sessionId, messageId, query);
if (recommendations) {
// Use recommendations in your application
for (const rec of recommendations) {
console.log(`Product: ${rec.product_title}`);
console.log(`Summary: ${rec.weave_summary}`);
console.log(`Click URL: ${rec.click_url}`);
console.log(`Exposure URL: ${rec.exposure_url}`);
console.log(`Trust Score: ${rec.trust_score}`);
}
} else {
// Fallback behavior
console.log('No recommendations available');
}
```
## Performance
- **Cache Hit Latency**: < 100ms when recommendations are cached in database
- **Cache Miss Latency**: 1-3 seconds for fresh recommendation generation
- **Timeout**: Default 30 seconds, configurable per request
- **Database TTL**: Recommendations cached for 60 seconds
- **Fallback**: Graceful degradation if recommendations unavailable
- **Lightweight**: SDK is a thin HTTP client with minimal overhead
## Migration Guide (v0.2.7 → v0.3.0)
### What Changed
Version 0.3.0 introduces **finalized minimal schema** with updated field names and structure:
**Breaking Changes:**
- Response structure: `data.response.recommendations` → `data.recommendations`
- Field names: `product_description` → `weave_summary`, `intent_match_score` → `contextual_relevance_score`
- Removed fields: `admesh_link`, `product_description`, `product_url`, `cpx_value`, `meta`
- New fields: `recommendation_id`, `citation_summary`, `product_logo` (object), `categories`, `trust_score`, `model_used`
### Migration Steps
1. **Update the SDK:**
```bash
npm install @admesh/weave-node@^0.3.0
```
2. **Update your code:**
```typescript
// OLD (v0.2.7)
for (const rec of result.recommendations) {
console.log(rec.product_description); // ❌ No longer available
console.log(rec.admesh_link); // ❌ No longer available
}
// NEW (v0.3.0)
for (const rec of result.recommendations) {
console.log(rec.weave_summary); // ✅ Use this instead
console.log(rec.click_url); // ✅ Use this instead
}
```
3. **Update field access:**
- `product_description` → `weave_summary`
- `intent_match_score` → `contextual_relevance_score`
- `admesh_link` → `click_url` (for click tracking)
- `image_url` → `product_logo.url` (now an object)
### Backward Compatibility
The SDK maintains backward compatibility:
- `WeaveClient` is still exported as an alias to `AdMeshClient`
- Old code using `WeaveClient` will continue to work
- Type definitions have been updated to match the new schema
---
## Migration Guide (v0.2.3 → v0.2.4+)
### What Changed
Version 0.2.4 introduced a **simplified database-backed architecture** that removes Google Cloud Pub/Sub and SSE subscriptions:
**Before (v0.2.3):**
- Used Pub/Sub for real-time message delivery
- Required SSE subscription endpoint (`/weave/subscribe`)
- Complex race condition handling with delays and polling
- Required GCP credentials and Pub/Sub configuration
**After (v0.2.4+):**
- Direct HTTP POST to `/agent/recommend` endpoint
- Database-backed caching with 60-second TTL
- Simple request/response pattern
- No GCP Pub/Sub dependencies
### Breaking Changes
The following options have been **removed** from `getRecommendationsForWeave()`:
- `pollIntervalMs` - No longer needed (direct HTTP call, not polling)
- `delayMs` - No longer needed (no race condition with database-backed approach)
### Migration Steps
1. **Update the SDK:**
```bash
npm install @admesh/weave-node@^0.2.4
```
2. **Update your code:**
```typescript
// OLD (v0.2.3)
const result = await client.getRecommendationsForWeave({
sessionId,
messageId,
query,
timeoutMs: 10000,
pollIntervalMs: 100, // ❌ Remove this
delayMs: 500 // ❌ Remove this
});
// NEW (v0.2.4+)
const result = await client.getRecommendationsForWeave({
sessionId,
messageId,
query,
timeoutMs: 30000 // Increased default timeout
});
```
3. **Remove Pub/Sub environment variables** (no longer needed):
```bash
# ❌ Remove these from your .env file
GCP_PROJECT_ID=...
PUBSUB_TOPIC_RECOMMENDATIONS=...
PUBSUB_TOPIC_ACK=...
PUBSUB_SUBSCRIPTION_ID=...
```
4. **Keep these environment variables:**
```bash
# ✅ Still required
ADMESH_API_KEY=your_api_key_here
ADMESH_API_BASE_URL=http://localhost:8000
```
### Backward Compatibility
The SDK maintains backward compatibility:
- `WeaveClient` is still exported as an alias to `AdMeshClient`
- Old code using `WeaveClient` will continue to work
- The removed options (`pollIntervalMs`, `delayMs`) are simply ignored if provided
### Benefits of the New Architecture
✅ **Simpler**: No Pub/Sub setup, no SSE subscriptions, no race conditions
✅ **Faster**: Database cache hits return in < 100ms
✅ **More Reliable**: No message delivery issues, no subscription timeouts
✅ **Easier to Debug**: Simple HTTP request/response, standard error handling
✅ **Lower Latency**: Direct database lookup instead of Pub/Sub message routing
## Error Handling
```typescript
const result = await weave.getRecommendationsForWeave({
sessionId,
messageId,
timeoutMs: 10000
});
if (!result.found) {
console.error('Failed to retrieve recommendations:', result.error);
// Fallback behavior
return {
success: false,
recommendations: [],
error: result.error
};
}
// Use recommendations
return {
success: true,
recommendations: result.recommendations,
query: result.query
};
```
## Troubleshooting
### No recommendations found
**Possible causes:**
1. admesh-protocol is not running or not accessible
2. Query doesn't match any products in the database
3. Session ID or Message ID mismatch
4. Timeout too short for fresh generation
5. Invalid API key
**Solution:**
```typescript
// Debug mode is automatically enabled in development (NODE_ENV=development)
// Try with longer timeout
const result = await client.getRecommendationsForWeave({
sessionId,
messageId,
query: 'specific product query', // Provide a clear query
timeoutMs: 45000 // Increase timeout for generation
});
console.log('Found:', result.found);
console.log('Error:', result.error);
```
### Connection errors
**Possible causes:**
1. Network connectivity issues
2. Invalid API key
3. AdMesh API service is down
**Solution:**
```typescript
// Check API key format
console.log('API key starts with:', process.env.ADMESH_API_KEY?.substring(0, 10));
// Test the connection
try {
const result = await client.getRecommendationsForWeave({
sessionId: 'test',
messageId: 'test',
query: 'test query',
timeoutMs: 5000
});
console.log('Connection successful:', result.found);
} catch (error) {
console.error('Connection failed:', error.message);
}
```
### Slow response times
**Possible causes:**
1. First call (cache miss) - recommendations are being generated
2. Complex query requiring more processing
3. Database connection issues
**Solution:**
```typescript
// First call will be slower (1-3 seconds) - this is normal
const result1 = await client.getRecommendationsForWeave({
sessionId,
messageId,
query,
timeoutMs: 30000
});
console.log('First call (generation):', result1.found);
// Second call with same session_id + message_id should be fast (< 100ms)
const result2 = await client.getRecommendationsForWeave({
sessionId,
messageId,
query,
timeoutMs: 5000 // Can use shorter timeout for cached results
});
console.log('Second call (cache hit):', result2.found);
```
## Types
### AdMeshRecommendation
Individual recommendation object returned by the API.
```typescript
interface AdMeshRecommendation {
ad_id: string; // Unique ad identifier
product_id: string; // Product ID
recommendation_id: string; // Recommendation identifier
product_title: string; // Product name
citation_summary: string; // Citation text (moved from top-level)
weave_summary: string; // Weave format summary
exposure_url: string; // Exposure tracking URL
click_url: string; // Click tracking URL
product_logo: { url: string }; // Product logo object
categories: string[]; // Product categories
contextual_relevance_score: number; // Contextual relevance score (0-100)
trust_score: number; // Trust score
model_used: string; // Model used for generation
}
```
### AdMeshIntegrationResult
Result from `integrateRecommendations()` method.
```typescript
interface AdMeshIntegrationResult {
success: boolean; // Whether recommendations were found
recommendations: AdMeshRecommendation[]; // Array of recommendations
query: string; // Original query
weaveText: string; // Formatted recommendations for LLM
error?: string; // Error message if unsuccessful
}
```
### AdMeshWaitResult
Result from `getRecommendationsForWeave()` method.
```typescript
interface AdMeshWaitResult {
found: boolean; // Whether recommendations were found
recommendations?: AdMeshRecommendation[]; // Array of recommendations
query?: string; // Original query
requestId?: string; // Request ID
error?: string; // Error message if not found
}
```
### AdMeshClientConfig
Configuration for initializing the AdMeshClient.
```typescript
interface AdMeshClientConfig {
apiKey: string; // Required: Your AdMesh API key
}
```
**Note:** All other configuration (API endpoint, debug mode, timeouts) is handled internally.
## Architecture Details
### How It Works (v0.2.4+)
1. **@admesh/weave-node SDK** makes HTTP POST to `/agent/recommend` endpoint
2. **admesh-protocol** checks database cache for existing recommendations
3. **Cache Hit**: Returns cached recommendations immediately (< 100ms)
4. **Cache Miss**: Generates new recommendations, saves to database, returns (1-3s)
5. SDK returns recommendations in a format ready for LLM integration
### Data Flow
```
Your Application
↓
@admesh/weave-node SDK
↓ (HTTP POST)
admesh-protocol /agent/recommend
↓
Check Database Cache (session_id + message_id)
↓
Cache Hit? → Return Cached (< 100ms)
↓ (cache miss)
Generate Recommendations
↓
Save to Database (60s TTL)
↓
Return Recommendations
↓
SDK Formats for LLM
↓
Integrate into Prompt
↓
LLM Response with Weave Ads
```
### Database Caching
- **Collection**: `recommendations` in Firestore (reuses existing collection)
- **Query**: By `session_id` and `message_id` fields
- **Freshness Window**: 60 seconds (validated using `created_at` timestamp)
- **Cache Hit**: < 100ms response time (reconstructs response from individual documents)
- **Cache Miss**: 1-3 seconds for fresh generation
- **No TTL Required**: Application-level freshness validation, documents persist for billing/analytics
### Key Design Principles
- **Lightweight**: SDK is a thin HTTP client with minimal dependencies
- **Fast**: Database cache hits return in < 100ms
- **Simple**: Direct request/response pattern, no complex subscriptions
- **Reliable**: No message delivery issues, no race conditions
- **Graceful Fallback**: Works seamlessly even if recommendations aren't available
- **Configurable**: Timeout is customizable per request
- **Debug-friendly**: Optional debug logging for troubleshooting
## License
MIT