diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 75373db..d9845dd 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -102,6 +102,19 @@ pub async fn get_usage_stats( manager.get_usage_stats(&conversation_id) } +/// Load persisted lifetime stats from store (no bridge required) +#[tauri::command] +pub async fn get_persisted_stats(app: AppHandle) -> Result { + let mut stats = UsageStats::new(); + + // Load persisted stats if available + if let Some(persisted) = crate::stats::load_stats(&app).await { + stats.apply_persisted(persisted); + } + + Ok(stats) +} + #[tauri::command] pub async fn validate_directory( path: String, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e7b4f98..0dc2487 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -95,6 +95,7 @@ pub fn run() { get_config, save_config, get_usage_stats, + get_persisted_stats, load_saved_achievements, answer_question, send_windows_notification, diff --git a/src-tauri/src/stats.rs b/src-tauri/src/stats.rs index 189ab71..5ac8be3 100644 --- a/src-tauri/src/stats.rs +++ b/src-tauri/src/stats.rs @@ -3,6 +3,7 @@ use chrono::{Local, Timelike}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::time::Instant; +use tauri_plugin_store::StoreExt; #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UsageStats { @@ -241,6 +242,111 @@ pub struct StatsUpdateEvent { pub stats: UsageStats, } +/// Serializable struct for persisting only lifetime (total) stats +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct PersistedStats { + pub total_input_tokens: u64, + pub total_output_tokens: u64, + pub total_cost_usd: f64, + pub messages_exchanged: u64, + pub code_blocks_generated: u64, + pub files_edited: u64, + pub files_created: u64, + pub tools_usage: HashMap, + pub sessions_started: u64, + pub consecutive_days: u64, + pub total_days_used: u64, + pub morning_sessions: u64, + pub night_sessions: u64, + pub last_session_date: Option, +} + +impl From<&UsageStats> for PersistedStats { + fn from(stats: &UsageStats) -> Self { + PersistedStats { + total_input_tokens: stats.total_input_tokens, + total_output_tokens: stats.total_output_tokens, + total_cost_usd: stats.total_cost_usd, + messages_exchanged: stats.messages_exchanged, + code_blocks_generated: stats.code_blocks_generated, + files_edited: stats.files_edited, + files_created: stats.files_created, + tools_usage: stats.tools_usage.clone(), + sessions_started: stats.sessions_started, + consecutive_days: stats.consecutive_days, + total_days_used: stats.total_days_used, + morning_sessions: stats.morning_sessions, + night_sessions: stats.night_sessions, + last_session_date: stats.last_session_date.clone(), + } + } +} + +impl UsageStats { + /// Apply persisted stats to restore lifetime totals + pub fn apply_persisted(&mut self, persisted: PersistedStats) { + self.total_input_tokens = persisted.total_input_tokens; + self.total_output_tokens = persisted.total_output_tokens; + self.total_cost_usd = persisted.total_cost_usd; + self.messages_exchanged = persisted.messages_exchanged; + self.code_blocks_generated = persisted.code_blocks_generated; + self.files_edited = persisted.files_edited; + self.files_created = persisted.files_created; + self.tools_usage = persisted.tools_usage; + self.sessions_started = persisted.sessions_started; + self.consecutive_days = persisted.consecutive_days; + self.total_days_used = persisted.total_days_used; + self.morning_sessions = persisted.morning_sessions; + self.night_sessions = persisted.night_sessions; + self.last_session_date = persisted.last_session_date; + } +} + +/// Save lifetime stats to persistent store +pub async fn save_stats(app: &tauri::AppHandle, stats: &UsageStats) -> Result<(), String> { + let store = app.store("stats.json").map_err(|e| e.to_string())?; + + let persisted = PersistedStats::from(stats); + + println!("Saving stats: {:?}", persisted); + + store.set( + "lifetime_stats", + serde_json::to_value(persisted).map_err(|e| e.to_string())?, + ); + store.save().map_err(|e| e.to_string())?; + + println!("Stats saved successfully"); + Ok(()) +} + +/// Load lifetime stats from persistent store +pub async fn load_stats(app: &tauri::AppHandle) -> Option { + println!("Loading stats from store..."); + + let store = match app.store("stats.json") { + Ok(s) => s, + Err(e) => { + println!("Failed to open stats store: {}", e); + return None; + } + }; + + if let Some(stats_value) = store.get("lifetime_stats") { + println!("Found lifetime stats in store: {:?}", stats_value); + if let Ok(persisted) = serde_json::from_value::(stats_value.clone()) { + println!("Loaded lifetime stats successfully"); + return Some(persisted); + } else { + println!("Failed to parse lifetime stats"); + } + } else { + println!("No lifetime stats found in store"); + } + + None +} + #[cfg(test)] mod tests { use super::*; diff --git a/src-tauri/src/wsl_bridge.rs b/src-tauri/src/wsl_bridge.rs index e0a6fcd..b1e8f31 100644 --- a/src-tauri/src/wsl_bridge.rs +++ b/src-tauri/src/wsl_bridge.rs @@ -112,7 +112,7 @@ impl WslBridge { return Err("Process already running".to_string()); } - // Load saved achievements when starting a new session + // Load saved achievements and stats when starting a new session let app_clone = app.clone(); let stats = self.stats.clone(); tauri::async_runtime::spawn(async move { @@ -122,7 +122,17 @@ impl WslBridge { "Loaded {} unlocked achievements", achievements.unlocked.len() ); - stats.write().achievements = achievements; + + println!("Loading saved stats..."); + let persisted_stats = crate::stats::load_stats(&app_clone).await; + + let mut stats_guard = stats.write(); + stats_guard.achievements = achievements; + + if let Some(persisted) = persisted_stats { + println!("Applying persisted lifetime stats"); + stats_guard.apply_persisted(persisted); + } }); let working_dir = &options.working_dir; @@ -440,6 +450,18 @@ impl WslBridge { self.session_id = None; self.mcp_config_file = None; // Temp file is automatically deleted when dropped + // Save lifetime stats before resetting session + let stats_snapshot = self.stats.read().clone(); + let app_clone = app.clone(); + tauri::async_runtime::spawn(async move { + println!("Saving stats on session stop..."); + if let Err(e) = crate::stats::save_stats(&app_clone, &stats_snapshot).await { + eprintln!("Failed to save stats: {}", e); + } else { + println!("Stats saved successfully on session stop"); + } + }); + // Reset session stats on explicit disconnect self.stats.write().reset_session(); @@ -733,10 +755,23 @@ fn process_json_line( let current_stats = stats.read().clone(); let stats_event = StatsUpdateEvent { - stats: current_stats, + stats: current_stats.clone(), }; let _ = app.emit("claude:stats", stats_event); + // Save stats periodically (every 10 messages to avoid excessive disk writes) + if current_stats.session_messages_exchanged.is_multiple_of(10) + && current_stats.session_messages_exchanged > 0 + { + let app_handle = app.clone(); + tauri::async_runtime::spawn(async move { + println!("Periodic stats save (every 10 messages)..."); + if let Err(e) = crate::stats::save_stats(&app_handle, ¤t_stats).await { + eprintln!("Failed to save stats: {}", e); + } + }); + } + // Only emit error results - success content is already sent via Assistant message if subtype != "success" { if let Some(text) = result { diff --git a/src/lib/stores/achievements.ts b/src/lib/stores/achievements.ts index d749e6c..16dc960 100644 --- a/src/lib/stores/achievements.ts +++ b/src/lib/stores/achievements.ts @@ -10,12 +10,14 @@ interface AchievementState { lastUnlocked: Achievement | null; } -// Initial achievement definitions +// Initial achievement definitions - must match Rust backend exactly! const achievementDefinitions: Record< AchievementId, Omit > = { - // Token milestones + // ============================================ + // Token Milestones + // ============================================ FirstSteps: { id: "FirstSteps", name: "First Steps", @@ -45,11 +47,29 @@ const achievementDefinitions: Record< name: "Token Master", description: "One million tokens! You're unstoppable!", icon: "๐Ÿ‘‘", - rarity: "legendary", + rarity: "epic", maxProgress: 1000000, }, + TokenBillionaire: { + id: "TokenBillionaire", + name: "Token Billionaire", + description: "Generated 10 million tokens!", + icon: "๐Ÿ’ฐ", + rarity: "legendary", + maxProgress: 10000000, + }, + TokenTreasure: { + id: "TokenTreasure", + name: "Token Treasure", + description: "Generated 50 million tokens - a true treasure trove!", + icon: "๐Ÿ’Ž", + rarity: "legendary", + maxProgress: 50000000, + }, - // Code generation + // ============================================ + // Code Generation + // ============================================ HelloWorld: { id: "HelloWorld", name: "Hello, World!", @@ -74,8 +94,26 @@ const achievementDefinitions: Record< rarity: "epic", maxProgress: 1000, }, + CodeFactory: { + id: "CodeFactory", + name: "Code Factory", + description: "Generated 5,000 code blocks!", + icon: "๐Ÿญ", + rarity: "epic", + maxProgress: 5000, + }, + CodeEmpire: { + id: "CodeEmpire", + name: "Code Empire", + description: "Generated 10,000 code blocks - an empire of code!", + icon: "๐Ÿฐ", + rarity: "legendary", + maxProgress: 10000, + }, - // File operations + // ============================================ + // File Operations + // ============================================ FileManipulator: { id: "FileManipulator", name: "File Manipulator", @@ -87,13 +125,31 @@ const achievementDefinitions: Record< FileArchitect: { id: "FileArchitect", name: "File Architect", - description: "Created or edited 100 files", + description: "Edited 100 files", icon: "๐Ÿ›๏ธ", rarity: "rare", maxProgress: 100, }, + FileEngineer: { + id: "FileEngineer", + name: "File Engineer", + description: "Edited 500 files", + icon: "โš™๏ธ", + rarity: "epic", + maxProgress: 500, + }, + FileLegend: { + id: "FileLegend", + name: "File Legend", + description: "Edited 1,000 files - legendary file manipulation!", + icon: "๐ŸŒŸ", + rarity: "legendary", + maxProgress: 1000, + }, - // Conversation milestones + // ============================================ + // Conversation Milestones + // ============================================ ConversationStarter: { id: "ConversationStarter", name: "Conversation Starter", @@ -118,8 +174,26 @@ const achievementDefinitions: Record< rarity: "rare", maxProgress: 1000, }, + ChatMarathon: { + id: "ChatMarathon", + name: "Chat Marathon", + description: "5,000 messages exchanged!", + icon: "๐Ÿƒโ€โ™€๏ธ", + rarity: "epic", + maxProgress: 5000, + }, + ChatLegend: { + id: "ChatLegend", + name: "Chat Legend", + description: "10,000 messages - a legendary conversationalist!", + icon: "๐Ÿ‘‘", + rarity: "legendary", + maxProgress: 10000, + }, - // Tool usage + // ============================================ + // Tool Usage + // ============================================ Toolsmith: { id: "Toolsmith", name: "Toolsmith", @@ -137,12 +211,14 @@ const achievementDefinitions: Record< maxProgress: 10, }, - // Time-based achievements + // ============================================ + // Time-Based Achievements + // ============================================ EarlyBird: { id: "EarlyBird", name: "Early Bird", description: "Started a session between 5 AM and 7 AM", - icon: "๐ŸŒ…", + icon: "๐Ÿฆ", rarity: "common", }, NightOwl: { @@ -172,9 +248,12 @@ const achievementDefinitions: Record< description: "Coded for 30 days in a row", icon: "๐Ÿ†", rarity: "legendary", + maxProgress: 30, }, - // Search and exploration + // ============================================ + // Search and Exploration + // ============================================ Explorer: { id: "Explorer", name: "Explorer", @@ -192,7 +271,9 @@ const achievementDefinitions: Record< maxProgress: 500, }, - // Session achievements + // ============================================ + // Session Achievements + // ============================================ QuickSession: { id: "QuickSession", name: "Quick Session", @@ -221,8 +302,24 @@ const achievementDefinitions: Record< icon: "๐Ÿƒโ€โ™€๏ธ", rarity: "epic", }, + UltraMarathon: { + id: "UltraMarathon", + name: "Ultra Marathon", + description: "8 hour coding session!", + icon: "๐Ÿฆธโ€โ™€๏ธ", + rarity: "epic", + }, + CodingRetreat: { + id: "CodingRetreat", + name: "Coding Retreat", + description: "12 hour coding session - take care of yourself!", + icon: "๐Ÿ•๏ธ", + rarity: "legendary", + }, - // Special achievements + // ============================================ + // Special Achievements + // ============================================ FirstMessage: { id: "FirstMessage", name: "First Message", @@ -276,7 +373,7 @@ const achievementDefinitions: Record< description: "Used all available Claude models", icon: "๐ŸŽจ", rarity: "epic", - maxProgress: 5, // Adjust based on available models + maxProgress: 5, }, MarathonCoder: { id: "MarathonCoder", @@ -287,7 +384,9 @@ const achievementDefinitions: Record< maxProgress: 10000, }, + // ============================================ // Relationship & Greetings + // ============================================ GoodMorning: { id: "GoodMorning", name: "Good Morning!", @@ -300,7 +399,7 @@ const achievementDefinitions: Record< id: "GoodNight", name: "Sweet Dreams", description: "Said good night to Hikari", - icon: "๐ŸŒ™", + icon: "๐ŸŒƒ", rarity: "common", maxProgress: 1, }, @@ -320,14 +419,56 @@ const achievementDefinitions: Record< rarity: "rare", maxProgress: 1, }, + HelloHikari: { + id: "HelloHikari", + name: "Hello Hikari!", + description: "Greeted Hikari by name", + icon: "๐Ÿ‘‹", + rarity: "common", + maxProgress: 1, + }, + HowAreYou: { + id: "HowAreYou", + name: "Caring Friend", + description: "Asked how Hikari is doing", + icon: "๐Ÿ’ญ", + rarity: "common", + maxProgress: 1, + }, + MissedYou: { + id: "MissedYou", + name: "Missed You", + description: "Told Hikari you missed her", + icon: "๐Ÿฅบ", + rarity: "rare", + maxProgress: 1, + }, + BackAgain: { + id: "BackAgain", + name: "Back Again", + description: "Announced your return", + icon: "๐Ÿ”™", + rarity: "common", + maxProgress: 1, + }, + // ============================================ // Personality & Fun + // ============================================ EmojiUser: { id: "EmojiUser", - name: "Emoji Master", - description: "Used 20+ emojis in messages", + name: "Emoji User", + description: "Used an emoji in a message", icon: "๐Ÿ˜„", rarity: "common", + maxProgress: 1, + }, + QuestionMaster: { + id: "QuestionMaster", + name: "Question Master", + description: "Asked 20 questions with ?", + icon: "โ“", + rarity: "common", maxProgress: 20, }, CapsLock: { @@ -338,101 +479,904 @@ const achievementDefinitions: Record< rarity: "common", maxProgress: 1, }, - QuestionMaster: { - id: "QuestionMaster", - name: "Question Master", - description: "Asked 50 questions", - icon: "โ“", - rarity: "common", - maxProgress: 50, - }, PleaseAndThankYou: { id: "PleaseAndThankYou", name: "Polite Programmer", - description: "Always says please and thank you", + description: "Uses please in messages", icon: "๐ŸŽฉ", rarity: "common", - maxProgress: 10, + maxProgress: 1, }, + // ============================================ + // Emotional + // ============================================ + Frustrated: { + id: "Frustrated", + name: "Frustrated", + description: "Expressed frustration (we all have those days)", + icon: "๐Ÿ˜ค", + rarity: "common", + maxProgress: 1, + }, + Excited: { + id: "Excited", + name: "Excited", + description: "Expressed excitement!", + icon: "๐ŸŽ‰", + rarity: "common", + maxProgress: 1, + }, + Confused: { + id: "Confused", + name: "Confused", + description: "Expressed confusion", + icon: "๐Ÿ˜•", + rarity: "common", + maxProgress: 1, + }, + Curious: { + id: "Curious", + name: "Curious Mind", + description: "Asked why or how something works", + icon: "๐Ÿค”", + rarity: "common", + maxProgress: 1, + }, + Impressed: { + id: "Impressed", + name: "Impressed", + description: "Was impressed by something", + icon: "๐Ÿ˜ฒ", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ // Git & Development - CommitMaster: { - id: "CommitMaster", - name: "Commit Master", - description: "Made 100 commits through Hikari", - icon: "๐Ÿ“", - rarity: "rare", - maxProgress: 100, - }, - PRO: { - id: "PRO", - name: "PRO", - description: "Created 10 pull requests", - icon: "๐Ÿ”€", - rarity: "rare", - maxProgress: 10, - }, - Reviewer: { - id: "Reviewer", - name: "Code Reviewer", - description: "Reviewed 10 pull requests", - icon: "๐Ÿ‘€", - rarity: "rare", - maxProgress: 10, - }, - IssueTracker: { - id: "IssueTracker", - name: "Issue Tracker", - description: "Created 25 issues", - icon: "๐ŸŽฏ", - rarity: "rare", - maxProgress: 25, - }, + // ============================================ GitGuru: { id: "GitGuru", name: "Git Guru", - description: "Mastered git operations", + description: "Used git commands 10 times", icon: "๐ŸŒฒ", + rarity: "common", + maxProgress: 10, + }, + TestWriter: { + id: "TestWriter", + name: "Test Writer", + description: "Created test files", + icon: "๐Ÿงช", + rarity: "common", + maxProgress: 1, + }, + Debugger: { + id: "Debugger", + name: "Debugger", + description: "Fixed bugs (messages with fix, bug, error)", + icon: "๐Ÿ›", + rarity: "common", + maxProgress: 1, + }, + CommitKing: { + id: "CommitKing", + name: "Commit King", + description: "Made 50 commits", + icon: "๐Ÿ“", + rarity: "rare", + maxProgress: 50, + }, + CommitLegend: { + id: "CommitLegend", + name: "Commit Legend", + description: "Made 200 commits!", + icon: "๐Ÿ…", rarity: "epic", + maxProgress: 200, + }, + BranchMaster: { + id: "BranchMaster", + name: "Branch Master", + description: "Created 10 branches", + icon: "๐ŸŒฟ", + rarity: "rare", + maxProgress: 10, + }, + MergeExpert: { + id: "MergeExpert", + name: "Merge Expert", + description: "Merged 20 PRs", + icon: "๐Ÿ”€", + rarity: "rare", + maxProgress: 20, + }, + ConflictResolver: { + id: "ConflictResolver", + name: "Conflict Resolver", + description: "Resolved merge conflicts", + icon: "๐Ÿค", + rarity: "rare", + maxProgress: 1, }, + // ============================================ // Tool Mastery + // ============================================ BashMaster: { id: "BashMaster", name: "Bash Master", - description: "Used bash commands 100 times", + description: "Used Bash tool 50 times", icon: "๐Ÿ’ป", rarity: "rare", - maxProgress: 100, + maxProgress: 50, }, FileExplorer: { id: "FileExplorer", name: "File Explorer", - description: "Explored files 100 times", + description: "Used Read tool 100 times", icon: "๐Ÿ“‚", - rarity: "common", + rarity: "rare", maxProgress: 100, }, SearchExpert: { id: "SearchExpert", name: "Search Expert", - description: "Mastered advanced search queries", + description: "Used Grep tool 50 times", icon: "๐Ÿ”Ž", rarity: "rare", + maxProgress: 50, }, - AgentCommander: { - id: "AgentCommander", - name: "Agent Commander", - description: "Used task agents effectively", - icon: "๐Ÿค–", + EditMaster: { + id: "EditMaster", + name: "Edit Master", + description: "Used Edit tool 100 times", + icon: "โœ‚๏ธ", rarity: "rare", + maxProgress: 100, }, - MCPMaster: { - id: "MCPMaster", - name: "MCP Master", - description: "Mastered MCP tool usage", - icon: "๐Ÿ› ๏ธ", + WriteMaster: { + id: "WriteMaster", + name: "Write Master", + description: "Used Write tool 50 times", + icon: "๐Ÿ“", + rarity: "rare", + maxProgress: 50, + }, + GlobMaster: { + id: "GlobMaster", + name: "Glob Master", + description: "Used Glob tool 100 times", + icon: "๐ŸŒ", + rarity: "rare", + maxProgress: 100, + }, + TaskMaster: { + id: "TaskMaster", + name: "Task Master", + description: "Used Task tool 50 times", + icon: "๐Ÿ“‹", + rarity: "rare", + maxProgress: 50, + }, + WebFetcher: { + id: "WebFetcher", + name: "Web Fetcher", + description: "Used WebFetch tool 20 times", + icon: "๐ŸŒ", + rarity: "rare", + maxProgress: 20, + }, + McpExplorer: { + id: "McpExplorer", + name: "MCP Explorer", + description: "Used MCP tools 50 times", + icon: "๐Ÿ”ฎ", rarity: "epic", + maxProgress: 50, + }, + + // ============================================ + // Daily Streaks + // ============================================ + WeekStreak: { + id: "WeekStreak", + name: "Week Streak", + description: "7 days in a row!", + icon: "๐Ÿ“…", + rarity: "common", + maxProgress: 7, + }, + TwoWeekStreak: { + id: "TwoWeekStreak", + name: "Two Week Streak", + description: "14 days in a row!", + icon: "๐Ÿ—“๏ธ", + rarity: "rare", + maxProgress: 14, + }, + MonthStreak: { + id: "MonthStreak", + name: "Month Streak", + description: "30 days in a row!", + icon: "๐Ÿ“†", + rarity: "epic", + maxProgress: 30, + }, + QuarterStreak: { + id: "QuarterStreak", + name: "Quarter Streak", + description: "90 days in a row - incredible dedication!", + icon: "๐ŸŽ–๏ธ", + rarity: "legendary", + maxProgress: 90, + }, + + // ============================================ + // Time Challenges + // ============================================ + MorningPerson: { + id: "MorningPerson", + name: "Morning Person", + description: "10 sessions started before 9 AM", + icon: "๐ŸŒ„", + rarity: "common", + maxProgress: 10, + }, + NightCoder: { + id: "NightCoder", + name: "Night Coder", + description: "10 sessions after 10 PM", + icon: "๐ŸŒƒ", + rarity: "common", + maxProgress: 10, + }, + LunchBreakCoder: { + id: "LunchBreakCoder", + name: "Lunch Break Coder", + description: "Session during 12-1 PM", + icon: "๐Ÿฑ", + rarity: "common", + maxProgress: 1, + }, + CoffeeTime: { + id: "CoffeeTime", + name: "Coffee Time", + description: "Session during 3-4 PM", + icon: "โ˜•", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Day-Specific + // ============================================ + MondayMotivation: { + id: "MondayMotivation", + name: "Monday Motivation", + description: "Coding on Monday", + icon: "๐Ÿ’ช", + rarity: "common", + maxProgress: 1, + }, + FridayFinisher: { + id: "FridayFinisher", + name: "Friday Finisher", + description: "Coding on Friday", + icon: "๐ŸŽŠ", + rarity: "common", + maxProgress: 1, + }, + HumpDay: { + id: "HumpDay", + name: "Hump Day", + description: "Coding on Wednesday", + icon: "๐Ÿซ", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Seasonal/Special Times + // ============================================ + NewYearCoder: { + id: "NewYearCoder", + name: "New Year Coder", + description: "Coding on January 1st", + icon: "๐ŸŽ†", + rarity: "rare", + maxProgress: 1, + }, + ValentinesDev: { + id: "ValentinesDev", + name: "Valentine's Dev", + description: "Coding on February 14th", + icon: "๐Ÿ’", + rarity: "rare", + maxProgress: 1, + }, + SpookyCode: { + id: "SpookyCode", + name: "Spooky Code", + description: "Coding on October 31st", + icon: "๐ŸŽƒ", + rarity: "rare", + maxProgress: 1, + }, + HolidayCoder: { + id: "HolidayCoder", + name: "Holiday Coder", + description: "Coding on December 25th", + icon: "๐ŸŽ„", + rarity: "rare", + maxProgress: 1, + }, + LeapDayCoder: { + id: "LeapDayCoder", + name: "Leap Day Coder", + description: "Coding on February 29th - rare!", + icon: "๐Ÿธ", + rarity: "epic", + maxProgress: 1, + }, + + // ============================================ + // Message Content + // ============================================ + LongMessage: { + id: "LongMessage", + name: "Long Message", + description: "Sent a message over 500 characters", + icon: "๐Ÿ“œ", + rarity: "common", + maxProgress: 1, + }, + NovelWriter: { + id: "NovelWriter", + name: "Novel Writer", + description: "Sent a message over 2000 characters", + icon: "๐Ÿ“–", + rarity: "rare", + maxProgress: 1, + }, + ShortAndSweet: { + id: "ShortAndSweet", + name: "Short and Sweet", + description: "Completed a task with messages under 50 chars each", + icon: "๐Ÿฌ", + rarity: "rare", + maxProgress: 1, + }, + CodeInMessage: { + id: "CodeInMessage", + name: "Code in Message", + description: "Included code block in your message", + icon: "๐Ÿ’ป", + rarity: "common", + maxProgress: 1, + }, + MarkdownMaster: { + id: "MarkdownMaster", + name: "Markdown Master", + description: "Used markdown formatting in message", + icon: "๐Ÿ“‹", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Programming Languages + // ============================================ + RustDeveloper: { + id: "RustDeveloper", + name: "Rust Developer", + description: "Generated Rust code", + icon: "๐Ÿฆ€", + rarity: "common", + maxProgress: 1, + }, + PythonDeveloper: { + id: "PythonDeveloper", + name: "Python Developer", + description: "Generated Python code", + icon: "๐Ÿ", + rarity: "common", + maxProgress: 1, + }, + JavaScriptDev: { + id: "JavaScriptDev", + name: "JavaScript Dev", + description: "Generated JavaScript code", + icon: "๐Ÿ“œ", + rarity: "common", + maxProgress: 1, + }, + TypeScriptDev: { + id: "TypeScriptDev", + name: "TypeScript Dev", + description: "Generated TypeScript code", + icon: "๐Ÿ’Ž", + rarity: "common", + maxProgress: 1, + }, + GoDeveloper: { + id: "GoDeveloper", + name: "Go Developer", + description: "Generated Go code", + icon: "๐Ÿน", + rarity: "common", + maxProgress: 1, + }, + CppDeveloper: { + id: "CppDeveloper", + name: "C++ Developer", + description: "Generated C++ code", + icon: "โš™๏ธ", + rarity: "common", + maxProgress: 1, + }, + JavaDeveloper: { + id: "JavaDeveloper", + name: "Java Developer", + description: "Generated Java code", + icon: "โ˜•", + rarity: "common", + maxProgress: 1, + }, + HtmlCssDev: { + id: "HtmlCssDev", + name: "HTML/CSS Dev", + description: "Generated HTML/CSS code", + icon: "๐ŸŽจ", + rarity: "common", + maxProgress: 1, + }, + SqlDeveloper: { + id: "SqlDeveloper", + name: "SQL Developer", + description: "Generated SQL code", + icon: "๐Ÿ—„๏ธ", + rarity: "common", + maxProgress: 1, + }, + ShellScripter: { + id: "ShellScripter", + name: "Shell Scripter", + description: "Generated shell/bash scripts", + icon: "๐Ÿš", + rarity: "common", + maxProgress: 1, + }, + FullStackDev: { + id: "FullStackDev", + name: "Full Stack Dev", + description: "Generated code in 10+ languages", + icon: "๐ŸŒˆ", + rarity: "epic", + maxProgress: 10, + }, + + // ============================================ + // Project Types + // ============================================ + FrontendDev: { + id: "FrontendDev", + name: "Frontend Dev", + description: "Worked on frontend files", + icon: "๐Ÿ–ผ๏ธ", + rarity: "common", + maxProgress: 1, + }, + BackendDev: { + id: "BackendDev", + name: "Backend Dev", + description: "Worked on backend files", + icon: "โš™๏ธ", + rarity: "common", + maxProgress: 1, + }, + ConfigEditor: { + id: "ConfigEditor", + name: "Config Editor", + description: "Edited config files", + icon: "โš™๏ธ", + rarity: "common", + maxProgress: 1, + }, + DocWriter: { + id: "DocWriter", + name: "Doc Writer", + description: "Edited documentation", + icon: "๐Ÿ“š", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Error Handling + // ============================================ + ErrorHunter: { + id: "ErrorHunter", + name: "Error Hunter", + description: "Fixed 10 errors", + icon: "๐ŸŽฏ", + rarity: "common", + maxProgress: 10, + }, + ExceptionSlayer: { + id: "ExceptionSlayer", + name: "Exception Slayer", + description: "Fixed 50 errors", + icon: "โš”๏ธ", + rarity: "rare", + maxProgress: 50, + }, + BugExterminator: { + id: "BugExterminator", + name: "Bug Exterminator", + description: "Fixed 100 bugs", + icon: "๐Ÿชฒ", + rarity: "epic", + maxProgress: 100, + }, + + // ============================================ + // Refactoring + // ============================================ + CleanCoder: { + id: "CleanCoder", + name: "Clean Coder", + description: "Refactored code", + icon: "๐Ÿงน", + rarity: "common", + maxProgress: 1, + }, + Optimizer: { + id: "Optimizer", + name: "Optimizer", + description: "Optimized performance", + icon: "โšก", + rarity: "rare", + maxProgress: 1, + }, + Simplifier: { + id: "Simplifier", + name: "Simplifier", + description: "Simplified complex code", + icon: "โœจ", + rarity: "rare", + maxProgress: 1, + }, + + // ============================================ + // Testing + // ============================================ + TestNovice: { + id: "TestNovice", + name: "Test Novice", + description: "Wrote 10 tests", + icon: "๐Ÿงช", + rarity: "common", + maxProgress: 10, + }, + TestEnthusiast: { + id: "TestEnthusiast", + name: "Test Enthusiast", + description: "Wrote 50 tests", + icon: "๐Ÿ”ฌ", + rarity: "rare", + maxProgress: 50, + }, + TestMaster: { + id: "TestMaster", + name: "Test Master", + description: "Wrote 100 tests", + icon: "๐Ÿ†", + rarity: "epic", + maxProgress: 100, + }, + CoverageKing: { + id: "CoverageKing", + name: "Coverage King", + description: "Achieved test coverage mentions", + icon: "๐Ÿ‘‘", + rarity: "epic", + maxProgress: 1, + }, + + // ============================================ + // Documentation + // ============================================ + Documenter: { + id: "Documenter", + name: "Documenter", + description: "Wrote documentation", + icon: "๐Ÿ“", + rarity: "common", + maxProgress: 1, + }, + CommentWriter: { + id: "CommentWriter", + name: "Comment Writer", + description: "Added comments to code", + icon: "๐Ÿ’ฌ", + rarity: "common", + maxProgress: 1, + }, + ReadmeHero: { + id: "ReadmeHero", + name: "README Hero", + description: "Created/edited README files", + icon: "๐Ÿ“–", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // API & Integration + // ============================================ + ApiExplorer: { + id: "ApiExplorer", + name: "API Explorer", + description: "Worked with APIs", + icon: "๐Ÿ”Œ", + rarity: "common", + maxProgress: 1, + }, + DatabaseDev: { + id: "DatabaseDev", + name: "Database Dev", + description: "Worked with databases", + icon: "๐Ÿ—„๏ธ", + rarity: "common", + maxProgress: 1, + }, + CloudCoder: { + id: "CloudCoder", + name: "Cloud Coder", + description: "Worked with cloud services", + icon: "โ˜๏ธ", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Special Milestones + // ============================================ + CenturyClub: { + id: "CenturyClub", + name: "Century Club", + description: "100 sessions", + icon: "๐Ÿ’ฏ", + rarity: "rare", + maxProgress: 100, + }, + ThousandSessions: { + id: "ThousandSessions", + name: "Thousand Sessions", + description: "1000 sessions!", + icon: "๐ŸŽŠ", + rarity: "epic", + maxProgress: 1000, + }, + Veteran: { + id: "Veteran", + name: "Veteran", + description: "Used Hikari for 30+ days total", + icon: "๐ŸŽ–๏ธ", + rarity: "rare", + maxProgress: 30, + }, + OldTimer: { + id: "OldTimer", + name: "Old Timer", + description: "Used Hikari for 90+ days total", + icon: "๐Ÿง“", + rarity: "epic", + maxProgress: 90, + }, + Loyalist: { + id: "Loyalist", + name: "Loyalist", + description: "Used Hikari for 365+ days total", + icon: "๐Ÿ†", + rarity: "legendary", + maxProgress: 365, + }, + + // ============================================ + // Fun & Easter Eggs + // ============================================ + Perfectionist: { + id: "Perfectionist", + name: "Perfectionist", + description: "Redo something 5 times", + icon: "โœจ", + rarity: "common", + maxProgress: 5, + }, + Persistent: { + id: "Persistent", + name: "Persistent", + description: "Asked the same question 3 times", + icon: "๐Ÿ”„", + rarity: "common", + maxProgress: 3, + }, + Patient: { + id: "Patient", + name: "Patient", + description: "Waited for a long response", + icon: "โณ", + rarity: "common", + maxProgress: 1, + }, + Speedy: { + id: "Speedy", + name: "Speedy", + description: "Sent 10 messages in 1 minute", + icon: "๐Ÿ’จ", + rarity: "rare", + maxProgress: 10, + }, + + // ============================================ + // UI Exploration + // ============================================ + MultiTasker: { + id: "MultiTasker", + name: "Multi-Tasker", + description: "Used multiple conversations", + icon: "๐ŸชŸ", + rarity: "common", + maxProgress: 1, + }, + Minimalist: { + id: "Minimalist", + name: "Minimalist", + description: "Used compact mode", + icon: "๐Ÿ“ฆ", + rarity: "common", + maxProgress: 1, + }, + PrivacyFirst: { + id: "PrivacyFirst", + name: "Privacy First", + description: "Used streamer mode", + icon: "๐Ÿ”’", + rarity: "common", + maxProgress: 1, + }, + ThemeChanger: { + id: "ThemeChanger", + name: "Theme Changer", + description: "Changed themes", + icon: "๐ŸŽจ", + rarity: "common", + maxProgress: 1, + }, + SettingsTweaker: { + id: "SettingsTweaker", + name: "Settings Tweaker", + description: "Adjusted settings", + icon: "โš™๏ธ", + rarity: "common", + maxProgress: 1, + }, + + // ============================================ + // Achievement Meta + // ============================================ + AchievementHunter: { + id: "AchievementHunter", + name: "Achievement Hunter", + description: "Unlocked 25 achievements", + icon: "๐Ÿ…", + rarity: "rare", + maxProgress: 25, + }, + Completionist: { + id: "Completionist", + name: "Completionist", + description: "Unlocked 50 achievements", + icon: "๐Ÿ†", + rarity: "epic", + maxProgress: 50, + }, + MasterUnlocker: { + id: "MasterUnlocker", + name: "Master Unlocker", + description: "Unlocked 100 achievements", + icon: "๐Ÿ”“", + rarity: "epic", + maxProgress: 100, + }, + PlatinumStatus: { + id: "PlatinumStatus", + name: "Platinum Status", + description: "Unlocked all achievements!", + icon: "๐Ÿ’Ž", + rarity: "legendary", + }, + + // ============================================ + // Clipboard & Snippets + // ============================================ + ClipboardCollector: { + id: "ClipboardCollector", + name: "Clipboard Collector", + description: "Used clipboard history", + icon: "๐Ÿ“‹", + rarity: "common", + maxProgress: 1, + }, + SnippetCreator: { + id: "SnippetCreator", + name: "Snippet Creator", + description: "Created a snippet", + icon: "โœ‚๏ธ", + rarity: "common", + maxProgress: 1, + }, + SnippetMaster: { + id: "SnippetMaster", + name: "Snippet Master", + description: "Created 20 snippets", + icon: "๐Ÿ“š", + rarity: "rare", + maxProgress: 20, + }, + + // ============================================ + // Other Features + // ============================================ + QuickActionUser: { + id: "QuickActionUser", + name: "Quick Action User", + description: "Used quick actions", + icon: "โšก", + rarity: "common", + maxProgress: 1, + }, + HistoryBuff: { + id: "HistoryBuff", + name: "History Buff", + description: "Browsed history", + icon: "๐Ÿ“œ", + rarity: "common", + maxProgress: 1, + }, + Archivist: { + id: "Archivist", + name: "Archivist", + description: "Exported sessions", + icon: "๐Ÿ—ƒ๏ธ", + rarity: "common", + maxProgress: 1, + }, + SessionExporter: { + id: "SessionExporter", + name: "Session Exporter", + description: "Exported a session", + icon: "๐Ÿ“ค", + rarity: "common", + maxProgress: 1, + }, + GitPanelUser: { + id: "GitPanelUser", + name: "Git Panel User", + description: "Used the Git panel", + icon: "๐ŸŒฒ", + rarity: "common", + maxProgress: 1, + }, + FeatureExplorer: { + id: "FeatureExplorer", + name: "Feature Explorer", + description: "Used 10+ features", + icon: "๐Ÿ—บ๏ธ", + rarity: "rare", + maxProgress: 10, }, }; @@ -558,22 +1502,22 @@ export const achievementCategories = [ { name: "Token Milestones", description: "Track your token generation progress", - ids: ["FirstSteps", "GrowingStrong", "BlossomingCoder", "TokenMaster"] as AchievementId[], + ids: ["FirstSteps", "GrowingStrong", "BlossomingCoder", "TokenMaster", "TokenBillionaire", "TokenTreasure"] as AchievementId[], }, { name: "Code Generation", description: "Achievements for generating code", - ids: ["HelloWorld", "CodeWizard", "ThousandBlocks"] as AchievementId[], + ids: ["HelloWorld", "CodeWizard", "ThousandBlocks", "CodeFactory", "CodeEmpire"] as AchievementId[], }, { name: "File Operations", description: "Working with files and projects", - ids: ["FileManipulator", "FileArchitect"] as AchievementId[], + ids: ["FileManipulator", "FileArchitect", "FileEngineer", "FileLegend"] as AchievementId[], }, { name: "Conversations", description: "Building our relationship through chat", - ids: ["ConversationStarter", "ChattyKathy", "Conversationalist"] as AchievementId[], + ids: ["ConversationStarter", "ChattyKathy", "Conversationalist", "ChatMarathon", "ChatLegend"] as AchievementId[], }, { name: "Tools & Skills", @@ -604,23 +1548,30 @@ export const achievementCategories = [ "FocusedWork", "DeepDive", "MarathonSession", + "UltraMarathon", + "CodingRetreat", "MarathonCoder", ] as AchievementId[], }, { name: "Relationship & Greetings", description: "Our special moments together", - ids: ["GoodMorning", "GoodNight", "ThankYou", "LoveYou"] as AchievementId[], + ids: ["GoodMorning", "GoodNight", "ThankYou", "LoveYou", "HelloHikari", "HowAreYou", "MissedYou", "BackAgain"] as AchievementId[], }, { name: "Personality & Fun", description: "Express yourself!", ids: ["EmojiUser", "CapsLock", "QuestionMaster", "PleaseAndThankYou"] as AchievementId[], }, + { + name: "Emotional", + description: "All the feels", + ids: ["Frustrated", "Excited", "Confused", "Curious", "Impressed"] as AchievementId[], + }, { name: "Git & Development", description: "Version control mastery", - ids: ["CommitMaster", "PRO", "Reviewer", "IssueTracker", "GitGuru"] as AchievementId[], + ids: ["GitGuru", "TestWriter", "Debugger", "CommitKing", "CommitLegend", "BranchMaster", "MergeExpert", "ConflictResolver"] as AchievementId[], }, { name: "Tool Mastery", @@ -629,10 +1580,104 @@ export const achievementCategories = [ "BashMaster", "FileExplorer", "SearchExpert", - "AgentCommander", - "MCPMaster", + "EditMaster", + "WriteMaster", + "GlobMaster", + "TaskMaster", + "WebFetcher", + "McpExplorer", ] as AchievementId[], }, + { + name: "Daily Streaks", + description: "Keep the momentum going!", + ids: ["WeekStreak", "TwoWeekStreak", "MonthStreak", "QuarterStreak"] as AchievementId[], + }, + { + name: "Time Challenges", + description: "When you code", + ids: ["MorningPerson", "NightCoder", "LunchBreakCoder", "CoffeeTime"] as AchievementId[], + }, + { + name: "Day-Specific", + description: "Special days for coding", + ids: ["MondayMotivation", "FridayFinisher", "HumpDay"] as AchievementId[], + }, + { + name: "Seasonal", + description: "Holiday coding!", + ids: ["NewYearCoder", "ValentinesDev", "SpookyCode", "HolidayCoder", "LeapDayCoder"] as AchievementId[], + }, + { + name: "Message Content", + description: "How you communicate", + ids: ["LongMessage", "NovelWriter", "ShortAndSweet", "CodeInMessage", "MarkdownMaster"] as AchievementId[], + }, + { + name: "Programming Languages", + description: "Languages you've used", + ids: ["RustDeveloper", "PythonDeveloper", "JavaScriptDev", "TypeScriptDev", "GoDeveloper", "CppDeveloper", "JavaDeveloper", "HtmlCssDev", "SqlDeveloper", "ShellScripter", "FullStackDev"] as AchievementId[], + }, + { + name: "Project Types", + description: "Types of work you do", + ids: ["FrontendDev", "BackendDev", "ConfigEditor", "DocWriter"] as AchievementId[], + }, + { + name: "Error Handling", + description: "Bug squashing achievements", + ids: ["ErrorHunter", "ExceptionSlayer", "BugExterminator"] as AchievementId[], + }, + { + name: "Refactoring", + description: "Code improvement", + ids: ["CleanCoder", "Optimizer", "Simplifier"] as AchievementId[], + }, + { + name: "Testing", + description: "Test-driven achievements", + ids: ["TestNovice", "TestEnthusiast", "TestMaster", "CoverageKing"] as AchievementId[], + }, + { + name: "Documentation", + description: "Document your work", + ids: ["Documenter", "CommentWriter", "ReadmeHero"] as AchievementId[], + }, + { + name: "API & Integration", + description: "Working with services", + ids: ["ApiExplorer", "DatabaseDev", "CloudCoder"] as AchievementId[], + }, + { + name: "Special Milestones", + description: "Long-term achievements", + ids: ["CenturyClub", "ThousandSessions", "Veteran", "OldTimer", "Loyalist"] as AchievementId[], + }, + { + name: "Fun & Easter Eggs", + description: "Hidden gems", + ids: ["Perfectionist", "Persistent", "Patient", "Speedy"] as AchievementId[], + }, + { + name: "UI Exploration", + description: "Explore Hikari's features", + ids: ["MultiTasker", "Minimalist", "PrivacyFirst", "ThemeChanger", "SettingsTweaker"] as AchievementId[], + }, + { + name: "Achievement Meta", + description: "Achievements about achievements", + ids: ["AchievementHunter", "Completionist", "MasterUnlocker", "PlatinumStatus"] as AchievementId[], + }, + { + name: "Clipboard & Snippets", + description: "Clipboard and snippet features", + ids: ["ClipboardCollector", "SnippetCreator", "SnippetMaster"] as AchievementId[], + }, + { + name: "Other Features", + description: "Miscellaneous features", + ids: ["QuickActionUser", "HistoryBuff", "Archivist", "SessionExporter", "GitPanelUser", "FeatureExplorer"] as AchievementId[], + }, { name: "Special", description: "Unique accomplishments", diff --git a/src/lib/stores/stats.ts b/src/lib/stores/stats.ts index c8ffc58..59522b0 100644 --- a/src/lib/stores/stats.ts +++ b/src/lib/stores/stats.ts @@ -104,10 +104,11 @@ export async function initStatsListener() { stats.set(newStats); }); - // Load initial stats from backend + // Load initial persisted stats from backend (no bridge required) try { - const initialStats = await invoke("get_usage_stats"); + const initialStats = await invoke("get_persisted_stats"); stats.set(initialStats); + console.log("Loaded persisted stats:", initialStats); } catch (error) { console.error("Failed to load initial stats:", error); } diff --git a/src/lib/types/achievements.ts b/src/lib/types/achievements.ts index 254ae1a..902d1f3 100644 --- a/src/lib/types/achievements.ts +++ b/src/lib/types/achievements.ts @@ -14,34 +14,52 @@ export type AchievementId = | "GrowingStrong" // 10,000 tokens | "BlossomingCoder" // 100,000 tokens | "TokenMaster" // 1,000,000 tokens + | "TokenBillionaire" // 10,000,000 tokens + | "TokenTreasure" // 50,000,000 tokens + // Code Generation | "HelloWorld" // First code block | "CodeWizard" // 100 code blocks | "ThousandBlocks" // 1,000 code blocks + | "CodeFactory" // 5,000 code blocks + | "CodeEmpire" // 10,000 code blocks + // File Operations | "FileManipulator" // 10 files edited | "FileArchitect" // 100 files edited + | "FileEngineer" // 500 files edited + | "FileLegend" // 1,000 files edited + // Conversation milestones | "ConversationStarter" // 10 messages | "ChattyKathy" // 100 messages | "Conversationalist" // 1,000 messages + | "ChatMarathon" // 5,000 messages + | "ChatLegend" // 10,000 messages + // Tool usage | "Toolsmith" // 5 different tools | "ToolMaster" // 10 different tools + // Time-based achievements | "EarlyBird" // Started session 5-7 AM | "NightOwl" // Coding after midnight | "AllNighter" // Worked 2-5 AM | "WeekendWarrior" // Coding on weekend | "DedicatedDeveloper" // 30 days in a row + // Search and exploration | "Explorer" // 50 searches | "MasterSearcher" // 500 searches + // Session achievements | "QuickSession" // Productive session < 5 min | "FocusedWork" // 30 min session | "DeepDive" // 2 hour session | "MarathonSession" // 5+ hour session + | "UltraMarathon" // 8 hour session + | "CodingRetreat" // 12 hour session + // Special achievements | "FirstMessage" // First message sent | "FirstTool" // First tool used @@ -51,28 +69,165 @@ export type AchievementId = | "SpeedCoder" // 10 code blocks in 10 minutes | "ClaudeConnoisseur" // Used all Claude models | "MarathonCoder" // 10k tokens in one session + // Relationship & Greetings - | "GoodMorning" // Said good morning - | "GoodNight" // Said good night - | "ThankYou" // Said thank you - | "LoveYou" // Said love you + | "GoodMorning" // Say "good morning" + | "GoodNight" // Say "good night" or "goodnight" + | "ThankYou" // Say "thank you" or "thanks" + | "LoveYou" // Say "love you" or "ily" + | "HelloHikari" // Say "hello hikari" or "hi hikari" + | "HowAreYou" // Ask "how are you" + | "MissedYou" // Say "missed you" + | "BackAgain" // Say "i'm back" or "back again" + // Personality & Fun - | "EmojiUser" // Used 20+ emojis - | "CapsLock" // ALL CAPS MESSAGE - | "QuestionMaster" // Asked 50 questions - | "PleaseAndThankYou" // Polite user + | "EmojiUser" // Use an emoji in a message + | "QuestionMaster" // Use "?" in 20 messages + | "CapsLock" // Send a message in ALL CAPS + | "PleaseAndThankYou" // Use "please" in messages + + // Emotional + | "Frustrated" // Say "frustrated" or "ugh" or "argh" + | "Excited" // Say "excited" or "yay" or "woohoo" + | "Confused" // Say "confused" or "don't understand" + | "Curious" // Ask "why" or "how does" + | "Impressed" // Say "wow" or "amazing" or "incredible" + // Git & Development - | "CommitMaster" // 100 commits - | "PRO" // Created 10 PRs - | "Reviewer" // Reviewed 10 PRs - | "IssueTracker" // Created 25 issues - | "GitGuru" // Used git commands + | "GitGuru" // Use git commands 10 times + | "TestWriter" // Create test files + | "Debugger" // Fix bugs (messages with "fix", "bug", "error") + | "CommitKing" // 50 commits + | "CommitLegend" // 200 commits + | "BranchMaster" // Create 10 branches + | "MergeExpert" // Merge 20 PRs + | "ConflictResolver" // Resolve merge conflicts + // Tool Mastery - | "BashMaster" // Used bash 100 times - | "FileExplorer" // Searched files 100 times - | "SearchExpert" // Advanced searches - | "AgentCommander" // Used task agents - | "MCPMaster"; // Used MCP tools + | "BashMaster" // Use Bash tool 50 times + | "FileExplorer" // Use Read tool 100 times + | "SearchExpert" // Use Grep tool 50 times + | "EditMaster" // Use Edit tool 100 times + | "WriteMaster" // Use Write tool 50 times + | "GlobMaster" // Use Glob tool 100 times + | "TaskMaster" // Use Task tool 50 times + | "WebFetcher" // Use WebFetch tool 20 times + | "McpExplorer" // Use MCP tools 50 times + + // Daily Streaks + | "WeekStreak" // 7 days in a row + | "TwoWeekStreak" // 14 days in a row + | "MonthStreak" // 30 days in a row + | "QuarterStreak" // 90 days in a row + + // Time Challenges + | "MorningPerson" // 10 sessions started before 9 AM + | "NightCoder" // 10 sessions after 10 PM + | "LunchBreakCoder" // Session during 12-1 PM + | "CoffeeTime" // Session during 3-4 PM + + // Day-specific + | "MondayMotivation" // Coding on Monday + | "FridayFinisher" // Coding on Friday + | "HumpDay" // Coding on Wednesday + + // Seasonal/Special Times + | "NewYearCoder" // Coding on January 1st + | "ValentinesDev" // Coding on February 14th + | "SpookyCode" // Coding on October 31st + | "HolidayCoder" // Coding on December 25th + | "LeapDayCoder" // Coding on February 29th + + // Message Content + | "LongMessage" // Send a message over 500 characters + | "NovelWriter" // Send a message over 2000 characters + | "ShortAndSweet" // Complete a task with messages under 50 chars each + | "CodeInMessage" // Include code block in user message + | "MarkdownMaster" // Use markdown formatting in message + + // Programming Languages + | "RustDeveloper" // Generate Rust code + | "PythonDeveloper" // Generate Python code + | "JavaScriptDev" // Generate JavaScript code + | "TypeScriptDev" // Generate TypeScript code + | "GoDeveloper" // Generate Go code + | "CppDeveloper" // Generate C++ code + | "JavaDeveloper" // Generate Java code + | "HtmlCssDev" // Generate HTML/CSS code + | "SqlDeveloper" // Generate SQL code + | "ShellScripter" // Generate shell/bash scripts + | "FullStackDev" // Generate code in 10+ languages + + // Project Types + | "FrontendDev" // Work on frontend files + | "BackendDev" // Work on backend files + | "ConfigEditor" // Edit config files + | "DocWriter" // Edit documentation + + // Error Handling + | "ErrorHunter" // Fix 10 errors + | "ExceptionSlayer" // Fix 50 errors + | "BugExterminator" // Fix 100 bugs + + // Refactoring + | "CleanCoder" // Refactor code + | "Optimizer" // Optimize performance + | "Simplifier" // Simplify complex code + + // Testing + | "TestNovice" // Write 10 tests + | "TestEnthusiast" // Write 50 tests + | "TestMaster" // Write 100 tests + | "CoverageKing" // Achieve test coverage mentions + + // Documentation + | "Documenter" // Write documentation + | "CommentWriter" // Add comments to code + | "ReadmeHero" // Create/edit README files + + // API & Integration + | "ApiExplorer" // Work with APIs + | "DatabaseDev" // Work with databases + | "CloudCoder" // Work with cloud services + + // Special Milestones + | "CenturyClub" // 100 sessions + | "ThousandSessions" // 1000 sessions + | "Veteran" // Used Hikari for 30+ days total + | "OldTimer" // Used Hikari for 90+ days total + | "Loyalist" // Used Hikari for 365+ days total + + // Fun & Easter Eggs + | "Perfectionist" // Redo something 5 times + | "Persistent" // Ask same question 3 times + | "Patient" // Wait for long response + | "Speedy" // Send 10 messages in 1 minute + + // UI Exploration + | "MultiTasker" // Multiple conversations + | "Minimalist" // Use compact mode + | "PrivacyFirst" // Use streamer mode + | "ThemeChanger" // Change themes + | "SettingsTweaker" // Adjust settings + + // Achievement Meta + | "AchievementHunter" // Unlock 25 achievements + | "Completionist" // Unlock 50 achievements + | "MasterUnlocker" // Unlock 100 achievements + | "PlatinumStatus" // Unlock all achievements + + // Clipboard & Snippets + | "ClipboardCollector" // Use clipboard history + | "SnippetCreator" // Create a snippet + | "SnippetMaster" // Create 20 snippets + + // Other Features + | "QuickActionUser" // Use quick actions + | "HistoryBuff" // Browse history + | "Archivist" // Export sessions + | "SessionExporter" // Export a session + | "GitPanelUser" // Use Git panel + | "FeatureExplorer"; // Use 10+ features export interface Achievement { id: AchievementId;