feat: Add xAI models support (#14523)

This commit is contained in:
Abdul Rahman
2025-09-16 21:25:11 +05:30
committed by GitHub
parent ba3cbd1676
commit 172cc12a82
9 changed files with 119 additions and 5 deletions
@@ -7,7 +7,7 @@ import { AI_MODELS, ModelProvider } from './ai-models.const';
describe('AI_MODELS', () => {
it('should contain all expected models', () => {
expect(AI_MODELS).toHaveLength(6);
expect(AI_MODELS).toHaveLength(9);
expect(AI_MODELS.map((model) => model.modelId)).toEqual([
'gpt-4o',
'gpt-4o-mini',
@@ -15,6 +15,9 @@ describe('AI_MODELS', () => {
'claude-opus-4-20250514',
'claude-sonnet-4-20250514',
'claude-3-5-haiku-20241022',
'grok-3',
'grok-3-mini',
'grok-4',
]);
});
});
@@ -3,6 +3,7 @@ export enum ModelProvider {
OPENAI = 'openai',
ANTHROPIC = 'anthropic',
OPENAI_COMPATIBLE = 'open_ai_compatible',
XAI = 'xai',
}
export type ModelId =
@@ -13,6 +14,9 @@ export type ModelId =
| 'claude-opus-4-20250514'
| 'claude-sonnet-4-20250514'
| 'claude-3-5-haiku-20241022'
| 'grok-3'
| 'grok-3-mini'
| 'grok-4'
| string; // Allow custom model names
export interface AIModelConfig {
@@ -66,4 +70,25 @@ export const AI_MODELS: AIModelConfig[] = [
inputCostPer1kTokensInCents: 0.08,
outputCostPer1kTokensInCents: 0.4,
},
{
modelId: 'grok-3',
label: 'Grok-3',
provider: ModelProvider.XAI,
inputCostPer1kTokensInCents: 0.3,
outputCostPer1kTokensInCents: 1.5,
},
{
modelId: 'grok-3-mini',
label: 'Grok-3 Mini',
provider: ModelProvider.XAI,
inputCostPer1kTokensInCents: 0.03,
outputCostPer1kTokensInCents: 0.05,
},
{
modelId: 'grok-4',
label: 'Grok-4',
provider: ModelProvider.XAI,
inputCostPer1kTokensInCents: 0.5,
outputCostPer1kTokensInCents: 2.5,
},
];
@@ -2,12 +2,13 @@ import { Injectable } from '@nestjs/common';
import { anthropic } from '@ai-sdk/anthropic';
import { createOpenAI, openai } from '@ai-sdk/openai';
import { xai } from '@ai-sdk/xai';
import { type LanguageModel } from 'ai';
import {
AI_MODELS,
type AIModelConfig,
ModelProvider,
type AIModelConfig,
} from 'src/engine/core-modules/ai/constants/ai-models.const';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
@@ -40,6 +41,12 @@ export class AiModelRegistryService {
this.registerAnthropicModels();
}
const xaiApiKey = this.twentyConfigService.get('XAI_API_KEY');
if (xaiApiKey) {
this.registerXaiModels();
}
const openaiCompatibleBaseUrl = this.twentyConfigService.get(
'OPENAI_COMPATIBLE_BASE_URL',
);
@@ -83,6 +90,20 @@ export class AiModelRegistryService {
});
}
private registerXaiModels(): void {
const xaiModels = AI_MODELS.filter(
(model) => model.provider === ModelProvider.XAI,
);
xaiModels.forEach((modelConfig) => {
this.modelRegistry.set(modelConfig.modelId, {
modelId: modelConfig.modelId,
provider: ModelProvider.XAI,
model: xai(modelConfig.modelId),
});
});
}
private registerOpenAICompatibleModels(
baseUrl: string,
modelNamesString: string,
@@ -206,6 +227,9 @@ export class AiModelRegistryService {
case ModelProvider.ANTHROPIC:
apiKey = this.twentyConfigService.get('ANTHROPIC_API_KEY');
break;
case ModelProvider.XAI:
apiKey = this.twentyConfigService.get('XAI_API_KEY');
break;
case ModelProvider.OPENAI_COMPATIBLE:
apiKey = this.twentyConfigService.get('OPENAI_COMPATIBLE_API_KEY');
break;
@@ -1053,6 +1053,15 @@ export class ConfigVariables {
@IsOptional()
OPENAI_COMPATIBLE_API_KEY: string;
@ConfigVariablesMetadata({
group: ConfigVariablesGroup.LLM,
isSensitive: true,
description: 'API key for xAI integration',
type: ConfigVariableType.STRING,
})
@IsOptional()
XAI_API_KEY: string;
@ConfigVariablesMetadata({
group: ConfigVariablesGroup.ServerConfig,
description: 'Enable or disable multi-workspace support',