feat(plugins): manifest v2 — schema version, api_version, inter-plugin deps, pip-dependency declaration seam, config schema (#64165)

Additive plugin.yaml v2 fields (all optional; v1 manifests unchanged forever):

- manifest_version: manifest FILE-FORMAT version (absent = 1). Deliberately
  split from api_version per the round-2 design correction. Newer-than-
  supported versions load with a warning, unknown fields ignored.
- api_version: runtime plugin API generation the plugin targets (integer).
- requires_plugins: advisory inter-plugin deps ({id, version_range?}).
  Missing dep = warn + still load (ctx.has_plugin() runtime probe added).
  Load ORDER is dependency-respecting: graphlib topological sort, stable
  alphabetical tiebreak; cycles warn and fall back to alphabetical.
- python_dependencies: declared pip requirements — VALIDATED AND SURFACED
  ONLY (loader warning + install-time printout + doctor checks with a pip
  install hint). Never auto-installed: the isolation design for the install
  seam (#15220) is an explicitly deferred follow-up per the round-2 review.
- config_schema: JSON-schema-ish description of plugins.entries.<id>.settings
  keys; validated at load, mismatches are actionable warnings naming the key
  and expected type — never load failures.
- Formalized metadata: license, homepage, tags.
- Unknown manifest fields warn-don't-fail (debug-level for v1 manifests).
- hermes plugins doctor gains v2 checks: future manifest_version, invalid
  api_version, dep declarations, unpinned/missing python_dependencies,
  unknown config_schema types.
- Docs: manifest v2 reference table in the developer-guide plugins index,
  including the explicit pip-seam isolation deferral and the note that
  #64166 packs build on these fields.
- Tests: tests/hermes_cli/test_plugin_manifest_v2.py (19 tests) covering v1
  regression, v2 parse, unknown-field warn, dep order, cycle fallback,
  config_schema warnings, and the surfaced-not-installed pip seam.
This commit is contained in:
Teknium
2026-08-12 17:20:07 -07:00
parent c89ca9c4bf
commit bd6dcd4bd5
5 changed files with 959 additions and 0 deletions
+28
View File
@@ -331,6 +331,32 @@ def _missing_requires_env_names(manifest: dict) -> list[str]:
return [s["name"] for s in env_specs if s.get("name") and not get_env_value(s["name"])]
def _print_python_dependencies(manifest: dict, console) -> None:
"""Surface declared python_dependencies at install time (#64165).
Declaration seam ONLY — Hermes never auto-installs plugin pip
dependencies (isolation design deferred; see #64165 / #15220). We print
the declared requirements with a copy-pasteable install hint.
"""
deps = manifest.get("python_dependencies") or []
if not isinstance(deps, list):
return
deps = [d.strip() for d in deps if isinstance(d, str) and d.strip()]
if not deps:
return
plugin_name = manifest.get("name", "this plugin")
console.print(
f"\n[bold]{plugin_name}[/bold] declares Python dependencies "
"(not installed automatically):"
)
for dep in deps:
console.print(f" - {dep}")
console.print(
"[dim]Install them yourself if needed: "
f"pip install {' '.join(repr(d) for d in deps)}[/dim]\n"
)
def _prompt_plugin_env_vars(manifest: dict, console) -> None:
"""Prompt for required environment variables declared in plugin.yaml.
@@ -835,6 +861,8 @@ def cmd_install(
_prompt_plugin_env_vars(installed_manifest, console)
_print_python_dependencies(installed_manifest, console)
_display_after_install(target, identifier)
should_enable = enable