Skip to main content

llm_manager/tui/app/
help.rs

1use super::types::{ActivePanel, App};
2use ratatui::style::{Color, Modifier, Style};
3use ratatui::text::{Line, Span};
4
5impl App {
6    pub fn panel_help_lines(&self) -> Vec<Line<'static>> {
7        let y = Style::default()
8            .fg(Color::Yellow)
9            .add_modifier(Modifier::BOLD);
10
11        match self.ui.active_panel {
12            ActivePanel::Models => vec![
13                Line::from(Span::styled("MODELS PANEL", y)),
14                Line::from(""),
15                Line::from("Displays your local GGUF models and their status."),
16                Line::from(""),
17                Line::from(vec![
18                    Span::styled("j / k / Arrow keys", y),
19                    Span::raw("  Navigate model list"),
20                ]),
21                Line::from(vec![
22                    Span::styled("Enter / l", y),
23                    Span::raw("  Load selected model into server"),
24                ]),
25                Line::from(vec![
26                    Span::styled("u", y),
27                    Span::raw("  Unload model from server"),
28                ]),
29                Line::from(vec![
30                    Span::styled("Ctrl+D / Del", y),
31                    Span::raw("  Delete model (with confirmation)"),
32                ]),
33                Line::from(""),
34                Line::from("In search mode (/):"),
35                Line::from(vec![
36                    Span::styled("Enter", y),
37                    Span::raw("  Execute search"),
38                ]),
39                Line::from(vec![Span::styled("Esc", y), Span::raw("  Exit search")]),
40                Line::from(vec![
41                    Span::styled("l", y),
42                    Span::raw("  View available GGUF files"),
43                ]),
44                Line::from(vec![
45                    Span::styled("S", y),
46                    Span::raw("  Cycle sort order (Relevance/Downloads/Likes/Trending/Created)"),
47                ]),
48                Line::from(vec![Span::styled("B", y), Span::raw("  Go back one page")]),
49                Line::from(vec![
50                    Span::styled("Down at bottom", y),
51                    Span::raw("  Load more results (infinite scroll)"),
52                ]),
53                Line::from(vec![
54                    Span::styled("R", y),
55                    Span::raw("  Fetch and view README"),
56                ]),
57                Line::from(""),
58                Line::from(vec![
59                    Span::styled("Shift+← / →", y),
60                    Span::raw("  Resize panel split (20%-80%)"),
61                ]),
62                Line::from(vec![
63                    Span::styled("Mouse drag on border", y),
64                    Span::raw("  Resize panel split"),
65                ]),
66                Line::from(""),
67                Line::from(vec![
68                    Span::styled("Shift+A", y),
69                    Span::raw("  About box (GPLv3)"),
70                ]),
71            ],
72            ActivePanel::Log => vec![
73                Line::from(Span::styled("LOG PANEL", y)),
74                Line::from(""),
75                Line::from("Live output from the llama.cpp server."),
76                Line::from(""),
77                Line::from(vec![
78                    Span::styled("j / k / Arrow keys", y),
79                    Span::raw("  Scroll log (Manual mode)"),
80                ]),
81                Line::from(vec![
82                    Span::styled("f", y),
83                    Span::raw("  Toggle Follow mode"),
84                ]),
85                Line::from(vec![
86                    Span::styled("g", y),
87                    Span::raw("  Jump to top (Manual mode)"),
88                ]),
89                Line::from(vec![
90                    Span::styled("G", y),
91                    Span::raw("  Jump to bottom (Follow mode)"),
92                ]),
93                Line::from(vec![
94                    Span::styled("Enter", y),
95                    Span::raw("  Expand log (fills screen)"),
96                ]),
97                Line::from(vec![Span::styled("Esc", y), Span::raw("  Collapse log")]),
98                Line::from(""),
99                Line::from(vec![
100                    Span::styled("Shift+A", y),
101                    Span::raw("  About box (GPLv3)"),
102                ]),
103            ],
104            ActivePanel::ServerSettings => {
105                vec![
106                    Line::from(Span::styled("SERVER SETTINGS", y)),
107                    Line::from(""),
108                    Line::from("Configuration for the llama.cpp server."),
109                    Line::from(""),
110                    Line::from(vec![
111                        Span::styled("j / k", y),
112                        Span::raw("  Select setting"),
113                    ]),
114                    Line::from(vec![Span::styled("Enter", y), Span::raw("  Toggle value")]),
115                    Line::from(vec![
116                        Span::styled("Left / Right", y),
117                        Span::raw("  Adjust value"),
118                    ]),
119                    Line::from(""),
120                    Line::from(vec![
121                        Span::styled("Host", y),
122                        Span::raw("  Bind address (127.0.0.1 or 0.0.0.0)"),
123                    ]),
124                    Line::from(vec![
125                        Span::styled("Backend", y),
126                        Span::raw("  Acceleration backend (cpu / vulkan / rocm)"),
127                    ]),
128                    Line::from(vec![
129                        Span::styled("Threads", y),
130                        Span::raw("  CPU threads for generation (1 to max)"),
131                    ]),
132                    Line::from(vec![
133                        Span::styled("Threads Batch", y),
134                        Span::raw("  CPU threads for batch processing (1 to 32)"),
135                    ]),
136                    Line::from(vec![
137                        Span::styled("Mode", y),
138                        Span::raw("  Server mode (Normal / Bench GPU / BenchTune)"),
139                    ]),
140                    Line::from(vec![
141                        Span::styled("API Endpoint", y),
142                        Span::raw("  Enable API proxy (True/False)"),
143                    ]),
144                    Line::from(vec![
145                        Span::styled("API Port", y),
146                        Span::raw(self.get_api_port_str()),
147                    ]),
148                    Line::from(""),
149                    Line::from(vec![
150                        Span::styled("Shift+A", y),
151                        Span::raw("  About box (GPLv3)"),
152                    ]),
153                ]
154            }
155            ActivePanel::LlmSettings => vec![
156                Line::from(Span::styled("LLM SETTINGS", y)),
157                Line::from(""),
158                Line::from("Fine-tuned settings for loading and running a model."),
159                Line::from(""),
160                Line::from(vec![
161                    Span::styled("j / k", y),
162                    Span::raw("  Navigate settings"),
163                ]),
164                Line::from(vec![Span::styled("Enter", y), Span::raw("  Apply value")]),
165                Line::from(vec![
166                    Span::styled("Left / Right", y),
167                    Span::raw("  Adjust value"),
168                ]),
169                Line::from(vec![
170                    Span::styled("0-9, -, .", y),
171                    Span::raw("  Type numeric value  ·  Ctrl+F7/8/9 switch panels"),
172                ]),
173                Line::from(vec![Span::styled("Esc", y), Span::raw("  Cancel edit")]),
174                Line::from(""),
175                Line::from(vec![
176                    Span::styled("Ctrl+S", y),
177                    Span::raw("  Save settings for selected model"),
178                ]),
179                Line::from(vec![
180                    Span::styled("Ctrl+R", y),
181                    Span::raw("  Reset to defaults"),
182                ]),
183                Line::from(vec![
184                    Span::styled("Ctrl+E", y),
185                    Span::raw("  Toggle enabled/disabled"),
186                ]),
187                Line::from(vec![
188                    Span::styled("Ctrl+X", y),
189                    Span::raw("  Toggle expert mode (shows additional parameters)"),
190                ]),
191                Line::from(""),
192                Line::from(vec![Span::styled("--- Loading ---", y)]),
193                Line::from(vec![
194                    Span::styled("Context", y),
195                    Span::raw(
196                        "  Context window size in tokens. Determines how much of the conversation history is kept in memory. A larger context allows longer conversations but uses more RAM. Typical: 8192-65536 depending on model and RAM.",
197                    ),
198                ]),
199                Line::from(vec![
200                    Span::styled("Prompt", y),
201                    Span::raw(
202                        "  System prompt preset. Pre-configured prompts that shape how the model behaves (e.g., 'coder', 'assistant', 'creative'). Affects the model's personality and output style.",
203                    ),
204                ]),
205                Line::from(vec![
206                    Span::styled("Keep in memory", y),
207                    Span::raw(
208                        "  Lock model weights in RAM (mlock). Prevents the OS from swapping model weights to disk. Slows model load time but ensures faster inference once loaded. Useful for repeated use.",
209                    ),
210                ]),
211                Line::from(""),
212                Line::from(vec![Span::styled("--- GPU Offload ---", y)]),
213                Line::from(vec![
214                    Span::styled("GPU Layers", y),
215                    Span::raw(
216                        "  How many model layers to offload to GPU. Arrow keys cycle: Auto → 1 → 2 → ... → N → All → Auto. Auto lets llama.cpp decide based on VRAM. All loads every layer (999). Specific number sets exact offload count.",
217                    ),
218                ]),
219                Line::from(vec![
220                    Span::styled("Flash Attention", y),
221                    Span::raw(
222                        "  Enable Flash Attention (flash-attn) for faster inference. Requires compatible GPU (Ampere+ / Ada). Significantly speeds up long-context inference. Only works with certain GGUF formats.",
223                    ),
224                ]),
225                Line::from(vec![
226                    Span::styled("KV Cache Offload", y),
227                    Span::raw(
228                        "  Offload KV cache to RAM when GPU memory is full. Allows larger batch sizes and contexts at the cost of some speed. Useful when VRAM is limited but you still want longer conversations.",
229                    ),
230                ]),
231                Line::from(vec![
232                    Span::styled("Cache Type K / V", y),
233                    Span::raw(
234                        "  Quantization precision for KV cache (K = keys, V = values). Lower precision (e.g., Q4, Q8) saves VRAM but may slightly reduce quality. Default is usually FP16. Use lower values if running out of VRAM.",
235                    ),
236                ]),
237                Line::from(vec![
238                    Span::styled("Active Experts", y),
239                    Span::raw(
240                        "  Number of MoE (Mixture of Experts) experts to activate per token. -1 = auto (all active). Reducing this speeds up inference for MoE models like Mixtral but may reduce quality. Typical: 2-8 for Mixtral.",
241                    ),
242                ]),
243                Line::from(""),
244                Line::from(vec![Span::styled("--- Evaluation ---", y)]),
245                Line::from(vec![
246                    Span::styled("Eval Batch", y),
247                    Span::raw(
248                        "  Batch size for evaluation (inference). Larger batches use more VRAM but can improve throughput via parallelism. Small values (1-8) for low VRAM, larger (16-128) for high VRAM setups.",
249                    ),
250                ]),
251                Line::from(vec![
252                    Span::styled("Unified KV", y),
253                    Span::raw(
254                        "  Share KV cache across sequences. Reduces VRAM usage when running multiple requests by reusing allocated cache. May slightly reduce performance but enables more concurrent users.",
255                    ),
256                ]),
257                Line::from(vec![
258                    Span::styled("Max Concurrent Pred", y),
259                    Span::raw(
260                        "  Maximum number of models that can run simultaneously. Press Enter to open a picker that shows how context length divides per model. Each model needs its own VRAM/CPU resources.",
261                    ),
262                ]),
263                Line::from(""),
264                Line::from(vec![Span::styled("--- Sampling ---", y)]),
265                Line::from(vec![
266                    Span::styled("Seed", y),
267                    Span::raw(
268                        "  Random seed for reproducible outputs. -1 = random (default). Set to a fixed value for deterministic, repeatable responses — useful for debugging or testing prompts.",
269                    ),
270                ]),
271                Line::from(vec![
272                    Span::styled("Temp", y),
273                    Span::raw(
274                        "  Sampling temperature. Controls creativity: 0 = deterministic (most predictable), 0.7 = balanced, 1.0+ = creative. Lower values produce more focused, factual outputs. Typical: 0.7-0.9 for general use.",
275                    ),
276                ]),
277                Line::from(vec![
278                    Span::styled("Top-k", y),
279                    Span::raw(
280                        "  Only consider the top k most likely tokens at each step. Smaller top-k (e.g., 10-40) makes output more deterministic. Larger values allow more variety. Typical: 40-50. Set to 0 to disable.",
281                    ),
282                ]),
283                Line::from(vec![
284                    Span::styled("Top-p", y),
285                    Span::raw(
286                        "  Nucleus sampling: only consider tokens whose cumulative probability reaches p. Smaller top-p (e.g., 0.9) is more conservative, larger (e.g., 0.95-0.99) allows more variety. Often preferred over top-k. Typical: 0.9-0.95.",
287                    ),
288                ]),
289                Line::from(vec![
290                    Span::styled("Min P", y),
291                    Span::raw(
292                        "  Minimum probability threshold relative to the most likely token. Tokens below min_p * max_prob are excluded. A filter that's more principled than top-k/top-p for controlling diversity. Typical: 0.01-0.1.",
293                    ),
294                ]),
295                Line::from(vec![
296                    Span::styled("Max Tokens", y),
297                    Span::raw(
298                        "  Maximum number of tokens to generate in the response. Prevents runaway responses. Set to 0 or Disabled for no limit. Typical: 4096-8192 for chat, higher for code generation.",
299                    ),
300                ]),
301                Line::from(""),
302                Line::from(vec![Span::styled("--- Repetition ---", y)]),
303                Line::from(vec![
304                    Span::styled("Repeat Penalty", y),
305                    Span::raw(
306                        "  Controls repetition penalty (1.0 = no penalty, 1.1 = mild, 1.2 = strong). Higher values discourage the model from repeating phrases. Typical: 1.05-1.15 for most use cases.",
307                    ),
308                ]),
309                Line::from(vec![
310                    Span::styled("Repeat Last N", y),
311                    Span::raw(
312                        "  How many recent tokens to check for repetition (0 = all). Smaller values (32-64) focus on local repetition, larger values (128-256) catch longer patterns. Typical: 64.",
313                    ),
314                ]),
315                Line::from(vec![
316                    Span::styled("Presence Penalty", y),
317                    Span::raw(
318                        "  Encourages the model to talk about new topics (+) or stay on topic (-). Positive values reduce topic repetition, negative values encourage deeper exploration. Typical: 0.0 (off).",
319                    ),
320                ]),
321                Line::from(vec![
322                    Span::styled("Freq Penalty", y),
323                    Span::raw(
324                        "  Penalizes tokens based on how often they appear in the text (+) or rewards them (-). Positive values reduce word repetition, negative values encourage denser language. Typical: 0.0 (off).",
325                    ),
326                ]),
327                Line::from(""),
328                Line::from(vec![Span::styled("--- Tags ---", y)]),
329                Line::from(vec![
330                    Span::styled("Tags", y),
331                    Span::raw(
332                        "  Comma-separated labels for the model (e.g., 'coding, chat, reasoning'). Used for filtering and organization. Press Enter to open a tag editor.",
333                    ),
334                ]),
335                Line::from(""),
336                Line::from(vec![Span::styled("--- Backend ---", y)]),
337                Line::from(vec![
338                    Span::styled("LLama.cpp Version", y),
339                    Span::raw(
340                        "  Select the llama.cpp backend binary (CPU / Vulkan / ROCm / CUDA). Press Enter to open a version picker. Different backends support different GPU types and features.",
341                    ),
342                ]),
343                Line::from(""),
344                Line::from(vec![Span::styled("--- Yarn RoPE ---", y)]),
345                Line::from(vec![
346                    Span::styled("Yarn RoPE", y),
347                    Span::raw(
348                        "  Enable YaRN (Yet another RoPE extensioN) for scaling context beyond training limits. YaRN uses a frequency rescaling technique to handle longer contexts. Toggle on/off with Enter.",
349                    ),
350                ]),
351                Line::from(vec![
352                    Span::styled("Yarn Params", y),
353                    Span::raw(
354                        "  YaRN configuration: rope_scale (context multiplier), rope_freq_base (frequency base), rope_freq_scale (frequency scaling). Press Enter to open the YaRN parameter editor.",
355                    ),
356                ]),
357                Line::from(""),
358                Line::from(vec![Span::styled("--- Speculative Decoding ---", y)]),
359                Line::from(vec![
360                    Span::styled("Spec Type", y),
361                    Span::raw(
362                        "  Speculative decoding method for faster inference. Options: Off, draft-mtp (MTP-based), draft-simple, draft-eagle3, ngram-simple, ngram-map-k, ngram-map-k4v, ngram-mod, ngram-cache. Draft-mtp requires a compatible model with MTP architecture.",
363                    ),
364                ]),
365                Line::from(vec![
366                    Span::styled("Spec Draft N Max", y),
367                    Span::raw(
368                        "  Maximum number of draft tokens per step (0-16). More drafts = more potential speedup but also more wasted computation if drafts are rejected. Typical: 4-8 for draft-mtp.",
369                    ),
370                ]),
371                Line::from(""),
372                Line::from(vec![Span::styled("--- Ultra Expert: Loading ---", y)]),
373                Line::from(vec![
374                    Span::styled("Threads Batch", y),
375                    Span::raw(
376                        "  CPU threads for batch processing (1 to 32). Separate from Threads (inference threads). Keep equal for most workloads, or reduce batch threads to lower CPU usage during batch operations.",
377                    ),
378                ]),
379                Line::from(vec![
380                    Span::styled("UBatch Size", y),
381                    Span::raw(
382                        "  Unlimited batch size for prompt processing. Larger values improve prompt evaluation throughput but use more RAM. Typical: 512-2048. Set to 0 to match context_length.",
383                    ),
384                ]),
385                Line::from(vec![
386                    Span::styled("Keep", y),
387                    Span::raw(
388                        "  Number of layers to keep in memory when swapping (negative = all). Useful for fast reloading of the same model. Typical: -1 (all) or 0 (none).",
389                    ),
390                ]),
391                Line::from(vec![
392                    Span::styled("SWA Full", y),
393                    Span::raw(
394                        "  Enable sliding window attention (SWA) for all layers. Allows longer contexts on models trained with SWA (e.g., some Llama variants). Toggle on/off with Enter.",
395                    ),
396                ]),
397                Line::from(vec![
398                    Span::styled("MMap", y),
399                    Span::raw(
400                        "  Memory-map the model file instead of loading it entirely into RAM. Saves RAM but may slow model loading. Toggle on/off with Enter.",
401                    ),
402                ]),
403                Line::from(vec![
404                    Span::styled("NUMA", y),
405                    Span::raw(
406                        "  NUMA (Non-Uniform Memory Access) strategy: None, Distribute, Isolate, or Numactl. Affects CPU thread affinity on multi-socket systems. None = default.",
407                    ),
408                ]),
409                Line::from(""),
410                Line::from(vec![Span::styled("--- Ultra Expert: GPU ---", y)]),
411                Line::from(vec![
412                    Span::styled("Split Mode", y),
413                    Span::raw(
414                        "  GPU split strategy: None, Layer (default), Row, or Tensor. Controls how model layers are distributed across multiple GPUs. Layer splits by layer count, Row/Tensor split by matrix dimensions for multi-GPU setups.",
415                    ),
416                ]),
417                Line::from(vec![
418                    Span::styled("Tensor Split", y),
419                    Span::raw(
420                        "  Fraction of model weights to load on each GPU (colon-separated for multi-GPU, e.g., '0.5:0.5'). For single GPU, leave empty. Press Enter to edit.",
421                    ),
422                ]),
423                Line::from(vec![
424                    Span::styled("Main GPU", y),
425                    Span::raw(
426                        "  Index of the main GPU (0-based). Handles initial model loading and some computations. Typical: 0 for single GPU, 0 for primary in multi-GPU setups.",
427                    ),
428                ]),
429                Line::from(vec![
430                    Span::styled("Fit", y),
431                    Span::raw(
432                        "  Automatically adjust arguments to fit device memory. Toggle on/off with Enter.",
433                    ),
434                ]),
435                Line::from(vec![
436                    Span::styled("LoRA", y),
437                    Span::raw(
438                        "  Path to a LoRA adapter to apply to the model. Press Enter to open a file picker. LoRA adapters modify model behavior without full fine-tuning.",
439                    ),
440                ]),
441                Line::from(vec![
442                    Span::styled("LoRA Scaled", y),
443                    Span::raw(
444                        "  Path to a LoRA adapter with scaling. Press Enter to open a file picker. Scaling adjusts the adapter's influence on the model.",
445                    ),
446                ]),
447                Line::from(vec![
448                    Span::styled("RPC", y),
449                    Span::raw(
450                        "  RPC endpoint for distributed inference (e.g., 'localhost:50052'). Press Enter to edit. Used for offloading parts of the model to remote devices.",
451                    ),
452                ]),
453                Line::from(vec![
454                    Span::styled("Embedding", y),
455                    Span::raw(
456                        "  Enable embedding mode for generating vector embeddings. Toggle on/off with Enter. Required for embedding/semantic search models.",
457                    ),
458                ]),
459                Line::from(""),
460                Line::from(vec![Span::styled("--- Ultra Expert: Sampling ---", y)]),
461                Line::from(vec![
462                    Span::styled("Typical P", y),
463                    Span::raw(
464                        "  Locally typical sampling (typ_p). Controls diversity by keeping tokens with typical probability mass. Values near 1.0 = no effect, 0.1-0.5 = moderate diversity. Typical: 1.0 (off).",
465                    ),
466                ]),
467                Line::from(vec![
468                    Span::styled("Mirostat", y),
469                    Span::raw(
470                        "  Mirostat sampling mode: Off (default), Mirostat, or Mirostat2. Adaptive temperature control that maintains target perplexity. Mirostat2 is more aggressive. Useful for consistent output quality.",
471                    ),
472                ]),
473                Line::from(vec![
474                    Span::styled("Mirostat LR", y),
475                    Span::raw(
476                        "  Mirostat learning rate (eta). Controls how quickly the temperature adapts. Smaller = smoother adjustments. Typical: 0.1.",
477                    ),
478                ]),
479                Line::from(vec![
480                    Span::styled("Mirostat Ent", y),
481                    Span::raw(
482                        "  Mirostat target entropy. Controls the diversity of output. Higher = more diverse. Typical: 5.0.",
483                    ),
484                ]),
485                Line::from(vec![
486                    Span::styled("Ignore EOS", y),
487                    Span::raw(
488                        "  Ignore end-of-sequence tokens during generation. Toggle on/off with Enter. Useful when you want to force the model to continue generating.",
489                    ),
490                ]),
491                Line::from(vec![
492                    Span::styled("Samplers", y),
493                    Span::raw(
494                        "  Semicolon-separated sampler order string (e.g., 'mirostat;temperature;top_k;top_p'). Controls which samplers are applied and in what order. Press Enter to edit.",
495                    ),
496                ]),
497                Line::from(""),
498                Line::from(vec![Span::styled("--- Ultra Expert: DRY ---", y)]),
499                Line::from(vec![
500                    Span::styled("DRY Multiplier", y),
501                    Span::raw(
502                        "  DRY (Don't Repeat Yourself) multiplier. Scales the penalty for repetition. Higher values = stronger anti-repetition. Typical: 1.75.",
503                    ),
504                ]),
505                Line::from(vec![
506                    Span::styled("DRY Base", y),
507                    Span::raw(
508                        "  DRY penalty base (log scale). Controls the strength of the repetition penalty. Typical: 1.0 (log2) or 0.0 (linear).",
509                    ),
510                ]),
511                Line::from(vec![
512                    Span::styled("DRY Allowed Length", y),
513                    Span::raw(
514                        "  Number of recent tokens to check for repetition (penalty starts after this). Higher values check longer context. Typical: 2.",
515                    ),
516                ]),
517                Line::from(vec![
518                    Span::styled("DRY Penalty Last N", y),
519                    Span::raw(
520                        "  How many tokens to consider for DRY penalty (0 = all). Larger values catch longer repetition patterns. Typical: -1 (all) or 128.",
521                    ),
522                ]),
523                Line::from(""),
524                Line::from(vec![Span::styled("--- Ultra Expert: Server ---", y)]),
525                Line::from(vec![
526                    Span::styled("Cache Prompt", y),
527                    Span::raw(
528                        "  Cache prompt tokens to avoid re-evaluating them on each request. Toggle on/off with Enter. Requires API server mode. Dramatically speeds up multi-turn conversations.",
529                    ),
530                ]),
531                Line::from(vec![
532                    Span::styled("Cache Reuse", y),
533                    Span::raw(
534                        "  Amount of KV cache to reuse (0 = none). Enables partial cache reuse between requests. Higher values save computation but use more memory. Typical: 0.",
535                    ),
536                ]),
537                Line::from(vec![
538                    Span::styled("WebUI", y),
539                    Span::raw(
540                        "  Enable WebUI mode for interactive chat via browser. Toggle on/off with Enter. Starts a web interface accessible via HTTP.",
541                    ),
542                ]),
543                Line::from(""),
544                Line::from(vec![
545                    Span::styled("Shift+A", y),
546                    Span::raw("  About box (GPLv3)"),
547                ]),
548            ],
549            ActivePanel::ActiveModel => vec![
550                Line::from(Span::styled("ACTIVE MODEL PANEL", y)),
551                Line::from(""),
552                Line::from("Displays metrics for the currently loaded model."),
553                Line::from(""),
554                Line::from("Shows Tokens/s, context usage (progress bar), CPU, RAM, and VRAM."),
555            ],
556            ActivePanel::ModelInfo => vec![
557                Line::from(Span::styled("MODEL INFO PANEL", y)),
558                Line::from(""),
559                Line::from("GGUF metadata for the selected model."),
560                Line::from(""),
561                Line::from("Displays file name, size, architecture, layers, and training context."),
562            ],
563            ActivePanel::Profiles => vec![
564                Line::from(Span::styled("PROFILES PANEL", y)),
565                Line::from(""),
566                Line::from("Saved presets of settings for quick switching."),
567                Line::from(""),
568                Line::from(vec![
569                    Span::styled("j / k", y),
570                    Span::raw("  Select profile"),
571                ]),
572                Line::from(vec![
573                    Span::styled("Enter", y),
574                    Span::raw("  Apply profile settings"),
575                ]),
576                Line::from(vec![
577                    Span::styled("s", y),
578                    Span::raw("  Save current settings as new profile"),
579                ]),
580                Line::from(vec![
581                    Span::styled("d", y),
582                    Span::raw("  Delete user profile"),
583                ]),
584                Line::from(vec![
585                    Span::styled("Esc", y),
586                    Span::raw("  Back to settings"),
587                ]),
588            ],
589            ActivePanel::SystemPromptPresets => vec![
590                Line::from(Span::styled("SYSTEM PROMPT PRESETS", y)),
591                Line::from(""),
592                Line::from("Named system prompts for different use cases."),
593                Line::from(""),
594                Line::from(vec![Span::styled("j / k", y), Span::raw("  Select preset")]),
595                Line::from(vec![Span::styled("Enter", y), Span::raw("  Apply preset")]),
596                Line::from(vec![
597                    Span::styled("e", y),
598                    Span::raw("  Edit selected preset"),
599                ]),
600                Line::from(vec![Span::styled("n", y), Span::raw("  Create new preset")]),
601                Line::from(vec![
602                    Span::styled("Esc", y),
603                    Span::raw("  Back to settings"),
604                ]),
605            ],
606            ActivePanel::SearchReadme => vec![
607                Line::from(Span::styled("README PANEL", y)),
608                Line::from(""),
609                Line::from("README documentation for the selected model."),
610                Line::from(""),
611                Line::from(vec![
612                    Span::styled("j / k / Arrow keys", y),
613                    Span::raw("  Scroll"),
614                ]),
615                Line::from(vec![
616                    Span::styled("h / l", y),
617                    Span::raw("  Scroll horizontally"),
618                ]),
619                Line::from(vec![
620                    Span::styled("Enter", y),
621                    Span::raw("  Expand to fullscreen"),
622                ]),
623                Line::from(vec![Span::styled("Esc", y), Span::raw("  Collapse / Exit")]),
624            ],
625            ActivePanel::Downloads => vec![
626                Line::from(Span::styled("DOWNLOADS PANEL", y)),
627                Line::from(""),
628                Line::from("Active model downloads from HuggingFace."),
629                Line::from(""),
630                Line::from(vec![
631                    Span::styled("j / k / Arrow keys", y),
632                    Span::raw("  Select download"),
633                ]),
634                Line::from(vec![
635                    Span::styled("p", y),
636                    Span::raw("  Pause / Resume selected download"),
637                ]),
638                Line::from(vec![
639                    Span::styled("⌥C", y),
640                    Span::raw("  Cancel selected download"),
641                ]),
642            ],
643        }
644    }
645}