UNPKG

openai-cli-unofficial

Version:

A powerful OpenAI CLI Coding Agent built with TypeScript

853 lines 44.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigPage = void 0; const prompts_1 = require("@inquirer/prompts"); const chalk_1 = __importDefault(require("chalk")); const figlet_1 = __importDefault(require("figlet")); const language_1 = require("../../services/language"); const storage_1 = require("../../services/storage"); const utils_1 = require("../../utils"); const components_1 = require("../components"); class ConfigPage { constructor() { this.gradients = utils_1.AnimationUtils.getGradients(); } async show() { utils_1.AnimationUtils.forceClearScreen(); await this.showHeader(); await this.showConfigMenu(); } async showHeader() { const messages = language_1.languageService.getMessages(); // 显示配置页面标题 const configTitle = figlet_1.default.textSync('CONFIG', { font: 'ANSI Shadow', horizontalLayout: 'default', verticalLayout: 'default', width: 60 }); console.log(this.gradients.secondary(configTitle)); console.log(); // 显示副标题 console.log(' ' + this.gradients.primary(messages.config.subtitle)); console.log(); // 显示分割线 console.log(' ' + chalk_1.default.gray('─'.repeat(60))); console.log(); } async showConfigMenu() { const messages = language_1.languageService.getMessages(); const choices = [ { name: messages.config.menuOptions.baseUrl, value: 'baseUrl', description: messages.config.menuDescription.baseUrl }, { name: messages.config.menuOptions.apiKey, value: 'apiKey', description: messages.config.menuDescription.apiKey }, { name: messages.config.menuOptions.model, value: 'model', description: messages.config.menuDescription.model }, { name: messages.config.menuOptions.contextTokens, value: 'contextTokens', description: messages.config.menuDescription.contextTokens }, { name: messages.config.menuOptions.maxConcurrency, value: 'maxConcurrency', description: messages.config.menuDescription.maxConcurrency }, { name: messages.config.menuOptions.role, value: 'role', description: messages.config.menuDescription.role }, { name: messages.config.menuOptions.mcpConfig, value: 'mcpConfig', description: messages.config.menuDescription.mcpConfig }, { name: messages.config.menuOptions.mcpFunctionConfirmation, value: 'mcpFunctionConfirmation', description: messages.config.menuDescription.mcpFunctionConfirmation }, { name: messages.config.menuOptions.maxToolCalls, value: 'maxToolCalls', description: messages.config.menuDescription.maxToolCalls }, { name: messages.config.menuOptions.terminalSensitiveWords, value: 'terminalSensitiveWords', description: messages.config.menuDescription.terminalSensitiveWords }, { name: messages.config.menuOptions.viewConfig, value: 'viewConfig', description: messages.config.menuDescription.viewConfig }, { name: messages.config.menuOptions.resetConfig, value: 'resetConfig', description: messages.config.menuDescription.resetConfig }, { name: messages.config.menuOptions.back, value: 'back', description: messages.config.menuDescription.back } ]; const action = await components_1.InteractiveMenu.show({ message: messages.config.menuPrompt + ':', choices }); await this.handleConfigAction(action); } async handleConfigAction(action) { const messages = language_1.languageService.getMessages(); console.log(); switch (action) { case 'baseUrl': await this.editBaseUrl(); break; case 'apiKey': await this.editApiKey(); break; case 'model': await this.editModel(); break; case 'contextTokens': await this.editContextTokens(); break; case 'maxConcurrency': await this.editMaxConcurrency(); break; case 'role': await this.editRole(); break; case 'mcpConfig': await this.editMcpConfig(); break; case 'mcpFunctionConfirmation': await this.editMcpFunctionConfirmation(); break; case 'maxToolCalls': await this.editMaxToolCalls(); break; case 'terminalSensitiveWords': await this.editTerminalSensitiveWords(); break; case 'viewConfig': await this.viewCurrentConfig(); // 查看配置后暂停让用户查看,使用自定义的等待输入方法避免终端状态冲突 console.log(); await this.waitForEnter(); break; case 'resetConfig': await this.resetConfig(); break; case 'back': return; // 直接返回到欢迎页 default: console.log(' ' + chalk_1.default.red(messages.welcome.actions.unknownAction)); } // 除了返回操作,其他操作完成后自动返回配置菜单 if (action !== 'back') { await this.show(); // 递归显示配置页面 } } async editBaseUrl() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.baseUrl)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.baseUrl)); if (currentConfig.baseUrl) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentConfig.baseUrl}`)); } console.log(); try { const baseUrl = await components_1.NativeInput.url(' ' + messages.config.prompts.baseUrlInput + ':', currentConfig.baseUrl || messages.config.prompts.baseUrlPlaceholder); const result = { baseUrl }; if (result.baseUrl && result.baseUrl.trim()) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveBaseUrl(result.baseUrl.trim()); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,直接返回 console.log(); return; } } async editApiKey() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.apiKey)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.apiKey)); if (currentConfig.apiKey) { const maskedKey = utils_1.StringUtils.maskApiKey(currentConfig.apiKey); console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${maskedKey}`)); } console.log(); try { const apiKey = await components_1.NativeInput.text(' ' + messages.config.prompts.apiKeyInput + ':'); if (apiKey && apiKey.trim()) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveApiKey(apiKey.trim()); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,直接返回 console.log(); return; } } async editModel() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.model)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.model)); if (currentConfig.model) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentConfig.model}`)); } console.log(); // 提供一些常用模型的选项,包含退出选项 const commonModelChoices = [ { name: 'gpt-4.1', value: 'gpt-4.1' }, { name: 'gpt-4o', value: 'gpt-4o' }, { name: 'o3', value: 'o3' }, { name: 'o3-mini', value: 'o3-mini' }, { name: 'o4-mini', value: 'o4-mini' }, { name: messages.config.actions.custom, value: 'custom' }, { name: messages.config.actions.cancel, value: 'cancel' } ]; const modelChoice = await components_1.InteractiveMenu.show({ message: ' ' + messages.config.prompts.modelInput + ':', choices: commonModelChoices }); let finalModel = modelChoice; if (modelChoice === 'custom') { const model = await components_1.NativeInput.text(' ' + messages.config.prompts.modelInput + ':', currentConfig.model || messages.config.prompts.modelPlaceholder); finalModel = model; } if (modelChoice === 'cancel') { return; } if (finalModel && finalModel.trim()) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveModel(finalModel.trim()); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } async editContextTokens() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.contextTokens)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.contextTokens)); if (currentConfig.contextTokens) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentConfig.contextTokens}`)); } console.log(); try { const contextTokens = await components_1.NativeInput.number(' ' + messages.config.prompts.contextTokensInput + ':', currentConfig.contextTokens || parseInt(messages.config.prompts.contextTokensPlaceholder), 1000, 2000000); if (contextTokens) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveContextTokens(contextTokens); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,直接返回 console.log(); return; } } async editMaxConcurrency() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.maxConcurrency)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.maxConcurrency)); if (currentConfig.maxConcurrency) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentConfig.maxConcurrency}`)); } console.log(); try { const maxConcurrency = await components_1.NativeInput.number(' ' + messages.config.prompts.maxConcurrencyInput + ':', currentConfig.maxConcurrency || parseInt(messages.config.prompts.maxConcurrencyPlaceholder), 1, 100); if (maxConcurrency) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveMaxConcurrency(maxConcurrency); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,直接返回 console.log(); return; } } async editMcpConfig() { const messages = language_1.languageService.getMessages(); const currentConfigJson = storage_1.StorageService.getMcpConfigJson(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.mcpConfig)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.mcpConfig)); if (currentConfigJson && currentConfigJson !== '{\n "mcpServers": {}\n}') { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: `)); const lines = currentConfigJson.split('\n'); lines.slice(0, 5).forEach(line => { console.log(' ' + chalk_1.default.gray(line)); }); if (lines.length > 5) { console.log(' ' + chalk_1.default.gray('...')); } } console.log(); console.log(' ' + chalk_1.default.gray(messages.config.messages.mcpConfigEditorPrompt)); try { const mcpConfigJson = await (0, prompts_1.editor)({ message: ' ' + messages.config.prompts.mcpConfigInput + ':', default: currentConfigJson || messages.config.prompts.mcpConfigPlaceholder, validate: (input) => { if (!input.trim()) { return messages.config.messages.invalidInput; } // 使用新的验证方法 const validation = storage_1.StorageService.validateMcpConfigJson(input.trim()); if (!validation.isValid) { return validation.error || messages.config.messages.invalidJson; } return true; } }); // 重置终端状态,防止影响后续交互 this.resetTerminalState(); if (mcpConfigJson && mcpConfigJson.trim()) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); // 验证并保存配置 const validation = storage_1.StorageService.validateMcpConfigJson(mcpConfigJson.trim()); if (validation.isValid && validation.parsedConfig) { storage_1.StorageService.saveMcpConfig(validation.parsedConfig); // 显示保存成功消息 console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); // 如果有系统服务被恢复,显示额外信息 if (validation.hasSystemUpdates && validation.restoredServices && validation.restoredServices.length > 0) { console.log(' ' + chalk_1.default.yellow('ℹ ' + messages.config.messages.mcpSystemServicesRestored)); validation.restoredServices.forEach(serviceName => { console.log(' ' + chalk_1.default.gray(`- ${serviceName} (${messages.systemDetector.builtinServices.protected})`)); }); } } } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,也需要重置终端状态 this.resetTerminalState(); console.log(); return; } } async editMcpFunctionConfirmation() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getMcpFunctionConfirmationConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.mcpFunctionConfirmation)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.mcpFunctionConfirmation)); console.log(); try { // 获取所有可用的MCP函数(包括内置和外部) await utils_1.AnimationUtils.showActionAnimation('Detecting and connecting MCP services...', 500); // 使用SystemDetector获取所有工具定义 const { SystemDetector } = await Promise.resolve().then(() => __importStar(require('../../services/system-detector'))); const systemDetector = new SystemDetector(); try { // 先执行完整的系统检测,这会连接所有MCP服务器 const detectionResult = await systemDetector.detectSystem(); // 然后获取所有工具定义 const allToolDefinitions = await systemDetector.getAllToolDefinitions(); if (!allToolDefinitions || allToolDefinitions.length === 0) { console.log(' ' + chalk_1.default.yellow(messages.config.messages.noMcpFunctionsFound)); console.log(' ' + chalk_1.default.gray('Please configure MCP servers first, or check if MCP servers are running.')); // 显示检测到的服务器状态 if (detectionResult.mcpServers && detectionResult.mcpServers.length > 0) { console.log(); console.log(' ' + chalk_1.default.gray('MCP server status:')); detectionResult.mcpServers.forEach(server => { const statusIcon = server.status === 'connected' ? chalk_1.default.green('✓') : chalk_1.default.red('✗'); const toolsInfo = server.tools ? ` (${server.tools.length} tools)` : ' (no tools)'; console.log(` ${statusIcon} ${server.name}: ${server.status}${toolsInfo}`); if (server.error) { console.log(` ${chalk_1.default.gray('Error:')} ${chalk_1.default.red(server.error)}`); } }); } return; } console.log(' ' + chalk_1.default.green(`✓ Found ${allToolDefinitions.length} MCP functions`)); // 显示服务器连接状态 if (detectionResult.mcpServers && detectionResult.mcpServers.length > 0) { const connectedServers = detectionResult.mcpServers.filter(s => s.status === 'connected'); const totalTools = detectionResult.mcpServers.reduce((sum, s) => sum + (s.tools?.length || 0), 0); console.log(' ' + chalk_1.default.gray(`Connected ${connectedServers.length}/${detectionResult.mcpServers.length} servers, ${totalTools} tools`)); } console.log(); // 创建复选框选项 const checkboxOptions = allToolDefinitions.map(toolDef => { const functionName = toolDef.function.name; const description = toolDef.function.description || 'No description available'; // 提取服务器名(从函数名中) const serverName = functionName.includes('_') ? functionName.split('_')[0] : 'unknown'; return { name: `[${serverName}] ${functionName} - ${description.length > 50 ? description.substring(0, 50) + '...' : description}`, value: functionName, checked: currentConfig[functionName] === true }; }); // 显示当前配置状态 const confirmedFunctions = Object.keys(currentConfig).filter(key => currentConfig[key] === true); if (confirmedFunctions.length > 0) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${confirmedFunctions.length} ${messages.config.labels.configured}`)); confirmedFunctions.forEach(funcName => { console.log(' ' + chalk_1.default.green('✓ ') + chalk_1.default.gray(funcName)); }); } else { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${messages.config.labels.notConfigured}`)); } console.log(); // 显示操作说明 console.log(' ' + chalk_1.default.yellow(messages.config.messages.mcpFunctionConfirmationInstructions)); console.log(); // 使用复选框让用户选择 const selectedFunctions = await (0, prompts_1.checkbox)({ message: ' ' + messages.config.prompts.mcpFunctionConfirmationPrompt + ':', choices: checkboxOptions, pageSize: 10, loop: false, // 禁用无限滚动 validate: (answer) => { // 允许空选择,表示所有函数都不需要确认 return true; }, // 添加自定义指令 instructions: false // 禁用默认指令,我们已经显示了自定义指令 }); // 重置终端状态 this.resetTerminalState(); // 构建新的配置 const newConfig = {}; // 先将所有函数设为不需要确认 allToolDefinitions.forEach(toolDef => { const functionName = toolDef.function.name; newConfig[functionName] = false; }); // 然后将选中的函数设为需要确认 selectedFunctions.forEach(functionName => { newConfig[functionName] = true; }); // 保存配置 await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveMcpFunctionConfirmationConfig(newConfig); // 显示保存结果 console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.mcpFunctionConfirmationSaved)); if (selectedFunctions.length > 0) { console.log(' ' + chalk_1.default.gray(`${selectedFunctions.length} functions need to be confirmed manually.`)); selectedFunctions.forEach(funcName => { console.log(' ' + chalk_1.default.green('✓ ') + chalk_1.default.white(funcName)); }); } else { console.log(' ' + chalk_1.default.gray('All MCP functions will execute automatically without confirmation.')); } // 清理SystemDetector资源 await systemDetector.cleanup(); } catch (mcpError) { console.log(' ' + chalk_1.default.yellow(`Failed to retrieve MCP function list: ${mcpError instanceof Error ? mcpError.message : String(mcpError)}`)); console.log(' ' + chalk_1.default.gray('Please ensure that the MCP service is configured correctly and the server is running.')); return; } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,也需要重置终端状态 this.resetTerminalState(); console.log(); return; } } async editMaxToolCalls() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.maxToolCalls)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.maxToolCalls)); if (currentConfig.maxToolCalls) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentConfig.maxToolCalls}`)); } console.log(); try { const maxToolCalls = await components_1.NativeInput.number(' ' + messages.config.prompts.maxToolCallsInput + ':', currentConfig.maxToolCalls || parseInt(messages.config.prompts.maxToolCallsPlaceholder), 1, 100); if (maxToolCalls) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveMaxToolCalls(maxToolCalls); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,直接返回 console.log(); return; } } async editRole() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.role)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.role)); if (currentConfig.role) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: `)); console.log(' ' + chalk_1.default.gray(currentConfig.role.split('\n').join('\n '))); } console.log(); console.log(' ' + chalk_1.default.gray(messages.config.messages.roleEditorPrompt)); try { const role = await (0, prompts_1.editor)({ message: ' ' + messages.config.prompts.roleInput + ':', default: currentConfig.role || messages.config.prompts.rolePlaceholder, validate: (input) => { if (!input.trim()) { return messages.config.messages.invalidInput; } return true; } }); // 重置终端状态,防止影响后续交互 this.resetTerminalState(); if (role && role.trim()) { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveRole(role.trim()); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { // 用户按 ESC 或 Ctrl+C 取消输入,也需要重置终端状态 this.resetTerminalState(); console.log(); return; } } /** * 重置终端状态,防止editor等外部工具影响后续交互 */ resetTerminalState() { // 恢复光标显示 process.stdout.write('\x1B[?25h'); // 确保stdin处于正确状态,让InteractiveMenu能正常工作 if (process.stdin.isTTY) { process.stdin.setRawMode(false); process.stdin.pause(); // 立即resume,让后续的InteractiveMenu可以正常接管 process.stdin.resume(); } } async viewCurrentConfig() { const messages = language_1.languageService.getMessages(); console.log(' ' + chalk_1.default.cyan.bold(messages.config.messages.currentConfig)); console.log(' ' + chalk_1.default.gray('─'.repeat(40))); console.log(); await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.loading, 0); const config = storage_1.StorageService.getApiConfig(); if (!storage_1.StorageService.hasConfig()) { console.log(' ' + chalk_1.default.yellow(messages.config.messages.noConfigFound)); return; } // 显示配置状态 this.displayConfigItem(messages.config.labels.baseUrl, config.baseUrl, config.baseUrl ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.apiKey, config.apiKey ? utils_1.StringUtils.maskApiKey(config.apiKey) : undefined, config.apiKey ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.model, config.model, config.model ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.contextTokens, config.contextTokens?.toString(), config.contextTokens ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.maxConcurrency, config.maxConcurrency?.toString(), config.maxConcurrency ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.maxToolCalls, config.maxToolCalls?.toString(), config.maxToolCalls ? messages.config.labels.configured : messages.config.labels.notConfigured); this.displayConfigItem(messages.config.labels.role, config.role, config.role ? messages.config.labels.configured : messages.config.labels.notConfigured); const mcpConfig = storage_1.StorageService.getMcpConfig(); const serverNames = Object.keys(mcpConfig.mcpServers); const hasMcpServers = serverNames.length > 0; let mcpDisplayValue; if (hasMcpServers) { // 显示服务器名称列表,如果太多则显示前几个 if (serverNames.length <= 3) { mcpDisplayValue = serverNames.join(', '); } else { mcpDisplayValue = `${serverNames.slice(0, 2).join(', ')} +${serverNames.length - 2} more`; } } // MCP配置需要特殊处理,显示更详细的信息 if (hasMcpServers) { this.displayMcpConfigItem(messages.config.labels.mcpConfig, mcpConfig, messages.config.labels.configured); } else { this.displayConfigItem(messages.config.labels.mcpConfig, mcpDisplayValue, messages.config.labels.notConfigured); } // 显示MCP函数确认配置 const mcpFunctionConfig = storage_1.StorageService.getMcpFunctionConfirmationConfig(); const confirmedFunctions = Object.keys(mcpFunctionConfig).filter(key => mcpFunctionConfig[key] === true); let mcpFunctionDisplayValue; if (confirmedFunctions.length > 0) { if (confirmedFunctions.length <= 3) { mcpFunctionDisplayValue = confirmedFunctions.join(', '); } else { mcpFunctionDisplayValue = `${confirmedFunctions.slice(0, 2).join(', ')} +${confirmedFunctions.length - 2} more`; } } this.displayConfigItem(messages.config.labels.mcpFunctionConfirmation, mcpFunctionDisplayValue, confirmedFunctions.length > 0 ? messages.config.labels.configured : messages.config.labels.notConfigured); const terminalSensitiveWords = config.terminalSensitiveWords || []; let terminalWordsDisplayValue; if (terminalSensitiveWords.length > 0) { if (terminalSensitiveWords.length <= 5) { terminalWordsDisplayValue = terminalSensitiveWords.join(', '); } else { terminalWordsDisplayValue = `${terminalSensitiveWords.slice(0, 5).join(', ')} +${terminalSensitiveWords.length - 5} more`; } } this.displayConfigItem(messages.config.labels.terminalSensitiveWords, terminalWordsDisplayValue, terminalSensitiveWords.length > 0 ? messages.config.labels.configured : messages.config.labels.notConfigured); console.log(); // 显示配置完整性状态 const validation = storage_1.StorageService.validateApiConfig(); if (validation.isValid) { console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.allConfigured)); } else { console.log(' ' + chalk_1.default.yellow(`⚠ Missing: ${validation.missing.join(', ')}`)); } } displayConfigItem(label, value, status) { const statusColor = value ? chalk_1.default.green : chalk_1.default.yellow; console.log(' ' + chalk_1.default.white.bold(label + ':')); if (value) { // 对于多行内容,特别是role,进行特殊处理 if (label.includes('角色') || label.includes('Role')) { console.log(' ' + chalk_1.default.gray('Value: ')); const lines = value.split('\n'); lines.forEach(line => { console.log(' ' + chalk_1.default.white(line)); }); } else { console.log(' ' + chalk_1.default.gray('Value: ') + chalk_1.default.white(value)); } } else { console.log(' ' + chalk_1.default.gray('Value: ') + chalk_1.default.gray('(not set)')); } console.log(' ' + chalk_1.default.gray('Status: ') + statusColor(status)); console.log(); } displayMcpConfigItem(label, mcpConfig, status) { const statusColor = chalk_1.default.green; const messages = language_1.languageService.getMessages(); console.log(' ' + chalk_1.default.white.bold(label + ':')); console.log(' ' + chalk_1.default.gray('Servers: ')); // 显示每个MCP服务器的详细信息 Object.entries(mcpConfig.mcpServers).forEach(([serverName, serverConfig]) => { // 判断是否为系统自带服务 const isBuiltIn = serverConfig.transport === 'builtin' || (serverName === 'file-system' && serverConfig.description?.includes('Unified file system service')); const serverIcon = isBuiltIn ? chalk_1.default.green('●') : chalk_1.default.cyan('●'); const serverLabel = isBuiltIn ? chalk_1.default.white.bold(serverName) + chalk_1.default.gray(' (' + messages.systemDetector.builtinServices.name + ')') : chalk_1.default.white.bold(serverName); console.log(' ' + serverIcon + ' ' + serverLabel); // 智能检测服务器类型并显示相应信息 if (serverConfig.transport === 'builtin') { // 内置服务 console.log(' ' + chalk_1.default.gray('Type: ') + chalk_1.default.green('BUILTIN')); console.log(' ' + chalk_1.default.gray('Status: ') + chalk_1.default.green(messages.systemDetector.builtinServices.running)); } else if (serverConfig.url) { // HTTP/HTTPS类型的服务器 console.log(' ' + chalk_1.default.gray('Type: ') + chalk_1.default.white('HTTP')); console.log(' ' + chalk_1.default.gray('URL: ') + chalk_1.default.white(serverConfig.url)); } else if (serverConfig.command) { // STDIO类型的服务器 console.log(' ' + chalk_1.default.gray('Type: ') + chalk_1.default.white('STDIO')); if (!isBuiltIn) { // 只有非系统服务才显示详细的command和args console.log(' ' + chalk_1.default.gray('Command: ') + chalk_1.default.white(serverConfig.command)); if (serverConfig.args && Array.isArray(serverConfig.args)) { console.log(' ' + chalk_1.default.gray('Args: ') + chalk_1.default.white(serverConfig.args.join(' '))); } } } else if (serverConfig.transport) { // 其他传输类型 console.log(' ' + chalk_1.default.gray('Type: ') + chalk_1.default.white(serverConfig.transport.toUpperCase())); } else { // 未知类型,显示原始配置 console.log(' ' + chalk_1.default.gray('Type: ') + chalk_1.default.yellow('Unknown')); } // 显示描述信息 if (serverConfig.description) { console.log(' ' + chalk_1.default.gray('Description: ') + chalk_1.default.white(serverConfig.description)); } // 显示其他配置信息(排除已经显示的主要字段) const excludeKeys = ['url', 'command', 'args', 'transport', 'description']; const extraConfig = Object.entries(serverConfig).filter(([key]) => !excludeKeys.includes(key)); if (extraConfig.length > 0 && !isBuiltIn) { // 系统自带服务不显示复杂的配置细节 extraConfig.forEach(([key, value]) => { let displayValue = typeof value === 'object' ? JSON.stringify(value) : String(value); // 如果是token类似的敏感信息,进行部分隐藏 if (key.toLowerCase().includes('token') || key.toLowerCase().includes('key') || key.toLowerCase().includes('password')) { displayValue = displayValue.length > 10 ? displayValue.substring(0, 8) + '...' : displayValue; } console.log(' ' + chalk_1.default.gray(`${key}: `) + chalk_1.default.white(displayValue)); }); } }); console.log(' ' + chalk_1.default.gray('Status: ') + statusColor(status)); console.log(); } /** * 等待用户按Enter键,避免与InteractiveMenu的终端状态冲突 */ async waitForEnter() { return new Promise((resolve) => { console.log(' ' + chalk_1.default.gray('Press Enter to continue...')); // 确保stdin处于正确状态 if (process.stdin.isTTY) { process.stdin.setRawMode(true); } process.stdin.resume(); process.stdin.setEncoding('utf8'); const cleanup = () => { // 重要:不要在这里设置setRawMode(false),让InteractiveMenu自己管理 process.stdin.removeListener('data', keyHandler); process.stdin.pause(); }; const keyHandler = (key) => { switch (key) { case '\r': // 回车 case '\n': cleanup(); resolve(); break; case '\u0003': // Ctrl+C cleanup(); process.exit(); break; // 忽略其他按键,只响应Enter和Ctrl+C } }; process.stdin.on('data', keyHandler); }); } async editTerminalSensitiveWords() { const messages = language_1.languageService.getMessages(); const currentConfig = storage_1.StorageService.getApiConfig(); const currentWords = currentConfig.terminalSensitiveWords || []; console.log(' ' + chalk_1.default.cyan.bold(messages.config.menuOptions.terminalSensitiveWords)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.terminalSensitiveWords)); if (currentWords.length > 0) { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${currentWords.length} words configured`)); currentWords.slice(0, 5).forEach(word => { console.log(' ' + chalk_1.default.gray(`- ${word}`)); }); if (currentWords.length > 5) { console.log(' ' + chalk_1.default.gray('...')); } } else { console.log(' ' + chalk_1.default.gray(`${messages.config.labels.status}: ${messages.config.labels.notConfigured}`)); } console.log(); console.log(' ' + chalk_1.default.gray(messages.config.messages.terminalSensitiveWordsEditorPrompt)); try { const wordsString = await (0, prompts_1.editor)({ message: ' ' + messages.config.prompts.terminalSensitiveWordsInput + ':', default: currentWords.join('\n'), validate: (input) => { return true; } }); this.resetTerminalState(); if (wordsString !== undefined) { const newWords = wordsString.split('\n').map(w => w.trim()).filter(w => w.length > 0); await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.saving); storage_1.StorageService.saveTerminalSensitiveWords(newWords); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configSaved)); } } catch (error) { this.resetTerminalState(); console.log(); return; } } async resetConfig() { const messages = language_1.languageService.getMessages(); console.log(' ' + chalk_1.default.yellow.bold(messages.config.menuOptions.resetConfig)); console.log(' ' + chalk_1.default.gray(messages.config.menuDescription.resetConfig)); console.log(); const confirmationChoices = [ { name: messages.config.actions.yes, value: 'yes' }, { name: messages.config.actions.no, value: 'no' } ]; const confirmation = await components_1.InteractiveMenu.show({ message: ' ' + messages.config.prompts.confirmReset, choices: confirmationChoices }); if (confirmation === 'yes') { await utils_1.AnimationUtils.showActionAnimation(messages.config.actions.resetting); storage_1.StorageService.clearConfig(); console.log(' ' + chalk_1.default.green('✓ ' + messages.config.messages.configReset)); } else { console.log(' ' + chalk_1.default.gray(messages.config.messages.resetCancelled)); } } } exports.ConfigPage = ConfigPage; //# sourceMappingURL=config.js.map