fix(hindsight): declare full local_embedded pip deps + actionable upstream packaging-gap error - #57243
fix(hindsight): declare full local_embedded pip deps + actionable upstream packaging-gap error#57243agy590 wants to merge 1 commit into
Conversation
…tream packaging-gap error
When users switch to mode: local_embedded after a fresh plugin install, they
hit 'ModuleNotFoundError: No module named hindsight' at the
'from hindsight import HindsightEmbedded' line in _get_client. The plugin's
pip_dependencies only declared 'hindsight-client' (the cloud-mode HTTP
client), but the local_embedded code path imports from 'hindsight' (a
top-level package shipped inside the 'hindsight-all' wheel whose own
setuptools metadata does not declare that bare package as installed), so
neither a fresh install nor 'pip install hindsight-all' makes the import
succeed.
This commit:
1. Adds 'hindsight-embed>=0.8.4' and 'hindsight-api-slim[embedded-db]>=0.8.4'
to the plugin's pip_dependencies, matching what the setup wizard
(post_setup) installs by hand. A fresh plugin install now brings the
daemon manager and the embedded PostgreSQL backend automatically.
2. Wraps the 'from hindsight import HindsightEmbedded' import in a clear
error message that names the upstream packaging gap (vectorize-io/hindsight
0.8.4) and lists the three known workarounds in preference order, so the
next person who hits this gets actionable guidance instead of a bare
ModuleNotFoundError.
3. Adds a 'Local Embedded - Ollama / OpenAI-Compatible Notes' section to
README.md covering:
- required env vars for pointing embeddings at Ollama
(HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai and friends - not read from
config.json, only from env)
- the Ollama 0.24.x + structured-output + concurrency hang and the
*_MAX_CONCURRENT=1 + LLM_TIMEOUT=300 mitigations
- the retain_async=True recommendation (default False blocks the client
for minutes waiting on fact-extraction + embedding + consolidation)
- the upstream hindsight-all packaging note with the three workarounds
Tested end-to-end (2026-07-03, WSL2 + Ollama 0.24, host RAM 8GB / WSL 6GB)Verified the full local_embedded pipeline after this PR: Environment
Results
What this PR fixes: the packaging-gap failure mode that prevents the daemon from starting at all. Pre-PR: fresh What this PR does NOT fix: fact-extract quality / LLM capacity. That is bounded by (1) the LLM model the user wires up via the Reproduction (verified): $ uv pip install --python ~/.hermes/hermes-agent/venv/bin/python3 hermes-agent
$ ollama pull qwen2.5:3b && ollama pull nomic-embed-text
$ ~/.hermes/hermes-agent/venv/bin/hindsight-api --daemon --port 9177 &
$ curl -s http://127.0.0.1:9177/health
{"status":"healthy","database":"connected"}
$ python3 -c "from hindsight.client_wrapper import Hindsight; \
c=Hindsight(base_url='http://127.0.0.1:9177'); \
print(c.recall(bank_id='hermes', query='test', budget='low'))"
# returns semantically retrieved facts within ~3sSide-note for review: the recall-side path (embed → pgvector → cross-encoder rerank) works end-to-end with |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for documenting a real local-embedded setup gap. The current implementation needs rework before it can safely land.
Problems
hermes_cli/memory_setup.py:219and:277install everyplugin.yamldependency beforepost_setupselects a Hindsight mode. Addinghindsight-embedandhindsight-api-slimatplugins/memory/hindsight/plugin.yaml:16-17would therefore install local-only packages for cloud and local-external users.- The new import wrapper is after the existing runtime probe.
_check_local_runtime()importshindsightatplugins/memory/hindsight/__init__.py:135-140, and_get_client()raises at:1016-1021when that probe fails; the proposed actionable ImportError would not be reached for the reported missing-module path. - The added bare
>=0.8.4constraints conflict with the bounded-dependency policy inAGENTS.md:561-576. - No regression test accompanies the new failure path; the existing embedded-client test mocks the runtime probe as successful at
tests/plugins/memory/test_hindsight_provider.py:420-441.
Suggested changes
- Resolve local dependencies only after
local_embeddedis selected, surface the diagnostic from the pre-import failure path, and add a hermetic missing-import test.
Automated hermes-sweeper review.
| # (which separately pulls a fuller set including torch for sentence-transformers). | ||
| - "hindsight-client>=0.6.1" | ||
| - "hindsight-embed>=0.8.4" | ||
| - "hindsight-api-slim[embedded-db]>=0.8.4" |
There was a problem hiding this comment.
hermes_cli/memory_setup.py:219 and :277 install all manifest dependencies before post_setup selects cloud, local_external, or local_embedded. This makes this local-only package install for cloud and external users too; keep dependency selection mode-specific inside the local-embedded setup path.
|
Thanks for tackling this @agy590 — one heads-up before this lands. I checked the published wheels (0.8.5): The tricky part is that the correct package ( |
Guard local_embedded memory tools from repeating the daemon startup wait when the embedded runtime is broken or still booting. Probe sentence_transformers before daemon startup, track startup failure state, and fail fast during the cooldown with log/status remediation hints. Refs upstream Hindsight lifecycle/dependency work: - NousResearch#57243 - NousResearch#51066 - NousResearch#60358 (cherry picked from commit dc92daf653f7cf583e72037d53bb1eda720f9cba) (cherry picked from commit 4b6d16ff8aaf7f14cdac8e2ea84867837ffcc27a)
Guard local_embedded memory tools from repeating the daemon startup wait when the embedded runtime is broken or still booting. Probe sentence_transformers before daemon startup, track startup failure state, and fail fast during the cooldown with log/status remediation hints. Refs upstream Hindsight lifecycle/dependency work: - NousResearch#57243 - NousResearch#51066 - NousResearch#60358 (cherry picked from commit dc92daf653f7cf583e72037d53bb1eda720f9cba)
What changed
Three files in
plugins/memory/hindsight/:plugin.yaml— addedhindsight-embed>=0.8.4andhindsight-api-slim[embedded-db]>=0.8.4topip_dependencies. The setup wizard (post_setup) was already installing these by hand; making them declarative fixes the silent "fresh install + edit-config mode=local_embedded + retry → ModuleNotFoundError" footgun.__init__.py— wrapped thefrom hindsight import HindsightEmbeddedimport in a try/except that raises a clear, actionable error message pointing at the three known workarounds for the upstreamhindsight-allpackaging gap (the barehindsight/package is shipped inside the wheel but its metadata does not declare it as a dependency, so neitherpip install hindsight-allnor a transitive resolution makes the import succeed).README.md— added a "Local Embedded — Ollama / OpenAI-Compatible Notes" section covering:~/.hermes/hindsight/config.json— only from env)*_MAX_CONCURRENT=1+LLM_TIMEOUT=300mitigations that have been stable on CPU-only Linuxretain_async=Truerecommendation (the defaultFalseblocks the client for minutes waiting on fact-extraction + embedding + consolidation)hindsight-allpackaging note with the three workarounds, in preference orderWhy a PR and not a fresh issue
The packaging bug lives upstream in
vectorize-io/hindsight. This PR does the parts that can be fixed inside hermes-agent: declaring the dependencies the wizard was already installing, and giving the next person who hits this a useful error message plus a documentation page they can land on.Reproduction (before this PR)
After:
hindsight-embedandhindsight-api-slim[embedded-db]are auto-installed by the plugin load, and the import either succeeds (when the upstream fix lands) or raises an actionable error pointing at workarounds.Scope notes
hindsight-allas a dependency — that package has the packaging bug and would pull 1.5 GB of torch/CUDA dependencies for every plugin user.retain_asyncdefault behavior — defaults stay the same, the README documents the recommendation._get_client.Test plan
pip_dependencies, verifyhindsight-embedandhindsight-api-slim[embedded-db]get installed automaticallysite-packages/hindsight/, verify the new error message is what a user sees (actionable + lists 3 workarounds)from hindsight_client import Hindsight) path is untouched