mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-26 01:01:40 +00:00
Merge pull request #14135 from helix4u/fix/tui-state-db-optional
fix(tui): degrade gracefully when state.db init fails
This commit is contained in:
commit
e47537e99d
2 changed files with 109 additions and 7 deletions
|
|
@ -2,6 +2,7 @@ import atexit
|
|||
import concurrent.futures
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import queue
|
||||
import subprocess
|
||||
|
|
@ -15,6 +16,8 @@ from pathlib import Path
|
|||
from hermes_constants import get_hermes_home
|
||||
from hermes_cli.env_loader import load_hermes_dotenv
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_hermes_home = get_hermes_home()
|
||||
load_hermes_dotenv(
|
||||
hermes_home=_hermes_home, project_env=Path(__file__).parent.parent / ".env"
|
||||
|
|
@ -34,6 +37,7 @@ _methods: dict[str, callable] = {}
|
|||
_pending: dict[str, tuple[str, threading.Event]] = {}
|
||||
_answers: dict[str, str] = {}
|
||||
_db = None
|
||||
_db_error: str | None = None
|
||||
_stdout_lock = threading.Lock()
|
||||
_cfg_lock = threading.Lock()
|
||||
_cfg_cache: dict | None = None
|
||||
|
|
@ -170,14 +174,28 @@ atexit.register(
|
|||
|
||||
|
||||
def _get_db():
|
||||
global _db
|
||||
global _db, _db_error
|
||||
if _db is None:
|
||||
from hermes_state import SessionDB
|
||||
|
||||
_db = SessionDB()
|
||||
try:
|
||||
_db = SessionDB()
|
||||
_db_error = None
|
||||
except Exception as exc:
|
||||
_db_error = str(exc)
|
||||
logger.warning(
|
||||
"TUI session store unavailable — continuing without state.db features: %s",
|
||||
exc,
|
||||
)
|
||||
return None
|
||||
return _db
|
||||
|
||||
|
||||
def _db_unavailable_error(rid, *, code: int):
|
||||
detail = _db_error or "state.db unavailable"
|
||||
return _err(rid, code, f"state.db unavailable: {detail}")
|
||||
|
||||
|
||||
def write_json(obj: dict) -> bool:
|
||||
line = json.dumps(obj, ensure_ascii=False) + "\n"
|
||||
try:
|
||||
|
|
@ -1329,7 +1347,9 @@ def _(rid, params: dict) -> dict:
|
|||
finally:
|
||||
_clear_session_context(tokens)
|
||||
|
||||
_get_db().create_session(key, source="tui", model=_resolve_model())
|
||||
db = _get_db()
|
||||
if db is not None:
|
||||
db.create_session(key, source="tui", model=_resolve_model())
|
||||
session["agent"] = agent
|
||||
|
||||
try:
|
||||
|
|
@ -1401,6 +1421,9 @@ def _(rid, params: dict) -> dict:
|
|||
|
||||
@method("session.list")
|
||||
def _(rid, params: dict) -> dict:
|
||||
db = _get_db()
|
||||
if db is None:
|
||||
return _db_unavailable_error(rid, code=5006)
|
||||
try:
|
||||
# Resume picker should include human conversation surfaces beyond
|
||||
# tui/cli (notably telegram from blitz row #7), but avoid internal
|
||||
|
|
@ -1427,7 +1450,7 @@ def _(rid, params: dict) -> dict:
|
|||
fetch_limit = max(limit * 5, 100)
|
||||
rows = [
|
||||
s
|
||||
for s in _get_db().list_sessions_rich(source=None, limit=fetch_limit)
|
||||
for s in db.list_sessions_rich(source=None, limit=fetch_limit)
|
||||
if (s.get("source") or "").strip().lower() in allow
|
||||
][:limit]
|
||||
return _ok(
|
||||
|
|
@ -1456,6 +1479,8 @@ def _(rid, params: dict) -> dict:
|
|||
if not target:
|
||||
return _err(rid, 4006, "session_id required")
|
||||
db = _get_db()
|
||||
if db is None:
|
||||
return _db_unavailable_error(rid, code=5000)
|
||||
found = db.get_session(target)
|
||||
if not found:
|
||||
found = db.get_session_by_title(target)
|
||||
|
|
@ -1494,13 +1519,16 @@ def _(rid, params: dict) -> dict:
|
|||
session, err = _sess(params, rid)
|
||||
if err:
|
||||
return err
|
||||
db = _get_db()
|
||||
if db is None:
|
||||
return _db_unavailable_error(rid, code=5007)
|
||||
title, key = params.get("title", ""), session["session_key"]
|
||||
if not title:
|
||||
return _ok(
|
||||
rid, {"title": _get_db().get_session_title(key) or "", "session_key": key}
|
||||
rid, {"title": db.get_session_title(key) or "", "session_key": key}
|
||||
)
|
||||
try:
|
||||
_get_db().set_session_title(key, title)
|
||||
db.set_session_title(key, title)
|
||||
return _ok(rid, {"title": title})
|
||||
except Exception as e:
|
||||
return _err(rid, 5007, str(e))
|
||||
|
|
@ -1636,6 +1664,8 @@ def _(rid, params: dict) -> dict:
|
|||
if err:
|
||||
return err
|
||||
db = _get_db()
|
||||
if db is None:
|
||||
return _db_unavailable_error(rid, code=5008)
|
||||
old_key = session["session_key"]
|
||||
with session["history_lock"]:
|
||||
history = [dict(msg) for msg in session.get("history", [])]
|
||||
|
|
@ -3483,11 +3513,14 @@ def _(rid, params: dict) -> dict:
|
|||
@method("insights.get")
|
||||
def _(rid, params: dict) -> dict:
|
||||
days = params.get("days", 30)
|
||||
db = _get_db()
|
||||
if db is None:
|
||||
return _db_unavailable_error(rid, code=5017)
|
||||
try:
|
||||
cutoff = time.time() - days * 86400
|
||||
rows = [
|
||||
s
|
||||
for s in _get_db().list_sessions_rich(limit=500)
|
||||
for s in db.list_sessions_rich(limit=500)
|
||||
if (s.get("started_at") or 0) >= cutoff
|
||||
]
|
||||
return _ok(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue