rawi
Version:
Rawi (راوي) is the developer-friendly AI CLI that brings the power of 12 major AI providers directly to your terminal. With seamless shell integration, persistent conversations, and 200+ specialized prompt templates, Rawi transforms your command line into
1 lines • 6.14 kB
Source Map (JSON)
{"version":3,"sources":["/home/mkabumattar/withrawi/rawi/dist/chunk-SUWS4T5H.cjs","../src/core/configs/managers/interactive.manager.ts"],"names":["InteractiveConfigManager","ConfigValidator","profile"],"mappings":"AAAA;AACA,wDAAwC,wDAAgD,wDAAgD,4CCDzF,4EAC7B,IAULA,CAAAA,WAAN,KAA+B,qEACnB,SAAA,CAAY,IAAIC,oBAAAA,MAE3B,UAAA,CAAWC,CAAAA,CAAmC,CAClD,EAAA,CAAIA,CAAAA,CAAS,CACX,EAAA,CAAI,CAAC,IAAA,CAAK,kBAAA,CAAmBA,CAAO,CAAA,CAClC,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyBA,CAAO,CAAA,CAAA;ADfuT","file":"/home/mkabumattar/withrawi/rawi/dist/chunk-SUWS4T5H.cjs","sourcesContent":[null,"import {confirm, input, password, select} from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport {getAllProviders, getProvider} from '../../providers/index.js';\nimport {\n DEFAULT_LANGUAGE,\n DEFAULT_PROFILE,\n type SupportedLanguage,\n type SupportedProvider,\n} from '../../shared/index.js';\nimport {ConfigValidator} from '../validators/config.validator.js';\n\nexport class InteractiveConfigManager {\n private readonly validator = new ConfigValidator();\n\n async getProfile(profile?: string): Promise<string> {\n if (profile) {\n if (!this.isValidProfileName(profile)) {\n throw new Error(`Invalid profile name: ${profile}`);\n }\n return profile;\n }\n\n return input({\n message: 'Profile Name:',\n default: DEFAULT_PROFILE,\n validate: (input: string) => {\n if (!input.trim()) {\n return 'Profile name is required';\n }\n if (!this.isValidProfileName(input.trim())) {\n return 'Profile name can only contain letters, numbers, hyphens, and underscores';\n }\n return true;\n },\n });\n }\n\n async selectProvider(\n defaultProvider?: SupportedProvider,\n ): Promise<SupportedProvider> {\n const providers = getAllProviders();\n const choices = providers.map((p) => ({\n name: `${p.displayName} (${p.name})`,\n value: p.name as SupportedProvider,\n }));\n\n return select({\n message: 'Select AI Provider:',\n choices,\n default: defaultProvider,\n });\n }\n\n async selectModel(\n provider: SupportedProvider,\n defaultModel?: string,\n ): Promise<string> {\n const providerConfig = getProvider(provider);\n\n if (!providerConfig) {\n throw new Error(`Unknown provider: ${provider}`);\n }\n\n const choices = providerConfig.models.map((model) => ({\n name: model.displayName || model.name,\n value: model.name,\n description: model.description || '',\n }));\n\n if (choices.length === 0) {\n throw new Error(`No models available for provider: ${provider}`);\n }\n\n return select({\n message: `Select ${providerConfig.displayName} Model:`,\n choices,\n default: defaultModel,\n });\n }\n\n async getApiKey(\n defaultApiKey?: string,\n provider?: SupportedProvider,\n ): Promise<string> {\n const message = provider\n ? `${getProvider(provider)?.displayName || provider} API Key:`\n : 'API Key:';\n\n let apiKey: string;\n\n if (defaultApiKey) {\n const useExisting = await confirm({\n message: `Use existing API key (${this.maskApiKey(defaultApiKey)})?`,\n default: true,\n });\n\n if (useExisting) {\n return defaultApiKey;\n }\n }\n\n do {\n apiKey = await password({\n message,\n mask: '*',\n validate: (input: string) => {\n if (!input.trim()) {\n return 'API key is required';\n }\n\n if (provider) {\n const validation = this.validator.validateApiKey(\n input.trim(),\n provider,\n );\n if (!validation.isValid) {\n return validation.errors[0] || 'Invalid API key';\n }\n\n if (validation.warnings.length > 0) {\n console.log(\n chalk.yellow(`Warning: ${validation.warnings.join(', ')}`),\n );\n }\n }\n\n return true;\n },\n });\n } while (!apiKey.trim());\n\n return apiKey.trim();\n }\n\n async getTemperature(defaultTemperature = 0.7): Promise<number> {\n const input_result = await input({\n message: 'Temperature (0.0 - 2.0):',\n default: defaultTemperature.toString(),\n validate: (input: string) => {\n const num = Number.parseFloat(input);\n if (Number.isNaN(num)) {\n return 'Temperature must be a number';\n }\n if (num < 0 || num > 2) {\n return 'Temperature must be between 0.0 and 2.0';\n }\n return true;\n },\n });\n\n return Number.parseFloat(input_result);\n }\n\n async getMaxTokens(defaultMaxTokens = 2048): Promise<number> {\n const input_result = await input({\n message: 'Max Tokens (1 - 100000):',\n default: defaultMaxTokens.toString(),\n validate: (input: string) => {\n const num = Number.parseInt(input, 10);\n if (Number.isNaN(num)) {\n return 'Max tokens must be a number';\n }\n if (num < 1 || num > 100000) {\n return 'Max tokens must be between 1 and 100000';\n }\n return true;\n },\n });\n\n return Number.parseInt(input_result, 10);\n }\n\n async getLanguage(\n defaultLanguage: SupportedLanguage = DEFAULT_LANGUAGE,\n ): Promise<SupportedLanguage> {\n const languages: Array<{name: string; value: SupportedLanguage}> = [\n {name: 'English', value: 'english'},\n {name: 'Arabic', value: 'arabic'},\n ];\n\n return select({\n message: 'Response Language:',\n choices: languages,\n default: defaultLanguage,\n });\n }\n\n private isValidProfileName(name: string): boolean {\n const profileNameRegex = /^[a-zA-Z0-9_-]+$/;\n return profileNameRegex.test(name) && name.length <= 50;\n }\n\n private maskApiKey(apiKey: string): string {\n if (apiKey.length <= 8) {\n return '*'.repeat(apiKey.length);\n }\n return `${apiKey.slice(0, 4)}${'*'.repeat(apiKey.length - 8)}${apiKey.slice(-4)}`;\n }\n}\n"]}