Spaces:
Paused
Paused
| # ============================================================================ | |
| # CENTRALIZED APPLICATION CONFIGURATION (FULL INTEGRATED) | |
| # ============================================================================ | |
| # Drop-in config used by app_gradio.py and other modules. | |
| # This file is resilient: prefers values from graph_config.py when available, | |
| # but falls back to safe defaults to avoid runtime AttributeError. | |
| # ============================================================================ | |
| import os | |
| import json | |
| import logging | |
| from typing import Dict, Any, List, Optional | |
| # Safe import of gradio (UI helpers) | |
| try: | |
| import gradio as gr | |
| except Exception: | |
| gr = None | |
| # Initialize module logger | |
| log = logging.getLogger("app_config") | |
| if not log.handlers: | |
| # Basic console logging if not configured elsewhere | |
| h = logging.StreamHandler() | |
| fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s") | |
| h.setFormatter(fmt) | |
| log.addHandler(h) | |
| log.setLevel(logging.INFO) | |
| # ============================================================================ | |
| # Attempt to import graph_config for canonical values; if absent, use defaults | |
| # ============================================================================ | |
| try: | |
| import graph_config as graph_cfg # type: ignore | |
| except Exception: | |
| graph_cfg = None | |
| def _from_graph(attr: str, default): | |
| """Helper to return attr from graph_cfg if available, else default.""" | |
| try: | |
| if graph_cfg is not None and hasattr(graph_cfg, attr): | |
| return getattr(graph_cfg, attr) | |
| except Exception: | |
| pass | |
| return default | |
| # ============================================================================ | |
| # FILES & PATHS | |
| # ============================================================================ | |
| OUT_DIR = _from_graph("OUT_DIR", os.environ.get("OUT_DIR", "outputs")) | |
| OUTPUTS_DIR = _from_graph("OUTPUTS_DIR", "outputs") | |
| UPLOADS_DIR = _from_graph("UPLOADS_DIR", "uploads") | |
| USER_ARTIFACTS_DIR = _from_graph("USER_ARTIFACTS_DIR", "outputs/user_artifacts") | |
| EXPORTS_DIR = _from_graph("EXPORTS_DIR", os.path.join(OUT_DIR, "exports")) | |
| FEEDBACK_STORAGE_DIR = _from_graph("FEEDBACK_STORAGE_DIR", os.path.join(OUTPUTS_DIR, "feedback")) | |
| ARTIFACT_REGISTRY_FILE = _from_graph("ARTIFACT_REGISTRY_FILE", os.path.join(OUTPUTS_DIR, "artifact_registry.json")) | |
| # Directory creation flag used by os.makedirs(..., exist_ok=...) | |
| DIR_EXIST_OK = _from_graph("DIR_EXIST_OK", True) | |
| # Ensure core directories exist early | |
| os.makedirs(OUT_DIR, exist_ok=DIR_EXIST_OK) | |
| os.makedirs(OUTPUTS_DIR, exist_ok=DIR_EXIST_OK) | |
| os.makedirs(UPLOADS_DIR, exist_ok=DIR_EXIST_OK) | |
| os.makedirs(USER_ARTIFACTS_DIR, exist_ok=DIR_EXIST_OK) | |
| os.makedirs(os.path.dirname(ARTIFACT_REGISTRY_FILE), exist_ok=DIR_EXIST_OK) | |
| os.makedirs(FEEDBACK_STORAGE_DIR, exist_ok=DIR_EXIST_OK) | |
| # ============================================================================ | |
| # THEME & UI METADATA | |
| # ============================================================================ | |
| GRADIO_THEME = _from_graph("GRADIO_THEME", "soft") | |
| def get_theme(): | |
| """Return a gradio theme object or None if gr is not available.""" | |
| if gr is None: | |
| return None | |
| theme_map = { | |
| "default": gr.themes.Default(), | |
| "soft": gr.themes.Soft(), | |
| "monochrome": gr.themes.Monochrome(), | |
| "glass": gr.themes.Glass() | |
| } | |
| return theme_map.get(GRADIO_THEME, gr.themes.Soft()) | |
| APP_TITLE = _from_graph("APP_TITLE", "Autonomous AI Lab") | |
| APP_TITLE_EMOJI = _from_graph("APP_TITLE_EMOJI", "🤖") | |
| APP_SUBTITLE = _from_graph("APP_SUBTITLE", "*AI-powered research and development assistant*") | |
| CUSTOM_CSS = _from_graph("CUSTOM_CSS", """ | |
| /* Basic layout helpers */ | |
| .status-bar { padding: 8px 12px; background: #f8f9fa; border-radius: 6px; font-size: 0.95em; margin: 8px 0; } | |
| .artifact-list { font-size: 0.9em; max-height: 220px; overflow-y: auto; } | |
| .context-indicator { font-size: 0.9em; color: #444; margin-top: 6px; } | |
| .warning-text { font-size: 0.85em; color: #666; font-style: italic; } | |
| @media (max-width: 768px) { | |
| .gradio-container { padding: 8px !important; } | |
| .chatbot { height: 60vh !important; } | |
| } | |
| """) | |
| # ============================================================================ | |
| # CONTEXT INDICATORS | |
| # ============================================================================ | |
| SHOW_CONTEXT_INDICATOR = _from_graph("SHOW_CONTEXT_INDICATOR", True) | |
| CONTEXT_INDICATOR_NEW = _from_graph("CONTEXT_INDICATOR_NEW", "📊 **New conversation**") | |
| CONTEXT_INDICATOR_FOLLOW_UP = _from_graph("CONTEXT_INDICATOR_FOLLOW_UP", "🔄 Follow-up detected") | |
| CONTEXT_INDICATOR_FORMAT = _from_graph("CONTEXT_INDICATOR_FORMAT", "💬 **Context: {count} exchange(s)**") | |
| # ============================================================================ | |
| # DEFAULT CONFIG & HELPERS (used by app_gradio.get_default_state) | |
| # ============================================================================ | |
| DEFAULT_REWORK_CYCLES = _from_graph("DEFAULT_REWORK_CYCLES", 0) | |
| DEFAULT_APPROVED = _from_graph("DEFAULT_APPROVED", False) | |
| DEFAULT_BUDGET_EXCEEDED = _from_graph("DEFAULT_BUDGET_EXCEEDED", False) | |
| DEFAULT_USER_CONFIRMED_APPROVE_WITH_WARNING = _from_graph("DEFAULT_USER_CONFIRMED_APPROVE_WITH_WARNING", False) | |
| DEFAULT_AWAITING_USER_CONFIRMATION = _from_graph("DEFAULT_AWAITING_USER_CONFIRMATION", False) | |
| DEFAULT_CONFIG = _from_graph("DEFAULT_CONFIG", { | |
| # Execution control & loops | |
| "max_loops": _from_graph("DEFAULT_MAX_LOOPS", 3), | |
| "rework_cycles": DEFAULT_REWORK_CYCLES, | |
| # Budget & cost | |
| "budget": _from_graph("DEFAULT_INITIAL_BUDGET", 0.10), | |
| "current_cost": _from_graph("DEFAULT_INITIAL_COST", 0.0), | |
| "stop_threshold": _from_graph("DEFAULT_STOP_THRESHOLD", 1.2), | |
| "budget_buffer_percentage": _from_graph("BUDGET_BUFFER_PERCENTAGE", 0.20), | |
| # Governance | |
| "flexible_budget_mode": _from_graph("DEFAULT_FLEXIBLE_BUDGET_MODE", True), | |
| "auto_accept_approved_with_warning": _from_graph("DEFAULT_AUTO_ACCEPT_APPROVED_WITH_WARNING", True), | |
| "allow_escalation": _from_graph("DEFAULT_ALLOW_ESCALATION", False), | |
| "preferred_tier": _from_graph("DEFAULT_PREFERRED_TIER", "standard"), | |
| # Booleans | |
| "approved": DEFAULT_APPROVED, | |
| "budget_exceeded": DEFAULT_BUDGET_EXCEEDED, | |
| "user_confirmed_approve_with_warning": DEFAULT_USER_CONFIRMED_APPROVE_WITH_WARNING, | |
| "awaiting_user_confirmation": DEFAULT_AWAITING_USER_CONFIRMATION, | |
| }) | |
| def get_default_config() -> Dict[str, Any]: | |
| """Return a shallow copy of DEFAULT_CONFIG so callers can mutate safely.""" | |
| return DEFAULT_CONFIG.copy() | |
| # ============================================================================ | |
| # GRADIO UI CONSTANTS (used by app_gradio) | |
| # ============================================================================ | |
| # Chat layout | |
| CHAT_COLUMN_SCALE = _from_graph("CHAT_COLUMN_SCALE", 3) | |
| SIDEBAR_COLUMN_SCALE = _from_graph("SIDEBAR_COLUMN_SCALE", 1) | |
| CHATBOT_HEIGHT = _from_graph("CHATBOT_HEIGHT", 520) | |
| CHATBOT_SHOW_LABEL = _from_graph("CHATBOT_SHOW_LABEL", False) | |
| CHAT_COLUMN_PADDING = _from_graph("CHAT_COLUMN_PADDING", 8) | |
| # Placeholder text | |
| ASSISTANT_THINKING_PLACEHOLDER = _from_graph("ASSISTANT_THINKING_PLACEHOLDER", "_Thinking..._") | |
| PLACEHOLDER_MESSAGE_INPUT = _from_graph("PLACEHOLDER_MESSAGE_INPUT", "Type your request and press Send") | |
| # Input box sizing | |
| INPUT_TEXTBOX_SCALE = _from_graph("INPUT_TEXTBOX_SCALE", 4) | |
| INPUT_LINES = _from_graph("INPUT_LINES", 3) | |
| INPUT_SHOW_LABEL = _from_graph("INPUT_SHOW_LABEL", False) | |
| # Buttons, sizes and variants | |
| BUTTON_SEND = _from_graph("BUTTON_SEND", "Send") | |
| BUTTON_PROCEED = _from_graph("BUTTON_PROCEED", "Proceed") | |
| BUTTON_CANCEL = _from_graph("BUTTON_CANCEL", "Cancel") | |
| BUTTON_NEW_CHAT = _from_graph("BUTTON_NEW_CHAT", "New Chat") | |
| BUTTON_RESET = _from_graph("BUTTON_RESET", "Reset System") | |
| BUTTON_REFRESH = _from_graph("BUTTON_REFRESH", "Refresh") | |
| BUTTON_SIZE_SMALL = _from_graph("BUTTON_SIZE_SMALL", "sm") | |
| BUTTON_SIZE_LARGE = _from_graph("BUTTON_SIZE_LARGE", None) | |
| BUTTON_VARIANT_PRIMARY = _from_graph("BUTTON_VARIANT_PRIMARY", "primary") | |
| BUTTON_VARIANT_SECONDARY = _from_graph("BUTTON_VARIANT_SECONDARY", "secondary") | |
| BUTTON_VARIANT_STOP = _from_graph("BUTTON_VARIANT_STOP", "stop") | |
| PROCEED_BUTTON_SCALE = _from_graph("PROCEED_BUTTON_SCALE", 1) | |
| CANCEL_BUTTON_SCALE = _from_graph("CANCEL_BUTTON_SCALE", 1) | |
| SUBMIT_BUTTON_SCALE = _from_graph("SUBMIT_BUTTON_SCALE", 1) | |
| PROCEED_BUTTON_SCALE = _from_graph("PROCEED_BUTTON_SCALE", 1) | |
| BUTTON_VARIANT_PRIMARY = _from_graph("BUTTON_VARIANT_PRIMARY", "primary") | |
| # Approval box behavior | |
| APPROVAL_BOX_DEFAULT_VISIBLE = _from_graph("APPROVAL_BOX_DEFAULT_VISIBLE", False) | |
| # Budget UI | |
| LABEL_MAX_BUDGET = _from_graph("LABEL_MAX_BUDGET", "Max Budget (USD)") | |
| BUDGET_DEFAULT_VALUE = _from_graph("BUDGET_DEFAULT_VALUE", 0.10) | |
| BUDGET_MINIMUM = _from_graph("BUDGET_MINIMUM", 0.0) | |
| BUDGET_STEP = _from_graph("BUDGET_STEP", 0.01) | |
| BUDGET_INPUT_SCALE = _from_graph("BUDGET_INPUT_SCALE", 1) | |
| LABEL_FLEXIBLE_BUDGET = _from_graph("LABEL_FLEXIBLE_BUDGET", "Flexible Budget") | |
| LABEL_PREFERRED_TIER = _from_graph("LABEL_PREFERRED_TIER", "Preferred Tier") | |
| TIER_CHOICES = _from_graph("TIER_CHOICES", ["lite", "standard", "full"]) | |
| TIER_DEFAULT = _from_graph("TIER_DEFAULT", "standard") | |
| # Feedback UI | |
| SECTION_FEEDBACK = _from_graph("SECTION_FEEDBACK", "Feedback & Rating") | |
| FEEDBACK_PURPOSE_TEXT = _from_graph("FEEDBACK_PURPOSE_TEXT", "Help us improve by rating this run.") | |
| FEEDBACK_CATEGORIES = _from_graph("FEEDBACK_CATEGORIES", {"quality": "Quality", "usability": "Usability", "other": "Other"}) | |
| LABEL_RATING = _from_graph("LABEL_RATING", "Rating") | |
| RATING_MIN = _from_graph("RATING_MIN", 1) | |
| RATING_MAX = _from_graph("RATING_MAX", 5) | |
| RATING_DEFAULT_VALUE = _from_graph("RATING_DEFAULT_VALUE", 5) | |
| LABEL_FEEDBACK_COMMENTS = _from_graph("LABEL_FEEDBACK_COMMENTS", "Comments") | |
| FEEDBACK_COMMENT_LINES = _from_graph("FEEDBACK_COMMENT_LINES", 3) | |
| FEEDBACK_PLACEHOLDER = _from_graph("FEEDBACK_PLACEHOLDER", "Optional: leave a comment about your experience") | |
| BUTTON_SUBMIT_FEEDBACK = _from_graph("BUTTON_SUBMIT_FEEDBACK", "Submit Feedback") | |
| FEEDBACK_THANK_YOU_MESSAGES = _from_graph("FEEDBACK_THANK_YOU_MESSAGES", [ | |
| "Thanks — your feedback helps us improve!", | |
| "Appreciate your feedback — thank you!", | |
| "Thanks! We logged your feedback." | |
| ]) | |
| # Files UI | |
| SECTION_FILES_ARTIFACTS = _from_graph("SECTION_FILES_ARTIFACTS", "Files & Artifacts") | |
| LABEL_UPLOAD_FILES = _from_graph("LABEL_UPLOAD_FILES", "Upload files") | |
| ALLOWED_FILE_TYPES = _from_graph("ALLOWED_FILE_TYPES", None) # None means allow any | |
| UPLOAD_STATUS_SHOW_LABEL = _from_graph("UPLOAD_STATUS_SHOW_LABEL", False) | |
| PLACEHOLDER_NO_FILES = _from_graph("PLACEHOLDER_NO_FILES", "No files uploaded") | |
| # Debug / JSON display | |
| SECTION_DEBUG = _from_graph("SECTION_DEBUG", "Debug") | |
| ACCORDION_DEBUG_OPEN = _from_graph("ACCORDION_DEBUG_OPEN", False) | |
| LABEL_AGENT_STATE = _from_graph("LABEL_AGENT_STATE", "Agent State (debug)") | |
| DEBUG_JSON_VISIBLE = _from_graph("DEBUG_JSON_VISIBLE", False) | |
| # ============================================================================ | |
| # UI text / status messages (fallbacks) | |
| # ============================================================================ | |
| RESET_SUCCESS_MESSAGE = _from_graph("RESET_SUCCESS_MESSAGE", "✅ System reset complete.") | |
| RESET_LOG_MESSAGE = _from_graph("RESET_LOG_MESSAGE", RESET_SUCCESS_MESSAGE) | |
| RESET_ERROR_MESSAGE_PREFIX = _from_graph("RESET_ERROR_MESSAGE_PREFIX", "⚠️ Reset error: ") | |
| NO_FILE_UPLOADED_MESSAGE = _from_graph("NO_FILE_UPLOADED_MESSAGE", "No file uploaded.") | |
| FILE_UPLOAD_SUCCESS_PREFIX = _from_graph("FILE_UPLOAD_SUCCESS_PREFIX", "📎 Uploaded ") | |
| FILE_UPLOAD_SUCCESS_SUFFIX = _from_graph("FILE_UPLOAD_SUCCESS_SUFFIX", " file(s): ") | |
| UPLOAD_LOG_MESSAGE_PREFIX = _from_graph("UPLOAD_LOG_MESSAGE_PREFIX", "Uploaded: ") | |
| NO_ARTIFACTS_MESSAGE = _from_graph("NO_ARTIFACTS_MESSAGE", "No artifacts yet.") | |
| NO_ARTIFACTS_GENERATED_MESSAGE = _from_graph("NO_ARTIFACTS_GENERATED_MESSAGE", "No artifacts generated yet.") | |
| CLEAR_CONVERSATION_MESSAGE = _from_graph("CLEAR_CONVERSATION_MESSAGE", "🗑️ Conversation cleared.") | |
| ASSISTANT_THINKING_PLACEHOLDER = _from_graph("ASSISTANT_THINKING_PLACEHOLDER", ASSISTANT_THINKING_PLACEHOLDER) | |
| # Execution status messages | |
| STATUS_ANALYZING = _from_graph("STATUS_ANALYZING", "🔄 Analyzing request...") | |
| STATUS_READY = _from_graph("STATUS_READY", "💬 Ready") | |
| STATUS_AWAITING_APPROVAL = _from_graph("STATUS_AWAITING_APPROVAL", "⏸️ Awaiting approval") | |
| STATUS_TASK_APPROVED = _from_graph("STATUS_TASK_APPROVED", "✅ Task approved. Starting...") | |
| STATUS_RUNNING_PREFIX = _from_graph("STATUS_RUNNING_PREFIX", "🔄 ") | |
| STATUS_RUNNING_SUFFIX = _from_graph("STATUS_RUNNING_SUFFIX", " | Cost: ${cost:.2f} / ${threshold:.2f} (120%)") | |
| STATUS_TASK_COMPLETE = _from_graph("STATUS_TASK_COMPLETE", "✅ Task complete | Cost: ${cost:.2f} (${budget} + {buffer}% buffer)") | |
| STATUS_BUDGET_EXCEEDED = _from_graph("STATUS_BUDGET_EXCEEDED", "⚠️ Budget limit reached | Used: ${cost:.2f} / ${threshold:.2f}") | |
| STATUS_PARTIAL_COMPLETION = _from_graph("STATUS_PARTIAL_COMPLETION", "⚠️ Partial completion | Cost: ${cost:.2f}") | |
| STATUS_CANCELLED = _from_graph("STATUS_CANCELLED", "⏸️ Cancelled. Ready.") | |
| STATUS_NO_RUNTIME = _from_graph("STATUS_NO_RUNTIME", "❌ No runtime") | |
| STATUS_ERROR_PREFIX = _from_graph("STATUS_ERROR_PREFIX", "❌ Error: ") | |
| ERROR_EXECUTION_PREFIX = _from_graph("ERROR_EXECUTION_PREFIX", "❌ Execution failed: ") | |
| # ---------------------------------------------------------------------------- | |
| # AVATAR CONFIGURATION — minimal, robust, and guaranteed to return >= 2 items | |
| # ---------------------------------------------------------------------------- | |
| import os | |
| from typing import List | |
| # Prefer a local avatar placed at ./assets/avatar.png (relative to project root) | |
| LOCAL_AVATAR_PATH = os.path.join(os.path.dirname(__file__), "assets", "avatar.png") | |
| # Secondary local candidate(s) | |
| LOCAL_AVATAR_CANDIDATES = [ | |
| LOCAL_AVATAR_PATH, | |
| os.path.join(os.path.dirname(__file__), "static", "avatar.png"), | |
| os.path.join(os.path.dirname(__file__), "assets", "bot.png"), | |
| ] | |
| # Stable remote fallbacks (used only if no local file is present) | |
| REMOTE_FALLBACKS = [ | |
| "https://i.imgur.com/b5OqI32.png", | |
| "https://i.imgur.com/8Km9tLL.png" | |
| ] | |
| def get_avatar_images() -> List[str]: | |
| """ | |
| Return a list of avatar image paths/URLs with length >= 2. | |
| Priority: | |
| 1) Use two local images if available | |
| 2) If only one local image found, duplicate it (safe) | |
| 3) Else return two stable remote fallback URLs | |
| """ | |
| imgs: List[str] = [] | |
| # 1) collect existing local candidates | |
| for candidate in LOCAL_AVATAR_CANDIDATES: | |
| try: | |
| if candidate and os.path.exists(candidate): | |
| imgs.append(candidate) | |
| except Exception: | |
| # ignore filesystem oddities; continue to next candidate | |
| continue | |
| if len(imgs) >= 2: | |
| break | |
| # 2) if only one local image found, duplicate it so Gradio has two entries | |
| if len(imgs) == 1: | |
| imgs.append(imgs[0]) | |
| # 3) if none found, use remote fallbacks | |
| if not imgs: | |
| imgs = REMOTE_FALLBACKS.copy() | |
| # 4) final safety: ensure length >= 2 (pad with last element) | |
| while len(imgs) < 2: | |
| imgs.append(imgs[-1]) | |
| return imgs | |
| # ============================================================================ | |
| # Server config helpers (used at app launch) | |
| # ============================================================================ | |
| DEFAULT_SERVER_CONFIG = _from_graph("DEFAULT_SERVER_CONFIG", { | |
| "server_name": "0.0.0.0", | |
| "server_port": int(os.environ.get("PORT", os.environ.get("SERVER_PORT", 7860))), | |
| "share": False, # gradio share link | |
| "debug": False | |
| }) | |
| def get_server_config() -> Dict[str, Any]: | |
| """Return server config for demo.launch(**cfg).""" | |
| cfg = DEFAULT_SERVER_CONFIG.copy() | |
| # Allow environment overrides | |
| try: | |
| if os.environ.get("GRADIO_SHARE", "").lower() in ("1", "true", "yes"): | |
| cfg["share"] = True | |
| except Exception: | |
| pass | |
| return cfg | |
| def log_launch_banner(port: int): | |
| """Small friendly banner used at startup logs.""" | |
| try: | |
| log.info("=" * 60) | |
| log.info(f"Launching Gradio app on port {port} — {APP_TITLE} {APP_TITLE_EMOJI}") | |
| log.info("=" * 60) | |
| except Exception: | |
| pass | |
| # ============================================================================ | |
| # Small validation helper used by app_gradio feedback flow | |
| # ============================================================================ | |
| def validate_rating(rating: int): | |
| if not isinstance(rating, int): | |
| raise ValueError("Rating must be integer") | |
| if rating < RATING_MIN or rating > RATING_MAX: | |
| raise ValueError(f"Rating must be between {RATING_MIN} and {RATING_MAX}") | |
| return True | |
| # ---------------------------------------------------------------------------- | |
| # INITIAL STATUS MESSAGE (used by app_gradio) | |
| # ---------------------------------------------------------------------------- | |
| INITIAL_STATUS = "💬 Ready to help" | |
| # ---------------------------------------------------------------------------- | |
| # DEFAULT CHECKBOX STATES & GOVERNANCE FLAGS (used in app_gradio sidebar) | |
| # ---------------------------------------------------------------------------- | |
| # Liberal defaults (auto-approve & flexible budgets enabled by default) | |
| DEFAULT_FLEXIBLE_CHECKBOX = True | |
| DEFAULT_AUTO_ACCEPT_CHECKBOX = True | |
| # Escalation is optional, off by default | |
| DEFAULT_ALLOW_ESCALATION = False | |
| # ---------------------------------------------------------------------------- | |
| # ADD MISSING UI LABELS (small, safe defaults) | |
| # ---------------------------------------------------------------------------- | |
| # Label for the "auto accept" checkbox in the UI sidebar | |
| LABEL_AUTO_ACCEPT = "Auto-accept 'approve with warning' decisions" | |
| # (Ensure there's also a corresponding checkbox default; safe default = True) | |
| DEFAULT_AUTO_ACCEPT_CHECKBOX = globals().get("DEFAULT_AUTO_ACCEPT_CHECKBOX", True) | |
| # ---------------------------------------------------------------------------- | |
| # FILES / ARTIFACTS UI LABELS | |
| # ---------------------------------------------------------------------------- | |
| # Label shown on the "download artifacts" Files component | |
| LABEL_DOWNLOAD_ARTIFACTS = "Download artifacts" | |
| # Helpful siblings used elsewhere in the UI (safe defaults) | |
| LABEL_UPLOAD_FILES = globals().get("LABEL_UPLOAD_FILES", "Upload files") | |
| LABEL_DOWNLOAD_ZIP = globals().get("LABEL_DOWNLOAD_ZIP", "Download all as .zip") | |
| PLACEHOLDER_NO_FILES = globals().get("PLACEHOLDER_NO_FILES", "No files available") | |
| # ---------------------------------------------------------------------------- | |
| # PLAN DISPLAY / ESTIMATION TEXT CONSTANTS (used by start_estimation) | |
| # ---------------------------------------------------------------------------- | |
| # Section headers | |
| PLAN_HEADER = "**📋 Execution Plan:**\n" | |
| PLAN_ESTIMATE_HEADER = "\n\n**📊 Estimate:**\n" | |
| # Step prefix used in list output | |
| PLAN_STEP_PREFIX = "- " | |
| # Formatting patterns for estimation details | |
| PLAN_ATTEMPTS_FORMAT = "- Attempts: up to **{}**\n" | |
| PLAN_COST_FORMAT = "- Estimated cost: **${}**\n" | |
| PLAN_BUFFER_FORMAT = "- With 20% buffer: **${:.2f}**" | |
| # Default initial max loops used by estimation when no override provided | |
| DEFAULT_MAX_LOOPS_INITIAL = globals().get("DEFAULT_MAX_LOOPS_INITIAL", 0) | |
| # Budget multipliers (used when showing cost with buffer) | |
| BUDGET_BUFFER_MULTIPLIER = globals().get("BUDGET_BUFFER_MULTIPLIER", 1.20) | |
| # ---------------------------------------------------------------------------- | |
| # Additional safe defaults to prevent missing-attribute errors (add these) | |
| # ---------------------------------------------------------------------------- | |
| # Feedback / logging helpers | |
| LOG_FEEDBACK_SUBMISSION_FAILED = "Failed saving feedback" | |
| FEEDBACK_THANK_YOU_MESSAGES = globals().get("FEEDBACK_THANK_YOU_MESSAGES", [ | |
| "Thanks — your feedback helps us improve!", | |
| "Appreciate your feedback — thank you!", | |
| "Thanks! We logged your feedback." | |
| ]) | |
| # Feedback defaults / counts | |
| DEFAULT_COMMENT = "No comment provided" | |
| DEFAULT_RUN_COST = 0.0 | |
| DEFAULT_AVG_REWARD = 0.0 | |
| DEFAULT_FEEDBACK_COUNT = 0 | |
| # Optional feedback agent hooks (module.function style) - leave None if unused | |
| FEEDBACK_AGENT_MODULE = None | |
| FEEDBACK_AGENT_FUNCTION = None | |
| # Download / artifacts label (if not already present) | |
| LABEL_DOWNLOAD_ARTIFACTS = globals().get("LABEL_DOWNLOAD_ARTIFACTS", "Download artifacts") | |
| # Default budget value shown in the UI (USD) | |
| DEFAULT_BUDGET_DISPLAY = globals().get("DEFAULT_BUDGET_DISPLAY", 0.10) | |
| # ============================================================================ | |
| # Export list for other modules | |
| # ============================================================================ | |
| __all__ = [ | |
| # Paths | |
| "OUT_DIR", "OUTPUTS_DIR", "UPLOADS_DIR", "USER_ARTIFACTS_DIR", "EXPORTS_DIR", | |
| "ARTIFACT_REGISTRY_FILE", "FEEDBACK_STORAGE_DIR", "DIR_EXIST_OK", | |
| # Theme & UI | |
| "get_theme", "APP_TITLE", "APP_TITLE_EMOJI", "APP_SUBTITLE", "CUSTOM_CSS", | |
| "GRADIO_THEME", | |
| # Context | |
| "SHOW_CONTEXT_INDICATOR", "CONTEXT_INDICATOR_NEW", "CONTEXT_INDICATOR_FOLLOW_UP", | |
| "CONTEXT_INDICATOR_FORMAT", | |
| # Default config | |
| "DEFAULT_CONFIG", "get_default_config", | |
| # UI constants | |
| "CHAT_COLUMN_SCALE", "SIDEBAR_COLUMN_SCALE", "CHATBOT_HEIGHT", "CHATBOT_SHOW_LABEL", | |
| "PLACEHOLDER_MESSAGE_INPUT", "INPUT_TEXTBOX_SCALE", "INPUT_LINES", "INPUT_SHOW_LABEL", | |
| "BUTTON_SEND", "BUTTON_PROCEED", "BUTTON_CANCEL", "BUTTON_NEW_CHAT", "BUTTON_RESET", | |
| "BUTTON_REFRESH", "BUTTON_SUBMIT_FEEDBACK", "BUTTON_VARIANT_PRIMARY", | |
| "BUTTON_VARIANT_SECONDARY", "BUTTON_VARIANT_STOP", "BUTTON_SIZE_SMALL", | |
| "BUTTON_SIZE_LARGE", "PROCEED_BUTTON_SCALE", "CANCEL_BUTTON_SCALE", "SUBMIT_BUTTON_SCALE", | |
| "APPROVAL_BOX_DEFAULT_VISIBLE", | |
| # Budget & tiers | |
| "LABEL_MAX_BUDGET", "BUDGET_DEFAULT_VALUE", "BUDGET_MINIMUM", "BUDGET_STEP", "BUDGET_INPUT_SCALE", | |
| "LABEL_FLEXIBLE_BUDGET", "LABEL_PREFERRED_TIER", "TIER_CHOICES", "TIER_DEFAULT", | |
| # Feedback & files | |
| "SECTION_FEEDBACK", "FEEDBACK_PURPOSE_TEXT", "FEEDBACK_CATEGORIES", "LABEL_RATING", | |
| "RATING_MIN", "RATING_MAX", "RATING_DEFAULT_VALUE", "LABEL_FEEDBACK_COMMENTS", "FEEDBACK_PLACEHOLDER", | |
| "SECTION_FILES_ARTIFACTS", "LABEL_UPLOAD_FILES", "ALLOWED_FILE_TYPES", "UPLOAD_STATUS_SHOW_LABEL", | |
| "PLACEHOLDER_NO_FILES", "SECTION_DEBUG", "ACCORDION_DEBUG_OPEN", "LABEL_AGENT_STATE", "DEBUG_JSON_VISIBLE", | |
| "FEEDBACK_THANK_YOU_MESSAGES", | |
| # Messages & status | |
| "RESET_SUCCESS_MESSAGE", "RESET_LOG_MESSAGE", "RESET_ERROR_MESSAGE_PREFIX", "NO_FILE_UPLOADED_MESSAGE", | |
| "FILE_UPLOAD_SUCCESS_PREFIX", "FILE_UPLOAD_SUCCESS_SUFFIX", "NO_ARTIFACTS_MESSAGE", "NO_ARTIFACTS_GENERATED_MESSAGE", | |
| "CLEAR_CONVERSATION_MESSAGE", "ASSISTANT_THINKING_PLACEHOLDER", | |
| "STATUS_ANALYZING", "STATUS_READY", "STATUS_AWAITING_APPROVAL", "STATUS_TASK_APPROVED", | |
| "STATUS_TASK_COMPLETE", "STATUS_PARTIAL_COMPLETION", "STATUS_CANCELLED", "STATUS_ERROR_PREFIX", | |
| "ERROR_EXECUTION_PREFIX", | |
| # Helpers | |
| "get_avatar_images", "get_server_config", "log_launch_banner", "validate_rating", "INITIAL_STATUS", | |
| "DEFAULT_FLEXIBLE_CHECKBOX", | |
| "DEFAULT_AUTO_ACCEPT_CHECKBOX", | |
| "DEFAULT_ALLOW_ESCALATION", | |
| "LABEL_AUTO_ACCEPT", | |
| "DEFAULT_AUTO_ACCEPT_CHECKBOX", | |
| # UI / theme / metadata & helpers | |
| 'APP_TITLE', | |
| 'APP_TITLE_EMOJI', | |
| 'APP_SUBTITLE', | |
| 'CUSTOM_CSS', | |
| 'GRADIO_THEME', | |
| 'get_theme', | |
| # Context indicators & initial status | |
| 'SHOW_CONTEXT_INDICATOR', | |
| 'CONTEXT_INDICATOR_NEW', | |
| 'CONTEXT_INDICATOR_FOLLOW_UP', | |
| 'CONTEXT_INDICATOR_FORMAT', | |
| 'INITIAL_STATUS', | |
| # Paths & artifact flags | |
| 'USER_ARTIFACTS_DIR', | |
| 'DIR_EXIST_OK', | |
| # Avatar helpers | |
| 'get_avatar_images', | |
| 'AVATAR_USER', | |
| 'AVATAR_BOT', | |
| # Default config & helpers | |
| 'DEFAULT_CONFIG', | |
| 'get_default_config', | |
| # Checkbox defaults / governance & labels | |
| 'DEFAULT_FLEXIBLE_CHECKBOX', | |
| 'DEFAULT_AUTO_ACCEPT_CHECKBOX', | |
| 'DEFAULT_ALLOW_ESCALATION', | |
| 'LABEL_AUTO_ACCEPT', | |
| # Button & UI labels commonly used | |
| 'BUTTON_SEND', | |
| 'BUTTON_PROCEED', | |
| 'BUTTON_CANCEL', | |
| 'BUTTON_NEW_CHAT', | |
| 'BUTTON_RESET', | |
| 'BUTTON_REFRESH', | |
| 'BUTTON_SUBMIT_FEEDBACK', | |
| # Placeholders / small text | |
| 'ASSISTANT_THINKING_PLACEHOLDER', | |
| 'PLACEHOLDER_MESSAGE_INPUT', | |
| 'PLACEHOLDER_NO_FILES', | |
| # Server / logging helpers | |
| 'get_server_config', | |
| 'log_launch_banner', | |
| # Validation | |
| 'validate_rating', | |
| #artifacts | |
| 'LABEL_DOWNLOAD_ARTIFACTS', | |
| 'LABEL_UPLOAD_FILES', | |
| 'LABEL_DOWNLOAD_ZIP', | |
| 'PLACEHOLDER_NO_FILES', | |
| #plan | |
| 'PLAN_HEADER', | |
| 'PLAN_ESTIMATE_HEADER', | |
| 'PLAN_STEP_PREFIX', | |
| 'PLAN_ATTEMPTS_FORMAT', | |
| 'PLAN_COST_FORMAT', | |
| 'PLAN_BUFFER_FORMAT', | |
| 'DEFAULT_MAX_LOOPS_INITIAL', | |
| 'BUDGET_BUFFER_MULTIPLIER', | |
| 'LOG_FEEDBACK_SUBMISSION_FAILED', | |
| 'DEFAULT_COMMENT', | |
| 'DEFAULT_RUN_COST', | |
| 'DEFAULT_AVG_REWARD', | |
| 'DEFAULT_FEEDBACK_COUNT', | |
| 'FEEDBACK_AGENT_MODULE', | |
| 'FEEDBACK_AGENT_FUNCTION', | |
| 'LABEL_DOWNLOAD_ARTIFACTS', | |
| 'DEFAULT_BUDGET_DISPLAY' | |
| ] | |