Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions hermes_cli/memory_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def _install_dependencies(provider_name: str) -> None:
"honcho-ai": "honcho",
"mem0ai": "mem0",
"hindsight-client": "hindsight_client",
"hindsight-all": "hindsight",
}

# Check which packages are missing
Expand All @@ -166,9 +167,18 @@ def _install_dependencies(provider_name: str) -> None:
return

print(f"\n Installing dependencies: {', '.join(missing)}")

import shutil
uv_path = shutil.which("uv")
if not uv_path:
print(f" ⚠ uv not found — cannot install dependencies")
print(f" Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh")
print(f" Then re-run: hermes memory setup")
return

try:
subprocess.run(
[sys.executable, "-m", "pip", "install", "--quiet"] + missing,
[uv_path, "pip", "install", "--python", sys.executable, "--quiet"] + missing,
check=True, timeout=120,
capture_output=True,
)
Expand All @@ -178,10 +188,10 @@ def _install_dependencies(provider_name: str) -> None:
stderr = (e.stderr or b"").decode()[:200]
if stderr:
print(f" {stderr}")
print(f" Run manually: pip install {' '.join(missing)}")
print(f" Run manually: uv pip install --python {sys.executable} {' '.join(missing)}")
except Exception as e:
print(f" ⚠ Install failed: {e}")
print(f" Run manually: pip install {' '.join(missing)}")
print(f" Run manually: uv pip install --python {sys.executable} {' '.join(missing)}")

# Also show external dependencies (non-pip) if any
ext_deps = meta.get("external_dependencies", [])
Expand Down Expand Up @@ -275,7 +285,6 @@ def cmd_setup(args) -> None:

schema = provider.get_config_schema() if hasattr(provider, "get_config_schema") else []

# Provider config section
provider_config = config["memory"].get(name, {})
if not isinstance(provider_config, dict):
provider_config = {}
Expand All @@ -290,11 +299,25 @@ def cmd_setup(args) -> None:
key = field["key"]
desc = field.get("description", key)
default = field.get("default")
# Dynamic default: look up default from another field's value
default_from = field.get("default_from")
if default_from and isinstance(default_from, dict):
ref_field = default_from.get("field", "")
ref_map = default_from.get("map", {})
ref_value = provider_config.get(ref_field, "")
if ref_value and ref_value in ref_map:
default = ref_map[ref_value]
is_secret = field.get("secret", False)
choices = field.get("choices")
env_var = field.get("env_var")
url = field.get("url")

# Skip fields whose "when" condition doesn't match
when = field.get("when")
if when and isinstance(when, dict):
if not all(provider_config.get(k) == v for k, v in when.items()):
continue

if choices and not is_secret:
# Use curses picker for choice fields
choice_items = [(c, "") for c in choices]
Expand Down
74 changes: 67 additions & 7 deletions plugins/memory/hindsight/README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,98 @@
# Hindsight Memory Provider

Long-term memory with knowledge graph, entity resolution, and multi-strategy retrieval. Supports cloud and local modes.
Long-term memory with knowledge graph, entity resolution, and multi-strategy retrieval. Supports cloud and local (embedded) modes.

## Requirements

- Cloud: `pip install hindsight-client` + API key from [app.hindsight.vectorize.io](https://app.hindsight.vectorize.io)
- Local: `pip install hindsight` + LLM API key for embeddings
- **Cloud:** API key from [ui.hindsight.vectorize.io](https://ui.hindsight.vectorize.io)
- **Local:** API key for a supported LLM provider (OpenAI, Anthropic, Gemini, Groq, MiniMax, or Ollama). Embeddings and reranking run locally — no additional API keys needed.

## Setup

```bash
hermes memory setup # select "hindsight"
```

Or manually:
The setup wizard will install dependencies automatically via `uv` and walk you through configuration.

Or manually (cloud mode with defaults):
```bash
hermes config set memory.provider hindsight
echo "HINDSIGHT_API_KEY=your-key" >> ~/.hermes/.env
```

### Cloud Mode

Connects to the Hindsight Cloud API. Requires an API key from [ui.hindsight.vectorize.io](https://ui.hindsight.vectorize.io).

### Local Mode

Runs an embedded Hindsight server with built-in PostgreSQL. Requires an LLM API key (e.g. Groq, OpenAI, Anthropic) for memory extraction and synthesis. The daemon starts automatically in the background on first use and stops after 5 minutes of inactivity.

Daemon startup logs: `~/.hermes/logs/hindsight-embed.log`
Daemon runtime logs: `~/.hindsight/profiles/<profile>.log`

## Config

Config file: `$HERMES_HOME/hindsight/config.json` (or `~/.hindsight/config.json` legacy)
Config file: `~/.hermes/hindsight/config.json`

### Connection

| Key | Default | Description |
|-----|---------|-------------|
| `mode` | `cloud` | `cloud` or `local` |
| `bank_id` | `hermes` | Memory bank identifier |
| `budget` | `mid` | Recall thoroughness: `low`/`mid`/`high` |
| `api_url` | `https://api.hindsight.vectorize.io` | API URL (cloud mode) |
| `api_url` | `http://localhost:8888` | API URL (local mode, unused — daemon manages its own port) |

### Memory

| Key | Default | Description |
|-----|---------|-------------|
| `bank_id` | `hermes` | Memory bank name |
| `budget` | `mid` | Recall thoroughness: `low` / `mid` / `high` |

### Integration

| Key | Default | Description |
|-----|---------|-------------|
| `memory_mode` | `hybrid` | How memories are integrated into the agent |
| `prefetch_method` | `recall` | Method for automatic context injection |

**memory_mode:**
- `hybrid` — automatic context injection + tools available to the LLM
- `context` — automatic injection only, no tools exposed
- `tools` — tools only, no automatic injection

**prefetch_method:**
- `recall` — injects raw memory facts (fast)
- `reflect` — injects LLM-synthesized summary (slower, more coherent)

### Local Mode LLM

| Key | Default | Description |
|-----|---------|-------------|
| `llm_provider` | `openai` | LLM provider: `openai`, `anthropic`, `gemini`, `groq`, `minimax`, `ollama` |
| `llm_model` | per-provider | Model name (e.g. `gpt-4o-mini`, `openai/gpt-oss-120b`) |

The LLM API key is stored in `~/.hermes/.env` as `HINDSIGHT_LLM_API_KEY`.

## Tools

Available in `hybrid` and `tools` memory modes:

| Tool | Description |
|------|-------------|
| `hindsight_retain` | Store information with auto entity extraction |
| `hindsight_recall` | Multi-strategy search (semantic + entity graph) |
| `hindsight_reflect` | Cross-memory synthesis (LLM-powered) |

## Environment Variables

| Variable | Description |
|----------|-------------|
| `HINDSIGHT_API_KEY` | API key for Hindsight Cloud |
| `HINDSIGHT_LLM_API_KEY` | LLM API key for local mode |
| `HINDSIGHT_API_URL` | Override API endpoint |
| `HINDSIGHT_BANK_ID` | Override bank name |
| `HINDSIGHT_BUDGET` | Override recall budget |
| `HINDSIGHT_MODE` | Override mode (`cloud` / `local`) |
Loading