This commit is contained in:
2026-01-11 03:24:49 -08:00
parent e608b88062
commit 5985a8306a
13 changed files with 401 additions and 101 deletions

View File

@@ -209,15 +209,41 @@ class ConfigModal(ModalScreen):
item_type = str(self.editing_item_type or "")
item_name = str(self.editing_item_name or "")
provider_schema_map = {}
# Parse item_type for store-{stype} or just provider
if item_type.startswith("store-"):
stype = item_type.replace("store-", "")
container.mount(Label(f"Editing Store: {item_name} ({stype})", classes="config-label"))
section = self.config_data.get("store", {}).get(stype, {}).get(item_name, {})
# Fetch Store schema
classes = _discover_store_classes()
if stype in classes:
cls = classes[stype]
if hasattr(cls, "config") and callable(cls.config):
for field_def in cls.config():
k = field_def.get("key")
if k:
provider_schema_map[k.upper()] = field_def
else:
container.mount(Label(f"Editing {item_type.capitalize()}: {item_name}", classes="config-label"))
section = self.config_data.get(item_type, {}).get(item_name, {})
# Fetch Provider schema
if item_type == "provider":
from ProviderCore.registry import get_provider_class
try:
pcls = get_provider_class(item_name)
if pcls and hasattr(pcls, "config") and callable(pcls.config):
for field_def in pcls.config():
k = field_def.get("key")
if k:
provider_schema_map[k.upper()] = field_def
except Exception:
pass
# Show all existing keys
existing_keys_upper = set()
for k, v in section.items():
@@ -229,10 +255,43 @@ class ConfigModal(ModalScreen):
continue
existing_keys_upper.add(k_upper)
container.mount(Label(k))
container.mount(Input(value=str(v), id=f"item-{k}", classes="config-input"))
# Determine display props from schema
label_text = k
is_secret = False
schema = provider_schema_map.get(k_upper)
if schema:
label_text = schema.get("label") or k
if schema.get("required"):
label_text += " *"
if schema.get("secret"):
is_secret = True
container.mount(Label(label_text))
inp = Input(value=str(v), id=f"item-{k}", classes="config-input")
if is_secret:
inp.password = True
container.mount(inp)
# If it's a store, we might have required keys
# Add required/optional fields from schema that are missing
for k_upper, field_def in provider_schema_map.items():
if k_upper not in existing_keys_upper:
existing_keys_upper.add(k_upper)
key = field_def["key"]
label_text = field_def.get("label") or key
if field_def.get("required"):
label_text += " *"
default_val = str(field_def.get("default") or "")
inp = Input(value=default_val, id=f"item-{key}", classes="config-input")
if field_def.get("secret"):
inp.password = True
if field_def.get("placeholder"):
inp.placeholder = field_def.get("placeholder")
container.mount(Label(label_text))
container.mount(inp)
# If it's a store, we might have required keys (legacy check fallback)
if item_type.startswith("store-"):
stype = item_type.replace("store-", "")
classes = _discover_store_classes()
@@ -244,8 +303,9 @@ class ConfigModal(ModalScreen):
container.mount(Label(rk))
container.mount(Input(value="", id=f"item-{rk}", classes="config-input"))
# If it's a provider, we might have required keys
# If it's a provider, we might have required keys (legacy check fallback)
if item_type == "provider":
# 2. Legacy required_config_keys
from ProviderCore.registry import get_provider_class
try:
pcls = get_provider_class(item_name)
@@ -307,10 +367,28 @@ class ConfigModal(ModalScreen):
self.editing_item_type = "provider"
self.refresh_view()
elif bid == "add-store-btn":
options = list(_discover_store_classes().keys())
all_classes = _discover_store_classes()
options = []
for stype, cls in all_classes.items():
if hasattr(cls, "config") and callable(cls.config):
try:
if cls.config():
options.append(stype)
except Exception:
pass
self.app.push_screen(SelectionModal("Select Store Type", options), callback=self.on_store_type_selected)
elif bid == "add-provider-btn":
options = list(list_providers().keys())
provider_names = list(list_providers().keys())
options = []
from ProviderCore.registry import get_provider_class
for ptype in provider_names:
pcls = get_provider_class(ptype)
if pcls and hasattr(pcls, "config") and callable(pcls.config):
try:
if pcls.config():
options.append(ptype)
except Exception:
pass
self.app.push_screen(SelectionModal("Select Provider Type", options), callback=self.on_provider_type_selected)
elif bid.startswith("del-store-"):
parts = bid.replace("del-store-", "").split("-", 1)
@@ -338,10 +416,23 @@ class ConfigModal(ModalScreen):
new_config = {"NAME": new_name}
classes = _discover_store_classes()
if stype in classes:
required = _required_keys_for(classes[stype])
for rk in required:
if rk.upper() != "NAME":
new_config[rk] = ""
cls = classes[stype]
# Use schema for defaults if present
if hasattr(cls, "config") and callable(cls.config):
for field_def in cls.config():
key = field_def.get("key")
if key:
val = field_def.get("default", "")
# Don't override NAME if we already set it to new_stype
if key.upper() == "NAME":
continue
new_config[key] = val
else:
# Fallback to required keys list
required = _required_keys_for(cls)
for rk in required:
if rk.upper() != "NAME":
new_config[rk] = ""
self.config_data["store"][stype][new_name] = new_config
self.editing_item_type = f"store-{stype}"
@@ -355,15 +446,22 @@ class ConfigModal(ModalScreen):
# For providers, they are usually top-level entries in 'provider' dict
if ptype not in self.config_data["provider"]:
# Get required keys if possible
from ProviderCore.registry import get_provider_class
try:
pcls = get_provider_class(ptype)
new_config = {}
if pcls:
required = pcls.required_config_keys()
for rk in required:
new_config[rk] = ""
# Use schema for defaults
if hasattr(pcls, "config") and callable(pcls.config):
for field_def in pcls.config():
key = field_def.get("key")
if key:
new_config[key] = field_def.get("default", "")
else:
# Fallback to legacy required keys
required = pcls.required_config_keys()
for rk in required:
new_config[rk] = ""
self.config_data["provider"][ptype] = new_config
except Exception:
self.config_data["provider"][ptype] = {}
@@ -420,14 +518,25 @@ class ConfigModal(ModalScreen):
stype = item_type.replace("store-", "")
classes = _discover_store_classes()
if stype in classes:
required_keys = _required_keys_for(classes[stype])
required_keys = list(_required_keys_for(classes[stype]))
section = self.config_data.get("store", {}).get(stype, {}).get(item_name, {})
elif item_type == "provider":
from ProviderCore.registry import get_provider_class
try:
pcls = get_provider_class(item_name)
if pcls:
required_keys = pcls.required_config_keys()
# Collect required keys from schema
if hasattr(pcls, "config") and callable(pcls.config):
for field_def in pcls.config():
if field_def.get("required"):
k = field_def.get("key")
if k and k not in required_keys:
required_keys.append(k)
# Merge with legacy required keys
for rk in pcls.required_config_keys():
if rk not in required_keys:
required_keys.append(rk)
except Exception:
pass
section = self.config_data.get("provider", {}).get(item_name, {})