openai-cli-unofficial
Version:
A powerful OpenAI CLI Coding Agent built with TypeScript
853 lines • 44.7 kB
JavaScript
;
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