Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/client/cli/interface.py: 0%
114 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1# stdlib imports
2import os
3import sys
4from typing import Final
6# third party imports
7import click
9from litellm._logging import verbose_logger
12def styled_prompt():
13 """Create a styled blue box prompt for user input."""
15 # Get terminal height to ensure we have enough space
16 try:
17 terminal_height: Final = os.get_terminal_size().lines
18 # Ensure we have at least 5 lines of space (for the box + some buffer)
19 if terminal_height < 10:
20 # If terminal is too small, just add some newlines to push content up
21 click.echo("\n" * 3)
22 except Exception as e:
23 # Fallback if we can't get terminal size
24 verbose_logger.debug("Error getting terminal size: %s", e)
25 click.echo("\n" * 3)
27 # ASCII box drawing characters
28 top_left: Final = "+"
29 top_right: Final = "+"
30 bottom_left: Final = "+"
31 bottom_right: Final = "+"
32 horizontal: Final = "-"
33 vertical: Final = "|"
35 # Create the box with increased width
36 width: Final = 80
37 top_line: Final = top_left + horizontal * (width - 2) + top_right
38 bottom_line: Final = bottom_left + horizontal * (width - 2) + bottom_right
40 # Create styled elements
41 left_border: Final = click.style(vertical, fg="blue", bold=True)
42 right_border: Final = click.style(vertical, fg="blue", bold=True)
43 prompt_text: Final = click.style("> ", fg="cyan", bold=True)
45 # Display the complete box structure first to reserve space
46 click.echo(click.style(top_line, fg="blue", bold=True))
48 # Create empty space in the box for input
49 empty_space: Final = " " * (width - 4)
50 click.echo(f"{left_border} {empty_space} {right_border}")
52 # Display bottom border to complete the box
53 click.echo(click.style(bottom_line, fg="blue", bold=True))
55 # Now move cursor up to the input line and get input
56 click.echo("\033[2A", nl=False) # Move cursor up 2 lines
57 click.echo(f"\r{left_border} {prompt_text}", nl=False) # Position at start of input line
59 try:
60 # Get user input
61 user_input: Final = input().strip()
63 # Move cursor down to after the box
64 click.echo("\033[1B") # Move cursor down 1 line
65 click.echo("") # Add some space after
67 except (KeyboardInterrupt, EOFError):
68 # Move cursor down and add space
69 click.echo("\033[1B")
70 click.echo("")
71 raise
73 return user_input
76def show_commands():
77 """Display available commands, minus any the operator chose to hide."""
78 from .commands.agents import agent_commands
79 from .commands.config import hidden_command_names
81 commands = [
82 ("login", "Authenticate with the LiteLLM proxy server"),
83 ("logout", "Clear stored authentication"),
84 ("whoami", "Show current authentication status"),
85 ("models", "Manage and view model configurations"),
86 ("credentials", "Manage API credentials"),
87 ("chat", "Interactive streaming chat with models"),
88 ("http", "Make HTTP requests to the proxy"),
89 ("keys", "Manage API keys"),
90 ("teams", "Manage teams and team assignments"),
91 ("users", "Manage users"),
92 ]
93 commands += [(c.name, c.get_short_help_str()) for c in agent_commands()]
94 commands += [
95 ("version", "Show version information"),
96 ("help", "Show this help message"),
97 ("quit", "Exit the interactive session"),
98 ]
100 hidden: Final = hidden_command_names()
102 click.echo("Available commands:")
103 for cmd, description in commands:
104 if cmd not in hidden:
105 click.echo(f" {cmd:<20} {description}")
106 click.echo()
109def setup_shell(ctx: click.Context):
110 """Set up the interactive shell with banner and initial info."""
111 from litellm.proxy.common_utils.banner import show_banner
113 show_banner()
115 # Show server connection info
116 base_url: Final = ctx.obj.get("base_url")
117 click.secho(f"Connected to LiteLLM server: {base_url}\n", fg="green")
119 show_commands()
122def handle_special_commands(user_input: str) -> bool:
123 """Handle special commands like exit, help, clear. Returns True if command was handled."""
124 if user_input.lower() in ["exit", "quit"]:
125 click.echo("Goodbye!")
126 return True
127 elif user_input.lower() == "help":
128 click.echo("") # Add space before help
129 show_commands()
130 return True
131 elif user_input.lower() == "clear":
132 click.clear()
133 from litellm.proxy.common_utils.banner import show_banner
135 show_banner()
136 show_commands()
137 return True
139 return False
142def execute_command(user_input: str, ctx: click.Context):
143 """Parse and execute a command."""
144 # Parse command and arguments
145 parts: Final = user_input.split()
146 command: Final = parts[0]
147 args: Final = parts[1:] if len(parts) > 1 else []
149 # Import cli here to avoid circular import
150 from . import main
152 cli: Final = main.cli
154 # Check if command exists
155 if command not in cli.commands:
156 click.echo(f"Unknown command: {command}")
157 click.echo("Type 'help' to see available commands.")
158 return
160 # Execute the command
161 try:
162 # Create a new argument list for click to parse
163 sys.argv = ["lite"] + [command] + args
165 # Get the command object and invoke it
166 cmd: Final = cli.commands[command]
168 # Create a new context for the subcommand
169 with ctx.scope():
170 cmd.main(args, parent=ctx, standalone_mode=False)
172 except click.ClickException as e:
173 e.show()
174 except click.Abort:
175 click.echo("Command aborted.")
176 except SystemExit:
177 # Prevent the interactive shell from exiting on command errors
178 pass
179 except Exception as e:
180 click.echo(f"Error executing command: {e}")
183def interactive_shell(ctx: click.Context):
184 """Run the interactive shell."""
185 setup_shell(ctx)
187 while True:
188 try:
189 # Add some space before the input box to ensure it's positioned well
190 click.echo("\n") # Extra spacing
192 # Show styled prompt
193 user_input = styled_prompt()
195 if not user_input:
196 continue
198 # Handle special commands
199 if handle_special_commands(user_input):
200 if user_input.lower() in ["exit", "quit"]:
201 break
202 continue
204 # Execute regular commands
205 execute_command(user_input, ctx)
207 except (KeyboardInterrupt, EOFError):
208 click.echo("\nGoodbye!")
209 break
210 except Exception as e:
211 click.echo(f"Error: {e}")