openai-cli-unofficial
Version:
A powerful OpenAI CLI Coding Agent built with TypeScript
330 lines • 13.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WelcomeScreen = 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 update_checker_1 = require("../../services/update-checker");
const animation_1 = require("../../utils/animation");
const menu_1 = require("../components/menu");
const config_1 = require("../pages/config");
const help_1 = require("../pages/help");
const main_1 = require("../pages/main");
const packageJson = require('../../../package.json');
class WelcomeScreen {
constructor() {
this.gradients = animation_1.AnimationUtils.getGradients();
}
/**
* 从 package.json 读取版本信息
*/
getVersion() {
try {
return packageJson.version || '0.0.0';
}
catch (error) {
console.debug('Failed to read version from package.json:', error);
return '0.0.0';
}
}
async show() {
await this.showSplashScreen();
// 在显示主菜单前进行更新检查
await this.checkForUpdates();
await this.showMainMenu();
}
/**
* 检查更新并提示用户
*/
async checkForUpdates() {
try {
const updateInfo = await update_checker_1.updateChecker.checkForUpdates();
if (updateInfo.hasUpdate) {
const shouldUpdate = await update_checker_1.updateChecker.showUpdatePrompt(updateInfo);
if (shouldUpdate) {
await update_checker_1.updateChecker.performUpdate();
// 显示按键继续提示
const messages = language_1.languageService.getMessages();
await (0, prompts_1.input)({
message: ' ' + chalk_1.default.gray(messages.welcome.actions.pressEnter)
});
}
}
}
catch (error) {
// 静默处理更新检查错误,不影响正常启动
console.debug('Update check failed:', error);
}
}
async showSplashScreen() {
// 隐藏光标减少闪烁
process.stdout.write('\x1B[?25l');
animation_1.AnimationUtils.forceClearScreen();
// 显示加载动画
await this.showLoadingAnimation();
// 显示大标题
this.showGrandTitle();
// 显示副标题和描述
this.showDescription();
// 显示装饰性分割线
this.showDivider();
// 恢复光标
process.stdout.write('\x1B[?25h');
}
async showLoadingAnimation() {
const messages = language_1.languageService.getMessages();
// 使用统一的动画工具
const controller = animation_1.AnimationUtils.showLoadingAnimation({
text: messages.welcome.starting,
interval: 80
});
await new Promise(resolve => setTimeout(resolve, 100));
controller.stop();
}
showGrandTitle() {
// 创建更大气的标题
const title1 = figlet_1.default.textSync('OPENAI', {
font: 'ANSI Shadow',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 120,
whitespaceBreak: true
});
const title2 = figlet_1.default.textSync('CLI AGENT', {
font: 'ANSI Shadow',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 120,
whitespaceBreak: true
});
// 使用多层渐变效果
console.log(this.gradients.primary(title1));
console.log(this.gradients.accent(title2));
console.log();
// 添加版本信息和徽章
const versionBadge = ` [ v${this.getVersion()} ] `;
const statusBadge = ' [ BETA ] ';
const aiBadge = ' [ AI-POWERED ] ';
console.log(' ' +
chalk_1.default.bgBlue.white.bold(versionBadge) + ' ' +
chalk_1.default.bgGreen.white.bold(statusBadge) + ' ' +
chalk_1.default.bgMagenta.white.bold(aiBadge));
console.log();
}
showDescription() {
const messages = language_1.languageService.getMessages();
// 主标题和副标题
console.log(' ' + this.gradients.primary(messages.welcome.tagline));
console.log(' ' + this.gradients.accent('Github: https://github.com/MayDay-wpf/openai-cli'));
console.log();
}
showDivider() {
console.log(' ' + chalk_1.default.gray('─'.repeat(60)));
console.log();
}
async showMainMenu() {
const messages = language_1.languageService.getMessages();
const choices = [
{
name: messages.welcome.menuOptions.start,
value: 'start',
description: messages.welcome.menuDescription.start
},
{
name: messages.welcome.menuOptions.config,
value: 'config',
description: messages.welcome.menuDescription.config
},
{
name: messages.welcome.menuOptions.language,
value: 'language',
description: messages.welcome.menuDescription.language
},
{
name: messages.welcome.menuOptions.help,
value: 'help',
description: messages.welcome.menuDescription.help
},
{
name: messages.welcome.menuOptions.exit,
value: 'exit',
description: messages.welcome.menuDescription.exit
}
];
const action = await menu_1.InteractiveMenu.show({
message: messages.welcome.menuPrompt + ':',
choices
});
await this.handleMenuSelection(action);
}
async handleMenuSelection(action) {
const messages = language_1.languageService.getMessages();
console.log();
switch (action) {
case 'start':
try {
// 检查配置是否完整
const configValidation = storage_1.StorageService.validateApiConfig();
if (!configValidation.isValid) {
// 显示配置不完整的警告
const shouldGoToConfig = await this.showConfigWarning(configValidation.missing);
if (shouldGoToConfig) {
// 用户选择配置,跳转到配置页面
const configPage = new config_1.ConfigPage();
await configPage.show();
// 配置完成后确保终端状态重置
await this.ensureTerminalReset();
// 重新显示欢迎页面
await this.show();
}
else {
// 用户选择返回主菜单,清屏并重新显示整个欢迎页面
await this.show();
}
return;
}
// 配置完整,启动主页面
const mainPage = new main_1.MainPage();
await mainPage.show();
// 确保MainPage实例被正确清理
mainPage.destroy();
// 对话页面结束后,直接重新显示欢迎页面,不需要等待用户按键
await this.show();
}
catch (error) {
console.error(' ' + chalk_1.default.red('对话页面出现错误:'), error);
// 出错时也重新显示欢迎页面
await this.show();
}
return;
case 'config':
const configPage = new config_1.ConfigPage();
await configPage.show();
// 配置页面完成后,确保终端状态完全重置
await this.ensureTerminalReset();
// 重新显示完整的欢迎页
await this.show();
return;
case 'language':
await this.handleLanguageSelection();
return; // 直接返回,语言切换后会重新显示界面
case 'help':
const helpPage = new help_1.HelpPage();
await helpPage.show();
// 帮助页面结束后,等待用户按键继续
console.log();
await (0, prompts_1.input)({
message: ' ' + chalk_1.default.gray(messages.welcome.actions.pressEnter)
});
// 强制清屏后重新显示完整的欢迎页面
process.stdout.write('\x1B[2J\x1B[3J\x1B[H');
console.clear();
process.stdout.write('\x1Bc');
await this.show();
break;
case 'exit':
await this.showExitAnimation();
return;
default:
console.log(' ' + chalk_1.default.red(messages.welcome.actions.unknownAction));
await this.showMainMenu();
}
}
async handleLanguageSelection() {
const choices = language_1.languageService.createLanguageMenuChoices();
const selectedLanguage = await menu_1.InteractiveMenu.show({
message: 'Select Language / 选择语言:',
choices
});
const currentLanguage = language_1.languageService.getCurrentLanguage();
if (selectedLanguage !== currentLanguage) {
language_1.languageService.setLanguage(selectedLanguage);
const messages = language_1.languageService.getMessages();
await animation_1.AnimationUtils.showActionAnimation(messages.welcome.actions.changingLanguage);
// 重新显示整个界面
await this.show();
}
else {
await this.showMainMenu();
}
}
async showExitAnimation() {
console.log('\n'.repeat(5));
const messages = language_1.languageService.getMessages();
// 显示告别消息
const farewell = figlet_1.default.textSync('GOODBYE', {
font: 'ANSI Shadow',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 80
});
await animation_1.AnimationUtils.showExitAnimation(farewell, messages.welcome.actions.farewell);
process.exit(0);
}
async showConfigWarning(missingItems) {
const messages = language_1.languageService.getMessages();
const configCheck = messages.welcome.configCheck;
// 显示配置警告
console.log();
console.log(' ' + chalk_1.default.yellow.bold(configCheck.incompleteConfig));
console.log();
console.log(' ' + chalk_1.default.gray(configCheck.missingItems));
// 显示缺少的配置项
missingItems.forEach(item => {
let itemName = '';
switch (item) {
case 'baseUrl':
itemName = configCheck.baseUrl;
break;
case 'apiKey':
itemName = configCheck.apiKey;
break;
case 'model':
itemName = configCheck.model;
break;
}
console.log(' ' + chalk_1.default.red(itemName));
});
console.log();
// 显示选择菜单 - 只允许前往配置或返回主菜单
const choices = [
{
name: configCheck.goToConfig,
value: 'config',
description: messages.welcome.menuDescription.config
},
{
name: configCheck.backToMenu,
value: 'back',
description: messages.welcome.menuDescription.backToMenu
}
];
const choice = await menu_1.InteractiveMenu.show({
message: ' ' + configCheck.prompt,
choices
});
return choice === 'config';
}
/**
* 确保终端状态完全重置,防止外部编辑器等工具影响后续交互
*/
async ensureTerminalReset() {
// 恢复光标显示
process.stdout.write('\x1B[?25h');
// 确保stdin处于正确状态
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
process.stdin.pause();
// 短暂延迟确保状态重置完成
await new Promise(resolve => setTimeout(resolve, 100));
process.stdin.resume();
}
}
}
exports.WelcomeScreen = WelcomeScreen;
//# sourceMappingURL=welcome.js.map