Improve TUI startup and keep plugin toggles responsive

Auto-open the plugin table when only one installation exists, run enable and
disable work off the UI thread with immediate status feedback, and skip the
back action for single-instance setups.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pleb
2026-07-01 22:56:52 -07:00
parent c86e51b85a
commit b75d8ccc57
3 changed files with 85 additions and 35 deletions
+66 -29
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
import asyncio
from dataclasses import dataclass
from pathlib import Path
from typing import Any
@@ -64,6 +65,7 @@ class PluginHelperTui(App[int]):
self.selected_installation: InstallationChoice | None = None
self.plugin_rows: list[dict[str, Any]] = []
self.status_message = ""
self._busy = False
def compose(self) -> ComposeResult:
yield Header(show_clock=False)
@@ -75,6 +77,10 @@ class PluginHelperTui(App[int]):
def on_mount(self) -> None:
table = self.query_one(DataTable)
table.cursor_type = "row"
if len(self.choices) == 1:
self.selected_installation = self.choices[0]
self._show_plugins()
return
self._show_installations()
def action_select(self) -> None:
@@ -88,16 +94,20 @@ class PluginHelperTui(App[int]):
def action_back(self) -> None:
if self.mode == "plugins":
if len(self.choices) == 1:
return
self._show_installations()
def action_refresh(self) -> None:
if self._busy:
return
if self.mode == "plugins":
self._show_plugins()
else:
self._show_installations()
def action_toggle_plugin(self) -> None:
if self.mode != "plugins" or self.selected_installation is None:
async def action_toggle_plugin(self) -> None:
if self._busy or self.mode != "plugins" or self.selected_installation is None:
return
index = self._cursor_index(len(self.plugin_rows))
if index is None:
@@ -105,27 +115,32 @@ class PluginHelperTui(App[int]):
plugin = self.plugin_rows[index]
plugin_id = plugin["id"]
target = self.selected_installation
self._busy = True
try:
if plugin["status"] == "enabled":
result = disable_plugin(
self._set_status(f"Disabling {plugin_id}...")
result = await asyncio.to_thread(
disable_plugin,
target.instance_name,
target.instance_path,
target.state_root,
plugin_id,
force=False,
False,
)
if not result["stateUpdated"]:
self._set_status(f"Could not disable {plugin_id}: {self._format_skipped(result['skipped'])}")
return
self._set_status(f"Disabled {plugin_id}; removed {len(result['removed'])} files.")
elif plugin["status"] == "disabled":
result = enable_disabled_plugin(
self._set_status(f"Enabling {plugin_id}...")
result = await asyncio.to_thread(
enable_disabled_plugin,
instance=target.instance_name,
instance_path=target.instance_path,
state_root=target.state_root,
plugin_id=plugin_id,
repo=self.repo_root,
progress=lambda message: self._set_status(f"Bootstrapping: {message}"),
progress=self._bootstrap_progress,
)
self._set_status(f"Enabled {plugin_id}; applied {len(result['applied'])} files.")
else:
@@ -134,10 +149,12 @@ class PluginHelperTui(App[int]):
except Exception as exc:
self._set_status(f"Could not toggle {plugin_id}: {exc}")
return
finally:
self._busy = False
self._show_plugins(preserve_status=True)
def action_disable_all_plugins(self) -> None:
if self.mode != "plugins" or self.selected_installation is None:
async def action_disable_all_plugins(self) -> None:
if self._busy or self.mode != "plugins" or self.selected_installation is None:
return
target = self.selected_installation
enabled = [
@@ -148,32 +165,41 @@ class PluginHelperTui(App[int]):
skipped_bsipa = any(
plugin["status"] == "enabled" and plugin["id"] == BSIPA_PLUGIN_ID for plugin in self.plugin_rows
)
if not enabled:
self._set_status("No enabled plugins to disable.")
return
self._busy = True
self._set_status(f"Disabling {len(enabled)} plugins...")
changed = 0
errors: list[str] = []
for plugin in enabled:
plugin_id = plugin["id"]
try:
result = disable_plugin(
target.instance_name,
target.instance_path,
target.state_root,
plugin_id,
force=False,
)
if result["stateUpdated"]:
changed += 1
else:
errors.append(f"{plugin_id}: {self._format_skipped(result['skipped'])}")
except Exception as exc:
errors.append(f"{plugin_id}: {exc}")
try:
for plugin in enabled:
plugin_id = plugin["id"]
try:
result = await asyncio.to_thread(
disable_plugin,
target.instance_name,
target.instance_path,
target.state_root,
plugin_id,
False,
)
if result["stateUpdated"]:
changed += 1
else:
errors.append(f"{plugin_id}: {self._format_skipped(result['skipped'])}")
except Exception as exc:
errors.append(f"{plugin_id}: {exc}")
finally:
self._busy = False
if skipped_bsipa and not errors:
self._set_status(f"Disabled {changed} plugins (bsipa kept enabled).")
else:
self._set_bulk_status("Disabled", changed, errors)
self._show_plugins(preserve_status=True)
def action_enable_all_plugins(self) -> None:
if self.mode != "plugins" or self.selected_installation is None:
async def action_enable_all_plugins(self) -> None:
if self._busy or self.mode != "plugins" or self.selected_installation is None:
return
target = self.selected_installation
disabled = [plugin for plugin in self.plugin_rows if plugin["status"] == "disabled"]
@@ -181,23 +207,31 @@ class PluginHelperTui(App[int]):
self._set_status("No disabled plugins to enable.")
return
plugin_ids = [plugin["id"] for plugin in disabled]
self._busy = True
self._set_status(f"Enabling {len(plugin_ids)} plugins...")
try:
result = enable_disabled_plugins(
result = await asyncio.to_thread(
enable_disabled_plugins,
instance=target.instance_name,
instance_path=target.instance_path,
state_root=target.state_root,
plugin_ids=plugin_ids,
repo=self.repo_root,
progress=lambda message: self._set_status(f"Bootstrapping: {message}"),
progress=self._bootstrap_progress,
)
except Exception as exc:
self._set_status(f"Could not enable plugins: {exc}")
return
finally:
self._busy = False
changed = len(result["enabled"])
errors = [f"{item['plugin']}: {item['error']}" for item in result["errors"]]
self._set_bulk_status("Enabled", changed, errors)
self._show_plugins(preserve_status=True)
def _bootstrap_progress(self, message: str) -> None:
self.call_from_thread(self._set_status, f"Bootstrapping: {message}")
def _show_installations(self) -> None:
self.mode = "installations"
self.plugin_rows = []
@@ -253,7 +287,10 @@ class PluginHelperTui(App[int]):
)
if not preserve_status:
if self.plugin_rows:
self._set_status("Space toggles selected. d disables all. e enables all. b returns to installations.")
back_hint = "" if len(self.choices) == 1 else " b returns to installations."
self._set_status(
f"Space toggles selected. d disables all. e enables all.{back_hint}"
)
else:
self._set_status("No managed plugins recorded for this installation.")