Skip to content

fix(update): preserve activated extras across runtime rebuilds - #73310

Closed
hxwvaa wants to merge 3 commits into
NousResearch:mainfrom
hxwvaa:fix/preserve-runtime-extras
Closed

fix(update): preserve activated extras across runtime rebuilds#73310
hxwvaa wants to merge 3 commits into
NousResearch:mainfrom
hxwvaa:fix/preserve-runtime-extras

Conversation

@hxwvaa

@hxwvaa hxwvaa commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Preserves user-activated optional Python dependencies when hermes update replaces or repairs the managed runtime.

The updater snapshots optional state before the old site-packages disappears, then restores only that snapshot afterward:

  • Declared lazy backends are restored through the existing guarded LAZY_DEPS path.
  • Python SDKs installed explicitly through hermes tools are restored from a static allowlist (faster-whisper, KittenTTS, Piper, DDGS, and Langfuse).
  • The ZIP fallback and the no-new-commits runtime-repair path use the same restoration behavior.
  • Langfuse emits one clear warning when its plugin is enabled but the SDK is unavailable.

Root cause: post-rebuild import detection has no historical state after replacement site-packages removes a previously activated dependency.

Security behavior: security.allow_lazy_installs: false remains an absolute lazy-install opt-out. Lazy restoration uses the guarded ensure(..., prompt=False) path. Hermes Tools packages are resolved only through a static internal allowlist; arbitrary captured package names are ignored. Optional restore failures are reported without aborting the core update.

Related Issue

Fixes #72924

Type of Change

  • 🐛 Bug fix (non-breaking change)
  • ✅ Tests

Changes Made

  • Snapshot and propagate active lazy backends before runtime replacement.
  • Restore activated lazy backends through the existing security-gated installer.
  • Snapshot Python dependencies activated through hermes tools and restore missing ones after the locked runtime sync.
  • Add a one-time Langfuse missing-SDK warning.
  • Add updater-level propagation, static-allowlist, security opt-out, and warning regression coverage.

How to Test

  1. Activate a lazy backend such as Telegram and install Langfuse through hermes tools.
  2. Trigger a managed-runtime rebuild through hermes update.
  3. Verify both dependencies remain importable afterward.
  4. Repeat with security.allow_lazy_installs: false; verify lazy restoration is skipped without a pip call.
  5. Enable the Langfuse plugin without its SDK; verify one warning is logged and tracing remains disabled.

Local results:

  • Focused and adjacent canonical suites: 86 passed, 1 skipped.
  • Ruff lint and git diff --check: passed.
  • Broader test_cmd_update.py: 15 passed; 6 could not enter the tested update path because a live local Hermes gateway held the Windows venv. The running gateway was intentionally left untouched.

Checklist

Code

  • I've read the Contributing Guide.
  • My commit messages follow Conventional Commits.
  • I searched for existing PRs to make sure this isn't a duplicate.
  • My PR contains only changes related to this fix.
  • I've added tests for my changes.
  • I've tested on my platform: Windows 11.

Documentation & Housekeeping

  • Documentation changes are N/A; behavior is documented in code docstrings.
  • Configuration changes are N/A.
  • CONTRIBUTING.md and AGENTS.md changes are N/A.
  • Cross-platform impact considered: state transfer is platform-neutral and preserves existing guards.
  • Tool descriptions/schemas are N/A.

@hxwvaa
hxwvaa force-pushed the fix/preserve-runtime-extras branch 2 times, most recently from 171291f to a388699 Compare July 28, 2026 11:31
@hxwvaa
hxwvaa marked this pull request as ready for review July 28, 2026 11:33
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard area/install-update Installer, updater, packaging, wheels, doctor labels Jul 28, 2026
@hxwvaa
hxwvaa force-pushed the fix/preserve-runtime-extras branch from a388699 to 4bf614f Compare July 30, 2026 06:41

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracing the lost pre-rebuild activation state; the current update flow really does re-detect active features only after the core install (hermes_cli/update_cmd.py:3599-3632), while active_features() depends on an anchor package still being present (tools/lazy_deps.py:1023-1041).

Problems

  • tools/lazy_deps.py:1095 directly calls _venv_pip_install(missing) for a restore. That bypasses _allow_lazy_installs(), although current main defines security.allow_lazy_installs: false as an absolute opt-out (tools/lazy_deps.py:487-509) and documents it as disabling runtime installs entirely (website/docs/user-guide/security.md:796). The added test explicitly encodes this bypass.

Suggested changes

  • Preserve the snapshot approach, but gate restore installs with _allow_lazy_installs() and return the existing skipped status when disabled. Update the regression test to assert that no pip call occurs under the security opt-out.
  • Add an updater-level test for snapshot capture and propagation; the new helper-only test does not exercise _cmd_update_impl.

Automated hermes-sweeper review.

Comment thread tools/lazy_deps.py Outdated
@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Two PRs address #72924 through the same pre-rebuild snapshot-and-restore strategy. #73309 restores activated LAZY_DEPS backends but bypasses the install opt-out, while #73310 corrects that security behavior and adds updater-level propagation coverage; neither diff demonstrates preservation of extras outside LAZY_DEPS.

Related pull requests

Duplicates

#73309 and #73310 substantially duplicate the same pre-rebuild snapshot and allowlisted restoration mechanism; #73310 is the corrected open successor, while #73309 is already closed.

Suggested consolidation

Keep #73310 open with a salvage path as the Verify-selected best existing partial fix: retain its corrected snapshot-and-guarded-restore implementation for previously activated LAZY_DEPS backends, while explicitly limiting its claimed scope or extending it with evidence for the broader extras named in #72924. Keep #73309 closed as a duplicate of #73310 because it implements the same core fix with the unresolved security-opt-out bypass.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I72924(["issue #72924 (open)"])
    subgraph Dup73309 ["PRs duplicating each other"]
        P73309["PR #73309 (closed)"]
        P73310["PR #73310 (open)"]
    end
    P73310 -->|best fix| I72924
    class I72924 open
    class P73309 closed
    class P73310 open
    class P73310 best
    class P73310 target
    click I72924 "https://github.com/NousResearch/hermes-agent/issues/72924"
    click P73309 "https://github.com/NousResearch/hermes-agent/pull/73309"
    click P73310 "https://github.com/NousResearch/hermes-agent/pull/73310"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 24 kB of PR diffs, 9 kB of issue/PR text, 5 kB of discussion (4 comments), 3 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

@hxwvaa
hxwvaa force-pushed the fix/preserve-runtime-extras branch from 01c8891 to c3bf4a2 Compare August 7, 2026 12:17
@hxwvaa

hxwvaa commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Updated this PR to cover the additional reproduction in #72924. Dependencies installed through hermes tools, including Langfuse, are now preserved across managed-runtime rebuilds and repair paths. The Langfuse plugin also emits a one-time warning when its SDK is unavailable. The PR description has been updated with the full scope and validation details.

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #86728 with your authorship preserved — all three commits were cherry-picked onto current main (rebased across the #86687 update_cmd.py restructuring) and are now in the history under your name. Thanks for the fix, @hxwvaa! Closing this PR as merged-via.

@teknium1 teknium1 closed this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install-update Installer, updater, packaging, wheels, doctor comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runtime rebuild silently drops declared extras during hermes update

4 participants