{"_id":"@ai-universe/second-opinion-client","_rev":"5-ee0a16ff9fd78b80105d2b544f2a9e19","name":"@ai-universe/second-opinion-client","dist-tags":{"latest":"2.1.1"},"versions":{"1.0.0":{"name":"@ai-universe/second-opinion-client","version":"1.0.0","keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/second-opinion-client@1.0.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"9203f723963535140b47b23cb0b3792158a121d8","tarball":"https://registry.npmjs.org/@ai-universe/second-opinion-client/-/second-opinion-client-1.0.0.tgz","fileCount":40,"integrity":"sha512-lhYbpg22F8M6jjUWk0YOwlu5obQlerE9mKPExPKgwe1Ql7twDAekorytyu8/N39+N6XXYbTFSQMJOTz11RtPuA==","signatures":[{"sig":"MEQCICImfx7vFVkqknGO6wVTbmzptXJyjf2fvWMz6stTnnq7AiA5mrSSiTtxZQiNp3gOVzYHIWpKuVmToNRuJxqR/8hWeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":129767},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"scripts":{"lint":"eslint src/ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"TypeScript client library for AI Universe Second Opinion multi-model consultation API","directories":{},"_nodeVersion":"20.19.4","dependencies":{"firebase":"^10.7.1","node-fetch":"^3.3.2","@ai-universe/config-utils":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.1","typescript":"^5.3.3","@types/jest":"^29.5.8","@types/node":"^20.14.9","@jest/globals":"^29.7.0","@typescript-eslint/parser":"^6.12.0","@typescript-eslint/eslint-plugin":"^6.12.0"},"peerDependencies":{"@google-cloud/secret-manager":"^5.0.0"},"peerDependenciesMeta":{"@google-cloud/secret-manager":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/second-opinion-client_1.0.0_1762730675191_0.17933353419839193","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@ai-universe/second-opinion-client","version":"1.0.1","keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/second-opinion-client@1.0.1","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"100ebbec92fe0f241bc3bc0d49c99d97cf4df25b","tarball":"https://registry.npmjs.org/@ai-universe/second-opinion-client/-/second-opinion-client-1.0.1.tgz","fileCount":40,"integrity":"sha512-pzVsOulIDxdfvauNW5TZupbjchSMIc4FOi2w90cVorHAk9ouv3qv11EavKWzXRnKBzLOLTHPHDlDyEDXSlpIeA==","signatures":[{"sig":"MEQCICleN2roAnLXtDdVqOg4Jdqty+To5lOe1AhLqVpmS9cBAiBA0r6gf+1lDIPsOsywiKqnFfQUdGeepbLAif/7bJDKQA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":139051},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"scripts":{"lint":"eslint src/ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"TypeScript client library for AI Universe Second Opinion multi-model consultation API","directories":{},"_nodeVersion":"20.19.4","dependencies":{"firebase":"^10.9.0","node-fetch":"^3.3.2","@ai-universe/config-utils":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.1","typescript":"^5.3.3","@types/jest":"^29.5.8","@types/node":"^20.14.9","@jest/globals":"^29.7.0","@typescript-eslint/parser":"^6.12.0","@typescript-eslint/eslint-plugin":"^6.12.0"},"peerDependencies":{"@google-cloud/secret-manager":"^5.0.0"},"peerDependenciesMeta":{"@google-cloud/secret-manager":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/second-opinion-client_1.0.1_1763087622811_0.03978276014869775","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@ai-universe/second-opinion-client","version":"2.0.0","keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/second-opinion-client@2.0.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"21f1c1971007a159fd5a303652eb62e68d188dde","tarball":"https://registry.npmjs.org/@ai-universe/second-opinion-client/-/second-opinion-client-2.0.0.tgz","fileCount":40,"integrity":"sha512-2g3Sl7iQ6pBnnktuGDtyTBGA6qSI64XEwuum5UcgvVLIjM1PenN/YpG9buenCOZb+NoE99dVVVj4iqK3sa319g==","signatures":[{"sig":"MEUCIQDgwSHtLelK2OupRauvAwj3UD12aENhA1iLrxSf3opJuwIgZLU54Rl3gcUXqHkEgafWLYktPMg9ls4M+Fettm3JBsg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":145234},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"scripts":{"lint":"eslint src/ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"8.19.4","description":"TypeScript client library for AI Universe MCP Server - Complete MCP tool access including multi-model consultation and conversation management","directories":{},"_nodeVersion":"20.19.4","dependencies":{"firebase":"^10.9.0","node-fetch":"^3.3.2","@ai-universe/config-utils":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.1","typescript":"^5.3.3","@types/jest":"^29.5.8","@types/node":"^20.14.9","@jest/globals":"^29.7.0","@typescript-eslint/parser":"^6.12.0","@typescript-eslint/eslint-plugin":"^6.12.0"},"peerDependencies":{"@google-cloud/secret-manager":"^5.0.0"},"peerDependenciesMeta":{"@google-cloud/secret-manager":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/second-opinion-client_2.0.0_1763154334072_0.0072229033346888905","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@ai-universe/second-opinion-client","version":"2.1.0","keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","_id":"@ai-universe/second-opinion-client@2.1.0","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"dist":{"shasum":"bd5de24d73c918e5f3d5720f11854e0e446cb432","tarball":"https://registry.npmjs.org/@ai-universe/second-opinion-client/-/second-opinion-client-2.1.0.tgz","fileCount":40,"integrity":"sha512-Sr3EtIAzSaSUtNt0xxJiHotj2Y9EU8bMqAnIZEd89DaoaY26sWGck9nL/QTi/sNNhZkGy9Drzv3In5wV7EJaqg==","signatures":[{"sig":"MEYCIQCiGgtplOZLgrZLGak3r085gvYg6LFqQV1WX4an2/NvcgIhAJTxRJ0SgcHpre3XAB1jaxlQVLjW9Ue8E4BmvJqB5/aa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":146204},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"scripts":{"lint":"eslint src/ --ext .ts","test":"jest","build":"tsc","clean":"rm -rf dist","prepare":"node ../../scripts/run-build-if-ready.mjs"},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"_npmVersion":"11.5.1","description":"TypeScript client library for AI Universe MCP Server - Complete MCP tool access including multi-model consultation and conversation management","directories":{},"_nodeVersion":"24.6.0","dependencies":{"firebase":"^10.9.0","node-fetch":"^3.3.2","@ai-universe/config-utils":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.1","typescript":"^5.3.3","@types/jest":"^29.5.8","@types/node":"^20.14.9","@jest/globals":"^29.7.0","@typescript-eslint/parser":"^6.12.0","@typescript-eslint/eslint-plugin":"^6.12.0"},"peerDependencies":{"@google-cloud/secret-manager":"^5.0.0"},"peerDependenciesMeta":{"@google-cloud/secret-manager":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/second-opinion-client_2.1.0_1763754830157_0.25246954902691754","host":"s3://npm-registry-packages-npm-production"}},"2.1.1":{"name":"@ai-universe/second-opinion-client","version":"2.1.1","description":"TypeScript client library for AI Universe MCP Server - Complete MCP tool access including multi-model consultation and conversation management","type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./dist/*":"./dist/*","./package.json":"./package.json"},"scripts":{"build":"tsc","prepare":"node ../../scripts/run-build-if-ready.mjs","test":"jest","lint":"eslint src/ --ext .ts","clean":"rm -rf dist"},"dependencies":{"@ai-universe/config-utils":"^1.0.0","firebase":"^10.9.0","node-fetch":"^3.3.2"},"peerDependencies":{"@google-cloud/secret-manager":"^5.0.0"},"peerDependenciesMeta":{"@google-cloud/secret-manager":{"optional":true}},"devDependencies":{"typescript":"^5.3.3","jest":"^29.7.0","@jest/globals":"^29.7.0","@types/jest":"^29.5.8","ts-jest":"^29.1.1","eslint":"^8.57.0","@typescript-eslint/eslint-plugin":"^6.12.0","@typescript-eslint/parser":"^6.12.0","@types/node":"^20.14.9"},"keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"author":{"name":"AI Universe Team"},"license":"MIT","engines":{"node":">=18"},"publishConfig":{"access":"public"},"_id":"@ai-universe/second-opinion-client@2.1.1","_nodeVersion":"20.19.4","_npmVersion":"8.19.4","dist":{"integrity":"sha512-9IE+eTS0O7gVTbgZzCUxhCo9I5ZizRlnXkHrjaPCRFpgcYQ0GOKwUIY3xwULtSGocNJmoqW+pu2SnD7xom6EcA==","shasum":"3ded8147c693f40a24e5d9c849beb779bcf42263","tarball":"https://registry.npmjs.org/@ai-universe/second-opinion-client/-/second-opinion-client-2.1.1.tgz","fileCount":40,"unpackedSize":146204,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIC6cP6IPipJ2tQAexKocr3KVYuu1CNY/CjaKrVM1/V+gAiEA/V4/n6/y8wxsqY2mw1HEUKUcg2KcqGEQ0nyU0CkHTPk="}]},"_npmUser":{"name":"jleechan","email":"jleechan+npm@gmail.com"},"directories":{},"maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/second-opinion-client_2.1.1_1763755340270_0.6424602716934547"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-09T23:24:35.111Z","modified":"2025-11-21T20:02:20.742Z","1.0.0":"2025-11-09T23:24:35.404Z","1.0.1":"2025-11-14T02:33:43.004Z","2.0.0":"2025-11-14T21:05:34.244Z","2.1.0":"2025-11-21T19:53:50.399Z","2.1.1":"2025-11-21T20:02:20.487Z"},"author":{"name":"AI Universe Team"},"license":"MIT","keywords":["ai","second-opinion","multi-model","consultation","typescript","client","api","firebase","mcp","ai-universe"],"description":"TypeScript client library for AI Universe MCP Server - Complete MCP tool access including multi-model consultation and conversation management","maintainers":[{"name":"jleechan","email":"jleechan+npm@gmail.com"}],"readme":"# @ai-universe/second-opinion-client\n\nTypeScript/JavaScript client library for AI Universe MCP Server - Complete MCP tool access including multi-model consultation, conversation management, and authentication.\n\n## Features\n\n- 🤖 **Multi-Model Consultation** - Get opinions from Cerebras, Claude, Gemini, Perplexity, OpenAI, and Grok\n- 🔄 **Intelligent Synthesis** - AI-powered synthesis combining all model responses\n- 💬 **Full Conversation Management** - Send messages, list conversations, get history, delete conversations\n- 🔐 **Firebase Authentication** - Built-in authentication with Google sign-in\n- 📊 **Rate Limit Management** - Check and monitor your rate limits\n- 🏥 **Health Checks** - Server and conversation service health monitoring\n- 🛡️ **Type-Safe** - Full TypeScript support with comprehensive types\n- ⚡ **Flexible** - Works in Node.js, browsers, and edge runtimes\n- 🎯 **Simple API** - Intuitive interface with sensible defaults\n- 📋 **Complete MCP Access** - All backend MCP tools exposed via clean API\n\n## Installation\n\n```bash\nnpm install @ai-universe/second-opinion-client\n```\n\nor\n\n```bash\nyarn add @ai-universe/second-opinion-client\n```\n\nor\n\n```bash\npnpm add @ai-universe/second-opinion-client\n```\n\n## Quick Start\n\n### Basic Usage (Anonymous)\n\n```typescript\nimport { SecondOpinionClient } from '@ai-universe/second-opinion-client';\n\n// Create client\nconst client = new SecondOpinionClient();\n\n// Ask a question\nconst response = await client.ask('What is machine learning?');\n\n// Access primary model response\nconsole.log(response.primary.response);\n\n// Access secondary opinions\nresponse.secondaryOpinions?.forEach((opinion) => {\n  console.log(`${opinion.modelDisplayName}: ${opinion.response}`);\n});\n\n// Access multi-model synthesis\nconsole.log(response.synthesis?.response);\n```\n\n### Authenticated Usage (Higher Rate Limits)\n\n```typescript\nimport { SecondOpinionClient } from '@ai-universe/second-opinion-client';\n\n// Create client with Firebase config (example uses AI Universe production config)\nconst client = new SecondOpinionClient({\n  firebaseConfig: {\n    apiKey: 'AIzaSyDWT4aEG2UoKEtTxozniGC6uPZi1fgjtG8',\n    authDomain: 'ai-universe-b3551.firebaseapp.com',\n    projectId: 'ai-universe-b3551',\n  },\n});\n\n// Sign in with Google\nawait client.signInWithGoogle();\n\n// Now make requests with higher rate limits\nconst response = await client.ask('What is deep learning?');\n```\n\n### Follow-up Questions (Conversation Threading)\n\n```typescript\n// First question\nconst response1 = await client.ask('What is quantum computing?');\n\n// Follow-up question in same conversation\nconst response2 = await client.ask({\n  question: 'How does it differ from classical computing?',\n  conversationId: response1.conversationId,\n});\n\n// Get conversation history\nconst history = await client.getConversationHistory(response1.conversationId);\n```\n\n## API Reference\n\n### Constructor\n\n```typescript\nnew SecondOpinionClient(config?: SecondOpinionClientConfig)\n```\n\n#### Configuration Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `baseUrl` | `string` | `https://ai-universe-backend-final.onrender.com` | Base URL of the AI Universe backend |\n| `firebaseConfig` | `object` | `undefined` | Firebase configuration for authentication |\n| `timeout` | `number` | `120000` (2 minutes) | Request timeout in milliseconds |\n| `headers` | `object` | `{}` | Custom headers to include in all requests |\n| `debug` | `boolean` | `false` | Enable debug logging |\n\n### Methods\n\n#### `ask(questionOrOptions)`\n\nAsk a question and get multi-model second opinions.\n\n**Parameters:**\n\n- `questionOrOptions`: `string | SecondOpinionRequestOptions`\n\n**Simple Usage:**\n\n```typescript\nconst response = await client.ask('What is AI?');\n```\n\n**Advanced Usage:**\n\n```typescript\nconst response = await client.ask({\n  question: 'What is neural network architecture?',\n  primaryModel: 'claude',              // Choose primary model\n  secondaryModels: ['gemini', 'grok'], // Choose secondary models\n  maxOpinions: 2,                      // Number of secondary opinions (0-10)\n  conversationId: 'abc123',            // For follow-up questions\n  userId: 'user-123',                  // Optional user ID\n});\n```\n\n**Request Options:**\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `question` | `string` | *required* | The question to ask (max 320,000 chars) |\n| `primaryModel` | `PrimaryModelName` | `'cerebras'` | Primary model to use |\n| `secondaryModels` | `SecondaryModelName[]` | Auto-selected | Secondary models to consult |\n| `maxOpinions` | `number` | `4` | Number of secondary opinions (0-10) |\n| `conversationId` | `string` | Auto-generated | Conversation ID for follow-ups |\n| `userId` | `string` | Auto-generated | User ID for tracking |\n| `sessionId` | `string` | `undefined` | Session ID for grouping |\n\n**Available Models:**\n\n- **Primary Models**: `cerebras`, `grok`, `claude`, `gemini`, `perplexity`, `openai`\n- **Secondary Models**: `gemini`, `perplexity`, `openai`, `grok`, `cerebras`\n\n**Response:**\n\n```typescript\ninterface SecondOpinionResponse {\n  // Core response data\n  primary: ModelOpinion;\n  secondaryOpinions?: ModelOpinion[];\n  synthesis: Synthesis | null;\n\n  // Conversation tracking\n  conversationId: string;\n  conversationCreated?: boolean;\n  conversationTitle?: string | null;\n\n  // Summary statistics\n  summary?: {\n    totalModels: number;\n    totalTokens: number;\n    totalCost: number;\n    totalLatencyMs: number;\n  };\n\n  // Latency breakdown\n  latency?: {\n    totalMs: number;\n    primary?: number;\n    secondary?: number;\n    synthesis?: number;\n  };\n\n  // Additional metadata\n  metadata?: object;\n  persistenceStatus?: object;\n  thinkingLog?: Array<object>;\n}\n```\n\n**Model Opinion Structure:**\n\n```typescript\ninterface ModelOpinion {\n  model: string;                    // Model name\n  modelDisplayName?: string;        // Human-readable name\n  response: string;                 // Model's response\n  tokensUsed?: number;             // Tokens consumed\n  latencyMs?: number;              // Response time\n  cost?: number;                   // API cost\n  citations?: CitationSource[];    // Search citations (Perplexity)\n  error?: boolean;                 // Error flag\n}\n```\n\n#### Authentication Methods\n\n##### `signInWithGoogle()`\n\nSign in with Google using Firebase Authentication.\n\n```typescript\nconst authState = await client.signInWithGoogle();\nconsole.log('User:', authState.user?.displayName);\n```\n\n##### `signOut()`\n\nSign out the current user.\n\n```typescript\nawait client.signOut();\n```\n\n##### `getAuthState()`\n\nGet current authentication state.\n\n```typescript\nconst authState = await client.getAuthState();\nif (authState.isAuthenticated) {\n  console.log('User:', authState.user?.email);\n  console.log('Token expires:', new Date(authState.expiresAt!));\n}\n```\n\n##### `isAuthenticated()`\n\nCheck if user is currently authenticated.\n\n```typescript\nif (client.isAuthenticated()) {\n  console.log('User is signed in');\n}\n```\n\n##### `onAuthStateChange(callback)`\n\nListen to authentication state changes.\n\n```typescript\nconst unsubscribe = client.onAuthStateChange((state) => {\n  console.log('Auth state changed:', state.isAuthenticated);\n});\n\n// Later, stop listening\nunsubscribe();\n```\n\n#### Conversation Methods\n\n##### `getConversationHistory(conversationId)`\n\nGet all messages in a conversation.\n\n```typescript\nconst history = await client.getConversationHistory('conversation-id');\nhistory.forEach((message) => {\n  console.log(`${message.role}: ${message.content}`);\n});\n```\n\n##### `listConversations(userId?)`\n\nList user's conversations.\n\n```typescript\nconst conversations = await client.listConversations();\nconversations.forEach((conv) => {\n  console.log(`${conv.title} - ${conv.messageCount} messages`);\n});\n```\n\n##### `sendMessage(options)`\n\nSend a message to a conversation.\n\n```typescript\nconst response = await client.sendMessage({\n  content: 'Hello, world!',\n  conversationId: 'conv-123', // Optional, auto-creates if omitted\n  role: 'user', // Optional, defaults to 'user'\n  title: 'My Conversation', // Optional\n  metadata: { source: 'web' }, // Optional\n});\n\nconsole.log('Message ID:', response.message.id);\nconsole.log('Assistant reply:', response.assistantMessage?.content);\n```\n\n##### `deleteConversation(conversationId, userId)`\n\nDelete a conversation.\n\n```typescript\nawait client.deleteConversation('conversation-id', 'user-id');\n```\n\n##### `conversationHealth()`\n\nCheck conversation service health.\n\n```typescript\nconst health = await client.conversationHealth();\nconsole.log('Status:', health.status); // 'healthy' or 'unhealthy'\n```\n\n#### Authentication & Rate Limiting\n\n##### `getFirebaseInfo()`\n\nGet Firebase authentication setup instructions.\n\n```typescript\nconst info = await client.getFirebaseInfo();\nconsole.log('Instructions:', info.instructions);\nconsole.log('Config:', info.config);\n```\n\n##### `getRateLimitStatus()`\n\nGet current rate limit status (requires authentication).\n\n```typescript\n// Must be authenticated first\nawait client.signInWithGoogle();\n\nconst status = await client.getRateLimitStatus();\nconsole.log('Limit:', status.limit);\nconsole.log('Remaining:', status.remaining);\nconsole.log('Resets at:', new Date(status.resetTime));\n```\n\n#### Server Health\n\n##### `getServerHealth()`\n\nGet MCP server health status (includes all tools).\n\n```typescript\nconst health = await client.getServerHealth();\nconsole.log('Server status:', health.status);\nconsole.log('Version:', health.version);\nconsole.log('Services:', health.services);\n```\n\n##### `checkHealth()`\n\nCheck HTTP server health (simple health check endpoint).\n\n```typescript\nconst health = await client.checkHealth();\nconsole.log('Status:', health.status); // 'healthy' or 'unhealthy'\n```\n\n## Usage Examples\n\n### Example 1: Simple Question\n\n```typescript\nconst client = new SecondOpinionClient();\nconst response = await client.ask('What is machine learning?');\n\nconsole.log('Primary:', response.primary.response);\nconsole.log('Synthesis:', response.synthesis?.response);\n```\n\n### Example 2: Custom Model Selection\n\n```typescript\nconst response = await client.ask({\n  question: 'What are the latest AI trends?',\n  primaryModel: 'perplexity',  // Good for recent info\n  secondaryModels: ['claude', 'gemini'],\n  maxOpinions: 2,\n});\n```\n\n### Example 3: Primary-Only Mode (No Synthesis)\n\n```typescript\nconst response = await client.ask({\n  question: 'Quick factual question',\n  maxOpinions: 0,  // Skip secondary opinions and synthesis\n});\n// Only response.primary will be populated\n```\n\n### Example 4: Multi-Turn Conversation\n\n```typescript\n// Start conversation\nconst r1 = await client.ask('What is blockchain?');\n\n// Follow-up questions\nconst r2 = await client.ask({\n  question: 'How does it ensure security?',\n  conversationId: r1.conversationId,\n});\n\nconst r3 = await client.ask({\n  question: 'What are practical applications?',\n  conversationId: r1.conversationId,\n});\n\n// Get full history\nconst history = await client.getConversationHistory(r1.conversationId);\n```\n\n### Example 5: Error Handling\n\n```typescript\nimport {\n  SecondOpinionClient,\n  ValidationError,\n  RateLimitError,\n  NetworkError,\n  TimeoutError,\n} from '@ai-universe/second-opinion-client';\n\nconst client = new SecondOpinionClient();\n\ntry {\n  const response = await client.ask('What is AI?');\n} catch (error) {\n  if (error instanceof ValidationError) {\n    console.error('Invalid request:', error.message);\n  } else if (error instanceof RateLimitError) {\n    console.error('Rate limit exceeded. Retry after:', error.retryAfter);\n  } else if (error instanceof NetworkError) {\n    console.error('Network error:', error.message);\n  } else if (error instanceof TimeoutError) {\n    console.error('Request timed out');\n  } else {\n    console.error('Unknown error:', error);\n  }\n}\n```\n\n### Example 6: Custom Configuration\n\n```typescript\nconst client = new SecondOpinionClient({\n  baseUrl: 'http://localhost:2000',  // Local development\n  timeout: 60000,                     // 1 minute timeout\n  debug: true,                        // Enable debug logs\n  headers: {\n    'X-Custom-Header': 'value',\n  },\n});\n```\n\n### Example 7: Accessing Citations (Perplexity)\n\n```typescript\nconst response = await client.ask({\n  question: 'What are recent breakthroughs in AI?',\n  primaryModel: 'perplexity',  // Includes citations\n});\n\nresponse.primary.citations?.forEach((citation) => {\n  console.log(`${citation.title}: ${citation.url}`);\n});\n```\n\n## Rate Limits\n\n| User Type | Rate Limit |\n|-----------|------------|\n| Anonymous | 10 requests / 5 minutes |\n| Authenticated | 50 requests / 5 minutes |\n| Admin | 1000 requests / 5 minutes |\n\n**Recommendation:** Use authentication for production applications to get higher rate limits.\n\n## Error Types\n\n| Error Class | Description |\n|-------------|-------------|\n| `ValidationError` | Request validation failed (empty question, invalid params, etc.) |\n| `RateLimitError` | Rate limit exceeded (includes `retryAfter` in seconds) |\n| `AuthenticationError` | Firebase authentication failed |\n| `NetworkError` | Network request failed |\n| `TimeoutError` | Request exceeded timeout limit |\n| `ApiError` | API returned error response (includes status code) |\n| `SecondOpinionClientError` | Base error class for all client errors |\n\n## TypeScript Support\n\nThis library is written in TypeScript and provides full type definitions.\n\n```typescript\nimport type {\n  SecondOpinionResponse,\n  ModelOpinion,\n  Synthesis,\n  CitationSource,\n  AuthState,\n  Conversation,\n} from '@ai-universe/second-opinion-client';\n```\n\n## Browser Support\n\nThis library works in modern browsers with ES2020+ support. For older browsers, use a transpiler like Babel.\n\n**Note:** Firebase Authentication requires browser environment for Google sign-in popup.\n\n## Node.js Support\n\nRequires Node.js 18 or later.\n\n**Note:** Firebase Authentication in Node.js requires additional setup for OAuth flow. Consider using the CLI authentication tool from the main AI Universe repository for server-side usage.\n\n## Environment Variables (Optional)\n\nFor authenticated usage examples:\n\n```bash\nexport AI_UNIVERSE_FIREBASE_API_KEY=\"your-api-key\"\nexport AI_UNIVERSE_FIREBASE_AUTH_DOMAIN=\"your-auth-domain\"\nexport AI_UNIVERSE_FIREBASE_PROJECT_ID=\"your-project-id\"\n```\n\n## Development\n\n### Build\n\n```bash\nnpm run build\n```\n\n### Test\n\n```bash\nnpm test\n```\n\n### Lint\n\n```bash\nnpm run lint\n```\n\n### Clean\n\n```bash\nnpm run clean\n```\n\n## Examples\n\nSee the `examples/` directory for complete working examples:\n\n- `basic-usage.ts` - Anonymous usage examples\n- `authenticated-usage.ts` - Firebase authentication examples\n\n## License\n\nMIT\n\n## Support\n\nFor issues and questions:\n- GitHub Issues: [https://github.com/your-org/ai-universe](https://github.com/your-org/ai-universe)\n- Documentation: [https://docs.ai-universe.dev](https://docs.ai-universe.dev)\n\n## Credits\n\nBuilt by the AI Universe Team with ❤️\n","readmeFilename":"README.md"}