Metadata-Version: 2.4
Name: moeit
Version: 0.4.0
Summary: MoEit — Agent Operating System (Lite form: single-process, zero-infra default)
Author: MoEit Authors
License: Proprietary
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pydantic>=2.7.0
Requires-Dist: pydantic-settings>=2.3.0
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: prompt_toolkit>=3.0.0
Requires-Dist: tomli>=2.0; python_version < "3.11"
Provides-Extra: dev
Requires-Dist: pytest>=8.2.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
Requires-Dist: ruff>=0.5.0; extra == "dev"

# MoEit — Agent Operating System

**Mixture-of-Experts for coding, shell, and search.** Single Python process by default, scales to a distributed cluster when you need it.

```bash
pip install moeit          # or: uv tool install moeit
moe doctor                 # check your environment
moe "fix the failing test in tests/test_auth.py"
```

That's the whole quick start. No Docker, no NATS, no Redis. MoEit runs as a single Python process and falls back to a subprocess sandbox when Docker isn't available. When your team grows past a single laptop, see [`docs/distributed.md`](docs/distributed.md) for the L2/L3 upgrade path.

---

## Why MoEit?

| You want to… | MoEit Lite form (default) |
|---|---|
| Fix a bug in one file | `moe "fix the bug in auth.py"` |
| Run an interactive coding session | `moe` (REPL — Phase 3) |
| Audit what the agent did | `cat ~/.moeit/logs/{session,expert,llm,tool}.log` |
| Use OpenAI / Anthropic / DeepSeek / Gemini / Ollama | `export OPENAI_API_KEY=sk-...` (auto-detected) |
| Run in CI / containers | Same CLI, single Python process |

The default form is intentionally boring. A 5-line `pyproject.toml`, a single CLI, four log files. When you outgrow it, the same CLI talks to the L2 (single-node distributed) or L3 (Kubernetes) form without code changes.

## Quick Start

### 1. Install

```bash
pip install moeit
# or
uv tool install moeit
# or, skip the Python setup entirely:
docker pull yourorg/moeit
docker run --rm yourorg/moeit moe doctor
```

Requires Python ≥ 3.10. No system dependencies. Docker is *optional* — without it, MoEit uses a path-jailed subprocess sandbox. The pre-built image ([docs/docker.md](docs/docker.md)) is multi-arch (linux/amd64 + linux/arm64), non-root, and ships the same CLI.

### 2. Verify

```bash
moe doctor
```

Sample output:

```
MoEit Doctor — ~/.moeit
────────────────────────────────────────────────────────────
  ✓ Python 3.12.3
  ✓ User paths: ~/.moeit (7 subdirs, writable)
  ✓ Disk: 124 GB free
  ✓ LLM: openai (model: gpt-4o)
  ⚠ Sandbox: Docker not detected; will use subprocess fallback
  · NATS not reachable at 127.0.0.1:4222
  · Redis not reachable at 127.0.0.1:6379
  ✓ SACP protocol: generated and importable
────────────────────────────────────────────────────────────
  5 ok, 3 info, 1 warn, 0 fail

  ⚠ Lite runs in degraded mode. WARN items above.
```

If LLM shows FAIL, set one of:

```bash
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export DEEPSEEK_API_KEY=...
export GEMINI_API_KEY=...
export OLLAMA_HOST=http://localhost:11434   # local, no key
```

Or run `moe doctor --fix` to seed `~/.moeit/config/.env` (placeholders are stripped to empty by default).

### 3. Run a task

```bash
moe "refactor the database module to use connection pooling"
moe "add a test for the login flow"
moe "find every place we call requests.get and add a timeout"
```

Output is streamed as the experts work. Logs go to `~/.moeit/logs/`.

For a guided walkthrough (install → first task → inspect artifacts in 5 minutes), see [`docs/quickstart.md`](docs/quickstart.md). For common patterns once you're set up, see [`docs/recipes/`](docs/recipes/).

## Architecture (Lite form)

```
                  ┌────────────────────────────────────────────┐
                  │          MoEit Lite (1 process)            │
   CLI / HTTP ──► │ ┌──────────┐  ┌──────────┐  ┌──────────┐  │
                  │ │  Coder   │  │  Shell   │  │  Search  │  │
                  │ │  Expert  │  │  Expert  │  │  Expert  │  │
                  │ └────┬─────┘  └────┬─────┘  └────┬─────┘  │
                  │      └──────────────┼──────────────┘       │
                  │         ┌──────────┴──────────┐            │
                  │         │   In-proc EventBus  │            │
                  │         │  (asyncio.Queue)    │            │
                  │         └──────────┬──────────┘            │
                  │                    │                       │
                  │         ┌──────────┴──────────┐            │
                  │         │  LLM + Subprocess   │            │
                  │         │   Sandbox + SQLite  │            │
                  │         └─────────────────────┘            │
                  └────────────────────────────────────────────┘
```

A single Python process. Experts are asyncio tasks in one event loop. The bus is an in-memory subject-routed queue. Memory is SQLite at `~/.moeit/memory/`. Sandbox defaults to subprocess with path jail + command whitelist; Docker is used if `docker info` succeeds.

## Observability

`moe serve` exposes a Prometheus scrape target out of the box:

```bash
moe serve --host 127.0.0.1 --port 8765 &
curl -s http://127.0.0.1:8765/v1/metrics/prom
```

Two endpoints:

| Endpoint | Format | Use |
|---|---|---|
| `GET /v1/metrics` | JSON | `curl \| jq`, ad-hoc dashboards |
| `GET /v1/metrics/prom` | Prometheus text v0.0.4 | production scrape configs |

Both come out of the same collector, so the JSON and Prometheus views can never drift. The collector surfaces five slices — runtime state (uptime, experts, in-flight), task counters (per-status), LLM token / cost totals (per-model and per-provider), trace event timing (p50 / p90 per span kind), and memory health. A scrape walks the in-memory store with a 50,000-chunk cap so a long-running agent doesn't OOM the scraper.

Example `prometheus.yml` scrape config:

```yaml
scrape_configs:
  - job_name: moeit
    static_configs:
      - targets: ['127.0.0.1:8765']
    metrics_path: /v1/metrics/prom
    scrape_interval: 30s
```

Exposed metric names (selection):

- `moe_uptime_seconds` (gauge)
- `moe_tasks_in_flight` (gauge), `moe_tasks_completed_total{status="ok|failed|..."}` (counter)
- `moe_llm_calls_total{model="..."}` (counter), `moe_llm_tokens_total{kind="prompt|completion"}` (counter), `moe_llm_cost_usd_total` (counter)
- `moe_span_duration_ms{kind="...",quantile="0.5|0.9"}` (gauge)
- `moe_memory_chunks`, `moe_memory_tasks`, `moe_memory_trace_events` (gauges)

## CLI surface

```
$ moe --help
usage: moe [-h] [--version] <command> ...

MoEit 0.2.0 — Agent Operating System (Lite form).

positional arguments:
  <command>
    doctor    Self-check the environment (and optionally auto-fix).
    trace     [Phase 6] Replay or inspect a past task by id.
    expert    [Phase 4] List or inspect registered experts.

$ moe --version
moe 0.2.0 (Lite form)

$ moe "add a test for login"        # Phase 1+: real task execution
$ moe trace <task_id>                # Phase 6
$ moe expert list                    # Phase 4
```

## Project layout

```
moeit/
├── __init__.py          # version + lite form marker
├── paths.py             # ~/.moeit/ directory layout
├── config.py            # pydantic-settings + LLM auto-detect
├── logging.py           # session / expert / llm / tool log categories
├── protocol/            # generated SACP protobuf (shared with Rust)
├── runtime/             # 4 Protocols: Bus / Expert / Router / Memory
│   ├── bus/
│   ├── experts/
│   ├── router/
│   └── memory/
├── experts/             # Coder / Shell / Search (Phase 1+)
├── llm/                 # OpenAI / Anthropic / DeepSeek / Ollama adapters
├── sandbox/             # SubprocessSandbox / DockerSandbox
├── cli/                 # `moe` command — doctor / trace / expert
├── observability/       # /v1/metrics collector + Prometheus formatter
└── __main__.py          # `python -m moeit` entry

bin/moe                  # shell wrapper for development
Dockerfile               # Multi-stage L1 image (build + publish via .github/workflows/docker.yml)
docs/distributed.md      # L2 / L3 (Rust Kernel + NATS + Docker Compose)
docs/quickstart.md       # 5-minute guided walkthrough
docs/recipes/            # Common `moe "..."` patterns (8 recipes)
docs/configuration.md    # Full env-var / CLI reference
docs/docker.md           # Pre-built image: pull, run, env vars, digest pinning
docs/publishing.md       # PyPI release runbook (tag → Trusted Publishing)
docs/troubleshooting.md  # Operator runbook
CHANGELOG.md             # Release notes
kernel/                  # legacy Rust Kernel (L3 cluster mode)
agents/                  # legacy Python daemon (kept for Phase 1 migration)
```

## Deployment forms

| Form | When | Install | Runtime |
|---|---|---|---|
| **L1 Lite** (default) | Personal / small team / POC | `pip install moeit` | Single Python process |
| **L2 Distributed** | Department / single node | `git clone && moe deploy up` | NATS + Redis + Rust Kernel + Python agents |
| **L3 Cluster** | Multi-team / SaaS | `helm install moeit` | Kubernetes + multi-node agent pool |

All three forms use the **same CLI and the same Protocol types**. L1 is just the in-process implementation of `EventBus` and `Memory`; L2/L3 swap them for NATS and Redis/Postgres without touching the experts. See [`docs/distributed.md`](docs/distributed.md) for L2/L3 details.

## Configuration

| Variable | Default | Description |
|---|---|---|
| `MOEIT_HOME` | `~/.moeit` | User-state root (config, memory, logs, sessions) |
| `MOE_LLM_API_KEY` | — | LLM API key (overrides vendor env vars) |
| `MOE_LLM_BASE_URL` | provider default | LLM endpoint |
| `MOE_LLM_MODEL` | provider default | LLM model name |
| `MOE_LLM_*` | — | All other LLM settings (temperature, retries, timeout) |
| `MOE_SANDBOX_*` | `auto` / `python:3.12-slim` | Sandbox backend (auto/subprocess/docker) |
| `MOEIT_LOG_LEVEL` | `INFO` | One of `DEBUG` / `INFO` / `WARNING` / `ERROR` |
| `NATS_URL` | `nats://127.0.0.1:4222` | Only used in L2/L3 form |
| `REDIS_URL` | `redis://127.0.0.1:6379` | Only used in L2/L3 form |

LLM credentials auto-detect from `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `DEEPSEEK_API_KEY` / `GEMINI_API_KEY` / `OLLAMA_HOST` when `MOE_LLM_API_KEY` is not set.

## Development

```bash
git clone https://github.com/yourorg/MoEit
cd MoEit
pip install -e ".[dev]"

# Tests
pytest tests/                      # top-level (moeit package)
cd agents && pytest tests/         # legacy agents (Phase 1 migration source)

# Build proto
make proto                         # writes moeit/protocol/generated/

# Run doctor
moe doctor --fix
moe doctor --json | jq

# Local install
pip install -e .                   # installs `moe` console script
./bin/moe doctor                   # fallback wrapper

# Cutting a release
# See docs/publishing.md for the end-to-end release runbook
# (bump version, tag, PyPI Trusted Publishing).
```

## License

Proprietary. All rights reserved.
