feat: enhance config migration with new environment variable tracking
Added a system to track environment variables introduced in each config version, allowing migration prompts to only mention new variables since the user's last version. Updated the interactive configuration process to offer users the option to set these new optional keys during migration.
This commit is contained in:
parent
132e5ec179
commit
f824c10429
1 changed files with 48 additions and 26 deletions
|
|
@ -156,6 +156,15 @@ DEFAULT_CONFIG = {
|
||||||
# Config Migration System
|
# Config Migration System
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
# Track which env vars were introduced in each config version.
|
||||||
|
# Migration only mentions vars new since the user's previous version.
|
||||||
|
ENV_VARS_BY_VERSION: Dict[int, List[str]] = {
|
||||||
|
3: ["FIRECRAWL_API_KEY", "BROWSERBASE_API_KEY", "BROWSERBASE_PROJECT_ID", "FAL_KEY"],
|
||||||
|
4: ["VOICE_TOOLS_OPENAI_KEY", "ELEVENLABS_API_KEY"],
|
||||||
|
5: ["WHATSAPP_ENABLED", "WHATSAPP_MODE", "WHATSAPP_ALLOWED_USERS",
|
||||||
|
"SLACK_BOT_TOKEN", "SLACK_APP_TOKEN", "SLACK_ALLOWED_USERS"],
|
||||||
|
}
|
||||||
|
|
||||||
# Required environment variables with metadata for migration prompts.
|
# Required environment variables with metadata for migration prompts.
|
||||||
# LLM provider is required but handled in the setup wizard's provider
|
# LLM provider is required but handled in the setup wizard's provider
|
||||||
# selection step (Nous Portal / OpenRouter / Custom endpoint), so this
|
# selection step (Nous Portal / OpenRouter / Custom endpoint), so this
|
||||||
|
|
@ -625,34 +634,47 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
|
||||||
if v["name"] not in required_names and not v.get("advanced")
|
if v["name"] not in required_names and not v.get("advanced")
|
||||||
]
|
]
|
||||||
|
|
||||||
if interactive and missing_optional:
|
# Only offer to configure env vars that are NEW since the user's previous version
|
||||||
print(" Would you like to configure any optional keys now?")
|
new_var_names = set()
|
||||||
|
for ver in range(current_ver + 1, latest_ver + 1):
|
||||||
|
new_var_names.update(ENV_VARS_BY_VERSION.get(ver, []))
|
||||||
|
|
||||||
|
if new_var_names and interactive and not quiet:
|
||||||
|
new_and_unset = [
|
||||||
|
(name, OPTIONAL_ENV_VARS[name])
|
||||||
|
for name in sorted(new_var_names)
|
||||||
|
if not get_env_value(name) and name in OPTIONAL_ENV_VARS
|
||||||
|
]
|
||||||
|
if new_and_unset:
|
||||||
|
print(f"\n {len(new_and_unset)} new optional key(s) in this update:")
|
||||||
|
for name, info in new_and_unset:
|
||||||
|
print(f" • {name} — {info.get('description', '')}")
|
||||||
|
print()
|
||||||
try:
|
try:
|
||||||
answer = input(" Configure optional keys? [y/N]: ").strip().lower()
|
answer = input(" Configure new keys? [y/N]: ").strip().lower()
|
||||||
except (EOFError, KeyboardInterrupt):
|
except (EOFError, KeyboardInterrupt):
|
||||||
answer = "n"
|
answer = "n"
|
||||||
|
|
||||||
if answer in ("y", "yes"):
|
if answer in ("y", "yes"):
|
||||||
print()
|
print()
|
||||||
for var in missing_optional:
|
for name, info in new_and_unset:
|
||||||
desc = var.get("description", "")
|
if info.get("url"):
|
||||||
if var.get("url"):
|
print(f" {info.get('description', name)}")
|
||||||
print(f" {desc}")
|
print(f" Get your key at: {info['url']}")
|
||||||
print(f" Get your key at: {var['url']}")
|
|
||||||
else:
|
else:
|
||||||
print(f" {desc}")
|
print(f" {info.get('description', name)}")
|
||||||
|
if info.get("password"):
|
||||||
if var.get("password"):
|
|
||||||
import getpass
|
import getpass
|
||||||
value = getpass.getpass(f" {var['prompt']} (Enter to skip): ")
|
value = getpass.getpass(f" {info.get('prompt', name)} (Enter to skip): ")
|
||||||
else:
|
else:
|
||||||
value = input(f" {var['prompt']} (Enter to skip): ").strip()
|
value = input(f" {info.get('prompt', name)} (Enter to skip): ").strip()
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
save_env_value(var["name"], value)
|
save_env_value(name, value)
|
||||||
results["env_added"].append(var["name"])
|
results["env_added"].append(name)
|
||||||
print(f" ✓ Saved {var['name']}")
|
print(f" ✓ Saved {name}")
|
||||||
print()
|
print()
|
||||||
|
else:
|
||||||
|
print(" Set later with: hermes config set KEY VALUE")
|
||||||
|
|
||||||
# Check for missing config fields
|
# Check for missing config fields
|
||||||
missing_config = get_missing_config_fields()
|
missing_config = get_missing_config_fields()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue