Skip to content

fix(desktop): preserve custom provider identity on resume#45578

Merged
teknium1 merged 4 commits into
mainfrom
hermes/hermes-477a2160
Jun 13, 2026
Merged

fix(desktop): preserve custom provider identity on resume#45578
teknium1 merged 4 commits into
mainfrom
hermes/hermes-477a2160

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Desktop/TUI resume now preserves custom-provider session identity and keeps reasoning-only turns visible.

Changes

  • tui_gateway/server.py: skip bare billing buckets as resume provider identities so old billing_provider="custom" rows fall back to configured provider resolution.
  • tui_gateway/server.py + hermes_cli/runtime_provider.py: persist/recover named custom provider identities as custom:<name> from the session endpoint URL instead of lossy bare custom.
  • tui_gateway/server.py: keep assistant turns with reasoning fields even when visible text is empty.
  • scripts/release.py: map salvaged contributor emails for changelog attribution.

Validation

Check Result
Targeted tests scripts/run_tests.sh tests/test_tui_gateway_server.py tests/hermes_cli/test_custom_provider_identity.py tests/tui_gateway/test_custom_provider_session_persistence.py → 282 passed
E2E custom-provider resume probe old bare billing row no longer restores provider_override; custom endpoint persists as custom:mimo-v2.5-pro; poisoned row rebuilds an AIAgent with the configured endpoint/key; reasoning-only turn survives _history_to_messages
Static py_compile scripts/release.py; git diff --check

Fixes #44022.
Refs #44108.

Salvages focused fixes from #44062 by @HaozheZhang6 and #44109/#44402 by @AIalliAI with commit authorship preserved.

Infographic

desktop-resume-custom-providers-fixed

HaozheZhang6 and others added 4 commits June 13, 2026 05:06
…ssion's provider

`_stored_session_runtime_overrides` restored the session provider from
`billing_provider` when `model_config` had no explicit provider. For a
`custom:<name>` endpoint that only ran normal turns (no `/model` switch), the
persisted `billing_provider` is the bare billing bucket `"custom"`, which
`agent_init` treats as non-routable, so `session.resume` failed with
"No LLM provider configured" even though new chats and CLI `--resume` work.

Only restore an explicit `model_config.provider`; skip a bare billing bucket
(`auto`/`openrouter`/`custom`) so resume falls back to the configured default,
matching the CLI path.

Fixes #44022
_runtime_model_config persisted the live agent's RESOLVED provider into
the session row's model_config JSON. For any named providers:/
custom_providers: entry, agent.provider is the literal string "custom",
so the entry name was lost (and the api_key is deliberately never
persisted). On session.resume or _reset_session_agent the stored
provider="custom" fed resolve_runtime_provider(requested="custom"),
which cannot match a named entry — the rebuild either raised "No LLM
provider configured" or silently resolved placeholder credentials
against the patched-back base_url.

Persist the REQUESTED/entry identity instead: a new reverse lookup
find_custom_provider_identity(base_url) maps the endpoint URL back to
the canonical custom:<name> menu key. _runtime_model_config stores that
key; _make_agent performs the same recovery for rows persisted before
the fix, falling back to passing the stored base_url as
explicit_base_url so the direct-alias branch still targets the
session's endpoint when no entry matches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A thinking-only assistant turn (reasoning present, empty visible text) is
persisted with its reasoning fields and stays recallable from the transcript,
but `_history_to_messages` dropped it as "empty" before its reasoning was
attached. On desktop/TUI resume or reload the turn therefore vanished from the
session view while the agent could still recall it from a fresh session --
exactly the "messages disappear when the LLM uses its thinking block, but a new
session can recall them" symptom reported on #44022.

Keep an assistant turn when it carries reasoning, even with empty text, so the
desktop "Thinking…" disclosure has something to render. Genuinely empty turns
(no text, no reasoning, no tool calls) are still filtered out.

Refs #44022

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-477a2160 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10888 on HEAD, 10887 on base (🆕 +1)

🆕 New issues (1):

Rule Count
invalid-argument-type 1
First entries
tests/hermes_cli/test_custom_provider_identity.py:76: [invalid-argument-type] invalid-argument-type: Argument to function `find_custom_provider_identity` is incorrect: Expected `str`, found `None`

✅ Fixed issues: none

Unchanged: 5710 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alpharou

Copy link
Copy Markdown

@teknium1 That infographic is something else, thanks for your continued work teknium! This next update better be called "the thousand bricks update" or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Desktop/TUI session.resume fails with "No LLM provider configured" when session only stored a bare billing_provider (e.g. custom)

4 participants