Metadata-Version: 2.5
Name: brian-core
Version: 2.0.0rc1
Summary: A provider-neutral, fault-tolerant agent runtime
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.50.0
Requires-Dist: apscheduler>=3.10.0
Requires-Dist: coverage>=7.15.0
Requires-Dist: ddgs>=9.0.0
Requires-Dist: fastapi>=0.138.1
Requires-Dist: fastembed>=0.8.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp<2,>=1.27
Requires-Dist: openai>=2.0.0
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: paramiko>=3.4.0
Requires-Dist: playwright>=1.49.0
Requires-Dist: prompt-toolkit>=3.0.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: pymongo>=4.6.0
Requires-Dist: pymupdf>=1.24.0
Requires-Dist: pymysql>=1.1.0
Requires-Dist: pytesseract>=0.3.13
Requires-Dist: python-docx>=1.1.0
Requires-Dist: python-pptx>=1.0.0
Requires-Dist: rich>=15.0.0
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: tavily-python>=0.5.0
Requires-Dist: textual>=8.0.0
Requires-Dist: uvicorn[standard]>=0.49.0
Provides-Extra: hosted
Requires-Dist: opentelemetry-api>=1.38.0; extra == 'hosted'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.38.0; extra == 'hosted'
Requires-Dist: opentelemetry-sdk>=1.38.0; extra == 'hosted'
Requires-Dist: psycopg[binary]>=3.2.0; extra == 'hosted'
Provides-Extra: providers
Requires-Dist: boto3>=1.42.0; extra == 'providers'
Requires-Dist: google-genai>=1.56.0; extra == 'providers'
Description-Content-Type: text/markdown

# BRIAN

A self-hosted AI **harness**: a model plus the loop, tools, memory, and permissions that turn it into an agent you can actually run.

Package: `brian-core` `2.0.0rc1`. Command: **`brian`**. `agent` is a silent alias of the same program. Code lives under `src/brian_core`.

This checkout is `/srv/brian` on branch `brian`. It is **not** the live operator at `/srv/agent` (ab212.io) and not HeyBrian. Do not copy those trees’ `.env`, `memory/`, or sessions here.

## Install

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh && uv tool install brian-core && brian
```

Or run [`scripts/install.sh`](scripts/install.sh). First run asks for a provider and key, writes `~/.brian/.env` (mode 0600), then starts the REPL. Type `brian` from any folder — keys, USER.md, and sessions live in `~/.brian`. You still need your own LLM key. The wheel is code only; a stranger’s brain starts blank.

## Three doors

| Door | What it is |
|---|---|
| CLI | Type `brian` |
| HTTP API | `brian --api` — OpenAI-shaped chat plus durable runs |
| Agent SDK | `from brian_core.sdk import run` — same loop in-process, not HTTP |

`BrianClient` is an HTTP helper for the API. It is not the Agent SDK.

```python
from brian_core.sdk import run, stream

print(run("list python files"))
for event in stream("list python files"):
    ...
```

## Run from this repo

Needs Git, Python 3.11+, and [uv](https://docs.astral.sh/uv/). Product home is still `~/.brian` (override with `BRIAN_HOME` or `BRIAN_ENV_FILE`). Tests may set `MEMORY_DIR`.

```bash
cd /srv/brian          # or clone the repo and check out this branch
uv sync
uv run brian --help
uv run brian           # first run: provider + key into ~/.brian/.env
uv run brian "list python files"   # one shot
```

Package layout is `src/brian_core`. Optional extras: `providers`, `hosted`.

## Modes

```bash
uv run brian                         # interactive REPL
uv run brian "do this"               # one shot
uv run brian --continue              # last session
uv run brian --resume <session-id>
uv run brian --fork-session <id>
uv run brian --tui                   # full-screen terminal UI
uv run brian --api                   # FastAPI server
uv run brian --scheduler             # durable job worker
uv run brian --heartbeat-only        # memory maintenance, then exit
uv run brian --learning-graph
uv run brian --version
uv run agent --help                  # same CLI; do not teach this name
```

One execution mode per invocation. `--api` requires `API_SERVER_KEY`.

## HTTP API

```bash
uv run brian --api
curl -fsS http://127.0.0.1:8000/health
curl -fsS http://127.0.0.1:8000/v1/chat/completions \
  -H "Authorization: Bearer $API_SERVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"agent","messages":[{"role":"user","content":"Say hello."}]}'
```

Bearer `API_SERVER_KEY` on almost every route. Public: `/health`, `/v1/health`, throttled `POST /api/web/login`, Twilio-signed `POST /hooks/twilio/sms`.

| Endpoint | Purpose |
|---|---|
| `POST /v1/chat/completions` | Chat, streaming or not |
| `POST /v1/runs` | Durable run that survives a closed tab |
| `GET /v1/runs/{id}/events` | SSE for that run |
| `POST /v1/runs/{id}/approval` | Human approval |
| `GET /v2/capabilities` | Machine-readable surface |
| `/api/sessions/*` | Session CRUD and chat |
| `/api/jobs/*` | Scheduler jobs |

Operator detail (SOUL, skills, MCP, session save): [`docs/brian-operator.md`](docs/brian-operator.md). What it can do in plain English: [`docs/CAPABILITIES.md`](docs/CAPABILITIES.md).

## Config

All settings are `.env` under `~/.brian` (or `BRIAN_ENV_FILE`). Names are in `env.example`. Required: `PROVIDER`, `MODEL`, and the key for that provider.

On first interactive start, if `~/.brian/memory/USER.md` is empty, the CLI asks a few profile questions after keys work.

## What this tree is for

Build the product **here**. Leave `/srv/agent` as production. Tests that need config use a **local** env, never the live one.

Working rules for agents: [`AGENTS.md`](AGENTS.md).
