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
366 changes: 131 additions & 235 deletions packages/mukti-api/src/modules/ai/ai.controller.ts

Large diffs are not rendered by default.

30 changes: 29 additions & 1 deletion packages/mukti-api/src/modules/ai/ai.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,61 @@ import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';

import {
AiModelConfig,
AiModelConfigSchema,
} from '../../schemas/ai-model-config.schema';
import {
AiProviderConfig,
AiProviderConfigSchema,
} from '../../schemas/ai-provider-config.schema';
import { User, UserSchema } from '../../schemas/user.schema';
import { AuthModule } from '../auth/auth.module';
import { AiController } from './ai.controller';
import { AiPolicyService } from './services/ai-policy.service';
import { AiConfigService } from './services/ai-config.service';
import { AiGatewayService } from './services/ai-gateway.service';
import { AiSecretsService } from './services/ai-secrets.service';
import { GeminiClientFactory } from './services/gemini-client.factory';
import { OpenRouterClientFactory } from './services/openrouter-client.factory';
import { OpenRouterModelsService } from './services/openrouter-models.service';
import { AnthropicProviderService } from './services/providers/anthropic-provider.service';
import { GeminiProviderService } from './services/providers/gemini-provider.service';
import { OpenAiProviderService } from './services/providers/openai-provider.service';
import { OpenRouterProviderService } from './services/providers/openrouter-provider.service';

@Module({
controllers: [AiController],
exports: [
AiPolicyService,
AiConfigService,
AiGatewayService,
AiSecretsService,
GeminiClientFactory,
OpenRouterClientFactory,
OpenRouterModelsService,
],
imports: [
ConfigModule,
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
AuthModule,
MongooseModule.forFeature([
{ name: User.name, schema: UserSchema },
{ name: AiProviderConfig.name, schema: AiProviderConfigSchema },
{ name: AiModelConfig.name, schema: AiModelConfigSchema },
]),
],
providers: [
AiPolicyService,
AiConfigService,
AiGatewayService,
AiSecretsService,
GeminiClientFactory,
OpenRouterClientFactory,
OpenRouterModelsService,
OpenAiProviderService,
AnthropicProviderService,
GeminiProviderService,
OpenRouterProviderService,
],
})
export class AiModule {}
83 changes: 83 additions & 0 deletions packages/mukti-api/src/modules/ai/dto/admin-model.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
IsBoolean,
IsIn,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
Min,
ValidateNested,
} from 'class-validator';

import { AI_PROVIDER_VALUES } from '../../../schemas/ai-provider-config.schema';

export class AiModelPricingDto {
@ApiProperty({
description: 'Prompt price in USD per 1M input tokens',
example: 0.15,
})
@IsNumber()
@Min(0)
promptUsdPer1M: number;

@ApiProperty({
description: 'Completion price in USD per 1M output tokens',
example: 0.6,
})
@IsNumber()
@Min(0)
completionUsdPer1M: number;
}

export class UpsertAiModelDto {
@ApiProperty({
description: 'Client-facing model label',
example: 'GPT-4.1 Mini',
})
@IsNotEmpty()
@IsString()
label: string;

@ApiProperty({
description: 'Provider for this model',
enum: AI_PROVIDER_VALUES,
example: 'openai',
})
@IsIn(AI_PROVIDER_VALUES)
provider: string;

@ApiProperty({
description: 'Provider-specific model identifier',
example: 'gpt-4.1-mini',
})
@IsNotEmpty()
@IsString()
providerModel: string;

@ApiProperty({
description: 'Pricing configuration for deterministic cost tracking',
type: AiModelPricingDto,
})
@Type(() => AiModelPricingDto)
@ValidateNested()
pricing: AiModelPricingDto;

@ApiPropertyOptional({
description: 'Whether this model is available to users',
example: true,
})
@IsBoolean()
@IsOptional()
isActive?: boolean;
}

export class ToggleAiModelDto {
@ApiProperty({
description: 'Whether this model is active',
example: true,
})
@IsBoolean()
isActive: boolean;
}
21 changes: 21 additions & 0 deletions packages/mukti-api/src/modules/ai/dto/admin-provider.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';

export class SetProviderApiKeyDto {
@ApiProperty({
description: 'Provider API key to store on the server',
example: 'sk-...',
})
@IsNotEmpty()
@IsString()
apiKey: string;
}

export class ToggleProviderDto {
@ApiProperty({
description: 'Whether this provider is active for model routing',
example: true,
})
@IsBoolean()
isActive: boolean;
}
4 changes: 2 additions & 2 deletions packages/mukti-api/src/modules/ai/dto/ai-settings.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { IsOptional, IsString } from 'class-validator';

export class UpdateAiSettingsDto {
@ApiPropertyOptional({
description: 'Globally active OpenRouter model id',
example: 'openai/gpt-5-mini',
description: 'Globally active AI model id',
example: 'default-gpt-5-mini',
})
@IsOptional()
@IsString()
Expand Down
Loading
Loading