NousResearch/hermes-agent

Plugin.yaml manifests missing from distributed packages

Cluster 28149 · skills. Data as of

Nothing open on GitHub. Fix merged in #34484 on 29 May 2026. Check it covers your case.

The short answer

0open issues
0open PRs
4items grouped
Known?
Yes. 4 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #34484. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this unresolved. That is separate from the fix event.
Still open
Nothing open on GitHub.

These issues and pull requests concern plugin.yaml manifest files being absent from wheel, sdist, and Homebrew bottle distributions. The work involves packaging fixes to ensure these files are included when the software is distributed.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #34484 fix(packaging): ship bundled plugin.yaml manifests in wheel and sdist

    merged to main

    files: MANIFEST.in, pyproject.toml, tests/test_packaging_metadata.py

    Show the diff
    • MANIFEST.in
      @@ -1,4 +1,9 @@
       graft skills
       graft optional-skills
      +# Bundled plugin manifests (plugin.yaml / plugin.yml). Without these the
      +# PluginManager scan (hermes_cli/plugins.py) finds zero plugins on installs
      +# built from the sdist (e.g. Homebrew, downstream packagers). package-data
      +# below covers the wheel; this covers the sdist. See #34034 / #28149.
      +recursive-include plugins plugin.yaml plugin.yml
       global-exclude __pycache__
       global-exclude *.py[cod]
    • pyproject.toml
      @@ -226,6 +226,14 @@ plugins = [
         "*/dashboard/manifest.json",
         "*/dashboard/dist/*",
         "*/dashboard/dist/**/*",
      +  # Plugin discovery (hermes_cli/plugins.py) reads a plugin.yaml/plugin.yml
      +  # manifest from each bundled plugin directory to register it. Wheels only
      +  # carry files declared here, so without this glob the wheel ships every
      +  # plugin's Python code but none of its manifests — the scan finds zero
      +  # plugins and all gateway platforms fail with "No adapter available for
      +  # <platform>" (#34034), web-search providers go missing (#28149), etc.
      +  "**/plugin.yaml",
      +  "**/plugin.yml",
       ]
       
       [tool.setuptools.packages.find]
    • tests/test_packaging_metadata.py
      @@ -20,3 +20,42 @@ def test_manifest_includes_bundled_skills():
       
           assert "graft skills" in manifest
           assert "graft optional-skills" in manifest
      +
      +
      +def test_bundled_plugin_manifests_ship_in_both_wheel_and_sdist():
      +    """Regression test for #34034 / #28149.
      +
      +    Plugin discovery (hermes_cli/plugins.py) registers each bundled plugin by
      +    reading its ``plugin.yaml`` / ``plugin.yml`` manifest. Those manifests are
      +    data files, not Python modules, so they only reach installed packages when
      +    declared explicitly:
      +
      +    - wheel  -> ``[tool.setuptools.package-data]`` ``plugins`` glob
      +    - sdist  -> ``MANIFEST.in`` (Homebrew and other downstream packagers build
      +                from the sdist)
      +
      +    v0.15.0 declared neither, so the wheel shipped every adapter's Python code
      +    but none of its manifests, and *every* gateway platform failed with
      +    "No adapter available for <platform>". Both channels must cover manifests.
      +    """
      +    # There must actually be manifests on disk for the globs to match.
      +    on_disk = list((REPO_ROOT / "plugins").rglob("plugin.yaml")) + list(
      +        (REPO_ROOT / "plugins").rglob("plugin.yml")
      +    )
      +    assert on_disk, "expected bundled plugin manifests under plugins/"
      +
      +    # Wheel channel: package-data must declare a glob that matches plugin
      +    # manifests anywhere under the plugins package.
      +    data = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8"))
      +    plugins_pkg_data = data["tool"]["setuptools"]["package-data"].get("plugins", [])
      +    assert any(
      +        g.endswith("plugin.yaml") or g.endswith("plugin.yml")
      +        for g in plugins_pkg_data
      +    ), "pyproject package-data 'plugins' must ship plugin.yaml/plugin.yml (wheel)"
      +
      +    # Sdist channel: MANIFEST.in must recursively include the manifests so
      +    # downstream packagers building from the sdist also get them.
      +    manifest = (REPO_ROOT / "MANIFEST.in").read_text(encoding="utf-8")
      +    assert "recursive-include plugins" in manifest and "plugin.yaml" in manifest, (
      +        "MANIFEST.in must recursive-include plugins plugin.yaml/plugin.yml (sdist)"
      +    )

2 PRs closed without merging

From the close comments: done elsewhere 2

  • #28162 fix(packaging): ship plugin.yaml manifests in wheel and sdist (#28149) · done elsewhere → 2765b02, #34484
  • #28170 fix(packaging): ship plugin.yaml manifests in wheel and sdist · done elsewhere → 2765b02, #34484
Closed issues · 1
  • Closed#28149Brew bottle missing plugin.yaml manifests for web search providers
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
skills
Merged PRs
#34484
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
29 May 2026

For your agent

The same facts, typed.