Skip to content
Open
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ HYPERBOLIC_API_KEY=your_hyperbolic_api_key_here
# Get your API key from: https://openrouter.ai/keys
OPEN_ROUTER_API_KEY=your_openrouter_api_key_here

# TokenLab (Unified model provider)
# Get your API key from: https://tokenlab.sh/
TOKENLAB_API_KEY=your_tokenlab_api_key_here

# ======================================
# CUSTOM PROVIDER BASE URLS (Optional)
# ======================================
Expand Down
7 changes: 6 additions & 1 deletion .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ ANTHROPIC_API_KEY=
# You only need this environment variable set if you want to use OpenRouter models
OPEN_ROUTER_API_KEY=

# Get your TokenLab API key -
# https://tokenlab.sh/
# You only need this environment variable set if you want to use TokenLab models
TOKENLAB_API_KEY=

# Get your Google Generative AI API Key by following these instructions -
# https://console.cloud.google.com/apis/credentials
# You only need this environment variable set if you want to use Google Generative AI models
Expand Down Expand Up @@ -139,4 +144,4 @@ VITE_SUPABASE_ACCESS_TOKEN=
# DEFAULT_NUM_CTX=24576 # Consumes 32GB of VRAM
# DEFAULT_NUM_CTX=12288 # Consumes 26GB of VRAM
# DEFAULT_NUM_CTX=6144 # Consumes 24GB of VRAM
DEFAULT_NUM_CTX=
DEFAULT_NUM_CTX=
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![bolt.diy: AI-Powered Full-Stack Web Development in the Browser](./public/social_preview_index.jpg)](https://bolt.diy)

Welcome to bolt.diy, the official open source version of Bolt.new, which allows you to choose the LLM that you use for each prompt! Currently, you can use OpenAI, Anthropic, Ollama, OpenRouter, Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, Groq, Cohere, Together, Perplexity, Moonshot (Kimi), Hyperbolic, GitHub Models, Amazon Bedrock, and OpenAI-like providers - and it is easily extended to use any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models.
Welcome to bolt.diy, the official open source version of Bolt.new, which allows you to choose the LLM that you use for each prompt! Currently, you can use OpenAI, Anthropic, Ollama, OpenRouter, TokenLab, Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, Groq, Cohere, Together, Perplexity, Moonshot (Kimi), Hyperbolic, GitHub Models, Amazon Bedrock, and OpenAI-like providers - and it is easily extended to use any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models.

-----
Check the [bolt.diy Docs](https://stackblitz-labs.github.io/bolt.diy/) for more official installation instructions and additional information.
Expand Down Expand Up @@ -44,7 +44,7 @@ project, please check the [project management guide](./PROJECT.md) to get starte
## Recent Major Additions

### ✅ Completed Features
- **19+ AI Provider Integrations** - OpenAI, Anthropic, Google, Groq, xAI, DeepSeek, Mistral, Cohere, Together, Perplexity, HuggingFace, Ollama, LM Studio, OpenRouter, Moonshot, Hyperbolic, GitHub Models, Amazon Bedrock, OpenAI-like
- **20+ AI Provider Integrations** - OpenAI, Anthropic, Google, Groq, xAI, DeepSeek, Mistral, Cohere, Together, Perplexity, HuggingFace, Ollama, LM Studio, OpenRouter, TokenLab, Moonshot, Hyperbolic, GitHub Models, Amazon Bedrock, OpenAI-like
- **Electron Desktop App** - Native desktop experience with full functionality
- **Advanced Deployment Options** - Netlify, Vercel, and GitHub Pages deployment
- **Supabase Integration** - Database management and query capabilities
Expand Down Expand Up @@ -342,6 +342,7 @@ LMSTUDIO_BASE_URL=http://127.0.0.1:1234
- **Perplexity** - Sonar models for search and reasoning
- **HuggingFace** - Access to HuggingFace model hub
- **OpenRouter** - Unified API for multiple model providers
- **TokenLab** - Unified API with OpenAI-compatible chat completions plus native Responses, Anthropic Messages, and Gemini endpoints
- **Moonshot (Kimi)** - Kimi AI models
- **Hyperbolic** - High-performance model inference
- **GitHub Models** - Models available through GitHub
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ProviderName =
| 'OpenAI'
| 'OpenRouter'
| 'Perplexity'
| 'TokenLab'
| 'Together'
| 'XAI';

Expand All @@ -48,6 +49,7 @@ const PROVIDER_ICONS: Record<ProviderName, IconType> = {
OpenAI: SiOpenai,
OpenRouter: FaCloud,
Perplexity: SiPerplexity,
TokenLab: BsCloud,
Together: BsCloud,
XAI: BsRobot,
};
Expand All @@ -57,6 +59,7 @@ const PROVIDER_DESCRIPTIONS: Partial<Record<ProviderName, string>> = {
Anthropic: 'Access Claude and other Anthropic models',
Github: 'Use OpenAI models hosted through GitHub infrastructure',
OpenAI: 'Use GPT-4, GPT-3.5, and other OpenAI models',
TokenLab: 'Use TokenLab unified model access with OpenAI-compatible chat completions',
};

const CloudProvidersTab = () => {
Expand Down
1 change: 1 addition & 0 deletions app/lib/.server/llm/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const PROVIDER_COMPLETION_LIMITS: Record<string, number> = {
OpenRouter: 8192,
Perplexity: 8192,
Together: 8192,
TokenLab: 8192,
xAI: 8192,
LMStudio: 8192,
OpenAILike: 8192,
Expand Down
266 changes: 266 additions & 0 deletions app/lib/modules/llm/providers/tokenlab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
import { createOpenAI } from '@ai-sdk/openai';
import { BaseProvider } from '~/lib/modules/llm/base-provider';
import type { ModelInfo } from '~/lib/modules/llm/types';
import type { IProviderSetting } from '~/types/model';
import type { LanguageModelV1 } from 'ai';

const TOKENLAB_API_BASE_URL = 'https://api.tokenlab.sh/v1';

interface TokenLabModel {
id?: string;
owned_by?: string;
tokenlab?: TokenLabMetadata;
lemondata?: TokenLabMetadata;
}

interface TokenLabMetadata {
category?: string;
max_input_tokens?: number;
max_output_tokens?: number;
pricing?: {
input_per_1m?: string | number | null;
output_per_1m?: string | number | null;
};
}

interface TokenLabModelsResponse {
data?: TokenLabModel[];
}

const toNumber = (value: string | number | null | undefined): number | undefined => {
if (value === undefined || value === null || value === '') {
return undefined;
}

const parsed = Number(value);

return Number.isFinite(parsed) ? parsed : undefined;
};

const formatContextSize = (tokens: number): string => {
if (tokens >= 1_000_000) {
return `${Math.floor(tokens / 1_000_000)}M`;
}

if (tokens >= 1_000) {
return `${Math.floor(tokens / 1_000)}k`;
}

return String(tokens);
};

const formatModelLabel = (id: string, owner: string | undefined, metadata: TokenLabMetadata): string => {
const inputPrice = toNumber(metadata.pricing?.input_per_1m);
const outputPrice = toNumber(metadata.pricing?.output_per_1m);
const contextWindow = metadata.max_input_tokens ?? 200_000;
const price =
inputPrice !== undefined && outputPrice !== undefined
? ` - in:$${inputPrice.toFixed(2)} out:$${outputPrice.toFixed(2)}`
: '';
const ownerSuffix = owner ? ` (${owner})` : '';

return `${id}${ownerSuffix}${price} - context ${formatContextSize(contextWindow)}`;
};

export default class TokenLabProvider extends BaseProvider {
name = 'TokenLab';
getApiKeyLink = 'https://tokenlab.sh/';

config = {
apiTokenKey: 'TOKENLAB_API_KEY',
};

staticModels: ModelInfo[] = [
{
name: 'claude-fable-5',
label: 'Claude Fable 5',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 128_000,
},
{
name: 'claude-opus-4-8',
label: 'Claude Opus 4.8',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 128_000,
},
{
name: 'claude-sonnet-5',
label: 'Claude Sonnet 5',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 128_000,
},
{
name: 'glm-5.2',
label: 'GLM 5.2',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 128_000,
},
{
name: 'deepseek-v4-pro',
label: 'DeepSeek V4 Pro',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 384_000,
},
{
name: 'deepseek-v4-flash',
label: 'DeepSeek V4 Flash',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 384_000,
},
{
name: 'gpt-5.5',
label: 'GPT-5.5',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 128_000,
},
{ name: 'gpt-5.4', label: 'GPT-5.4', provider: 'TokenLab', maxTokenAllowed: 400_000, maxCompletionTokens: 128_000 },
{
name: 'gpt-5.4-mini',
label: 'GPT-5.4 Mini',
provider: 'TokenLab',
maxTokenAllowed: 400_000,
maxCompletionTokens: 128_000,
},
{
name: 'minimax-m3',
label: 'MiniMax M3',
provider: 'TokenLab',
maxTokenAllowed: 1_048_576,
maxCompletionTokens: 524_288,
},
{
name: 'kimi-k2.7-code',
label: 'Kimi K2.7 Code',
provider: 'TokenLab',
maxTokenAllowed: 262_144,
maxCompletionTokens: 131_072,
},
{
name: 'qwen3.7-max',
label: 'Qwen3.7 Max',
provider: 'TokenLab',
maxTokenAllowed: 991_808,
maxCompletionTokens: 65_536,
},
{
name: 'gemini-3.5-flash',
label: 'Gemini 3.5 Flash',
provider: 'TokenLab',
maxTokenAllowed: 1_048_576,
maxCompletionTokens: 65_536,
},
{
name: 'gemini-3.1-flash-lite',
label: 'Gemini 3.1 Flash Lite',
provider: 'TokenLab',
maxTokenAllowed: 1_048_576,
maxCompletionTokens: 65_536,
},
{
name: 'grok-4.3',
label: 'Grok 4.3',
provider: 'TokenLab',
maxTokenAllowed: 1_000_000,
maxCompletionTokens: 131_072,
},
{
name: 'grok-4-fast',
label: 'Grok 4 Fast',
provider: 'TokenLab',
maxTokenAllowed: 2_000_000,
maxCompletionTokens: 16_384,
},
];

async getDynamicModels(
apiKeys?: Record<string, string>,
settings?: IProviderSetting,
serverEnv: Record<string, string> = {},
): Promise<ModelInfo[]> {
const { apiKey } = this.getProviderBaseUrlAndKey({
apiKeys,
providerSettings: settings,
serverEnv,
defaultBaseUrlKey: '',
defaultApiTokenKey: 'TOKENLAB_API_KEY',
});

try {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};

if (apiKey) {
headers.Authorization = `Bearer ${apiKey}`;
}

const response = await fetch(`${TOKENLAB_API_BASE_URL}/models`, {
headers,
signal: this.createTimeoutSignal(),
});

if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

const data = (await response.json()) as TokenLabModelsResponse;

return (data.data ?? [])
.filter((model) => {
const metadata = model.tokenlab ?? model.lemondata;
return Boolean(model.id && metadata?.category === 'chat');
})
.map((model) => {
const metadata = (model.tokenlab ?? model.lemondata)!;
const name = model.id!;

return {
name,
label: formatModelLabel(name, model.owned_by, metadata),
provider: this.name,
maxTokenAllowed: metadata.max_input_tokens ?? 200_000,
maxCompletionTokens: metadata.max_output_tokens ?? 8_192,
};
})
.sort((a, b) => a.label.localeCompare(b.label));
} catch (error) {
console.error('Error getting TokenLab models:', error);
return [];
}
}

getModelInstance(options: {
model: string;
serverEnv: Env;
apiKeys?: Record<string, string>;
providerSettings?: Record<string, IProviderSetting>;
}): LanguageModelV1 {
const { model, serverEnv, apiKeys, providerSettings } = options;

const { apiKey } = this.getProviderBaseUrlAndKey({
apiKeys,
providerSettings: providerSettings?.[this.name],
serverEnv: serverEnv as any,
defaultBaseUrlKey: '',
defaultApiTokenKey: 'TOKENLAB_API_KEY',
});

if (!apiKey) {
throw new Error(`Missing API key for ${this.name} provider`);
}

const openai = createOpenAI({
baseURL: TOKENLAB_API_BASE_URL,
apiKey,
});

return openai(model);
}
}
2 changes: 2 additions & 0 deletions app/lib/modules/llm/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import OpenAILikeProvider from './providers/openai-like';
import OpenAIProvider from './providers/openai';
import PerplexityProvider from './providers/perplexity';
import TogetherProvider from './providers/together';
import TokenLabProvider from './providers/tokenlab';
import XAIProvider from './providers/xai';
import HyperbolicProvider from './providers/hyperbolic';
import AmazonBedrockProvider from './providers/amazon-bedrock';
Expand All @@ -38,6 +39,7 @@ export {
OpenRouterProvider,
OpenAILikeProvider,
PerplexityProvider,
TokenLabProvider,
XAIProvider,
TogetherProvider,
LMStudioProvider,
Expand Down
1 change: 1 addition & 0 deletions app/lib/services/importExportService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ export class ImportExportService {
Mistral: '',
OpenAILike: '',
Together: '',
TokenLab: '',
xAI: '',
Perplexity: '',
Cohere: '',
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Welcome to bolt diy

bolt.diy allows you to choose the LLM that you use for each prompt! Currently, you can use models from 19 providers including OpenAI, Anthropic, Ollama, OpenRouter, Google/Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, Groq, Cohere, Together AI, Perplexity AI, Hyperbolic, Moonshot AI (Kimi), Amazon Bedrock, GitHub Models, and more - with easy extensibility to add any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models.
bolt.diy allows you to choose the LLM that you use for each prompt! Currently, you can use models from 20 providers including OpenAI, Anthropic, Ollama, OpenRouter, TokenLab, Google/Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, Groq, Cohere, Together AI, Perplexity AI, Hyperbolic, Moonshot AI (Kimi), Amazon Bedrock, GitHub Models, and more - with easy extensibility to add any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models.

## Table of Contents

Expand Down Expand Up @@ -40,7 +40,7 @@ Also [this pinned post in our community](https://thinktank.ottomator.ai/t/videos
## Features

- **AI-powered full-stack web development** directly in your browser with live preview
- **Support for 19 LLM providers** with an extensible architecture to integrate additional models
- **Support for 20 LLM providers** with an extensible architecture to integrate additional models
- **Attach images and files to prompts** for better contextual understanding
- **Integrated terminal** with WebContainer sandbox for running commands and testing
- **Version control with Git** - import/export projects, connect to GitHub repositories
Expand Down
Loading