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:
// 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
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
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)
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
export interface PayloadLogger {
isEnabled(): boolean;
logPayload(payload: OpenAILogData, type: 'chat' | 'stream'): Promise<void>;
}
FilePayloadLogger (Node.js)
export class FilePayloadLogger implements PayloadLogger {
constructor(options: {
logDir: string;
enabled?: boolean;
includeTimestamp?: boolean;
}) {
// Node.js fs-based implementation
}
}
ConsolePayloadLogger (Browser)
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
{
"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:
// ✅ This still works (automatic fallback to no logging)
const provider = new OpenAIProvider({
client: openaiClient
});
For Advanced Users
Upgrade to explicit logger configuration:
// 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:
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:
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
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)
// Perfect for production or resource-constrained environments
const provider = new OpenAIProvider({
client: openaiClient
// No logger = SilentLogger (no output)
});
DefaultConsoleLogger (Development)
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)
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:
// 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