diff --git a/src/commands/config.ts b/src/commands/config.ts index b708075..848d065 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -15,6 +15,9 @@ export default class ConfigCommand extends Command { 'api-key': Flags.string({ description: 'Set OpenAI API key', }), + 'base-url': Flags.string({ + description: 'Set OpenAI Base URL', + }), show: Flags.boolean({ description: 'Show current configuration', }), @@ -27,6 +30,10 @@ export default class ConfigCommand extends Command { await this.setApiKey(flags['api-key']); } + if (flags['base-url']) { + await this.setBaseUrl(flags['base-url']); + } + if (flags.show) { await this.showConfig(); } @@ -49,6 +56,19 @@ export default class ConfigCommand extends Command { this.log(chalk.dim('Built with ❤️ by \u001b]8;;https://codewithbeto.dev\u001b\\codewithbeto.dev\u001b]8;;\u001b\\ - Ship faster, contribute more, lead with confidence')); } + + private async setBaseUrl(baseUrl: string): Promise { + const error = ValidationService.validateBaseUrl(baseUrl); + if (error) { + this.error(chalk.red(error)); + } + + await ConfigService.set('openai_base_url', baseUrl); + this.log(chalk.green('✅ OpenAI Base URL configured successfully!')); + this.log(''); + this.log(chalk.dim('Built with ❤️ by \u001b]8;;https://codewithbeto.dev\u001b\\codewithbeto.dev\u001b]8;;\u001b\\ - Ship faster, contribute more, lead with confidence')); + } + private async showConfig(): Promise { const config = await ConfigService.getConfig(); @@ -62,6 +82,10 @@ export default class ConfigCommand extends Command { this.log(`🔑 OpenAI API Key: ${chalk.red('Not configured')}`); this.log(chalk.gray(' Set with: snapai config --api-key YOUR_KEY')); } + + if (config.openai_base_url) { + this.log(`🔗 OpenAI Base URL: ${chalk.blue(config.openai_base_url)}`); + } if (config.default_output_path) { this.log(`📁 Default Output: ${chalk.blue(config.default_output_path)}`); diff --git a/src/services/openai.ts b/src/services/openai.ts index 4380809..6146429 100644 --- a/src/services/openai.ts +++ b/src/services/openai.ts @@ -5,6 +5,7 @@ import { IconGenerationOptions, OpenAIResponse } from "../types.js"; export class OpenAIService { private static async getClient(): Promise { const apiKey = await ConfigService.get("openai_api_key"); + const baseUrl = await ConfigService.get("openai_base_url"); if (!apiKey) { throw new Error( @@ -14,6 +15,7 @@ export class OpenAIService { return new OpenAI({ apiKey: apiKey, + baseURL: baseUrl }); } diff --git a/src/types.ts b/src/types.ts index 9d3b8a0..c8a7307 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ export interface ConfigData { openai_api_key?: string; + openai_base_url?: string; default_output_path?: string; } diff --git a/src/utils/validation.ts b/src/utils/validation.ts index b562fc9..ef39d4f 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -19,6 +19,14 @@ export class ValidationService { return null; } + static validateBaseUrl(baseUrl: string): string | null { + if (!baseUrl || !baseUrl.startsWith('https://')) { + return 'Invalid OpenAI URL format'; + } + + return null; + } + static validateOutputPath(outputPath: string): string | null { if (!outputPath || outputPath.trim().length === 0) { return 'Output path cannot be empty';