mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-10-20 05:15:31 +00:00
fix(cli): store custom endpoint API key in .env instead of config.yaml
hermes model's custom-endpoint flow is the other write path that produced a plaintext key, on both the model block and the custom_providers entry. Route it through the same .env indirection as the Desktop panel, and swap an existing entry's inline key for the reference when the URL is re-saved. Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
This commit is contained in:
parent
bd2dcfe9ca
commit
8a2925f794
2 changed files with 37 additions and 7 deletions
|
|
@ -3975,13 +3975,17 @@ def _custom_provider_base_url_config_value(provider_info, resolved_base_url=""):
|
|||
|
||||
|
||||
def _save_custom_provider(
|
||||
base_url, api_key="", model="", context_length=None, name=None, api_mode=None
|
||||
base_url, api_key="", model="", context_length=None, name=None, api_mode=None,
|
||||
key_env=""
|
||||
):
|
||||
"""Save a custom endpoint to custom_providers in config.yaml.
|
||||
|
||||
Deduplicates by base_url — if the URL already exists, updates the
|
||||
model name, context_length, and api_mode but doesn't add a duplicate entry.
|
||||
Uses *name* when provided, otherwise auto-generates from the URL.
|
||||
|
||||
When *key_env* is set the caller has already written the key to ``.env``,
|
||||
so the entry references it instead of inlining the secret (#69449).
|
||||
"""
|
||||
from hermes_cli.config import load_config, save_config
|
||||
|
||||
|
|
@ -4013,6 +4017,10 @@ def _save_custom_provider(
|
|||
elif "api_mode" in entry:
|
||||
entry.pop("api_mode", None)
|
||||
changed = True
|
||||
if key_env and (entry.get("key_env") != key_env or entry.get("api_key")):
|
||||
entry["key_env"] = key_env
|
||||
entry.pop("api_key", None)
|
||||
changed = True
|
||||
if changed:
|
||||
cfg["custom_providers"] = providers
|
||||
save_config(cfg)
|
||||
|
|
@ -4023,7 +4031,9 @@ def _save_custom_provider(
|
|||
name = _auto_provider_name(base_url)
|
||||
|
||||
entry = {"name": name, "base_url": base_url}
|
||||
if api_key:
|
||||
if key_env:
|
||||
entry["key_env"] = key_env
|
||||
elif api_key:
|
||||
entry["api_key"] = api_key
|
||||
if model:
|
||||
entry["model"] = model
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ from __future__ import annotations
|
|||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import urllib.parse
|
||||
|
||||
from hermes_cli.config import clear_model_endpoint_credentials
|
||||
|
||||
|
|
@ -833,7 +834,13 @@ def _model_flow_custom(config):
|
|||
"""
|
||||
from hermes_cli.main import _auto_provider_name, _prompt_custom_api_mode_selection, _save_custom_provider
|
||||
from hermes_cli.auth import _save_model_choice, deactivate_provider
|
||||
from hermes_cli.config import get_env_value, load_config, save_config
|
||||
from hermes_cli.config import (
|
||||
custom_endpoint_key_env,
|
||||
get_env_value,
|
||||
load_config,
|
||||
save_config,
|
||||
save_env_value,
|
||||
)
|
||||
from hermes_cli.secret_prompt import masked_secret_prompt
|
||||
|
||||
current_url = get_env_value("OPENAI_BASE_URL") or ""
|
||||
|
|
@ -988,6 +995,18 @@ def _model_flow_custom(config):
|
|||
print(f"Invalid context length: {context_length_str} — will auto-detect.")
|
||||
context_length = None
|
||||
|
||||
# The key goes to .env and config.yaml only references it (#69449). Keyed
|
||||
# on host:port so two servers on one machine keep separate credentials.
|
||||
custom_key_env = ""
|
||||
if effective_key:
|
||||
_parsed = urllib.parse.urlparse(effective_url)
|
||||
_identity = _parsed.hostname or ""
|
||||
if _parsed.port:
|
||||
_identity = f"{_identity}_{_parsed.port}"
|
||||
custom_key_env = custom_endpoint_key_env(_identity)
|
||||
save_env_value(custom_key_env, effective_key)
|
||||
print(f" API key saved to .env as {custom_key_env}")
|
||||
|
||||
if model_name:
|
||||
_save_model_choice(model_name)
|
||||
|
||||
|
|
@ -999,8 +1018,8 @@ def _model_flow_custom(config):
|
|||
cfg["model"] = model
|
||||
model["provider"] = "custom"
|
||||
model["base_url"] = effective_url
|
||||
if effective_key:
|
||||
model["api_key"] = effective_key
|
||||
if custom_key_env:
|
||||
model["api_key"] = f"${{{custom_key_env}}}"
|
||||
if api_mode:
|
||||
model["api_mode"] = api_mode
|
||||
else:
|
||||
|
|
@ -1025,8 +1044,8 @@ def _model_flow_custom(config):
|
|||
_caller_model = {"default": _caller_model} if _caller_model else {}
|
||||
_caller_model["provider"] = "custom"
|
||||
_caller_model["base_url"] = effective_url
|
||||
if effective_key:
|
||||
_caller_model["api_key"] = effective_key
|
||||
if custom_key_env:
|
||||
_caller_model["api_key"] = f"${{{custom_key_env}}}"
|
||||
if api_mode:
|
||||
_caller_model["api_mode"] = api_mode
|
||||
else:
|
||||
|
|
@ -1042,6 +1061,7 @@ def _model_flow_custom(config):
|
|||
context_length=context_length,
|
||||
name=display_name,
|
||||
api_mode=api_mode,
|
||||
key_env=custom_key_env,
|
||||
)
|
||||
_prune_replaced_custom_model_config_credentials(
|
||||
effective_url,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue