-
Notifications
You must be signed in to change notification settings - Fork 0
[NA] [SDK] fix: entry point resolves to module so pip-install works (0.1.1) + pip E2E coverage #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4b9c04f
[NA] [SDK] fix: entry point must resolve to the module (pip-install s…
JetoPistola fce9056
ci: update build-job entry-point assert to expect module (opik_hermes)
JetoPistola 601827e
ci: extract entry-point verification into a shared script (address re…
JetoPistola 3c85d9c
ci: drop stray heredoc 'PY' left after inlining assert_entrypoint call
JetoPistola 7b42789
ci: make assert_entrypoint.py the single behavioral entry-point check…
JetoPistola File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # E2E image for the PIP-INSTALL path: install opik-hermes from a locally-built | ||
| # wheel into Hermes' venv, so the plugin is discovered via its | ||
| # ``hermes_agent.plugins`` entry point — NOT copied into a plugins directory. | ||
| # This exercises the entry-point discovery path a `pip install opik-hermes` user | ||
| # gets, complementing run_e2e.sh's directory-install path. | ||
| # | ||
| # The build context must contain the built wheel at dist/*.whl (run_e2e_wheel.sh | ||
| # builds it before `docker build`). | ||
| ARG HERMES_IMAGE=nousresearch/hermes-agent:latest | ||
| FROM ${HERMES_IMAGE} | ||
|
|
||
| COPY dist/ /tmp/opik-hermes-dist/ | ||
| RUN /opt/hermes/.venv/bin/python -m pip install --no-cache-dir /tmp/opik-hermes-dist/*.whl \ | ||
| || uv pip install --python /opt/hermes/.venv/bin/python --no-cache-dir /tmp/opik-hermes-dist/*.whl | ||
|
|
||
| # Build-time guard for the entry-point-loading contract: Hermes does | ||
| # ep.load() then getattr(<result>, "register"), so the entry point must resolve | ||
| # to the MODULE (opik = opik_hermes), not the function (opik_hermes:register). | ||
| # A regression here is exactly the bug this path exists to catch. | ||
| RUN /opt/hermes/.venv/bin/python - <<'PY' | ||
| import types | ||
| from importlib.metadata import entry_points, version | ||
| e = next(x for x in entry_points(group="hermes_agent.plugins") if x.name == "opik") | ||
| loaded = e.load() | ||
| assert isinstance(loaded, types.ModuleType), ( | ||
| f"entry point must load the module, got {type(loaded)!r} — " | ||
| "check pyproject: opik = opik_hermes (not opik_hermes:register)" | ||
| ) | ||
| assert callable(getattr(loaded, "register", None)), "loaded module has no register()" | ||
| print("opik-hermes", version("opik-hermes"), "entry point ->", loaded.__name__, "register OK") | ||
| PY | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #!/usr/bin/env bash | ||
| # End-to-end test of the PIP-INSTALL path: build the wheel from source, install | ||
| # it into the latest Hermes image, and drive a turn against a mock LLM + mock | ||
| # Opik — asserting the plugin was discovered via its hermes_agent.plugins ENTRY | ||
| # POINT (no plugin directory copied in) and produced the expected spans. | ||
| # | ||
| # Complements run_e2e.sh (which tests the directory-install path). Both install | ||
| # methods are supported, so CI exercises both. No real keys; the agent has no | ||
| # internet at run time. | ||
| # | ||
| # Run from the repo root: bash e2e/run_e2e_wheel.sh | ||
| set -euo pipefail | ||
|
|
||
| REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" | ||
| NET="opik-hermes-e2e-wheel" | ||
| HERMES_IMAGE="${HERMES_IMAGE:-nousresearch/hermes-agent:latest}" | ||
| WORK="$(mktemp -d)" | ||
| JOURNAL_DIR="$WORK/journal" | ||
| HERMES_HOME="$WORK/hermes" | ||
| CTX="$WORK/ctx" | ||
| mkdir -p "$JOURNAL_DIR" "$HERMES_HOME" "$CTX" | ||
|
|
||
| cleanup() { | ||
| docker rm -f e2e-w-mock-llm e2e-w-mock-opik e2e-w-hermes >/dev/null 2>&1 || true | ||
| docker network rm "$NET" >/dev/null 2>&1 || true | ||
| } | ||
| trap cleanup EXIT | ||
|
|
||
| echo "==> pulling $HERMES_IMAGE" | ||
| docker pull -q "$HERMES_IMAGE" >/dev/null | ||
|
|
||
| # --- build the wheel from source into the docker build context --------------- | ||
| echo "==> building opik-hermes wheel from source" | ||
| python3 -m venv "$WORK/.venv" | ||
| "$WORK/.venv/bin/pip" install -q -U build | ||
| "$WORK/.venv/bin/python" -m build --wheel --outdir "$CTX/dist" "$REPO_ROOT" >/dev/null | ||
| cp "$REPO_ROOT/e2e/Dockerfile.wheel" "$CTX/Dockerfile" | ||
| echo "==> wheel: $(ls "$CTX/dist")" | ||
|
|
||
| # --- build the Hermes image with the wheel pip-installed (ep assert at build) - | ||
| E2E_IMAGE="opik-hermes-e2e-wheel:local" | ||
| echo "==> building $E2E_IMAGE (opik-hermes pip-installed)" | ||
| docker build -q --build-arg HERMES_IMAGE="$HERMES_IMAGE" \ | ||
| -f "$CTX/Dockerfile" -t "$E2E_IMAGE" "$CTX" >/dev/null | ||
|
|
||
| echo "==> private network (no internet; only mocks reachable)" | ||
| docker network create "$NET" >/dev/null | ||
|
|
||
| echo "==> mock-opik + mock-llm" | ||
| docker run -d --name e2e-w-mock-opik --network "$NET" \ | ||
| -e MOCK_OPIK_JOURNAL=/journal/opik-journal.jsonl -e MOCK_OPIK_PORT=5173 \ | ||
| -v "$REPO_ROOT/e2e/mock_opik_server.py:/srv/s.py:ro" \ | ||
| -v "$JOURNAL_DIR:/journal" \ | ||
| python:3.12-slim python /srv/s.py >/dev/null | ||
|
|
||
| docker run -d --name e2e-w-mock-llm --network "$NET" \ | ||
| -e MOCK_LLM_PORT=18790 \ | ||
| -v "$REPO_ROOT/e2e/mock_llm_server.py:/srv/s.py:ro" \ | ||
| python:3.12-slim python /srv/s.py >/dev/null | ||
|
|
||
| # --- Hermes home: config + .env, NO plugin dir (entry-point discovery only) -- | ||
| cat > "$HERMES_HOME/config.yaml" <<YAML | ||
| model: | ||
| default: gpt-5 | ||
| provider: openai-api | ||
| base_url: http://e2e-w-mock-llm:18790/v1 | ||
| providers: {} | ||
| plugins: | ||
| enabled: | ||
| - opik | ||
| agent: | ||
| max_turns: 4 | ||
| terminal: | ||
| backend: local | ||
| YAML | ||
|
|
||
| cat > "$HERMES_HOME/.env" <<ENV | ||
| OPENAI_API_KEY=mock-key | ||
| OPENAI_BASE_URL=http://e2e-w-mock-llm:18790/v1 | ||
| OPIK_URL_OVERRIDE=http://e2e-w-mock-opik:5173/api | ||
| OPIK_PROJECT_NAME=hermes-e2e-wheel | ||
| HERMES_OPIK_DEBUG=true | ||
| ENV | ||
| # NOTE: deliberately NO `cp observability/opik` here — the plugin must be found | ||
| # via the pip entry point, which is the whole point of this path. | ||
|
|
||
| echo "==> running one Hermes turn (plugin from pip entry point)" | ||
| if command -v timeout >/dev/null 2>&1; then TIMEOUT="timeout 180"; else TIMEOUT=""; fi | ||
| $TIMEOUT docker run --rm --name e2e-w-hermes --network "$NET" \ | ||
| -e HERMES_UID=0 -e HERMES_GID=0 \ | ||
| -v "$HERMES_HOME:/opt/data" \ | ||
| "$E2E_IMAGE" \ | ||
| sh -c ' | ||
| hermes chat -q "Compute 2 to the power 10 and report the number." \ | ||
| --provider openai-api --model gpt-5 2>&1 | tail -20 | ||
| ' < /dev/null || echo "(hermes turn exited non-zero / timed out; assertion judges from the journal)" | ||
|
|
||
| sleep 3 | ||
| cp "$JOURNAL_DIR/opik-journal.jsonl" /tmp/opik-e2e-wheel-journal.jsonl 2>/dev/null || true | ||
| echo "==> journal saved ($(wc -l < "$JOURNAL_DIR/opik-journal.jsonl" 2>/dev/null || echo 0) rows)" | ||
|
|
||
| echo "==> asserting journal" | ||
| MOCK_OPIK_JOURNAL="$JOURNAL_DIR/opik-journal.jsonl" python3 "$REPO_ROOT/e2e/assert_journal.py" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.