mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-11 12:52:03 +08:00
116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
|
|
"""CLI handlers for ``hermes migrate ...``.
|
||
|
|
|
||
|
|
Currently exposes only ``hermes migrate xai`` — diagnoses and (with --apply)
|
||
|
|
rewrites references to xAI models retired on May 15, 2026.
|
||
|
|
"""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from hermes_cli.colors import Colors, color
|
||
|
|
from hermes_cli.config import load_config
|
||
|
|
|
||
|
|
|
||
|
|
def cmd_migrate(args: Any) -> int:
|
||
|
|
"""Dispatcher for ``hermes migrate <subtype>``."""
|
||
|
|
sub = getattr(args, "migrate_type", None)
|
||
|
|
if sub == "xai":
|
||
|
|
return cmd_migrate_xai(args)
|
||
|
|
|
||
|
|
print("usage: hermes migrate xai [--apply] [--no-backup]", file=sys.stderr)
|
||
|
|
return 2
|
||
|
|
|
||
|
|
|
||
|
|
def cmd_migrate_xai(args: Any) -> int:
|
||
|
|
"""Run xAI May-15 model migration in dry-run or apply mode."""
|
||
|
|
from hermes_cli.xai_retirement import (
|
||
|
|
MIGRATION_GUIDE_URL,
|
||
|
|
RETIREMENT_DATE,
|
||
|
|
apply_migration,
|
||
|
|
find_retired_xai_refs,
|
||
|
|
format_issue,
|
||
|
|
)
|
||
|
|
|
||
|
|
apply = bool(getattr(args, "apply", False))
|
||
|
|
no_backup = bool(getattr(args, "no_backup", False))
|
||
|
|
|
||
|
|
config = load_config()
|
||
|
|
issues = find_retired_xai_refs(config)
|
||
|
|
|
||
|
|
print()
|
||
|
|
print(color(
|
||
|
|
f"◆ xAI Model Retirement Migration ({RETIREMENT_DATE})",
|
||
|
|
Colors.CYAN, Colors.BOLD,
|
||
|
|
))
|
||
|
|
print()
|
||
|
|
|
||
|
|
if not issues:
|
||
|
|
print(f" {color('✓', Colors.GREEN)} No retired xAI models in config — nothing to migrate.")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
print(f" Found {len(issues)} retired xAI model reference(s):")
|
||
|
|
print()
|
||
|
|
for issue in issues:
|
||
|
|
print(f" {color('⚠', Colors.YELLOW)} {format_issue(issue)}")
|
||
|
|
print()
|
||
|
|
print(f" {color('→', Colors.CYAN)} Migration guide: {MIGRATION_GUIDE_URL}")
|
||
|
|
print()
|
||
|
|
|
||
|
|
config_path = _resolve_config_path()
|
||
|
|
|
||
|
|
if not apply:
|
||
|
|
print(color("Dry-run mode — no changes written.", Colors.DIM))
|
||
|
|
print(color(
|
||
|
|
"Re-run with `hermes migrate xai --apply` to rewrite "
|
||
|
|
f"{config_path} in-place (backup created automatically).",
|
||
|
|
Colors.DIM,
|
||
|
|
))
|
||
|
|
return 0
|
||
|
|
|
||
|
|
if not config_path or not config_path.exists():
|
||
|
|
print(
|
||
|
|
f" {color('✗', Colors.RED)} Could not locate config.yaml "
|
||
|
|
f"(looked at: {config_path})",
|
||
|
|
file=sys.stderr,
|
||
|
|
)
|
||
|
|
return 1
|
||
|
|
|
||
|
|
try:
|
||
|
|
result = apply_migration(
|
||
|
|
config_path=config_path,
|
||
|
|
issues=issues,
|
||
|
|
backup=not no_backup,
|
||
|
|
)
|
||
|
|
except Exception as exc:
|
||
|
|
print(
|
||
|
|
f" {color('✗', Colors.RED)} Migration failed: {exc}",
|
||
|
|
file=sys.stderr,
|
||
|
|
)
|
||
|
|
return 1
|
||
|
|
|
||
|
|
if not result.config_changed:
|
||
|
|
print(f" {color('⚠', Colors.YELLOW)} No changes written.")
|
||
|
|
return 0
|
||
|
|
|
||
|
|
if result.backup_path is not None:
|
||
|
|
print(f" {color('✓', Colors.GREEN)} Backup: {result.backup_path}")
|
||
|
|
print(
|
||
|
|
f" {color('✓', Colors.GREEN)} Updated {len(result.issues_resolved)} "
|
||
|
|
f"slot(s) in {result.file_path}"
|
||
|
|
)
|
||
|
|
print()
|
||
|
|
print(color(
|
||
|
|
"Run `hermes doctor` to confirm no retired xAI models remain.",
|
||
|
|
Colors.DIM,
|
||
|
|
))
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
def _resolve_config_path() -> Path:
|
||
|
|
"""Best-effort: locate the active config.yaml on disk."""
|
||
|
|
from hermes_cli.config import get_hermes_home
|
||
|
|
|
||
|
|
return get_hermes_home() / "config.yaml"
|