Skip to content

Conversation

@Camier
Copy link
Member

@Camier Camier commented Nov 14, 2025

Summary

  • add a dedicated ptui_dashboard_core package that splits the curses dashboard into focused modules for models, config, network helpers, monitoring, actions, utilities, and UI rendering
  • rewrite scripts/ptui_dashboard.py into a thin compatibility shim that keeps the historical API surface (for tests and CLI tooling) while delegating to the new package and refreshing validation logic
  • update the PTUI dashboard documentation to describe the modular architecture, adjusted comparison table, and new extension points

Testing

  • pytest tests/unit/test_ptui_dashboard.py -v

Codex Task

Copilot AI review requested due to automatic review settings November 14, 2025 06:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the monolithic ptui_dashboard.py script into a modular package structure while maintaining backward compatibility through a thin compatibility shim. The refactoring improves code organization, testability, and maintainability by splitting concerns into focused modules.

Key Changes:

  • Created ptui_dashboard_core package with 8 specialized modules (models, config, network, monitor, actions, ui, utils, init)
  • Rewrote scripts/ptui_dashboard.py as a 200-line compatibility shim that re-exports the core package's API
  • Updated documentation to reflect the new modular architecture and adjusted the comparison table

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/ptui_dashboard_core/__init__.py Public API surface with comprehensive re-exports from all submodules
scripts/ptui_dashboard_core/models.py Dataclass definitions for Service, ActionItem, and MenuItem
scripts/ptui_dashboard_core/config.py Environment variable validation and YAML-based service configuration loader
scripts/ptui_dashboard_core/network.py Synchronous and asynchronous HTTP JSON fetching with optional aiohttp support
scripts/ptui_dashboard_core/monitor.py Service health checking and state gathering logic with async/sync modes
scripts/ptui_dashboard_core/actions.py Quick action handlers including refresh, health probe, and validation runner
scripts/ptui_dashboard_core/ui.py Complete curses UI implementation with rendering, event handling, and terminal setup
scripts/ptui_dashboard_core/utils.py Shared utility functions like latency formatting
scripts/ptui_dashboard.py Compatibility shim providing historical API surface while delegating to core package
docs/ptui-dashboard.md Updated documentation describing modular architecture and extension points

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

message = f"Health probe: failing services - {', '.join(failing)}."
else:
message = "Health probe completed."
message = f"Health probe: failing services - {', '.join(failing)}."
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for handling failures is missing the else clause that existed in the old code. When there are failing services, this code now always returns the failing services message, but the old code would return "Health probe completed." if the failing list is empty. This appears to be a logic change that could affect behavior.

Suggested change
message = f"Health probe: failing services - {', '.join(failing)}."
if not failing:
message = "Health probe completed."
else:
message = f"Health probe: failing services - {', '.join(failing)}."

Copilot uses AI. Check for mistakes.
Comment on lines 109 to 113
def gather_state_smart(timeout: float) -> dict[str, Any]:
"""Gather state using async if available, otherwise fallback to sync.
This is the main entry point that other code should use.
"""
if ASYNC_AVAILABLE:
# Use async version for better performance
return asyncio.run(gather_state_async(timeout))

# Fallback to synchronous version
_sync_services()
return _monitor.gather_state_smart(timeout)
return gather_state(timeout)
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When ASYNC_AVAILABLE is True, this function calls _monitor.gather_state_smart(timeout) which will internally check ASYNC_AVAILABLE again and call asyncio.run(gather_state_async(timeout)). However, gather_state_async is defined locally in this file (lines 104-106) and it calls _monitor.gather_state_async(timeout), but the local SERVICES list may have been modified and needs to be synchronized via _sync_services() first. The _sync_services() call on line 111 is placed, but when calling _monitor.gather_state_smart() on line 112, the flow will go through the core module's version which doesn't use the locally modified SERVICES. Consider simplifying this logic.

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +208
def main() -> int:
"""Launch the curses dashboard."""

return run_dashboard()
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The main() function signature changed from returning None (with implicit sys.exit() calls) to returning int. While this is a cleaner approach, tests or external code that expect main() to return None may break. The change appears intentional for the refactor, but ensure existing tests and callers are updated accordingly.

Copilot uses AI. Check for mistakes.
"run_validation",
"safe_addstr",
"subprocess",
"urlopen",
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The urlopen function is exported in __all__ but it's only imported, not defined or re-exported explicitly. While Python allows this, it's unusual to export imported standard library functions unless they're part of the module's public API. Consider whether this is intentionally part of the backward compatibility surface or if it should be removed.

Suggested change
"urlopen",

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +86
else:
display_name = provider_data.get("description", key)
endpoint = provider_data.get("health_endpoint", "/health")
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The health endpoint default changed from "/health" (in the old code) to provider_data.get("health_endpoint", "/health") which is correct. However, this is a subtle change in behavior - the old code didn't specify a default from the provider_data, it just used "/health". The new code is more flexible and correct, but ensure this doesn't break existing configurations that relied on the old behavior.

Copilot uses AI. Check for mistakes.
@Camier
Copy link
Member Author

Camier commented Nov 16, 2025

Heads-up: dashboard direction is now the Hello Kitty Textual app (see scripts/ai-dashboard and dashboards/hello_kitty). Please align this PTUI refactor with that plan or discuss whether PTUI remains as secondary/read-only. Suggest pausing merge until we confirm scope against the Hello Kitty dashboard.

@Camier Camier added the blocked Needs attention before merge label Nov 16, 2025
@Camier
Copy link
Member Author

Camier commented Nov 16, 2025

Alignment checklist for Hello Kitty–only dashboard direction:\n- Launcher must remain → ; please remove/deprecate any WTH/Bubble Tea paths.\n- If PTUI stays, mark it secondary/SSH-only and add a quick smoke () plus note its scope.\n- Validation: run ================================================================================
LiteLLM Configuration Generator

🔍 Checking for manual edits...
✓ No manual edits detected

💾 Creating backup...
✓ Backed up to: config/backups/litellm-unified.yaml.20251116-133233
Cleaning up old backups (keeping 10)...
Removed: litellm-unified.yaml.20251105-214339

🏗️ Building complete configuration...

🔀 Building router settings...
✓ Created 6 capability groups
✓ Created 18 fallback chains

⏱️ Building rate limit settings...
✓ Configured rate limits for 12 models
✓ Configuration built successfully

✍️ Writing configuration to config/litellm-unified.yaml...
✓ Configuration written successfully

📌 Version saved: git-6da51ef

✅ Validating generated configuration...
✓ Validation passed

================================================================================
✅ Configuration generated successfully!

Output: config/litellm-unified.yaml
Version: git-6da51ef
Backup: config/backups/

Next steps:

  1. Review generated configuration
  2. Test: curl http://localhost:4000/v1/models
  3. Ensure service is provisioned: ./runtime/scripts/run_litellm.sh
  4. Restart: systemctl --user restart litellm.service then ==================================
    AI Unified Backend Validation
    ==================================

=== Phase 1: System Checks ===

�[1;33mℹ�[0m Checking systemd services...
�[0;32m✅�[0m LiteLLM service is running
�[0;31m❌�[0m Ollama service exists but is NOT running

=== Phase 2: Provider Health Checks ===

�[1;33mℹ�[0m Testing provider endpoints...
�[0;31m❌�[0m Ollama is NOT accessible; attach output.\n- Docs: adjust commands in README/docs to the Hello Kitty launcher and avoid conflicting guidance.\nHappy to re-review after these updates.

@Camier
Copy link
Member Author

Camier commented Nov 16, 2025

Alignment checklist for the Hello Kitty-only dashboard direction:

  • Keep launcher at scripts/ai-dashboard → dashboards/hello_kitty/src; remove/deprecate WTH paths.
  • If PTUI remains, mark it secondary/SSH-only and add a smoke run: python scripts/ptui_dashboard.py --help (document scope).
  • Validation: python scripts/generate-litellm-config.py && bash scripts/validate-unified-backend.sh; attach output.
  • Docs: adjust commands in README/docs to the Hello Kitty launcher; avoid conflicting guidance.
    Re-review after these updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Needs attention before merge codex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants