WIP - adding first screen for tui

This commit is contained in:
rajeevrajeshuni 2025-11-29 09:11:09 +05:30
parent 4152ecfc1f
commit 40b8f2b501
2 changed files with 168 additions and 0 deletions

View file

@ -92,6 +92,7 @@ def _discover_commands() -> List[Type[SupportsCliCommand]]:
("cognee.cli.commands.cognify_command", "CognifyCommand"),
("cognee.cli.commands.delete_command", "DeleteCommand"),
("cognee.cli.commands.config_command", "ConfigCommand"),
("cognee.cli.commands.tui_command", "TuiCommand"),
]
for module_path, class_name in command_modules:

View file

@ -0,0 +1,167 @@
import argparse
from typing import List
from cognee.cli import SupportsCliCommand
from cognee.cli.config import DEFAULT_DOCS_URL
import cognee.cli.echo as fmt
from cognee.cli.exceptions import CliCommandException
class TuiCommand(SupportsCliCommand):
@property
def command_string(self) -> str:
return "tui"
@property
def help_string(self) -> str:
return "Launch the interactive Textual TUI for cognee commands"
@property
def docs_url(self) -> str:
return f"{DEFAULT_DOCS_URL}/usage/tui"
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
# No additional arguments for now
pass
def execute(self, args: argparse.Namespace) -> None:
try:
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, ListView, ListItem, Static
from textual.containers import Container, Vertical
from textual.binding import Binding
class CommandItem(Static):
"""A custom widget for command items with icon and description."""
def __init__(self, icon: str, command: str, description: str):
self.icon = icon
self.command = command
self.description = description
super().__init__()
def render(self) -> str:
return f"{self.icon} {self.command:<12} {self.description}"
class CogneeTUI(App):
"""A k9s-style TUI for cognee commands."""
CSS = """
Screen {
background: $surface;
}
#header {
dock: top;
height: 3;
background: $boost;
color: $text;
content-align: center middle;
border: solid $primary;
}
#main-container {
height: 100%;
border: thick $primary;
background: $surface;
padding: 1;
}
#title {
text-align: center;
color: $accent;
text-style: bold;
padding: 1;
}
ListView {
height: auto;
background: $surface;
border: none;
padding: 0 2;
}
ListItem {
background: $surface;
color: $text;
padding: 0 1;
height: auto;
}
ListItem:hover {
background: $surface;
}
ListItem.--highlight {
background: $primary;
color: $text;
}
CommandItem {
width: 100%;
}
#footer-info {
dock: bottom;
height: 3;
background: $boost;
color: $text-muted;
content-align: center middle;
border: solid $primary;
}
"""
BINDINGS = [
Binding("q", "quit", "Quit", priority=True),
Binding("escape", "quit", "Quit", priority=True),
Binding("enter", "select", "Select", priority=True),
]
def compose(self) -> ComposeResult:
yield Static("🧠 cognee v1.0.0", id="header")
with Container(id="main-container"):
yield Static("Select Command", id="title")
yield ListView(
ListItem(CommandItem("📥", "add", "Add data to cognee")),
ListItem(CommandItem("🔍", "search", "Search data in cognee")),
ListItem(CommandItem("", "cognify", "Process data in cognee")),
ListItem(CommandItem("🗑️", "delete", "Delete data from cognee")),
ListItem(CommandItem("⚙️", "config", "Configure cognee settings")),
)
yield Static(
"↑↓: Navigate • Enter: Select • q/Esc: Quit",
id="footer-info"
)
def on_mount(self) -> None:
"""Focus the list view on mount."""
self.query_one(ListView).index = 0
def on_list_view_selected(self, event: ListView.Selected) -> None:
"""Handle command selection."""
command_item = event.item.query_one(CommandItem)
command = command_item.command
fmt.echo(f"Selected command: {command}")
self.exit()
def action_select(self) -> None:
"""Select the current item."""
list_view = self.query_one(ListView)
list_view.action_select_cursor()
app = CogneeTUI()
app.run()
fmt.success("TUI exited successfully!")
except ImportError:
raise CliCommandException(
"Textual is not installed. Install with: pip install textual",
docs_url=self.docs_url,
)
except Exception as ex:
raise CliCommandException(
f"Failed to launch TUI: {str(ex)}",
docs_url=self.docs_url,
raiseable_exception=ex,
)