UNPKG

@spyder1211/cc-history

Version:
274 lines 13.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UI = void 0; const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); class UI { /** * メインメニューを表示 */ async showMainMenu(threads, stats) { while (true) { console.clear(); this.showHeader(); this.showMessageList(threads); this.showStats(stats); const { action } = await inquirer_1.default.prompt([ { type: 'list', name: 'action', message: 'Select an option:', choices: [ ...threads.map((thread, index) => ({ name: this.formatMessageChoice(thread, index + 1), value: `message_${index}` })), new inquirer_1.default.Separator(), { name: 'Exit', value: 'quit' } ], pageSize: 15 } ]); if (action === 'quit') { break; } if (action.startsWith('message_')) { const index = parseInt(action.split('_')[1]); await this.showMessageDetail(threads[index]); } } } /** * ヘッダーを表示 */ showHeader() { const today = new Date().toISOString().split('T')[0]; console.log(chalk_1.default.cyan('┌─────────────────────────────────────────────────────────────────────────────────┐')); console.log(chalk_1.default.cyan(`│ Claude Code Message History - ${today} │`)); console.log(chalk_1.default.cyan('└─────────────────────────────────────────────────────────────────────────────────┘')); console.log(''); } /** * メッセージ一覧を表示 */ showMessageList(threads) { if (threads.length === 0) { console.log(chalk_1.default.yellow('No messages found for today.')); return; } threads.forEach((thread, index) => { const time = thread.startTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); const projectName = this.getProjectName(thread.user.cwd); const content = this.truncateMessage(thread.user.message.content, 60); console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.blue(time)} ${chalk_1.default.green(`[${projectName}]`)}`); console.log(` ${chalk_1.default.white('💬')} ${content}`); console.log(` ${chalk_1.default.cyan('🔄')} ${thread.responses.length} exchanges | ${chalk_1.default.magenta('🛠️')} ${thread.tools} tools | ${chalk_1.default.yellow('💰')} $${thread.cost.toFixed(6)}`); console.log(''); }); } /** * 統計情報を表示 */ showStats(stats) { console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); console.log(''); console.log(chalk_1.default.bold('📈 Today\'s Statistics:')); console.log(` ${chalk_1.default.blue('👤')} User messages: ${stats.userMessages}`); console.log(` ${chalk_1.default.cyan('🔄')} Total exchanges: ${stats.totalExchanges} (avg ${(stats.totalExchanges / Math.max(stats.userMessages, 1)).toFixed(1)}/question)`); console.log(` ${chalk_1.default.magenta('🛠️')} Tools used: ${stats.toolsUsed}`); console.log(` ${chalk_1.default.white('🔢')} Total tokens: input ${stats.totalTokens.input} | output ${stats.totalTokens.output} | cache ${stats.totalTokens.cacheCreation + stats.totalTokens.cacheRead}`); console.log(` ${chalk_1.default.yellow('💰')} Estimated cost: $${stats.totalCost.toFixed(5)}`); if (stats.userMessages > 0) { const startTime = stats.startTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }); const endTime = stats.endTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }); console.log(` ${chalk_1.default.gray('⏰')} Active time: ${startTime} - ${endTime}`); } console.log(''); } /** * メッセージ詳細を表示 */ async showMessageDetail(thread) { while (true) { console.clear(); this.showDetailHeader(thread); this.showUserMessage(thread); this.showAssistantResponses(thread); this.showThreadStats(thread); const { action } = await inquirer_1.default.prompt([ { type: 'list', name: 'action', message: 'Select an option:', choices: [ { name: 'Back', value: 'back' }, { name: 'Exit', value: 'quit' } ] } ]); if (action === 'back') { break; } if (action === 'quit') { process.exit(0); } } } /** * 詳細ヘッダーを表示 */ showDetailHeader(thread) { const time = thread.startTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); const date = thread.startTime.toISOString().split('T')[0]; console.log(chalk_1.default.cyan('┌─────────────────────────────────────────────────────────────────────────────────┐')); console.log(chalk_1.default.cyan(`│ Message Details - ${date} ${time} │`)); console.log(chalk_1.default.cyan('└─────────────────────────────────────────────────────────────────────────────────┘')); console.log(''); } /** * ユーザメッセージを表示 */ showUserMessage(thread) { const projectName = this.getProjectName(thread.user.cwd); console.log(chalk_1.default.bold(`📝 User Message [${projectName}]:`)); console.log(chalk_1.default.white(thread.user.message.content)); console.log(''); } /** * アシスタントの応答を表示 */ showAssistantResponses(thread) { console.log(chalk_1.default.bold(`🤖 Assistant Response History (${thread.responses.length} exchanges):`)); console.log(''); thread.responses.forEach((response, index) => { const time = new Date(response.timestamp).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); const usage = response.message.usage; const cost = ((usage.input_tokens || 0) * (3.00 / 1000000) + (usage.output_tokens || 0) * (15.00 / 1000000) + ((usage.cache_creation_input_tokens || 0) + (usage.cache_read_input_tokens || 0)) * (3.75 / 1000000)); console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.blue(time)} ${this.getResponseTypeIcon(response.message.content)}`); // 応答内容を表示 this.showResponseContent(response.message.content); console.log(` ${chalk_1.default.gray('📊')} Input: ${usage.input_tokens || 0} | Output: ${usage.output_tokens || 0} | Cache: ${(usage.cache_creation_input_tokens || 0) + (usage.cache_read_input_tokens || 0)} | ${chalk_1.default.yellow('💰')} $${cost.toFixed(6)}`); console.log(''); }); } /** * 応答内容を表示 */ showResponseContent(content) { for (const item of content) { if (item.type === 'text') { console.log(` ${chalk_1.default.white('💬')} ${this.truncateMessage(item.text || '', 100)}`); } else if (item.type === 'tool_use') { console.log(` ${chalk_1.default.magenta('🛠️')} ${item.name}${item.input ? ` - ${this.formatToolInput(item.input)}` : ''}`); } } } /** * スレッド統計を表示 */ showThreadStats(thread) { const duration = Math.round((thread.endTime.getTime() - thread.startTime.getTime()) / 1000); const toolBreakdown = this.getToolBreakdown(thread.responses); console.log(chalk_1.default.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); console.log(''); console.log(chalk_1.default.bold('📈 Question Statistics:')); console.log(` ${chalk_1.default.cyan('🔄')} Total exchanges: ${thread.responses.length}`); console.log(` ${chalk_1.default.magenta('🛠️')} Tools used: ${thread.tools}${toolBreakdown}`); console.log(` ${chalk_1.default.white('🔢')} Total tokens: input ${thread.totalTokens.input} | output ${thread.totalTokens.output} | cache ${thread.totalTokens.cacheCreation + thread.totalTokens.cacheRead}`); console.log(` ${chalk_1.default.yellow('💰')} Estimated cost: $${thread.cost.toFixed(6)}`); console.log(` ${chalk_1.default.gray('⏰')} Processing time: ${duration}s`); console.log(''); } /** * ヘルプを表示 */ showHelp() { console.log(chalk_1.default.bold('Claude Code History Viewer')); console.log(''); console.log('Usage:'); console.log(' cc-history Show today\'s message history'); console.log(' cc-history --help Show this help'); console.log(''); console.log('Features:'); console.log(' • Display today\'s user messages list'); console.log(' • Show detailed view by selecting a message'); console.log(' • Assistant response history and tool usage'); console.log(' • Token usage and cost analysis'); console.log(''); } // ユーティリティメソッド formatMessageChoice(thread, index) { const time = thread.startTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }); const projectName = this.getProjectName(thread.user.cwd); const content = this.truncateMessage(thread.user.message.content, 50); return `${index}. ${time} [${projectName}] ${content}`; } getProjectName(cwd) { const parts = cwd.split('/'); return parts[parts.length - 1] || 'unknown'; } truncateMessage(message, maxLength) { if (message.length <= maxLength) return message; return message.substring(0, maxLength) + '...'; } getResponseTypeIcon(content) { const hasText = content.some(c => c.type === 'text'); const hasTools = content.some(c => c.type === 'tool_use'); if (hasText && hasTools) return '[💬+🛠️]'; if (hasTools) return '[🛠️]'; return '[💬]'; } formatToolInput(input) { if (typeof input === 'string') { return this.truncateMessage(input, 50); } return this.truncateMessage(JSON.stringify(input), 50); } getToolBreakdown(responses) { const tools = {}; for (const response of responses) { const content = response.message.content; if (content && Array.isArray(content)) { for (const item of content) { if (item.type === 'tool_use' && item.name) { tools[item.name] = (tools[item.name] || 0) + 1; } } } } const toolList = Object.entries(tools) .map(([name, count]) => `${name}: ${count}x`) .join(', '); return toolList ? ` (${toolList})` : ''; } } exports.UI = UI; //# sourceMappingURL=ui.js.map