Metadata-Version: 2.4
Name: prajnyavan
Version: 0.3.6
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.
- The RAM gate stays tied to [benchmarks/results.json](/E:/BRAIN/brain-db/benchmarks/results.json) and should be treated as provisional until `linux_verified` is flipped by Ubuntu CI.
- Cross-platform wheel/bootstrap proof is tracked separately in [platform_matrix.json](/E:/BRAIN/brain-db/benchmarks/platform_matrix.json). Do not widen public platform claims until that matrix is green for Windows, Linux, and macOS.

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.

### 0.3.6 Proof-First Release
- `0.3.6` keeps the hardening focus. It does not widen memory semantics; it makes proof and runtime truth more explicit.
- The Python clients, `prajnyavan status`, and `prajnyavan doctor` now expose the active embedding provider so `local -> hash` fallback is visible instead of inferred.
- The installed-wheel QA harness now proves `logs --rotate`, `demo`, embedding-status truth, and bootstrap-mode startup for CI/platform runs.
- CI now has a wheel-proof matrix plus a repo-tracked [platform_matrix.json](/E:/BRAIN/brain-db/benchmarks/platform_matrix.json) reducer so Windows/Linux/macOS proof can be committed back as artifacts instead of described informally.
- 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_6.md](/E:/BRAIN/brain-db/docs/RELEASE_READINESS_0_3_6.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 |

Embedding truth is now explicit in the shipped surfaces:

- `MemoryClient.brain_status()` and `AsyncMemoryClient.brain_status()` include `embedding.requested_provider`, `active_provider`, `model`, `fallback_reason`, `local_model_available`, and `cache_path`.
- `prajnyavan status --json` returns the same `embedding` object for scripts and CI.
- `prajnyavan status --verbose` prints one embedding line such as `embedding: local -> hash (model unavailable)` or `embedding: local (all-mpnet-base-v2)`.
- `prajnyavan doctor --json` adds an `embedding_provider` check. Requested `local` with hash fallback is a `warn`; missing credentials for explicit remote providers is a `fail`.
- `embedding_provider="local"` still falls back to hash embeddings if the local model cannot load; `0.3.6` makes that visible without changing the fallback behavior.

### 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, embedding truth
- `prajnyavan status --json`     # machine-readable daemon + embedding status for scripts/CI
- `prajnyavan doctor`            # readiness checks (writable dirs, port, health, token issue, embedding provider)
- `prajnyavan doctor --json`     # machine-readable readiness report including embedding_provider
- `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.6
- `0.3.6` is a proof-and-runtime-truth release on top of `0.3.5`, not a new feature family.
- The source-tree QA artifact in [qa_report_latest.json](/E:/BRAIN/brain-db/qa_report_latest.json) is green on `0.3.6`.
- The Windows installed-wheel artifact in [qa_report_wheel_0_3_6.json](/E:/BRAIN/brain-db/qa_report_wheel_0_3_6.json) is green and now proves embedding truth, `logs --rotate`, and `demo` in addition to the existing lifecycle, CRUD, async, restart, and reset checks.
- The installed upgrade artifact in [qa_report_upgrade_0_3_6.json](/E:/BRAIN/brain-db/qa_report_upgrade_0_3_6.json) is green for `0.3.5 -> 0.3.6`.
- The restart-bound soak artifact in [qa_report_soak_0_3_6.json](/E:/BRAIN/brain-db/qa_report_soak_0_3_6.json) is green on the current source tree.
- Cross-platform installed-wheel/bootstrap proof is now designed to land in [platform_matrix.json](/E:/BRAIN/brain-db/benchmarks/platform_matrix.json); until that file is green on CI, README and PyPI claims should stay narrower than “cross-platform installed-wheel verified.”
- The Python SDK and CLI now surface embedding truth directly, including visible `local -> hash` fallback and explicit doctor severity rules for missing remote-provider credentials.
- The installed-wheel harness now proves `logs --rotate`, `demo`, machine-readable zero-config startup, and bootstrap-mode startup in addition to the existing CRUD, async, restart, and reset coverage.

### 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
