Merge branch 'simp/r3-21-E' into simp/integration3
This commit is contained in:
@@ -150,32 +150,26 @@ def _save_aux_choice(task: str, *, provider: str, model: str = "", base_url: str
|
||||
def _reset_aux_to_auto() -> int:
|
||||
"""Reset every known aux task (built-in + plugin) back to auto/empty. Returns number reset."""
|
||||
from hermes_cli.config import load_config, save_config
|
||||
cfg = load_config()
|
||||
aux = _ensure_dict_section(cfg, "auxiliary")
|
||||
count = 0
|
||||
for task, _name, _desc in _all_aux_tasks():
|
||||
entry = _ensure_dict_section(aux, task)
|
||||
def _clear(entry: dict, auto: str) -> bool:
|
||||
# Only the routing fields; timeout/download_timeout (aux) and max_concurrent_children
|
||||
# etc. (delegation) are user-tuned and preserved. *auto* is the reset provider value
|
||||
# ("auto" for aux tasks, "" for delegation); anything else counts as a change.
|
||||
changed = False
|
||||
if entry.get("provider") not in {None, "", "auto"}:
|
||||
entry["provider"] = "auto"
|
||||
if entry.get("provider") not in {None, "", auto}:
|
||||
entry["provider"] = auto
|
||||
changed = True
|
||||
for field in ("model", "base_url", "api_key"):
|
||||
if entry.get(field):
|
||||
entry[field] = ""
|
||||
changed = True
|
||||
# Preserve timeout/download_timeout — those are user-tuned, not routing
|
||||
if changed:
|
||||
count += 1
|
||||
# Delegation: clear only the routing fields; max_concurrent_children etc. are preserved.
|
||||
return changed
|
||||
|
||||
cfg = load_config()
|
||||
aux = _ensure_dict_section(cfg, "auxiliary")
|
||||
count = sum(_clear(_ensure_dict_section(aux, task), "auto") for task, _name, _desc in _all_aux_tasks())
|
||||
dele = cfg.get("delegation")
|
||||
if isinstance(dele, dict):
|
||||
changed = False
|
||||
for field in ("provider", "model", "base_url", "api_key"):
|
||||
if dele.get(field):
|
||||
dele[field] = ""
|
||||
changed = True
|
||||
if changed:
|
||||
count += 1
|
||||
count += _clear(dele, "")
|
||||
save_config(cfg)
|
||||
return count
|
||||
|
||||
@@ -444,7 +438,6 @@ def _save_custom_provider(base_url, api_key="", model="", context_length=None, n
|
||||
providers = cfg.get("custom_providers") or []
|
||||
if not isinstance(providers, list):
|
||||
providers = []
|
||||
|
||||
for entry in providers:
|
||||
if not (isinstance(entry, dict) and entry.get("base_url", "").rstrip("/") == base_url.rstrip("/")):
|
||||
continue
|
||||
@@ -453,11 +446,7 @@ def _save_custom_provider(base_url, api_key="", model="", context_length=None, n
|
||||
entry["model"] = model
|
||||
changed = True
|
||||
if model and context_length:
|
||||
models_cfg = entry.get("models", {})
|
||||
if not isinstance(models_cfg, dict):
|
||||
models_cfg = {}
|
||||
models_cfg[model] = {"context_length": context_length}
|
||||
entry["models"] = models_cfg
|
||||
_ensure_dict_section(entry, "models")[model] = {"context_length": context_length}
|
||||
changed = True
|
||||
if api_mode:
|
||||
if entry.get("api_mode") != api_mode:
|
||||
@@ -475,8 +464,7 @@ def _save_custom_provider(base_url, api_key="", model="", context_length=None, n
|
||||
save_config(cfg)
|
||||
return # already saved, updated if needed
|
||||
|
||||
if not name:
|
||||
name = _auto_provider_name(base_url)
|
||||
name = name or _auto_provider_name(base_url)
|
||||
entry = {"name": name, "base_url": base_url}
|
||||
if key_env:
|
||||
entry["key_env"] = key_env
|
||||
@@ -754,10 +742,7 @@ def _named_custom_provider_map(cfg) -> dict[str, dict[str, str]]:
|
||||
name_lc = str(name or "").strip().lower()
|
||||
pkey_lc = str(provider_key or "").strip().lower()
|
||||
model = str(model or "").strip()
|
||||
for identity in ((pkey_lc, model), (pkey_lc,), (name_lc, model), (name_lc,)):
|
||||
if identity[0] and identity in refs:
|
||||
return refs[identity]
|
||||
return ""
|
||||
return next((refs[i] for i in ((pkey_lc, model), (pkey_lc,), (name_lc, model), (name_lc,)) if i[0] and i in refs), "")
|
||||
|
||||
custom_provider_map = {}
|
||||
for entry in get_compatible_custom_providers(cfg):
|
||||
|
||||
@@ -308,9 +308,7 @@ def _model_flow_nous(config, current_model="", args=None):
|
||||
# Portal URL is needed for upgrade links and the recommendations endpoints.
|
||||
_nous_portal_url = ""
|
||||
with contextlib.suppress(Exception):
|
||||
_nous_state = get_provider_auth_state("nous")
|
||||
if _nous_state:
|
||||
_nous_portal_url = _nous_state.get("portal_base_url", "")
|
||||
_nous_portal_url = (get_provider_auth_state("nous") or {}).get("portal_base_url", "")
|
||||
|
||||
catalog = _nous_model_catalog(free_tier, _nous_portal_url, model_ids, pricing)
|
||||
if catalog is None:
|
||||
@@ -352,8 +350,7 @@ def _model_flow_openai_codex(config, current_model=""):
|
||||
_codex_token = None
|
||||
with contextlib.suppress(Exception):
|
||||
_codex_status = get_codex_auth_status()
|
||||
if _codex_status.get("logged_in"):
|
||||
_codex_token = _codex_status.get("api_key")
|
||||
_codex_token = _codex_status.get("api_key") if _codex_status.get("logged_in") else None
|
||||
if not _codex_token:
|
||||
with contextlib.suppress(Exception):
|
||||
from hermes_cli.auth import resolve_codex_runtime_credentials
|
||||
@@ -401,11 +398,9 @@ def _model_flow_qwen_oauth(_config, current_model=""):
|
||||
from hermes_cli.models import fetch_api_models
|
||||
status = get_qwen_auth_status()
|
||||
if not status.get("logged_in"):
|
||||
_say("Not logged into Qwen CLI OAuth.", "Run: qwen auth qwen-oauth")
|
||||
if status.get("auth_file"):
|
||||
print(f"Expected credentials file: {status.get('auth_file')}")
|
||||
if status.get("error"):
|
||||
print(f"Error: {status.get('error')}")
|
||||
_say("Not logged into Qwen CLI OAuth.", "Run: qwen auth qwen-oauth",
|
||||
*([f"Expected credentials file: {status.get('auth_file')}"] if status.get("auth_file") else []),
|
||||
*([f"Error: {status.get('error')}"] if status.get("error") else []))
|
||||
return
|
||||
|
||||
# Try live model discovery, fall back to curated list.
|
||||
@@ -541,12 +536,9 @@ def _model_flow_copilot(config, current_model=""):
|
||||
else:
|
||||
if source in {"GITHUB_TOKEN", "GH_TOKEN"}:
|
||||
from hermes_cli.env_loader import format_secret_source_suffix
|
||||
print(f" GitHub token: {api_key[:8]}... ✓ ({source}{format_secret_source_suffix(source)})")
|
||||
elif source == "gh auth token":
|
||||
print(" GitHub token: ✓ (from `gh auth token`)")
|
||||
_say(f" GitHub token: {api_key[:8]}... ✓ ({source}{format_secret_source_suffix(source)})", "")
|
||||
else:
|
||||
print(" GitHub token: ✓")
|
||||
print()
|
||||
_say(" GitHub token: ✓ (from `gh auth token`)" if source == "gh auth token" else " GitHub token: ✓", "")
|
||||
|
||||
effective_base = pconfig.inference_base_url
|
||||
catalog, live_models, _normalize = _copilot_catalog(api_key)
|
||||
@@ -674,14 +666,11 @@ def _model_flow_stepfun(config, current_model=""):
|
||||
current_base = str(model_cfg.get("base_url") or "").strip()
|
||||
current_region = _infer_stepfun_region(current_base or pconfig.inference_base_url)
|
||||
|
||||
ordered_regions = []
|
||||
for region_key, region_name in (("international", "International"), ("china", "China")):
|
||||
label = f"{region_name} ({_stepfun_base_url_for_region(region_key)})"
|
||||
if region_key == current_region:
|
||||
ordered_regions.insert(0, (region_key, f"{label} ← currently active"))
|
||||
else:
|
||||
ordered_regions.append((region_key, label))
|
||||
ordered_regions.append(("cancel", "Cancel"))
|
||||
regions = [(key, f"{name} ({_stepfun_base_url_for_region(key)})") for key, name in
|
||||
(("international", "International"), ("china", "China"))]
|
||||
# Active region first, marked; then the other; then Cancel.
|
||||
ordered_regions = ([(k, f"{label} ← currently active") for k, label in regions if k == current_region]
|
||||
+ [(k, label) for k, label in regions if k != current_region] + [("cancel", "Cancel")])
|
||||
|
||||
region_idx = _prompt_provider_choice([label for _, label in ordered_regions])
|
||||
if region_idx is None or ordered_regions[region_idx][0] == "cancel":
|
||||
|
||||
Reference in New Issue
Block a user