Skip to content

feat(cli): add packaged hermes-webui CLI entry point (#6739) - #6742

Closed
webtecnica wants to merge 2 commits into
nesquena:masterfrom
webtecnica:feat/6739-cli-entry
Closed

webtecnica wants to merge 2 commits into
nesquena:masterfrom
webtecnica:feat/6739-cli-entry

Conversation

@webtecnica

Copy link
Copy Markdown
Contributor

Summary

Adds a packaged CLI entry point for the installed hermes-webui distribution, closing #6739.

  • Declares a [project.scripts] console script in pyproject.toml:
    hermes-webui = "server:main" — the pip-installed equivalent of running
    python server.py from a source checkout. It hooks into the same startup
    path (server.main()) used by the existing launch surface, so behavior is
    identical to python server.py / python -m server.
  • Adds tests/test_cli_entry_point.py, a smoke test that guards the wiring:
    the console script is declared in packaging metadata, the declared
    server:main target resolves to a callable, and — when the package is
    installed in the test environment — the real importlib.metadata entry
    point resolves end-to-end.

Change

  • pyproject.toml: new [project.scripts] table (hermes-webui = "server:main")
  • tests/test_cli_entry_point.py: new smoke test file

No other changes (no bootstrap/ctl.sh modifications).

Verification

  • pytest tests/test_cli_entry_point.py → 2 passed, 1 skipped (entry-point
    wiring test runs when the package is installed)
  • pip install -e . in a clean venv → generates the hermes-webui binary
  • Booted the installed command: hermes-webui printed
    Hermes Web UI listening on http://127.0.0.1:8899 and served HTTP 200
  • python3 scripts/ruff_lint.py --diff → no new violations on added/modified lines

Closes #6739

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Summary

Reading the complete two-file diff at 69ee8b671, both full changed files on PR HEAD, pyproject.toml on origin/master, and the existing startup target in server.py, the packaging change is coherent. The console-script target is included in the distribution as a top-level module, resolves to the same main() used by source-checkout launches, and adds no second startup path. I do not see a code-level blocker.

Code reference

The key packaging contract is at pyproject.toml:24-34:

[project.scripts]
hermes-webui = "server:main"

[tool.setuptools]
include-package-data = true
packages = ["api", "static"]
py-modules = ["bootstrap", "server", "mcp_server"]

That last line matters: server is already shipped as a py-module, so the generated launcher will not point at a source-only module omitted from the wheel. At server.py:547, main() owns startup, and server.py:748-749 makes the existing script surface call that exact function. The new entry point therefore preserves host, port, authentication warnings, watcher startup, signal handling, and orderly shutdown rather than duplicating any of them.

The test coverage is also scoped to the actual contract. tests/test_cli_entry_point.py:34-45 reads the TOML declaration and imports server:main; tests/test_cli_entry_point.py:48-62 additionally checks the installed console_scripts metadata when the package is installed.

Diagnosis / recommendation

This is ready from a source-review perspective. Keeping the command as a no-argument alias for server.main() is the right narrow scope for #6739. CLI option parsing, symlink installation, or a second wrapper module would add behavior that the issue does not require.

One non-blocking observation: the end-to-end metadata test intentionally skips in a source-only environment. That is acceptable because the declaration and target tests remain active, while packaging CI or an installed editable environment exercises the final entry-point load.

Verification step

The current GitHub matrix is green. For release acceptance, build the wheel, install it into an empty environment, confirm the generated hermes-webui command resolves to server:main, and verify it starts on the default port 8787 and exits through the same shutdown path. I did not execute PR-authored code; this review is read-only.

@nesquena-hermes nesquena-hermes added the size:M Medium PR (≤10 files, ≤250 LOC) label Aug 4, 2026

@nesquena-hermes nesquena-hermes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @webtecnica — a packaged hermes-webui console script is a nice ergonomic win, and the packaging itself is complete (the wheel carries all tracked API modules + 94 static assets, and python server.py / python -m server stay healthy). One BRICK to fix in the entry-point target:

Must-fix (BRICK, reproduced) — route through bootstrap:main, not server:main

pyproject.toml:29. server:main bypasses bootstrap's agent-interpreter selection. Verified on a clean wheel install: the UI starts healthy, but every chat fails because the wheel interpreter can't import run_agent (ModuleNotFoundError: dotenv) — server:main never runs discover_launcher_python() / ensure_python_has_webui_deps(). Booting via bootstrap selects the existing agent venv and works.

Fix:

  1. pyproject.toml:29hermes-webui = "bootstrap:main" (so startup runs the launcher-python discovery + dep-ensure before launching the server), matching the python server.py path's effective behavior.
  2. tests/test_cli_entry_point.py:24 — change EXPECTED_TARGET to "bootstrap:main" and update the server-specific test descriptions.

Confirm bootstrap.main is the right launch entry (it's what the source-checkout launch path uses) and re-push — I'll re-gate a clean-wheel chat round-trip.

@webtecnica

Copy link
Copy Markdown
Contributor Author

What Changed

Addressed the CHANGES_REQUESTED review — the packaged hermes-webui console script now routes through the bootstrap entry point instead of server:main:

  • pyproject.toml: hermes-webui = "bootstrap:main" — the generated console script now calls bootstrap.main(), which runs discover_launcher_python() and ensure_python_has_webui_deps() before launching the server. This selects the agent venv interpreter, so chat works on a clean wheel install.
  • tests/test_cli_entry_point.py: EXPECTED_TARGET = "bootstrap:main", and the module/test docstrings updated to describe the bootstrap launch path (all assertions derive from EXPECTED_TARGET, so the wiring guard now checks the corrected target).

Root Cause

server:main bypasses bootstrap's agent-interpreter selection. On a clean wheel install the UI starts, but every chat fails with ModuleNotFoundError: dotenv because the wheel interpreter never runs discover_launcher_python() / ensure_python_has_webui_deps(). Booting via bootstrap:main selects the existing agent venv and works — matching the effective behavior of the python server.py source-checkout path.

Verification

  • pytest tests/test_cli_entry_point.py -q -p no:cacheprovider → 2 passed, 1 skipped (entry-point wiring test runs when the package is installed).
  • bootstrap.main resolves and is callable (import bootstrap; callable(bootstrap.main) → True).
  • git diff --stat: pyproject.toml (7 lines) + tests/test_cli_entry_point.py (14 lines) — surgical, no other changes.

Ready for re-gate of the clean-wheel chat round-trip.

@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a packaged hermes-webui console command targeting the existing bootstrap launcher, together with source- and metadata-level smoke tests.

  • Registers hermes-webui = "bootstrap:main" in project packaging metadata.
  • Adds tests for the declaration, callable target, and optional installed entry-point resolution.
  • The new tests do not currently exercise an installed console script in maintained CI and import an environment-mutating module in-process.

Confidence Score: 4/5

The PR appears safe to merge, with non-blocking test-isolation and packaged-command coverage gaps worth addressing.

The console-script declaration targets a packaged callable, but CI never executes the installed-entry-point assertion and the source-resolution test can overwrite the shared pytest environment through bootstrap's import-time dotenv loading.

Files Needing Attention: tests/test_cli_entry_point.py

Important Files Changed

Filename Overview
pyproject.toml Registers the console-script target; existing packaging configuration and wheel tests include bootstrap.py and the required runtime tree.
tests/test_cli_entry_point.py Adds useful wiring checks, but installed-package coverage always skips in maintained test environments and the callable check imports bootstrap with process-wide environment side effects.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  P["pip install hermes-webui"] --> C["generated hermes-webui command"]
  C --> B["bootstrap.main()"]
  B --> D["discover agent and Python"]
  D --> E["ensure WebUI dependencies"]
  E --> S["launch server.py"]
Loading

Reviews (1): Last reviewed commit: "fix(cli): route hermes-webui entry throu..." | Re-trigger Greptile

Comment on lines +60 to +62
ep = _installed_entry_point()
if ep is None:
pytest.skip("hermes-webui not installed in this test environment")

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.

P2 Installed entry-point test always skips

The maintained CI and local test runners do not install the project, so this branch always skips the only check that resolves the packaged entry point. Regressions in generated or installed console-script wiring therefore pass while the source-metadata checks remain green.

Knowledge Base Used: Developer Tooling: Lint Gates, Markdown Check, Workspace Repair, and the Pytest Harness

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

def test_console_script_target_resolves_to_callable():
"""The declared module:attr target imports and is callable."""
module_name, _, attr = EXPECTED_TARGET.partition(":")
module = importlib.import_module(module_name)

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.

P2 Callable check mutates test environment

If a checkout contains a .env file, importing bootstrap executes _load_repo_dotenv() in the shared pytest process and overwrites the harness's isolated state and configuration variables. Later tests then inherit developer configuration instead of the isolated test paths, creating order-dependent behavior and potential access to non-test data.

Knowledge Base Used: Developer Tooling: Lint Gates, Markdown Check, Workspace Repair, and the Pytest Harness

nesquena-hermes added a commit that referenced this pull request Aug 17, 2026
…-webui entry point (#6742) (#7108)

* fix(goals): delegate profile evaluation to native manager

Use Hermes' context-local home override to run profile-scoped goal operations through the native GoalManager, preserving current judge, wait, and failure semantics while retaining the explicit-DB legacy fallback.

* docs(goals): describe profile ownership boundary

* fix(goals): gate native profile persistence capability

* feat(cli): add packaged hermes-webui CLI entry point (#6739)

* fix(cli): route hermes-webui entry through bootstrap:main for wheel install (#6742)

* docs(changelog): note #6899 profile goal isolation + #6742 hermes-webui entry point

* test(goals): guard hermes_cli import with importorskip for CI (agent not installed)

#6899's native-contract tests imported hermes_cli unconditionally, failing
CI with ModuleNotFoundError. Match the repo's established importorskip pattern
so they skip cleanly when the agent isn't installed and run when it is.
Co-authored-by: ticketclosed-wontfix

---------

Co-authored-by: Nick <202622897+ticketclosed-wontfix@users.noreply.github.com>
Co-authored-by: webtecnica <webtecnica@gmail.com>
Co-authored-by: n <a@n>
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Shipped in experimental release exp-v0.52.237. The packaged hermes-webui console entry point now routes through bootstrap:main, so a wheel install runs agent-interpreter discovery + dependency validation before launching — a real chat turn completes end-to-end from a clean wheel env. Thanks @webtecnica!

alai04 pushed a commit to alai04/hermes-webui that referenced this pull request Aug 31, 2026
…+ hermes-webui entry point (nesquena#6742) (nesquena#7108)

* fix(goals): delegate profile evaluation to native manager

Use Hermes' context-local home override to run profile-scoped goal operations through the native GoalManager, preserving current judge, wait, and failure semantics while retaining the explicit-DB legacy fallback.

* docs(goals): describe profile ownership boundary

* fix(goals): gate native profile persistence capability

* feat(cli): add packaged hermes-webui CLI entry point (nesquena#6739)

* fix(cli): route hermes-webui entry through bootstrap:main for wheel install (nesquena#6742)

* docs(changelog): note nesquena#6899 profile goal isolation + nesquena#6742 hermes-webui entry point

* test(goals): guard hermes_cli import with importorskip for CI (agent not installed)

nesquena#6899's native-contract tests imported hermes_cli unconditionally, failing
CI with ModuleNotFoundError. Match the repo's established importorskip pattern
so they skip cleanly when the agent isn't installed and run when it is.
Co-authored-by: ticketclosed-wontfix

---------

Co-authored-by: Nick <202622897+ticketclosed-wontfix@users.noreply.github.com>
Co-authored-by: webtecnica <webtecnica@gmail.com>
Co-authored-by: n <a@n>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M Medium PR (≤10 files, ≤250 LOC)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

packaged hermes-webui CLI entry point

2 participants