diff --git a/acp_registry/agent.json b/acp_registry/agent.json index f6d9d7a574e..b94a48e089f 100644 --- a/acp_registry/agent.json +++ b/acp_registry/agent.json @@ -8,8 +8,9 @@ "authors": ["Nous Research"], "license": "MIT", "distribution": { - "npx": { - "package": "@nousresearch/hermes-agent-acp@0.13.0" + "uvx": { + "package": "hermes-agent[acp]==0.13.0", + "args": ["hermes-acp"] } } } diff --git a/docs/plans/acp-registry-zed-integration.md b/docs/plans/acp-registry-zed-integration.md deleted file mode 100644 index 05358f7afed..00000000000 --- a/docs/plans/acp-registry-zed-integration.md +++ /dev/null @@ -1,97 +0,0 @@ -# Hermes Agent ACP Registry + Zed Integration Implementation Plan - -> For Hermes: Use subagent-driven-development skill to implement this plan task-by-task. - -Goal: Make Hermes Agent installable from Zed's official ACP Registry, so users can add Hermes from Zed's agent panel without manual custom `agent_servers` settings. - -Architecture: Use the official `agentclientprotocol/registry` flow instead of the deprecated Zed Agent Server Extension path. Ship a registry-compatible launcher distribution, advertise valid ACP auth methods during every handshake, validate against official registry schema and auth CI, then submit a registry PR for `hermes-agent`. - -Tech Stack: Hermes Agent Python package, ACP adapter (`hermes acp` / `hermes-acp`), npm launcher package, official ACP Registry JSON schema, Zed external agent UI. - ---- - -## Compliance constraints - -- Zed v0.221.x+ prefers the ACP Registry for external agents; do not use Zed Agent Server Extensions for distribution. -- Registry repo layout is top-level `hermes-agent/agent.json` and `hermes-agent/icon.svg`, not `agents/hermes-agent/`. -- Registry metadata must use the official schema: `id`, `name`, `version`, `description`, `distribution`, optional `repository`, `website`, `authors`, `license`. -- Distribution must be exactly one supported type unless intentionally adding another: `binary`, `npx`, or `uvx`. -- Hermes must advertise at least one valid `authMethods` entry on a clean first-run handshake. No-provider/no-auth is not compliant. -- Terminal Auth must be explicit and deterministic: `id: hermes-setup`, `type: terminal`, `args: ["--setup"]`. -- `icon.svg` must be 16x16, square, monochrome, and use only `currentColor` / `none` for fill/stroke; no gradients, hardcoded colors, or `url(#...)` paints. -- ACP server mode must reserve stdout for JSON-RPC only. Diagnostics/logs go to stderr. `--version`, `--check`, and `--setup` are not server mode and may print normally. -- Published npm package must exist and be runnable before the upstream registry PR references it. - ---- - -## Tasks - -1. Verify/implement ACP auth methods. - - Always return terminal setup auth from `initialize()`. - - Return configured provider auth in addition when provider credentials are resolvable. - - Add tests for provider auth, terminal fallback auth, and authenticate behavior before/after provider setup. - -2. Add non-interactive ACP commands. - - `hermes acp --version` - - `hermes acp --check` - - `hermes acp --setup` - - Same behavior through `hermes-acp`. - -3. Build npm launcher package. - - Package: `@nousresearch/hermes-agent-acp@`. - - Command: `uvx --from 'hermes-agent[acp]==' hermes-acp ...args`. - - Fallback: `uv tool run --from ...` when only `uv` exists. - - Forward all args, including `--setup`, `--version`, and `--check`. - - Preserve stdio in server mode. - - Print actionable stderr error when `uv`/`uvx` is missing. - -4. Replace local registry metadata. - - Convert `acp_registry/agent.json` from old command-style local format to official registry schema. - - Replace `acp_registry/icon.svg` with compliant 16x16 currentColor icon. - - Add tests rejecting old fields (`schema_version`, `display_name`, `distribution.type`, `distribution.command`) and unknown distribution keys. - -5. Update docs. - - Zed docs show official ACP Registry install first: Add Agent / `zed: acp registry` -> search Hermes Agent -> install. - - Manual `agent_servers` JSON remains only as local-development fallback. - - Docs include `uv` prerequisite and `hermes acp --check` troubleshooting. - - Developer internals mention npm launcher and terminal setup auth. - -6. Validate locally. - - `python -m pytest tests/acp/test_auth.py tests/acp/test_server.py tests/acp/test_entry.py tests/acp/test_registry_manifest.py -q` - - `(cd packages/hermes-agent-acp && npm test)` - - `(cd packages/hermes-agent-acp && npm pack --dry-run)` - - `hermes acp --version` - - `hermes acp --check` - -7. Validate against official registry tooling before PR. - - In a clone/fork of `agentclientprotocol/registry`, copy files into top-level `hermes-agent/`. - - Run official dry-run build, e.g. `uv run --with jsonschema .github/workflows/build_registry.py --dry-run`. - - Run official auth check if available, e.g. `.github/workflows/scripts/run-registry-docker.sh python3 .github/workflows/verify_agents.py --auth-check`. - - Fix any schema/auth issues before submitting. - -8. Publish and submit. - - Publish `@nousresearch/hermes-agent-acp@`. - - Verify published package: - - `npx @nousresearch/hermes-agent-acp@ --version` - - `npx @nousresearch/hermes-agent-acp@ --check` - - ACP initialize/authMethods smoke test through the published package. - - Open PR to `agentclientprotocol/registry` adding `hermes-agent/agent.json` and `hermes-agent/icon.svg`. - -9. End-to-end Zed verification. - - Install Hermes Agent through Zed's ACP Registry. - - Start a Hermes thread. - - Verify workspace cwd, file tools, terminal tools, tool rendering, and approval prompts. - ---- - -## Acceptance criteria - -- Hermes appears in Zed's official ACP Registry UI. -- Install starts Hermes without custom Zed settings. -- Registry CI passes schema and auth validation. -- ACP stdout remains JSON-RPC only; all logs go to stderr. -- `authMethods` are present and valid on clean first run. -- Terminal Auth can launch Hermes provider/model setup with `--setup`. -- Zed workspace cwd is honored by Hermes file and terminal tools. -- Docs describe registry install first and manual custom config second. -- Package/release automation prevents registry entries from pointing at unpublished versions. diff --git a/packages/hermes-agent-acp/README.md b/packages/hermes-agent-acp/README.md deleted file mode 100644 index b3e9eea0afa..00000000000 --- a/packages/hermes-agent-acp/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# @nousresearch/hermes-agent-acp - -ACP launcher for Hermes Agent. - -This package is intended for clients such as Zed that install agents through the official ACP Registry. It launches the Python Hermes ACP server with: - -```bash -uvx --from 'hermes-agent[acp]==0.13.0' hermes-acp -``` - -## Requirements - -- Node.js 18+ -- `uv` or `uvx` on PATH -- Hermes provider credentials configured with `hermes model`, or through Hermes' normal `~/.hermes/.env` / `~/.hermes/config.yaml` setup - -## Commands - -```bash -npx @nousresearch/hermes-agent-acp@0.13.0 --version -npx @nousresearch/hermes-agent-acp@0.13.0 --check -npx @nousresearch/hermes-agent-acp@0.13.0 --setup -npx @nousresearch/hermes-agent-acp@0.13.0 -``` - -Normal no-argument mode reserves stdout for ACP JSON-RPC traffic. Diagnostics are emitted on stderr by Hermes. diff --git a/packages/hermes-agent-acp/bin/hermes-agent-acp.js b/packages/hermes-agent-acp/bin/hermes-agent-acp.js deleted file mode 100755 index b9d571d3550..00000000000 --- a/packages/hermes-agent-acp/bin/hermes-agent-acp.js +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -const { spawn, spawnSync } = require('node:child_process'); - -const HERMES_AGENT_VERSION = '0.13.0'; -const HERMES_SPEC = `hermes-agent[acp]==${HERMES_AGENT_VERSION}`; - -function commandExists(command) { - const result = spawnSync(command, ['--version'], { stdio: 'ignore' }); - return !result.error && result.status === 0; -} - -function buildCommand(argv, exists = commandExists) { - if (exists('uvx')) { - return { - command: 'uvx', - args: ['--from', HERMES_SPEC, 'hermes-acp', ...argv], - }; - } - - if (exists('uv')) { - return { - command: 'uv', - args: ['tool', 'run', '--from', HERMES_SPEC, 'hermes-acp', ...argv], - }; - } - - return null; -} - -function main() { - const argv = process.argv.slice(2); - const command = buildCommand(argv); - - if (!command) { - console.error('Hermes Agent ACP requires uv or uvx to launch the Python package.'); - console.error('Install uv from https://docs.astral.sh/uv/getting-started/installation/'); - console.error('Then retry this agent from Zed.'); - process.exit(127); - } - - const child = spawn(command.command, command.args, { - stdio: 'inherit', - env: process.env, - }); - - child.on('error', (error) => { - console.error(`Failed to start Hermes Agent ACP: ${error.message}`); - process.exit(1); - }); - - child.on('exit', (code, signal) => { - if (signal) { - process.kill(process.pid, signal); - return; - } - process.exit(code ?? 0); - }); -} - -if (require.main === module) { - main(); -} - -module.exports = { buildCommand, HERMES_AGENT_VERSION, HERMES_SPEC }; diff --git a/packages/hermes-agent-acp/package.json b/packages/hermes-agent-acp/package.json deleted file mode 100644 index 224bb275b77..00000000000 --- a/packages/hermes-agent-acp/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@nousresearch/hermes-agent-acp", - "version": "0.13.0", - "description": "ACP launcher for Hermes Agent", - "bin": { - "hermes-agent-acp": "bin/hermes-agent-acp.js" - }, - "files": [ - "bin/", - "README.md" - ], - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/NousResearch/hermes-agent.git", - "directory": "packages/hermes-agent-acp" - }, - "engines": { - "node": ">=18" - }, - "scripts": { - "test": "node --test" - } -} diff --git a/packages/hermes-agent-acp/test/launcher.test.js b/packages/hermes-agent-acp/test/launcher.test.js deleted file mode 100644 index 7a338305e56..00000000000 --- a/packages/hermes-agent-acp/test/launcher.test.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -const test = require('node:test'); -const assert = require('node:assert/strict'); -const { buildCommand, HERMES_SPEC } = require('../bin/hermes-agent-acp.js'); - -test('uses uvx when available and forwards args', () => { - const command = buildCommand(['--version'], (name) => name === 'uvx'); - - assert.equal(command.command, 'uvx'); - assert.deepEqual(command.args, ['--from', HERMES_SPEC, 'hermes-acp', '--version']); -}); - -test('falls back to uv tool run and forwards setup args', () => { - const command = buildCommand(['--setup'], (name) => name === 'uv'); - - assert.equal(command.command, 'uv'); - assert.deepEqual(command.args, ['tool', 'run', '--from', HERMES_SPEC, 'hermes-acp', '--setup']); -}); - -test('returns null when neither uvx nor uv is available', () => { - assert.equal(buildCommand([], () => false), null); -}); diff --git a/scripts/release.py b/scripts/release.py index 17a8dffd31e..621ebddec95 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -34,12 +34,10 @@ REPO_ROOT = Path(__file__).resolve().parent.parent VERSION_FILE = REPO_ROOT / "hermes_cli" / "__init__.py" PYPROJECT_FILE = REPO_ROOT / "pyproject.toml" -# ACP Registry assets that must stay version-locked with pyproject.toml. -# tests/acp/test_registry_manifest.py enforces this lockstep, so the release -# bump touches all four files atomically. +# ACP Registry manifest must stay version-locked with pyproject.toml. +# tests/acp/test_registry_manifest.py enforces this lockstep so the release +# bump touches both files atomically. ACP_REGISTRY_MANIFEST = REPO_ROOT / "acp_registry" / "agent.json" -ACP_NPM_PACKAGE_JSON = REPO_ROOT / "packages" / "hermes-agent-acp" / "package.json" -ACP_NPM_LAUNCHER = REPO_ROOT / "packages" / "hermes-agent-acp" / "bin" / "hermes-agent-acp.js" # ────────────────────────────────────────────────────────────────────── # Git email → GitHub username mapping @@ -1168,38 +1166,23 @@ def update_version_files(semver: str, calver_date: str): def _update_acp_registry_versions(semver: str) -> None: - """Bump the ACP Registry manifest, npm package, and launcher in lockstep. + """Bump the ACP Registry manifest's version + uvx package pin in lockstep + with pyproject. - Skips silently if any of the files are missing — the ACP Registry assets - landed mid-cycle and older release branches may not have them. + Skips silently if the manifest is missing — older release branches predate + the ACP Registry assets. """ if ACP_REGISTRY_MANIFEST.exists(): manifest = json.loads(ACP_REGISTRY_MANIFEST.read_text(encoding="utf-8")) manifest["version"] = semver - npx = manifest.get("distribution", {}).get("npx", {}) - if "package" in npx: - npx["package"] = f"@nousresearch/hermes-agent-acp@{semver}" + uvx = manifest.get("distribution", {}).get("uvx", {}) + if "package" in uvx: + uvx["package"] = f"hermes-agent[acp]=={semver}" # Preserve trailing newline + 2-space indent the file already uses. ACP_REGISTRY_MANIFEST.write_text( json.dumps(manifest, indent=2) + "\n", encoding="utf-8" ) - if ACP_NPM_PACKAGE_JSON.exists(): - package = json.loads(ACP_NPM_PACKAGE_JSON.read_text(encoding="utf-8")) - package["version"] = semver - ACP_NPM_PACKAGE_JSON.write_text( - json.dumps(package, indent=2) + "\n", encoding="utf-8" - ) - - if ACP_NPM_LAUNCHER.exists(): - launcher = ACP_NPM_LAUNCHER.read_text(encoding="utf-8") - launcher = re.sub( - r"const HERMES_AGENT_VERSION\s*=\s*'[^']+';", - f"const HERMES_AGENT_VERSION = '{semver}';", - launcher, - ) - ACP_NPM_LAUNCHER.write_text(launcher, encoding="utf-8") - def build_release_artifacts(semver: str) -> list[Path]: """Build sdist/wheel artifacts for the current release. diff --git a/tests/acp/test_registry_manifest.py b/tests/acp/test_registry_manifest.py index 134cb5415ae..633b4a8494c 100644 --- a/tests/acp/test_registry_manifest.py +++ b/tests/acp/test_registry_manifest.py @@ -39,36 +39,30 @@ def test_agent_json_matches_official_registry_required_fields(): assert set(data["distribution"]) <= ALLOWED_DISTRIBUTIONS -def test_agent_json_uses_npx_distribution_without_local_command_fields(): +def test_agent_json_uses_uvx_distribution_without_local_command_fields(): data = _manifest() - assert set(data["distribution"]) == {"npx"} - assert set(data["distribution"]["npx"]) == {"package"} - assert data["distribution"]["npx"]["package"] == ( - f"@nousresearch/hermes-agent-acp@{data['version']}" - ) + assert set(data["distribution"]) == {"uvx"} + uvx = data["distribution"]["uvx"] + # Schema allows {package, args, env}; we use {package, args}. + assert set(uvx) <= {"package", "args", "env"} + assert "package" in uvx + assert uvx["package"] == f"hermes-agent[acp]=={data['version']}" + assert uvx["args"] == ["hermes-acp"] + # Old command-shape fields must not leak back in. assert "type" not in data["distribution"] assert "command" not in data["distribution"] - assert "args" not in data["distribution"] def test_agent_json_version_matches_pyproject(): assert _manifest()["version"] == _pyproject_version() -def test_npm_launcher_versions_match_pyproject_and_manifest(): - version = _pyproject_version() - package = json.loads( - (ROOT / "packages" / "hermes-agent-acp" / "package.json").read_text(encoding="utf-8") - ) - launcher = (ROOT / "packages" / "hermes-agent-acp" / "bin" / "hermes-agent-acp.js").read_text( - encoding="utf-8" - ) - - assert package["version"] == version - assert f"const HERMES_AGENT_VERSION = '{version}';" in launcher - assert _manifest()["distribution"]["npx"]["package"] == ( - f"@nousresearch/hermes-agent-acp@{version}" +def test_agent_json_pins_uvx_package_to_pyproject_version(): + """The registry CI rejects ``@latest`` and floating pins; the manifest must + always reference the exact PyPI version listed in pyproject.toml.""" + assert _manifest()["distribution"]["uvx"]["package"] == ( + f"hermes-agent[acp]=={_pyproject_version()}" ) diff --git a/tests/scripts/test_release_acp_registry.py b/tests/scripts/test_release_acp_registry.py index a2e71bd0b19..4d20cda25bd 100644 --- a/tests/scripts/test_release_acp_registry.py +++ b/tests/scripts/test_release_acp_registry.py @@ -1,11 +1,11 @@ """Tests for the ACP Registry version-lockstep bump in scripts/release.py. -The official ACP Registry manifest, the @nousresearch/hermes-agent-acp npm -package, and the npm launcher's HERMES_AGENT_VERSION constant must all match -``pyproject.toml`` exactly — ``tests/acp/test_registry_manifest.py`` enforces -this at lint time. The release script is the single place that bumps them in -lockstep with pyproject; if that bump ever silently breaks, weekly releases -fail the manifest test until someone hand-edits four files. +The official ACP Registry manifest must match ``pyproject.toml`` exactly — +``tests/acp/test_registry_manifest.py`` enforces this at lint time, and the +upstream registry CI rejects ``@latest`` / floating pins. The release script +is the single place that bumps the manifest in lockstep with pyproject; if +that bump ever silently breaks, weekly releases fail the manifest test +until someone hand-edits the JSON. """ from __future__ import annotations @@ -25,26 +25,14 @@ def _load_release_module(monkeypatch, tmp_root: Path): module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) - # Repoint every REPO_ROOT-derived path at our temp tree. monkeypatch.setattr(module, "REPO_ROOT", tmp_root) monkeypatch.setattr( module, "ACP_REGISTRY_MANIFEST", tmp_root / "acp_registry" / "agent.json" ) - monkeypatch.setattr( - module, - "ACP_NPM_PACKAGE_JSON", - tmp_root / "packages" / "hermes-agent-acp" / "package.json", - ) - monkeypatch.setattr( - module, - "ACP_NPM_LAUNCHER", - tmp_root / "packages" / "hermes-agent-acp" / "bin" / "hermes-agent-acp.js", - ) return module -def _write_fixture(root: Path, version: str) -> None: - """Write the three ACP-registry files we expect release.py to bump.""" +def _write_manifest(root: Path, version: str) -> None: manifest_dir = root / "acp_registry" manifest_dir.mkdir(parents=True) (manifest_dir / "agent.json").write_text( @@ -55,7 +43,10 @@ def _write_fixture(root: Path, version: str) -> None: "version": version, "description": "test", "distribution": { - "npx": {"package": f"@nousresearch/hermes-agent-acp@{version}"} + "uvx": { + "package": f"hermes-agent[acp]=={version}", + "args": ["hermes-acp"], + } }, }, indent=2, @@ -64,29 +55,9 @@ def _write_fixture(root: Path, version: str) -> None: encoding="utf-8", ) - package_dir = root / "packages" / "hermes-agent-acp" - (package_dir / "bin").mkdir(parents=True) - (package_dir / "package.json").write_text( - json.dumps( - { - "name": "@nousresearch/hermes-agent-acp", - "version": version, - "bin": {"hermes-agent-acp": "bin/hermes-agent-acp.js"}, - }, - indent=2, - ) - + "\n", - encoding="utf-8", - ) - (package_dir / "bin" / "hermes-agent-acp.js").write_text( - f"const HERMES_AGENT_VERSION = '{version}';\n" - f"const HERMES_SPEC = `hermes-agent[acp]==${{HERMES_AGENT_VERSION}}`;\n", - encoding="utf-8", - ) - -def test_update_acp_registry_versions_bumps_all_three_files(monkeypatch, tmp_path): - _write_fixture(tmp_path, "0.13.0") +def test_update_acp_registry_versions_bumps_manifest_and_pin(monkeypatch, tmp_path): + _write_manifest(tmp_path, "0.13.0") module = _load_release_module(monkeypatch, tmp_path) module._update_acp_registry_versions("0.14.0") @@ -95,41 +66,27 @@ def test_update_acp_registry_versions_bumps_all_three_files(monkeypatch, tmp_pat (tmp_path / "acp_registry" / "agent.json").read_text(encoding="utf-8") ) assert manifest["version"] == "0.14.0" - assert ( - manifest["distribution"]["npx"]["package"] - == "@nousresearch/hermes-agent-acp@0.14.0" - ) - - package = json.loads( - ( - tmp_path / "packages" / "hermes-agent-acp" / "package.json" - ).read_text(encoding="utf-8") - ) - assert package["version"] == "0.14.0" - - launcher = ( - tmp_path / "packages" / "hermes-agent-acp" / "bin" / "hermes-agent-acp.js" - ).read_text(encoding="utf-8") - assert "const HERMES_AGENT_VERSION = '0.14.0';" in launcher - assert "0.13.0" not in launcher + assert manifest["distribution"]["uvx"]["package"] == "hermes-agent[acp]==0.14.0" + # args stay untouched so we don't accidentally rewrite them. + assert manifest["distribution"]["uvx"]["args"] == ["hermes-acp"] -def test_update_acp_registry_versions_is_silent_when_files_missing( +def test_update_acp_registry_versions_is_silent_when_manifest_missing( monkeypatch, tmp_path ): - """Older release branches predate the ACP Registry assets — must no-op.""" + """Older release branches predate the ACP Registry asset — must no-op.""" module = _load_release_module(monkeypatch, tmp_path) # No fixture written; function should not raise. module._update_acp_registry_versions("0.14.0") -def test_update_version_files_bumps_acp_assets_alongside_pyproject( +def test_update_version_files_bumps_manifest_alongside_pyproject( monkeypatch, tmp_path ): """End-to-end: update_version_files() is the function release.py actually - calls, so it must drive the ACP bump too.""" - _write_fixture(tmp_path, "0.13.0") + calls, so it must drive the manifest bump too.""" + _write_manifest(tmp_path, "0.13.0") (tmp_path / "pyproject.toml").write_text( '[project]\nname = "hermes-agent"\nversion = "0.13.0"\n', encoding="utf-8" ) @@ -153,7 +110,4 @@ def test_update_version_files_bumps_acp_assets_alongside_pyproject( (tmp_path / "acp_registry" / "agent.json").read_text(encoding="utf-8") ) assert manifest["version"] == "0.14.0" - assert ( - manifest["distribution"]["npx"]["package"] - == "@nousresearch/hermes-agent-acp@0.14.0" - ) + assert manifest["distribution"]["uvx"]["package"] == "hermes-agent[acp]==0.14.0" diff --git a/website/docs/developer-guide/acp-internals.md b/website/docs/developer-guide/acp-internals.md index f688869033d..89ae398b6af 100644 --- a/website/docs/developer-guide/acp-internals.md +++ b/website/docs/developer-guide/acp-internals.md @@ -31,7 +31,7 @@ hermes acp / hermes-acp / python -m acp_adapter -> acp.run_agent(agent, use_unstable_protocol=True) ``` -The Zed ACP Registry path launches the same adapter through `npx @nousresearch/hermes-agent-acp@`, which delegates to `uvx --from 'hermes-agent[acp]==' hermes-acp`. +The Zed ACP Registry path launches the same adapter through `uvx --from 'hermes-agent[acp]==' hermes-acp`, pointed at the `hermes-agent` PyPI release. Stdout is reserved for ACP JSON-RPC transport. Human-readable logs go to stderr. diff --git a/website/docs/user-guide/features/acp.md b/website/docs/user-guide/features/acp.md index b55664191c3..92a755c9ada 100644 --- a/website/docs/user-guide/features/acp.md +++ b/website/docs/user-guide/features/acp.md @@ -45,13 +45,13 @@ This installs the `agent-client-protocol` dependency and enables: - `hermes-acp` - `python -m acp_adapter` -For Zed registry installs, Zed launches Hermes through the official ACP Registry entry. That entry uses the npm launcher package `@nousresearch/hermes-agent-acp`, which runs: +For Zed registry installs, Zed launches Hermes through the official ACP Registry entry. That entry uses a `uvx` distribution that runs: ```bash uvx --from 'hermes-agent[acp]==' hermes-acp ``` -Make sure `uv` or `uvx` is available on `PATH` before using the registry install path. +Make sure `uv` is available on `PATH` before using the registry install path. ## Launching the ACP server @@ -150,13 +150,13 @@ acp_registry/icon.svg The upstream registry PR copies those files into the top-level `hermes-agent/` directory in `agentclientprotocol/registry`. -The registry entry uses an `npx` distribution: +The registry entry uses a `uvx` distribution that points directly at the `hermes-agent` PyPI release: ```text -npx @nousresearch/hermes-agent-acp@ +uvx --from 'hermes-agent[acp]==' hermes-acp ``` -The launcher then runs `hermes-acp` from the matching Python package version. +The registry CI verifies that the pinned version exists on PyPI, so the manifest's `version` and uvx `package` pin must always match `pyproject.toml`. `scripts/release.py` keeps them in lockstep automatically. ## Configuration and credentials @@ -207,7 +207,7 @@ Check: - For manual/local development, verify the custom `agent_servers` command points to `hermes acp`. - Hermes is installed and on your PATH. - The ACP extra is installed (`pip install -e '.[acp]'`). -- `uv` or `uvx` is installed if launching from the official Zed registry entry. +- `uv` is installed if launching from the official Zed registry entry. ### ACP starts but immediately errors