Metadata-Version: 2.4
Name: maestro-nerve
Version: 0.1.2
Summary: Data intelligence layer for AI agents — connect, understand, and analyze enterprise data
Project-URL: Homepage, https://github.com/maestro-ai-stack/maestro-nerve-internal
Project-URL: Repository, https://github.com/maestro-ai-stack/maestro-nerve-internal.git
Author-email: Maestro AI <open-source@maestro.onl>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,data-intelligence,mcp,postgres,semantic-layer
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: argon2-cffi>=23.1
Requires-Dist: boto3>=1.40
Requires-Dist: cryptography>=43.0
Requires-Dist: duckdb>=1.0
Requires-Dist: email-validator>=2.1
Requires-Dist: fastapi>=0.115
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.0
Requires-Dist: numpy>=1.26
Requires-Dist: openpyxl>=3.1
Requires-Dist: pdfplumber>=0.10
Requires-Dist: pgvector>=0.3
Requires-Dist: psycopg[binary,pool]>=3.2
Requires-Dist: pyjwt[crypto]>=2.9
Requires-Dist: sentence-transformers>=3.0
Requires-Dist: stripe>=10.0
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn>=0.30
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: import-linter>=2.11; extra == 'dev'
Requires-Dist: mypy>=1.18; extra == 'dev'
Requires-Dist: pip-audit>=2.10; extra == 'dev'
Requires-Dist: pre-commit>=4.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=7.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: ner
Requires-Dist: gliner>=0.2; extra == 'ner'
Provides-Extra: onnx
Requires-Dist: onnxruntime>=1.18; extra == 'onnx'
Requires-Dist: optimum[onnxruntime]>=1.19; extra == 'onnx'
Provides-Extra: predict
Requires-Dist: scikit-learn>=1.5; extra == 'predict'
Requires-Dist: statsforecast>=2.0; extra == 'predict'
Description-Content-Type: text/markdown

<p align="center"><img src=".github/maestro-logo.png" alt="Maestro" width="120" /></p>
<h1 align="center">maestro-nerve</h1>
<p align="center"><strong>Shared intelligence memory layer for procurement, compliance, and tender-review agents.</strong></p>
<p align="center">
  <a href="https://pypi.org/project/maestro-nerve/"><img src="https://img.shields.io/pypi/v/maestro-nerve.svg" alt="PyPI version" /></a>
  <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+" /></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License: MIT" /></a>
</p>

---

**maestro-nerve** gives AI agents a shared, evidence-backed memory over fragmented work sources. It is built for procurement, compliance, and tender-review workflows where Gmail, Drive, docs, sheets, notes, and agent outputs need to converge into one inspectable intelligence layer.

## Why nerve?

| Feature | nerve | Vector DB | SQLite + embeddings |
|---------|-------|-----------|---------------------|
| Structured knowledge (entities + edges) | Yes | No | Manual |
| Multi-channel recall (BM25 + embedding + graph + co-access + temporal + session) | Yes | Embedding only | Manual |
| Online learning (Thompson Sampling) | Yes | No | No |
| Batch API (multiple ops in one call) | Yes | No | No |
| Remote semantic embeddings | Yes | Varies | No |

## Quickstart

### For AI Agents (Claude Code skill)

```bash
# nerve is available as a Claude Code skill
mnerve understand "your query"
```

### For Developers

Neon is the required V1 database. Point `NEON_DATABASE_URL` at a Neon Postgres database with `sslmode=require`, then initialize and serve:

```bash
# Install
pip install maestro-nerve

# Point nerve at Neon
export NEON_DATABASE_URL="postgresql://USER:PASS@HOST.neon.tech/DB?sslmode=require"
mnerve init

# Start daemon
mnerve serve
```

## Architecture

```
┌─────────────────────────────────────────────────────┐
│         External Sources + Heterogeneous Agents     │
├───────────────────────┬─────────────────────────────┤
│  source intake        │  agent-authored intake      │
│  Gmail · Drive · ...  │  fact · conclusion · ...    │
├───────────────────────┴─────────────────────────────┤
│                 Evidence Ledger                     │
│   source_objects · facts · conclusions · events     │
├─────────────────────────────────────────────────────┤
│                 Semantic Layer                      │
│     entities · claims · evidence · decisions        │
├─────────────────────────────────────────────────────┤
│                 Serve Layer                         │
│        MCP · HTTP · CLI · workspace surfaces        │
└─────────────────────────────────────────────────────┘
```

## Legacy compatibility CLI

The repo still contains legacy `remember/understand/feedback` surfaces. They are compatibility-only and do **not** define the long-term product contract. The authoritative V1 and cross-agent naming lives in:

- `docs/superpowers/specs/2026-04-21-mcp-v1-tools.md`
- `docs/superpowers/plans/2026-04-23-cross-agent-memory-broker.md`
- `docs/superpowers/plans/2026-04-23-unified-agent-source-intake-architecture.md`

Legacy examples:

```bash
# Store knowledge (structured)
echo '{"nodes":[{"name":"Dr. Chen","type":"person","properties":{"affiliation":"NUS"}}]}' \
  | mnerve remember --structured

# Recall
mnerve understand "climate data gaps"

# Feedback (improves future ranking)
mnerve feedback q-abc123 548 515

# Batch (preferred — one call instead of many)
mnerve batch '[
  {"op":"understand","params":{"question":"ERA5 climate"}},
  {"op":"remember","params":{"content":"ERA5 has gaps pre-1979","type":"experience"}},
  {"op":"feedback","params":{"query_id":"$0.query_id","selected":[548]}}
]'
```

## Legacy compatibility API reference

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/health` | Health check with PG status + cache stats |
| GET | `/understand?question=...` | 6-channel recall with fusion ranking |
| POST | `/remember` | Legacy compatibility write surface; not the long-term shared-memory contract |
| POST | `/feedback` | Legacy compatibility ranking feedback surface |
| POST | `/batch` | Multiple operations in one request |
| GET | `/schema-hint?preview=...` | Existing types + matches before storing |
| POST | `/learn` | Record rules, aliases, authorities |
| POST | `/register` | Register a data source |
| GET | `/sources` | List registered data sources |
| GET | `/discover` | Discover tables and columns |
| POST | `/query` | Query data with semantic context |
| GET | `/search?q=...` | Semantic column search |

## Configuration

| Env var | Default | Description |
|---------|---------|-------------|
| `NEON_DATABASE_URL` | *(none)* | Canonical cloud Postgres / Neon connection string; required for V1 |
| `NERVE_DSN` | *(none)* | Explicit daemon / CLI override; if set, it must also be a Neon DSN |
| `NERVE_LEGACY` | `0` | Enable deprecated nerve-v1 REST surface temporarily when set to `1` |
| `NERVE_API_KEY` | *(none)* | Bearer token for API auth |
| `NERVE_CORS_ORIGINS` | `http://localhost:3000` | Comma-separated CORS origins |
| `CLOUDFLARE_ACCOUNT_ID` | *(none)* | Cloudflare account ID for Workers AI embeddings |
| `CLOUDFLARE_API_TOKEN` | *(none)* | Cloudflare API token with `AI:Run` permission |
| `NERVE_EMBED_MODEL` | `@cf/qwen/qwen3-embedding-0.6b` | Override Workers AI embedding model |
| `NERVE_ENCRYPTION_KEY` | *(none)* | Fernet key for credential encryption |

### Local V1 env setup

The repo includes a root env template at [`.env.example`](/Users/ding/maestro/projects/maestro-nerve/.env.example).

What you need right now for the current V1 scaffold:

- `NEON_DATABASE_URL` for the Python daemon / CLI
- `NERVE_LEGACY=1` only if you still need the deprecated nerve-v1 REST surface during migration
- `INTERNAL_API_BASE_URL` only if `apps/web` should talk to a daemon URL other than `http://127.0.0.1:7420`
- repo-root SQL migrations under [`migrations/`](/Users/ding/maestro/projects/maestro-nerve/migrations) are applied by `mnerve init` and on daemon startup

What is documented but not yet required for the current scaffold:

- `NERVE_AUTH_SECRET`
- `GOOGLE_CLIENT_ID`
- `GOOGLE_CLIENT_SECRET`
- `MICROSOFT_CLIENT_ID`
- `MICROSOFT_CLIENT_SECRET`
- `STRIPE_SECRET_KEY`
- `STRIPE_WEBHOOK_SECRET`
- `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`
- `R2_*`
- `NERVE_DSN` only if you intentionally override `NEON_DATABASE_URL` with another Neon DSN

Those V1 cloud variables are part of the target architecture, but the current web and desktop passes are still scaffold / contract-first for auth, billing, and companion flows. They should be requested when the corresponding runtime path is actually wired, not before.

For Google OAuth, keep the two redirect URIs distinct:

- Sign-in auth callback: `http://localhost:3000/api/auth/google/callback`
- Connector grant callback: `http://127.0.0.1:7420/api/connectors/google/callback`

For Microsoft connector OAuth:

- Connector grant callback: `http://127.0.0.1:7420/api/connectors/microsoft/callback`

In production, replace those origins with the real web and daemon base URLs.

### Workspace RLS note

V1 tables use real PostgreSQL row-level security with `current_setting('app.workspace_id')::uuid`.
The schema is in place, but the current daemon does not yet inject `app.workspace_id` on every connection checkout.
Until workspace-scoped request plumbing lands, callers that query V1 tables directly must `SET app.workspace_id = '<workspace-uuid>'` on the session before issuing workspace-bound SQL.

## Performance

Benchmarked on M4 Pro, single uvicorn worker:

| Metric | Value |
|--------|-------|
| understand (cold) | 58ms p50 |
| understand (cached) | 1ms p50 |
| remember | 65ms |
| batch (3 ops) | 183ms |
| Cache hit rate | 74.5% |
| Sustained QPS | 17+ (cold) / 251 (cached) |

Embedding inference runs through Cloudflare Workers AI in the V1 runtime; the Python daemon no longer loads a local embedding model on startup.

## Contributing

```bash
# Dev setup
git clone https://github.com/maestro-ai-stack/maestro-nerve-internal.git maestro-nerve
cd maestro-nerve
pip install -e ".[dev,onnx]"

# Run tests
pytest tests/ -x -v

# Lint
ruff check src/ tests/
```

## Harness

Canonical repo-level harness entrypoints:

```bash
scripts/harness-fast.sh
scripts/harness-python-fast.sh
scripts/harness-web-fast.sh
scripts/harness-web-smoke.sh
scripts/harness-desktop-fast.sh
scripts/harness-install-hooks.sh
```

What they do:

- `scripts/harness-fast.sh`: hygiene, import boundaries, Python fast lane, web fast lane, desktop fast lane
- `scripts/harness-python-fast.sh`: `ruff + mypy + pytest-cov` for the stable runtime lane
- `scripts/harness-web-fast.sh`: `eslint + typecheck + vitest + next build`
- `scripts/harness-web-smoke.sh`: Playwright smoke suite for landing, 404, and health route
- `scripts/harness-desktop-fast.sh`: desktop `typecheck + build:ui + cargo check`
- `scripts/harness-install-hooks.sh`: installs local `pre-commit` and `pre-push` hooks

## License

MIT — see [LICENSE](LICENSE).

<p align="center">Built by <a href="https://maestro.onl">Maestro</a> — Singapore AI product studio.</p>
