[AI] new model tab design (#19384)

closes
https://discord.com/channels/1130383047699738754/1480979892610007121

<img width="1839" height="1316" alt="CleanShot 2026-04-07 at 15 22 38"
src="https://github.com/user-attachments/assets/d8f6048c-4e0f-425f-b7ea-4913d116020e"
/>
This commit is contained in:
nitin
2026-04-09 19:45:43 +05:30
committed by GitHub
parent 74e26ae635
commit 50c5a1a8de
37 changed files with 873 additions and 570 deletions
@@ -228,6 +228,17 @@ export class AdminPanelResolver {
return true;
}
@UseGuards(AdminPanelGuard)
@Mutation(() => Boolean)
async setAdminAiModelsEnabled(
@Args('modelIds', { type: () => [String] }) modelIds: string[],
@Args('enabled', { type: () => Boolean }) enabled: boolean,
): Promise<boolean> {
await this.aiModelRegistryService.setModelsAdminEnabled(modelIds, enabled);
return true;
}
@UseGuards(AdminPanelGuard)
@Mutation(() => Boolean)
async setAdminAiModelRecommended(
@@ -239,6 +250,20 @@ export class AdminPanelResolver {
return true;
}
@UseGuards(AdminPanelGuard)
@Mutation(() => Boolean)
async setAdminAiModelsRecommended(
@Args('modelIds', { type: () => [String] }) modelIds: string[],
@Args('recommended', { type: () => Boolean }) recommended: boolean,
): Promise<boolean> {
await this.aiModelRegistryService.setModelsRecommended(
modelIds,
recommended,
);
return true;
}
@UseGuards(AdminPanelGuard)
@Mutation(() => Boolean)
async setAdminDefaultAiModel(
@@ -56,11 +56,11 @@ export class ClientAIModelConfig {
@Field(() => String, { nullable: true })
sdkPackage: AiSdkPackage | null;
@Field(() => Number)
inputCostPerMillionTokensInCredits: number;
@Field(() => Number, { nullable: true })
inputCostPerMillionTokens?: number;
@Field(() => Number)
outputCostPerMillionTokensInCredits: number;
@Field(() => Number, { nullable: true })
outputCostPerMillionTokens?: number;
@Field(() => NativeModelCapabilities, { nullable: true })
nativeCapabilities?: NativeModelCapabilities;
@@ -74,6 +74,15 @@ export class ClientAIModelConfig {
@Field(() => String, { nullable: true })
providerName?: string;
@Field(() => String, { nullable: true })
providerLabel?: string;
@Field(() => Number, { nullable: true })
contextWindowTokens?: number;
@Field(() => Number, { nullable: true })
maxOutputTokens?: number;
@Field(() => String, { nullable: true })
dataResidency?: string;
}
@@ -38,6 +38,9 @@ describe('ClientConfigService', () => {
getAdminFilteredModels: jest.fn().mockReturnValue([]),
getRecommendedModelIds: jest.fn().mockReturnValue(new Set()),
getModelConfig: jest.fn().mockReturnValue(undefined),
getResolvedProvidersForAdmin: jest.fn().mockReturnValue({}),
getDefaultSpeedModel: jest.fn().mockReturnValue(undefined),
getDefaultPerformanceModel: jest.fn().mockReturnValue(undefined),
},
},
{
@@ -21,7 +21,6 @@ import {
import { DomainServerConfigService } from 'src/engine/core-modules/domain/domain-server-config/services/domain-server-config.service';
import { PUBLIC_FEATURE_FLAGS } from 'src/engine/core-modules/feature-flag/constants/public-feature-flag.const';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { convertDollarsToBillingCredits } from 'src/engine/metadata-modules/ai/ai-billing/utils/convert-dollars-to-billing-credits.util';
import {
AUTO_SELECT_FAST_MODEL_ID,
AUTO_SELECT_SMART_MODEL_ID,
@@ -69,6 +68,13 @@ export class ClientConfigService {
this.aiModelRegistryService.getAdminFilteredModels();
const recommendedModelIds =
this.aiModelRegistryService.getRecommendedModelIds();
const resolvedProviders =
this.aiModelRegistryService.getResolvedProvidersForAdmin();
const getProviderLabel = (providerName?: string | null) =>
providerName
? (resolvedProviders[providerName]?.label ?? providerName)
: undefined;
const aiModels: ClientAIModelConfig[] = availableModels.map(
(registeredModel) => {
@@ -77,6 +83,7 @@ export class ClientConfigService {
);
const modelFamily = modelConfig?.modelFamily;
const providerName = registeredModel.providerName;
return {
modelId: registeredModel.modelId,
@@ -86,20 +93,15 @@ export class ClientConfigService {
? MODEL_FAMILY_LABELS[modelFamily]
: undefined,
sdkPackage: registeredModel.sdkPackage,
providerName: registeredModel.providerName,
providerName,
providerLabel: getProviderLabel(providerName),
nativeCapabilities: this.deriveNativeCapabilities(
registeredModel.sdkPackage,
),
inputCostPerMillionTokensInCredits: modelConfig
? convertDollarsToBillingCredits(
modelConfig.inputCostPerMillionTokens,
)
: 0,
outputCostPerMillionTokensInCredits: modelConfig
? convertDollarsToBillingCredits(
modelConfig.outputCostPerMillionTokens,
)
: 0,
inputCostPerMillionTokens: modelConfig?.inputCostPerMillionTokens,
outputCostPerMillionTokens: modelConfig?.outputCostPerMillionTokens,
contextWindowTokens: modelConfig?.contextWindowTokens,
maxOutputTokens: modelConfig?.maxOutputTokens,
isDeprecated: modelConfig?.isDeprecated,
isRecommended: recommendedModelIds.has(registeredModel.modelId),
dataResidency: modelConfig?.dataResidency,
@@ -129,9 +131,17 @@ export class ClientConfigService {
'Default',
modelFamily: defaultPerformanceModelConfig?.modelFamily,
providerName: defaultPerformanceModel?.providerName,
providerLabel: getProviderLabel(
defaultPerformanceModel?.providerName,
),
sdkPackage: defaultPerformanceModel?.sdkPackage ?? null,
inputCostPerMillionTokensInCredits: 0,
outputCostPerMillionTokensInCredits: 0,
inputCostPerMillionTokens:
defaultPerformanceModelConfig?.inputCostPerMillionTokens,
outputCostPerMillionTokens:
defaultPerformanceModelConfig?.outputCostPerMillionTokens,
contextWindowTokens:
defaultPerformanceModelConfig?.contextWindowTokens,
maxOutputTokens: defaultPerformanceModelConfig?.maxOutputTokens,
},
{
modelId: AUTO_SELECT_FAST_MODEL_ID,
@@ -141,9 +151,14 @@ export class ClientConfigService {
'Default',
modelFamily: defaultSpeedModelConfig?.modelFamily,
providerName: defaultSpeedModel?.providerName,
providerLabel: getProviderLabel(defaultSpeedModel?.providerName),
sdkPackage: defaultSpeedModel?.sdkPackage ?? null,
inputCostPerMillionTokensInCredits: 0,
outputCostPerMillionTokensInCredits: 0,
inputCostPerMillionTokens:
defaultSpeedModelConfig?.inputCostPerMillionTokens,
outputCostPerMillionTokens:
defaultSpeedModelConfig?.outputCostPerMillionTokens,
contextWindowTokens: defaultSpeedModelConfig?.contextWindowTokens,
maxOutputTokens: defaultSpeedModelConfig?.maxOutputTokens,
},
);
}