Commit Graph

47 Commits

Author SHA1 Message Date
615dd4a5ef fix(P3): 3 priority-3 fixes — timezone, decay rounding, rate limiter
#16  Timezone consistency — added TZ=Europe/Sofia to docker-compose.yml
     so datetime.now() returns local time inside the container. Removed
     the +3 hour hack from get_time_of_day(). All three time-of-day
     consumers (autonomous_v1_legacy, moods, autonomous_engine) now
     use the same correct local hour automatically.

#17  Decay truncation — replaced int() with round() in decay_events()
     so a counter of 1 survives one more 15-minute cycle instead of
     being immediately zeroed (round(0.841)=1 vs int(0.841)=0).

#20  Unpersisted rate limiter — _last_action_execution dict in
     autonomous.py is now seeded from the engine's persisted
     server_last_action on import, so restarts don't bypass the
     30-second cooldown.

Note: #18 (dead config fields) was a false positive — autonomous_interval_minutes
IS used by the scheduler. #19 deferred to bipolar mode rework.
2026-02-23 13:53:22 +02:00
2b743ed65e fix(P2): 5 priority-2 bug fixes — emoji consolidation, DM safety, pause gap
#10  Redundant coin flip in join_conversation — removed the 50% random
     gate that doubled the V2 engine's own decision to act.

#11  Message-triggered actions skip _autonomous_paused — _check_and_act
     and _check_and_react now bail out immediately when the autonomous
     system is paused (voice session), matching the scheduled-tick path.

#12  Duplicate emoji dictionaries — removed MOOD_EMOJIS and
     EVIL_MOOD_EMOJIS from globals.py (had different emojis from moods.py).
     bipolar_mode.py and evil_mode.py now import the canonical dicts
     from utils/moods.py so all code sees the same emojis.

#13  DM mood can spontaneously become 'asleep' — rotate_dm_mood() now
     filters 'asleep' out of the candidate list since DMs have no
     sleepy-to-asleep transition guard and no wakeup timer.

#15  Engage-user fallback misreports action type — log level raised to
     WARNING with an explicit [engage_user->general] prefix so the
     cooldown-triggered fallback is visible in logs.
2026-02-23 13:43:15 +02:00
0e4aebf353 fix(P1): 6 priority-1 bug fixes for autonomous engine and mood system
#4  Sleep/mood desync — set_server_mood() now clears is_sleeping when
    mood changes away from 'asleep', preventing ghost-sleep state.

#5  Race condition in _check_and_act — added per-guild asyncio.Lock so
    overlapping ticks + message-triggered calls cannot fire concurrently.

#6  Class-level attrs on ServerConfig — sleepy_responses_left,
    angry_wakeup_timer, and forced_angry_until are now proper dataclass
    fields with defaults, so asdict()/from_dict() round-trip correctly.
    Also strips unknown keys in from_dict() to survive schema changes.

#7  Persistence decay_factor crash — initialise decay_factor = 1.0
    before the loop so empty-server or zero-downtime paths don't
    raise NameError.

#8  Double record_action — removed the redundant call in
    autonomous_tick_v2(); only _check_and_act records the action now.

#9  Engine mood desync — on_mood_change() is now called inside
    set_server_mood() (single source of truth) and removed from 4
    call-sites in api.py, moods.py, and server_manager wakeup task.
2026-02-23 13:31:15 +02:00
422366df4c fix: 3 critical autonomous engine & mood system bugs
1. Momentum cliff at 10 messages (P0): The conversation momentum formula
   had a discontinuity where the 10th message caused momentum to DROP from
   0.9 to 0.5. Replaced with a smooth log1p curve that monotonically
   increases (0→0→0.20→0.32→...→0.70→0.89→1.0 at 30 msgs).

2. Neutral keywords overriding all moods (P0): detect_mood_shift() checked
   neutral early with generic keywords (okay, sure, hmm) that matched
   almost any response, constantly resetting mood to neutral. Now: all
   specific moods are scored by match count first (best-match wins),
   neutral is only checked as fallback and requires 2+ keyword matches.

3. Uncancellable delayed_wakeup tasks (P0): Fire-and-forget sleep tasks
   could stack and overwrite mood state after manual wake-up. Added a
   centralized wakeup task registry in ServerManager with automatic
   cancellation on manual wake or new sleep cycle.
2026-02-20 15:37:57 +02:00
2f0d430c35 feat: Add manual trigger bypass for web UI autonomous engagement
- Added manual_trigger parameter to /autonomous/engage endpoint to bypass 12h cooldown
- Updated miku_engage_random_user_for_server() and miku_engage_random_user() to accept manual_trigger flag
- Modified Web UI to always send manual_trigger=true when engaging users from the UI
- Users can now manually engage the same user multiple times from web UI without cooldown restriction
- Regular autonomous schedules still respect the 12h cooldown between engagements to the same user

Changes:
- bot/api.py: Added manual_trigger parameter with string-to-boolean conversion
- bot/static/index.html: Added manual_trigger=true to engage user request
- bot/utils/autonomous_v1_legacy.py: Added manual_trigger parameter and cooldown bypass logic
2026-02-20 00:53:42 +02:00
9972edb06d fix(docker): add config_manager.py to Dockerfile and logger components
- Add COPY config_manager.py to Dockerfile so it's included in the image
- Add 'config_manager' to logger COMPONENTS list to enable logging

Fixes the ModuleNotFoundError and ValueError when importing config_manager
2026-02-19 11:02:58 +02:00
7b7abcfc68 fix(tasks): replace fire-and-forget asyncio.create_task with create_tracked_task
Add utils/task_tracker.py with create_tracked_task() that wraps background
tasks with error logging, cancellation handling, and reference tracking.

Replace all 17 fire-and-forget asyncio.create_task() calls across 7 files:
- bot/bot.py (5 interjection checks)
- bot/utils/autonomous.py (2 check-and-act/react tasks)
- bot/utils/bipolar_mode.py (3 argument tasks)
- bot/commands/uno.py (1 game loop task)
- bot/utils/voice_receiver.py (3 STT/interruption callbacks)
- bot/utils/persona_dialogue.py (4 dialogue turn/interjection tasks)

Previously-tracked tasks (voice_audio.py, voice_manager.py) were left as-is
since they already store task references for cancellation.

Closes #1
2026-02-18 12:01:08 +02:00
33e5095607 Optimize miku-bot container size by removing unused dependencies
Major changes:
- Remove unused ML libraries: torch, scikit-learn, langchain-core, langchain-text-splitters, langchain-community, faiss-cpu
- Comment out unused langchain imports in utils/core.py (only used in commented-out code)
- Keep transformers (used in persona_dialogue.py for sentiment analysis)

Results:
- Container size reduced from 14.5GB to 2.6GB
- 82% reduction (11.9GB saved)
- Bot runs correctly without errors
- All functionality preserved

Removed packages:
- torch: ~1.0-1.5GB (not used, only in soprano_to_rvc/)
- scikit-learn: ~200-300MB (not used in bot/)
- langchain-core: ~50-100MB (not used, only in commented code)
- langchain-text-splitters: ~30-50MB (not used, only in commented code)
- langchain-community: ~50-80MB (not used, only in commented code)
- faiss-cpu: ~100-200MB (not used in bot/)

This is Phase 1 of container optimization (Quick Wins).
Further optimizations possible:
- OpenCV headless (150-200MB)
- Evaluate Playwright usage (500MB-1GB)
- Alpine base image (1-1.5GB)
- Multi-stage builds (200-400MB)
2026-02-15 20:56:25 +02:00
8d09a8a52f Implement comprehensive config system and clean up codebase
Major changes:
- Add Pydantic-based configuration system (bot/config.py, bot/config_manager.py)
- Add config.yaml with all service URLs, models, and feature flags
- Fix config.yaml path resolution in Docker (check /app/config.yaml first)
- Remove Fish Audio API integration (tested feature that didn't work)
- Remove hardcoded ERROR_WEBHOOK_URL, import from config instead
- Add missing Pydantic models (LogConfigUpdateRequest, LogFilterUpdateRequest)
- Enable Cheshire Cat memory system by default (USE_CHESHIRE_CAT=true)
- Add .env.example template with all required environment variables
- Add setup.sh script for user-friendly initialization
- Update docker-compose.yml with proper env file mounting
- Update .gitignore for config files and temporary files

Config system features:
- Static configuration from config.yaml
- Runtime overrides from config_runtime.yaml
- Environment variables for secrets (.env)
- Web UI integration via config_manager
- Graceful fallback to defaults

Secrets handling:
- Move ERROR_WEBHOOK_URL from hardcoded to .env
- Add .env.example with all placeholder values
- Document all required secrets
- Fish API key and voice ID removed from .env

Documentation:
- CONFIG_README.md - Configuration system guide
- CONFIG_SYSTEM_COMPLETE.md - Implementation summary
- FISH_API_REMOVAL_COMPLETE.md - Removal record
- SECRETS_CONFIGURED.md - Secrets setup record
- BOT_STARTUP_FIX.md - Pydantic model fixes
- MIGRATION_CHECKLIST.md - Setup checklist
- WEB_UI_INTEGRATION_COMPLETE.md - Web UI config guide
- Updated readmes/README.md with new features
2026-02-15 19:51:00 +02:00
985ac60191 Webhook pfp updates properly now 2026-02-10 22:57:55 +02:00
34167eddae feat: Restore mood system and implement comprehensive memory editor UI
MOOD SYSTEM FIX:
- Mount bot/moods directory in docker-compose.yml for Cat container access
- Update miku_personality plugin to load mood descriptions from .txt files
- Add Cat logger for debugging mood loading (replaces print statements)
- Moods now dynamically loaded from working_memory instead of hardcoded neutral
2026-02-10 22:03:54 +02:00
beb1a89000 Fix: Optimize Twitter fetching to avoid Playwright hangs
- Replaced Playwright browser scraping with direct API media extraction
- Both fetch_miku_tweets() and fetch_figurine_tweets_latest() now use twscrape's built-in media info
- Reduced tweet fetching from 10-15 minutes to ~5 seconds
- Eliminated browser timeout/hanging issues
- Relaxed autonomous tweet sharing conditions:
  * Increased message threshold from 10 to 20 per hour
  * Reduced cooldown from 3600s to 2400s (40 minutes)
  * Increased energy threshold from 50% to 70%
  * Added 'silly' and 'flirty' moods to allowed sharing moods

This makes both figurine notifications and tweet sharing much more reliable and responsive.
2026-02-08 14:55:01 +02:00
11b90ebb46 fix: Phase 3 bug fixes - memory APIs, username visibility, web UI layout, Docker
**Critical Bug Fixes:**

1. Per-user memory isolation bug
   - Changed CatAdapter from HTTP POST to WebSocket /ws/{user_id}
   - User_id now comes from URL path parameter (true per-user isolation)
   - Verified: Different users can't see each other's memories

2. Memory API 405 errors
   - Replaced non-existent Cat endpoint calls with Qdrant direct queries
   - get_memory_points(): Now uses POST /collections/{collection}/points/scroll
   - delete_memory_point(): Now uses POST /collections/{collection}/points/delete

3. Memory stats showing null counts
   - Reimplemented get_memory_stats() to query Qdrant directly
   - Now returns accurate counts: episodic: 20, declarative: 6, procedural: 4

4. Miku couldn't see usernames
   - Modified discord_bridge before_cat_reads_message hook
   - Prepends [Username says:] to every message text
   - LLM now knows who is texting: [Alice says:] Hello Miku!

5. Web UI Memory tab layout
   - Tab9 was positioned outside .tab-container div (showed to the right)
   - Moved tab9 HTML inside container, before closing divs
   - Memory tab now displays below tab buttons like other tabs

**Code Changes:**

bot/utils/cat_client.py:
- Line 25: Logger name changed to 'llm' (available component)
- get_memory_stats() (lines 256-285): Query Qdrant directly via HTTP GET
- get_memory_points() (lines 275-310): Use Qdrant POST /points/scroll
- delete_memory_point() (lines 350-370): Use Qdrant POST /points/delete

cat-plugins/discord_bridge/discord_bridge.py:
- Fixed .pop() → .get() (UserMessage is Pydantic BaseModelDict)
- Added before_cat_reads_message logic to prepend [Username says:]
- Message format: [Alice says:] message content

Dockerfile.llamaswap-rocm:
- Lines 37-44: Added conditional check for UI directory
- if [ -d ui ] before npm install && npm run build
- Fixes build failure when llama-swap UI dir doesn't exist

bot/static/index.html:
- Moved tab9 from lines 1554-1688 (outside container)
- To position before container closing divs (now inside)
- Memory tab button at line 673: 🧠 Memories

**Testing & Verification:**
 Per-user isolation verified (Docker exec test)
 Memory stats showing real counts (curl test)
 Memory API working (facts/episodic loading)
 Web UI layout fixed (tab displays correctly)
 All 5 services running (llama-swap, llama-swap-amd, qdrant, cat, bot)
 Username prepending working (message context for LLM)

**Result:** All Phase 3 critical bugs fixed and verified working.
2026-02-07 23:27:15 +02:00
14e1a8df51 Phase 3: Unified Cheshire Cat integration with WebSocket-based per-user isolation
Key changes:
- CatAdapter (bot/utils/cat_client.py): WebSocket /ws/{user_id} for chat
  queries instead of HTTP POST (fixes per-user memory isolation when no
  API keys are configured — HTTP defaults all users to user_id='user')
- Memory management API: 8 endpoints for status, stats, facts, episodic
  memories, consolidation trigger, multi-step delete with confirmation
- Web UI: Memory tab (tab9) with collection stats, fact/episodic browser,
  manual consolidation trigger, and 3-step delete flow requiring exact
  confirmation string
- Bot integration: Cat-first response path with query_llama fallback for
  both text and embed responses, server mood detection
- Discord bridge plugin: fixed .pop() to .get() (UserMessage is a Pydantic
  BaseModelDict, not a raw dict), metadata extraction via extra attributes
- Unified docker-compose: Cat + Qdrant services merged into main compose,
  bot depends_on Cat healthcheck
- All plugins (discord_bridge, memory_consolidation, miku_personality)
  consolidated into cat-plugins/ for volume mount
- query_llama deprecated but functional for compatibility
2026-02-07 20:22:03 +02:00
0a9145728e Ability to play Uno implemented in early stages! 2026-01-30 21:43:20 +02:00
7368ef0cd5 Added Japanese and Bulgarian addressing 2026-01-30 21:34:24 +02:00
ecd14cf704 Able to now address Miku in Cyrillic, Kanji and both Kanas, incl. Japanese honorifics 2026-01-27 19:53:18 +02:00
641a5b83e8 Improved Evil Mode toggle to handle edge cases of the pfp and role color change. Japanese swallow model compatible (should be). 2026-01-27 19:52:39 +02:00
dca58328e4 Tuned the Japanese mode system prompt and model better 2026-01-23 17:01:47 +02:00
fe0962118b Implemented new Japanese only text mode with WebUI toggle, utilizing a llama3.1 swallow dataset model. Next up is Japanese TTS. 2026-01-23 15:02:36 +02:00
eb03dfce4d refactor: Implement low-latency STT pipeline with speculative transcription
Major architectural overhaul of the speech-to-text pipeline for real-time voice chat:

STT Server Rewrite:
- Replaced RealtimeSTT dependency with direct Silero VAD + Faster-Whisper integration
- Achieved sub-second latency by eliminating unnecessary abstractions
- Uses small.en Whisper model for fast transcription (~850ms)

Speculative Transcription (NEW):
- Start transcribing at 150ms silence (speculative) while still listening
- If speech continues, discard speculative result and keep buffering
- If 400ms silence confirmed, use pre-computed speculative result immediately
- Reduces latency by ~250-850ms for typical utterances with clear pauses

VAD Implementation:
- Silero VAD with ONNX (CPU-efficient) for 32ms chunk processing
- Direct speech boundary detection without RealtimeSTT overhead
- Configurable thresholds for silence detection (400ms final, 150ms speculative)

Architecture:
- Single Whisper model loaded once, shared across sessions
- VAD runs on every 512-sample chunk for immediate speech detection
- Background transcription worker thread for non-blocking processing
- Greedy decoding (beam_size=1) for maximum speed

Performance:
- Previous: 400ms silence wait + ~850ms transcription = ~1.25s total latency
- Current: 400ms silence wait + 0ms (speculative ready) = ~400ms (best case)
- Single model reduces VRAM usage, prevents OOM on GTX 1660

Container Manager Updates:
- Updated health check logic to work with new response format
- Changed from checking 'warmed_up' flag to just 'status: ready'
- Improved terminology from 'warmup' to 'models loading'

Files Changed:
- stt-realtime/stt_server.py: Complete rewrite with Silero VAD + speculative transcription
- stt-realtime/requirements.txt: Removed RealtimeSTT, using torch.hub for Silero VAD
- bot/utils/container_manager.py: Updated health check for new STT response format
- bot/api.py: Updated docstring to reflect new architecture
- backups/: Archived old RealtimeSTT-based implementation

This addresses low latency requirements while maintaining accuracy with configurable
speech detection thresholds.
2026-01-22 22:08:07 +02:00
2934efba22 Implemented experimental real production ready voice chat, relegated old flow to voice debug mode. New Web UI panel for Voice Chat. 2026-01-20 23:06:17 +02:00
362108f4b0 Decided on Parakeet ONNX Runtime. Works pretty great. Realtime voice chat possible now. UX lacking. 2026-01-19 00:29:44 +02:00
50e4f7a5f2 Error in llama-swap catchall implemented + webhook notifier 2026-01-18 01:30:26 +02:00
d1e6b21508 Phase 4 STT pipeline implemented — Silero VAD + faster-whisper — still not working well at all 2026-01-17 03:14:40 +02:00
3e59e5d2f6 Phase 3 implemented — Text LLM can now stream to the TTS pipeline with the !miku say command 2026-01-17 00:01:17 +02:00
9943cecdec Phase 2 implemented and tested. Added warmup to pipeline and Miku queues tokens while the pipeline is warming up 2026-01-16 23:37:34 +02:00
b0066f3525 Tested Phase 1, fixed text channel blocking while in voice and implemented joining and leaving VC from Phase 2 2026-01-16 20:39:23 +02:00
911f11ee9f Untested Phase 1 (Foundation & Resource management) of voice chat integration 2026-01-16 13:01:08 +02:00
353c9c9583 Face Detector container now able to be created, started and stopped from within miku-bot container 2026-01-11 02:01:41 +02:00
2d3b9d0e08 Fix IndentationError in persona_dialogue.py by removing stray docstring delimiter 2026-01-10 23:01:28 +02:00
32c2a7b930 feat: Implement comprehensive non-hierarchical logging system
- Created new logging infrastructure with per-component filtering
- Added 6 log levels: DEBUG, INFO, API, WARNING, ERROR, CRITICAL
- Implemented non-hierarchical level control (any combination can be enabled)
- Migrated 917 print() statements across 31 files to structured logging
- Created web UI (system.html) for runtime configuration with dark theme
- Added global level controls to enable/disable levels across all components
- Added timestamp format control (off/time/date/datetime options)
- Implemented log rotation (10MB per file, 5 backups)
- Added API endpoints for dynamic log configuration
- Configured HTTP request logging with filtering via api.requests component
- Intercepted APScheduler logs with proper formatting
- Fixed persistence paths to use /app/memory for Docker volume compatibility
- Fixed checkbox display bug in web UI (enabled_levels now properly shown)
- Changed System Settings button to open in same tab instead of new window

Components: bot, api, api.requests, autonomous, persona, vision, llm,
conversation, mood, dm, scheduled, gpu, media, server, commands,
sentiment, core, apscheduler

All settings persist across container restarts via JSON config.
2026-01-10 20:46:19 +02:00
ce00f9bd95 Changed misleading face detector warning message on startup in the log 2026-01-09 00:13:03 +02:00
1fc3d74a5b Add dual GPU support with web UI selector
Features:
- Built custom ROCm container for AMD RX 6800 GPU
- Added GPU selection toggle in web UI (NVIDIA/AMD)
- Unified model names across both GPUs for seamless switching
- Vision model always uses NVIDIA GPU (optimal performance)
- Text models (llama3.1, darkidol) can use either GPU
- Added /gpu-status and /gpu-select API endpoints
- Implemented GPU state persistence in memory/gpu_state.json

Technical details:
- Multi-stage Dockerfile.llamaswap-rocm with ROCm 6.2.4
- llama.cpp compiled with GGML_HIP=ON for gfx1030 (RX 6800)
- Proper GPU permissions without root (groups 187/989)
- AMD container on port 8091, NVIDIA on port 8090
- Updated bot/utils/llm.py with get_current_gpu_url() and get_vision_gpu_url()
- Modified bot/utils/image_handling.py to always use NVIDIA for vision
- Enhanced web UI with GPU selector button (blue=NVIDIA, red=AMD)

Files modified:
- docker-compose.yml (added llama-swap-amd service)
- bot/globals.py (added LLAMA_AMD_URL)
- bot/api.py (added GPU selection endpoints and helper function)
- bot/utils/llm.py (GPU routing for text models)
- bot/utils/image_handling.py (GPU routing for vision models)
- bot/static/index.html (GPU selector UI)
- llama-swap-rocm-config.yaml (unified model names)

New files:
- Dockerfile.llamaswap-rocm
- bot/memory/gpu_state.json
- bot/utils/gpu_router.py (load balancing utility)
- setup-dual-gpu.sh (setup verification script)
- DUAL_GPU_*.md (documentation files)
2026-01-09 00:03:59 +02:00
9786f984a6 Fix: Explicitly pass change_role_color=True when switching modes after bipolar argument
When an argument ends and a winner is determined, the bot now explicitly
passes all mode change parameters (change_username, change_pfp, change_nicknames,
change_role_color) to ensure the winner's role color is properly restored.

- Evil Miku wins: Saves current color, switches to dark red (#D60004)
- Regular Miku wins: Restores previously saved color (from before Evil Mode)

This ensures the visual identity matches the active persona after arguments.
2026-01-06 14:01:39 +02:00
8012030ea1 Implement Bipolar Mode: Dual persona arguments with webhooks, LLM arbiter, and persistent scoreboard
Major Features:
- Complete Bipolar Mode system allowing Regular Miku and Evil Miku to coexist and argue via webhooks
- LLM arbiter system using neutral model to judge argument winners with detailed reasoning
- Persistent scoreboard tracking wins, percentages, and last 50 results with timestamps and reasoning
- Automatic mode switching based on argument winner
- Webhook management per channel with profile pictures and display names
- Progressive probability system for dynamic argument lengths (starts at 10%, increases 5% per exchange, min 4 exchanges)
- Draw handling with penalty system (-5% end chance, continues argument)
- Integration with autonomous system for random argument triggers

Argument System:
- MIN_EXCHANGES = 4, progressive end chance starting at 10%
- Enhanced prompts for both personas (strategic, short, punchy responses 1-3 sentences)
- Evil Miku triumphant victory messages with gloating and satisfaction
- Regular Miku assertive defense (not passive, shows backbone)
- Message-based argument starting (can respond to specific messages via ID)
- Conversation history tracking per argument with special user_id
- Full context queries (personality, lore, lyrics, last 8 messages)

LLM Arbiter:
- Decisive prompt emphasizing picking winners (draws should be rare)
- Improved parsing with first-line exact matching and fallback counting
- Debug logging for decision transparency
- Arbiter reasoning stored in scoreboard history for review
- Uses neutral TEXT_MODEL (not evil) for unbiased judgment

Web UI & API:
- Bipolar mode toggle button (only visible when evil mode is on)
- Channel ID + Message ID input fields for argument triggering
- Scoreboard display with win percentages and recent history
- Manual argument trigger endpoint with string-based IDs
- GET /bipolar-mode/scoreboard endpoint for stats retrieval
- Real-time active arguments tracking (refreshes every 5 seconds)

Prompt Optimizations:
- All argument prompts limited to 1-3 sentences for impact
- Evil Miku system prompt with variable response length guidelines
- Removed walls of text, emphasizing brevity and precision
- "Sometimes the cruelest response is the shortest one"

Evil Miku Updates:
- Added height to lore (15.8m tall, 10x bigger than regular Miku)
- Height added to prompt facts for size-based belittling
- More strategic and calculating personality in arguments

Integration:
- Bipolar mode state restoration on bot startup
- Bot skips processing messages during active arguments
- Autonomous system checks for bipolar triggers after actions
- Import fixes (apply_evil_mode_changes/revert_evil_mode_changes)

Technical Details:
- State persistence via JSON (bipolar_mode_state.json, bipolar_webhooks.json, bipolar_scoreboard.json)
- Webhook caching per guild with fallback creation
- Event loop management with asyncio.create_task
- Rate limiting and argument conflict prevention
- Globals integration (BIPOLAR_MODE, BIPOLAR_WEBHOOKS, BIPOLAR_ARGUMENT_IN_PROGRESS, MOOD_EMOJIS)

Files Changed:
- bot/bot.py: Added bipolar mode restoration and argument-in-progress checks
- bot/globals.py: Added bipolar mode state variables and mood emoji mappings
- bot/utils/bipolar_mode.py: Complete 1106-line implementation
- bot/utils/autonomous.py: Added bipolar argument trigger checks
- bot/utils/evil_mode.py: Updated system prompt, added height info to lore/prompt
- bot/api.py: Added bipolar mode endpoints (trigger, toggle, scoreboard)
- bot/static/index.html: Added bipolar controls section with scoreboard
- bot/memory/: Various DM conversation updates
- bot/evil_miku_lore.txt: Added height description
- bot/evil_miku_prompt.txt: Added height to facts, updated personality guidelines
2026-01-06 13:57:59 +02:00
1e6e097958 Add role color management to evil mode
- Evil mode now saves current 'Miku Color' role color before changing
- Sets role color to #D60004 (dark red) when evil mode is enabled
- Restores saved color when evil mode is disabled
- Color is persisted in evil_mode_state.json between restarts
- Role color changes are skipped on startup restore to avoid rate limits
2026-01-02 19:45:56 +02:00
5d1e669b5a Add evil mode support to figurine tweet notifier
- Figurine DM notifications now respect evil mode state
- Evil Miku sends cruel, mocking comments about merch instead of excited ones
- Normal Miku remains enthusiastic and friendly about figurines
- Both modes use appropriate sign-off emojis (cute vs dark)
2026-01-02 18:09:50 +02:00
6ec33bcecb Implement Evil Miku mode with persistence, fix API event loop issues, and improve formatting
- Added Evil Miku mode with 4 evil moods (aggressive, cunning, sarcastic, evil_neutral)
- Created evil mode content files (evil_miku_lore.txt, evil_miku_prompt.txt, evil_miku_lyrics.txt)
- Implemented persistent evil mode state across restarts (saves to memory/evil_mode_state.json)
- Fixed API endpoints to use client.loop.create_task() to prevent timeout errors
- Added evil mode toggle in web UI with red theme styling
- Modified mood rotation to handle evil mode
- Configured DarkIdol uncensored model for evil mode text generation
- Reduced system prompt redundancy by removing duplicate content
- Added markdown escape for single asterisks (actions) while preserving bold formatting
- Evil mode now persists username, pfp, and nicknames across restarts without re-applying changes
2026-01-02 17:11:58 +02:00
b38bdf2435 feat: Add advanced engagement submenu with user targeting and engagement types
- Replace simple 'Engage Random User' button with expandable submenu
- Add user ID input field for targeting specific users
- Add engagement type selection: random, activity-based, general, status-based
- Update API endpoints to accept user_id and engagement_type parameters
- Modify autonomous functions to support targeted engagement
- Maintain backward compatibility with random user/type selection as default
2025-12-16 23:13:19 +02:00
65e6c3e7ea Add 'Detect and Join Conversation' button to Web UI and CLI
- Added /autonomous/join-conversation API endpoint in api.py
- Added 'Detect and Join Conversation' button to Web UI under Autonomous Actions
- Added 'autonomous join-conversation' command to CLI tool (miku-cli.py)
- Updated miku_detect_and_join_conversation_for_server to support force=True parameter
- When force=True: skips time limit, activity checks, and random chance
- Force mode uses last 10 user messages regardless of age
- Manual triggers via Web UI/CLI now work even with old messages
2025-12-10 14:57:59 +02:00
76aaf6c437 Fix autonomous logic: prevent actions when user addresses Miku
- Moved on_message_event() call to END of message processing in bot.py
- Only track messages for autonomous when NOT addressed to Miku
- Fixed autonomous_engine.py to convert all message-triggered actions to join_conversation
- Prevent inappropriate autonomous actions (general, share_tweet, change_profile_picture) when triggered by user messages
- Ensures Miku responds to user messages FIRST before any autonomous action fires

This fixes the issue where autonomous actions would fire before Miku's response to user messages, and ensures the 'detect and join conversation' safeguard works properly.
2025-12-10 10:56:34 +02:00
711101816a Fix: Apply twscrape monkey patch to resolve 'Failed to parse scripts' error
Twitter changed their JavaScript response format to include unquoted keys in JSON objects, which breaks twscrape's parser. This fix applies a monkey patch that uses regex to quote the unquoted keys before parsing.

This resolves the issue preventing figurine notifications from being sent for the past several days.

Reference: https://github.com/vladkens/twscrape/issues/284
2025-12-10 09:48:25 +02:00
330cedd9d1 chore: organize backup files into dated directory structure
- Consolidated all .bak.* files from bot/ directory into backups/2025-12-07/
- Moved unused autonomous_wip.py to backups (verified not imported anywhere)
- Relocated old .bot.bak.80825/ backup directory into backups/2025-12-07/old-bot-bak-80825/
- Preserved autonomous_v1_legacy.py as it is still actively used by autonomous.py
- Created new backups/ directory with date-stamped subdirectory for better organization
2025-12-07 23:54:38 +02:00
9009e9fc80 Add animated GIF support for profile pictures
- Detect animated GIFs and preserve animation frames during upload
- Extract dominant color from first frame for role color syncing
- Generate multi-frame descriptions using existing video analysis pipeline
- Skip face detection/cropping for GIFs to maintain original animation
- Update UI to inform users about GIF support and Nitro requirement
- Add metadata flag to distinguish animated vs static profile pictures
2025-12-07 23:48:12 +02:00
d58be3b33e Remove all Ollama remnants and complete migration to llama.cpp
- Remove Ollama-specific files (Dockerfile.ollama, entrypoint.sh)
- Replace all query_ollama imports and calls with query_llama
- Remove langchain-ollama dependency from requirements.txt
- Update all utility files (autonomous, kindness, image_generation, etc.)
- Update README.md documentation references
- Maintain backward compatibility alias in llm.py
2025-12-07 17:50:28 +02:00
8c74ad5260 Initial commit: Miku Discord Bot 2025-12-07 17:15:09 +02:00