Merge branch 'simp/r3-25-F' into simp/integration3

This commit is contained in:
Teknium
2026-09-02 22:40:48 -07:00
5 changed files with 127 additions and 159 deletions
-2
View File
@@ -39,13 +39,11 @@ _ACTION_RESULTS = LateState("_ACTION_RESULTS")
def _action_log_dir() -> Path:
"""Live ``web_server._ACTION_LOG_DIR`` (a Path value, so not proxied by LateState)."""
from hermes_cli.web_server import _ACTION_LOG_DIR
return _ACTION_LOG_DIR
def _project_root() -> Path:
from hermes_cli.web_server import PROJECT_ROOT
return PROJECT_ROOT
-3
View File
@@ -155,7 +155,6 @@ async def get_client_voice_config(profile: Optional[str] = None):
Gate: ``voice.client_direct`` in config.yaml (default true).
"""
from tools.voice_client_config import resolve_client_voice_config
try:
result = await _run_config_scoped(profile, resolve_client_voice_config)
except Exception:
@@ -323,7 +322,6 @@ async def tts_lease(payload: TTSLeaseRequest, profile: Optional[str] = None):
def _apply():
from tools.tts_tool import acquire_tts_lease, release_tts_lease
if payload.active:
with _config_profile_scope(profile):
return acquire_tts_lease(lease)
@@ -376,7 +374,6 @@ async def speak_stream_ws(ws: "WebSocket") -> None:
def _resolve():
from tools.tts_streaming import resolve_streaming_provider
from tools.tts_tool import _get_provider, _load_tts_config, _resolve_max_text_length
with _config_profile_scope(profile):
cfg = _load_tts_config()
streamer = resolve_streaming_provider(cfg)
+37 -32
View File
@@ -105,7 +105,6 @@ async def get_schema(profile: Optional[str] = None):
async def get_egress_status():
"""Dashboard/Desktop-readable egress proxy status and remediation text."""
from hermes_cli.proxy_cli import format_status_text
return {"text": format_status_text()}
@@ -149,6 +148,15 @@ def _provider_card(d, description: str, url, *, is_password: bool, advanced: boo
}
_AUTH_TYPE_ENV_VARS = {
"aws_sdk": (
("AWS_REGION", lambda d, var: f"{d.label} ({var})"),
("AWS_PROFILE", lambda d, var: f"{d.label} ({var})"),
),
"vertex": (("VERTEX_CREDENTIALS_PATH", lambda d, var: f"{d.label} — service account JSON path (or use ADC)"),),
}
def _catalog_provider_env_metadata() -> dict:
"""Map provider env vars -> desktop card metadata, derived from the catalog.
@@ -196,19 +204,11 @@ def _catalog_provider_env_metadata() -> dict:
# the Keys tab: AWS-SDK providers (Bedrock) authenticate via the AWS
# credential chain, Vertex via OAuth2 (service-account JSON path or
# ADC — a path, not a secret). Tag their env vars to the card.
if d.auth_type == "aws_sdk":
for aws_var in ("AWS_REGION", "AWS_PROFILE"):
existing = meta.get(aws_var, {})
meta[aws_var] = _provider_card(
d, existing.get("description") or f"{d.label} ({aws_var})", existing.get("url"),
is_password=False, advanced=existing.get("advanced", True),
)
if d.auth_type == "vertex":
existing = meta.get("VERTEX_CREDENTIALS_PATH", {})
meta["VERTEX_CREDENTIALS_PATH"] = _provider_card(
d,
existing.get("description") or f"{d.label} — service account JSON path (or use ADC)",
existing.get("url"), is_password=False, advanced=existing.get("advanced", True),
for var, describe in _AUTH_TYPE_ENV_VARS.get(d.auth_type, ()):
existing = meta.get(var, {})
meta[var] = _provider_card(
d, existing.get("description") or describe(d, var), existing.get("url"),
is_password=False, advanced=existing.get("advanced", True),
)
return meta
@@ -352,6 +352,19 @@ def _config_api_key_is_env_ref(endpoint_id: str) -> bool:
return bool(isinstance(raw_key, str) and re.search(r"\$\{[^}]+\}", raw_key))
def _endpoint_row(
endpoint_id: str, name: str, base_url: str, model: str, models: List[str], context_length,
discover_models: bool, key_entry: Dict[str, Any], is_current: bool, source: str,
) -> Dict[str, Any]:
has_api_key, api_key_preview = _api_key_display(key_entry)
return {
"id": endpoint_id, "name": name, "base_url": base_url, "model": model, "models": models,
"context_length": context_length, "discover_models": discover_models,
"has_api_key": has_api_key, "api_key_preview": api_key_preview,
"is_current": is_current, "source": source,
}
def _custom_endpoint_response(cfg: Dict[str, Any]) -> Dict[str, Any]:
model_cfg = cfg.get("model", {}) if isinstance(cfg.get("model"), dict) else {}
current_provider = str(model_cfg.get("provider", "") or "")
@@ -369,26 +382,18 @@ def _custom_endpoint_response(cfg: Dict[str, Any]) -> Dict[str, Any]:
continue
endpoint_id = str(provider_id)
models = _models_from_custom_endpoint_entry(raw_entry)
endpoint_model = str(raw_entry.get("model") or raw_entry.get("default_model") or (models[0] if models else ""))
has_api_key, api_key_preview = _api_key_display(raw_entry)
endpoints.append({
"id": endpoint_id, "name": str(raw_entry.get("name") or endpoint_id),
"base_url": base_url, "model": endpoint_model, "models": models,
"context_length": raw_entry.get("context_length"),
"discover_models": bool(raw_entry.get("discover_models", True)),
"has_api_key": has_api_key, "api_key_preview": api_key_preview,
"is_current": endpoint_id == current_provider, "source": "providers",
})
endpoints.append(_endpoint_row(
endpoint_id, str(raw_entry.get("name") or endpoint_id), base_url,
str(raw_entry.get("model") or raw_entry.get("default_model") or (models[0] if models else "")),
models, raw_entry.get("context_length"), bool(raw_entry.get("discover_models", True)),
raw_entry, endpoint_id == current_provider, "providers",
))
if current_provider.lower() == "custom" and current_base_url and not any(e["id"] == "custom" for e in endpoints):
has_api_key, api_key_preview = _api_key_display(model_cfg)
endpoints.insert(0, {
"id": "custom", "name": "Custom", "base_url": current_base_url, "model": current_model,
"models": [current_model] if current_model else [],
"context_length": model_cfg.get("context_length"), "discover_models": True,
"has_api_key": has_api_key, "api_key_preview": api_key_preview, "is_current": True,
"source": "direct-config",
})
endpoints.insert(0, _endpoint_row(
"custom", "Custom", current_base_url, current_model, [current_model] if current_model else [],
model_cfg.get("context_length"), True, model_cfg, True, "direct-config",
))
return {
"endpoints": endpoints,
+19 -32
View File
@@ -124,7 +124,6 @@ def _read_flat_json(provider: ProviderConfigSchema) -> Dict[str, Any]:
def _honcho_resolvers():
"""Lazily import the Honcho plugin's resolvers (optional plugin)."""
from plugins.memory.honcho.client import _host_block, resolve_active_host, resolve_config_path
return resolve_active_host, resolve_config_path, _host_block
@@ -434,40 +433,28 @@ def _install_memory_provider_external_dependencies(
check_cmd = dep.get("check") or ""
install_cmd = dep.get("install") or ""
def _check(status_of) -> bool:
"""Run the check command; append its result; True when it passed."""
def _run(kind: str, command: str, status_of, **kwargs) -> Optional[int]:
"""Run a setup command, append its result row; returncode or None on spawn failure."""
try:
check = _run_setup_command(shlex.split(check_cmd), display=check_cmd, timeout=20)
completed = _run_setup_command(command if kwargs.get("shell") else shlex.split(command), display=command, **kwargs)
except Exception as exc:
results.append(_command_result(kind="external_check", name=name, status=status_of(None), command=check_cmd, error=str(exc)))
return False
ok = check.returncode == 0
results.append(_command_result(kind="external_check", name=name, status=status_of(ok), command=check_cmd, completed=check))
return ok
results.append(_command_result(kind=kind, name=name, status=status_of(None), command=command, error=str(exc)))
return None
results.append(_command_result(kind=kind, name=name, status=status_of(completed.returncode == 0), command=command, completed=completed))
return completed.returncode
if check_cmd:
if _check(lambda ok: "already_installed" if ok else ("missing" if install_cmd else "failed")):
continue
if not install_cmd:
continue
if install_cmd:
try:
install = _run_setup_command(install_cmd, display=install_cmd, shell=True, timeout=300)
except Exception as exc:
results.append(_command_result(kind="external_install", name=name, status="failed", command=install_cmd, error=str(exc)))
continue
results.append(
_command_result(
kind="external_install", name=name,
status="installed" if install.returncode == 0 else "failed",
command=install_cmd, completed=install,
)
)
if check_cmd and install.returncode == 0:
_check(lambda ok: "verified" if ok else "failed")
# Check first: "already_installed" short-circuits; a failed check is
# "missing" when an install step can fix it, "failed" otherwise.
if check_cmd and _run(
"external_check", check_cmd,
lambda ok: "already_installed" if ok else ("missing" if install_cmd else "failed"), timeout=20,
) == 0:
continue
if not install_cmd:
continue
rc = _run("external_install", install_cmd, lambda ok: "installed" if ok else "failed", shell=True, timeout=300)
if check_cmd and rc == 0:
_run("external_check", check_cmd, lambda ok: "verified" if ok else "failed", timeout=20)
return results
+71 -90
View File
@@ -107,6 +107,14 @@ def _start_poller(target, sid: str) -> None:
threading.Thread(target=target, args=(sid,), daemon=True, name=f"oauth-poll-{sid[:6]}").start()
def _device_code_started(sid: str, user_code, verification_url, expires_in: int, poll_interval: int) -> Dict[str, Any]:
"""The /start response shape shared by every device-code flow."""
return {
"session_id": sid, "flow": "device_code", "user_code": user_code,
"verification_url": verification_url, "expires_in": expires_in, "poll_interval": poll_interval,
}
def _codex_full_login_worker(session_id: str) -> None:
"""Run the complete OpenAI Codex device-code flow.
@@ -232,63 +240,46 @@ def _codex_full_login_worker(session_id: str) -> None:
s["error_message"] = str(e)
# Hand-written status card shapes per provider id: (hauth getter name, shaper).
_OMIT: Any = object()
def _status_card(
raw: dict, source, source_label, token_preview, expires_at, has_refresh_token, last_refresh=_OMIT
) -> Dict[str, Any]:
card = {
"logged_in": bool(raw.get("logged_in")), "source": source, "source_label": source_label,
"token_preview": token_preview, "expires_at": expires_at, "has_refresh_token": has_refresh_token,
}
if last_refresh is not _OMIT:
card["last_refresh"] = last_refresh
return card
# Hand-written status cards per provider id: (hauth getter name, raw -> card).
# Providers absent here fall through to the slug-driven ``get_auth_status``.
def _nous_status(raw):
# Refresh-free snapshot so listing providers never performs an OAuth refresh.
return {
"logged_in": bool(raw.get("logged_in")), "source": "nous_portal",
"source_label": raw.get("portal_base_url") or "Nous Portal",
"token_preview": _truncate_token(raw.get("access_token")),
"expires_at": raw.get("access_expires_at"),
"has_refresh_token": bool(raw.get("has_refresh_token")),
}
def _codex_status(raw):
return {
"logged_in": bool(raw.get("logged_in")), "source": raw.get("source") or "openai_codex",
"source_label": raw.get("auth_mode") or "OpenAI Codex",
"token_preview": _truncate_token(raw.get("api_key")), "expires_at": None,
"has_refresh_token": False, "last_refresh": raw.get("last_refresh"),
}
def _qwen_status(raw):
return {
"logged_in": bool(raw.get("logged_in")), "source": "qwen_cli",
"source_label": raw.get("auth_store_path") or "Qwen CLI",
"token_preview": _truncate_token(raw.get("access_token")),
"expires_at": raw.get("expires_at"),
"has_refresh_token": bool(raw.get("has_refresh_token")),
}
def _minimax_status(raw):
return {
"logged_in": bool(raw.get("logged_in")), "source": "minimax_oauth",
"source_label": f"MiniMax ({raw.get('region', 'global')})", "token_preview": None,
"expires_at": raw.get("expires_at"), "has_refresh_token": True,
}
def _xai_status(raw):
# source_label is a human-readable origin (auth-store path / credential
# source), not the internal auth_mode string ("oauth_pkce").
return {
"logged_in": bool(raw.get("logged_in")), "source": raw.get("source") or "xai_oauth",
"source_label": raw.get("auth_store") or raw.get("source") or "xAI Grok OAuth",
"token_preview": _truncate_token(raw.get("api_key")), "expires_at": None,
"has_refresh_token": True, "last_refresh": raw.get("last_refresh"),
}
# nous: refresh-free local snapshot so listing providers never performs an OAuth
# refresh. xai: source_label is a human-readable origin (auth-store path /
# credential source), not the internal auth_mode string ("oauth_pkce").
_PROVIDER_STATUS: Dict[str, tuple[str, Callable[[dict], dict]]] = {
"nous": ("get_nous_auth_status_local", _nous_status),
"openai-codex": ("get_codex_auth_status", _codex_status),
"qwen-oauth": ("get_qwen_auth_status", _qwen_status),
"minimax-oauth": ("get_minimax_oauth_auth_status", _minimax_status),
"xai-oauth": ("get_xai_oauth_auth_status", _xai_status),
"nous": ("get_nous_auth_status_local", lambda r: _status_card(
r, "nous_portal", r.get("portal_base_url") or "Nous Portal",
_truncate_token(r.get("access_token")), r.get("access_expires_at"), bool(r.get("has_refresh_token")),
)),
"openai-codex": ("get_codex_auth_status", lambda r: _status_card(
r, r.get("source") or "openai_codex", r.get("auth_mode") or "OpenAI Codex",
_truncate_token(r.get("api_key")), None, False, r.get("last_refresh"),
)),
"qwen-oauth": ("get_qwen_auth_status", lambda r: _status_card(
r, "qwen_cli", r.get("auth_store_path") or "Qwen CLI",
_truncate_token(r.get("access_token")), r.get("expires_at"), bool(r.get("has_refresh_token")),
)),
"minimax-oauth": ("get_minimax_oauth_auth_status", lambda r: _status_card(
r, "minimax_oauth", f"MiniMax ({r.get('region', 'global')})", None, r.get("expires_at"), True,
)),
"xai-oauth": ("get_xai_oauth_auth_status", lambda r: _status_card(
r, r.get("source") or "xai_oauth", r.get("auth_store") or r.get("source") or "xAI Grok OAuth",
_truncate_token(r.get("api_key")), None, True, r.get("last_refresh"),
)),
}
@@ -310,21 +301,15 @@ def _resolve_provider_status(provider_id: str, status_fn) -> Dict[str, Any]:
# a new OAuth/account provider plugin never renders permanently logged-out.
raw = hauth.get_auth_status(provider_id)
if isinstance(raw, dict) and "logged_in" in raw:
return {
"logged_in": bool(raw.get("logged_in")),
"source": raw.get("source") or raw.get("provider") or provider_id,
"source_label": (
raw.get("source_label")
or raw.get("auth_store")
or raw.get("auth_store_path")
or raw.get("base_url")
or raw.get("name")
or ""
),
"token_preview": _truncate_token(raw.get("access_token") or raw.get("api_key")),
"expires_at": raw.get("expires_at") or raw.get("access_expires_at"),
"has_refresh_token": bool(raw.get("has_refresh_token")),
}
return _status_card(
raw,
raw.get("source") or raw.get("provider") or provider_id,
raw.get("source_label") or raw.get("auth_store") or raw.get("auth_store_path")
or raw.get("base_url") or raw.get("name") or "",
_truncate_token(raw.get("access_token") or raw.get("api_key")),
raw.get("expires_at") or raw.get("access_expires_at"),
bool(raw.get("has_refresh_token")),
)
except Exception as e:
return {"logged_in": False, "error": str(e)}
return {"logged_in": False}
@@ -359,11 +344,10 @@ async def _start_nous_device_code(profile: Optional[str]) -> Dict[str, Any]:
client_id=client_id, scope=effective_scope,
)
_start_poller(_nous_poller, sid)
return {
"session_id": sid, "flow": "device_code", "user_code": str(device_data["user_code"]),
"verification_url": str(device_data["verification_uri_complete"]),
"expires_in": int(device_data["expires_in"]), "poll_interval": int(device_data["interval"]),
}
return _device_code_started(
sid, str(device_data["user_code"]), str(device_data["verification_uri_complete"]),
int(device_data["expires_in"]), int(device_data["interval"]),
)
async def _start_codex_device_code(profile: Optional[str]) -> Dict[str, Any]:
@@ -385,11 +369,9 @@ async def _start_codex_device_code(profile: Optional[str]) -> Dict[str, Any]:
raise HTTPException(status_code=500, detail=s.get("error_message") or "device-auth failed")
if not s.get("user_code"):
raise HTTPException(status_code=504, detail="device-auth timed out before returning a user code")
return {
"session_id": sid, "flow": "device_code", "user_code": s["user_code"],
"verification_url": s["verification_url"], "expires_in": int(s.get("expires_in") or 900),
"poll_interval": int(s.get("interval") or 5),
}
return _device_code_started(
sid, s["user_code"], s["verification_url"], int(s.get("expires_in") or 900), int(s.get("interval") or 5)
)
async def _start_minimax_device_code(profile: Optional[str]) -> Dict[str, Any]:
@@ -433,11 +415,10 @@ async def _start_minimax_device_code(profile: Optional[str]) -> Dict[str, Any]:
expires_in_seconds = expired_in_raw
sess["expires_at"] = expires_at_ts
_start_poller(_minimax_poller, sid)
return {
"session_id": sid, "flow": "device_code", "user_code": str(device_data["user_code"]),
"verification_url": str(device_data["verification_uri"]), "expires_in": expires_in_seconds,
"poll_interval": max(2, (sess["interval_ms"] or 2000) // 1000),
}
return _device_code_started(
sid, str(device_data["user_code"]), str(device_data["verification_uri"]), expires_in_seconds,
max(2, (sess["interval_ms"] or 2000) // 1000),
)
async def _start_xai_device_code(profile: Optional[str]) -> Dict[str, Any]:
@@ -455,11 +436,11 @@ async def _start_xai_device_code(profile: Optional[str]) -> Dict[str, Any]:
expires_at=time.time() + int(device_data["expires_in"]),
)
_start_poller(_xai_device_poller, sid)
return {
"session_id": sid, "flow": "device_code", "user_code": str(device_data["user_code"]),
"verification_url": str(device_data.get("verification_uri_complete") or device_data["verification_uri"]),
"expires_in": int(device_data["expires_in"]), "poll_interval": int(device_data["interval"]),
}
return _device_code_started(
sid, str(device_data["user_code"]),
str(device_data.get("verification_uri_complete") or device_data["verification_uri"]),
int(device_data["expires_in"]), int(device_data["interval"]),
)
_DEVICE_CODE_STARTERS = {