Metadata-Version: 2.4
Name: radhiops
Version: 0.0.1
Summary: RadhiOps — BYOE AI Engineering Platform SDK
Author: RadhiOps
License: Apache-2.0
Keywords: agents,ai,byoe,devops,mcp,security
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.6
Provides-Extra: all
Requires-Dist: anthropic>=0.34; extra == 'all'
Requires-Dist: google-generativeai>=0.7; extra == 'all'
Requires-Dist: huggingface-hub>=0.24; extra == 'all'
Requires-Dist: openai>=1.30; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.34; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Provides-Extra: google
Requires-Dist: google-generativeai>=0.7; extra == 'google'
Provides-Extra: huggingface
Requires-Dist: huggingface-hub>=0.24; extra == 'huggingface'
Provides-Extra: openai
Requires-Dist: openai>=1.30; extra == 'openai'
Description-Content-Type: text/markdown

# radhiops

The Python SDK for **RadhiOps** — the BYOE (Bring Your Own Everything) AI
Engineering Platform.

```bash
pip install radhiops
# providers are optional extras — install only what you use:
pip install 'radhiops[openai]'        # or [anthropic], [google], [huggingface], [all]
# ollama needs no extra (talks to your local server)
```

## Quick start

```python
from radhiops import RadhiOps

# New here? A demo key seeds 500 free credits, fully offline.
ops = RadhiOps(access_key="radhi_demo_yourtrialkey123")

# Run a local security audit (no AI, no network needed).
report = ops.soc.audit("./my-project")
print(report.counts())          # {'low': 0, 'medium': 1, 'high': 0, 'critical': 0}
print(report.passed)            # gate result for pre-push / pre-deploy

# Bring your own model for AI-assisted remediation.
ops.use_model("openai", model="gpt-4o-mini", api_key="sk-...")
print(ops.soc.remediate(report))

# Or run a fully local model via Ollama — no API key:
ops.use_model("ollama", model="llama3.1")
```

## Repo agent — Git in plain English

```python
repo = ops.repo("./my-project")

repo.command("what changed?")
repo.command('commit "fix: handle null user"')
repo.command("create a new branch feature/login")
repo.command("merge dev into main")

# push() runs a RadhiSOC security gate first and BLOCKS on high/critical
# findings unless you explicitly override.
result = repo.push()
if not result.ok:
    print(result.message)   # e.g. "Security gate blocked the push: 1 finding"
```

Common verbs are parsed by rules (free, offline). Ambiguous phrasing falls back
to your BYOE model. Protected branches (main/master/prod) require
`allow_protected=True`, and force pushes use `--force-with-lease`.

```bash
radhiops repo "push my changes" --path ./my-project
radhiops repo "merge dev into main"
```

## Deployment agent — BYOE deploy targets

Bring your own platform token. RadhiOps never stores it.

```python
# Vercel / Netlify / Render / Railway / Surge
dep = ops.deploy("vercel", token="<vercel-token>", team_id="team_...")

dep.list(limit=5)                  # recent deployments (normalized)
d = dep.trigger()                  # kick a new deployment (where supported)
final = dep.watch(d.id)            # poll until ready/failed
if final.status.failed:
    diag = dep.diagnose(d.id)      # rule-based + AI root-cause from the logs
    print(diag.rule_based["suggestion"])
```

| Platform | name | Scope option | Triggers deploys |
|----------|------|--------------|------------------|
| Vercel | `vercel` | `team_id` (optional) | via git integration |
| Netlify | `netlify` | `site_id` | yes (build) |
| Render | `render` | `service_id` | yes |
| Railway | `railway` | `service_id` | (monitor) |
| Surge | `surge` | `domain` | yes (CLI) |

The log diagnoser recognises common failures (missing modules, unset env vars,
OOM, port conflicts, lockfile mismatches) with zero credits; anything it can't
classify is escalated to your BYOE model.

```bash
radhiops deploy render status --id dep_123 --token $RENDER_TOKEN --opt service_id=srv_abc
radhiops deploy vercel diagnose --id dpl_123 --token $VERCEL_TOKEN
```

## Runtime Monitor — production health & incidents

```python
mon = ops.monitor()
mon.add_target("api", "https://myapp.com/health", contains="ok")
mon.add_target("web", "https://myapp.com")

mon.poll()                         # probe every target once
for inc in mon.evaluate():         # anomalies -> incidents
    print(inc.severity, inc.summary, "->", inc.escalate_to)

# crash detection from a runtime log stream
crash = mon.ingest_logs("api", ["Traceback (most recent call last):", "MemoryError"])

# or run a monitoring loop with a callback per incident
mon.watch(rounds=10, interval=30, on_incident=lambda i: print(i.to_dict()))
```

Detects: endpoint down (consecutive failures), error-rate spikes, latency
degradation (p95), and runtime crashes (OOM, segfault, unhandled exceptions,
restart loops, DB connection failures). Each incident is tagged with the agent
that should handle it next (`DeploymentAgent`, `CyberDefenseAgent`), ready for
the autonomous loop. Thresholds are tunable via `Thresholds`.

## Cyber Defense agent — runtime attack detection

Feed inbound requests through the guard; it returns an allow/challenge/block
verdict and auto-blocklists serious offenders.

```python
guard = ops.defense()

verdict = guard.analyze({
    "ip": "203.0.113.9",
    "path": "/search",
    "query": "q=' UNION SELECT password FROM users--",
})
if verdict.blocked:
    return Response(status=403)

# behavioral: repeated failed logins from one IP -> brute force / stuffing
verdict, incident = guard.inspect({"ip": "203.0.113.9", "auth_failed": True, "user": "admin"})

# framework hook
guard_fn = guard.middleware(on_block=lambda v: log.warning("blocked %s", v.ip))
```

Detects: SQL injection, XSS, SSRF, path traversal, command injection, header
(CRLF) injection, brute force, credential stuffing, rate-limit abuse, and DDoS.
Code-level attacks escalate to RadhiSOC (fix the code); volumetric attacks are
blocked directly. Scoring/thresholds are tunable via `DefenseConfig`.

## CLI

```bash
export RADHIOPS_ACCESS_KEY=radhi_demo_yourtrialkey123
radhiops audit ./my-project
radhiops audit . --json
```

The `audit` command exits non-zero when high/critical findings are present, so
it drops straight into CI or a Kiro pre-push hook.

## Supported model providers (BYOE)

| Provider | name | Needs key? | Extra |
|----------|------|-----------|-------|
| OpenAI / compatible | `openai` | yes | `[openai]` |
| Anthropic | `anthropic` | yes | `[anthropic]` |
| Google Gemini | `google` | yes | `[google]` |
| Ollama (local) | `ollama` | no | — |
| Hugging Face | `huggingface` | yes | `[huggingface]` |

Register your own (e.g. an MCP-backed model) with
`radhiops.register_provider("mymodel", MyProviderClass)`.

## Status

Phase 0–5: BYOE model layer, access-key client, credit ledger (local + hosted),
and all five agents — RadhiSOC (security), Repo (Git + pre-push gate),
Deployment (multi-platform + log diagnosis), Runtime Monitor (health, anomalies,
crashes), and Cyber Defense (runtime attack detection) — plus the Supabase
backend. The autonomous cross-agent loop (incidents routing Monitor → Deployment
→ RadhiSOC → Repo automatically) is next.

### Online vs offline

```python
# Offline (default): local credit ledger, demo keys seeded with 500 credits.
ops = RadhiOps(access_key="radhi_demo_...")

# Online: validate + meter against the hosted backend (Supabase edge functions).
ops = RadhiOps(
    access_key="radhi_live_...",
    offline=False,
    api_base="https://<project-ref>.supabase.co",
    anon_key="<supabase-anon-key>",
)
```
