Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ PAYPAL_CLIENT_SECRET=your_paypal_client_secret_here
# AI & ML SERVICES
# ============================================================================

# Multi-Model Toolkit Configuration
# Set to FALSE to use single-model mode (works with just one API key)
USE_MULTI_MODEL=TRUE

# OpenAI - GPT models and embeddings
# Get from: https://platform.openai.com/api-keys
OPENAI_API_KEY=sk-your_openai_api_key_here
Expand All @@ -109,6 +113,10 @@ OPENAI_ORG_ID=org-your_org_id_here
# Get from: https://console.anthropic.com/settings/keys
ANTHROPIC_API_KEY=sk-ant-your_anthropic_api_key_here

# Google Gemini - Gemini models
# Get from: https://aistudio.google.com/app/apikey
GEMINI_API_KEY=your_gemini_api_key_here

# ============================================================================
# CONTENT & MEDIA
# ============================================================================
Expand Down
44 changes: 44 additions & 0 deletions tools/multi-model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
keywords
- **💰 Cost Optimization** - Use cheap models for simple tasks, reserve power
for complex ones
- **🔧 Flexible Configuration** - Works with just one API key or all three

## File Structure

Expand Down Expand Up @@ -51,6 +52,49 @@ ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=...
```

## Configuration

### Single-Model vs Multi-Model Mode

The toolkit automatically adapts based on your available API keys:

| API Keys Available | Mode | Behavior |
| ------------------ | ------------ | ---------------------------------- |
| All three | Multi-model | Consensus review across all models |
| Two keys | Multi-model | Consensus with 2 models |
| One key | Single-model | Direct review with one model |

**To explicitly disable multi-model mode** (even if you have multiple keys):

```bash
# In your .env file
USE_MULTI_MODEL=FALSE
```

This is useful for:

- Reducing API costs
- Faster reviews (single API call)
- Testing with a specific model

### Minimum Requirements

You only need **one API key** to use this toolkit:

```bash
# Option 1: OpenAI only
OPENAI_API_KEY=sk-...

# Option 2: Anthropic/Claude only
ANTHROPIC_API_KEY=sk-ant-...

# Option 3: Gemini only
GEMINI_API_KEY=...
```

The toolkit will automatically use the best available model for your
configuration.

## CLI Tools

### Multi-Model Code Review
Expand Down
22 changes: 19 additions & 3 deletions tools/multi-model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* - Anthropic (Claude 3 Opus, Sonnet, Haiku)
* - Google (Gemini Pro, Flash)
*
* Supports single-model mode when USE_MULTI_MODEL=FALSE or only one API key is available.
*
* @example
* import { reviewCode, createRouter, searchCodebase } from '@claude-sidekick/multi-model';
*
* // Multi-model code review
* // Multi-model code review (auto-adapts to available API keys)
* const results = await reviewCode(code, { filename: 'app.js' });
*
* // Intelligent routing
Expand All @@ -20,7 +22,7 @@
* const matches = await searchCodebase('authentication logic');
*/

// Clients
// Clients & Configuration
export {
complete,
embed,
Expand All @@ -30,10 +32,24 @@ export {
getGemini,
MODELS,
MODEL_COSTS,
// Configuration helpers
isMultiModelEnabled,
getAvailableProviders,
getAvailableModels,
getDefaultModel,
getBestModel,
hasProvider,
filterAvailableModels,
} from './lib/clients.js';

// Code Review
export { reviewCode, quickReview, deepReview, formatReviewResults } from './lib/code-review.js';
export {
reviewCode,
quickReview,
deepReview,
singleReview,
formatReviewResults,
} from './lib/code-review.js';

// Model Router
export {
Expand Down
100 changes: 100 additions & 0 deletions tools/multi-model/lib/clients.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Multi-Model AI Clients
* Unified interface for OpenAI, Anthropic, and Google Gemini
*
* Supports single-model mode when USE_MULTI_MODEL=FALSE or only one API key is available
*/

import OpenAI from 'openai';
Expand All @@ -15,6 +17,46 @@ let openaiClient = null;
let anthropicClient = null;
let geminiClient = null;

/**
* Check if multi-model mode is enabled
*/
export function isMultiModelEnabled() {
const setting = process.env.USE_MULTI_MODEL?.toUpperCase();
// Default to TRUE if not set, FALSE only if explicitly disabled
return setting !== 'FALSE' && setting !== '0' && setting !== 'NO';
}

/**
* Check which API keys are available
*/
export function getAvailableProviders() {
const providers = [];
if (process.env.OPENAI_API_KEY) providers.push('openai');
if (process.env.ANTHROPIC_API_KEY) providers.push('anthropic');
if (process.env.GEMINI_API_KEY || process.env.GEMENI_API_KEY) providers.push('gemini');
return providers;
}

/**
* Check if a specific provider is available
*/
export function hasProvider(provider) {
return getAvailableProviders().includes(provider);
}

/**
* Get the primary (first available) provider
*/
export function getPrimaryProvider() {
const providers = getAvailableProviders();
if (providers.length === 0) {
throw new Error(
'No API keys configured. Set at least one of: OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY'
);
}
return providers[0];
}

export function getOpenAI() {
if (!openaiClient) {
if (!process.env.OPENAI_API_KEY) {
Expand Down Expand Up @@ -158,3 +200,61 @@ export const MODEL_COSTS = {
'gemini-1.5-pro': [3.5, 10.5],
'gemini-2.0-flash': [0.075, 0.3],
};

/**
* Get provider from model name
*/
export function getProviderFromModel(model) {
if (model.startsWith('gpt-')) return 'openai';
if (model.startsWith('claude-')) return 'anthropic';
if (model.startsWith('gemini-')) return 'gemini';
return null;
}

/**
* Get available models based on configured API keys
*/
export function getAvailableModels() {
const models = [];
if (hasProvider('openai')) {
models.push(MODELS.GPT4O, MODELS.GPT4O_MINI);
}
if (hasProvider('anthropic')) {
models.push(MODELS.CLAUDE_SONNET, MODELS.CLAUDE_HAIKU);
}
if (hasProvider('gemini')) {
models.push(MODELS.GEMINI_PRO, MODELS.GEMINI_FLASH);
}
return models;
}

/**
* Get the default model (cheapest available fast model)
*/
export function getDefaultModel() {
// Prefer cheaper/faster models as default
if (hasProvider('gemini')) return MODELS.GEMINI_FLASH;
if (hasProvider('openai')) return MODELS.GPT4O_MINI;
if (hasProvider('anthropic')) return MODELS.CLAUDE_HAIKU;
throw new Error('No API keys configured');
}

/**
* Get the best available model for quality
*/
export function getBestModel() {
if (hasProvider('anthropic')) return MODELS.CLAUDE_SONNET;
if (hasProvider('openai')) return MODELS.GPT4O;
if (hasProvider('gemini')) return MODELS.GEMINI_PRO;
throw new Error('No API keys configured');
}

/**
* Filter models to only those with available API keys
*/
export function filterAvailableModels(models) {
return models.filter((model) => {
const provider = getProviderFromModel(model);
return provider && hasProvider(provider);
});
}
Loading
Loading