mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-29 11:42:04 +00:00
fix(hermes_state): persist billing provider/base_url after mid-session /model switch
The session database records billing_provider and billing_base_url using COALESCE(column, ?) in update_token_counts(), making them write-once. When a user switches models mid-session via /model, the runtime (agent.provider, agent.base_url) updates correctly, but the session row never reflects the new provider. This causes the dashboard Models page to display a stale provider badge and misattributes token usage / cost analytics. Fix: add update_session_billing_route() that unconditionally sets billing_provider, billing_base_url, and billing_mode (no COALESCE), and call it from switch_model() in agent_runtime_helpers.py after the swap succeeds. This follows the same pattern as update_session_model() which already unconditionally updates the model column (added for the identical COALESCE problem on the model field). Closes #48248
This commit is contained in:
parent
bf0513bca0
commit
c7e934a5b4
2 changed files with 51 additions and 0 deletions
|
|
@ -1697,6 +1697,27 @@ def switch_model(agent, new_model, new_provider, api_key='', base_url='', api_mo
|
|||
old_model, old_provider, new_model, new_provider,
|
||||
)
|
||||
|
||||
# ── Persist billing route to session DB ──
|
||||
# The agent's _session_db / session_id may not be set in all contexts
|
||||
# (tests, bare agents without a session DB, etc.). This ensures the
|
||||
# dashboard Model cards show the actual provider after a mid-session
|
||||
# /model switch instead of the stale session-creation provider.
|
||||
# See #48248 for the full bug description.
|
||||
_session_db = getattr(agent, "_session_db", None)
|
||||
_session_id = getattr(agent, "session_id", None)
|
||||
if _session_db is not None and _session_id:
|
||||
try:
|
||||
_session_db.update_session_billing_route(
|
||||
_session_id,
|
||||
provider=agent.provider,
|
||||
base_url=agent.base_url,
|
||||
billing_mode=getattr(agent, "api_mode", None),
|
||||
)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Failed to persist billing route after model switch",
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
|
||||
def invoke_tool(agent, function_name: str, function_args: dict, effective_task_id: str,
|
||||
|
|
|
|||
|
|
@ -1584,6 +1584,36 @@ class SessionDB:
|
|||
)
|
||||
self._execute_write(_do)
|
||||
|
||||
def update_session_billing_route(
|
||||
self,
|
||||
session_id: str,
|
||||
*,
|
||||
provider: str,
|
||||
base_url: str,
|
||||
billing_mode: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Unconditionally update the billing provider/base_url for a session.
|
||||
|
||||
Unlike ``update_token_counts`` which uses ``COALESCE(billing_provider, ?)``
|
||||
(only filling in NULL), this unconditionally sets the billing fields so
|
||||
that the dashboard reflects the user's latest /model switch.
|
||||
|
||||
Also nulls ``system_prompt`` so the cached snapshot (which embeds a
|
||||
stale ``Model:`` / ``Provider:`` header) is rebuilt — matching the
|
||||
behavior of ``update_session_model`` (see #48173, #48248).
|
||||
"""
|
||||
def _do(conn):
|
||||
conn.execute(
|
||||
"""UPDATE sessions SET
|
||||
billing_provider = ?,
|
||||
billing_base_url = ?,
|
||||
billing_mode = COALESCE(?, billing_mode),
|
||||
system_prompt = NULL
|
||||
WHERE id = ?""",
|
||||
(provider, base_url, billing_mode, session_id),
|
||||
)
|
||||
self._execute_write(_do)
|
||||
|
||||
def update_token_counts(
|
||||
self,
|
||||
session_id: str,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue