# LupisLabs Labs JavaScript SDK

Instrument any Node, Next.js, or edge worker to stream traces to LupisLabs—no separate auth step required.

## Installation

```bash
npm install lupislabs
# or
yarn add lupislabs
```

### Development-only install

If you only need LupisLabs for local debugging, install it as a dev dependency:

```bash
npm install --save-dev lupislabs
```

When the SDK is not explicitly enabled it stays idle, so keeping it in `devDependencies` will not impact your production runtime.

## Features

- 🔍 **Automatic HTTP Tracing**: Captures AI API calls automatically
- 💬 **Session Support**: Group traces by conversation/session
- 🎯 **TypeScript Support**: Full TypeScript definitions included
- 🔒 **Privacy-First**: Never collects request/response bodies, only analytics data

## Quick Start

### 1. Initialize a shared client

Create one `LupisLabs` instance when your app boots and import it wherever you need tracing:

```typescript
// lib/lupis.ts
import { LupisLabs } from 'lupislabs';

export const lupis = new LupisLabs({ projectId: 'local-dev' });
```

### 2. Use in your handlers

Use that client inside any handler or server action:

```typescript
// routes/chat.ts
import { lupis } from '../lib/lupis';

export async function POST(req: Request) {
  const body = await req.json();
  
  lupis.setChatId('chat-response');
  lupis.setMetadata({ prompt: body.prompt });
  
  const output = await agent.run(body.prompt);

  return Response.json({ output });
}
```

### 3. Open the desktop app

Launch the LupisLabs desktop app, open **Session Monitor**, and leave it running. The SDK streams traces directly to the app as soon as your server code executes.

### 4. Run your agent and watch traces

1. Start your dev server (`npm run dev`, `next dev`, `node server.js`, etc.).
2. Trigger a request.
3. The Session Monitor shows prompts, outputs, latency, token usage, and tool fan-out in real time.

## Advanced Configuration

The SDK automatically connects to the LupisLabs desktop app at `http://127.0.0.1:9009`. For advanced use cases, you can customize the configuration:

```typescript
import { LupisLabs } from 'lupislabs';

const lupis = new LupisLabs({
  projectId: 'local-dev',            // Required: project identifier
  enabled: true,                      // Optional: enable/disable tracking
  serviceName: 'my-service',          // Optional: service name for traces
  serviceVersion: '1.0.0',           // Optional: service version
  filterSensitiveData: true,         // Optional: enable sensitive data filtering
  sensitiveDataPatterns: [...],      // Optional: custom regex patterns to filter
  redactionMode: 'mask',             // Optional: 'mask', 'remove', or 'hash'
});
```

### Enabling/Disabling the SDK

The SDK is **disabled by default** for security. Enable it via environment variable:

```bash
# Enable the SDK
export LUPIS_SDK_ENABLED=true

# Or in your .env file
LUPIS_SDK_ENABLED=true
```

Or programmatically:

```typescript
import { LupisLabs } from 'lupislabs';

const lupis = new LupisLabs({
  projectId: 'local-dev',
  enabled: true,  // SDK will start collecting data
});
```

When disabled, the SDK will not instrument HTTP clients, collect traces, or send data to the collector.

## Data Collection

The SDK collects only analytics-focused data while protecting sensitive information:

### ✅ **Collected Data**

- **HTTP Metadata**: URL, method, status code, duration, headers (filtered)
- **Token Usage**: Input/output/cache tokens from AI providers
- **Cost Analytics**: Calculated costs based on token usage and provider pricing
- **Model Information**: AI model used for requests
- **User Context**: User ID, organization ID, session ID, chat ID
- **Performance Metrics**: Response times, error rates, success/failure status

### ❌ **Never Collected**

- **Request Bodies**: Full request payloads are never captured
- **Response Bodies**: Full response content is never captured
- **Sensitive Data**: API keys, tokens, passwords (filtered by default)
- **Personal Information**: PII is not collected by default

### 🔒 **Privacy Protection**

- Sensitive data filtering enabled by default
- Request/response bodies skipped to reduce span size
- Focus on analytics and cost tracking only
- User-controlled data collection

## Sensitive Data Filtering

The SDK automatically filters sensitive data in production to protect API keys, tokens, and other sensitive information. This feature is **enabled by default** for security.

### Default Filtering

The SDK automatically filters these common sensitive patterns:

#### API Keys & Tokens

- `sk-[a-zA-Z0-9]{20,}` - OpenAI API keys
- `pk_[a-zA-Z0-9]{20,}` - Paddle API keys  
- `ak-[a-zA-Z0-9]{20,}` - Anthropic API keys
- `Bearer [a-zA-Z0-9._-]+` - Bearer tokens
- `x-api-key`, `authorization` - API key headers

#### Authentication

- `password`, `passwd`, `pwd` - Password fields
- `token`, `access_token`, `refresh_token`, `session_token` - Various tokens
- `secret`, `private_key`, `api_secret` - Secret fields

#### Personal Data

- `ssn`, `social_security` - Social Security Numbers
- `credit_card`, `card_number` - Credit card numbers
- `cvv`, `cvc` - Security codes

### Redaction Modes

Choose how sensitive data is replaced when you initialize the SDK:

#### Mask Mode (Default)

```javascript
const lupis = new LupisLabs({
  projectId: 'your-project-id',
  redactionMode: 'mask', // Default
});

// Examples:
// sk-1234567890abcdef1234567890abcdef12345678 → sk-1***5678
// Bearer sk-1234567890abcdef1234567890abcdef12345678 → Bear***5678
// password: 'secret-password' → password: '***'
```

#### Remove Mode

```javascript
const lupis = new LupisLabs({
  projectId: 'your-project-id',
  redactionMode: 'remove',
});

// Examples:
// sk-1234567890abcdef1234567890abcdef12345678 → [REDACTED]
// password: 'secret-password' → password: [REDACTED]
```

#### Hash Mode

```javascript
const lupis = new LupisLabs({
  projectId: 'your-project-id',
  redactionMode: 'hash',
});

// Examples:
// sk-1234567890abcdef1234567890abcdef12345678 → [HASH:2dd0e9d5]
// password: 'secret-password' → password: [HASHED]
```

### Custom Patterns

Add your own sensitive data patterns during initialization:

```javascript
const lupis = new LupisLabs({
  projectId: 'your-project-id',
  filterSensitiveData: true,
  sensitiveDataPatterns: [
    'sk-[a-zA-Z0-9]{20,}', // OpenAI API keys
    'Bearer [a-zA-Z0-9._-]+', // Bearer tokens
    'custom_secret', // Your custom field
    'my_api_key', // Your custom field
    'email', // Email addresses
  ],
  redactionMode: 'mask',
});
```

### What Gets Filtered

The SDK filters sensitive data in:

- **Request Headers**: Authorization, API keys, tokens

**Note**: Request and response bodies are never collected, so no filtering is needed for them.

### Disable Filtering (Development Only)

⚠️ **Warning**: Only disable filtering in development environments:

```javascript
const lupis = new LupisLabs({
  projectId: 'your-project-id',
  filterSensitiveData: false, // ⚠️ Sensitive data will be exposed!
});
```

### Production Security

- ✅ **Enabled by default** - No configuration needed
- ✅ **Comprehensive coverage** - Common sensitive patterns included
- ✅ **Configurable** - Add custom patterns as needed
- ✅ **Performance optimized** - Minimal impact when enabled
- ✅ **Debugging friendly** - Mask mode preserves partial data for debugging

### Test Coverage

- ✅ **Unit Tests**: Filter utility with all redaction modes
- ✅ **Integration Tests**: SDK with HTTP interception
- ✅ **Custom Patterns**: User-defined sensitive data patterns
- ✅ **Disabled Filtering**: Development mode verification
- ✅ **Request/Response**: Headers, bodies, and span attributes

## Examples

See the `examples/` directory for more usage examples:

- `event-tracking-example.js` - Custom event tracking
- `anthropic-example.js` - Anthropic API integration
- `openai-example.js` - OpenAI API integration
- `langchain-example.js` - LangChain integration
- `streaming-example.js` - Streaming responses

## License

Made with ❤️ by the LupisLabs team
