Metadata-Version: 2.4
Name: prajnyavan
Version: 0.3.5
Summary: Persistent, emotionally-weighted memory for any LLM
Author: Prajnyavan Team
License-Expression: MIT
Project-URL: Homepage, https://github.com/prajnyavan/prajnyavan
Project-URL: Repository, https://github.com/prajnyavan/prajnyavan
Project-URL: Issues, https://github.com/prajnyavan/prajnyavan/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: requests>=2.28
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: cohere
Requires-Dist: cohere>=4.0; extra == "cohere"
Provides-Extra: local
Requires-Dist: sentence-transformers>=2.2; extra == "local"
Provides-Extra: uds
Requires-Dist: requests-unixsocket>=0.3; extra == "uds"
Provides-Extra: async
Requires-Dist: httpx>=0.27; extra == "async"
Provides-Extra: pydantic
Requires-Dist: pydantic>=2.0; extra == "pydantic"
Provides-Extra: langchain
Requires-Dist: langchain>=0.2; extra == "langchain"
Provides-Extra: llamaindex
Requires-Dist: llama-index>=0.10; extra == "llamaindex"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Provides-Extra: all
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: cohere>=4.0; extra == "all"
Requires-Dist: sentence-transformers>=2.2; extra == "all"
Requires-Dist: requests-unixsocket>=0.3; extra == "all"
Requires-Dist: httpx>=0.27; extra == "all"
Requires-Dist: pydantic>=2.0; extra == "all"
Requires-Dist: langchain>=0.2; extra == "all"
Requires-Dist: llama-index>=0.10; extra == "all"

# Prajnyavan - The Memory Layer for AI

Persistent, emotionally-weighted memory for any LLM. Zero-config locally, honest about what is stable today.

---
## Why Prajnyavan
Launch-facing benchmark snapshot from the current tree:

| metric | current evidence | status |
| --- | --- | --- |
| token compression | 96 vs 1,348 tokens | 51% smaller context |
| GPU proxy savings | 165 vs 442 tokens | 86% lower proxy attention cost |
| storage per memory | 3,274 vs 3,298 bytes | smaller than naive JSON |
| import throughput | best measured local run: 500 memories in 0.3258s | 1,534.80 memories/sec |
| RAM delta for 1,000 memories | 47.88 MB | under the 100 MB gate |

Notes:
- Token, GPU, storage, and import numbers are measured from the local benchmark and CI harness in this repo.
- Throughput depends on hardware, process model, and payload shape. Treat the table above as a measured run, not a universal guarantee.
- `linux_verified` is still pending in `benchmarks/results.json`, so the RAM benchmark should be treated as provisional until the Linux artifact is committed back.

Installed-wheel throughput check:
```bash
prajnyavan benchmark import --memories 500 --json
```

Repo-checkout benchmark:
```bash
python scripts/import_benchmark.py --memories 500
```

The `scripts/` and `evals/` commands below are source-tree tools. They are not installed into the PyPI wheel. For an installed-wheel health check, use `prajnyavan smoke`, `prajnyavan doctor`, `prajnyavan benchmark import`, and the Python round-trip examples in this README.

### Windows-first release
- `0.3.5` keeps the trust-release focus and closes the last `0.3.4` wheel-level gaps: legacy Python SDK compatibility is restored for the main CRUD helpers, portable import parity is fixed, metrics auth is enforced, and the release QA artifacts now cover the exact regressions that surfaced in the hard review.
- If you try it, please file bugs, onboarding friction, and DX feedback at the GitHub issues page linked on PyPI.
- Release leadership summary: [docs/RELEASE_READINESS_0_3_5.md](/E:/BRAIN/brain-db/docs/RELEASE_READINESS_0_3_5.md)

### Roadmap to #1
- The active strategy is now recorded in-tree: `docs/NO1_EXECUTION_PLAN.md`.
- The execution tracker is now recorded in-tree: `docs/NO1_EXECUTION_TRACKER.md`.
- The strategic order is fixed: trust, isolation, evaluation, retrieval quality, efficiency, then production hardening.

---
## Zero-config quickstart (5 lines)
```bash
pip install prajnyavan
prajnyavan dev                   # auto-starts the real local daemon
```
```python
from prajnyavan import MemoryClient
mem = MemoryClient.dev(user_id="user_123")   # zero config, hash embeddings

@mem.wrap_llm(user_id="user_123")
def chat(prompt):
    return your_llm_call(prompt)
```
- No Docker or manual tokens locally. CLI control files live in `~/.prajnyavan`; the daemon stores its durable state in the OS app-data directory.
- Set OPENAI_API_KEY or COHERE_API_KEY to auto-upgrade embeddings; otherwise hash embeddings keep deps at zero.
- For full features in one go: `pip install "prajnyavan[all]"`.

### 0.3.x SDK Compatibility
During the `0.3.x` line, the preferred Python SDK shape is identity-first:

```python
mem.store("user_123", "hello memory")
mem.search("user_123", "hello")
mem.bulk_store("user_123", [{"content": "hello"}])
```

The client now also accepts the older `0.3.2`-style content/query-first forms for the main CRUD helpers so existing apps do not break on a patch upgrade:

```python
mem.store("hello memory", user_id="user_123")
mem.search("hello", user_id="user_123")
mem.bulk_store([{"content": "hello"}], user_id="user_123")
mem.search_batch(["hello", "world"], user_id="user_123")
mem.store_profile(user_id="user_123", profile_data={"timezone": "Asia/Kathmandu"})
```

Identity-first is still the long-term contract, but the compatibility shim is kept in place for the `0.3.x` line.

### Portable Home Layout
If you set `PRAJNYAVAN_HOME=/custom/path`, Prajnyavan keeps its local control files under that directory:

- `dev.json`: active daemon URL, local token, and mode metadata
- `prajnyavan.pid`: active daemon PID
- `startup.lock`: single-startup lock file
- `prajnyavan.lock`: daemon runtime lock path
- `daemon.log`: daemon stdout/stderr log
- `models/`: optional local embedding model cache

When `MemoryClient.dev()` or `prajnyavan dev` starts the real daemon in portable mode, it also creates:

- `runtime/appdata/`
- `runtime/localappdata/`

Those runtime folders are used as the daemon's isolated OS app-data roots so the durable database, WAL, archive, auth DB, and other service files stay inside the portable home instead of leaking into the machine-wide profile.

### Supported launch contract
The launch-ready contract is intentionally narrow:

- `store`
- `search`
- `get_context`
- `get_memory`
- `update`
- `delete`
- `export/import`
- sessions / SSE
- `status`, `doctor`, `smoke`

Maintenance endpoints such as compaction and forced WAL recovery are currently disabled by default until that path is hardened. Trust comes before surface area.

### Retrieval profiles
`get_context()` now supports explicit runtime-cost profiles so developers can choose their cost/quality point instead of guessing:

- `edge`: smallest recall window, fewer entity groups, lowest token spend
- `standard`: balanced default with moderate recall depth and context budget
- `quality`: broader recall window, more entity groups, and the fullest context budget

```python
ctx = mem.get_context("user_123", "what matters here?", max_tokens=300, profile="edge")
print(ctx["profile_used"], ctx["tokens_used"], ctx["omitted_facts_count"])
for fact in ctx["facts"]:
    print(fact["layer"], fact["token_cost"], fact["content"])
```

### One-minute PyPI smoke test
```bash
prajnyavan smoke
```

### Serious release QA
For a stricter source-tree release pass, run the maintainer QA harness below. It starts an isolated real daemon, exercises the CLI, sync SDK, async SDK, restart persistence, invalid-auth boundaries, and import throughput, then emits one JSON report.

```bash
python scripts/run_release_qa.py --output release_qa.json
```

What it automates:
- `status`, `doctor`, `smoke`, and `benchmark import`
- sync SDK round-trip and export/import
- async bulk load against the real daemon
- restart persistence on the same isolated home
- invalid-token rejection
- profile budget ordering for `edge` / `standard` / `quality`

What still needs manual or environment-specific proof:
- clean-machine PyPI install on a host without a source checkout
- upgrade compatibility from older published versions
- long-running soak tests
- edge-device RAM verification on the actual target hardware

### Windows release packaging
Use the repo script below for Windows release artifacts. It prefers a normal CPython from the `py` launcher, creates a dedicated `.release-venv`, then runs `build` and `twine check` without depending on embedded Python runtimes on `PATH`.

```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\build_release.ps1
```

Or, if you want the equivalent Python round-trip:
```bash
python - <<'PY'
from prajnyavan import MemoryClient
mem = MemoryClient.dev(user_id="smoke")
mid = mem.store("smoke", "Hello, memory!", importance=0.7)
print("stored", mid)
print("search", mem.search("smoke", "hello", exact_match=True))
print("emotion", mem.get_emotion())
PY
```

### Repo eval runner
Requires a source checkout of this repository:

```bash
cargo build --release -p prajnyavan_service
python evals/run_evals.py --eval all --output evals/results/v033.json
```

This runs profile-aware checks for:
- entity disambiguation
- contradiction handling
- stale-memory suppression
- preference recall
- emotional retrieval bias
- multi-agent shared-memory correctness
- token efficiency vs raw-history / vector / summary baselines
- long-horizon memory checks across 100 turns

Current local proof snapshot from [evals/results/v033.json](/E:/BRAIN/brain-db/evals/results/v033.json):

| eval | edge | standard | quality |
| --- | --- | --- | --- |
| entity disambiguation | 1.00 | 1.00 | 1.00 |
| contradiction handling | 1.00 | 1.00 | 1.00 |
| stale suppression | 1.00 | 1.00 | 1.00 |
| preference recall | 1.00 | 1.00 | 1.00 |
| multi-agent shared memory | 1.00 | 1.00 | 1.00 |
| emotional bias (positive) | 1.00 | n/a | n/a |
| emotional bias (negative) | 1.00 | n/a | n/a |
| long-horizon memory | 1.00 | 1.00 | 1.00 |

Turn-50 token comparison from [evals/results/v033.json](/E:/BRAIN/brain-db/evals/results/v033.json):

| system | tokens at turn 50 |
| --- | --- |
| raw history | 2773 |
| vector baseline | 289 |
| summary baseline | 128 |
| Prajnyavan edge | 14 |
| Prajnyavan standard | 25 |
| Prajnyavan quality | 36 |

These eval results come from a source-built local run on March 28, 2026. They supersede the earlier `v030` snapshot, but Linux benchmark verification in [benchmarks/results.json](/E:/BRAIN/brain-db/benchmarks/results.json) is still pending.

Focused recheck after the `apply_profile_fact_floor = 0.35` change:
- [evals/results/long_horizon_recheck.json](/E:/BRAIN/brain-db/evals/results/long_horizon_recheck.json) confirms `long_horizon_memory.standard.score = 1.0` and `quality.score = 1.0` on March 27, 2026.
- The eval runner now enables request-aware token refresh against the real daemon, so multi-user eval sweeps do not fail with stale single-user auth.
- The source-tree release QA harness now completes with `ok = true`, including same-root restart persistence against the rebuilt Windows daemon binary.
- The refreshed [evals/results/v033.json](/E:/BRAIN/brain-db/evals/results/v033.json) artifact now also confirms `entity_disambiguation = 1.0` and `long_horizon_memory = 1.0` across all three context profiles.

### Embedding options
| provider | quality | deps | cost | note |
| --- | --- | --- | --- | --- |
| hash (default) | low | none | $0 | deterministic, zero setup |
| local (sentence-transformers) | medium | torch + model download | $0 | set embedding_provider="local" |
| openai | high | openai>=1.0 | $ | set OPENAI_API_KEY |
| cohere | high | cohere>=4.0 | $ | set COHERE_API_KEY |

### GPU & storage tradeoffs
Smaller context windows cut GPU work because transformer attention scales quadratically with sequence length. Smaller embeddings cut storage directly, and Prajnyavan already benefits from compact on-disk formats in the semantic store and archive layers.

| context tokens | relative attention ops | GPU time (relative) | cost vs 2000 tokens |
| --- | --- | --- | --- |
| 2000 | 4,000,000 | 1.0x | baseline |
| 1000 | 1,000,000 | 0.25x | 75% cheaper |
| 500 | 250,000 | 0.0625x | 93.75% cheaper |
| 200 | 40,000 | 0.01x | 99% cheaper |

| `embedding_dim` | storage change vs 768 | typical quality tradeoff | note |
| --- | --- | --- | --- |
| 768 | baseline | highest | default for the strongest semantic signal |
| 384 | 50% smaller | small drop | good balance for `all-MiniLM-L6-v2`-style embeddings |
| 96 | 87.5% smaller | noticeable drop | edge mode for tiny models or hash-style embeddings |

The exact runtime speedup depends on the model implementation, but the direction is stable: less context means less GPU work, and fewer embedding dimensions mean less storage.

wrap_llm caveat: it enriches the prompt. If your function accepts `memory_context` or `enriched_prompt`, it will receive them; otherwise the call signature stays the same.

### CLI helpers
- `prajnyavan status --verbose`  # health, uptime, memory count, cache size
- `prajnyavan status --json`     # machine-readable daemon status for scripts/CI
- `prajnyavan doctor`            # readiness checks (writable dirs, port, health, token issue)
- `prajnyavan doctor --json`     # machine-readable readiness report
- `prajnyavan smoke`             # start/store/search/emotion smoke test
- `prajnyavan benchmark import --memories 500 --json`  # wheel-available import throughput check with exact-count assertions
- `prajnyavan logs -n 50`        # tail daemon log
- `prajnyavan logs --rotate --max-mb 5`  # rotate daemon.log before tailing (defaults to 5 MB if unset)
- `prajnyavan export --user alice` / `import --user alice --file backup.json`
- `prajnyavan stop` | `prajnyavan reset`

### Launch notes for 0.3.5
- The source-tree QA artifact in [qa_report_latest.json](/E:/BRAIN/brain-db/qa_report_latest.json) is green on `0.3.5`.
- The installed-wheel artifact in [qa_report_wheel_0_3_5.json](/E:/BRAIN/brain-db/qa_report_wheel_0_3_5.json) proves the Windows installed-wheel contract after the compatibility and metrics-auth fixes.
- The installed upgrade artifact in [qa_report_upgrade_0_3_5.json](/E:/BRAIN/brain-db/qa_report_upgrade_0_3_5.json) proves `0.3.4 -> 0.3.5` continuity, restart persistence, and delete-by-original-id behavior after upgrade.
- The restart-bound soak artifact in [qa_report_soak_0_3_5.json](/E:/BRAIN/brain-db/qa_report_soak_0_3_5.json) is green on the current source tree.
- The Python SDK again accepts the main legacy `0.3.2` content/query-first call shapes for `store`, `search`, `bulk_store`, `store_batch`, `search_batch`, and profile imports while keeping identity-first as the preferred `0.3.x` style.
- Portable profile import deduplication is now target-user scoped, so replaying one export into multiple users preserves exact counts instead of skipping valid memories globally.
- `/v1/metrics` now enforces auth, and the sync/async Python clients request stats through the protected route.

### Launch notes for 0.3.4
- The rebuilt source-tree QA artifact in [qa_report_latest.json](/E:/BRAIN/brain-db/qa_report_latest.json) is green on `0.3.4`.
- The installed-wheel artifact in [qa_report_wheel_0_3_4.json](/E:/BRAIN/brain-db/qa_report_wheel_0_3_4.json) is green and now labels the installed package version explicitly.
- The installed upgrade artifact in [qa_report_upgrade_0_3_4.json](/E:/BRAIN/brain-db/qa_report_upgrade_0_3_4.json) is green for `0.3.3 -> 0.3.4`, including restart continuity and delete-by-original-id across an upgraded version chain.
- Startup now restores persisted version links from archive metadata, so deleting an original id still removes the live updated version after restart or upgrade.
- The restart-bound soak artifact in [qa_report_soak_0_3_4.json](/E:/BRAIN/brain-db/qa_report_soak_0_3_4.json) is green on the current source tree.

### Launch notes for 0.3.3
- Same-root daemon restart persistence is now verified on the real release binary instead of only inferred from unit coverage.
- WAL replay restores structural `user`, `category`, and `session` metadata, so scoped retrieval still works after a reboot.
- The maintainer QA harness now reports against `0.3.3` and passes end to end on the source tree used for that release.

### Launch notes for 0.3.2
- Windows release packaging now has a supported script: `powershell -ExecutionPolicy Bypass -File .\scripts\build_release.ps1`.
- The bundled Windows daemon binary was rebuilt so local `doctor` and `MemoryClient.dev()` no longer drift against the Python package version.
- Local dev token refresh is now request-aware, so strict per-user auth works even when a single client touches multiple user ids.
- Daemon startup recovery now handles stale version/config lock races more cleanly on restart.
- Context packing now uses tag overlap when embeddings are empty, which improves imported profile and pet recall.

### Launch notes for 0.3.1
- Python SDK contracts are stricter now: normalized memory objects, EdgeType ergonomics, explicit context payloads, better async parity, and clearer maintenance exceptions.
- The daemon now respects `infer_emotion=false` on store requests and warns when production runs without encrypt-at-rest enabled.
- Global encrypt-at-rest now derives usable WAL, semantic, and archive encryption material instead of only toggling partial flags.

### Launch notes for 0.3.0
- Repo proof is now committed in-tree: expanded eval datasets, `v030` eval results, turn-50 comparison output, restart persistence coverage, and cold-archive lifecycle tests.
- CI now has the missing benchmark-sync commit step so Linux verification can persist once the Ubuntu run succeeds on `main`.
- Linux benchmark parity is still pending in [benchmarks/results.json](/E:/BRAIN/brain-db/benchmarks/results.json); keep the RAM claim provisional until that artifact flips.
### Launch notes for 0.2.5
- Installed-wheel users now have a real benchmark entrypoint: `prajnyavan benchmark import --memories 500 --json`.
- The README now clearly separates wheel-local commands from repo-only benchmark and eval scripts.
- The existing 0.2.x trust fixes remain in place: honest `status` / `doctor`, real-daemon startup on Windows, safe maintenance failure, stable core CRUD, large-batch chunking, and measurable profile behavior.

### Legacy notes from 0.1.10
- Windows-friendly CLI: ASCII-safe output everywhere; `stop --force` cleans stale PID/locks.
- Built-in log rotation: `prajnyavan logs --rotate [--max-mb N]`.
- Fast-dev integration stubs for CI stay behind `RUN_PRAJNYAVAN_INTEGRATION=1`; normal runs use full MAS.
- Version alignment gates and wheel now include the Windows daemon binary.

---
## Works with any LLM
```python
import anthropic
from prajnyavan import MemoryClient

mem = MemoryClient.dev(user_id="user_123")

@mem.wrap_llm(user_id="user_123")
def chat_with_claude(prompt):
    return anthropic.Anthropic().messages.create(
        model="claude-opus-4-6",
        max_tokens=1000,
        messages=[{"role": "user", "content": prompt}]
    ).content[0].text
```

---
## Production / Advanced
- Docker: copy platform binary to /usr/local/bin/prajnyavan_service, set BRAIN_SECRET_KEY, bind 127.0.0.1:9999 by default.
- Env entrypoint: `PRAJNYAVAN_URL`, `PRAJNYAVAN_TOKEN`, optional `PRAJNYAVAN_EMBEDDING_PROVIDER`.
- Hosted API: `MemoryClient.hosted(base_url="https://your-hosted-url", token=os.environ["PRAJNYAVAN_TOKEN"])`.
- UDS (Linux/macOS): set PRAJNYAVAN_USE_UDS=1 before `prajnyavan dev` for unix socket transport.

---
## Troubleshooting (8 quick fixes)
1) `prajnyavan dev` hangs -> run `prajnyavan logs -n 50`; then `prajnyavan reset`.
2) 401/403 from client -> MemoryClient.dev() auto-refreshes; or `prajnyavan dev` to restart.
3) Binary missing -> reinstall or let `_daemon` auto-download from GitHub Releases.
4) Port in use -> daemon scans 9999-10008; set PRAJNYAVAN_USE_UDS=1 to avoid ports.
5) OpenAI/Cohere errors -> check API keys; fall back to hash by setting embedding_provider="hash".
6) Slow first call -> local model warms on first use; hash embedding is instant.
7) Log file missing -> start once with `prajnyavan dev`; logs at ~/.prajnyavan/daemon.log.
8) Corrupted dev.json -> delete ~/.prajnyavan/dev.json or run `prajnyavan reset`.
9) Unsure whether the install is healthy -> run `prajnyavan doctor` then `prajnyavan smoke`.

## Security
- BRAIN_SECRET_KEY required in prod; auto-generated per run in dev (tokens rotate on restart).
- dev.json is chmod 600 when possible; contains local bearer token and base_url.
- Use HTTPS/reverse proxy in prod; keep daemon bound to 127.0.0.1 by default.

## Performance baseline
Measured on this machine with release build, perf_targets dataset (hash embeddings):

| Operation       | p50  | p95  | p99  |
|-----------------|------|------|------|
| store()         | 12ms | 13ms | 14ms |
| search() k=5    | 0.3ms| 0.4ms| 0.5ms|
| list_memories() | 12ms | 13ms | 14ms |

Notes: timings are per-op averages derived from the `perf_targets` release tests on this machine (500 episodic writes + 50 reads, 200 semantic writes + 40 reads). Adjust for your hardware; rerun `scripts/bench_and_report.sh` from a repo checkout to refresh.

## RAM benchmark
Prajnyavan now exposes resident-memory measurement directly in the core and service layers. These commands require a repo checkout:

- `cargo test -p brain_core ram_usage_under_100mb_for_1000_memories -- --nocapture`
- `cargo test -p brain_core ram_compare_to_naive_dict -- --nocapture`
- `GET /v1/brain/status` now returns `memory_mb`, `hot_buffer`, `l1_count`, `l2_count`, `wal_bytes`, and `uptime_secs`

Target profiles:

| profile | key settings | target RSS delta for 1,000 memories |
| --- | --- | --- |
| standard | defaults | under 100 MiB |
| edge | `edge_mode = true`, `max_hot_buffer_size = 64`, `episodic_mmap_size_bytes = 4194304`, `embedding_dim = 384`, `ann_dimensions = 384` | under 50 MiB target |

Example local config (`prajnyavan.toml` or `brain.toml`):

```toml
edge_mode = true
max_hot_buffer_size = 64
episodic_mmap_size_bytes = 4194304
embedding_dim = 384
ann_dimensions = 384
```

## Contributing
- git clone && pip install -e '.[all]'
- cargo build -p prajnyavan_service
- pytest tests/ -v
- RUN_PRAJNYAVAN_INTEGRATION=1 pytest tests/integration/ -vv
- Good first issues: add Ollama adapter to wrap_llm; export/import CLI enhancements; make PRAJNYAVAN_TOKEN_TTL configurable.

## Python API Reference

### MemoryClient construction

| Method | Description |
|--------|-------------|
| MemoryClient.dev(user_id="developer") | Zero-config local daemon. Auto-starts. |
| MemoryClient.from_env()               | Production: reads PRAJNYAVAN_URL + TOKEN. |

### Storing memories

```python
# Basic store — returns memory id string
id = mem.store("alice", "Loves hiking in Nepal", importance=0.8, category="interests")

# Store with namespace scoping
id = mem.store("alice", "Q3 report done", namespace="work", ttl_days=90)

# Store a structured profile fact (upserts — same key replaces previous value)
mem.store_profile("alice", "role", "Lead Engineer", importance=0.9)

# Batch store
ids = mem.store_batch("alice", [
    {"content": "Likes coffee", "importance": 0.5},
    {"content": "Allergic to cats", "importance": 0.95, "category": "health"},
])

# Smart ingestion: infer category/memory type heuristically
mem.smart_store("alice", "Alice prefers bullet points in weekly updates.")

# Review an important memory to advance spaced repetition
mem.review_memory(ids[0])
```

### Searching memories

```python
# Basic semantic search
results = mem.search("alice", "outdoor activities", k=5)

# Filters — all optional, combinable
results = mem.search("alice", "work tasks",
    namespace="work",         # scope to namespace
    category="tasks",         # scope to category
    min_importance=0.6,       # only important memories
    valence_bias="positive",  # only positive-emotion memories
    exact_match=True,         # must contain query text (server-side)
)

# result shape: {id, content_text, relevance_score, primary_emotion, importance, tags}
```

### Retrieving and managing memories

```python
mem.get_memory(id)                      # fetch a single memory by UUID
mem.get_related(id, depth=2)            # graph-connected memories (spread activation)
mem.list_memories("alice")              # all memories for a user
mem.list_memories("alice", namespace="work")  # scoped list
profile = mem.export_user("alice")      # portable profile document (schema_version=1)
mem.import_profile(profile, target_user_id="alice")  # import/replay a portable profile
mem.update(id, {"importance": 0.9})     # partial update
mem.forget(id, "outdated",              # fine-grained delete
    tombstone_only=False,
    purge_archive=True)
mem.delete_memory(id)                   # simple delete
mem.delete_user("alice")                # delete all memories for user
```

### Portable Profiles

```python
profile = mem.export_user("alice")
assert profile["schema_version"] == 1

# Migrate the same profile into another Prajnyavan-backed product.
remote = MemoryClient.from_env()  # expects PRAJNYAVAN_URL + PRAJNYAVAN_TOKEN
remote.import_profile(profile, target_user_id="alice")
```

```bash
# Export from Product A
prajnyavan export --user alice --output alice_profile.json

# Import into Product B
PRAJNYAVAN_URL=https://productb.example.com \
PRAJNYAVAN_TOKEN="Bearer <token>" \
prajnyavan import --user alice --file alice_profile.json
```

### Analytics and state

```python
mem.highlights("alice", limit=10)       # highest-importance memories
mem.summary("alice", days=7)            # text summary of recent memories
mem.explain("outdoor activities")       # debug: scored source breakdown
mem.stats()                             # daemon performance metrics
mem.get_emotion()                       # global emotional state
mem.brain_status()                      # developmental stage
mem.last_strong_event("alice",          # most emotionally intense memory
    min_arousal=0.7)
```

### LLM context enrichment (decorator)

```python
@mem.wrap_llm(user_id="alice", k=5, valence_bias="positive", debug=False)
def chat(prompt):
    return your_llm_call(prompt)
# Automatically injects relevant memory context into prompt,
# stores the exchange after response.
```

### Knowledge graph

```python
mem.associate(id_a, id_b, edge_type=1, strength=0.9)  # create graph edge
# edge_type: 0=Temporal 1=Semantic 2=Causal 3=Episodic
#            4=Analogical 5=Cooccurrence 6=Contrary 7=PartOf
```

### Maintenance

```python
mem.compact("semantic")   # compact semantic vector store
mem.compact("episodic")   # compact ANN index
mem.compact("graph")      # compact knowledge graph
mem.recover_from_wal()    # replay WAL after crash
```

## Importance and emotion
- importance: float in [0,1]; higher = more salient; currently user-supplied or default from service.
- primary_emotion may be None for neutral text; surface your own emotion scores via tags if needed.

## Emotional context
The brain maintains a continuous emotional state that influences memory retrieval.

```python
state = mem.get_emotion()
# {'primary_emotion': 'joy', 'valence': 0.6, 'arousal': 0.4, 'mood': 'positive'}
```

To store a memory with explicit emotional tone:
```python
mem.store(user_id, "Great meeting today", valence=0.8, arousal=0.5)
```

valence: -1.0 (negative) to 1.0 (positive)  
arousal: 0.0 (calm) to 1.0 (excited)  
primary_emotion: joy, sadness, anger, fear, surprise, disgust, neutral
