This commit is contained in:
2026-01-18 10:50:42 -08:00
parent 66132811e0
commit 66e6c6eb72
34 changed files with 718 additions and 516 deletions

View File

@@ -4,7 +4,7 @@ import sys
from typing import List, Dict, Any, Optional, Sequence
from cmdlet._shared import Cmdlet, CmdletArg, parse_cmdlet_args
from SYS.logger import log
from SYS.result_table import ResultTable
from SYS.result_table import Table
from SYS import pipeline as ctx
ADJECTIVE_FILE = os.path.join(
@@ -42,7 +42,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
# If no args, list categories
if not args:
table = ResultTable("Adjective Categories")
table = Table("Adjective Categories")
for i, (category, tags) in enumerate(data.items()):
row = table.add_row()
row.add_column("#", str(i + 1))
@@ -125,7 +125,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
# List tags in category (Default action if no flags or after modification)
tags = data.get(category, [])
table = ResultTable(f"Tags in '{category}'")
table = Table(f"Tags in '{category}'")
for i, tag in enumerate(tags):
row = table.add_row()
row.add_column("#", str(i + 1))

View File

@@ -3,7 +3,7 @@ from typing import List, Dict, Any, Optional, Sequence
from cmdlet._shared import Cmdlet, CmdletArg
from SYS.config import load_config, save_config
from SYS import pipeline as ctx
from SYS.result_table import ResultTable
from SYS.result_table import Table
CMDLET = Cmdlet(
name=".config",
@@ -157,7 +157,7 @@ def _show_config_table(config_data: Dict[str, Any]) -> int:
return 0
items.sort(key=lambda x: x.get("key"))
table = ResultTable("Configuration")
table = Table("Configuration")
table.set_table("config")
table.set_source_command(".config", [])

View File

@@ -7,7 +7,7 @@ import sys
from cmdlet._shared import Cmdlet, CmdletArg, parse_cmdlet_args
from cmdlet import REGISTRY as CMDLET_REGISTRY, ensure_cmdlet_modules_loaded
from SYS.logger import log
from SYS.result_table import ResultTable
from SYS.result_table import Table
from SYS import pipeline as ctx
@@ -191,7 +191,7 @@ def _render_list(
filter_text: Optional[str],
args: Sequence[str]
) -> None:
table = ResultTable("Help")
table = Table("Help")
table.set_source_command(".help", list(args))
items: List[Dict[str, Any]] = []
@@ -259,11 +259,11 @@ def _render_detail(meta: Dict[str, Any], _args: Sequence[str]) -> None:
args_meta = meta.get("args", []) or []
args_table = ResultTable(title)
args_table = Table(title)
if header_lines:
args_table.set_header_lines(header_lines)
args_table.set_preserve_order(True)
args_table.set_no_choice(True)
args_table._perseverance(True)
args_table._interactive(True)
if not args_meta:
row = args_table.add_row()
@@ -285,8 +285,8 @@ def _render_detail(meta: Dict[str, Any], _args: Sequence[str]) -> None:
desc = f"{desc} ({choice_text})" if desc else choice_text
row.add_column("Description", desc)
example_table = ResultTable(f"{cmd_name} Examples")
example_table.set_preserve_order(True)
example_table = Table(f"{cmd_name} Examples")
example_table._perseverance(True)
example_table.set_header_line("Select @N to insert the example command into the REPL.")
example_items: List[str] = []
@@ -301,7 +301,7 @@ def _render_detail(meta: Dict[str, Any], _args: Sequence[str]) -> None:
if tokens:
example_table.set_row_selection_args(idx, tokens)
else:
example_table.set_no_choice(True)
example_table._interactive(True)
row = example_table.add_row()
row.add_column("Example", "(no examples available)")

View File

@@ -10,7 +10,7 @@ from urllib.parse import parse_qs, urlparse
from cmdlet._shared import Cmdlet, CmdletArg
from SYS.logger import log, debug
from SYS.result_table import ResultTable
from SYS.result_table import Table
from SYS import pipeline as ctx
_MATRIX_PENDING_ITEMS_KEY = "matrix_pending_items"
@@ -583,7 +583,7 @@ def _resolve_upload_path(item: Any, config: Dict[str, Any]) -> Optional[str]:
def _show_main_menu() -> int:
"""Display main menu: Rooms or Settings."""
table = ResultTable("Matrix (select with @N)")
table = Table("Matrix (select with @N)")
table.set_table("matrix")
table.set_source_command(".matrix", [])
@@ -613,7 +613,7 @@ def _show_main_menu() -> int:
def _show_settings_table(config: Dict[str, Any]) -> int:
"""Display Matrix configuration settings as a modifiable table."""
table = ResultTable("Matrix Settings (select with @N to modify)")
table = Table("Matrix Settings (select with @N to modify)")
table.set_table("matrix")
table.set_source_command(".matrix", ["-settings"])
@@ -800,7 +800,7 @@ def _show_rooms_table(config: Dict[str, Any]) -> int:
log("No joined rooms found.", file=sys.stderr)
return 0
table = ResultTable("Matrix Rooms (select with @N)")
table = Table("Matrix Rooms (select with @N)")
table.set_table("matrix")
table.set_source_command(".matrix", [])

View File

@@ -9,7 +9,7 @@ from urllib.parse import urlparse, parse_qs
from pathlib import Path
from cmdlet._shared import Cmdlet, CmdletArg, parse_cmdlet_args, resolve_tidal_manifest_path
from SYS.logger import debug, get_thread_stream, is_debug_enabled, set_debug, set_thread_stream
from SYS.result_table import ResultTable
from SYS.result_table import Table
from MPV.mpv_ipc import MPV
from SYS import pipeline as ctx
from SYS.models import PipeObject
@@ -1455,7 +1455,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
debug("No saved playlists found.")
return 0
table = ResultTable("Saved Playlists")
table = Table("Saved Playlists")
for i, pl in enumerate(playlists):
item_count = len(pl.get("items", []))
row = table.add_row()
@@ -1813,7 +1813,7 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
except NameError:
table_title = "MPV Playlist"
table = ResultTable(table_title, preserve_order=True)
table = Table(table_title, preserve_order=True)
# Convert MPV items to PipeObjects with proper hash and store
pipe_objects = []

View File

@@ -7,7 +7,7 @@ from datetime import datetime
from cmdlet._shared import Cmdlet, CmdletArg
from SYS import pipeline as ctx
from SYS.result_table import ResultTable
from SYS.result_table import Table
from SYS.logger import log, set_debug, debug
from SYS.rich_display import stdout_console
@@ -23,7 +23,7 @@ def _upper(value: Any) -> str:
return text.upper()
def _add_startup_check(
table: ResultTable,
table: Table,
status: str,
name: str,
*,
@@ -104,13 +104,20 @@ def _ping_first(urls: list[str]) -> tuple[bool, str]:
return False, "No ping target"
def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
startup_table = ResultTable(
startup_table = Table(
"*********<IGNITIO>*********<NOUSEMPEH>*********<RUGRAPOG>*********<OMEGHAU>*********"
)
startup_table.set_no_choice(True).set_preserve_order(True)
startup_table._interactive(True)._perseverance(True)
startup_table.set_value_case("upper")
debug_enabled = bool(config.get("debug", False))
try:
# Ensure global debug state follows config so HTTPClient and other helpers
# emit debug-level information during the status check.
set_debug(debug_enabled)
except Exception:
pass
debug(f"Status check: debug_enabled={debug_enabled}")
_add_startup_check(startup_table, "ENABLED" if debug_enabled else "DISABLED", "DEBUGGING")
try:
@@ -120,16 +127,24 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
MPV()
mpv_path = shutil.which("mpv")
_add_startup_check(startup_table, "ENABLED", "MPV", detail=mpv_path or "Available")
debug(f"MPV check OK: path={mpv_path or 'Available'}")
except Exception as exc:
_add_startup_check(startup_table, "DISABLED", "MPV", detail=str(exc))
debug(f"MPV check failed: {exc}")
# Store Registry
store_registry = None
try:
from Store import Store as StoreRegistry
store_registry = StoreRegistry(config=config, suppress_debug=True)
except Exception:
pass
try:
backends = store_registry.list_backends()
except Exception:
backends = []
debug(f"StoreRegistry initialized. backends={backends}")
except Exception as exc:
debug(f"StoreRegistry initialization failed: {exc}")
store_registry = None
# Hydrus
if _has_store_subtype(config, "hydrusnetwork"):
@@ -138,6 +153,7 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
if not isinstance(icfg, dict): continue
nkey = str(icfg.get("NAME") or iname)
uval = str(icfg.get("URL") or "").strip()
debug(f"Hydrus network check: name={nkey}, url={uval}")
ok = bool(store_registry and store_registry.is_available(nkey))
status = "ENABLED" if ok else "DISABLED"
files = None
@@ -148,9 +164,12 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
files = getattr(backend, "total_count", None)
if files is None and hasattr(backend, "get_total_count"):
files = backend.get_total_count()
except Exception: pass
debug(f"Hydrus backend '{nkey}' available: files={files}")
except Exception as exc:
debug(f"Hydrus backend '{nkey}' check failed: {exc}")
else:
err = store_registry.get_backend_error(iname) if store_registry else None
debug(f"Hydrus backend '{nkey}' not available: {err}")
detail = f"{uval} - {err or 'Unavailable'}"
_add_startup_check(startup_table, status, nkey, store="hydrusnetwork", files=files, detail=detail)
@@ -164,6 +183,7 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
s_avail = list_search_providers(config) or {}
f_avail = list_file_providers(config) or {}
m_avail = list_metadata_providers(config) or {}
debug(f"Provider registries: providers={list(p_avail.keys())}, search={list(s_avail.keys())}, file={list(f_avail.keys())}, metadata={list(m_avail.keys())}")
already = {"matrix"}
for pname in pcfg.keys():
@@ -176,25 +196,31 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
from Provider.alldebrid import _get_debrid_api_key
from API.alldebrid import AllDebridClient
api_key = _get_debrid_api_key(config)
debug(f"AllDebrid configured: api_key_present={bool(api_key)}")
if not api_key:
_add_startup_check(startup_table, "DISABLED", display, provider=prov, detail="Not configured")
else:
client = AllDebridClient(api_key)
_add_startup_check(startup_table, "ENABLED", display, provider=prov, detail=getattr(client, "base_url", "Connected"))
debug(f"AllDebrid client connected: base_url={getattr(client, 'base_url', 'unknown')}")
except Exception as exc:
_add_startup_check(startup_table, "DISABLED", display, provider=prov, detail=str(exc))
debug(f"AllDebrid check failed: {exc}")
already.add(prov)
continue
is_known = prov in p_avail or prov in s_avail or prov in f_avail or prov in m_avail
if not is_known:
_add_startup_check(startup_table, "UNKNOWN", display, provider=prov, detail="Not registered")
debug(f"Provider {prov} not registered")
else:
ok_val = p_avail.get(prov) or s_avail.get(prov) or f_avail.get(prov) or m_avail.get(prov)
detail = "Configured" if ok_val else "Not configured"
ping_targets = _default_provider_ping_targets(prov)
if ping_targets:
debug(f"Provider {prov} ping targets: {ping_targets}")
pok, pdet = _ping_first(ping_targets)
debug(f"Provider {prov} ping result: ok={pok}, detail={pdet}")
detail = pdet if ok_val else f"{detail} | {pdet}"
_add_startup_check(startup_table, "ENABLED" if ok_val else "DISABLED", display, provider=prov, detail=detail)
already.add(prov)
@@ -208,9 +234,16 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
hs = str(mcfg.get("homeserver") or "").strip()
rid = str(mcfg.get("room_id") or "").strip()
detail = f"{hs} room:{rid}"
_add_startup_check(startup_table, "ENABLED" if m_prov.validate() else "DISABLED", "Matrix", provider="matrix", detail=detail)
valid = False
try:
valid = bool(m_prov.validate())
except Exception as exc:
debug(f"Matrix validate failed: {exc}")
_add_startup_check(startup_table, "ENABLED" if valid else "DISABLED", "Matrix", provider="matrix", detail=detail)
debug(f"Matrix check: homeserver={hs}, room_id={rid}, validate={valid}")
except Exception as exc:
_add_startup_check(startup_table, "DISABLED", "Matrix", provider="matrix", detail=str(exc))
debug(f"Matrix instantiation failed: {exc}")
# Folders
if _has_store_subtype(config, "folder"):
@@ -219,6 +252,7 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
if not isinstance(icfg, dict): continue
nkey = str(icfg.get("NAME") or iname)
pval = str(icfg.get("PATH") or icfg.get("path") or "").strip()
debug(f"Folder store check: name={nkey}, path={pval}")
ok = bool(store_registry and store_registry.is_available(nkey))
if ok and store_registry:
backend = store_registry[nkey]
@@ -226,9 +260,11 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
sdet = getattr(backend, "scan_detail", "Up to date")
stats = getattr(backend, "scan_stats", {})
files = int(stats.get("files_total_db", 0)) if stats else None
debug(f"Folder backend '{nkey}': scan_ok={scan_ok}, scan_detail={sdet}, stats={stats}")
_add_startup_check(startup_table, "SCANNED" if scan_ok else "ERROR", nkey, store="folder", files=files, detail=f"{pval} - {sdet}")
else:
err = store_registry.get_backend_error(iname) if store_registry else None
debug(f"Folder backend '{nkey}' error: {err}")
_add_startup_check(startup_table, "ERROR", nkey, store="folder", detail=f"{pval} - {err or 'Unavailable'}")
# Cookies
@@ -236,20 +272,27 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
from tool.ytdlp import YtDlpTool
cf = YtDlpTool(config).resolve_cookiefile()
_add_startup_check(startup_table, "FOUND" if cf else "MISSING", "Cookies", detail=str(cf) if cf else "Not found")
except Exception: pass
debug(f"Cookies: resolved cookiefile={cf}")
except Exception as exc:
debug(f"Cookies check failed: {exc}")
# ZeroTier Hosting
zt_conf = config.get("networking", {}).get("zerotier", {})
if zt_conf.get("serve"):
from SYS.background_services import ensure_zerotier_server_running
ensure_zerotier_server_running()
try:
debug("ZeroTier hosting enabled; ensuring server is running")
ensure_zerotier_server_running()
except Exception as exc:
debug(f"ensure_zerotier_server_running failed: {exc}")
serve_target = zt_conf.get("serve")
port = zt_conf.get("port") or 999
status = "OFFLINE"
detail = f"Sharing: {serve_target} on port {port}"
try:
from API.HTTP import HTTPClient
debug(f"Probing ZeroTier health on 127.0.0.1:{port}")
# Probing 127.0.0.1 is more reliable on Windows than localhost
with HTTPClient(timeout=1.0, retries=0) as client:
resp = client.get(f"http://127.0.0.1:{port}/health")
@@ -257,8 +300,9 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
status = "ONLINE"
payload = resp.json()
detail += f" (Live: {payload.get('name', 'unknown')})"
except Exception:
pass
debug(f"ZeroTier host responded: status={resp.status_code}, payload_keys={list(payload.keys()) if isinstance(payload, dict) else 'unknown'}")
except Exception as exc:
debug(f"ZeroTier probe failed: {exc}")
_add_startup_check(startup_table, status, "ZeroTier Host", detail=detail)
except Exception as exc:
@@ -269,6 +313,7 @@ def _run(result: Any, args: List[str], config: Dict[str, Any]) -> int:
# (avoiding duplication in TUI logs, while keeping it in TUI Results)
setattr(startup_table, "_rendered_by_cmdlet", True)
ctx.set_current_stage_table(startup_table)
debug(f"Status check completed: {len(startup_table.rows)} checks recorded")
return 0

View File

@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional, Sequence
from cmdlet._shared import Cmdlet, CmdletArg
from SYS.logger import log
from SYS.result_table import ResultTable
from SYS.result_table import Table
from SYS import pipeline as ctx
_TELEGRAM_PENDING_ITEMS_KEY = "telegram_pending_items"
@@ -299,7 +299,7 @@ def _run(_result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
)
return 0
table = ResultTable("Telegram Chats")
table = Table("Telegram Chats")
table.set_table("telegram")
table.set_source_command(".telegram", [])

View File

@@ -11,14 +11,14 @@ if str(root) not in sys.path:
from cmdlet._shared import Cmdlet, CmdletArg
from SYS.config import load_config
from SYS.result_table import ResultTable
from SYS.result_table import Table
from API import zerotier as zt
def exec_zerotier(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
# Use provided config or fall back to CWD load
cfg = config if config else load_config(Path.cwd())
table = ResultTable("ZeroTier Status")
table = Table("ZeroTier Status")
# 1. Local Hub Status
row = table.add_row()