Skip to content

Browser Compatibility - Universal SDK

This document covers the complete browser compatibility implementation across all Robota SDK packages.

✅ Implementation Status

All Robota SDK packages have been fully updated to support browser environments with zero breaking changes to existing Node.js usage.

Supported Packages

  • @robota-sdk/agents - Core agent system
  • @robota-sdk/openai - OpenAI provider
  • @robota-sdk/anthropic - Anthropic provider
  • @robota-sdk/google - Google provider
  • @robota-sdk/sessions - Session management
  • @robota-sdk/team - Team collaboration
  • @robota-sdk/tools - Tool system
  • @robota-sdk/core - Core utilities

🏗️ Architecture: Interface-Based Dependency Injection

Problem Solved

The original PayloadLogger class used Node.js-specific fs and path modules, making it incompatible with browser environments.

Solution: Clean Separation of Concerns

Instead of environment detection and conditional imports, we implemented a clean interface-based dependency injection pattern:

typescript
// 1. Universal Interface (browser-compatible)
interface PayloadLogger {
  isEnabled(): boolean;
  logPayload(payload: OpenAILogData, type: 'chat' | 'stream'): Promise<void>;
}

// 2. Node.js Implementation
class FilePayloadLogger implements PayloadLogger {
  // Uses fs/path for file-based logging
}

// 3. Browser Implementation  
class ConsolePayloadLogger implements PayloadLogger {
  // Uses structured console logging
}

🎯 User Experience

Node.js Environment

typescript
import { OpenAIProvider } from '@robota-sdk/openai';
import { FilePayloadLogger } from '@robota-sdk/openai/loggers/file';

const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new FilePayloadLogger({ logDir: './logs/openai' })
});

Browser Environment

typescript
import { OpenAIProvider } from '@robota-sdk/openai';
import { ConsolePayloadLogger } from '@robota-sdk/openai/loggers/console';

const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new ConsolePayloadLogger()
});

No Logging (Both Environments)

typescript
const provider = new OpenAIProvider({
  client: openaiClient
  // payloadLogger: undefined (default)
});

📦 Bundle Optimization

Main Package (Browser Compatible)

  • ✅ Zero Node.js dependencies: No fs/path imports in main bundle
  • 📉 Reduced bundle size: 25% smaller (from 15.88KB to 12.17KB)
  • 🌐 Universal compatibility: Works in all JavaScript environments

Separate Implementation Files

  • @robota-sdk/openai/loggers/file: Node.js file-based logging
  • @robota-sdk/openai/loggers/console: Browser console-based logging
  • Tree-shaking friendly: Only imported implementations are bundled

🔧 Implementation Details

PayloadLogger Interface

typescript
export interface PayloadLogger {
  isEnabled(): boolean;
  logPayload(payload: OpenAILogData, type: 'chat' | 'stream'): Promise<void>;
}

FilePayloadLogger (Node.js)

typescript
export class FilePayloadLogger implements PayloadLogger {
  constructor(options: {
    logDir: string;
    enabled?: boolean;
    includeTimestamp?: boolean;
  }) {
    // Node.js fs-based implementation
  }
}

ConsolePayloadLogger (Browser)

typescript
export class ConsolePayloadLogger implements PayloadLogger {
  constructor(options: PayloadLoggerOptions = {}) {
    // Browser console-based implementation with structured logging
  }
}

🚫 Removed Features

Legacy Code Elimination

  • ❌ Legacy PayloadLogger class: Completely removed
  • ❌ Deprecated options: enablePayloadLogging, payloadLogDir, includeTimestampInLogFiles
  • ❌ Environment detection: No runtime environment checks
  • ❌ Conditional imports: No environment-based code branching

Robota SDK Architecture Compliance

Following the Robota SDK principle of "avoiding ambiguous features":

  • ✅ Explicit configuration: User explicitly chooses appropriate logger
  • ✅ Predictable behavior: No automatic environment detection
  • ✅ Clear error messages: Interface contract enforces proper usage
  • ✅ No policy decisions: Library doesn't make arbitrary choices

🧪 Testing & Validation

Browser Compatibility Verified

  • ✅ Main bundle: Zero Node.js dependencies
  • ✅ OpenAI SDK: Full browser support (v4+ fetch-based)
  • ✅ Streaming: Browser-compatible streaming implementation
  • ✅ Type safety: Full TypeScript support in all environments

Build System Integration

json
{
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./loggers/file": {
      "types": "./dist/loggers/file.d.ts",
      "import": "./dist/loggers/file.js",
      "require": "./dist/loggers/file.cjs"
    },
    "./loggers/console": {
      "types": "./dist/loggers/console.d.ts",
      "import": "./dist/loggers/console.js",
      "require": "./dist/loggers/console.cjs"
    }
  }
}

🎉 Benefits Achieved

1. Clean Architecture

  • Interface-based design promotes maintainability
  • Clear separation between interface and implementation
  • Zero coupling between environments

2. Performance Optimization

  • Smaller main bundle size (25% reduction)
  • Tree-shaking eliminates unused implementations
  • No runtime environment detection overhead

3. Developer Experience

  • Explicit logger selection improves clarity
  • Type-safe interfaces prevent configuration errors
  • Clear import paths indicate environment requirements

4. Future-Proof Design

  • Easy to add new logger implementations
  • Consistent patterns for other providers
  • Scalable architecture for complex logging needs

🔄 Migration Guide

For Existing Users (Zero Breaking Changes)

Existing Node.js code continues to work unchanged:

typescript
// ✅ This still works (automatic fallback to no logging)
const provider = new OpenAIProvider({
  client: openaiClient
});

For Advanced Users

Upgrade to explicit logger configuration:

typescript
// Node.js: Explicit file logging
import { FilePayloadLogger } from '@robota-sdk/openai/loggers/file';
const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new FilePayloadLogger({ logDir: './logs' })
});

// Browser: Explicit console logging  
import { ConsolePayloadLogger } from '@robota-sdk/openai/loggers/console';
const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new ConsolePayloadLogger()
});

@robota-sdk/anthropic

Anthropic provider is fully browser compatible with no Node.js dependencies:

typescript
import { Robota } from '@robota-sdk/agents';
import { AnthropicProvider } from '@robota-sdk/anthropic';
import Anthropic from '@anthropic-ai/sdk';

// Browser-compatible setup
const anthropicClient = new Anthropic({
  apiKey: 'your-api-key'
});

const provider = new AnthropicProvider({
  client: anthropicClient,
  model: 'claude-3-5-sonnet-20241022'
});

const agent = new Robota({
  aiProviders: [provider],
  defaultModel: {
    provider: 'anthropic',
    model: 'claude-3-5-sonnet-20241022'
  }
});

const response = await agent.run('Hello Claude!');
console.log(response);

@robota-sdk/google

Google provider is fully browser compatible with no Node.js dependencies:

typescript
import { Robota } from '@robota-sdk/agents';
import { GoogleProvider } from '@robota-sdk/google';

// Browser-compatible setup
const provider = new GoogleProvider({
  apiKey: 'your-google-api-key',
  model: 'gemini-1.5-flash'
});

const agent = new Robota({
  aiProviders: [provider],
  defaultModel: {
    provider: 'google',
    model: 'gemini-1.5-flash'
  }
});

const response = await agent.run('Hello Gemini!');
console.log(response);

🔧 Universal Logging System

Robota SDK implements a universal logging system that works consistently across all environments.

SimpleLogger Architecture

typescript
import { 
  SimpleLogger, 
  SilentLogger, 
  DefaultConsoleLogger, 
  StderrLogger 
} from '@robota-sdk/agents';

// Console-compatible interface
interface SimpleLogger {
  debug(...args: any[]): void;
  info(...args: any[]): void;
  warn(...args: any[]): void;
  error(...args: any[]): void;
  log(...args: any[]): void;
  group?(label?: string): void;
  groupEnd?(): void;
}

Environment-Specific Loggers

SilentLogger (Default)

typescript
// Perfect for production or resource-constrained environments
const provider = new OpenAIProvider({
  client: openaiClient
  // No logger = SilentLogger (no output)
});

DefaultConsoleLogger (Development)

typescript
import { ConsolePayloadLogger } from '@robota-sdk/openai/loggers/console';
import { DefaultConsoleLogger } from '@robota-sdk/agents';

const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new ConsolePayloadLogger({ 
    logger: DefaultConsoleLogger 
  })
});

StderrLogger (Special Environments)

typescript
import { StderrLogger } from '@robota-sdk/agents';

// For environments that only allow stderr output
const provider = new OpenAIProvider({
  client: openaiClient,
  payloadLogger: new ConsolePayloadLogger({ 
    logger: StderrLogger 
  })
});

Constructor Injection Pattern

All logging follows a clean dependency injection pattern:

typescript
// No global setters/getters
// Each component receives its logger via constructor
class StreamHandler {
  constructor(logger: SimpleLogger = SilentLogger) {
    this.logger = logger;
  }
}

🚀 Benefits

Zero Configuration

  • Default Silent Mode: No unwanted output in production
  • Explicit Logging: Only log when explicitly configured
  • Environment Agnostic: Same API works everywhere

Developer Experience

  • Console Compatible: Drop-in replacement for console.*
  • Type Safe: Full TypeScript support
  • Predictable: No environment-specific behavior surprises

Special Environment Support

  • Stderr-only environments: StderrLogger for constrained systems
  • Silent environments: SilentLogger prevents any output
  • Development environments: DefaultConsoleLogger for full debugging

Released under the MIT License.