Merge branch 'main' into onboarding-completion-trigger
This commit is contained in:
commit
b1bad91f02
4 changed files with 113 additions and 63 deletions
|
|
@ -366,6 +366,21 @@ class OpenRAGTUI(App):
|
||||||
self.env_manager = EnvManager()
|
self.env_manager = EnvManager()
|
||||||
self.docling_manager = DoclingManager() # Initialize singleton instance
|
self.docling_manager = DoclingManager() # Initialize singleton instance
|
||||||
|
|
||||||
|
def notify(
|
||||||
|
self,
|
||||||
|
message: str,
|
||||||
|
*,
|
||||||
|
title: str = "",
|
||||||
|
severity: str = "information",
|
||||||
|
timeout: float | None = None,
|
||||||
|
markup: bool = True,
|
||||||
|
) -> None:
|
||||||
|
"""Override notify to make notifications last 20 seconds by default."""
|
||||||
|
# If timeout is None (default), make it 20 seconds
|
||||||
|
if timeout is None:
|
||||||
|
timeout = 20.0
|
||||||
|
super().notify(message, title=title, severity=severity, timeout=timeout, markup=markup)
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
"""Initialize the application."""
|
"""Initialize the application."""
|
||||||
# Check for runtime availability and show appropriate screen
|
# Check for runtime availability and show appropriate screen
|
||||||
|
|
|
||||||
|
|
@ -116,62 +116,75 @@ class EnvManager:
|
||||||
return f"'{escaped_value}'"
|
return f"'{escaped_value}'"
|
||||||
|
|
||||||
def load_existing_env(self) -> bool:
|
def load_existing_env(self) -> bool:
|
||||||
"""Load existing .env file if it exists."""
|
"""Load existing .env file if it exists, or fall back to environment variables."""
|
||||||
if not self.env_file.exists():
|
import os
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
# Map env vars to config attributes
|
||||||
with open(self.env_file, "r") as f:
|
attr_map = {
|
||||||
for line in f:
|
"OPENAI_API_KEY": "openai_api_key",
|
||||||
line = line.strip()
|
"ANTHROPIC_API_KEY": "anthropic_api_key",
|
||||||
if not line or line.startswith("#"):
|
"OLLAMA_ENDPOINT": "ollama_endpoint",
|
||||||
continue
|
"WATSONX_API_KEY": "watsonx_api_key",
|
||||||
|
"WATSONX_ENDPOINT": "watsonx_endpoint",
|
||||||
|
"WATSONX_PROJECT_ID": "watsonx_project_id",
|
||||||
|
"OPENSEARCH_PASSWORD": "opensearch_password",
|
||||||
|
"LANGFLOW_SECRET_KEY": "langflow_secret_key",
|
||||||
|
"LANGFLOW_SUPERUSER": "langflow_superuser",
|
||||||
|
"LANGFLOW_SUPERUSER_PASSWORD": "langflow_superuser_password",
|
||||||
|
"LANGFLOW_CHAT_FLOW_ID": "langflow_chat_flow_id",
|
||||||
|
"LANGFLOW_INGEST_FLOW_ID": "langflow_ingest_flow_id",
|
||||||
|
"LANGFLOW_URL_INGEST_FLOW_ID": "langflow_url_ingest_flow_id",
|
||||||
|
"NUDGES_FLOW_ID": "nudges_flow_id",
|
||||||
|
"GOOGLE_OAUTH_CLIENT_ID": "google_oauth_client_id",
|
||||||
|
"GOOGLE_OAUTH_CLIENT_SECRET": "google_oauth_client_secret",
|
||||||
|
"MICROSOFT_GRAPH_OAUTH_CLIENT_ID": "microsoft_graph_oauth_client_id",
|
||||||
|
"MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET": "microsoft_graph_oauth_client_secret",
|
||||||
|
"WEBHOOK_BASE_URL": "webhook_base_url",
|
||||||
|
"AWS_ACCESS_KEY_ID": "aws_access_key_id",
|
||||||
|
"AWS_SECRET_ACCESS_KEY": "aws_secret_access_key",
|
||||||
|
"LANGFLOW_PUBLIC_URL": "langflow_public_url",
|
||||||
|
"OPENRAG_DOCUMENTS_PATHS": "openrag_documents_paths",
|
||||||
|
"OPENSEARCH_DATA_PATH": "opensearch_data_path",
|
||||||
|
"LANGFLOW_AUTO_LOGIN": "langflow_auto_login",
|
||||||
|
"LANGFLOW_NEW_USER_IS_ACTIVE": "langflow_new_user_is_active",
|
||||||
|
"LANGFLOW_ENABLE_SUPERUSER_CLI": "langflow_enable_superuser_cli",
|
||||||
|
"DISABLE_INGEST_WITH_LANGFLOW": "disable_ingest_with_langflow",
|
||||||
|
}
|
||||||
|
|
||||||
if "=" in line:
|
loaded_from_file = False
|
||||||
key, value = line.split("=", 1)
|
|
||||||
key = key.strip()
|
|
||||||
value = sanitize_env_value(value)
|
|
||||||
|
|
||||||
# Map env vars to config attributes
|
# Try to load from .env file first
|
||||||
attr_map = {
|
if self.env_file.exists():
|
||||||
"OPENAI_API_KEY": "openai_api_key",
|
try:
|
||||||
"ANTHROPIC_API_KEY": "anthropic_api_key",
|
with open(self.env_file, "r") as f:
|
||||||
"OLLAMA_ENDPOINT": "ollama_endpoint",
|
for line in f:
|
||||||
"WATSONX_API_KEY": "watsonx_api_key",
|
line = line.strip()
|
||||||
"WATSONX_ENDPOINT": "watsonx_endpoint",
|
if not line or line.startswith("#"):
|
||||||
"WATSONX_PROJECT_ID": "watsonx_project_id",
|
continue
|
||||||
"OPENSEARCH_PASSWORD": "opensearch_password",
|
|
||||||
"LANGFLOW_SECRET_KEY": "langflow_secret_key",
|
|
||||||
"LANGFLOW_SUPERUSER": "langflow_superuser",
|
|
||||||
"LANGFLOW_SUPERUSER_PASSWORD": "langflow_superuser_password",
|
|
||||||
"LANGFLOW_CHAT_FLOW_ID": "langflow_chat_flow_id",
|
|
||||||
"LANGFLOW_INGEST_FLOW_ID": "langflow_ingest_flow_id",
|
|
||||||
"LANGFLOW_URL_INGEST_FLOW_ID": "langflow_url_ingest_flow_id",
|
|
||||||
"NUDGES_FLOW_ID": "nudges_flow_id",
|
|
||||||
"GOOGLE_OAUTH_CLIENT_ID": "google_oauth_client_id",
|
|
||||||
"GOOGLE_OAUTH_CLIENT_SECRET": "google_oauth_client_secret",
|
|
||||||
"MICROSOFT_GRAPH_OAUTH_CLIENT_ID": "microsoft_graph_oauth_client_id",
|
|
||||||
"MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET": "microsoft_graph_oauth_client_secret",
|
|
||||||
"WEBHOOK_BASE_URL": "webhook_base_url",
|
|
||||||
"AWS_ACCESS_KEY_ID": "aws_access_key_id",
|
|
||||||
"AWS_SECRET_ACCESS_KEY": "aws_secret_access_key",
|
|
||||||
"LANGFLOW_PUBLIC_URL": "langflow_public_url",
|
|
||||||
"OPENRAG_DOCUMENTS_PATHS": "openrag_documents_paths",
|
|
||||||
"OPENSEARCH_DATA_PATH": "opensearch_data_path",
|
|
||||||
"LANGFLOW_AUTO_LOGIN": "langflow_auto_login",
|
|
||||||
"LANGFLOW_NEW_USER_IS_ACTIVE": "langflow_new_user_is_active",
|
|
||||||
"LANGFLOW_ENABLE_SUPERUSER_CLI": "langflow_enable_superuser_cli",
|
|
||||||
"DISABLE_INGEST_WITH_LANGFLOW": "disable_ingest_with_langflow",
|
|
||||||
}
|
|
||||||
|
|
||||||
if key in attr_map:
|
if "=" in line:
|
||||||
setattr(self.config, attr_map[key], value)
|
key, value = line.split("=", 1)
|
||||||
|
key = key.strip()
|
||||||
|
value = sanitize_env_value(value)
|
||||||
|
|
||||||
|
if key in attr_map:
|
||||||
|
setattr(self.config, attr_map[key], value)
|
||||||
|
|
||||||
|
loaded_from_file = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error loading .env file", error=str(e))
|
||||||
|
|
||||||
|
# Fall back to environment variables if .env file doesn't exist or failed to load
|
||||||
|
if not loaded_from_file:
|
||||||
|
logger.info("No .env file found, loading from environment variables")
|
||||||
|
for env_key, attr_name in attr_map.items():
|
||||||
|
value = os.environ.get(env_key, "")
|
||||||
|
if value:
|
||||||
|
setattr(self.config, attr_name, value)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
return loaded_from_file
|
||||||
logger.error("Error loading .env file", error=str(e))
|
|
||||||
return False
|
|
||||||
|
|
||||||
def setup_secure_defaults(self) -> None:
|
def setup_secure_defaults(self) -> None:
|
||||||
"""Set up secure default values for passwords and keys."""
|
"""Set up secure default values for passwords and keys."""
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,9 @@ class ConfigScreen(Screen):
|
||||||
self.env_manager = EnvManager()
|
self.env_manager = EnvManager()
|
||||||
self.inputs = {}
|
self.inputs = {}
|
||||||
|
|
||||||
|
# Check if .env file exists
|
||||||
|
self.has_env_file = self.env_manager.env_file.exists()
|
||||||
|
|
||||||
# Load existing config if available
|
# Load existing config if available
|
||||||
self.env_manager.load_existing_env()
|
self.env_manager.load_existing_env()
|
||||||
|
|
||||||
|
|
@ -156,12 +159,15 @@ class ConfigScreen(Screen):
|
||||||
with ScrollableContainer(id="config-scroll"):
|
with ScrollableContainer(id="config-scroll"):
|
||||||
with Vertical(id="config-form"):
|
with Vertical(id="config-form"):
|
||||||
yield from self._create_all_fields()
|
yield from self._create_all_fields()
|
||||||
yield Horizontal(
|
# Create button row - conditionally include Back button
|
||||||
|
buttons = [
|
||||||
Button("Generate Passwords", variant="default", id="generate-btn"),
|
Button("Generate Passwords", variant="default", id="generate-btn"),
|
||||||
Button("Save Configuration", variant="success", id="save-btn"),
|
Button("Save Configuration", variant="success", id="save-btn"),
|
||||||
Button("Back", variant="default", id="back-btn"),
|
]
|
||||||
classes="button-row",
|
# Only show Back button if .env file exists
|
||||||
)
|
if self.has_env_file:
|
||||||
|
buttons.append(Button("Back", variant="default", id="back-btn"))
|
||||||
|
yield Horizontal(*buttons, classes="button-row")
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def _create_header_text(self) -> Text:
|
def _create_header_text(self) -> Text:
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,6 @@ class WelcomeScreen(Screen):
|
||||||
|
|
||||||
BINDINGS = [
|
BINDINGS = [
|
||||||
("q", "quit", "Quit"),
|
("q", "quit", "Quit"),
|
||||||
("enter", "default_action", "Continue"),
|
|
||||||
("1", "no_auth_setup", "Basic Setup"),
|
|
||||||
("2", "full_setup", "Advanced Setup"),
|
|
||||||
("3", "monitor", "Status"),
|
|
||||||
("4", "diagnostics", "Diagnostics"),
|
|
||||||
("5", "start_stop_services", "Start/Stop Services"),
|
|
||||||
("6", "open_app", "Open App"),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -42,6 +35,9 @@ class WelcomeScreen(Screen):
|
||||||
self.default_button_id = "basic-setup-btn"
|
self.default_button_id = "basic-setup-btn"
|
||||||
self._state_checked = False
|
self._state_checked = False
|
||||||
|
|
||||||
|
# Check if .env file exists
|
||||||
|
self.has_env_file = self.env_manager.env_file.exists()
|
||||||
|
|
||||||
# Load .env file if it exists
|
# Load .env file if it exists
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
|
@ -161,6 +157,23 @@ class WelcomeScreen(Screen):
|
||||||
|
|
||||||
buttons = []
|
buttons = []
|
||||||
|
|
||||||
|
# If no .env file exists, only show setup buttons
|
||||||
|
if not self.has_env_file:
|
||||||
|
if has_oauth:
|
||||||
|
# If OAuth is configured, only show advanced setup
|
||||||
|
buttons.append(
|
||||||
|
Button("Advanced Setup", variant="success", id="advanced-setup-btn")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# If no OAuth, show both options with basic as primary
|
||||||
|
buttons.append(
|
||||||
|
Button("Basic Setup", variant="success", id="basic-setup-btn")
|
||||||
|
)
|
||||||
|
buttons.append(
|
||||||
|
Button("Advanced Setup", variant="default", id="advanced-setup-btn")
|
||||||
|
)
|
||||||
|
return Horizontal(*buttons, classes="button-row")
|
||||||
|
|
||||||
# Check if all services (native + container) are running
|
# Check if all services (native + container) are running
|
||||||
all_services_running = self.services_running and self.docling_running
|
all_services_running = self.services_running and self.docling_running
|
||||||
|
|
||||||
|
|
@ -189,7 +202,7 @@ class WelcomeScreen(Screen):
|
||||||
)
|
)
|
||||||
|
|
||||||
buttons.append(
|
buttons.append(
|
||||||
Button("Start All Services", variant="primary", id="start-all-services-btn")
|
Button("Start OpenRAG", variant="primary", id="start-all-services-btn")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Always show status option
|
# Always show status option
|
||||||
|
|
@ -253,6 +266,9 @@ class WelcomeScreen(Screen):
|
||||||
|
|
||||||
async def on_screen_resume(self) -> None:
|
async def on_screen_resume(self) -> None:
|
||||||
"""Called when returning from another screen (e.g., config screen)."""
|
"""Called when returning from another screen (e.g., config screen)."""
|
||||||
|
# Check if .env file exists (may have been created)
|
||||||
|
self.has_env_file = self.env_manager.env_file.exists()
|
||||||
|
|
||||||
# Reload environment variables
|
# Reload environment variables
|
||||||
load_dotenv(override=True)
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue