Compare commits

..

34 Commits

Author SHA1 Message Date
10d95951a3 feat: implement QoL features (toast notifications, command palette, auto-save)
Add three major quality-of-life features to improve user experience:

Toast Notification System:
- Non-blocking notifications for all major actions
- Four variants: success, error, warning, info
- Auto-dismiss with progress bar
- Bottom-right positioning with smooth animations
- Replaced old status messages throughout the app

Command Palette (Ctrl+P):
- Keyboard-driven quick access to all actions
- 14 built-in commands across 5 categories
- Real-time fuzzy search with arrow key navigation
- Shows keyboard shortcuts for each command
- Grouped by category with visual feedback

Auto-save & Recovery:
- Automatic draft saving (1s debounce)
- Per-character draft storage in localStorage
- Auto-recovery on app restart or character switch
- Draft age display (e.g., "2 hours ago")
- Auto-cleanup of drafts older than 7 days
- Clears draft when message is sent

Updated README with new Ctrl+P keyboard shortcut
Updated ROADMAP with Phase 8: Quality of Life & Polish section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 12:27:20 -07:00
50d3177e9e feat: implement chat branching and checkpoints
Add conversation branching system that allows creating and exploring alternate conversation paths from any message point. Each branch maintains its own complete message history.

Backend (Rust):
- Branch data structures with backward-compatible storage migration
- Tauri commands for create, switch, delete, rename, and list operations
- Automatic cleanup of child branches when parent is deleted

Frontend:
- Branch button on all messages for creating new branches
- Branch indicator badge in header showing active branch
- Branch manager modal with full branch list and controls
- Visual improvements to message action toolbar (more opaque, positioned above messages)

Branches are character-specific and persist across sessions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 08:17:08 -07:00
86a9d54e70 feat: replace character creation prompts with themed modal
Replace native prompt() dialogs with a themed inline form modal for character creation:
- Modal displays with name input and system prompt textarea
- Includes Cancel and Create buttons
- Escape key closes the modal
- Auto-focuses name input when opened
- Proper event listener cleanup
- Matches existing UI theme and styling

This provides a much better user experience with the application's dark theme, compared to the browser's default prompt dialogs which looked out of place.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:28:42 -07:00
600b50f239 feat: add active features indicator badges in header
Add visual badges in header showing which roleplay features are currently active:
- World Info: Shows count of enabled entries (e.g., "WI: 3")
- Persona: Shows persona name when enabled
- Preset: Shows active preset name
- Examples: Shows when message examples are enabled
- Author's Note: Shows when author's note is enabled (displays as "A/N")

Badges update dynamically when features are toggled, providing at-a-glance visibility of active roleplay features without opening the Roleplay Tools panel.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:26:39 -07:00
a7c9657ff1 feat: make context limit configurable in API settings
Add context limit field to API settings that:
- Stores context limit in config (defaults to 200000)
- Allows users to set custom limits for different models
- Uses configured limit in token counter display
- Shows format like "2.5k / 200k tokens" using actual limit

This allows proper token tracking for non-Claude models with
different context windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:20:13 -07:00
e47bd3bf87 refactor: remove color coding from token counter
Keep simple clean format: '2.5k / 200k tokens' without color changes
2025-10-16 22:16:25 -07:00
41437e1751 feat: make token counter visible by default with color coding
Changes:
- Remove display:none from token counter (always visible)
- Add compact formatting (2.5k / 200k tokens instead of 2500 tokens)
- Color coding based on usage percentage:
  - Green: < 50% usage
  - Yellow: 50-80% usage
  - Red: > 80% usage
- Keep counter visible even on error (shows 0 / 200k)
- Improve discoverability of token tracking feature

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:13:15 -07:00
8c70e0558f feat: add keyboard shortcuts and copy message buttons
Keyboard shortcuts:
- Up Arrow: Edit last user message (when input at start)
- Left/Right Arrow: Navigate swipes (when not in input)
- Escape: Close panels/modals, cancel editing
- Ctrl+K: Focus message input
- Ctrl+/: Toggle Roleplay Tools
- Ctrl+Enter: Send message (alternative)

Message controls:
- Add Copy Message button for both user and assistant messages
- Visual feedback (checkmark) after copying
- 2-second feedback duration

Updated README to reflect actual implemented shortcuts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:12:14 -07:00
0bd1590681 feat: replace preset prompts with inline forms
Replace popup dialogs with themed inline forms for preset creation and
duplication. Both operations now use consistent UI styling with proper
theme colors, validation, and cancel/save workflows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 22:03:37 -07:00
26d1430d6a feat: replace popup dialogs with inline editing for World Info and Instructions
Replaced all prompt() dialogs with themed inline forms for better UX:
- World Info entries now have inline add/edit forms
- Instruction blocks now have inline add/edit forms
- Forms match app theme and stay within the interface
- Added CSS styling for edit forms

Still using prompts for preset creation/duplication - will replace in next commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:54:28 -07:00
bc05747f5f fix: add proper theming for preset textareas
Fixed black text on white background in preset system additions and authors note textareas by adding CSS rules with !important to override inline styles.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:46:43 -07:00
71bac12cd9 docs: rewrite README to be more concise and professional
Removed excessive emojis, marketing fluff, and outdated information. Updated to reflect actually implemented features and current development focus.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:37:39 -07:00
9da17c824d docs: update roadmap to mark message examples as complete
Updated current focus to Chat Branching/Checkpoints as next feature. Added Message Examples and Token Counter to implemented features list.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:34:45 -07:00
d8cb4a768b feat: implement message examples usage from character cards
Add support for using mes_example field from character cards to teach the AI the character's voice and writing style. Examples are parsed, processed with template variable replacement, and injected into the context at a configurable position.

Backend changes:
- Extended RoleplaySettings with examples_enabled and examples_position fields
- Implemented parse_message_examples() to parse <START>-delimited example blocks
- Added example injection in build_api_messages() with position control
- Integrated examples into token counter with accurate counting
- Created update_examples_settings command for saving settings

Frontend changes:
- Added Message Examples UI controls in Author's Note tab
- Checkbox to enable/disable examples
- Dropdown to select injection position (after_system/before_history)
- Save button with success/error feedback
- Token breakdown now shows examples token count
- Settings load/save integrated with roleplay panel

Message examples help the AI understand character personality, speaking patterns, and response style by providing concrete examples of how the character should respond.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:33:50 -07:00
b9230772ed feat: implement enhanced message controls with regenerate any message
Added comprehensive message control features for fine-grained conversation management:

Backend (Rust):
- Extended Message struct with 'pinned' and 'hidden' boolean fields
- Added delete_message_at_index() command for removing any message
- Added toggle_message_pin() command to mark important messages
- Added toggle_message_hidden() command to temporarily hide messages
- Added continue_message() command to append AI continuations
- Added regenerate_at_index() command to regenerate ANY message (not just last)

Frontend (JavaScript):
- Added delete, pin, hide buttons to all messages (user & assistant)
- Added continue button for assistant messages
- Updated regenerate to work on any message, not just the last one
- Implemented state persistence for pinned/hidden in chat history
- Added dynamic icon changes for hide/unhide states
- Integrated with token counter for real-time updates

UI/UX (CSS):
- Pinned messages: accent-colored left border with glow effect
- Hidden messages: 40% opacity with blur effect (70% on hover)
- Delete button: red hover warning (#ef4444)
- Active state indicators for pin/hide buttons
- Always-visible controls on hidden messages for quick access

Features:
- Delete any message with confirmation dialog
- Pin messages to always keep them in context
- Hide messages with visual blur (still in context but dimmed)
- Continue incomplete assistant responses
- Regenerate any assistant message (creates new swipe)
- All states persist in chat history JSON

This completes Phase 3.2 "Enhanced Message Controls" from the roadmap,
providing users with complete control over their conversation history.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 17:19:07 -07:00
9b4bc63e1a fix: use theme CSS variables for user messages
User messages were using hard-coded indigo colors instead of respecting
the selected theme. Now properly uses:
- var(--accent) for gradient start
- var(--user-msg) for gradient end
- Dynamic box-shadow based on theme color

This ensures user messages match the selected theme (Dark, Light, Abyss,
Nord, Mocha, etc.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 13:26:39 -07:00
501f226542 chore: update Cargo.lock for tiktoken-rs dependency 2025-10-16 13:25:02 -07:00
2444ca0811 feat: implement token counter with real-time breakdown
Add comprehensive token counting functionality to provide visibility into
context usage:

Backend (Rust):
- Add tiktoken-rs dependency for OpenAI-compatible token counting
- Implement get_token_count command with detailed breakdown
- Count tokens for: system prompt, preset instructions, persona, world info,
  author's note, message history, and current input
- Per-section token breakdown for optimization insights

Frontend (JavaScript/HTML/CSS):
- Add token counter widget in status bar
- Real-time updates as user types (debounced 300ms)
- Expandable breakdown tooltip showing per-section counts
- Automatic update when chat history loads or changes
- Clean, minimal UI with hover interactions

Features:
- Accurate token counting using cl100k_base tokenizer
- Debounced updates for performance
- Detailed breakdown by context section
- Visual indicator with total token count
- Click to expand/collapse detailed breakdown
- Auto-hide when no character is active

This completes the "Must-Have for Basic Roleplay" features from the roadmap:
 World Info/Lorebooks
 Author's Note
 Token Counter
- Message Examples Usage (next)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 13:24:49 -07:00
828475ae4f feat: make built-in presets editable with restore-to-default
Add ability to edit built-in presets (Default, Roleplay, Creative Writing,
Assistant) while preserving original defaults:

- Built-in presets are now fully editable (system additions, author's note,
  instruction blocks)
- Modifications are saved as overrides in ~/.config/claudia/presets/
- "Modified" badge appears when built-in preset has been customized
- "Restore to Default" button removes overrides and restores originals
- Backend commands: is_builtin_preset_modified, restore_builtin_preset
- All instruction blocks support expand/collapse and drag-and-drop reordering

Also update ROADMAP.md to reflect completed features:
- World Info/Lorebook System 
- Author's Note 
- User Personas 
- Regex Scripts 
- Chat History Import/Export 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 13:19:43 -07:00
cdb7baa197 feat: enhance roleplay features with regex, exports, and validation
This commit implements Options B, C, and D for enhanced roleplay capabilities:

**Option B: Enhanced Roleplay Features**
- Add regex pattern matching for World Info keywords with fallback to literal matching
- Make scan depth configurable (default: 20, range: 1-100 messages)
- Make Author's Note insertion depth configurable (default: 3, range: 1-50 messages)
- Add World Info import/export functionality with merge/replace options
- Update WorldInfoEntry struct with use_regex field
- Update RoleplaySettings with scan_depth and authors_note_depth fields
- Modify build_roleplay_context() to return configurable note_depth
- Update all 4 chat functions to use configurable Author's Note depth

**Option C: Chat Export Enhancements**
- Add export_chat_as_markdown: Clean markdown format with bold role labels
- Add export_chat_as_text: Simple plain text format with decorative separator
- Add export_chat_as_html: Styled HTML with responsive design and color-coded messages
- All exports use native file dialogs with appropriate file filters

**Option D: Polish & Quality of Life**
- Add validate_regex_pattern command for real-time regex validation
- Add update_roleplay_depths command with range validation
- Enhance add_world_info_entry with input validation (regex, empty checks)
- Enhance update_world_info_entry with input validation
- Add detailed error messages for all validation failures

**Technical Details:**
- Add regex dependency to Cargo.toml
- Use #[serde(default)] attributes for backward compatibility
- Graceful error handling with fallback strategies
- HTML export includes proper escaping for XSS protection
- All new commands registered in Tauri invoke_handler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 17:01:16 -07:00
9707121a59 feat: implement Phase 2 roleplay context injection
Add full context injection system for World Info, Author's Note, and Persona:

- Add scan_for_world_info() function to detect keywords in last 20 messages
- Add build_roleplay_context() to assemble all roleplay additions
- Inject Persona into system prompt as [{{user}}'s Persona: name - desc]
- Inject activated World Info entries into system prompt by priority
- Inject Author's Note as system message before last 3 messages
- Apply context injection to all 4 chat functions:
  - chat() - regular non-streaming
  - chat_stream() - streaming
  - generate_response_only() - regenerate non-streaming
  - generate_response_stream() - regenerate streaming

All roleplay features now fully functional and affecting AI generation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 21:11:42 -07:00
e364ecfc51 feat: add World Info/Lorebook, Author's Note, and Persona systems
Backend changes:
- Add RoleplaySettings and WorldInfoEntry data structures
- Implement per-character roleplay settings storage in ~/.config/claudia/roleplay_{id}.json
- Add Tauri commands for CRUD operations on World Info entries
- Add commands for saving Author's Note and Persona settings

Frontend changes:
- Add World Info entry management UI with add/edit/delete functionality
- Implement keyword-triggered context injection system with priority ordering
- Add Author's Note textarea with enable toggle
- Add Persona name and description fields with enable toggle
- Load roleplay settings when opening the roleplay panel
- Add CSS styles for World Info entry cards with hover effects

Features:
- World Info entries support multiple keywords, priority levels, and enable/disable
- Settings are per-character and persist across sessions
- Entries sorted by priority (higher priority injected first)
- Clean UI with edit/delete buttons and visual feedback
2025-10-14 19:55:08 -07:00
5d32489c3c feat: add roleplay tools sidebar UI
Created left-sliding sidebar for roleplay features:
- Slides in from left (opposite of settings sidebar from right)
- Three tabs: World Info, Author's Note, Persona
- Hamburger menu button in header
- Overlay backdrop closes sidebar
- Tab switching with smooth transitions
- Responsive design matching settings panel

UI structure ready for implementation of:
- World Info/Lorebook entries with keyword triggers
- Author's Note for prompt injection
- Persona system for user character description
2025-10-14 18:07:19 -07:00
83e9793dce feat: add chat history import and export functionality
Implemented full chat history import/export with JSON format:
- Export button saves current conversation to JSON file
- Import button loads conversation from JSON file
- File dialog integration using tauri-plugin-dialog
- Message count feedback on successful import
- Automatic history reload after import
- Preserves all message data including swipes and timestamps
- Smart error handling (ignores cancelled dialogs)

Backend (Rust):
- export_chat_history: Opens save dialog, writes JSON to selected path
- import_chat_history: Opens file picker, parses JSON, saves to current character
- Message migration for backward compatibility
- Returns helpful feedback (file path on export, message count on import)

Frontend (JavaScript):
- Export/import buttons in header with up/down arrow icons
- Status updates during operations
- Auto-reload chat view after import
- Error handling with user-friendly messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 18:03:34 -07:00
84d3e0df67 feat: add font size customization with slider control
Implemented global font size scaling with range slider:
- Adjustable from 80% to 140% in 10% increments
- Slider in Appearance tab with live value display
- Persistent preference saved to localStorage
- Updates CSS custom property --base-font-size
- Scales entire UI proportionally from 11.2px to 19.6px
- Smooth transitions with styled slider thumb
- Live preview as you drag the slider

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:34:09 -07:00
30e6af61ca feat: add view mode toggle with compact/cozy/comfortable options
Implemented message density control with three view modes:
- Compact: Tight spacing (10px gaps), smaller text (13px), small avatars (24px)
- Cozy: Balanced spacing (16px gaps), default text (14px) - default mode
- Comfortable: Spacious layout (24px gaps), larger text (15px), larger avatars (32px)

Features:
- View mode selector in Appearance tab
- Persistent preference saved to localStorage
- Dynamic CSS classes applied to body element
- Adjusts message padding, gaps, font sizes, avatar sizes
- Scales headings, code blocks, and all UI elements proportionally

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:32:07 -07:00
32fc57fab0 feat: add theme customization with 6 color schemes
Added comprehensive theme system with:
- 6 themes: Dark (default), Darker, Midnight Blue, Forest, Sunset, Light
- New Appearance tab in settings with theme selector
- Live theme preview showing user/assistant message styles
- Theme persistence using localStorage
- Dynamic CSS variable updates for instant theme switching
- Each theme includes custom gradients, accent colors, and text colors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:30:06 -07:00
efa3ccbd26 feat: redesign settings as slide-in sidebar with collapsible sections
- Changed from full-screen overlay to 500px slide-in sidebar from right
- Added dark overlay backdrop that dims chat
- Organized character settings into collapsible sections:
  * Basic Information (name, avatar, system prompt, greeting)
  * Roleplay Details (personality, description, scenario, examples)
  * Advanced Settings (post-history, alternate greetings)
  * Metadata (tags, creator, version, notes)
- Smooth slide and collapse animations
- Click overlay to close sidebar
- Responsive: full width on mobile
- More compact button layouts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:14:51 -07:00
b9ea771ff0 feat: add better loading states and animations
- Added spinning loading indicators on all buttons
- Fade-in animations for newly revealed elements
- Loading states with visual feedback (opacity, cursor)
- Smooth CSS animations for spinners and fades
- Loading indicators on: API validation, save operations,
  regenerate buttons, and character operations
- Improved UX with clear visual feedback during async operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:11:11 -07:00
4866c11245 feat: improve status feedback with detailed messages and colors
- Added color-coded status indicators (success, error, streaming)
- Detailed status messages for all operations
- Success messages auto-reset to "Ready" after 2 seconds
- Error messages show context for debugging
- Status feedback for: API calls, character switching, history clearing,
  configuration saving, message generation, and regeneration
- Smooth color transitions for better UX

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:09:57 -07:00
e0239aceda feat: add character name indicators to assistant messages
- Character names display in accent color above all assistant messages
- Created renderAssistantContent() helper for consistent rendering
- Character names show on new messages, history, swipes, and regenerations
- Styled with small, bold text for clear attribution
- Enhances multi-character roleplay clarity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:08:39 -07:00
4694114ff9 feat: add message timestamps with smart formatting
- Added timestamp field to Message struct in Rust backend
- Timestamps automatically captured on message creation
- Smart relative time formatting (Just now, Xm ago, time, date)
- Timestamps display below message content with subtle styling
- Fixed avatar squishing issue with flex-shrink: 0
- Backward compatible with existing messages via serde(default)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 12:07:19 -07:00
ab6ae14bbc docs: note current focus on UI/UX improvements before roleplay features 2025-10-14 09:01:58 -07:00
a9b686f0d1 docs: add comprehensive roleplay enhancement roadmap
Created ROADMAP.md with detailed plan to transform Claudia into a full-featured
roleplay platform comparable to SillyTavern. Based on extensive research of
SillyTavern's features and roleplay community needs.

Key planned features organized in 7 phases:
- Phase 1: World Info/Lorebooks, Author's Note, Jailbreak Templates
- Phase 2: User Personas, Character Expressions, Message Examples
- Phase 3: Chat Branching, Enhanced Message Controls, Timeline Viz
- Phase 4: Group Chats with multi-character support
- Phase 5: Token Counter, Context Templates, Smart Management
- Phase 6: Quick Replies, Macros, Regex Scripts, Hotkeys
- Phase 7: Polish and UX improvements

Updated README.md to:
- Reflect current roleplay-focused vision
- Document all implemented features
- Reference the detailed roadmap
- Add version milestones (v0.1.0 → v0.2.0)

Next target: v0.2.0 "Roleplay Foundation" with World Info, Author's Note,
and Token Counter as the core infrastructure for quality roleplay.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 08:56:55 -07:00
9 changed files with 11923 additions and 428 deletions

3631
CELIA 3.8.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,28 +1,36 @@
# Claudia # Claudia
Beautiful AI desktop companion built with Tauri and Rust. Desktop AI chat application built with Tauri and Rust, focused on roleplay and character-based interactions.
## Features ## Features
### Core Features ### Chat
- 🎨 **Beautiful glassmorphic UI** with gradient backgrounds and blur effects - Streaming responses with real-time display
- 🔧 **Bring-your-own-API** - supports any Anthropic-compatible API - Full markdown rendering with syntax highlighting
- **API validation** via /v1/models endpoint - Message swipes (multiple response alternatives)
- 💬 **Full conversation context** - AI remembers your entire conversation - Edit and regenerate from any message
- 💾 **Persistent chat history** - conversations saved between sessions - Per-character conversation history
- 🎯 **Custom window controls** - drag, minimize, maximize, close - Copy code blocks with one click
### Message Display ### Characters
- 📝 **Full markdown rendering** - headers, lists, tables, links, blockquotes - V2/V3 character card import/export (PNG format)
- 🎨 **Syntax highlighting** - beautiful code blocks with highlight.js - Multiple characters with avatar support
- 📋 **Copy code blocks** - one-click copy button on hover - Full character editor (description, personality, scenario, examples, etc.)
- **Smooth animations** - elegant message transitions - Character-specific chat history
### User Experience ### Roleplay Tools
- ⌨️ **Keyboard shortcuts** - Enter or Ctrl+Enter to send, Shift+Enter for new lines - World Info/Lorebook system with keyword detection and priority
- 🗑️ **Clear conversations** - easily start fresh - Author's Note with configurable positioning
- 🎯 **Auto-resizing input** - textarea grows with your message - User Personas with chat/character locking
- 🎭 **Light/dark mode** - automatic based on system preferences - Prompt Presets with instruction blocks
- Message Examples from character cards
- Regex Scripts for text transformations
- Token counter with per-section breakdown
### API
- Bring-your-own-API (Anthropic-compatible)
- Automatic model detection via /v1/models
- API validation and error handling
## Running ## Running
@@ -31,31 +39,49 @@ npm install
npm run dev npm run dev
``` ```
Build: Build for production:
```bash ```bash
npm run build npm run build
``` ```
**Note**: The dev script includes `WEBKIT_DISABLE_DMABUF_RENDERER=1` to fix Wayland compatibility issues on KDE Plasma.
## Configuration ## Configuration
On first launch, click settings and configure: On first launch, configure in Settings:
- Base URL (e.g., https://api.anthropic.com) - Base URL (e.g., https://api.anthropic.com)
- API Key - API Key
- Model (validated from /v1/models endpoint) - Model
- Config stored in `~/.config/claudia/config.json` Config stored in `~/.config/claudia/config.json`
- Chat history stored in `~/.config/claudia/history.json`
## Usage ## Keyboard Shortcuts
### Keyboard Shortcuts
- **Enter** - Send message - **Enter** - Send message
- **Shift+Enter** - New line in message - **Shift+Enter** - New line
- **Ctrl+Enter** - Send message (alternative)
- **Up Arrow** - Edit last user message (when input is at start)
- **Left/Right Arrow** - Navigate between response alternatives
- **Escape** - Close panels/modals, cancel editing
- **Ctrl+K** - Focus message input
- **Ctrl+P** - Open command palette (quick access to all actions)
- **Ctrl+/** - Toggle Roleplay Tools panel
### Interface ## Roadmap
- **Drag header** - Move window around your desktop
- **Trash icon** - Clear conversation history See [ROADMAP.md](ROADMAP.md) for detailed development plans.
- **Settings icon** - Configure API settings
- **Minimize/Maximize** - Window controls **Current Focus:** Chat Branching/Checkpoints for non-linear conversation exploration
**Upcoming:**
- Chat branching with timeline visualization
- Character expression sprites
- Group chats with multiple characters
- Quick replies and macro system
- Context templates for different model formats
## Development
Built with:
- Tauri 2.0
- Rust backend
- Vanilla JavaScript frontend
- tiktoken-rs for token counting

504
ROADMAP.md Normal file
View File

@@ -0,0 +1,504 @@
# Claudia Roleplay Enhancement Roadmap
## Current Status
### ✅ Implemented Features
- V2/V3 Character Card Import/Export
- Message Swipes (multiple response alternatives)
- Streaming Responses with toggle
- Character Management (multiple characters)
- Character Avatars with upload and zoom
- Expanded Character Editor (all v2/v3 fields)
- Prompt Presets System (built-in and custom presets with instruction blocks)
- Editable Built-in Presets with Restore to Default
- World Info/Lorebook System (keyword detection, priority, insertion)
- Author's Note (configurable depth and positioning)
- User Personas (identity management with chat/character locking)
- Regex Scripts (global and character-scoped text transformations)
- Chat History Import/Export (JSON format)
- Enhanced Message Controls (delete, pin, hide, continue, regenerate any message)
- Token Counter (real-time display with per-section breakdown)
- Message Examples (character card examples injected into context)
- Chat Branching/Checkpoints (create, switch, delete, rename branches from any message)
### 🎯 Current Focus: Quality of Life & Polish
**Next Up:** Implementing high-impact QoL features to reduce friction and improve user experience - starting with Toast Notifications, Command Palette, Auto-save, Drag & Drop, and Chat Search.
**Recent Completion:** Chat Branching/Checkpoints - Full conversation branching system allowing users to create and explore alternate conversation paths from any message point. Each branch maintains its own complete message history with a branch manager modal for easy navigation.
## Phase 1: Core Roleplay Infrastructure (High Priority)
**Goal: Enable basic roleplay-focused prompt engineering**
### 1. World Info/Lorebook System ✅
- [x] Create UI for managing lorebook entries (keyword, content, priority)
- [x] Implement keyword detection in recent messages
- [x] Add context injection before message generation
- [x] Support recursive entry activation
- [x] Per-character lorebook assignment
- [x] Import/export lorebook files
**Why Important:** World Info is the foundation of consistent roleplay. It allows dynamic context injection based on what's currently relevant in the conversation, saving tokens while maintaining world consistency.
### 2. Author's Note ✅
- [x] Add configurable Author's Note field (inserted at depth 1-5)
- [x] Position control (after system, before/after examples, etc.)
- [x] Per-character Author's Note support
- [x] Template variables in Author's Note
**Why Important:** Author's Note is considered better than system prompts for roleplay because it appears closer to the actual conversation, reducing AI tendency to ignore or forget instructions.
### 3. Jailbreak Templates ✅ (Implemented as Prompt Presets)
- [x] Add jailbreak template field in settings (Prompt Presets with system additions)
- [x] Preset jailbreak templates for roleplay (Built-in presets: Default, Roleplay, Creative Writing, Assistant)
- [x] Per-character jailbreak override option (Active preset per character)
- [x] Template preview and testing (Editable instruction blocks with live preview)
**Why Important:** Many roleplay scenarios require specific prompting to work well with API safety filters and to maintain character consistency.
## Phase 2: Enhanced Character Features (High Priority)
**Goal: Better character representation and user identity**
### 1. User Personas ✅
- [x] Create persona management UI (name, description, avatar)
- [x] Chat-level persona locking
- [x] Character-level persona locking
- [x] Default persona setting
- [x] Quick persona switching
**Why Important:** Allows users to have multiple identities for different roleplay scenarios without manually changing their name and description each time.
### 2. Character Expressions/Sprites
- [ ] Support for emotion-based character images
- [ ] Sentiment analysis of AI responses (local model)
- [ ] 28+ emotion presets (happy, sad, angry, neutral, etc.)
- [ ] Expression sprite packs (import/export)
- [ ] Manual expression override with /emote command
- [ ] Sprite positioning options (beside chat, behind chat, etc.)
**Why Important:** Visual representation of character emotions dramatically enhances immersion and makes conversations feel more alive.
### 3. Message Examples in Context ✅
- [x] Actually use mes_example field from character cards
- [x] Format and inject into prompt properly
- [x] Position control in context
- [x] Token budget allocation for examples
**Why Important:** Message examples help the AI understand the character's voice and writing style, leading to more accurate portrayals.
## Phase 3: Advanced Chat Management (Medium Priority)
**Goal: Non-linear conversation control**
### 1. Chat Branching/Checkpoints ✅
- [x] Save conversation state at any message
- [x] Create branches from any point
- [x] Switch between branches
- [x] Visual branch indicator in UI
- [x] Branch naming and organization
- [x] Delete branches
- [ ] Merge branches (deferred - nice to have)
**Why Important:** Roleplay often involves exploring "what if" scenarios. Branching lets you explore different conversation paths without losing previous progress.
### 2. Enhanced Message Controls ✅
- [x] Delete individual messages (not just clearing all)
- [x] Regenerate any message (not just last)
- [x] Continue incomplete messages
- [x] Message pinning (keep certain messages in context)
- [x] Message folding/hiding
- [ ] Bulk message operations (deferred - nice to have)
**Why Important:** Fine-grained control over conversation history allows users to craft the perfect roleplay session.
### 3. Timeline Visualization
- [ ] Visual tree of chat branches
- [ ] Quick navigation between branches
- [ ] Branch metadata (creation date, message count, etc.)
- [ ] Visual diff between branches
- [ ] Merge branch capability
**Why Important:** Makes managing complex branching conversations intuitive and prevents users from getting lost.
## Phase 4: Multi-Character/Group Chats (Medium Priority)
**Goal: Enable complex multi-character scenarios**
### 1. Group Chat Foundation
- [ ] Create group chat data structure
- [ ] UI for managing group members
- [ ] Add/remove characters from groups
- [ ] Group chat history management
- [ ] Per-group settings
**Why Important:** Many roleplay scenarios involve multiple characters interacting. Group chats enable DM-style gameplay and complex social scenarios.
### 2. Reply Management
- [ ] Manual character selection
- [ ] Natural order (mention-based)
- [ ] Talkativeness settings per character (0-100%)
- [ ] Auto-mode (characters respond automatically)
- [ ] Character muting/unmuting
- [ ] Reply order presets
**Why Important:** Gives users control over conversation flow while allowing for spontaneous multi-character interactions.
### 3. Group Chat UI
- [ ] Character indicators on messages
- [ ] Character list sidebar
- [ ] Mute/unmute controls
- [ ] Character ordering/priority
- [ ] Group-wide lorebook support
**Why Important:** Clear visual indicators make group conversations easy to follow.
## Phase 5: Context & Token Management (Medium Priority)
**Goal: Visibility and control over context usage**
### 1. Token Counter ✅
- [x] Real-time token count display
- [x] Per-section breakdown (system, history, WI, etc.)
- [ ] Visual context budget indicator (deferred)
- [ ] Dotted line showing context cutoff in chat (deferred)
- [ ] Warning when approaching limit (deferred)
**Why Important:** Understanding what's in context and what's being cut is crucial for debugging issues and optimizing prompts. Core functionality complete - visual enhancements can be added later.
### 2. Context Templates
- [ ] Customizable prompt assembly order
- [ ] Handlebars template support
- [ ] Presets for different model types (Alpaca, ChatML, Llama, etc.)
- [ ] Template preview
- [ ] Variable substitution visualization
**Why Important:** Different models expect different prompt formats. Templates ensure prompts are formatted correctly for each model.
### 3. Smart Context Management
- [ ] Summarization of old messages
- [ ] Automatic message trimming
- [ ] Priority-based context allocation
- [ ] Context budget per source (system, WI, history, etc.)
- [ ] Smart message selection (keep important messages)
**Why Important:** Efficient context usage means longer, more coherent conversations without running out of tokens.
## Phase 6: Power User Features (Low Priority)
**Goal: Advanced customization and automation**
### 1. Quick Replies
- [ ] Preset message buttons
- [ ] Macro support in quick replies
- [ ] Import/export QR sets
- [ ] Character-specific QR sets
- [ ] Conditional quick replies
- [ ] Quick reply categories/folders
**Why Important:** Speeds up common actions and reduces repetitive typing in roleplay scenarios.
### 2. Macro System
- [ ] Basic macros ({{user}}, {{char}}, {{random}}, etc.)
- [ ] Date/time macros
- [ ] Conditional macros
- [ ] Custom macro definitions
- [ ] Nested macro support
- [ ] Macro debugging
**Why Important:** Makes prompts and messages dynamic and reusable across different scenarios.
### 3. Regex Scripts ✅
- [x] Global and character-scoped scripts
- [x] Text transformation on messages
- [x] Auto-markdown formatting
- [x] Import/export regex presets
- [x] Regex testing interface
- [x] Script priority/ordering
**Why Important:** Allows automatic text formatting, correction, and enhancement without manual intervention.
### 4. Hotkey System
- [ ] Customizable keyboard shortcuts
- [ ] Quick actions (regen, edit, delete, etc.)
- [ ] Markdown formatting hotkeys
- [ ] Quick Reply hotkeys
- [ ] Navigation hotkeys
- [ ] Hotkey conflict detection
**Why Important:** Power users rely on keyboard shortcuts for efficient workflow.
## Phase 7: Polish & UX (Ongoing)
**Goal: Better user experience for roleplay**
### 1. Instruct Mode Support
- [ ] Preset templates (Alpaca, ChatML, Llama, etc.)
- [ ] Custom template creation
- [ ] Auto-detect model format from API
- [ ] Instruction wrapping for system/user/assistant messages
**Why Important:** Ensures compatibility with instruction-tuned models that expect specific formats.
### 2. Export/Import Improvements
- [ ] Export chats as markdown
- [ ] Export chats as formatted text
- [x] Export chats as JSON with metadata
- [x] Import chats from other formats
- [ ] Bulk character import
- [ ] Character pack support (multiple characters + lorebooks)
**Why Important:** Sharing and migrating content between platforms and backing up work.
### 3. UI Enhancements
- [ ] Message timestamps
- [ ] Character indicators in messages
- [ ] Better settings organization (categories, search)
- [ ] Theme customization (colors, fonts, etc.)
- [ ] Compact/cozy view modes
- [ ] Responsive design for different screen sizes
- [ ] Accessibility improvements
**Why Important:** Better UI means less friction and more immersion in roleplay.
## Phase 8: Quality of Life & Polish (High Priority)
**Goal: Reduce friction, improve feedback, and enhance overall user experience**
### 1. Toast Notification System
- [ ] Create toast component (bottom-right positioning)
- [ ] Success/error/info/warning variants
- [ ] Auto-dismiss with configurable timeout
- [ ] Queue multiple toasts
- [ ] Hook into all major actions (save, delete, import, export, etc.)
**Why Important:** Users currently have no immediate feedback when actions succeed or fail. Toasts provide instant visual confirmation without blocking workflow.
### 2. Command Palette
- [ ] Ctrl+P to open command palette modal
- [ ] Fuzzy search for all actions
- [ ] Keyboard navigation (arrow keys, enter, escape)
- [ ] Recent/frequent actions at top
- [ ] Show keyboard shortcuts in results
- [ ] Categories (Chat, Character, Settings, etc.)
**Why Important:** Power users want keyboard-first workflow. Command palette dramatically speeds up common actions without memorizing shortcuts.
### 3. Auto-save & Recovery
- [ ] Auto-save unsent message in input field
- [ ] Restore unsent message after app restart
- [ ] Draft system for in-progress edits
- [ ] Session recovery (restore scroll position, open panels)
- [ ] Crash recovery with last known state
**Why Important:** Losing work due to crashes or accidental closes is extremely frustrating. Auto-save provides a safety net for all user work.
### 4. Drag & Drop Support
- [ ] Drag character card PNGs to import
- [ ] Drag lorebook JSON files to import
- [ ] Drag chat history JSON to import
- [ ] Drag images to set as character avatar
- [ ] Drop zone overlay with visual feedback
- [ ] Support for multiple file drops
**Why Important:** Drag & drop feels natural and is much faster than navigate-click-select workflow. Modern desktop apps are expected to support this.
### 5. Search in Chat History
- [ ] Ctrl+F to open search bar
- [ ] Highlight all matches in messages
- [ ] Navigate between results (prev/next buttons)
- [ ] Case-insensitive search
- [ ] Search counter (e.g., "3 of 42 matches")
- [ ] Clear search and restore view
**Why Important:** Long roleplay sessions can span hundreds of messages. Finding specific content without search is tedious and time-consuming.
### 6. Context Menus (Right-Click)
- [ ] Right-click messages for actions (edit, delete, regenerate, branch, copy)
- [ ] Right-click character dropdown for quick actions
- [ ] Right-click World Info entries for edit/delete
- [ ] Right-click in message input for paste/clear/templates
- [ ] Context-aware menu items
**Why Important:** Right-click is muscle memory for desktop users. Faster than hovering to reveal action buttons.
### 7. Better Feedback & Confirmations
- [ ] Confirmation dialogs for destructive actions (delete character, clear chat)
- [ ] Loading spinners for API calls
- [ ] Progress bars for file imports
- [ ] "Saving..." / "Saved" indicators
- [ ] Success messages for completed actions
**Why Important:** Users should never wonder if an action succeeded or is still processing. Clear feedback prevents confusion and repeated clicks.
### 8. Undo/Redo System
- [ ] Undo message edit (Ctrl+Z)
- [ ] Undo message delete
- [ ] Undo character field changes
- [ ] Undo World Info changes
- [ ] Action history panel (optional)
- [ ] Redo support (Ctrl+Shift+Z)
**Why Important:** Mistakes happen. An undo system provides a safety net and encourages experimentation without fear of losing work.
### 9. Settings Search
- [ ] Search bar at top of settings panel
- [ ] Fuzzy search across all setting names and descriptions
- [ ] Highlight matching settings
- [ ] Collapse/expand sections based on matches
- [ ] "Recently changed" section
**Why Important:** With 22+ features, finding specific settings is tedious. Search makes configuration much faster.
### 10. Character Management Enhancements
- [ ] Recent characters quick-switch dropdown
- [ ] Character search/filter by name or tags
- [ ] Character folders/categories
- [ ] Duplicate character (as template)
- [ ] Favorite/star characters
- [ ] Sort options (name, date created, last used)
**Why Important:** Managing 10+ characters becomes messy. Better organization tools scale with user's character collection.
### 11. Enhanced Keyboard Support
- [ ] Full keyboard navigation in all modals (Tab, Arrow keys, Enter)
- [ ] Escape to close any open panel/modal
- [ ] Vim-style navigation mode (optional, j/k for scroll)
- [ ] Keyboard shortcut hints on hover
- [ ] Focus indicators for keyboard navigation
**Why Important:** Keyboard navigation should work everywhere. Current implementation is inconsistent across different UI sections.
### 12. Export/Share Enhancements
- [ ] Export conversation as formatted HTML
- [ ] Export conversation as formatted PDF
- [ ] Export as markdown with proper formatting
- [ ] Copy conversation to clipboard (formatted)
- [ ] Export individual messages
**Why Important:** Users want to share and archive conversations in readable formats, not just JSON.
### 13. Accessibility Improvements
- [ ] ARIA labels for all interactive elements
- [ ] Screen reader support
- [ ] High contrast mode option
- [ ] Larger click targets option (accessibility mode)
- [ ] Reduced motion mode (respect prefers-reduced-motion)
- [ ] Focus indicators for keyboard navigation
**Why Important:** Accessibility makes the app usable for everyone, including users with disabilities. It's also often legally required.
### 14. Better Visual Feedback
- [ ] Smooth transitions for panel open/close
- [ ] Hover states for all interactive elements
- [ ] Active state indicators (focused panel)
- [ ] Better empty states with helpful text
- [ ] Skeleton loaders for content loading
- [ ] Micro-animations for actions (delete, save, etc.)
**Why Important:** Visual polish makes the app feel responsive and professional. Small animations provide context for state changes.
### 15. Smart Defaults & Templates
- [ ] Scenario templates (fantasy RPG, sci-fi, modern, etc.)
- [ ] Pre-filled World Info templates
- [ ] Character card templates
- [ ] Quick-start wizard for new users
- [ ] Import from popular character repositories
**Why Important:** Reduces friction for new users and speeds up common tasks. Templates provide starting points for customization.
## Implementation Priority Ranking
### Must-Have for Basic Roleplay:
1. **World Info/Lorebooks** - Core feature for consistent roleplay
2. **Author's Note** - Better prompt control than system prompts alone
3. **Token Counter** - Visibility into what's happening
4. **Message Examples Usage** - Better character accuracy
### Important for Good Roleplay:
5. **User Personas** - Identity management
6. **Chat Branching** - Non-linear exploration
7. **Enhanced Message Controls** - Fine-grained editing
8. **Jailbreak Templates** - Handle various scenarios
### Great for Enhanced Experience:
9. **Expression Sprites** - Visual immersion
10. **Quick Replies + Macros** - Efficiency
11. **Context Templates** - Model compatibility
12. **Group Chats** - Complex scenarios
### Nice to Have:
13. **Timeline Visualization** - Advanced branch management
14. **Regex Scripts** - Automation
15. **Hotkeys** - Power user efficiency
16. **Smart Context Management** - Optimization
## Research Sources
This roadmap is based on research into SillyTavern's features and best practices from the roleplay AI community:
- SillyTavern official documentation (docs.sillytavern.app)
- Character card specifications (V2/V3 format)
- Community presets and guides on HuggingFace
- Roleplay community feedback and feature requests
## Technical Considerations
### Data Structures Needed:
- Lorebook entries (keyword, content, priority, insertion order, depth)
- Personas (name, description, avatar, chat/character locks)
- Chat branches (branch point, parent branch, metadata)
- Expression mappings (emotion → image file)
- Quick replies (text, macros, conditions, categories)
- Context templates (format strings, variables, presets)
### Backend Changes Required:
- Context assembly refactor (modular system for injecting different sources)
- Token counting integration (model-specific tokenizers)
- Sentiment analysis (local model or API integration)
- Branching chat storage (tree structure instead of linear)
- Group chat message routing (multi-character generation)
### UI Additions Needed:
- Lorebook editor panel
- Persona management panel
- Branch visualization widget
- Token counter display
- Group chat member list
- Quick reply buttons
- Expression sprite overlay
- Context template editor
## Version Milestones
### v0.2.0 - "Roleplay Foundation"
- World Info/Lorebooks
- Author's Note
- Token Counter
- Better Message Controls
### v0.3.0 - "Character Enhancement"
- User Personas
- Expression Sprites
- Message Examples Usage
- Jailbreak Templates
### v0.4.0 - "Advanced Chat"
- Chat Branching
- Timeline Visualization
- Group Chats (basic)
### v0.5.0 - "Power User"
- Quick Replies
- Macros
- Regex Scripts
- Hotkeys
### v1.0.0 - "Feature Complete"
- All planned features implemented
- Polished UI
- Comprehensive documentation
- Import/Export from SillyTavern
## Notes
- Focus on **compatibility with SillyTavern** where possible (character cards, lorebooks, etc.)
- Keep **performance** in mind - roleplay sessions can be long
- Maintain **desktop-first** design - power users prefer desktop interfaces
- Consider **offline-first** approach - local models are popular for roleplay
- Remember **privacy** - roleplay content is often sensitive
---
Last updated: 2025-10-16

62
src-tauri/Cargo.lock generated
View File

@@ -270,6 +270,21 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bit-set"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]] [[package]]
name = "bit_field" name = "bit_field"
version = "0.10.3" version = "0.10.3"
@@ -352,6 +367,17 @@ dependencies = [
"alloc-stdlib", "alloc-stdlib",
] ]
[[package]]
name = "bstr"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
dependencies = [
"memchr",
"regex-automata",
"serde",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.19.0" version = "3.19.0"
@@ -502,8 +528,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [ dependencies = [
"iana-time-zone", "iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen",
"windows-link 0.2.1", "windows-link 0.2.1",
] ]
@@ -1020,6 +1048,16 @@ dependencies = [
"zune-inflate", "zune-inflate",
] ]
[[package]]
name = "fancy-regex"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7493d4c459da9f84325ad297371a6b2b8a162800873a22e3b6b6512e61d18c05"
dependencies = [
"bit-set",
"regex",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.3.0" version = "2.3.0"
@@ -3459,6 +3497,12 @@ version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.4.1" version = "0.4.1"
@@ -4194,9 +4238,11 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"bytes", "bytes",
"chrono",
"futures", "futures",
"image", "image",
"png", "png",
"regex",
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
@@ -4204,6 +4250,7 @@ dependencies = [
"tauri-build", "tauri-build",
"tauri-plugin-dialog", "tauri-plugin-dialog",
"tauri-plugin-opener", "tauri-plugin-opener",
"tiktoken-rs",
"tokio", "tokio",
"uuid", "uuid",
] ]
@@ -4525,6 +4572,21 @@ dependencies = [
"weezl", "weezl",
] ]
[[package]]
name = "tiktoken-rs"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c314e7ce51440f9e8f5a497394682a57b7c323d0f4d0a6b1b13c429056e0e234"
dependencies = [
"anyhow",
"base64 0.21.7",
"bstr",
"fancy-regex",
"lazy_static",
"parking_lot",
"rustc-hash",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.44" version = "0.3.44"

View File

@@ -31,4 +31,7 @@ bytes = "1"
png = "0.17" png = "0.17"
base64 = "0.21" base64 = "0.21"
image = "0.24" image = "0.24"
regex = "1"
chrono = "0.4"
tiktoken-rs = "0.5"

File diff suppressed because it is too large Load Diff

View File

@@ -15,10 +15,20 @@
<div class="app-container"> <div class="app-container">
<header class="app-header"> <header class="app-header">
<div class="header-content"> <div class="header-content">
<div class="header-left-controls">
<button id="roleplay-btn" class="icon-btn" title="Roleplay Tools">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
</div>
<div class="character-display"> <div class="character-display">
<div class="avatar-circle"></div> <div class="avatar-circle"></div>
<span id="character-header-name"></span> <span id="character-header-name"></span>
</div> </div>
<div id="feature-badges" class="feature-badges">
<!-- Feature badges will be added here dynamically -->
</div>
<div class="character-controls"> <div class="character-controls">
<div class="select-wrapper"> <div class="select-wrapper">
<select id="character-select" class="character-select"></select> <select id="character-select" class="character-select"></select>
@@ -30,6 +40,18 @@
</button> </button>
</div> </div>
<div class="header-controls"> <div class="header-controls">
<button id="import-chat-btn" class="icon-btn" title="Import conversation">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M8 11V3M5 8l3 3 3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 13h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
<button id="export-chat-btn" class="icon-btn" title="Export conversation">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M8 3v8M5 6l3-3 3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 13h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
<button id="clear-btn" class="icon-btn" title="Clear conversation"> <button id="clear-btn" class="icon-btn" title="Clear conversation">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M3 4h10M6 4V3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v1M5 4v8a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/> <path d="M3 4h10M6 4V3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v1M5 4v8a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
@@ -55,7 +77,233 @@
</div> </div>
</main> </main>
<div class="settings-panel" id="settings-panel" style="display: none;"> <!-- Roleplay sidebar overlay -->
<div class="roleplay-overlay" id="roleplay-overlay"></div>
<!-- Roleplay sidebar (left) -->
<div class="roleplay-panel" id="roleplay-panel">
<div class="roleplay-header">
<h2>Roleplay Tools</h2>
<button id="close-roleplay-btn" class="icon-btn">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<line x1="4" y1="4" x2="12" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<line x1="12" y1="4" x2="4" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
</div>
<div class="roleplay-tabs">
<button class="roleplay-tab-btn active" data-tab="worldinfo">World Info</button>
<button class="roleplay-tab-btn" data-tab="authorsnote">Author's Note</button>
<button class="roleplay-tab-btn" data-tab="persona">Persona</button>
<button class="roleplay-tab-btn" data-tab="presets">Prompt Preset</button>
</div>
<div id="worldinfo-tab" class="roleplay-tab-content active">
<div class="roleplay-content">
<div class="form-group">
<label>World Info / Lorebook</label>
<p style="color: var(--text-secondary); font-size: 12px; margin-bottom: 12px;">
Create entries that inject context when keywords are mentioned.
</p>
<label for="recursion-depth" style="font-size: 13px; margin-top: 8px;">Recursion Depth</label>
<input
type="number"
id="recursion-depth"
min="0"
max="10"
value="3"
style="width: 80px; margin-bottom: 8px;"
/>
<p style="color: var(--text-secondary); font-size: 11px; margin-bottom: 12px;">
Maximum depth for cascading World Info activation. When a World Info entry is triggered, its content is scanned for additional keywords up to this depth. (Default: 3)
</p>
<button type="button" id="add-worldinfo-btn" class="btn-secondary" style="width: 100%;">
+ Add Entry
</button>
</div>
<div id="worldinfo-list" class="worldinfo-list">
<!-- World info entries will be added here -->
</div>
</div>
</div>
<div id="authorsnote-tab" class="roleplay-tab-content">
<div class="roleplay-content">
<div class="form-group">
<label for="authors-note-text">Author's Note</label>
<p style="color: var(--text-secondary); font-size: 12px; margin-bottom: 8px;">
Instructions inserted near the end of the prompt before the latest messages.
</p>
<textarea
id="authors-note-text"
placeholder="Write in present tense. Focus on sensory details..."
rows="6"
></textarea>
<div style="background: var(--bg-secondary); padding: 8px; border-radius: 4px; margin-top: 8px;">
<p style="color: var(--text-secondary); font-size: 11px; margin: 0 0 4px 0; font-weight: 500;">Template Variables:</p>
<p style="color: var(--text-secondary); font-size: 11px; margin: 0; font-family: monospace;">
{{char}} - Character name<br/>
{{user}} - User/Persona name<br/>
{{date}} - Current date (YYYY-MM-DD)<br/>
{{time}} - Current time (HH:MM)
</p>
</div>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="authors-note-enabled" />
Enable Author's Note
</label>
</div>
<button type="button" id="save-authors-note-btn" class="btn-primary" style="width: 100%; margin-bottom: 20px;">
Save Author's Note
</button>
<!-- Message Examples Section -->
<div class="form-group" style="border-top: 1px solid var(--border); padding-top: 16px;">
<label>Message Examples</label>
<p style="color: var(--text-secondary); font-size: 12px; margin-bottom: 8px;">
Use character card's message examples to teach the AI the character's voice and style.
</p>
<label>
<input type="checkbox" id="examples-enabled" />
Enable Message Examples
</label>
</div>
<div class="form-group">
<label for="examples-position">Examples Position</label>
<select id="examples-position" style="width: 100%;">
<option value="after_system">After System Prompt (Recommended)</option>
<option value="before_history">Before Message History</option>
</select>
<p style="color: var(--text-secondary); font-size: 11px; margin-top: 4px;">
Where to inject examples in the context. After system prompt works best for most models.
</p>
</div>
<button type="button" id="save-examples-btn" class="btn-primary" style="width: 100%;">
Save Examples Settings
</button>
</div>
</div>
<div id="persona-tab" class="roleplay-tab-content">
<div class="roleplay-content">
<div class="form-group">
<label for="persona-name">Persona Name</label>
<input
type="text"
id="persona-name"
placeholder="Your character name"
/>
</div>
<div class="form-group">
<label for="persona-description">Persona Description</label>
<p style="color: var(--text-secondary); font-size: 12px; margin-bottom: 8px;">
Describe yourself as the user in this roleplay.
</p>
<textarea
id="persona-description"
placeholder="Describe your character's appearance, personality, background..."
rows="8"
></textarea>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="persona-enabled" />
Enable Persona
</label>
</div>
<button type="button" id="save-persona-btn" class="btn-primary" style="width: 100%;">
Save Persona
</button>
</div>
</div>
<div id="presets-tab" class="roleplay-tab-content">
<div class="roleplay-content">
<div class="form-group">
<label for="preset-select">Prompt Preset</label>
<p style="color: var(--text-secondary); font-size: 12px; margin-bottom: 8px;">
Choose a preset to apply specialized prompting strategies for different use cases.
</p>
<select id="preset-select" style="width: 100%; margin-bottom: 12px;">
<option value="">No Preset</option>
</select>
</div>
<!-- Preset Info/Editor -->
<div id="preset-info" style="display: none; background: var(--bg-secondary); padding: 12px; border-radius: 6px; margin-bottom: 16px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<div style="font-weight: 500; color: var(--text-primary);">
<span id="preset-name"></span>
<span id="preset-builtin-badge" style="display: none; font-size: 10px; color: var(--text-secondary); margin-left: 8px; padding: 2px 6px; background: var(--bg-primary); border-radius: 3px;">Built-in</span>
<span id="preset-modified-badge" style="display: none; font-size: 10px; color: var(--accent); margin-left: 8px; padding: 2px 6px; background: var(--bg-primary); border-radius: 3px;">Modified</span>
</div>
<div style="display: flex; gap: 4px;">
<button type="button" id="restore-preset-btn" class="worldinfo-btn" style="display: none; font-size: 11px; padding: 4px 8px;">Restore to Default</button>
<button type="button" id="duplicate-preset-btn" class="worldinfo-btn" style="display: none; font-size: 11px; padding: 4px 8px;">Duplicate</button>
<button type="button" id="delete-preset-btn" class="worldinfo-btn worldinfo-btn-danger" style="display: none; font-size: 11px; padding: 4px 8px;">Delete</button>
</div>
</div>
<p id="preset-description" style="color: var(--text-secondary); font-size: 12px; margin-bottom: 12px;"></p>
<!-- System Additions (Read-only preview for built-in, editable for custom) -->
<div id="preset-system-section" style="margin-bottom: 12px;">
<div style="font-size: 11px; color: var(--text-secondary); margin-bottom: 4px;">
<strong>System Additions:</strong>
</div>
<div id="preset-system-readonly" style="display: none; background: var(--bg-primary); padding: 8px; border-radius: 4px; font-size: 11px; white-space: pre-wrap;"></div>
<textarea id="preset-system-editable" style="display: none; width: 100%; min-height: 60px; font-size: 11px;" placeholder="Additional text to prepend to system prompt..."></textarea>
</div>
<!-- Instruction Blocks Editor -->
<div id="preset-instructions-section">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<div style="font-size: 11px; color: var(--text-secondary);">
<strong>Instruction Blocks:</strong>
</div>
<button type="button" id="add-instruction-btn" class="worldinfo-btn" style="display: none; font-size: 11px; padding: 4px 8px;">+ Add Block</button>
</div>
<div id="preset-instructions-list" style="background: var(--bg-primary); padding: 8px; border-radius: 4px; margin-bottom: 12px;">
<!-- Instructions will be listed here -->
</div>
</div>
<!-- Author's Note Default -->
<div id="preset-authors-note-section" style="margin-bottom: 12px;">
<div style="font-size: 11px; color: var(--text-secondary); margin-bottom: 4px;">
<strong>Default Author's Note:</strong>
</div>
<div id="preset-authors-note-readonly" style="display: none; background: var(--bg-primary); padding: 8px; border-radius: 4px; font-size: 11px; white-space: pre-wrap;"></div>
<textarea id="preset-authors-note-editable" style="display: none; width: 100%; min-height: 60px; font-size: 11px;" placeholder="Default Author's Note if user hasn't set one..."></textarea>
</div>
<!-- Save Changes Button (only for custom presets) -->
<button type="button" id="save-preset-changes-btn" class="btn-secondary" style="display: none; width: 100%; margin-bottom: 8px;">
Save Changes
</button>
</div>
<button type="button" id="apply-preset-btn" class="btn-primary" style="width: 100%; margin-bottom: 8px;" disabled>
Apply Preset
</button>
<button type="button" id="create-preset-btn" class="btn-secondary" style="width: 100%;">
Create Custom Preset
</button>
<p style="color: var(--text-secondary); font-size: 11px; margin-top: 12px; padding: 8px; background: var(--bg-secondary); border-radius: 4px;">
<strong>Note:</strong> Custom presets will be stored in ~/.config/claudia/presets/ and will be available across all characters.
</p>
</div>
</div>
</div>
<!-- Settings overlay backdrop -->
<div class="settings-overlay" id="settings-overlay"></div>
<div class="settings-panel" id="settings-panel">
<div class="settings-header"> <div class="settings-header">
<h2>Settings</h2> <h2>Settings</h2>
<button id="close-settings-btn" class="icon-btn"> <button id="close-settings-btn" class="icon-btn">
@@ -69,6 +317,7 @@
<div class="settings-tabs"> <div class="settings-tabs">
<button class="tab-btn active" data-tab="api">API</button> <button class="tab-btn active" data-tab="api">API</button>
<button class="tab-btn" data-tab="character">Character</button> <button class="tab-btn" data-tab="character">Character</button>
<button class="tab-btn" data-tab="appearance">Appearance</button>
</div> </div>
<div id="api-tab" class="tab-content active"> <div id="api-tab" class="tab-content active">
@@ -104,6 +353,19 @@
</select> </select>
</div> </div>
<div class="form-group">
<label for="context-limit">Context Limit (tokens)</label>
<input
type="number"
id="context-limit"
placeholder="200000"
value="200000"
min="1000"
step="1000"
/>
<small style="color: var(--text-secondary); margin-top: 4px; display: block;">Maximum tokens for model context (e.g., 200000 for Claude)</small>
</div>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" id="stream-toggle" /> <input type="checkbox" id="stream-toggle" />
@@ -125,6 +387,18 @@
<label for="character-settings-select">Select Character</label> <label for="character-settings-select">Select Character</label>
<select id="character-settings-select"></select> <select id="character-settings-select"></select>
</div> </div>
<!-- Basic Info Section -->
<div class="settings-section" data-section="basic">
<div class="settings-section-header">
<div class="settings-section-title">
<svg class="settings-section-icon" viewBox="0 0 16 16" fill="none">
<path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Basic Information
</div>
</div>
<div class="settings-section-content">
<div class="form-group"> <div class="form-group">
<label for="character-name">Character Name</label> <label for="character-name">Character Name</label>
<input <input
@@ -174,9 +448,22 @@
rows="2" rows="2"
></textarea> ></textarea>
</div> </div>
</div>
</div>
<!-- Roleplay Details Section -->
<div class="settings-section collapsed" data-section="roleplay">
<div class="settings-section-header">
<div class="settings-section-title">
<svg class="settings-section-icon" viewBox="0 0 16 16" fill="none">
<path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Roleplay Details
</div>
</div>
<div class="settings-section-content">
<div class="form-group"> <div class="form-group">
<label for="character-personality">Personality Tags (Optional)</label> <label for="character-personality">Personality Tags</label>
<input <input
type="text" type="text"
id="character-personality" id="character-personality"
@@ -185,16 +472,16 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-description">Description (Optional)</label> <label for="character-description">Description</label>
<textarea <textarea
id="character-description" id="character-description"
placeholder="Detailed character description, appearance, background..." placeholder="Detailed character description, appearance, background..."
rows="10" rows="8"
></textarea> ></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-scenario">Scenario (Optional)</label> <label for="character-scenario">Scenario</label>
<textarea <textarea
id="character-scenario" id="character-scenario"
placeholder="The setting or situation where the character exists..." placeholder="The setting or situation where the character exists..."
@@ -203,16 +490,29 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-mes-example">Message Example (Optional)</label> <label for="character-mes-example">Message Examples</label>
<textarea <textarea
id="character-mes-example" id="character-mes-example"
placeholder="Example dialogue from the character..." placeholder="Example dialogue from the character..."
rows="4" rows="4"
></textarea> ></textarea>
</div> </div>
</div>
</div>
<!-- Advanced Settings Section -->
<div class="settings-section collapsed" data-section="advanced">
<div class="settings-section-header">
<div class="settings-section-title">
<svg class="settings-section-icon" viewBox="0 0 16 16" fill="none">
<path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Advanced Settings
</div>
</div>
<div class="settings-section-content">
<div class="form-group"> <div class="form-group">
<label for="character-post-history">Post-History Instructions (Optional)</label> <label for="character-post-history">Post-History Instructions</label>
<textarea <textarea
id="character-post-history" id="character-post-history"
placeholder="Instructions to apply after chat history..." placeholder="Instructions to apply after chat history..."
@@ -221,16 +521,29 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-alt-greetings">Alternate Greetings (Optional)</label> <label for="character-alt-greetings">Alternate Greetings</label>
<textarea <textarea
id="character-alt-greetings" id="character-alt-greetings"
placeholder="One greeting per line..." placeholder="One greeting per line..."
rows="3" rows="3"
></textarea> ></textarea>
</div> </div>
</div>
</div>
<!-- Metadata Section -->
<div class="settings-section collapsed" data-section="metadata">
<div class="settings-section-header">
<div class="settings-section-title">
<svg class="settings-section-icon" viewBox="0 0 16 16" fill="none">
<path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Metadata
</div>
</div>
<div class="settings-section-content">
<div class="form-group"> <div class="form-group">
<label for="character-tags">Tags (Optional)</label> <label for="character-tags">Tags</label>
<input <input
type="text" type="text"
id="character-tags" id="character-tags"
@@ -239,7 +552,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-creator">Creator (Optional)</label> <label for="character-creator">Creator</label>
<input <input
type="text" type="text"
id="character-creator" id="character-creator"
@@ -248,7 +561,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-version">Character Version (Optional)</label> <label for="character-version">Character Version</label>
<input <input
type="text" type="text"
id="character-version" id="character-version"
@@ -257,26 +570,28 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="character-creator-notes">Creator Notes (Optional)</label> <label for="character-creator-notes">Creator Notes</label>
<textarea <textarea
id="character-creator-notes" id="character-creator-notes"
placeholder="Notes from the creator..." placeholder="Notes from the creator..."
rows="2" rows="2"
></textarea> ></textarea>
</div> </div>
</div>
</div>
<div id="character-message" class="validation-message"></div> <div id="character-message" class="validation-message"></div>
<button type="submit" id="save-character-btn" class="btn-primary"> <div style="display: flex; gap: 8px;">
<button type="submit" id="save-character-btn" class="btn-primary" style="flex: 1;">
Save Character Save Character
</button> </button>
<button type="button" id="delete-character-btn" class="btn-danger"> <button type="button" id="delete-character-btn" class="btn-danger">
Delete Character Delete
</button> </button>
</div>
<div class="form-group" style="margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border-color);"> <div style="display: flex; gap: 8px;">
<label>Character Card Import/Export</label>
<div style="display: flex; gap: 0.5rem;">
<button type="button" id="import-character-btn" class="btn-secondary" style="flex: 1;"> <button type="button" id="import-character-btn" class="btn-secondary" style="flex: 1;">
Import v2 Card Import v2 Card
</button> </button>
@@ -284,9 +599,67 @@
Export v2 Card Export v2 Card
</button> </button>
</div> </div>
</div>
</form> </form>
</div> </div>
<div id="appearance-tab" class="tab-content">
<div class="settings-form">
<div class="form-group">
<label for="theme-select">Theme</label>
<select id="theme-select" class="theme-select">
<option value="dark">Dark (Default)</option>
<option value="darker">Darker</option>
<option value="midnight">Midnight Blue</option>
<option value="forest">Forest</option>
<option value="sunset">Sunset</option>
<option value="light">Light</option>
</select>
<small style="color: var(--text-secondary); margin-top: 4px; display: block;">Choose your preferred color scheme</small>
</div>
<div class="form-group">
<label for="view-mode-select">View Mode</label>
<select id="view-mode-select" class="view-mode-select">
<option value="compact">Compact - Tight spacing, smaller text</option>
<option value="cozy">Cozy - Balanced spacing (Default)</option>
<option value="comfortable">Comfortable - Spacious layout</option>
</select>
<small style="color: var(--text-secondary); margin-top: 4px; display: block;">Adjust message density and spacing</small>
</div>
<div class="form-group">
<label for="font-size-slider">
Font Size: <span id="font-size-value">100%</span>
</label>
<input
type="range"
id="font-size-slider"
min="80"
max="140"
value="100"
step="10"
class="font-size-slider"
/>
<div style="display: flex; justify-content: space-between; margin-top: 4px;">
<small style="color: var(--text-secondary);">Small (80%)</small>
<small style="color: var(--text-secondary);">Large (140%)</small>
</div>
</div>
<div class="theme-preview-container">
<div class="theme-preview-label">Preview</div>
<div class="theme-preview">
<div class="theme-preview-message user-preview">
<div class="theme-preview-content">User message</div>
</div>
<div class="theme-preview-message assistant-preview">
<div class="theme-preview-avatar"></div>
<div class="theme-preview-content">Assistant response</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<footer class="input-container"> <footer class="input-container">
@@ -305,10 +678,88 @@
</form> </form>
<div class="status-bar"> <div class="status-bar">
<span id="status-text" class="status-text">Ready</span> <span id="status-text" class="status-text">Ready</span>
<div id="token-counter" class="token-counter">
<span id="token-count-total" class="token-count">0 tokens</span>
<button id="token-details-btn" class="token-details-btn" title="Show breakdown">
<svg width="12" height="12" viewBox="0 0 16 16" fill="none">
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/>
<path d="M8 7v4M8 5h.01" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
</div>
</div>
<!-- Token Breakdown Tooltip -->
<div id="token-breakdown" class="token-breakdown" style="display: none;">
<div class="token-breakdown-header">Token Breakdown</div>
<div class="token-breakdown-list">
<div class="token-breakdown-item">
<span>System Prompt:</span>
<span id="token-system">0</span>
</div>
<div class="token-breakdown-item">
<span>Preset Instructions:</span>
<span id="token-preset">0</span>
</div>
<div class="token-breakdown-item">
<span>Persona:</span>
<span id="token-persona">0</span>
</div>
<div class="token-breakdown-item">
<span>World Info:</span>
<span id="token-worldinfo">0</span>
</div>
<div class="token-breakdown-item">
<span>Author's Note:</span>
<span id="token-authorsnote">0</span>
</div>
<div class="token-breakdown-item">
<span>Message Examples:</span>
<span id="token-examples">0</span>
</div>
<div class="token-breakdown-item">
<span>Message History:</span>
<span id="token-history">0</span>
</div>
<div class="token-breakdown-item">
<span>Current Input:</span>
<span id="token-input">0</span>
</div>
<div class="token-breakdown-total">
<span>Total:</span>
<span id="token-total-detail">0</span>
</div>
</div>
</div> </div>
</footer> </footer>
</div> </div>
<!-- Toast Container -->
<div id="toast-container" class="toast-container"></div>
<!-- Command Palette -->
<div id="command-palette-modal" class="command-palette-modal" style="display: none;">
<div class="command-palette-overlay"></div>
<div class="command-palette-content">
<div class="command-palette-search">
<svg class="command-palette-search-icon" width="20" height="20" viewBox="0 0 20 20" fill="none">
<circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="2"/>
<path d="M12.5 12.5L17 17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
<input
type="text"
id="command-palette-input"
class="command-palette-input"
placeholder="Type a command or search..."
autocomplete="off"
/>
<kbd class="command-palette-hint">Esc to close</kbd>
</div>
<div id="command-palette-results" class="command-palette-results">
<!-- Command results will be dynamically populated here -->
</div>
</div>
</div>
<!-- Avatar zoom modal --> <!-- Avatar zoom modal -->
<div id="avatar-modal" class="avatar-modal" style="display: none;"> <div id="avatar-modal" class="avatar-modal" style="display: none;">
<div class="avatar-modal-overlay"></div> <div class="avatar-modal-overlay"></div>
@@ -316,5 +767,50 @@
<img id="avatar-modal-img" src="" alt="Avatar" /> <img id="avatar-modal-img" src="" alt="Avatar" />
</div> </div>
</div> </div>
<!-- New Character modal -->
<div id="new-character-modal" class="new-character-modal" style="display: none;">
<div class="new-character-overlay"></div>
<div class="new-character-content">
<div class="new-character-header">
<h3>Create New Character</h3>
<button id="close-new-character-btn" class="icon-btn">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<line x1="4" y1="4" x2="12" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<line x1="12" y1="4" x2="4" y2="12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
</div>
<form id="new-character-form">
<div class="form-group">
<label for="new-character-name">Character Name</label>
<input
type="text"
id="new-character-name"
placeholder="Enter a name for the new character"
required
autofocus
/>
</div>
<div class="form-group">
<label for="new-character-system-prompt">System Prompt</label>
<textarea
id="new-character-system-prompt"
placeholder="You are a helpful AI assistant..."
rows="6"
required
></textarea>
</div>
<div class="new-character-actions">
<button type="button" id="cancel-new-character-btn" class="btn-secondary">
Cancel
</button>
<button type="submit" class="btn-primary">
Create
</button>
</div>
</form>
</div>
</div>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff