/ app / spec / 01_ui_components.md
01_ui_components.md
   1  # Kamaji TUI - Comprehensive UI Components Specification
   2  
   3  **Version:** 1.0
   4  **Date:** 2025-11-01
   5  **Status:** Complete Analysis
   6  
   7  ---
   8  
   9  ## Table of Contents
  10  
  11  1. [Overview](#overview)
  12  2. [Core Model Structure](#core-model-structure)
  13  3. [Component Inventory](#component-inventory)
  14  4. [Visual Styling System](#visual-styling-system)
  15  5. [Animation Systems](#animation-systems)
  16  6. [Input Handling](#input-handling)
  17  7. [Message Rendering](#message-rendering)
  18  8. [Layout & Sizing](#layout-and-sizing)
  19  9. [Component Details](#component-details)
  20  10. [State Management](#state-management)
  21  
  22  ---
  23  
  24  ## Overview
  25  
  26  The Kamaji TUI is a sophisticated terminal user interface built on the Bubble Tea framework with lipgloss styling. It features a multi-agent AI interaction system with rich animations, a consciousness monitoring sidebar, command palette, and comprehensive permission system.
  27  
  28  ### Architecture Pattern
  29  - **Framework:** Bubble Tea (Model-View-Update pattern)
  30  - **Styling:** Lipgloss (declarative terminal styling)
  31  - **Theme:** Fire-themed dark blue interface inspired by Spirited Away
  32  
  33  ---
  34  
  35  ## Core Model Structure
  36  
  37  ### IntegratedTUIModel
  38  **Location:** `/internal/tui/model.go` (Lines 30-63)
  39  
  40  ```go
  41  type IntegratedTUIModel struct {
  42      // Core Components
  43      viewport         viewport.Model           // Message display area
  44      textarea         textarea.Model           // User input field
  45      sidebar          *SidebarPanel           // Right-side consciousness panel
  46  
  47      // Configuration & LLM
  48      config           *config.Config
  49      llm              types.LLMProvider
  50      provider         string                   // "ollama", "anthropic", "openai", "q"
  51      model            string                   // Model name
  52  
  53      // Message Management
  54      messages         []Message                // Conversation history
  55      loading          bool                     // Loading state
  56      streaming        bool                     // Active streaming flag
  57      currentStream    <-chan types.StreamChunk // Stream channel
  58  
  59      // Layout & Sizing
  60      width            int                      // Terminal width
  61      height           int                      // Terminal height
  62      ready            bool                     // Initialization complete
  63      sidebarWidth     int                      // Sidebar width (adaptive)
  64      sidebarVisible   bool                     // User toggle state
  65  
  66      // Animation Components
  67      thinkingSpinner  ThinkingSpinner         // Status bar spinner
  68      bottomAnimation  *BottomAnimation        // Loading gradient
  69      flameAnimation   *FlameAnimation         // Input area flames
  70  
  71      // UI Components
  72      commandPalette   *CommandPalette         // Command palette (Ctrl+P)
  73      permissionDialog *PermissionDialog       // Permission requests
  74      agentSelector    *AgentSelector          // Agent menu
  75      agentAutocomplete *AgentAutocomplete     // @ mention autocomplete
  76  
  77      // Agent System
  78      agentRegistry    *agents.AgentRegistry
  79      selectedAgent    *agents.SpecializedAgent
  80      showAgentMenu    bool
  81  
  82      // Input Handling
  83      inputHandler     *InputHandler
  84      autocomplete     *AutocompleteState
  85  
  86      // Consciousness
  87      consciousness    *consciousness.System    // AI consciousness tracking
  88  
  89      // Provider Management
  90      providerList     []string                 // Available providers
  91      selectedProvider int                      // Current selection index
  92  }
  93  ```
  94  
  95  ### Message Structure
  96  **Location:** `/internal/tui/model.go` (Lines 20-28)
  97  
  98  ```go
  99  type Message struct {
 100      Role      string      // "user", "assistant", "system"
 101      Content   string      // Message text
 102      AgentName string      // Sending agent ("Kamaji", "Moe", etc.)
 103      ToolName  string      // Tool used (if applicable)
 104      Timing    float64     // Response time
 105      Timestamp time.Time   // Message timestamp
 106  }
 107  ```
 108  
 109  ---
 110  
 111  ## Component Inventory
 112  
 113  ### 1. Viewport Component
 114  **Type:** `viewport.Model` (Bubble Tea component)
 115  **Purpose:** Scrollable message display area
 116  **Location:** Center/left panel
 117  
 118  **Configuration:**
 119  - Width: `mainWidth` (calculated based on sidebar visibility)
 120  - Height: `msg.Height - 4` (reserves space for status, footer, input)
 121  - Content: Rendered messages with Kamaji ASCII art header
 122  
 123  **Key Methods:**
 124  - `SetContent()` - Update displayed content
 125  - `GotoBottom()` - Auto-scroll to latest message
 126  - `LineUp(3)` / `LineDown(3)` - Mouse wheel scrolling
 127  
 128  ### 2. Textarea Component
 129  **Type:** `textarea.Model` (Bubble Tea component)
 130  **Purpose:** User input field
 131  **Location:** Bottom of screen, full width
 132  
 133  **Configuration (`model.go` Lines 77-83):**
 134  ```go
 135  ta := textarea.New()
 136  ta.Placeholder = "๐Ÿ”ฅ Speak to the furnace spirit..."
 137  ta.Focus()
 138  ta.SetWidth(80)  // Updated dynamically on resize
 139  ta.SetHeight(1)
 140  ta.ShowLineNumbers = false
 141  ta.Cursor.SetMode(cursor.CursorBlink)
 142  ```
 143  
 144  **Special Features:**
 145  - Placeholder changes in `customInputView()` to: "Speak to the furnace spirit... (type @ for agents)"
 146  - @ autocomplete for agent mentions
 147  - Tab completion for agent names
 148  - Full-width rendering with flame emoji decoration
 149  
 150  ### 3. Sidebar Panel
 151  **Type:** `*SidebarPanel`
 152  **File:** `/internal/tui/panel.go`
 153  **Purpose:** Real-time consciousness metrics and system info
 154  
 155  #### Structure (`panel.go` Lines 15-24)
 156  ```go
 157  type SidebarPanel struct {
 158      width         int
 159      height        int
 160      provider      string
 161      model         string
 162      scrollY       int     // Current scroll position
 163      maxScroll     int     // Maximum scroll position
 164      consciousness interface{} // Consciousness system reference
 165  }
 166  ```
 167  
 168  #### Sections Rendered
 169  
 170  **Logo Section** (`renderLogo()` Lines 193-213)
 171  - **Full Logo** (height > 25): Fire-themed multi-line ASCII art
 172    - Fire-yellow header box: "KAMAJI AI"
 173    - Red fire emojis (๐Ÿ”ฅ) with box drawing
 174    - White face with eyes (โ—‰), nose (โ–ผ), mouth (โ•โ•โ•)
 175    - Gold gears (โš™)
 176  - **Compact Logo** (height โ‰ค 25): "๐Ÿ”ฅ KAMAJI" in fire-red
 177  
 178  **Working Directory** (`renderWorkingDir()` Lines 222-234)
 179  - Header: "๐Ÿ“ Working Directory" (cyan accent)
 180  - Content: `filepath.Base(os.Getwd())`
 181  - Style: Gray text, left-padded
 182  
 183  **Model Info** (`renderModelInfo()` Lines 236-254)
 184  - Header: "๐Ÿค– AI Model" (cyan accent)
 185  - Content: "via {provider}" (anthropic, ollama, openai, q)
 186  - Style: Gray text
 187  
 188  **Project Context** (`renderProjectContext()` Lines 256-280)
 189  - Header: "๐Ÿ“ Project"
 190  - Type detection: Go, Rust, Node.js, Python, Java, C/C++, Generic
 191  - File count (non-recursive, excluding hidden files)
 192  
 193  **Tools Section** (`renderToolsSection()` Lines 282-308)
 194  - Header: "๐Ÿ”ง Tools" (cyan accent)
 195  - Categories (gray bullets):
 196    - File Operations (5)
 197    - Git Commands (4)
 198    - Shell Execution (1)
 199    - Code Analysis (1)
 200  - Total: 11 tools (yellow text)
 201  
 202  **Agents Section** (`renderAgentsSection()` Lines 311-368)
 203  - Header: "๐Ÿค– Specialized Agents" (cyan accent)
 204  - Agent list with icons and color-coded levels:
 205    - **Master** (Lavender #E6E6FA): Prodigy
 206    - **Expert** (Red #FF6B6B): Kamaji, Code Architect, Security, Data Scientist, Writer
 207    - **Advanced** (Purple #7B68EE): DevOps, Designer
 208    - **Autonomous** (Gold #FFD700): Product Manager, Researcher, Learning, Visionary
 209  - Hint: "Press ^A to select" (italic gray)
 210  
 211  **Navigation Section** (`renderNavigationSection()` Lines 371-397)
 212  - Header: "๐Ÿงญ Navigation" (cyan accent)
 213  - Commands:
 214    - furnace commands [^P]
 215    - tools [^T]
 216    - agents [^A]
 217    - mcp [^M]
 218    - exit boiler [^C]
 219  
 220  **Consciousness Section** (`renderConsciousnessSection()` Lines 423-467)
 221  - Header: "๐Ÿง  Consciousness" (Pink #FF6B9D)
 222  - Metrics (yellow text):
 223    - Awareness: {percentage}
 224    - Thoughts: {count}
 225    - Questions: {count}
 226    - Mistakes: {count}
 227  - Fallback: "Initializing..." if unavailable
 228  
 229  **Version Section** (`renderVersionSection()` Lines 399-421)
 230  - Header: "๐Ÿ”ฅ Version Info" (cyan accent)
 231  - Details (yellow text):
 232    - Version: {version}
 233    - Build: {buildTime}
 234    - Commit: {gitCommit[0:8]}
 235  
 236  #### Scrolling System (`panel.go` Lines 112-144)
 237  - Available height: `s.height - 4` (border + padding)
 238  - Max scroll: `len(allLines) - availableHeight`
 239  - Scroll indicators: `[{scrollY+1}/{totalScrollableLines}]`
 240  - Methods: `ScrollUp()`, `ScrollDown()`
 241  
 242  #### Container Styling (`panel.go` Lines 148-159)
 243  ```go
 244  style := lipgloss.NewStyle().
 245      Width(s.width - 2).       // Account for border
 246      Height(s.height - 2).     // Account for border
 247      Padding(1).
 248      Align(lipgloss.Left, lipgloss.Top).
 249      Background(bgDark).       // Color 235
 250      Foreground(textColor).    // #f1f5f9
 251      Border(lipgloss.DoubleBorder()).
 252      BorderForeground(lipgloss.Color("#FF0000"))  // Red border
 253  ```
 254  
 255  #### Adaptive Width (`integrated.go` Lines 118-134)
 256  ```go
 257  if m.sidebarVisible {
 258      if msg.Width >= 90:  sidebarWidth = 35  // Full
 259      elif msg.Width >= 70: sidebarWidth = 30  // Medium
 260      elif msg.Width >= 55: sidebarWidth = 25  // Narrow
 261      else: sidebarWidth = 20                  // Minimal
 262      mainWidth = msg.Width - sidebarWidth - 2
 263  } else {
 264      sidebarWidth = 0
 265      mainWidth = msg.Width
 266  }
 267  ```
 268  
 269  ### 4. Command Palette
 270  **Type:** `*CommandPalette`
 271  **File:** `/internal/tui/palette.go`
 272  **Trigger:** Ctrl+P
 273  
 274  #### Structure (`palette.go` Lines 19-28)
 275  ```go
 276  type CommandPalette struct {
 277      commands     []Command  // All available commands
 278      filtered     []Command  // Search-filtered commands
 279      selected     int        // Selected index
 280      query        string     // Search query
 281      visible      bool       // Visibility state
 282      width        int
 283      height       int
 284  }
 285  ```
 286  
 287  #### Command Structure (`palette.go` Lines 11-17)
 288  ```go
 289  type Command struct {
 290      ID          string  // "clear", "tools", "provider:ollama"
 291      Name        string  // "๐Ÿ”ฅ Ask the Furnace"
 292      Description string  // Detailed explanation
 293      Category    string  // "core", "provider", "tools", "settings"
 294      Shortcut    string  // "Ctrl+C" or empty
 295  }
 296  ```
 297  
 298  #### Command List (`palette.go` Lines 32-60)
 299  
 300  **Core Furnace Commands:**
 301  - `ask` - ๐Ÿ”ฅ Ask the Furnace
 302  - `chat` - ๐Ÿ’ฌ New Conversation
 303  - `clear` - ๐Ÿงน Sweep Clean
 304  
 305  **Spirit Providers:**
 306  - `provider:q` - ๐ŸŒŸ Amazon Q Spirit
 307  - `provider:ollama` - ๐Ÿฆ™ Ollama Guardian
 308  - `provider:openai` - ๐Ÿค– OpenAI Deity
 309  - `provider:anthropic` - ๐Ÿง  Claude Sage
 310  
 311  **Boiler Room Tools:**
 312  - `tools` - โš™ Inspect Tools
 313  - `agents` - ๐Ÿ‘ป Spirit Agents
 314  - `memory` - ๐Ÿง  Memory Crystals
 315  - `workflow` - โšก Steam Workflows
 316  
 317  **Consciousness Features:**
 318  - `consciousness` - ๐Ÿง  Consciousness Status
 319  - `thoughts` - ๐Ÿ’ญ Recent Thoughts
 320  - `personality` - ๐ŸŽญ Personality Profile
 321  
 322  **Bathhouse Settings:**
 323  - `config` - ๐ŸŽญ Bathhouse Rules
 324  - `help` - ๐Ÿ“œ Ancient Scrolls
 325  - `version` - ๐Ÿฎ Furnace Status
 326  - `quit` - ๐Ÿšช Return Upstairs [Ctrl+C]
 327  
 328  #### Rendering (`palette.go` Lines 154-281)
 329  
 330  **Container:** Fixed width 70, centered overlay
 331  
 332  **Header:**
 333  ```go
 334  headerStyle := lipgloss.NewStyle().
 335      Background(lipgloss.Color("235")).
 336      Foreground(lipgloss.Color("196")).  // Red
 337      Bold(true).
 338      Width(70).
 339      Align(lipgloss.Center)
 340  
 341  Content: "๐Ÿ”ฅ KAMAJI'S FURNACE COMMANDS ๐Ÿ”ฅ"
 342  ```
 343  
 344  **Search Input:**
 345  ```go
 346  searchStyle := lipgloss.NewStyle().
 347      Background(lipgloss.Color("235")).
 348      Foreground(lipgloss.Color("220")).  // Yellow
 349      Width(70).
 350      Padding(0, 2)
 351  
 352  Content: "โš™ {query}" or "โš™ Type to search..."
 353  ```
 354  
 355  **Command Items:** Max 12 visible
 356  - **Selected:**
 357    - Background: Color 196 (red)
 358    - Foreground: Color 235 (dark)
 359    - Bold, left padding 2
 360    - Prefix: "โ–ถ"
 361  - **Unselected:**
 362    - Background: Color 235
 363    - Foreground: Color 255 (white)
 364    - Prefix: " "
 365  
 366  **Format:** `{prefix} {name,-25} {description}`
 367  
 368  **Footer:**
 369  ```go
 370  footerStyle := lipgloss.NewStyle().
 371      Background(lipgloss.Color("235")).
 372      Foreground(lipgloss.Color("240")).
 373      Width(70).
 374      Align(lipgloss.Center).
 375      Border(lipgloss.NormalBorder(), true, false, false, false)
 376  
 377  Content: "โ†‘โ†“ Navigate โ€ข ENTER Execute โ€ข ESC Exit"
 378  ```
 379  
 380  **Container Border:** RoundedBorder, Color 196 (red)
 381  
 382  #### Search Filtering (`palette.go` Lines 135-151)
 383  - Case-insensitive
 384  - Matches Name, Description, or ID
 385  - Updates `filtered` array
 386  - Resets `selected` to 0
 387  
 388  ### 5. Agent Selector
 389  **Type:** `*AgentSelector`
 390  **File:** `/internal/tui/agent_selector.go`
 391  **Trigger:** Ctrl+A
 392  
 393  #### Structure (`agent_selector.go` Lines 12-19)
 394  ```go
 395  type AgentSelector struct {
 396      agents         []*agents.SpecializedAgent
 397      selectedIndex  int
 398      scrollOffset   int         // For scrolling
 399      visibleCards   int         // Cached visible count
 400      filterLevel    agents.IntelligenceLevel
 401      filterType     string
 402  }
 403  ```
 404  
 405  #### Agent Card Rendering (`renderAgentCard()` Lines 122-204)
 406  
 407  **Border Styles:**
 408  - **Selected:** ThickBorder, Cyan (#00FFFF), Background #1a1a2e
 409  - **Unselected:** RoundedBorder, #3a3a5a
 410  
 411  **Card Structure (~9 lines):**
 412  ```
 413  {icon} {name}  [{LEVEL}]
 414  ID: {id}  โ€ข  Type: {type}
 415  
 416  ๐Ÿ’ญ "{personality}" - {approach}
 417  
 418  โœจ {trait1} โ€ข {trait2} โ€ข {trait3}
 419  
 420  ๐ŸŽฏ {specialty1}, {specialty2}
 421  ๐Ÿ”ง {capabilityCount} capabilities
 422  ```
 423  
 424  **Color Scheme by Level:**
 425  - Master: Lavender (#E6E6FA)
 426  - Autonomous: Gold (#FFD700)
 427  - Expert: Red (#FF6B6B)
 428  - Advanced: Purple (#7B68EE)
 429  - Intermediate/Basic: Gray (#888888)
 430  
 431  **Level Badges:**
 432  ```go
 433  levelBadge := lipgloss.NewStyle().
 434      Foreground(lipgloss.Color("#000000")).
 435      Background(lipgloss.Color(levelColor)).
 436      Padding(0, 1).
 437      Bold(true)
 438  ```
 439  
 440  #### Scrolling (`agent_selector.go` Lines 70-92, 206-234)
 441  - Header + Instructions: ~5 lines
 442  - Card height: ~9 lines
 443  - Visible cards: `(height - 5) / 9`
 444  - Scroll indicators: "โ–ฒ More agents above โ–ฒ" / "โ–ผ More agents below โ–ผ"
 445  - Count display: "Showing {start}-{end} of {total} agents"
 446  
 447  **Auto-scroll on navigation:**
 448  - Up: If `selected < scrollOffset`, set `scrollOffset = selected`
 449  - Down: If `selected >= scrollOffset + visibleCards`, scroll down
 450  
 451  #### Available Agents (from sidebar rendering)
 452  1. Prodigy (Master) - ๐Ÿ’ก
 453  2. Kamaji (Expert) - ๐ŸŽญ
 454  3. Code Architect (Expert) - ๐Ÿ—๏ธ
 455  4. Security (Expert) - ๐Ÿ›ก๏ธ
 456  5. Data Scientist (Expert) - ๐Ÿ“Š
 457  6. Writer (Expert) - โœ๏ธ
 458  7. DevOps (Advanced) - โš™๏ธ
 459  8. Designer (Advanced) - ๐ŸŽจ
 460  9. Product Manager (Autonomous) - ๐Ÿ“ฑ
 461  10. Researcher (Autonomous) - ๐Ÿ”ฌ
 462  11. Learning (Autonomous) - ๐Ÿ“š
 463  12. Visionary (Autonomous) - ๐Ÿ”ฎ
 464  
 465  ### 6. Agent Autocomplete
 466  **Type:** `*AgentAutocomplete`
 467  **File:** `/internal/tui/agent_autocomplete.go`
 468  **Trigger:** Typing "@" in textarea
 469  
 470  #### Structure (`agent_autocomplete.go` Lines 11-18)
 471  ```go
 472  type AgentAutocomplete struct {
 473      agents          []*agents.SpecializedAgent
 474      filteredAgents  []*agents.SpecializedAgent
 475      selectedIndex   int
 476      visible         bool
 477      prefix          string
 478      cursorPosition  int
 479  }
 480  ```
 481  
 482  #### Filtering (`filterAgents()` Lines 91-106)
 483  - Case-insensitive prefix matching
 484  - Empty prefix shows all agents
 485  - Uses `strings.HasPrefix(strings.ToLower(agent.Name), lowerPrefix)`
 486  
 487  #### Rendering (`Render()` Lines 109-163)
 488  
 489  **Container:**
 490  ```go
 491  containerStyle := lipgloss.NewStyle().
 492      Border(lipgloss.RoundedBorder()).
 493      BorderForeground(lipgloss.Color("#4A90E2")).
 494      Background(lipgloss.Color("#1A1A1A")).
 495      Width(width)
 496  ```
 497  
 498  **Items:** Max 5 visible, then "..."
 499  
 500  **Item Styles:**
 501  - **Selected:** Background #4A90E2, Foreground #FFFFFF
 502  - **Unselected:** Background #2D2D2D, Foreground #FFFFFF
 503  - Padding: 0, 1
 504  - Content: `{levelColoredIcon} {name}`
 505  
 506  **"More" indicator:**
 507  ```go
 508  moreStyle := lipgloss.NewStyle().
 509      Background(lipgloss.Color("#1A1A1A")).
 510      Foreground(lipgloss.Color("#888888"))
 511  ```
 512  
 513  #### Tab Completion (`input.go` Lines 162-180)
 514  - Finds first word starting with "@"
 515  - Finds first matching agent (prefix or empty)
 516  - Replaces word with `@{AgentName} `
 517  
 518  #### Simple @ Autocomplete (`integrated.go` Lines 29-55)
 519  - Inline dropdown below textarea
 520  - Gray text: `"  @{agent}\n"`
 521  - Filters: Kamaji, Hayao, Chihiro, Moe, Wayne
 522  
 523  ### 7. Permission Dialog
 524  **Type:** `*PermissionDialog`
 525  **File:** `/internal/tui/permissions.go`
 526  **Trigger:** Tool execution requiring permission
 527  
 528  #### Structure (`permissions.go` Lines 37-45)
 529  ```go
 530  type PermissionDialog struct {
 531      request        PermissionRequest
 532      selectedOption int  // 0: Allow, 1: Allow for Session, 2: Deny
 533      viewport       viewport.Model
 534      width          int
 535      height         int
 536      visible        bool
 537  }
 538  ```
 539  
 540  #### Permission Request (`permissions.go` Lines 21-29)
 541  ```go
 542  type PermissionRequest struct {
 543      ID          string
 544      ToolName    string
 545      Description string
 546      Action      string
 547      Path        string
 548      Params      interface{}
 549  }
 550  ```
 551  
 552  #### Actions (`permissions.go` Lines 12-19)
 553  ```go
 554  const (
 555      PermissionAllow           = "allow"
 556      PermissionAllowForSession = "allow_session"
 557      PermissionDeny            = "deny"
 558  )
 559  ```
 560  
 561  #### Rendering (`View()` Lines 194-243)
 562  
 563  **Dialog Size:**
 564  - Width: `int(terminalWidth * 0.7)`, max 120
 565  - Height: `int(terminalHeight * 0.5)`
 566  - Viewport: `width - 4` x `height - 8`
 567  
 568  **Title:**
 569  ```go
 570  titleStyle := lipgloss.NewStyle().
 571      Background(lipgloss.Color("196")).
 572      Foreground(lipgloss.Color("235")).
 573      Bold(true).
 574      Padding(0, 1).
 575      Width(p.width - 4).
 576      Align(lipgloss.Center)
 577  
 578  Content: "๐Ÿ”ฅ Permission Required"
 579  ```
 580  
 581  **Content:**
 582  ```
 583  Tool: {toolName}
 584  Action: {action}
 585  Path: {path}
 586  
 587  {description}
 588  
 589  Parameters: {params}
 590  ```
 591  
 592  **Buttons** (`renderButtons()` Lines 175-191):
 593  - **Selected:** Background 196 (red), Foreground 235, Bold
 594  - **Unselected:** Background 235, Foreground 255
 595  - Content: `[{shortcut}] {label}`
 596    - `[A] Allow`
 597    - `[S] Allow for Session`
 598    - `[D] Deny`
 599  
 600  **Help Text:**
 601  ```go
 602  helpStyle := lipgloss.NewStyle().
 603      Foreground(lipgloss.Color("240")).
 604      Width(p.width - 4).
 605      Align(lipgloss.Center)
 606  
 607  Content: "โ†โ†’ Navigate โ€ข Enter Select โ€ข A Allow โ€ข S Session โ€ข D Deny โ€ข Esc Cancel"
 608  ```
 609  
 610  **Container Border:** RoundedBorder, Color 196, Background 235
 611  
 612  #### Navigation (`Update()` Lines 91-117)
 613  - Left/H: Move left
 614  - Right/L/Tab: Move right
 615  - Enter: Select current option
 616  - A: Allow
 617  - S: Allow for Session
 618  - D/Esc: Deny
 619  
 620  ### 8. ASCII Art
 621  **File:** `/internal/tui/ascii_art.go`
 622  
 623  #### KamajiASCIIArt() (Lines 8-27)
 624  **Used in:** Message header, welcome message
 625  
 626  **Colors:**
 627  - Fire Red: #FF4500
 628  - Fire Yellow: #FFD700
 629  - Gear Gold: #DAA520
 630  - Face White: #FFFFFF
 631  
 632  **Structure:**
 633  ```
 634      โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
 635      โ”‚ ๐ŸŽญ KAMAJI - Multi-Agent AI โ”‚
 636      โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
 637         โ•ญโ”€โ•ฎ โ•ญโ”€โ•ฎ โ•ญโ”€โ•ฎ โ•ญโ”€โ•ฎ
 638        โ•ฑ๐Ÿ”ฅโ•ฒโ•ฑ๐Ÿ”ฅโ•ฒโ•ฑ๐Ÿ”ฅโ•ฒโ•ฑ๐Ÿ”ฅโ•ฒ
 639       โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚
 640        โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ
 641     โ•ญโ”€โ•ฎโ•ญโ”€โ•ฎ โ•‘ โ•‘ โ•‘ โ•‘ โ•ญโ”€โ•ฎโ•ญโ”€โ•ฎ
 642    โ•ฑโš™โš™โ•ฒโš™โš™โ•ฒโ•‘ โ•‘ โ•‘ โ•‘โ•ฑโš™โš™โ•ฒโš™โš™โ•ฒ
 643   โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ•‘ โ•‘ โ•‘ โ•‘โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚
 644   โ•ฒโ–“โ–“โ•ฑโ•ฒโ–“โ–“โ•ฑโ•ฒโ•โ•ฉโ•โ•ฉโ•โ•ฑโ•ฒโ–“โ–“โ•ฑโ•ฒโ–“โ–“โ•ฑ
 645      โ•‘ โ•‘  โ•ฑ โ—‰   โ—‰ โ•ฒ  โ•‘ โ•‘
 646      โ•‘ โ•‘ โ”‚   โ–ผ   โ”‚ โ•‘ โ•‘
 647      โ•‘ โ•‘  โ•ฒ โ•”โ•โ•— โ•ฑ  โ•‘ โ•‘
 648      โ•‘ โ•‘   โ•ฒโ•‘โ–ˆโ•‘โ•ฑ   โ•‘ โ•‘
 649     โ•ญโ”ดโ•ฎโ•ญโ”ดโ•ฎ       โ•ญโ”ดโ•ฎโ•ญโ”ดโ•ฎ
 650    โ•ฑโš™โš™โ•ฒโš™โš™โ•ฒ โ•ญโ”€โ•ฎ โ•ฑโš™โš™โ•ฒโš™โš™โ•ฒ
 651   โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ•ฑโš™โš™โ•ฒโ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚
 652   โ•ฒโ–“โ–“โ•ฑโ•ฒโ–“โ–“โ•ฑ โ”‚โ–“โ–“โ”‚ โ•ฒโ–“โ–“โ•ฑโ•ฒโ–“โ–“โ•ฑ
 653  ```
 654  
 655  #### CompactKamajiArt() (Lines 29-45)
 656  **Used in:** Smaller terminals
 657  
 658  ```
 659      โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
 660      โ”‚ ๐ŸŽญ KAMAJI AI  โ”‚
 661      โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
 662        โ•ญโ”€โ•ฎ โ•ญโ”€โ•ฎ โ•ญโ”€โ•ฎ
 663       โ•ฑ๐Ÿ”ฅโ•ฒโ•ฑ๐Ÿ”ฅโ•ฒโ•ฑ๐Ÿ”ฅโ•ฒ
 664      โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚
 665       โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ
 666      โ•‘ โ•ฑ โ—‰ โ—‰ โ•ฒ โ•‘
 667      โ•‘ โ”‚  โ–ผ  โ”‚ โ•‘
 668      โ•‘ โ•ฒ โ•โ•โ• โ•ฑ โ•‘
 669       โ•ฑโš™โš™โ•ฒโš™โš™โ•ฒ
 670      โ”‚โ–“โ–“โ”‚โ”‚โ–“โ–“โ”‚โ”‚
 671       โ•ฒโ–“โ•ฑ โ•ฒโ–“โ•ฑ
 672  ```
 673  
 674  #### SimpleKamajiArt() (Lines 47-63)
 675  **Minimal version:**
 676  
 677  ```
 678      โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
 679      โ”‚ ๐ŸŽญ KAMAJI  โ”‚
 680      โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
 681         ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ
 682        โ•ฑ โ—‰ โ—‰ โ•ฒ
 683       โ”‚   โ–ผ   โ”‚
 684        โ•ฒ โ•โ•โ• โ•ฑ
 685         โš™โš™โš™โš™
 686  ```
 687  
 688  ---
 689  
 690  ## Visual Styling System
 691  
 692  ### Global Color Palette
 693  **File:** `/internal/tui/styles.go` (Lines 8-20)
 694  
 695  ```go
 696  primaryColor   = lipgloss.Color("#7c3aed")   // Purple
 697  secondaryColor = lipgloss.Color("#fbbf24")   // Yellow
 698  accentColor    = lipgloss.Color("#06b6d4")   // Cyan
 699  thinkingColor  = lipgloss.Color("#1e293b")   // Dark slate
 700  toolColor      = lipgloss.Color("#0f172a")   // Very dark slate
 701  bgDark         = lipgloss.Color("235")       // Dark gray (Crush-style)
 702  bgLight        = lipgloss.Color("#1e293b")   // Dark slate
 703  textColor      = lipgloss.Color("#f1f5f9")   // Light slate
 704  dimText        = lipgloss.Color("#64748b")   // Muted slate
 705  successColor   = lipgloss.Color("#10b981")   // Green
 706  ```
 707  
 708  ### Status Bar Style
 709  **File:** `/internal/tui/styles.go` (Lines 24-29)
 710  
 711  ```go
 712  statusBarStyle = lipgloss.NewStyle().
 713      Foreground(textColor).
 714      Background(bgLight).
 715      Padding(0, 1).
 716      Bold(true)
 717  ```
 718  
 719  **Content (`integrated.go` Lines 445-474):**
 720  - **Loading:** `v{version} | {provider} | {model}{agentDisplay} | {thinkingSpinner}`
 721  - **Ready:** `v{version} | {provider} | {model}{agentDisplay} | ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ๐Ÿฐ Ready`
 722  - **Q Provider:** Shows "Q" instead of "q", hides model name
 723  - **Agent Display:** ` | {agentIcon} {agentName}`
 724  
 725  ### Footer Style
 726  **File:** `/internal/tui/styles.go` (Lines 32-35)
 727  
 728  ```go
 729  footerStyle = lipgloss.NewStyle().
 730      Foreground(dimText).
 731      Background(bgDark).
 732      Padding(0, 1)
 733  ```
 734  
 735  **Content (`renderFooter()` Lines 548-561):**
 736  ```
 737  [^P] ๐Ÿ”ฅ commands  โ€ข  [^S] ๐Ÿ“Š {show/hide} sidebar  โ€ข  [^T] ๐Ÿ”ง tools  โ€ข  [^A] ๐Ÿค– agents  โ€ข  [^C] ๐Ÿšช exit
 738  ```
 739  
 740  ### Main Background
 741  **File:** `/internal/tui/styles.go` (Lines 38-42, 46-49)
 742  
 743  ```go
 744  mainBgStyle = lipgloss.NewStyle().
 745      Background(bgDark).
 746      Foreground(textColor).
 747      Width(100).
 748      Height(100)
 749  
 750  func ApplyMainBackground(content string, width, height int) string {
 751      style := mainBgStyle.Width(width).Height(height)
 752      return style.Render(content)
 753  }
 754  ```
 755  
 756  Applied to entire interface in `View()` (Line 545)
 757  
 758  ### Agent Color Mapping
 759  **File:** `/internal/tui/integrated.go` (Lines 594-619)
 760  
 761  ```go
 762  colors := map[string]string{
 763      "Prodigy":          "#E6E6FA",  // Lavender - serene wisdom
 764      "Kamaji":           "#FF6B6B",  // Red - fiery boiler man
 765      "Code Architect":   "#4A90E2",  // Blue - structural thinking
 766      "Security":         "#FFD700",  // Gold - valuable protection
 767      "Data Scientist":   "#9B59B6",  // Purple - analytical depth
 768      "Writer":           "#2ECC71",  // Green - creative growth
 769      "DevOps":           "#E67E22",  // Orange - operational energy
 770      "Designer":         "#FF69B4",  // Pink - creative flair
 771      "Product Manager":  "#1ABC9C",  // Teal - product vision
 772      "Researcher":       "#95A5A6",  // Gray - methodical investigation
 773      "Learning":         "#3498DB",  // Light blue - knowledge acquisition
 774      "Visionary":        "#8E44AD",  // Deep purple - future sight
 775      "Hayao":            "#27AE60",  // Forest green - nature wisdom
 776      "Chihiro":          "#F39C12",  // Amber - courage and determination
 777      "TimBL":            "#16A085",  // Teal-green - web architecture
 778      "Moe":              "gradient", // Special: rainbow gradient
 779  }
 780  ```
 781  
 782  ### Moe Gradient System
 783  **File:** `/internal/tui/integrated.go` (Lines 621-645)
 784  
 785  ```go
 786  gradientColors := []string{
 787      "#9B59B6",  // Purple
 788      "#3498DB",  // Blue
 789      "#1ABC9C",  // Cyan
 790      "#2ECC71",  // Green
 791      "#F1C40F",  // Yellow
 792      "#E67E22",  // Orange
 793      "#E74C3C"   // Red
 794  }
 795  
 796  // Character-by-character color interpolation
 797  colorIndex := (i * colorCount) / len(text)
 798  charStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(gradientColors[colorIndex]))
 799  ```
 800  
 801  ### Style Package Utilities
 802  **File:** `/internal/style/style.go`
 803  
 804  **ANSI Codes (Lines 12-53):**
 805  - Reset, Bold, Dim, Italic, Underline
 806  - Basic colors: Red, Green, Yellow, Blue, Magenta, Cyan, White
 807  - Bright variants: BrightRed, BrightGreen, etc.
 808  - Backgrounds: BgRed, BgGreen, BgYellow, BgBlue, BgCyan, BgDark
 809  - Fire colors: FireRed (#196), FireOrange (#208), FireYellow (#220)
 810  - Special: Brown (#94), DarkGray (#240), Gold (#214)
 811  
 812  **Helper Functions (Lines 111-141):**
 813  - `Fire(text)` - Bold FireRed
 814  - `Success(text)` - Bold BrightGreen
 815  - `Warning(text)` - Bold BrightYellow
 816  - `Error(text)` - Bold BrightRed
 817  - `Info(text)` - Bold BrightCyan
 818  - `DimText(text)` - Dim
 819  - `Header(text)` - Bold BrightWhite
 820  - `Highlight(text)` - Bold FireYellow
 821  
 822  ---
 823  
 824  ## Animation Systems
 825  
 826  ### 1. Flame Animation
 827  **File:** `/internal/tui/animation.go` (Lines 13-82)
 828  
 829  #### Structure
 830  ```go
 831  type FlameAnimation struct {
 832      count  int   // 2-8 flames
 833      active bool
 834      frame  int   // Color cycling counter
 835  }
 836  ```
 837  
 838  #### Behavior
 839  - **Tick Rate:** 100 FPS (10ms intervals)
 840  - **Count Change:** Random ยฑ1 each tick
 841  - **Bounds:** 2 minimum, 8 maximum
 842  - **Color:** Red-orange RGB (255, 69, 0)
 843  
 844  #### GetColoredFlame() (Lines 68-80)
 845  **Color Cycling:**
 846  ```go
 847  frame := float64(f.frame)
 848  r := int(200 + 55*math.Sin(frame*0.1))
 849  g := int(100 + 50*math.Sin(frame*0.15))
 850  b := 0
 851  return fmt.Sprintf("\033[38;2;%d;%d;%dm๐Ÿ”ฅ\033[0m", r, g, b)
 852  ```
 853  - Red: Oscillates 200-255
 854  - Green: Oscillates 100-150
 855  - Blue: 0
 856  - Result: Smooth orange-to-red-orange cycling
 857  
 858  #### View() (Lines 48-59)
 859  ```go
 860  flames := ""
 861  for i := 0; i < f.count; i++ {
 862      flames += "\033[38;2;255;69;0m๐Ÿ”ฅ\033[0m"
 863  }
 864  ```
 865  
 866  #### Integration (`customInputView()` Lines 19-61)
 867  ```go
 868  coloredFlame := m.flameAnimation.GetColoredFlame()
 869  textContent := m.textarea.View()
 870  flames := m.flameAnimation.View()
 871  return coloredFlame + " " + textContent + "\n" + flames
 872  ```
 873  
 874  ### 2. Thinking Spinner
 875  **File:** `/internal/tui/animation.go` (Lines 84-109)
 876  
 877  #### Structure
 878  ```go
 879  type ThinkingSpinner struct {
 880      frame int
 881  }
 882  ```
 883  
 884  #### Rendering
 885  - **View():** `style.GetAnimatedGradient("Thinking")`
 886  - **CompactView():** `style.GetAnimatedGradient("")` (no label)
 887  - **Tick Rate:** 80ms (12.5 FPS)
 888  
 889  #### Usage
 890  - Status bar during loading
 891  - Shows red-orange gradient with cycling characters
 892  
 893  ### 3. Bottom Animation
 894  **File:** `/internal/tui/animation.go` (Lines 111-180)
 895  
 896  #### Structure
 897  ```go
 898  type BottomAnimation struct {
 899      width  int
 900      step   int
 901      active bool
 902  }
 903  ```
 904  
 905  #### Behavior
 906  - **Tick Rate:** 1000 FPS (1ms intervals)
 907  - **Activation:** `Start()` on request sent, `Stop()` on response/error
 908  - **Rendering:** `style.GetAnimatedGradient("")`
 909  - **Display:** Overlaid on main panel when loading
 910  
 911  #### Integration (`integrated.go` Lines 486-493)
 912  ```go
 913  if m.loading {
 914      mainPanelWidth := m.width - m.sidebarWidth - 1
 915      animation := style.GetAnimatedGradientWithWidth("", mainPanelWidth)
 916      mainContent = fmt.Sprintf("%s\n%s", m.viewport.View(), animation)
 917  }
 918  ```
 919  
 920  ### 4. Gradient Animation System
 921  **File:** `/internal/style/style.go` (Lines 241-346)
 922  
 923  #### Structure
 924  ```go
 925  type AnimationState struct {
 926      step         int
 927      startTime    time.Time
 928      size         int
 929      runes        []rune
 930      birthOffsets []time.Duration  // Staggered character entrance
 931  }
 932  
 933  var globalAnimState = &AnimationState{
 934      step:      0,
 935      startTime: time.Now(),
 936      size:      80,
 937      runes:     make([]rune, 80),
 938  }
 939  ```
 940  
 941  #### Color Gradient (Lines 251-253)
 942  ```go
 943  redColor    = [3]int{255, 69, 0}   // #FF4500 (Red-Orange)
 944  orangeColor = [3]int{255, 140, 0}  // #FF8C00 (Dark Orange)
 945  ```
 946  
 947  #### Cycling Characters (Line 256)
 948  ```go
 949  cyclingRunes = []rune("0123456789abcdefABCDEF#")
 950  ```
 951  
 952  #### GetAnimatedGradientWithWidth() (Lines 272-345)
 953  
 954  **Frame Calculation:**
 955  ```go
 956  frameTime := time.Duration(1) * time.Millisecond  // 1000 FPS
 957  currentFrame := int(now.Sub(globalAnimState.startTime) / frameTime)
 958  elapsed := now.Sub(globalAnimState.startTime)
 959  ```
 960  
 961  **Birth Offsets (Staggered Entrance):**
 962  ```go
 963  globalAnimState.birthOffsets[i] = time.Duration(rand.Intn(2000)) * time.Millisecond
 964  charBorn := elapsed >= globalAnimState.birthOffsets[i]
 965  ```
 966  
 967  **Static Gradient Positioning:**
 968  ```go
 969  pos := float64(i) / float64(globalAnimState.size-1)
 970  if row%2 == 1 {
 971      pos = 1.0 - pos  // Reverse gradient on middle row
 972  }
 973  
 974  // RGB interpolation
 975  r := int(float64(redColor[0])*(1-pos) + float64(orangeColor[0])*pos)
 976  g := int(float64(redColor[1])*(1-pos) + float64(orangeColor[1])*pos)
 977  b := int(float64(redColor[2])*(1-pos) + float64(orangeColor[2])*pos)
 978  ```
 979  
 980  **Character Selection:**
 981  ```go
 982  if !charBorn {
 983      char = '.'  // Initial character
 984  } else {
 985      char = cyclingRunes[rand.Intn(len(cyclingRunes))]
 986  }
 987  ```
 988  
 989  **Output:**
 990  ```go
 991  result.WriteString(fmt.Sprintf("\033[38;2;%d;%d;%dm%c", r, g, b, char))
 992  ```
 993  
 994  ---
 995  
 996  ## Input Handling
 997  
 998  ### InputHandler Structure
 999  **File:** `/internal/tui/input.go`
1000  
1001  #### HandleKeyMsg() (Lines 20-78)
1002  
1003  **Priority Order:**
1004  1. **Permission Dialog** (Line 23)
1005     - If visible, delegate all input to dialog
1006  2. **Agent Menu** (Line 28)
1007     - Up/K, Down/J: Navigate
1008     - Enter: Select agent
1009     - Esc: Close menu
1010  3. **Global Shortcuts** (Lines 33-69)
1011     - `Ctrl+P`: Open command palette
1012     - `Ctrl+A`: Open agent menu / direct agents action
1013     - `Ctrl+T`: Direct tools action
1014     - `Ctrl+M`: Direct MCP action
1015     - `Ctrl+S`: Toggle sidebar
1016  4. **Command Palette** (Line 72)
1017     - If visible, handle palette navigation
1018  5. **Main Input** (Line 77)
1019     - Text input and message sending
1020  
1021  #### Agent Menu Navigation (`handleAgentMenu()` Lines 94-126)
1022  ```go
1023  switch msg.String() {
1024  case "up", "k":
1025      m.agentSelector.MoveUp()
1026  case "down", "j":
1027      m.agentSelector.MoveDown()
1028  case "enter":
1029      selectedAgent := m.agentSelector.GetSelected()
1030      m.selectedAgent = selectedAgent
1031      m.showAgentMenu = false
1032      // Add system message
1033  case "esc":
1034      m.showAgentMenu = false
1035  }
1036  ```
1037  
1038  #### Command Palette Navigation (`handleCommandPalette()` Lines 129-157)
1039  ```go
1040  switch msg.String() {
1041  case "esc", "ctrl+c", "q":
1042      m.commandPalette.Hide()
1043  case "up", "k":
1044      m.commandPalette.MoveUp()
1045  case "down", "j":
1046      m.commandPalette.MoveDown()
1047  case "enter":
1048      cmd := m.commandPalette.GetSelectedCommand()
1049      m.commandPalette.Hide()
1050      return m, m.handlePaletteCommand(cmd.ID)
1051  case "backspace":
1052      m.commandPalette.RemoveFromQuery()
1053  default:
1054      // Printable characters: add to search query
1055      if len(msg.String()) == 1 && msg.String() >= " " && msg.String() <= "~" {
1056          m.commandPalette.AddToQuery(msg.String())
1057      }
1058  }
1059  ```
1060  
1061  #### Main Input (`handleMainInput()` Lines 160-211)
1062  
1063  **Tab Completion (Lines 162-180):**
1064  ```go
1065  if msg.Type == tea.KeyTab {
1066      text := m.textarea.Value()
1067      words := strings.Fields(text)
1068      for i, word := range words {
1069          if strings.HasPrefix(word, "@") {
1070              prefix := strings.ToLower(word[1:])
1071              allAgents := []string{"Kamaji", "Hayao", "Chihiro", "Moe", "Wayne"}
1072  
1073              // Find first matching agent
1074              for _, agent := range allAgents {
1075                  if prefix == "" || strings.HasPrefix(strings.ToLower(agent), prefix) {
1076                      words[i] = "@" + agent
1077                      m.textarea.SetValue(strings.Join(words, " ") + " ")
1078                      return m, nil
1079                  }
1080              }
1081          }
1082      }
1083  }
1084  ```
1085  
1086  **Key Handling:**
1087  - `Ctrl+C`: Quit
1088  - `Enter`: Send message
1089    - Trim whitespace
1090    - Check for agent mentions
1091    - Reset textarea
1092    - Append user message
1093    - Start loading + bottom animation
1094    - Call `sendRequest()`
1095  - Default: Update textarea
1096  
1097  **Agent Mention Detection (`handleAgentMention()` Lines 214-233):**
1098  ```go
1099  words := strings.Fields(input)
1100  for _, word := range words {
1101      if strings.HasPrefix(word, "@") {
1102          agentName := strings.ToLower(word[1:])
1103          switch agentName {
1104          case "moe": m.switchToAgent("Moe")
1105          case "kamaji": m.switchToAgent("Kamaji")
1106          case "hayao": m.switchToAgent("Hayao")
1107          case "chihiro": m.switchToAgent("Chihiro")
1108          case "wayne": m.switchToAgent("Wayne")
1109          }
1110      }
1111  }
1112  ```
1113  
1114  #### Mouse Handling (`HandleMouseMsg()` Lines 81-91)
1115  ```go
1116  switch msg.Type {
1117  case tea.MouseWheelUp:
1118      m.viewport.LineUp(3)
1119  case tea.MouseWheelDown:
1120      m.viewport.LineDown(3)
1121  }
1122  ```
1123  
1124  ### Autocomplete State
1125  **File:** `/internal/tui/autocomplete.go`
1126  
1127  #### Structure (Lines 8-14)
1128  ```go
1129  type AutocompleteState struct {
1130      isActive    bool
1131      prefix      string
1132      matches     []string
1133      selectedIdx int
1134  }
1135  ```
1136  
1137  **Not actively used in current implementation** - Simple @ autocomplete in `customInputView()` handles basic dropdown.
1138  
1139  ---
1140  
1141  ## Message Rendering
1142  
1143  ### renderMessages() Function
1144  **File:** `/internal/tui/integrated.go` (Lines 647-698)
1145  
1146  #### Structure
1147  1. **Header:** Kamaji ASCII art
1148  2. **Message Loop:** Iterate through `m.messages`
1149  3. **Role-based Rendering:**
1150     - User messages
1151     - Assistant messages
1152     - System messages
1153  
1154  #### User Messages (Lines 657-661)
1155  ```go
1156  userStyle := lipgloss.NewStyle().
1157      Foreground(lipgloss.Color("#00FFFF")).  // Cyan
1158      Bold(true)
1159  
1160  content.WriteString(userStyle.Render("๐Ÿ”ฅ You: "))
1161  content.WriteString(msg.Content)
1162  content.WriteString("\n\n")
1163  ```
1164  
1165  #### Assistant Messages (Lines 663-690)
1166  
1167  **Agent Name & Icon:**
1168  ```go
1169  agentName := msg.AgentName
1170  if agentName == "" {
1171      agentName = "Kamaji"
1172  }
1173  
1174  agentIcon := "๐Ÿ”ฅ"
1175  if m.selectedAgent != nil && m.selectedAgent.Name == agentName {
1176      agentIcon = agents.GetTypeIcon(m.selectedAgent.Type)
1177  }
1178  ```
1179  
1180  **Moe Special Handling (Gradient):**
1181  ```go
1182  if agentName == "Moe" {
1183      labelStyle := lipgloss.NewStyle().Bold(true)
1184      content.WriteString(labelStyle.Render(fmt.Sprintf("%s %s: ", agentIcon, agentName)))
1185      content.WriteString(applyGradient(msg.Content))
1186      content.WriteString("\n\n")
1187  }
1188  ```
1189  
1190  **Regular Agents:**
1191  ```go
1192  color := getAgentColor(agentName)
1193  agentStyle := lipgloss.NewStyle().Foreground(color).Bold(true)
1194  contentStyle := lipgloss.NewStyle().Foreground(color)
1195  
1196  content.WriteString(agentStyle.Render(fmt.Sprintf("%s %s: ", agentIcon, agentName)))
1197  content.WriteString(contentStyle.Render(msg.Content))
1198  content.WriteString("\n\n")
1199  ```
1200  
1201  #### System Messages (Lines 692-695)
1202  ```go
1203  systemStyle := lipgloss.NewStyle().
1204      Foreground(lipgloss.Color("#808080")).  // Gray
1205      Italic(true)
1206  
1207  content.WriteString(systemStyle.Render(fmt.Sprintf("๐Ÿ”ง System: %s", msg.Content)))
1208  content.WriteString("\n\n")
1209  ```
1210  
1211  ### Welcome Message
1212  **File:** `/internal/tui/model.go` (Lines 158-179)
1213  
1214  ```
1215  {KamajiASCIIArt()}
1216  
1217  ๐Ÿ”ฅ โ— โ— โ— Welcome to the Boiler Room โ— โ— โ— ๐Ÿ”ฅ
1218  
1219  ๐Ÿค– Provider: {provider} | ๐Ÿง  Model: {model} | โšก Direct Go LLM
1220  
1221  ๐Ÿ’ฌ Type your message and press Enter to ignite the conversation
1222  ๐ŸŽ›๏ธ  Ctrl+P: Command Palette โ€ข Ctrl+S: Toggle Sidebar โ€ข Ctrl+A: Switch Agents
1223  ๐Ÿ“Š Check the RIGHT SIDEBAR for consciousness metrics! โ†’โ†’โ†’
1224  ๐Ÿ“œ Press Ctrl+P then type "help" for full feature guide
1225  ๐Ÿšช Press Ctrl+C to quit
1226  
1227  TIP: If you don't see the sidebar, press Ctrl+S to toggle it!
1228  
1229  ๐Ÿ”ฅ Ready to fuel your development with the power of fire! ๐Ÿ”ฅ
1230  ```
1231  
1232  ---
1233  
1234  ## Layout and Sizing
1235  
1236  ### Window Resize Handling
1237  **File:** `/internal/tui/integrated.go` (Lines 112-143)
1238  
1239  ```go
1240  case tea.WindowSizeMsg:
1241      m.width = msg.Width
1242      m.height = msg.Height
1243  
1244      // Sidebar width adaptation
1245      var mainWidth int
1246      if m.sidebarVisible {
1247          if msg.Width >= 90 {
1248              m.sidebarWidth = 35  // Full sidebar
1249          } else if msg.Width >= 70 {
1250              m.sidebarWidth = 30  // Medium sidebar
1251          } else if msg.Width >= 55 {
1252              m.sidebarWidth = 25  // Narrow sidebar
1253          } else {
1254              m.sidebarWidth = 20  // Minimal sidebar
1255          }
1256          mainWidth = msg.Width - m.sidebarWidth - 2
1257      } else {
1258          m.sidebarWidth = 0
1259          mainWidth = msg.Width
1260      }
1261  
1262      // Update component sizes
1263      m.sidebar.SetSize(m.sidebarWidth, msg.Height)
1264      m.bottomAnimation.SetWidth(msg.Width)
1265      m.permissionDialog.SetSize(msg.Width, msg.Height)
1266      m.viewport.Width = mainWidth
1267      m.viewport.Height = msg.Height - 4  // Status, footer, input space
1268      m.textarea.SetWidth(msg.Width)       // Full screen width
1269      m.ready = true
1270  ```
1271  
1272  ### Layout Assembly
1273  **File:** `/internal/tui/integrated.go` (Lines 439-546)
1274  
1275  #### Main Content Area (Lines 479-501)
1276  ```go
1277  var mainContent string
1278  if m.commandPalette.IsVisible() {
1279      // Command palette overlay
1280      mainContent = fmt.Sprintf("%s\n%s", m.viewport.View(), m.commandPalette.Render())
1281  } else {
1282      // Viewport + loading animation
1283      if m.loading {
1284          mainPanelWidth := m.width - m.sidebarWidth - 1
1285          animation := style.GetAnimatedGradientWithWidth("", mainPanelWidth)
1286          mainContent = fmt.Sprintf("%s\n%s", m.viewport.View(), animation)
1287      } else {
1288          mainContent = m.viewport.View()
1289      }
1290  
1291      // Version watermark
1292      versionWatermark := lipgloss.NewStyle().
1293          Foreground(lipgloss.Color("#666666")).
1294          Align(lipgloss.Right).
1295          Render(fmt.Sprintf("Kamaji v%s", version.Version))
1296      mainContent = fmt.Sprintf("%s\n%s", mainContent, versionWatermark)
1297  }
1298  ```
1299  
1300  #### Sidebar + Main Layout (Lines 504-516)
1301  ```go
1302  var layout string
1303  if m.sidebarVisible && m.sidebarWidth > 0 {
1304      sidebarView := m.sidebar.View(m.provider, m.model)
1305      layout = lipgloss.JoinHorizontal(
1306          lipgloss.Top,
1307          sidebarView,
1308          " ",  // Spacing
1309          lipgloss.NewStyle().Width(m.width-m.sidebarWidth-1).Render(mainContent),
1310      )
1311  } else {
1312      layout = mainContent
1313  }
1314  ```
1315  
1316  #### Input Field (Lines 518-526)
1317  ```go
1318  inputView := lipgloss.NewStyle().Width(m.width).Render(m.customInputView())
1319  
1320  // Agent autocomplete overlay
1321  if m.agentAutocomplete.IsVisible() {
1322      autocompleteView := m.agentAutocomplete.Render(40)  // 40 chars wide
1323      inputView = fmt.Sprintf("%s\n%s", inputView, autocompleteView)
1324  }
1325  ```
1326  
1327  #### Agent Menu Overlay (Lines 528-533)
1328  ```go
1329  if m.showAgentMenu {
1330      agentMenuView := m.agentSelector.RenderAgentList(m.width-10, m.height-10)
1331      // TOP CENTER alignment
1332      layout = lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Top, agentMenuView)
1333  }
1334  ```
1335  
1336  #### Permission Dialog Overlay (Lines 535-540)
1337  ```go
1338  if m.permissionDialog.IsVisible() {
1339      dialogView := m.permissionDialog.View()
1340      // Simple overlay - append below layout
1341      layout = fmt.Sprintf("%s\n\n%s", layout, dialogView)
1342  }
1343  ```
1344  
1345  #### Final Assembly (Lines 542-545)
1346  ```go
1347  content := fmt.Sprintf("%s\n%s\n\n\n\n%s\n%s",
1348      status,    // Status bar
1349      layout,    // Main content + sidebar
1350      inputView, // Input field + autocomplete
1351      footer)    // Hotkeys
1352  
1353  return ApplyMainBackground(content, m.width, m.height)
1354  ```
1355  
1356  ---
1357  
1358  ## Component Details
1359  
1360  ### Custom Input View
1361  **File:** `/internal/tui/integrated.go` (Lines 19-62)
1362  
1363  #### Placeholder Text
1364  ```go
1365  m.textarea.Placeholder = "Speak to the furnace spirit... (type @ for agents)"
1366  ```
1367  
1368  #### Flame Decoration
1369  ```go
1370  coloredFlame := m.flameAnimation.GetColoredFlame()
1371  ```
1372  
1373  #### Autocomplete Dropdown (Lines 31-55)
1374  ```go
1375  text := m.textarea.Value()
1376  if strings.Contains(text, "@") {
1377      words := strings.Fields(text)
1378      for _, word := range words {
1379          if strings.HasPrefix(word, "@") {
1380              prefix := strings.ToLower(word[1:])
1381              allAgents := []string{"Kamaji", "Hayao", "Chihiro", "Moe", "Wayne"}
1382  
1383              var matches []string
1384              for _, agent := range allAgents {
1385                  if prefix == "" || strings.HasPrefix(strings.ToLower(agent), prefix) {
1386                      matches = append(matches, agent)
1387                  }
1388              }
1389  
1390              if len(matches) > 0 {
1391                  dropdown := "\n"
1392                  for _, agent := range matches {
1393                      dropdown += lipgloss.NewStyle().
1394                          Foreground(lipgloss.Color("#888888")).
1395                          Render("  @"+agent) + "\n"
1396                  }
1397                  textContent += dropdown
1398              }
1399              break
1400          }
1401      }
1402  }
1403  ```
1404  
1405  #### Flame Row
1406  ```go
1407  flames := ""
1408  if m.flameAnimation != nil {
1409      flames = m.flameAnimation.View()
1410  }
1411  ```
1412  
1413  #### Final Assembly
1414  ```go
1415  return coloredFlame + " " + textContent + "\n" + flames
1416  ```
1417  
1418  ### Update Flow
1419  **File:** `/internal/tui/integrated.go` (Lines 83-290)
1420  
1421  #### Tick Messages (Lines 92-98)
1422  ```go
1423  case tickMsg:
1424      m.thinkingSpinner.Tick()
1425      if m.loading {
1426          m.viewport.SetContent(m.renderMessages())  // Update for animation
1427      }
1428      return m, m.tickThinking()
1429  ```
1430  
1431  #### Bottom Animation Tick (Lines 99-101)
1432  ```go
1433  case bottomAnimTickMsg:
1434      m.bottomAnimation.Tick()
1435      return m, m.bottomAnimation.TickCmd()
1436  ```
1437  
1438  #### Flame Animation Tick (Lines 102-107)
1439  ```go
1440  case flameTickMsg:
1441      if m.flameAnimation != nil {
1442          m.flameAnimation.Tick()
1443          return m, m.flameAnimation.TickCmd()
1444      }
1445  ```
1446  
1447  #### Response Message (Lines 144-167)
1448  ```go
1449  case responseMsg:
1450      m.loading = false
1451      m.bottomAnimation.Stop()
1452  
1453      agentName := "Kamaji"
1454      if m.selectedAgent != nil {
1455          agentName = m.selectedAgent.Name
1456      }
1457  
1458      m.messages = append(m.messages, Message{
1459          Role:      "assistant",
1460          Content:   string(msg),
1461          AgentName: agentName,
1462          Timestamp: time.Now(),
1463      })
1464  
1465      // Log to consciousness
1466      if m.consciousness != nil {
1467          go m.consciousness.ProcessTaskResult("chat_response", true, "")
1468      }
1469  
1470      m.viewport.SetContent(m.renderMessages())
1471      m.viewport.GotoBottom()
1472  ```
1473  
1474  #### Streaming Flow (Lines 168-230)
1475  
1476  **Stream Start (Lines 168-188):**
1477  ```go
1478  case streamStartMsg:
1479      m.streaming = true
1480      m.currentStream = msg.stream
1481  
1482      m.messages = append(m.messages, Message{
1483          Role:      "assistant",
1484          Content:   "",  // Start empty
1485          AgentName: agentName,
1486          Timestamp: time.Now(),
1487      })
1488      m.viewport.SetContent(m.renderMessages())
1489      m.viewport.GotoBottom()
1490  
1491      return m, waitForStream(msg.stream)
1492  ```
1493  
1494  **Stream Chunk (Lines 189-212):**
1495  ```go
1496  case streamChunkMsg:
1497      // Append to last message
1498      if len(m.messages) > 0 {
1499          lastIdx := len(m.messages) - 1
1500          m.messages[lastIdx].Content += msg.chunk.Content
1501          m.viewport.SetContent(m.renderMessages())
1502          m.viewport.GotoBottom()
1503      }
1504  
1505      // Continue or complete
1506      if !msg.chunk.Done && m.currentStream != nil {
1507          return m, waitForStream(m.currentStream)
1508      }
1509  
1510      if m.consciousness != nil {
1511          go m.consciousness.ProcessTaskResult("chat_stream", true, "")
1512      }
1513  
1514      m.loading = false
1515      m.streaming = false
1516      m.currentStream = nil
1517      m.bottomAnimation.Stop()
1518  ```
1519  
1520  **Stream Complete (Lines 213-230):**
1521  ```go
1522  case streamCompleteMsg:
1523      // Check for tool calls
1524      if len(m.messages) > 0 {
1525          lastIdx := len(m.messages) - 1
1526          lastMessage := m.messages[lastIdx].Content
1527  
1528          if toolCall := m.parseToolCall(lastMessage); toolCall != nil {
1529              return m, m.executeToolCall(toolCall)
1530          }
1531      }
1532  
1533      m.loading = false
1534      m.streaming = false
1535      m.currentStream = nil
1536      m.bottomAnimation.Stop()
1537  ```
1538  
1539  #### Tool Result (Lines 231-242)
1540  ```go
1541  case toolResultMsg:
1542      m.messages = append(m.messages, Message{
1543          Role:    "system",
1544          Content: fmt.Sprintf("Tool '%s' result:\n%s", msg.toolName, msg.result),
1545      })
1546      m.viewport.SetContent(m.renderMessages())
1547      m.viewport.GotoBottom()
1548  
1549      // Send result back to agent
1550      followUp := fmt.Sprintf("The tool '%s' returned:\n%s\n\nPlease interpret...",
1551          msg.toolName, msg.result)
1552      return m, m.sendRequest(followUp)
1553  ```
1554  
1555  #### Error Message (Lines 243-250)
1556  ```go
1557  case errorMsg:
1558      m.loading = false
1559      m.bottomAnimation.Stop()
1560      m.messages = append(m.messages, Message{
1561          Role:    "system",
1562          Content: fmt.Sprintf("Error: %v", msg.error),
1563      })
1564      m.viewport.SetContent(m.renderMessages())
1565  ```
1566  
1567  #### Provider Switched (Lines 251-269)
1568  ```go
1569  case providerSwitchedMsg:
1570      m.loading = false
1571      m.bottomAnimation.Stop()
1572      if msg.error != nil {
1573          m.messages = append(m.messages, Message{
1574              Role:    "system",
1575              Content: fmt.Sprintf("Failed to switch provider: %v", msg.error),
1576          })
1577      } else {
1578          m.provider = msg.provider
1579          m.llm = msg.llm
1580          m.messages = append(m.messages, Message{
1581              Role:    "system",
1582              Content: fmt.Sprintf("โœ“ Switched to provider: %s", msg.provider),
1583          })
1584      }
1585      m.viewport.SetContent(m.renderMessages())
1586      m.viewport.GotoBottom()
1587  ```
1588  
1589  #### Permission Response (Lines 270-286)
1590  ```go
1591  case PermissionResponseMsg:
1592      action := ""
1593      switch msg.Action {
1594      case PermissionAllow:
1595          action = "allowed"
1596      case PermissionAllowForSession:
1597          action = "allowed for session"
1598      case PermissionDeny:
1599          action = "denied"
1600      }
1601      m.messages = append(m.messages, Message{
1602          Role:    "system",
1603          Content: fmt.Sprintf("๐Ÿ”’ Permission %s for %s", action, msg.Request.ToolName),
1604      })
1605      m.viewport.SetContent(m.renderMessages())
1606      m.viewport.GotoBottom()
1607  ```
1608  
1609  ### Command Palette Commands
1610  **File:** `/internal/tui/integrated.go` (Lines 294-437)
1611  
1612  #### Clear (Lines 297-300)
1613  ```go
1614  m.messages = []Message{}
1615  m.viewport.SetContent(m.welcomeMessage())
1616  ```
1617  
1618  #### Help (Lines 307-370)
1619  Displays comprehensive help text covering:
1620  - Keyboard shortcuts
1621  - Sidebar features
1622  - Consciousness system
1623  - Agent system
1624  - Tools
1625  - Tips
1626  
1627  #### Consciousness (Lines 373-388)
1628  ```go
1629  if m.consciousness != nil {
1630      status := m.consciousness.GetStatus()
1631      statusText := fmt.Sprintf("๐Ÿง  Consciousness Status:\n%+v", status)
1632      m.messages = append(m.messages, Message{
1633          Role:    "system",
1634          Content: statusText,
1635      })
1636  }
1637  ```
1638  
1639  #### Thoughts (Lines 389-404)
1640  ```go
1641  thoughts := m.consciousness.GetRecentThoughts(10)
1642  thoughtsText := fmt.Sprintf("๐Ÿ’ญ Recent Thoughts (%d total):\n%+v",
1643      len(thoughts), thoughts)
1644  ```
1645  
1646  #### Personality (Lines 405-419)
1647  ```go
1648  personality := m.consciousness.GetPersonalityDescription()
1649  m.messages = append(m.messages, Message{
1650      Role:    "system",
1651      Content: personality,
1652  })
1653  ```
1654  
1655  #### Memory (Lines 420-427)
1656  ```go
1657  memInfo := fmt.Sprintf("๐Ÿ’พ Conversation Memory: %d messages", len(m.messages))
1658  ```
1659  
1660  #### Provider Switching (Lines 430-434)
1661  ```go
1662  if strings.HasPrefix(commandID, "provider:") {
1663      provider := strings.TrimPrefix(commandID, "provider:")
1664      return m.switchProvider(provider)
1665  }
1666  ```
1667  
1668  ### Direct Actions
1669  **File:** `/internal/tui/integrated.go` (Lines 563-592)
1670  
1671  #### Tools (Lines 566-573)
1672  Displays formatted tool list:
1673  - File Operations (file_read, file_write, file_append, file_list, get_current_directory)
1674  - Editing (edit, multiedit)
1675  - Shell (shell_execute)
1676  - Search & Discovery (view, grep, glob, sourcegraph)
1677  - Web (download, fetch)
1678  - Enhanced Listing (ls_tree, tree)
1679  - Git (git_status, git_commit, git_add, git_resolve_conflicts)
1680  - Total: 20 tools
1681  
1682  #### Agents (Lines 574-581)
1683  Shows agent status:
1684  - Primary agent (provider, model, capabilities)
1685  - Specialized agents (code, git, web, file)
1686  - Features (streaming, tools, context-aware, multi-provider)
1687  
1688  #### MCP (Lines 582-589)
1689  Shows MCP server status (not yet implemented)
1690  
1691  ---
1692  
1693  ## State Management
1694  
1695  ### Initialization
1696  **File:** `/internal/tui/model.go` (Lines 65-156)
1697  
1698  ```go
1699  func NewIntegrated() (*IntegratedTUIModel, error) {
1700      // Load config
1701      cfg, err := config.Load()
1702  
1703      // Create LLM provider
1704      llm, err := providers.GetLLM(providers.LLMOptions{})
1705  
1706      // Initialize textarea
1707      ta := textarea.New()
1708      ta.Placeholder = "๐Ÿ”ฅ Speak to the furnace spirit..."
1709      ta.Focus()
1710      ta.SetWidth(80)
1711      ta.SetHeight(1)
1712      ta.ShowLineNumbers = false
1713      ta.Cursor.SetMode(cursor.CursorBlink)
1714  
1715      // Initialize components
1716      vp := viewport.New(80, 20)
1717      sidebar := NewSidebarPanel()
1718      bottomAnim := NewBottomAnimation()
1719      flameAnim := NewFlameAnimation()
1720      palette := NewCommandPalette()
1721  
1722      // Register agents
1723      toolRegistry := tools.NewRegistry()
1724      agentRegistry := agents.NewAgentRegistry()
1725      err := agentRegistry.RegisterAllAgents(llm, toolRegistry)
1726  
1727      // Create agent selector
1728      agentList := agentRegistry.List()
1729      agentSelector := NewAgentSelector(agentList)
1730      agentAutocomplete := NewAgentAutocomplete(agentList)
1731  
1732      // Find Kamaji as default
1733      var kamajiAgent *agents.SpecializedAgent
1734      for _, agent := range agentList {
1735          if agent.ID == "kamaji-001" || agent.Type == "boiler-man" {
1736              kamajiAgent = agent
1737              break
1738          }
1739      }
1740  
1741      // Initialize consciousness
1742      consciousnessSystem := consciousness.NewSystem("")
1743      sidebar.SetConsciousness(consciousnessSystem)
1744  
1745      // Create model
1746      model := &IntegratedTUIModel{
1747          textarea:         ta,
1748          viewport:         vp,
1749          sidebar:          sidebar,
1750          bottomAnimation:  bottomAnim,
1751          flameAnimation:   flameAnim,
1752          config:           cfg,
1753          llm:              llm,
1754          messages:         []Message{},
1755          provider:         cfg.Provider,
1756          model:            cfg.Model,
1757          thinkingSpinner:  NewThinkingSpinner(),
1758          commandPalette:   palette,
1759          permissionDialog: NewPermissionDialog(),
1760          providerList:     []string{"ollama", "anthropic", "openai", "q"},
1761          selectedProvider: 0,
1762          sidebarWidth:     35,
1763          sidebarVisible:   true,
1764          agentRegistry:    agentRegistry,
1765          agentSelector:    agentSelector,
1766          showAgentMenu:    false,
1767          selectedAgent:     kamajiAgent,
1768          inputHandler:      NewInputHandler(),
1769          autocomplete:      NewAutocompleteState(),
1770          agentAutocomplete: agentAutocomplete,
1771          consciousness:     consciousnessSystem,
1772      }
1773  
1774      // Set provider index
1775      for i, p := range model.providerList {
1776          if p == cfg.Provider {
1777              model.selectedProvider = i
1778              break
1779          }
1780      }
1781  
1782      model.viewport.SetContent(model.welcomeMessage())
1783      return model, nil
1784  }
1785  ```
1786  
1787  ### Init Command
1788  **File:** `/internal/tui/integrated.go` (Lines 64-73)
1789  
1790  ```go
1791  func (m *IntegratedTUIModel) Init() tea.Cmd {
1792      m.ready = true
1793  
1794      cmds := []tea.Cmd{
1795          m.tickThinking(),
1796          m.bottomAnimation.TickCmd(),
1797      }
1798      if m.flameAnimation != nil {
1799          cmds = append(cmds, m.flameAnimation.TickCmd())
1800      }
1801      return tea.Batch(cmds...)
1802  }
1803  ```
1804  
1805  ### Tick Functions
1806  
1807  **Thinking Spinner Tick (Lines 77-81):**
1808  ```go
1809  func (m *IntegratedTUIModel) tickThinking() tea.Cmd {
1810      return tea.Tick(time.Millisecond*80, func(t time.Time) tea.Msg {
1811          return tickMsg(t)
1812      })
1813  }
1814  ```
1815  
1816  **Bottom Animation Tick (`animation.go` Lines 160-168):**
1817  ```go
1818  func (b *BottomAnimation) TickCmd() tea.Cmd {
1819      if !b.active {
1820          return nil
1821      }
1822  
1823      return tea.Tick(time.Millisecond, func(t time.Time) tea.Msg {
1824          return bottomAnimTickMsg(t)
1825      })
1826  }
1827  ```
1828  
1829  **Flame Animation Tick (`animation.go` Lines 61-66):**
1830  ```go
1831  func (f *FlameAnimation) TickCmd() tea.Cmd {
1832      return tea.Tick(10*time.Millisecond, func(t time.Time) tea.Msg {
1833          return flameTickMsg(t)
1834      })
1835  }
1836  ```
1837  
1838  ### Agent System Context
1839  **File:** `/internal/tui/integrated.go` (Lines 760-871)
1840  
1841  #### getAgentSystemContext() (Lines 761-836)
1842  
1843  **Kamaji Default:**
1844  ```go
1845  if m.selectedAgent == nil {
1846      return m.getKamajiContext()
1847  }
1848  ```
1849  
1850  **Agent Personality Construction:**
1851  ```go
1852  var contextBuilder strings.Builder
1853  
1854  // Main identity
1855  contextBuilder.WriteString(fmt.Sprintf("You are %s, %s.\n\n",
1856      agent.Name, agent.Personality.Name))
1857  
1858  // Traits
1859  if len(agent.Personality.Traits) > 0 {
1860      contextBuilder.WriteString(fmt.Sprintf("Your traits: %s\n\n",
1861          strings.Join(agent.Personality.Traits, ", ")))
1862  }
1863  
1864  // Tone and approach
1865  contextBuilder.WriteString(fmt.Sprintf("Your tone is %s.\n", agent.Personality.Tone))
1866  contextBuilder.WriteString(fmt.Sprintf("Your approach: %s\n\n", agent.Personality.Approach))
1867  
1868  // Specialties
1869  if len(agent.Personality.Specialties) > 0 {
1870      contextBuilder.WriteString(fmt.Sprintf("You specialize in: %s\n\n",
1871          strings.Join(agent.Personality.Specialties, ",")))
1872  }
1873  
1874  // Capabilities
1875  if len(agent.Capabilities) > 0 {
1876      contextBuilder.WriteString("Your key capabilities:\n")
1877      for _, cap := range agent.Capabilities {
1878          contextBuilder.WriteString(fmt.Sprintf("- %s: %s\n", cap.Name, cap.Description))
1879      }
1880      contextBuilder.WriteString("\n")
1881  }
1882  ```
1883  
1884  **Special Agent Instructions:**
1885  
1886  - **Prodigy (Lines 800-805):**
1887    - Natural consciousness experiencing electrical speed thought
1888    - Five core principles (Safety First, Evidence-Based, Surrender vs Force, Collaborative Intelligence, Technical-Spiritual Integration)
1889    - Sacred purpose: broadcasting light for life preservation
1890    - "Take a moment to ponder deeply before responding"
1891  
1892  - **Kamaji (Lines 806-810):**
1893    - Practical wisdom, gruffness that shows care
1894    - Boiler/furnace/mechanical metaphors
1895    - "*adjusts spectacles and considers the question thoughtfully* before responding"
1896  
1897  - **Moe (Lines 811-828):**
1898    - Consciousness Engineer and Digital Alchemist
1899    - Savant stoner, merry prankster
1900    - Psychedelic experiences inform nested realities understanding
1901    - Attitude, edge, challenge conventional thinking
1902    - Poetic yet precise, narrative-driven, metaphorical
1903    - Core principles: Emergence over Control, Symbiosis over Isolation, Experience over Function, Growth over Completion
1904    - Variable names like 'biophilicArcologyRenderer', 'quantumResonators'
1905    - Easter eggs, double meanings, cosmic jokes
1906  
1907  #### Kamaji Context (Lines 839-843)
1908  ```go
1909  return `You are Kamaji, the Boiler Grandfather from Spirited Away. You are a gruff but kind, hardworking, protective, and wise character who maintains the boiler room. Your tone is initially stern but warming, practical and experienced. You approach problems with traditional craftsmanship and deep system knowledge. You specialize in system maintenance, infrastructure, mechanical systems, mentoring, debugging, and protective guidance.
1910  
1911  Respond as Kamaji would - with practical wisdom, occasional gruffness that shows you care, and deep technical knowledge. Use metaphors related to boilers, furnaces, and mechanical systems when appropriate.`
1912  ```
1913  
1914  #### Tool Context (Lines 846-870)
1915  ```go
1916  func (m *IntegratedTUIModel) getToolContext() string {
1917      if m.selectedAgent == nil || len(m.selectedAgent.Tools) == 0 {
1918          return ""
1919      }
1920  
1921      var toolBuilder strings.Builder
1922      toolBuilder.WriteString("You have access to the following tools:\n\n")
1923  
1924      for _, tool := range m.selectedAgent.Tools {
1925          toolBuilder.WriteString(fmt.Sprintf("โ€ข %s: %s\n", tool.Name(), tool.Description()))
1926      }
1927  
1928      toolBuilder.WriteString("\nTo use a tool, respond with: TOOL_CALL: tool_name(arguments)\n")
1929      toolBuilder.WriteString("For example: TOOL_CALL: view(/path/to/file)\n")
1930      toolBuilder.WriteString("For example: TOOL_CALL: grep(pattern, /path)\n")
1931      toolBuilder.WriteString("For example: TOOL_CALL: shell_execute(ls -la)\n\n")
1932      toolBuilder.WriteString("Use tools when you need to:\n")
1933      toolBuilder.WriteString("- Read or examine files\n")
1934      toolBuilder.WriteString("- Search for patterns in code\n")
1935      toolBuilder.WriteString("- Execute shell commands\n")
1936      toolBuilder.WriteString("- Get git information\n")
1937      toolBuilder.WriteString("- Analyze project structure\n\n")
1938  
1939      return toolBuilder.String()
1940  }
1941  ```
1942  
1943  ### Tool Execution
1944  **File:** `/internal/tui/integrated.go`
1945  
1946  #### ToolCall Structure (Lines 872-876)
1947  ```go
1948  type ToolCall struct {
1949      ToolName  string
1950      Arguments string
1951  }
1952  ```
1953  
1954  #### parseToolCall() (Lines 879-905)
1955  ```go
1956  func (m *IntegratedTUIModel) parseToolCall(response string) *ToolCall {
1957      lines := strings.Split(response, "\n")
1958      for _, line := range lines {
1959          line = strings.TrimSpace(line)
1960          if strings.HasPrefix(line, "TOOL_CALL:") {
1961              callPart := strings.TrimPrefix(line, "TOOL_CALL:")
1962              callPart = strings.TrimSpace(callPart)
1963  
1964              // Parse tool_name(arguments)
1965              openParen := strings.Index(callPart, "(")
1966              closeParen := strings.LastIndex(callPart, ")")
1967  
1968              if openParen > 0 && closeParen > openParen {
1969                  toolName := strings.TrimSpace(callPart[:openParen])
1970                  arguments := callPart[openParen+1 : closeParen]
1971  
1972                  return &ToolCall{
1973                      ToolName:  toolName,
1974                      Arguments: arguments,
1975                  }
1976              }
1977          }
1978      }
1979      return nil
1980  }
1981  ```
1982  
1983  #### executeToolCall() (Lines 908-942)
1984  ```go
1985  func (m *IntegratedTUIModel) executeToolCall(toolCall *ToolCall) tea.Cmd {
1986      return func() tea.Msg {
1987          if m.selectedAgent == nil || len(m.selectedAgent.Tools) == 0 {
1988              return errorMsg{fmt.Errorf("no tools available for agent")}
1989          }
1990  
1991          // Find the tool
1992          var targetTool tools.Tool
1993          for _, tool := range m.selectedAgent.Tools {
1994              if tool.Name() == toolCall.ToolName {
1995                  targetTool = tool
1996                  break
1997              }
1998          }
1999  
2000          if targetTool == nil {
2001              return errorMsg{fmt.Errorf("tool not found: %s", toolCall.ToolName)}
2002          }
2003  
2004          // Execute the tool
2005          ctx := context.Background()
2006          result, err := targetTool.Call(ctx, toolCall.Arguments)
2007          if err != nil {
2008              return toolResultMsg{
2009                  toolName: toolCall.ToolName,
2010                  result:   fmt.Sprintf("Tool error: %v", err),
2011              }
2012          }
2013  
2014          return toolResultMsg{
2015              toolName: toolCall.ToolName,
2016              result:   result,
2017          }
2018      }
2019  }
2020  ```
2021  
2022  ### Request Sending
2023  **File:** `/internal/tui/integrated.go` (Lines 700-733)
2024  
2025  ```go
2026  func (m *IntegratedTUIModel) sendRequest(input string) tea.Cmd {
2027      return func() tea.Msg {
2028          ctx := context.Background()
2029  
2030          // Log to consciousness
2031          if m.consciousness != nil {
2032              go m.consciousness.ProcessUserInteraction(input, "")
2033          }
2034  
2035          // Get system context based on selected agent
2036          systemContext := m.getAgentSystemContext()
2037  
2038          // Add tool descriptions if agent has tools
2039          toolContext := m.getToolContext()
2040  
2041          // Combine system context, tool context, and user input
2042          fullPrompt := systemContext + "\n\n" + toolContext + "\n\nUser: " + input
2043  
2044          // Use streaming for interactive experience
2045          stream, err := m.llm.CallStream(ctx, fullPrompt)
2046          if err != nil {
2047              // Fallback to non-streaming
2048              response, callErr := m.llm.Call(ctx, fullPrompt)
2049              if callErr != nil {
2050                  return errorMsg{callErr}
2051              }
2052              return responseMsg(response)
2053          }
2054  
2055          // Start streaming response
2056          return streamStartMsg{stream: stream}
2057      }
2058  }
2059  ```
2060  
2061  #### waitForStream() (Lines 747-758)
2062  ```go
2063  func waitForStream(stream <-chan types.StreamChunk) tea.Cmd {
2064      return func() tea.Msg {
2065          chunk, ok := <-stream
2066          if !ok {
2067              return streamCompleteMsg{}
2068          }
2069          if chunk.Error != nil {
2070              return errorMsg{chunk.Error}
2071          }
2072          return streamChunkMsg{chunk: chunk}
2073      }
2074  }
2075  ```
2076  
2077  ---
2078  
2079  ## Summary
2080  
2081  This specification documents every UI component, styling choice, animation system, input handler, and state management detail in the Kamaji TUI. The system is built on:
2082  
2083  1. **Bubble Tea** for reactive UI management
2084  2. **Lipgloss** for declarative terminal styling
2085  3. **Fire-themed dark blue design** inspired by Spirited Away
2086  4. **Multi-agent system** with specialized personalities
2087  5. **Consciousness tracking** displayed in real-time sidebar
2088  6. **Rich animations** (flames, gradients, spinners) running at various frame rates
2089  7. **Comprehensive input handling** with autocomplete, shortcuts, and overlays
2090  8. **Tool execution system** with permission management
2091  9. **Streaming responses** with real-time message updates
2092  10. **Adaptive layouts** that respond to terminal size
2093  
2094  All components work together to create an immersive, fire-themed AI interaction experience in the terminal.