feat(agent): add lmstudio integration

This commit is contained in:
Rugved Somwanshi 2026-04-25 12:30:55 -04:00 committed by kshitij
parent 7d4648461a
commit 214ca943ac
26 changed files with 1137 additions and 40 deletions

View file

@ -1123,7 +1123,7 @@ DEFAULT_CONFIG = {
},
# Config schema version - bump this when adding new required fields
"_config_version": 22,
"_config_version": 23,
}
# =============================================================================
@ -1223,6 +1223,22 @@ OPTIONAL_ENV_VARS = {
"category": "provider",
"advanced": True,
},
"LM_API_KEY": {
"description": "LM Studio bearer token for auth-enabled local servers",
"prompt": "LM Studio API key / bearer token",
"url": None,
"password": True,
"category": "provider",
"advanced": True,
},
"LM_BASE_URL": {
"description": "LM Studio base URL override",
"prompt": "LM Studio base URL (leave empty for default)",
"url": None,
"password": False,
"category": "provider",
"advanced": True,
},
"GLM_API_KEY": {
"description": "Z.AI / GLM API key (also recognized as ZAI_API_KEY / Z_AI_API_KEY)",
"prompt": "Z.AI / GLM API key",
@ -3107,6 +3123,28 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
"Use `hermes plugins enable <name>` to activate."
)
# ── Version 22 → 23: ensure LM_API_KEY is set when provider is lmstudio ──
# LM Studio's documented default is no-auth, but our API-key registry
# path needs *some* non-empty value to satisfy auxiliary_client and
# runtime resolution. Self-heal users whose config.yaml has
# provider:lmstudio but no LM_API_KEY in .env (cross-machine sync,
# manual edit, profile move).
if current_ver < 23:
try:
from hermes_cli.auth import LMSTUDIO_NOAUTH_PLACEHOLDER
config = load_config()
model_cfg = config.get("model")
if isinstance(model_cfg, dict) and str(model_cfg.get("provider") or "").strip().lower() == "lmstudio":
if not get_env_value("LM_API_KEY"):
save_env_value("LM_API_KEY", LMSTUDIO_NOAUTH_PLACEHOLDER)
results["env_added"].append(
f"LM_API_KEY={LMSTUDIO_NOAUTH_PLACEHOLDER} (placeholder for no-auth LM Studio)"
)
if not quiet:
print(" ✓ Added placeholder LM_API_KEY for LM Studio (no-auth default)")
except Exception:
pass
if current_ver < latest_ver and not quiet:
print(f"Config version: {current_ver}{latest_ver}")
@ -3806,7 +3844,7 @@ def save_env_value(key: str, value: str):
value = _check_non_ascii_credential(key, value)
ensure_hermes_home()
env_path = get_env_path()
# On Windows, open() defaults to the system locale (cp1252) which can
# cause OSError errno 22 on UTF-8 .env files.
read_kw = {"encoding": "utf-8", "errors": "replace"} if _IS_WINDOWS else {}
@ -3818,7 +3856,7 @@ def save_env_value(key: str, value: str):
lines = f.readlines()
# Sanitize on every read: split concatenated keys, drop stale placeholders
lines = _sanitize_env_lines(lines)
# Find and update or append
found = False
for i, line in enumerate(lines):
@ -3826,7 +3864,7 @@ def save_env_value(key: str, value: str):
lines[i] = f"{key}={value}\n"
found = True
break
if not found:
# Ensure there's a newline at the end of the file before appending
if lines and not lines[-1].endswith("\n"):