- profile_picture_manager.py:
- Add ORIGINAL_PATH constant; save full-res original before every crop
- Add skip_crop param to change_profile_picture() for manual crop workflow
- Add manual_crop(x,y,w,h) method with Discord avatar update + role color sync
- Add auto_crop_only() to re-run face-detection crop on stored original
- Add update_description() with Cheshire Cat declarative memory re-injection
- Add regenerate_description() via vision model
- Skip crop step if image is already at/below 512x512
- api.py:
- GET /profile-picture/image/original — serve full-res original (no-cache)
- GET /profile-picture/image/current — serve current cropped avatar (no-cache)
- POST /profile-picture/change-no-crop — acquire image, skip auto-crop
- POST /profile-picture/manual-crop — apply crop coords {x,y,width,height}
- POST /profile-picture/auto-crop — re-run intelligent crop on original
- POST /profile-picture/description — save freeform description + Cat inject
- POST /profile-picture/regenerate-description — re-generate via vision model
- GET /profile-picture/description — fetch current description text
- index.html:
- Add new tab11 '🖼️ Profile Picture Management'
- Remove PFP + role color sections from Actions tab (tab2)
- Add Cropper.js 1.6.2 via CDN for manual square crop
- Tab layout: action buttons, file upload, auto/manual crop toggle,
Cropper.js interface, side-by-side original/cropped previews,
role color management, freeform description editor, metadata box (bottom)
- Wire switchTab hook for tab11 → loadPfpTab()
- All new JS functions: pfpChangeDanbooru, pfpUploadCustom, pfpRestoreFallback,
pfpShowCropInterface, pfpApplyManualCrop, pfpApplyAutoCrop, pfpSaveDescription,
pfpRegenerateDescription, pfpRefreshPreviews, setCustomRoleColor, resetRoleColor
- Fixed missing client parameter in animated GIF webhook update path
- Added get_persona_avatar_urls() helper that returns bot's current Discord
avatar URL for Miku persona (always fresh, no cache lag)
- Pass avatar_url on every webhook.send() call in bipolar_mode.py,
persona_dialogue.py, and api.py so avatars always match current pfp
regardless of webhook cache state
- 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.
- 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