# Node.js SDK

Node.js SDK v2 for Owl Browser - AI-native browser automation with antidetect capabilities, TypeScript support, and flow execution.

## Package

`@olib-ai/owl-browser-sdk`

## Requirements

`Node.js 18+`

## License

`MIT`

## Installation

Install the SDK via npm, pnpm, or yarn.

```bash
npm install @olib-ai/owl-browser-sdk
```

## Quick Start

Get started with browser automation in seconds.

```typescript
import { OwlBrowser } from '@olib-ai/owl-browser-sdk';

const browser = new OwlBrowser({
  url: 'http://localhost:8080',
  token: 'your-secret-token',
  apiPrefix: ''  // Use '' for direct connection, '/api' for nginx proxy
});

await browser.connect();

// Create a context
const ctx = await browser.createContext();
const contextId = ctx.context_id;

// Navigate to a page
await browser.navigate({ context_id: contextId, url: 'https://example.com' });

// Click an element
await browser.click({ context_id: contextId, selector: 'button#submit' });

// Take a screenshot
const screenshot = await browser.screenshot({ context_id: contextId });

// Close the context
await browser.closeContext({ context_id: contextId });

await browser.close();
```

## Dynamic Methods

The SDK dynamically generates methods for all 144+ browser tools. Methods are available in both camelCase and snake_case.

```typescript
// These are equivalent
await browser.createContext();
await browser.create_context();

// Navigation
await browser.navigate({ context_id: ctx, url: 'https://example.com' });
await browser.reload({ context_id: ctx });
await browser.goBack({ context_id: ctx });

// Interaction
await browser.click({ context_id: ctx, selector: '#button' });
await browser.type({ context_id: ctx, selector: '#input', text: 'Hello' });

// AI-powered tools
await browser.queryPage({ context_id: ctx, question: 'What is the title?' });
await browser.solveCaptcha({ context_id: ctx });
```

## Flow Execution

Execute complex automation flows with variable resolution and expectations using the `FlowExecutor`.

### Running a Flow

```typescript
import { OwlBrowser, FlowExecutor } from '@olib-ai/owl-browser-sdk';

const browser = new OwlBrowser({ url: '...', token: '...' });
await browser.connect();

const ctx = await browser.createContext();
const executor = new FlowExecutor(browser, ctx.context_id);

// Load flow from JSON file
const flow = FlowExecutor.loadFlow('test-flows/navigation.json');
const result = await executor.execute(flow);

if (result.success) {
  console.log('Flow completed in', result.totalDurationMs, 'ms');
} else {
  console.error('Flow failed:', result.error);
}
```

### Flow JSON Format

```json
{
  "name": "Login Flow",
  "steps": [
    {
      "type": "browser_navigate",
      "url": "https://example.com/login"
    },
    {
      "type": "browser_type",
      "selector": "#email",
      "text": "user@example.com"
    },
    {
      "type": "browser_click",
      "selector": "#submit",
      "expected": {
        "notEmpty": true
      }
    }
  ]
}
```

## Configuration

Configuration options for the `OwlBrowser` client.

```typescript
interface RemoteConfig {
  // Required
  url: string;                    // Server URL

// Authentication
  token?: string;                 // Bearer token
  authMode?: AuthMode;            // 'token' or 'jwt'
  jwt?: JWTConfig;                // JWT configuration

// Optional
  transport?: TransportMode;      // 'http' or 'websocket'
  timeout?: number;               // Request timeout (default: 30s)
  maxConcurrent?: number;         // Max concurrent requests
  retry?: RetryConfig;            // Retry configuration
  verifySsl?: boolean;            // Verify SSL certificates
  apiPrefix?: string;             // API prefix (default: '/api')
}
```

## Error Handling

Handle specific errors like element not found, timeouts, or rate limits.

```typescript
import {
  OwlBrowserError,
  ElementNotFoundError,
  TimeoutError,
  AuthenticationError
} from '@olib-ai/owl-browser-sdk';

try {
  await browser.click({ context_id: ctx, selector: '#nonexistent' });
} catch (e) {
  if (e instanceof ElementNotFoundError) {
    console.log('Element not found:', e.selector);
  } else if (e instanceof TimeoutError) {
    console.log('Operation timed out');
  } else if (e instanceof AuthenticationError) {
    console.log('Auth failed:', e.message);
  }
}
```
