claude-conversation-manager
Version:
A CLI tool for managing Claude Code conversation history with parsing and i18n support
652 lines • 32.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const chalk_1 = __importDefault(require("chalk"));
const inquirer_1 = __importDefault(require("inquirer"));
const date_fns_1 = require("date-fns");
const manager_1 = require("./core/manager");
const memory_1 = require("./core/memory");
const i18n_1 = require("./core/i18n");
const program = new commander_1.Command();
const manager = new manager_1.ConversationManager();
// Utility functions
function formatFileSize(bytes) {
const sizes = ['B', 'KB', 'MB', 'GB'];
if (bytes === 0)
return '0 B';
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}
function formatDate(date) {
return (0, date_fns_1.format)(date, 'yyyy-MM-dd HH:mm:ss');
}
function truncateText(text, maxLength = 80) {
return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
}
function formatRelativeTime(date) {
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
const diffDays = Math.floor(diffHours / 24);
if (diffHours < 1) {
return 'now';
}
else if (diffHours < 24) {
return `${diffHours}h ago`;
}
else if (diffDays < 30) {
return `${diffDays}d ago`;
}
else {
return (0, date_fns_1.format)(date, 'MMM dd');
}
}
function printMemoryResults(results) {
if (results.length === 0) {
console.log(chalk_1.default.yellow('No memory found. Run ccm memory build first, or try a different query.'));
return;
}
console.log(chalk_1.default.bold('Relevant memory:\n'));
results.forEach((result, index) => {
console.log(`${index + 1}. [${result.item.type}] ${result.item.text}`);
console.log(chalk_1.default.gray(` Source: ${result.item.sourceSessionId} (${result.item.sourceFile})`));
});
}
// Commands
program
.name('ccm')
.description('Claude Conversation Manager - Manage your Claude Code conversation history')
.version('2.0.0');
// List conversations
program
.command('list')
.description('List all conversations')
.option('-d, --detailed', 'Show detailed information')
.option('-p, --project <project>', 'Filter by project path')
.option('-c, --corrupted', 'Show only corrupted conversations')
.option('--limit <number>', 'Limit number of results', '50')
.action(async (options) => {
try {
await manager.initialize();
const searchOptions = {};
if (options.project)
searchOptions.project = options.project;
if (options.corrupted)
searchOptions.corrupted = true;
let conversations = await manager.searchConversations(searchOptions);
const limit = parseInt(options.limit);
if (conversations.length > limit) {
conversations = conversations.slice(0, limit);
console.log(chalk_1.default.yellow(`Showing first ${limit} of ${conversations.length} conversations\\n`));
}
if (conversations.length === 0) {
console.log(chalk_1.default.yellow('No conversations found.'));
return;
}
console.log(chalk_1.default.bold(`Found ${conversations.length} conversations:\\n`));
if (options.detailed) {
conversations.forEach((conv, index) => {
console.log(`${index + 1}. ${chalk_1.default.bold(conv.id)}`);
console.log(` Project: ${chalk_1.default.cyan(conv.projectPath)}`);
console.log(` Directory: ${chalk_1.default.gray(conv.workingDirectory)}`);
console.log(` Summary: ${truncateText(conv.summary, 100)}`);
console.log(` Messages: ${conv.messageCount}, Size: ${formatFileSize(conv.fileSize)}`);
console.log(` Created: ${formatDate(conv.created)}, Modified: ${formatDate(conv.modified)}`);
if (conv.gitBranch)
console.log(` Git Branch: ${chalk_1.default.green(conv.gitBranch)}`);
if (conv.isCorrupted)
console.log(` ${chalk_1.default.red('⚠️ CORRUPTED:')} ${conv.corruptionReason}`);
console.log('');
});
}
else {
// Claude -r style format
console.log(chalk_1.default.bold(' Modified Created # Messages Git Branch Summary'));
console.log(chalk_1.default.bold(' Modified Created # Messages Git Branch Summary'));
conversations.forEach((conv, index) => {
const modifiedTime = formatRelativeTime(conv.modified);
const createdTime = formatRelativeTime(conv.created);
const messageCount = conv.messageCount.toString().padStart(3);
const gitBranch = (conv.gitBranch || 'unknown').padEnd(12);
const summary = truncateText(conv.summary, 60);
const line = `${index + 1}. ${modifiedTime.padEnd(10)} ${createdTime.padEnd(10)} ${messageCount} ${gitBranch} ${summary}`;
const projectInfo = ` Project: ${chalk_1.default.cyan(conv.projectPath)} | Directory: ${chalk_1.default.gray(conv.workingDirectory)}`;
if (conv.isCorrupted) {
console.log(chalk_1.default.red('❯ ' + line));
console.log(chalk_1.default.red(projectInfo));
}
else {
console.log(' ' + line);
console.log(chalk_1.default.gray(projectInfo));
}
console.log('');
});
}
}
catch (error) {
console.error(chalk_1.default.red('Error listing conversations:'), error);
process.exit(1);
}
});
// Search conversations
program
.command('search <keyword>')
.description('Search conversations by keyword')
.option('-p, --project <project>', 'Filter by project path')
.option('--from <date>', 'Filter from date (YYYY-MM-DD)')
.option('--to <date>', 'Filter to date (YYYY-MM-DD)')
.option('--min-size <bytes>', 'Minimum file size in bytes', parseInt)
.option('--max-size <bytes>', 'Maximum file size in bytes', parseInt)
.action(async (keyword, options) => {
try {
await manager.initialize();
const searchOptions = { keyword };
if (options.project)
searchOptions.project = options.project;
if (options.from)
searchOptions.dateFrom = new Date(options.from);
if (options.to)
searchOptions.dateTo = new Date(options.to);
if (options.minSize)
searchOptions.minSize = options.minSize;
if (options.maxSize)
searchOptions.maxSize = options.maxSize;
const conversations = await manager.searchConversations(searchOptions);
if (conversations.length === 0) {
console.log(chalk_1.default.yellow(`No conversations found matching "${keyword}".`));
return;
}
console.log(chalk_1.default.bold(`Found ${conversations.length} conversations matching "${keyword}":\\n`));
// Claude -r style display
console.log(chalk_1.default.bold(' Modified Created # Messages Git Branch Summary'));
console.log(chalk_1.default.bold(' Modified Created # Messages Git Branch Summary'));
conversations.forEach((conv, index) => {
const modifiedTime = formatRelativeTime(conv.modified);
const createdTime = formatRelativeTime(conv.created);
const messageCount = conv.messageCount.toString().padStart(3);
const gitBranch = (conv.gitBranch || 'unknown').padEnd(12);
const summary = truncateText(conv.summary, 60);
const line = ` ${index + 1}. ${modifiedTime.padEnd(10)} ${createdTime.padEnd(10)} ${messageCount} ${gitBranch} ${summary}`;
const projectInfo = ` Project: ${chalk_1.default.cyan(conv.projectPath)} | Directory: ${chalk_1.default.gray(conv.workingDirectory)}`;
if (conv.isCorrupted) {
console.log(chalk_1.default.red('❯ ' + line));
}
else {
console.log(' ' + line);
}
console.log(chalk_1.default.gray(projectInfo));
console.log('');
});
}
catch (error) {
console.error(chalk_1.default.red('Error searching conversations:'), error);
process.exit(1);
}
});
// Delete conversation
program
.command('delete [conversationId]')
.description('Delete conversation(s) - interactive selection if no ID provided')
.option('--no-backup', 'Skip creating backup before deletion')
.option('-f, --force', 'Force deletion without confirmation')
.option('-c, --corrupted', 'Show only corrupted conversations for deletion')
.action(async (conversationId, options) => {
try {
await manager.initialize();
if (conversationId) {
// Direct deletion by ID (original behavior)
const conversation = await manager.getConversation(conversationId);
if (!conversation) {
console.log(chalk_1.default.red(`Conversation ${conversationId} not found.`));
process.exit(1);
}
// Show conversation info and confirm
console.log(`About to delete conversation:`);
console.log(` ID: ${chalk_1.default.bold(conversationId)}`);
console.log(` Project: ${chalk_1.default.cyan(conversation.metadata.projectPath)}`);
console.log(` Summary: ${truncateText(conversation.metadata.summary, 100)}`);
console.log(` Messages: ${conversation.metadata.messageCount}`);
if (!options.force) {
const { confirmed } = await inquirer_1.default.prompt([{
type: 'confirm',
name: 'confirmed',
message: 'Are you sure you want to delete this conversation?',
default: false
}]);
if (!confirmed) {
console.log('Deletion cancelled.');
return;
}
}
const success = await manager.deleteConversation(conversationId, options.backup);
if (success) {
console.log(chalk_1.default.green(`✓ Conversation ${conversationId} deleted successfully.`));
if (options.backup) {
console.log(chalk_1.default.blue('ℹ Backup created before deletion.'));
}
}
else {
console.log(chalk_1.default.red(`✗ Failed to delete conversation ${conversationId}.`));
process.exit(1);
}
}
else {
// Interactive deletion - show list for selection
const searchOptions = {};
if (options.corrupted) {
searchOptions.corrupted = true;
}
const conversations = await manager.searchConversations(searchOptions);
if (conversations.length === 0) {
console.log(chalk_1.default.yellow('No conversations found.'));
return;
}
// Create choices for inquirer
const choices = conversations.map((conv, index) => {
const modifiedTime = formatRelativeTime(conv.modified);
const status = conv.isCorrupted ? chalk_1.default.red(' [CORRUPTED]') : '';
const summary = truncateText(conv.summary, 60);
const projectInfo = chalk_1.default.gray(`(${conv.projectPath})`);
return {
name: `${modifiedTime.padEnd(10)} ${conv.messageCount.toString().padStart(3)} messages ${summary}${status} ${projectInfo}`,
value: conv.id,
short: conv.id
};
});
choices.push({ name: chalk_1.default.gray('--- Cancel ---'), value: 'cancel', short: 'cancel' });
console.log(chalk_1.default.bold(`\\nSelect conversation(s) to delete:\\n`));
const { selectedConversations } = await inquirer_1.default.prompt([{
type: 'checkbox',
name: 'selectedConversations',
message: 'Select conversations to delete (use space to select, enter to confirm):',
choices,
validate: (input) => {
if (input.length === 0) {
return 'Please select at least one conversation or cancel.';
}
if (input.includes('cancel') && input.length > 1) {
return 'Cannot select cancel with other options.';
}
return true;
}
}]);
if (selectedConversations.includes('cancel') || selectedConversations.length === 0) {
console.log('Deletion cancelled.');
return;
}
// Show selected conversations and confirm
console.log(`\\n${chalk_1.default.bold('Selected conversations for deletion:')}`);
for (const id of selectedConversations) {
const conv = conversations.find(c => c.id === id);
if (conv) {
const status = conv.isCorrupted ? chalk_1.default.red(' [CORRUPTED]') : '';
console.log(` • ${chalk_1.default.cyan(conv.projectPath)} - ${truncateText(conv.summary, 50)}${status}`);
}
}
if (!options.force) {
const { finalConfirmed } = await inquirer_1.default.prompt([{
type: 'confirm',
name: 'finalConfirmed',
message: `Delete ${selectedConversations.length} conversation(s)?`,
default: false
}]);
if (!finalConfirmed) {
console.log('Deletion cancelled.');
return;
}
}
// Delete selected conversations
console.log(`\\n${chalk_1.default.yellow('Deleting conversations...')}`);
const result = await manager.deleteConversations(selectedConversations, options.backup);
if (result.deleted.length > 0) {
console.log(chalk_1.default.green(`✓ Successfully deleted ${result.deleted.length} conversation(s).`));
if (options.backup) {
console.log(chalk_1.default.blue('ℹ Backup created before deletion.'));
}
}
if (result.failed.length > 0) {
console.log(chalk_1.default.red(`✗ Failed to delete ${result.failed.length} conversation(s):`));
result.failed.forEach(id => console.log(` - ${id}`));
}
}
}
catch (error) {
console.error(chalk_1.default.red('Error deleting conversation:'), error);
process.exit(1);
}
});
// Health check
program
.command('health')
.description('Check conversation health and detect issues')
.option('--fix', 'Attempt to fix corrupted conversations')
.action(async (options) => {
try {
await manager.initialize();
console.log(chalk_1.default.bold('Checking conversation health...\\n'));
const stats = await manager.getStorageStats();
console.log(`Total conversations: ${chalk_1.default.bold(stats.totalConversations.toString())}`);
console.log(`Total size: ${chalk_1.default.bold(formatFileSize(stats.totalSize))}`);
console.log(`Projects: ${chalk_1.default.bold(stats.projectCount.toString())}`);
console.log(`Corrupted conversations: ${stats.corruptedCount > 0 ? chalk_1.default.red(stats.corruptedCount.toString()) : chalk_1.default.green('0')}`);
if (stats.largestConversation) {
console.log(`Largest conversation: ${chalk_1.default.yellow(stats.largestConversation.id)} (${formatFileSize(stats.largestConversation.fileSize)})`);
}
if (stats.oldestConversation) {
console.log(`Oldest conversation: ${formatDate(stats.oldestConversation.created)}`);
}
if (stats.corruptedCount > 0) {
console.log(`\\n${chalk_1.default.red('⚠️ Found corrupted conversations!')}`);
const corruptedConversations = await manager.searchConversations({ corrupted: true });
corruptedConversations.forEach((conv, index) => {
console.log(` ${index + 1}. ${conv.id} - ${chalk_1.default.red(conv.corruptionReason)}`);
});
if (options.fix) {
console.log(`\\n${chalk_1.default.yellow('Attempting to repair corrupted conversations...')}`);
const result = await manager.repairCorruptedConversations();
if (result.repaired.length > 0) {
console.log(`${chalk_1.default.green('✓')} Repaired ${result.repaired.length} conversations:`);
result.repaired.forEach(id => console.log(` - ${id}`));
}
if (result.failed.length > 0) {
console.log(`${chalk_1.default.red('✗')} Failed to repair ${result.failed.length} conversations:`);
result.failed.forEach(id => console.log(` - ${id}`));
}
}
else {
console.log(`\\nRun ${chalk_1.default.cyan('ccm health --fix')} to attempt repairs.`);
}
}
else {
console.log(`\\n${chalk_1.default.green('✓ All conversations are healthy!')}`);
}
}
catch (error) {
console.error(chalk_1.default.red('Error during health check:'), error);
process.exit(1);
}
});
// Interactive mode
program
.command('interactive')
.alias('i')
.description('Launch interactive conversation manager')
.action(handleInteractiveMode);
const memory = program
.command('memory')
.description('Build and search lightweight agent memory for the current project');
memory
.command('init')
.description('Initialize .claude-memory in the current project')
.action(async () => {
const memoryManager = new memory_1.MemoryManager(process.cwd());
const result = await memoryManager.init();
console.log(chalk_1.default.green('Memory initialized.'));
console.log(`Project: ${result.projectPath}`);
});
memory
.command('build')
.description('Build memory from Claude Code sessions for the current project')
.action(async () => {
const memoryManager = new memory_1.MemoryManager(process.cwd());
const result = await memoryManager.build();
console.log(chalk_1.default.green('Memory built.'));
console.log(`Sessions scanned: ${result.sessionsScanned}`);
console.log(`Items added: ${result.itemsAdded}`);
console.log(`Memory: ${result.memoryPath}`);
console.log(`Handoff: ${result.handoffPath}`);
});
memory
.command('search <keyword>')
.description('Keyword search local agent memory')
.action(async (keyword) => {
const memoryManager = new memory_1.MemoryManager(process.cwd());
const results = await memoryManager.search(keyword);
printMemoryResults(results);
});
memory
.command('recall <query>')
.description('Recall relevant memory with lightweight local similarity')
.action(async (query) => {
const memoryManager = new memory_1.MemoryManager(process.cwd());
const results = await memoryManager.recall(query);
printMemoryResults(results);
});
memory
.command('handoff')
.description('Print the current agent handoff')
.action(async () => {
const memoryManager = new memory_1.MemoryManager(process.cwd());
console.log(await memoryManager.handoff());
});
async function handleInteractiveAction(action) {
switch (action) {
case 'delete-corrupted':
const corruptedConversations = await manager.searchConversations({ corrupted: true });
if (corruptedConversations.length === 0) {
console.log(chalk_1.default.green(i18n_1.I18n.t('messages.noCorrupted')));
return;
}
console.log(`\n${chalk_1.default.bold.red(i18n_1.I18n.t('messages.corruptedFound', { count: corruptedConversations.length.toString() }))}\n`);
corruptedConversations.forEach((conv, index) => {
console.log(`${index + 1}. ${chalk_1.default.red(conv.id)}`);
console.log(` ${chalk_1.default.red(i18n_1.I18n.t('messages.reason'))} ${conv.corruptionReason}`);
console.log(` Project: ${chalk_1.default.cyan(conv.projectPath)} | Directory: ${chalk_1.default.gray(truncateText(conv.workingDirectory, 50))}`);
console.log(` Summary: ${truncateText(conv.summary, 60)}`);
console.log('');
});
const { confirmDeleteCorrupted } = await inquirer_1.default.prompt([{
type: 'confirm',
name: 'confirmDeleteCorrupted',
message: i18n_1.I18n.t('actions.deleteAll', { count: corruptedConversations.length.toString() }),
default: false
}]);
if (confirmDeleteCorrupted) {
console.log(`\n${chalk_1.default.yellow(i18n_1.I18n.t('messages.deletingCorrupted'))}`);
const corruptedIds = corruptedConversations.map(c => c.id);
const result = await manager.deleteConversations(corruptedIds, true); // with backup
if (result.deleted.length > 0) {
console.log(chalk_1.default.green(`✓ Successfully deleted ${result.deleted.length} corrupted conversation(s).`));
console.log(chalk_1.default.blue(i18n_1.I18n.t('messages.backupCreated')));
}
if (result.failed.length > 0) {
console.log(chalk_1.default.red(`✗ Failed to delete ${result.failed.length} conversation(s):`));
result.failed.forEach(id => console.log(` - ${id}`));
}
}
else {
console.log(i18n_1.I18n.t('messages.deletionCancelled'));
}
break;
case 'list':
const conversations = await manager.listConversations();
if (conversations.length === 0) {
console.log(chalk_1.default.yellow(i18n_1.I18n.t('messages.noConversations')));
return;
}
console.log(chalk_1.default.bold(`\\nFound ${conversations.length} conversations:\\n`));
conversations.slice(0, 20).forEach((conv, index) => {
const status = conv.isCorrupted ? chalk_1.default.red(' [CORRUPTED]') : '';
console.log(`${index + 1}. ${conv.id}${status}`);
console.log(` ${truncateText(conv.summary, 80)}`);
console.log(` Project: ${chalk_1.default.cyan(conv.projectPath)} | Directory: ${chalk_1.default.gray(truncateText(conv.workingDirectory, 60))}`);
console.log(` ${conv.messageCount} messages - ${formatDate(conv.modified)}`);
console.log('');
});
if (conversations.length > 20) {
console.log(chalk_1.default.yellow(`... and ${conversations.length - 20} more. Use 'ccm list' for full output.`));
}
break;
case 'delete':
const allConversations = await manager.listConversations();
if (allConversations.length === 0) {
console.log(chalk_1.default.yellow('No conversations found.'));
return;
}
// Create choices for deletion
const deleteChoices = allConversations.slice(0, 20).map((conv) => {
const modifiedTime = formatRelativeTime(conv.modified);
const status = conv.isCorrupted ? chalk_1.default.red(' [CORRUPTED]') : '';
const summary = truncateText(conv.summary, 50);
const projectInfo = chalk_1.default.gray(`(${conv.projectPath})`);
return {
name: `${modifiedTime.padEnd(10)} ${conv.messageCount.toString().padStart(3)} msgs ${summary}${status} ${projectInfo}`,
value: conv.id,
short: conv.id
};
});
deleteChoices.push({ name: chalk_1.default.gray(i18n_1.I18n.t('actions.cancel')), value: 'cancel', short: 'cancel' });
const { selectedForDeletion } = await inquirer_1.default.prompt([{
type: 'list',
name: 'selectedForDeletion',
message: i18n_1.I18n.t('messages.selectConversation'),
choices: deleteChoices,
pageSize: 15
}]);
if (selectedForDeletion !== 'cancel') {
const conversation = allConversations.find(c => c.id === selectedForDeletion);
if (conversation) {
console.log(`\\n${chalk_1.default.bold('Selected conversation:')}`);
console.log(` Project: ${chalk_1.default.cyan(conversation.projectPath)}`);
console.log(` Summary: ${truncateText(conversation.summary, 80)}`);
console.log(` Messages: ${conversation.messageCount}`);
if (conversation.isCorrupted) {
console.log(` Status: ${chalk_1.default.red('CORRUPTED - ' + conversation.corruptionReason)}`);
}
const { confirmed } = await inquirer_1.default.prompt([{
type: 'confirm',
name: 'confirmed',
message: 'Delete this conversation?',
default: false
}]);
if (confirmed) {
const success = await manager.deleteConversation(selectedForDeletion);
if (success) {
console.log(chalk_1.default.green('✓ Conversation deleted successfully.'));
}
else {
console.log(chalk_1.default.red('✗ Failed to delete conversation.'));
}
}
else {
console.log('Deletion cancelled.');
}
}
}
else {
console.log('Deletion cancelled.');
}
break;
case 'health':
const stats = await manager.getStorageStats();
console.log(`\\n${chalk_1.default.bold('Storage Statistics:')}`);
console.log(`Conversations: ${stats.totalConversations}`);
console.log(`Total size: ${formatFileSize(stats.totalSize)}`);
console.log(`Projects: ${stats.projectCount}`);
console.log(`Corrupted: ${stats.corruptedCount > 0 ? chalk_1.default.red(stats.corruptedCount.toString()) : chalk_1.default.green('0')}`);
break;
case 'backup':
console.log(chalk_1.default.yellow('Creating backup...'));
const backup = await manager.createBackup();
console.log(chalk_1.default.green(`✓ Backup created: ${backup.filename}`));
console.log(`Conversations: ${backup.conversationCount}`);
console.log(`Size: ${formatFileSize(backup.size)}`);
break;
case 'stats':
const storageStats = await manager.getStorageStats();
console.log(`\\n${chalk_1.default.bold('Detailed Storage Statistics:')}`);
console.log(`Total conversations: ${storageStats.totalConversations}`);
console.log(`Total size: ${formatFileSize(storageStats.totalSize)}`);
console.log(`Number of projects: ${storageStats.projectCount}`);
console.log(`Corrupted conversations: ${storageStats.corruptedCount}`);
if (storageStats.largestConversation) {
console.log(`\\nLargest conversation:`);
console.log(` ID: ${storageStats.largestConversation.id}`);
console.log(` Size: ${formatFileSize(storageStats.largestConversation.fileSize)}`);
console.log(` Messages: ${storageStats.largestConversation.messageCount}`);
}
break;
}
}
// Error handling
process.on('uncaughtException', (error) => {
console.error(chalk_1.default.red('Uncaught exception:'), error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error(chalk_1.default.red('Unhandled rejection at:'), promise, 'reason:', reason);
process.exit(1);
});
// Parse command line arguments
program.parse();
// Launch interactive mode if no command provided
if (!process.argv.slice(2).length) {
console.log(chalk_1.default.blue('🚀 Starting Claude Conversation Manager in interactive mode...\n'));
// Launch interactive mode directly
handleInteractiveMode();
}
async function handleInteractiveMode() {
try {
await manager.initialize();
while (true) {
console.clear();
console.log(chalk_1.default.bold.blue(i18n_1.I18n.t('title') + '\n'));
console.log(chalk_1.default.gray(i18n_1.I18n.t('subtitle') + '\n'));
const { action } = await inquirer_1.default.prompt([{
type: 'list',
name: 'action',
message: 'What would you like to do?',
choices: [
{ name: i18n_1.I18n.t('menu.list'), value: 'list' },
{ name: i18n_1.I18n.t('menu.delete'), value: 'delete' },
{ name: i18n_1.I18n.t('menu.deleteCorrupted'), value: 'delete-corrupted' },
{ name: i18n_1.I18n.t('menu.stats'), value: 'stats' },
{ name: i18n_1.I18n.t('menu.health'), value: 'health' },
{ name: i18n_1.I18n.t('menu.backup'), value: 'backup' },
{ name: `🌐 Language/语言 (${i18n_1.I18n.getLanguage().toUpperCase()})`, value: 'language' },
{ name: i18n_1.I18n.t('menu.exit'), value: 'exit' }
]
}]);
if (action === 'exit') {
console.log(chalk_1.default.green(i18n_1.I18n.t('messages.goodbye')));
process.exit(0);
}
if (action === 'language') {
await handleLanguageChange();
continue;
}
await handleInteractiveAction(action);
// Wait for user input before continuing
await inquirer_1.default.prompt([{
type: 'input',
name: 'continue',
message: chalk_1.default.gray(i18n_1.I18n.t('messages.pressEnter'))
}]);
}
}
catch (error) {
console.error(chalk_1.default.red('Error in interactive mode:'), error);
process.exit(1);
}
}
async function handleLanguageChange() {
const { language } = await inquirer_1.default.prompt([{
type: 'list',
name: 'language',
message: 'Select language / 选择语言:',
choices: [
{ name: 'English', value: 'en' },
{ name: '中文', value: 'zh' },
{ name: '← Back / 返回', value: 'back' }
]
}]);
if (language !== 'back') {
i18n_1.I18n.setLanguage(language);
console.log(chalk_1.default.green(`Language changed to ${language === 'en' ? 'English' : '中文'}`));
}
}
//# sourceMappingURL=cli.js.map