Metadata-Version: 2.4
Name: solidx-ai-agent
Version: 0.1.0
Summary: AI agent harness for the SolidX platform — build full-stack apps via natural language
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: litellm
Requires-Dist: mini-swe-agent>=2.2.8
Requires-Dist: pydantic>=2
Requires-Dist: pydantic-settings
Requires-Dist: python-dotenv
Requires-Dist: rich
Requires-Dist: typer
Requires-Dist: pyyaml
Requires-Dist: jinja2
Requires-Dist: fastapi
Requires-Dist: uvicorn[standard]
Requires-Dist: websockets
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: psycopg2-binary
Requires-Dist: openai>=1.0
Requires-Dist: anthropic
Requires-Dist: httpx
Requires-Dist: aiohttp
Requires-Dist: tqdm
Requires-Dist: starlette
Requires-Dist: mcp>=1.0
Provides-Extra: full
Requires-Dist: llama-index-core; extra == "full"
Requires-Dist: llama-index-embeddings-huggingface; extra == "full"
Requires-Dist: sentence-transformers; extra == "full"
Requires-Dist: PyMuPDF; extra == "full"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: ruff; extra == "dev"

# SolidX AI Agent

Build full-stack applications on the SolidX platform using natural language.

The SolidX AI Agent is an LLM-powered harness that wraps the SolidX platform tools — module creation, model/field management, layout editing, code generation, and more — so an LLM can orchestrate multi-step application building through a CLI, a persistent **server** (WebSocket + REST for the Chat UI), or `solidctl`.

```
You:     "Create a CRM module with Lead and Contact models,
          add name/email/phone fields, set up list views and menus"

Agent:   1. Checks existing modules           (solid_get_module_metadata)
         2. Creates CRM module                 (solid_create_module)
         3. Creates Lead model with fields     (solid_create_model_with_fields)
         4. Creates Contact model with fields  (solid_create_model_with_fields)
         5. Configures list/form layouts        (solid_update_layout)
         6. Adds sidebar menu entries           (solid_add_or_update_menu)
         → Done. DB + APIs + UI generated.
```

---

## Key Features

- **10 SolidX platform tools** exposed to the LLM alongside a `bash` shell tool — including `filesystem_tool` for unified frontend operations and `get_metadata` for read-only metadata inspection
- **Persistent server process** — FastAPI with WebSocket + REST endpoints for multi-turn conversations
- **Multi-turn sessions** — agent maintains conversation context across messages
- **Interaction logging** — all events persisted to PostgreSQL via agent-owned DB layer
- **solidctl integration** — `solidctl agent start` / `solidctl agent run <task>` commands
- **Event-driven architecture** — every agent action emits typed events for real-time streaming to CLI or Chat UI
- **Rich CLI output** — colored panels, step boundaries, tool call previews, cost tracking
- **Interactive mode** — REPL-style prompt for iterative building
- **Built on mini-SWE-agent** — lightweight, extensible observe-act loop with LiteLLM (supports Anthropic, OpenAI, and 100+ providers); uses **FastLLM for auxiliary tasks** (intent classification, session titles)

---

## Prerequisites

- **Python 3.11+** (recommended)
- **An LLM API key** — Anthropic (recommended) or OpenAI
- **PostgreSQL** with the SolidX database (`DATABASE_URL`)
- **For server interaction logging** (optional): `DATABASE_URL` so the agent can create its logging tables in PostgreSQL

---

## Quick Start

### 1. Install

```bash
cd /path/to/SolidXCode/solidx-ai-agent
pip install -e "./vendor/mini-swe-agent" -e ".[dev]"

# After taking pull 
pip install -e ".[full]"

```

### 2. Configure environment

```bash
cp .env.example .env
```

Edit `.env` with your settings:

```bash
# Required: LLM API key (pick one)
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...

# Required for native mode: database connection
DATABASE_URL=postgresql://user:password@localhost:5432/solidx_db

# Optional: which LLM model to use (default: anthropic/claude-sonnet-4-20250514)
# MSWEA_MODEL_NAME=anthropic/claude-sonnet-4-20250514

# Optional: RAG support uses LlamaIndex
```

### 3. Run the agent

**Start the agent server (for Chat UI):**

```bash
solidx-agent serve --port 8765
```

**Single task (CLI):**

```bash
solidx-agent "Create a Library Management module with Book and Author models"
```

**Interactive mode:**

```bash
solidx-agent -i
```

```
SolidX AI Agent — Interactive Mode

Type your task and press Enter. Type quit or exit to stop.

solidx> List all existing modules
solidx> Create a Book model with title, author, isbn, and published_date fields
solidx> Add a Publisher model to the Library module
solidx> quit
```

**As a Python module:**

```bash
python -m solidx_agent "Show me the field metadata for the Book model"
```

### 4. Verify the installation (no external services needed)

```bash
MSWEA_SILENT_STARTUP=1 python -m pytest tests/ -v
```

All 166+ tests across 24 test files pass using mock adapters — no database or LLM API required.

---

## CLI Reference

```
Usage: solidx-agent [OPTIONS] [TASK] COMMAND [ARGS]...

Commands:
  serve         Start the agent server (FastAPI + WebSocket + REST + /mcp mount)
  mcp           Run as a local MCP server over stdio (for Claude Desktop)
  mcp-remote    Run as a remote MCP server over Streamable HTTP

Arguments:
  [TASK]    Task description for the agent

Options:
  -c, --config TEXT       Path to custom YAML config file
  -m, --mode TEXT         Tool mode (default: native)
  -l, --log-level TEXT    Logging level (default: INFO)
  -i, --interactive       Interactive prompt mode
  --help                  Show this message and exit.
```

**`serve` subcommand:**

```
Usage: solidx-agent serve [OPTIONS]

Options:
  -p, --port INTEGER      Port to bind the server (default: 8765)
  -H, --host TEXT         Host to bind the server (default: 0.0.0.0)
  -l, --log-level TEXT    Logging level (default: INFO)
```

**`mcp` subcommand (local STDIO MCP):**

```
Usage: solidx-agent mcp [OPTIONS]

Options:
  -l, --log-level TEXT       Logging level (default: INFO)
  --file-logs/--no-file-logs Write logs to Claude Desktop logs directory
```

Requires `SOLIDX_API_KEY` (a solid-core user API key, format `sldx_…`)
in the environment.  The user's role must include the `mcp:invoke`
permission.

**`mcp-remote` subcommand (remote Streamable-HTTP MCP):**

```
Usage: solidx-agent mcp-remote [OPTIONS]

Options:
  --host TEXT             Bind address (default: 0.0.0.0)
  -p, --port INTEGER      Listen port (default: 9000)
  --mount-path TEXT       Path to mount the MCP app at (default: /mcp)
  -l, --log-level TEXT    Logging level (default: INFO)
```

Requires `DATABASE_URL` (the same Postgres as solid-core).  Clients
authenticate by sending the `solidx-api-key: sldx_…` header on every
request.  `GET /health` is exempt from auth for liveness probes.

**Examples:**

```bash
# One-shot task
solidx-agent "Add an email field to the Contact model in the CRM module"

# Persistent server (Chat UI)
solidx-agent serve --port 8765

# Use a different LLM model
MSWEA_MODEL_NAME=openai/gpt-4o solidx-agent "Create a Task model"

# Custom config file
solidx-agent --config my_config.yaml "Build a dashboard"

# Debug logging
solidx-agent -l DEBUG "Inspect the Library module"
```

---

## Running the MCP server (authenticated)

The MCP layer is exposed three ways:

| Entry point | Auth | Audit log | Notes |
|---|---|---|---|
| `solidx-agent serve` (`/mcp` mount) | **none** — agent mode | none (uses `ss_agent_events`) | Convenience for the bundled agent server. |
| `solidx-agent mcp` (STDIO) | **required** — `SOLIDX_API_KEY` env var | `ss_mcp_audit_log` | Local Claude Desktop, Cursor stdio, etc. |
| `solidx-agent mcp-remote` (HTTP) | **required** — `solidx-api-key` header | `ss_mcp_audit_log` | Cloud desktop, Codex CLI, remote clients. |

Both dedicated MCP commands authenticate against **solid-core user API
keys** (the keys minted via `POST /iam/api-keys`).  Validation is
performed against the shared Postgres directly — no HTTP call to
solid-core per request, with a short in-process cache.  The user's role
must include the `mcp:invoke` permission (configurable under
`mcp.remote.required_permission`).

### Local Claude Desktop (`mcp` STDIO)

1. Mint an API key for your user in solid-core (admin UI or `POST /iam/api-keys`).
2. Configure Claude Desktop's `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "solidx": {
      "command": "solidx-agent",
      "args": ["mcp"],
      "env": {
        "SOLIDX_API_KEY": "sldx_...",
        "DATABASE_URL": "postgresql://user:pw@host:5432/db"
      }
    }
  }
}
```

3. Restart Claude Desktop.  If the key is invalid or the user lacks the
   `mcp:invoke` permission, the server fails to start and the error is
   surfaced in Claude Desktop's "developer tools" log.

The STDIO server re-validates the key periodically (default every 5
minutes, see `mcp.remote.stdio_revalidate_seconds`) and exits if the
key is revoked or loses its permission, so revocations propagate
without restarting Claude.

### Remote (`mcp-remote` Streamable HTTP)

```bash
export DATABASE_URL=postgresql://user:pw@host:5432/db   # same DB as solid-core
solidx-agent mcp-remote --host 0.0.0.0 --port 9000
```

Test from the command line:

```bash
# Liveness — no auth required
curl http://localhost:9000/health

# Without the header → 401
curl -X POST http://localhost:9000/mcp/ \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# With a valid, permitted key → 200
curl -X POST http://localhost:9000/mcp/ \
  -H 'content-type: application/json' \
  -H 'solidx-api-key: sldx_...' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Configure your remote MCP client (Cursor, Codex CLI, etc.) to use
`http://<host>:9000/mcp/` with header `solidx-api-key: sldx_…`.

### Audit log (`ss_mcp_audit_log`)

Every dedicated-MCP request is persisted to `ss_mcp_audit_log` —
auth events (`auth.startup`, `auth.denied`, `auth.revalidate`),
non-tool JSON-RPC method calls (`tools/list`, `initialize`, etc.),
and tool invocations (`tools/call`) with their inputs and outputs.

Useful queries:

```sql
-- Recent activity per user
SELECT username, method, tool_name, status, duration_ms, created_at
FROM ss_mcp_audit_log
ORDER BY created_at DESC
LIMIT 50;

-- Failed auth attempts in the last hour
SELECT created_at, transport, client_addr, error_message
FROM ss_mcp_audit_log
WHERE method = 'auth.denied' AND created_at > NOW() - INTERVAL '1 hour';

-- Most-used tools per user this week
SELECT username, tool_name, COUNT(*) AS calls,
       AVG(duration_ms) AS avg_ms
FROM ss_mcp_audit_log
WHERE method = 'tools/call' AND created_at > NOW() - INTERVAL '7 days'
GROUP BY username, tool_name
ORDER BY calls DESC;
```

Large request/response payloads are JSON-encoded and truncated to
`mcp.audit.max_payload_chars` (default 100 KB).  Set
`mcp.audit.log_response_results: false` to skip response bodies (only
inputs are logged).  Set `mcp.audit.enabled: false` to disable audit
logging entirely.

> **Limitation:** STDIO mode logs auth events and every tool call, but
> not non-tool JSON-RPC methods (e.g. `tools/list`, `initialize`).
> Those are only visible in the audit log when going through `mcp-remote`.

---

## solidctl Commands

When using the SolidX CLI (`solidctl`), you can start the agent server or run a single task without invoking `solidx-agent` directly:

```bash
solidctl agent start --port 8765    # start agent server
solidctl agent run "Create a CRM"   # single-shot task
```

---

## Tool Execution

The agent imports tool functions directly and calls them as async Python functions (native mode). Only native mode is supported.

```
Agent process → Python import → manage_data_model() → PostgreSQL
```

**Requirements:**
- `DATABASE_URL` pointing to the SolidX PostgreSQL database
- (Optional) LlamaIndex RAG index for documentation-aware tools

**Best for:** Local development, single-user workflows, fastest execution.

---

## Available Tools

The agent exposes 11 tools (10 SolidX + bash):

| Tool | Category | Purpose |
|------|----------|---------|
| `bash` | Shell | Execute any shell command |
| `manage_data_model` | Backend | CRUD for modules, models, and fields |
| `get_backend_context` | Backend | Read-only backend inspection (code context, datasources, controllers, services, providers) |
| `filesystem_tool` | Frontend | Unified frontend filesystem operations (search, read, patch) |
| `get_metadata` | Backend | Read-only metadata inspection (modules, models, fields, roles, security rules, menus, layouts, dashboards, etc.) |
| `manage_metadata` | Backend | CRUD for menus, roles, security rules, layouts, templates, etc. |
| `edit_backend_code` | Backend | Backend code editing (controllers, services, providers, etc.) |
| `run_solidctl` | Deployment | Execute solidctl CLI commands |
| `introspect_database` | Backend | Introspect existing database schemas |
| `content_crud` | Backend | CRUD operations on model records via REST API |

> **Note:** `edit_frontend_code` and `get_frontend_context` still exist in the codebase but are NOT in the active tool list — they were replaced by `filesystem_tool`.

---

## Configuration

### Config file (`config/solidx.yaml`)

The default config is bundled with the package. Override it with `--config`:

```yaml
agent:
  step_limit: 30              # max LLM query cycles
  cost_limit: 5.0             # max USD spend per run
  mode: confirm               # confirm / yolo / human

tools:
  mode: native                # only native mode is supported

environment:
  timeout: 120                # shell command timeout (seconds)
  cwd: ""                     # working directory (default: current)

server:
  port: 8765
  host: "0.0.0.0"
  session_timeout: 1800
  max_sessions: 10

model:
  model_name: anthropic/claude-sonnet-4-20250514
  cost_tracking: ignore_errors
```

### Environment variable overrides

Any config value can be overridden via environment variables:

| Environment Variable | Config Path | Example |
|---------------------|-------------|---------|
| `MSWEA_MODEL_NAME` | `model.model_name` | `openai/gpt-4o` |
| `SOLIDX_PROJECT_ROOT` | `environment.cwd` | `/path/to/project` |
| `SOLIDX_AGENT_STEP_LIMIT` | `agent.step_limit` | `50` |
| `SOLIDX_AGENT_COST_LIMIT` | `agent.cost_limit` | `10.0` |
| `SOLIDX_SERVER_PORT` | `server.port` | `8765` |
| `SOLIDX_SERVER_HOST` | `server.host` | `0.0.0.0` |
| `SOLIDX_SESSION_TIMEOUT` | `server.session_timeout` | `1800` |
| `SOLIDX_MAX_SESSIONS` | `server.max_sessions` | `10` |

---

## Project Structure

```
solidx-ai-agent/
├── vendor/mini-swe-agent/               # Agent framework (editable install, not modified)
├── pyproject.toml                       # Package config and dependencies
├── .env.example                         # Environment variable template
├── README.md                            # This file
├── ARCHITECTURE.md                      # Detailed technical architecture reference
├── run.py                               # CLI entry point (Typer)
├── console.py                           # Rich terminal event listeners
├── exceptions.py                        # Agent exceptions (e.g. TurnComplete)
├── agent-ui/                            # Bundled React/Vite Chat UI
├── agents/
│   └── solidx_agent.py                  # Agent with lifecycle events
├── config/
│   ├── loader.py                        # YAML + env var config loading
│   └── solidx.yaml                      # Default configuration
├── db/
│   ├── base.py                          # SQLAlchemy declarative base
│   ├── session.py                       # Engine / session factory for agent DB
│   ├── repository.py                    # Persistence helpers
│   └── models/                          # ORM models (sessions, events)
├── environments/
│   └── solidx_environment.py            # Hybrid bash + SolidX tool executor
├── events/
│   ├── emitter.py                       # Async EventEmitter
│   └── events.py                        # Typed event dataclasses
├── models/
│   ├── solidx_model.py                  # Multi-tool LLM model
│   └── fast_llm.py                      # FastLLM for auxiliary tasks (intent classification, session titles)
├── prompts/
│   ├── system_prompt.md                 # SolidX builder system prompt
│   └── instance_prompt.md               # Per-task prompt template
├── server/
│   ├── app.py                           # FastAPI app: WebSocket + REST
│   ├── sessions.py                      # Multi-turn session manager
│   └── db_listener.py                   # Persists events to PostgreSQL
├── skills/                              # Skill library
│   ├── backend-studio/                  # 40 backend skills
│   ├── frontend-studio/                 # 4 frontend skills
│   ├── deployment-studio/               # 1 deployment skill
│   ├── platform/                        # 2 platform-level skills
│   ├── tools/                           # (reserved)
│   └── workflows/                       # (reserved)
├── solidx_platform/
│   ├── tools/                           # Tool implementations (includes deprecated edit_frontend_code, get_frontend_context)
│   └── helpers/                         # Helpers: backend_step_engine.py, code_context_selector.py, json_patch_helper.py, …
├── tools/
│   ├── adapter.py                       # Native tool adapter
│   ├── registry.py                      # OpenAI function schema builder
│   └── composite.py                     # Multi-step orchestration helpers
└── tests/                               # 166+ tests across 24 test files (all pass without external services)
```

**Dependency graph:**

```
solidx-ai-agent
  ├── sqlalchemy>=2.0, psycopg2-binary, fastapi, uvicorn, websockets, …
  └── mini-swe-agent        (pip install -e ./vendor/mini-swe-agent)
        └── litellm, pydantic, jinja2, …
```

---

## How It Works

### CLI and interactive mode

1. **User provides a task** via CLI argument or interactive prompt
2. **Config loads** from `solidx.yaml`, merged with environment variable overrides
3. **Tool adapter initializes** — discovers tool functions from the installed platform tools (native mode)
4. **Tool registry builds** OpenAI function-calling schemas from all discovered tools
5. **Agent loop starts** — LLM receives the system prompt (SolidX platform context + tool descriptions) and the user's task; **FastLLM classifies user intent** (e.g. backend vs frontend task) to select the right skill/workflow
6. **LLM reasons and calls tools** — can call `bash` for shell commands or any of the 10 SolidX tools
7. **Environment dispatches** — routes bash to subprocess, SolidX tools to the adapter
8. **Events stream** — every action emits typed events to the console (or WebSocket clients in server mode)
9. **Loop repeats** until the LLM signals completion or limits are reached
10. **Results displayed** with total steps and cost

### Server mode (Chat UI)

1. **Process starts** with `solidx-agent serve` (or `solidctl agent start`); FastAPI binds to `host`/`port` from config or flags
2. **Lifespan hook** loads config, initializes the tool adapter and registry, optionally creates SQLAlchemy engine/session factory for the **agent** database (same `DATABASE_URL` as native tools when logging is enabled)
3. **SessionManager** tracks WebSocket-backed sessions with idle timeout and max concurrent sessions
4. **Client connects** to `/ws/agent`, sends `start_session` → server returns `session_id` and streams lifecycle events for that connection
5. **Each user message** runs one **turn** — conversation history is kept in the session so the LLM sees prior turns (`UserMessage` / `TurnCompleteEvent` participate in the event stream and optional DB logging)
6. **DatabaseEventListener** (when DB is configured) writes interaction events to PostgreSQL for auditing and analytics
7. **REST** — `POST /api/agent/run` runs a single task in a temporary session; `GET`/`DELETE /api/agent/sessions` manage server-side sessions

---

## Streaming & Events

The agent emits typed events at every lifecycle point. This powers the CLI and the Chat UI over WebSocket.

**Events emitted during a run (representative flow):**

```
AgentStarted → UserMessage → StepStarted → LlmComplete → ToolCalling → ToolResult → StepComplete → … → TurnCompleteEvent → AgentComplete
```

(`UserMessage` records inbound user text in multi-turn flows; `TurnCompleteEvent` marks the end of one assistant turn.)

**CLI output example:**

```
╭──────────── SolidX Agent Started ─────────────╮
│ Create a Library module with Book model        │
╰────────────────────────────────────────────────╯
──────────── Step 1  (cost so far: $0.0000) ─────────────
Assistant (step 1, $0.0023):
Let me check what modules already exist first.
  > solid_get_module_metadata: {"module_matches": "Library"}

Calling tool: solid_get_module_metadata
Result: OK 234ms

──────────── Step 2  (cost so far: $0.0023) ─────────────
...
──────────────────────────────────────────────────────────
╭──────────── Agent Complete ────────────────────╮
│ Status: Submitted                              │
│ Steps: 4  |  Cost: $0.0089                     │
╰────────────────────────────────────────────────╯
```

**Chat UI — WebSocket** (`/ws/agent`): clients and server exchange JSON messages. **Client → server** (multi-turn protocol):

```json
{"action": "start_session"}
{"action": "message", "session_id": "<uuid>", "content": "Create a CRM module"}
{"action": "end_session", "session_id": "<uuid>"}
```

**Server → client:** after `start_session`, the server sends `session_started`, then streams typed events (same shape as below) for each turn, and ends the turn with `turn_complete`.

```json
{"type": "session_started", "session_id": "<uuid>"}
{"type": "UserMessage", "data": {"content": "Create a CRM module", "session_id": "<uuid>", "turn_number": 1}}
{"type": "StepStarted", "data": {"step": 1, "cost_so_far": 0.0}}
{"type": "ToolCalling", "data": {"tool_name": "solid_create_module", "arguments": {"prompt": "..."}}}
{"type": "ToolResult", "data": {"tool_name": "solid_create_module", "output": "...", "returncode": 0}}
{"type": "TurnCompleteEvent", "data": {"content": "...", "turn_number": 1, "total_cost": 0.01, "total_steps": 3}}
{"type": "turn_complete", "data": {"content": "...", "session_id": "<uuid>", "turn_count": 1}}
{"type": "session_ended", "session_id": "<uuid>"}
```

See **[docs/CHAT_UI_DEVELOPER_GUIDE.md](docs/CHAT_UI_DEVELOPER_GUIDE.md)** for full protocol details, REST endpoints, and integration notes.

---

## Example Tasks to Try

Once set up with a database and API key:

```bash
# Inspect existing state
solidx-agent "List all existing modules and their models"

# Explore metadata
solidx-agent "What modules exist in this project? Show me all models and their field counts."

# Create from scratch
solidx-agent "Create a Blog module with Post and Comment models. Posts should have title, content, published_date, and status fields. Comments should have body, author_name, and a relation to Post."

# Modify existing structures
solidx-agent "Add an email and phone_number field to the Author model in the Library module"

# Layout changes
solidx-agent "Update the list view for Books to show title, author, isbn, and published_date columns"

# Code changes
solidx-agent "Add a custom endpoint to the Book controller that returns books published in the last 30 days"

# Multi-step workflows
solidx-agent "Create a complete Task Management module with Project, Task, and Comment models. Projects have name and description. Tasks have title, description, status (todo/in-progress/done), priority, and due_date. Comments belong to Tasks. Set up menus for all models."
```

---

## Troubleshooting

**"DATABASE_URL environment variable is not set"**
Set `DATABASE_URL` in `.env` pointing to your SolidX PostgreSQL database.

**"No default model set"**
Set `MSWEA_MODEL_NAME` in `.env` (e.g., `anthropic/claude-sonnet-4-20250514`) or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`.

**Tests fail on import**
Run `pip install -e "./vendor/mini-swe-agent" -e ".[dev]"` to ensure both packages are installed as editable.

---

## Further Reading

- **[ARCHITECTURE.md](ARCHITECTURE.md)** — Detailed technical architecture, component deep dives, data flow diagrams, and extension points
- **[docs/CHAT_UI_DEVELOPER_GUIDE.md](docs/CHAT_UI_DEVELOPER_GUIDE.md)** — Chat UI integration: WebSocket protocol, REST API, and session flow
- **[mini-swe-agent docs](https://mini-swe-agent.com)** — Framework documentation for the underlying agent loop
- **[LiteLLM docs](https://docs.litellm.ai)** — Supported LLM providers and model names
