Metadata-Version: 2.4
Name: archit-studio
Version: 0.5.1
Summary: AI-powered architecture studio built on archit-app — multi-agent design assistant with FastAPI + React UI.
Keywords: AI,BIM,agents,architecture,crewai,fastapi,floorplan
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.40.0
Requires-Dist: archit-app>=0.3.4
Requires-Dist: crewai-tools>=0.14.0
Requires-Dist: crewai>=0.80.0
Requires-Dist: dynaconf>=3.2.0
Requires-Dist: fastapi>=0.110.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: openai>=1.30.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: tenacity>=8.3.0
Requires-Dist: uvicorn[standard]>=0.29.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="logo/archit-studio-icon-dark.svg">
  <img src="logo/archit-studio-icon-light.svg" alt="archit-studio" width="120">
</picture>

# archit-studio

AI-powered architecture design studio built on [archit-app](../archit-app/README.md).

```bash
pip install archit-studio
archit-studio          # starts FastAPI server at http://localhost:8000
```

[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../archit-app/LICENSE)

---

## Overview

`archit-studio` wraps the `archit-app` library in a multi-agent AI design assistant with a **React + FastAPI** web UI. A **6-specialist CrewAI crew** runs sequentially with LLM-based planning — each agent is an expert in its domain and acts only on tasks relevant to the user's request. Every agent calls `archit-app` Python tools directly; the building model is kept in-session and can be exported to SVG, JSON, DXF, or IFC at any time.

**Relationship to `archit-app`:**

| Layer | Package | Role |
|-------|---------|------|
| Data model + I/O | `archit-app` | Immutable building model, geometry, analysis, exports |
| AI agents + UI | `archit-studio` | CrewAI crew, FastAPI + React UI, session state, LLM routing |

`archit-studio` depends on `archit-app` as a PyPI dependency and never modifies the core library.

---

## Architecture

```
archit-studio/
├── studio/
│   ├── config.py          — Dynaconf settings (settings.toml + .env), model registry
│   ├── state/
│   │   └── session.py     — Per-session BuildingState + History (undo/redo) + JSON persistence
│   ├── agents/
│   │   ├── definitions.py — Role, goal, backstory for each of the 6 specialist agents
│   │   ├── crew.py        — CrewAI sequential crew assembly, planning, run()/arun() entry points
│   │   ├── tasks.py       — Per-specialist task factories
│   │   ├── tool_catalog.py — Tool registry, OpenAI schemas, and per-agent tool sets
│   │   └── tools/         — CrewAI tools wrapping archit-app API calls
│   │       ├── building_tools.py   — add_level, add_room, add_wall, add_opening, staircase,
│   │       │                         copy_element_to, mirror_element_tool, array_element_tool,
│   │       │                         undo/redo
│   │       ├── structural_tools.py — add_column, add_beam, add_slab, add_ramp, add_elevator, set_grid
│   │       ├── analysis_tools.py   — compliance, egress, accessibility, daylighting, visibility,
│   │       │                         adjacency, set_land
│   │       ├── interior_tools.py   — add_furniture, add_text_annotation, set_room_material
│   │       └── io_tools.py         — export_svg, export_json, export_pdf, export_geojson,
│   │                                 validate, save/load session
│   └── ui/
│       ├── app.py         — CLI entry point (uvicorn)
│       └── server.py      — FastAPI app: WebSocket chat, session management, file upload, SPA serving
├── frontend/              — React + TypeScript SPA (Vite)
│   ├── src/
│   │   ├── App.tsx
│   │   ├── types.ts
│   │   ├── hooks/useSession.ts    — WebSocket state management
│   │   └── components/            — ChatWindow, Message, MessageInput, SettingsPanel, StatsPanel
│   └── dist/              — Built output served by FastAPI (generated by npm run build)
├── data/sessions/         — Saved session JSON files (auto-created at runtime)
├── settings.toml          — Default configuration
├── Dockerfile             — Multi-stage: Node (React build) → Python (FastAPI server)
└── pyproject.toml
```

---

## The 6-Specialist Crew

The crew runs under `Process.sequential` with `planning=True`. Before execution, CrewAI's planning LLM analyses the user request and creates a step-by-step plan injected into every agent's task. Agents execute in order; each agent reads prior agents' output via context chaining, and agents whose domain is not relevant simply pass.

| Agent | Role | Tools |
|-------|------|-------|
| **Architect** | Spatial layout — rooms, walls, openings, levels, staircases | Building CRUD + copy/mirror/array + undo/redo |
| **Structural Engineer** | Columns, beams, slabs, ramps, elevators, structural grid | Structural tools + copy/mirror/array |
| **Compliance Analyst** | Zoning, FAR, egress, accessibility, daylighting, sightlines | Analysis tools + `set_land` + visibility check |
| **Interior Designer** | Furniture, materials, text annotations | Interior tools + copy/array |
| **Space Programmer** | Area reports, adjacency analysis, brief compliance | Area + adjacency tools |
| **BIM Coordinator** | SVG/JSON/PDF/GeoJSON export, model validation, session save/load | I/O tools |

Every agent also receives `get_building_context` and `get_building_detailed_context` (read-only shared tools).

The planning LLM uses the `project_manager` model slot (configurable) and runs once per request before any agent executes.

### Full tool list

| Tool | Agent(s) | Description |
|------|----------|-------------|
| `get_building_context` | All | Compact building summary |
| `get_building_detailed_context` | All | Per-room bounding boxes, centroids, wall/column data |
| `add_level` | Architect | Add a floor at a given elevation |
| `add_room` | Architect | Add a polygon room with a program type |
| `add_rooms_batch` | Architect | Add many rooms in one call (preferred for full floor plan layouts) |
| `add_wall` | Architect | Add a straight wall between two points |
| `add_walls_batch` | Architect | Add many walls in one call (preferred for perimeter placement) |
| `add_opening_to_wall` | Architect | Add a door or window to an existing wall |
| `get_walls_for_room` | Architect, Compliance | Find all walls adjacent to a room — returns wall IDs, facing, start/end points |
| `add_staircase` | Architect | Add a staircase connecting two levels |
| `remove_element` | Architect, Structural, Interior | Delete any element by UUID |
| `update_building_metadata` | Architect | Set project name, architect, client, date |
| `undo_last_change` / `redo_last_change` | Architect | History navigation |
| `copy_element_to` | Architect, Structural, Interior | Translate-copy any element by (dx, dy) offset |
| `mirror_element_tool` | Architect, Structural | Mirror any element across a vertical or horizontal axis |
| `array_element_tool` | Architect, Structural, Interior | Create a linear array of N copies with a step offset |
| `add_column` | Structural | Add a rectangular or circular structural column |
| `add_beam` | Structural | Add a structural beam between two points |
| `add_slab` | Structural | Add a floor, roof, or basement slab |
| `add_ramp` | Structural | Add an accessible, service, or parking ramp |
| `add_elevator` | Structural | Add a multi-level elevator |
| `set_structural_grid` | Structural | Define the column grid with named axes |
| `set_land` | Compliance | Set site boundary, address, and zoning parameters |
| `run_compliance_check` | Compliance | Check FAR, lot coverage, height, setbacks |
| `run_area_report` | Compliance, Space | Net/gross area by program type |
| `run_egress_report` | Compliance | Emergency exit distance compliance |
| `run_accessibility_check` | Compliance | Door widths, corridor widths, ramp slopes |
| `run_daylight_report` | Compliance | Window-to-floor ratio and solar orientation per room |
| `run_visibility_check` | Compliance | Isovist (visibility polygon) from any viewpoint |
| `run_adjacency_analysis` | Compliance, Space | Room adjacency graph |
| `add_furniture` | Interior | Place a furniture item by type and centre position |
| `add_text_annotation` | Interior | Add a text label to the floor plan |
| `set_room_material` | Interior | Assign a material finish to a room |
| `export_level_svg` | BIM | Export a floor level as an SVG drawing |
| `export_building_json` | BIM | Export the full building as canonical JSON |
| `export_building_pdf` | BIM | Export all floors as a multi-page PDF (A4/A3/A2) |
| `export_level_geojson` | BIM | Export a floor level as GeoJSON for GIS tools |
| `validate_building` | BIM | Check model for errors and inconsistencies |
| `save_session` | BIM | Persist the session to disk |

---

## Installation

**Prerequisites:** Python 3.11+

```bash
pip install archit-studio
```

Then install `archit-app`'s optional extras to enable SVG export, analysis, and image features:

```bash
pip install "archit-app[io,image,pdf,analysis]>=0.3.4"
```

**Environment setup:**

Create a `.env` file in the `archit-studio/` directory:

```dotenv
OPENAI_API_KEY=sk-...          # required for OpenAI models
ANTHROPIC_API_KEY=sk-ant-...   # required for Claude models
```

---

## Running

```bash
archit-studio
```

Or directly with uvicorn:

```bash
uvicorn studio.ui.server:app --host 0.0.0.0 --port 8000
```

Open `http://localhost:8000` in a browser.

**Frontend development** (hot-reload):

```bash
cd frontend
npm install
npm run dev        # starts Vite dev server at http://localhost:3000
                   # proxies /api and /ws to the Python server at :8000
```

---

## Docker

**docker-compose (recommended):**

```bash
# 1. Create a .env file with your API keys
echo "OPENAI_API_KEY=sk-..." > archit-studio/.env

# 2. Build and start
docker compose -f archit-studio/docker-compose.yml up --build
```

Open `http://localhost:8000`.

**Plain docker build:**

```bash
docker build -f archit-studio/Dockerfile -t archit-studio archit-studio/
docker run --rm -p 8000:8000 \
  --env-file archit-studio/.env \
  -v archit-studio-sessions:/data/sessions \
  archit-studio
```

The Dockerfile is multi-stage: Stage 1 builds the React frontend (Node 22), Stage 2 runs the FastAPI server (Python 3.11). The built React bundle is copied from Stage 1 and served as static files by FastAPI.

**Environment variables** (all optional — override `settings.toml` values):

| Variable | Default | Description |
|----------|---------|-------------|
| `OPENAI_API_KEY` | — | Required for OpenAI models |
| `ANTHROPIC_API_KEY` | — | Required for Claude models |
| `STUDIO_MODEL` | `gpt-4o-mini` | Default LLM for all agents |
| `STUDIO_VERBOSE_AGENTS` | `false` | Print agent chain-of-thought to logs |
| `STUDIO_DATA_DIR` | `/data/sessions` | Session save directory (inside container) |

Session JSON files are stored in the named volume `sessions` and persist across container restarts.

---

## API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| `POST` | `/api/session` | Create a new session — returns `session_id` and welcome message |
| `WS` | `/ws/{session_id}` | Real-time bidirectional chat (JSON events) |
| `POST` | `/api/upload/{session_id}` | Upload `.json` building or `.geojson` land parcel |
| `PUT` | `/api/settings/{session_id}` | Change active LLM model |
| `GET` | `/api/models` | List supported models with labels |

**WebSocket event types (server → client):**

| Type | Payload | Description |
|------|---------|-------------|
| `thinking` | `status` | Typing indicator |
| `message` | `author`, `content` | Agent response (Markdown) |
| `svg` | `level_index`, `level_name`, `room_count`, `area`, `svg` | Floor plan SVG |
| `svg_error` | `level_index`, `error` | SVG generation failure |
| `stats` | `project_name`, `total_levels`, `total_rooms`, `gross_floor_area`, `area_by_program`, `model` | Building summary |
| `error` | `message` | Session-level error |

---

## Configuration

All settings live in `settings.toml` and can be overridden by environment variables prefixed `STUDIO_` or by a `.env` file.

```toml
[default]
model = "gpt-4o-mini"          # default LLM for all agents
verbose_agents = false          # show full agent chain-of-thought in terminal
data_dir = "./data/sessions"    # where session JSON files are saved
max_history = 50                # undo/redo stack depth

[default.agents.project_manager]
model = ""   # planning LLM — empty → uses top-level default; set to a stronger model to improve planning
```

**Supported models** (selectable in the UI settings panel):

| ID | Provider | Notes |
|----|----------|-------|
| `gpt-4o-mini` | OpenAI | Default — fast and cost-efficient |
| `gpt-4o` | OpenAI | Higher capability |
| `gpt-5-mini` | OpenAI | Next-gen fast |
| `gpt-5` | OpenAI | Next-gen flagship |
| `claude-3-5-haiku-20241022` | Anthropic | Fast alternative |
| `claude-3-5-sonnet-20241022` | Anthropic | High-quality alternative |
| `claude-opus-4-5` | Anthropic | Most capable |

Override at runtime: `STUDIO_MODEL=claude-3-5-sonnet-20241022 archit-studio`

---

## Session State

Each session gets an isolated `SessionState` object holding:

- The current `Building` (from `archit-app`)
- A `History` stack for undo/redo (depth controlled by `max_history`)
- The active model name
- A session ID used for saving/loading JSON files to `data/sessions/`

Sessions are persisted as JSON and can be reloaded by uploading a `.json` file in the chat or asking the BIM Coordinator to load a named session.

---

## File Uploads

Drop files into the chat to import them:

| File type | Result |
|-----------|--------|
| `.json` (archit-app building) | Replaces current building in session |
| `.geojson` / `.geo.json` | Imported as a new Level in the current building |

---

## Auto SVG Export

After each response the server checks whether any drawable elements (rooms or walls) were added or changed. If so, SVG floor plans for every level are automatically exported and streamed to the UI as `svg` events. The BIM Coordinator can also export explicitly at any time via `export_level_svg`.

---

## Development

```bash
pip install -e "archit-studio[dev]"
pytest
ruff check studio/
mypy studio/
```

---

## Changelog

### 0.5.1
- **Tools: batch creation** — `add_rooms_batch` and `add_walls_batch` add entire floor-plan layouts in a single tool call, reducing round-trips and token usage. Both accept a JSON array string and are assigned to the Architect agent.
- **Tools: `get_walls_for_room`** — spatial query that returns every wall adjacent to a given room, with wall ID, facing direction, start/end points, and length. Used by the Architect to find the correct wall before calling `add_opening_to_wall`, and by the Compliance Analyst to check window placement.
- **Tools: fixed structured analysis results** — `run_egress_report`, `run_daylight_report`, and `run_accessibility_check` previously serialised findings as plain strings. They now return structured dicts with `compliant`, `issue`, and `suggested_fix` fields per room/element.
- **`get_building_detailed_context` now supports scoping** — new optional params `level_index`, `include_walls`, `include_furniture`, `include_columns` let agents request only the data they need, significantly reducing context window usage on large buildings.
- **Anthropic Claude models** — `claude-3-5-haiku-20241022`, `claude-3-5-sonnet-20241022`, `claude-opus-4-5` are now available in the model selector, powered by the `anthropic` SDK directly (same runner, parallel code path to OpenAI).
- **Dependency:** bumped `archit-app` pin to `>=0.3.4` to pull in the new batch APIs and Wall geometry helpers.

### 0.5.0
- **Tools: element transforms** — three new tools wrapping `archit_app.elements.transform_utils`: `copy_element_to` (translate-copy any element by dx/dy), `mirror_element_tool` (reflect across a vertical or horizontal axis), `array_element_tool` (linear array of N copies with a repeating step). Assigned to Architect, Structural, and Interior agents.
- **Tools: visibility / isovist analysis** — `run_visibility_check` wraps `archit_app.analysis.visibility.compute_isovist()`, ray-casting from any `(x, y)` viewpoint to report visible area in m² and identify which room the observer is in. Assigned to Compliance Analyst.
- **Tools: PDF export** — `export_building_pdf` wraps `archit_app.io.pdf.save_building_pdf()`, producing a multi-page vector PDF (A4/A3/A2, auto-landscape) with one page per floor. Assigned to BIM Coordinator.
- **Tools: GeoJSON export** — `export_level_geojson` wraps `archit_app.io.geojson.level_to_geojson_str()`, exporting rooms, walls, columns, and openings as a GeoJSON FeatureCollection for QGIS, Mapbox, or Leaflet. Assigned to BIM Coordinator.
- **Fix: `run_daylight_report` was unreachable** — the tool was defined in `analysis_tools.py` but never registered in `tool_catalog.py` or assigned to any agent. Now correctly wired into the registry, schema list, and `COMPLIANCE_TOOLS`.
- **tool_catalog: full tool table** — README now documents every tool, its owning agent(s), and a one-line description.

### 0.4.0
- **UI: replaced Chainlit with FastAPI + React** — full custom web UI with dark theme, WebSocket real-time chat, inline SVG floor plans, model selector, file upload, and building stats sidebar.
- **UI: phase-gate workflow** — after each design phase (Site & Brief → Floor Plan → Furniture & Finishes → Validation & Export) the UI surfaces a phase-gate card with a progress pip row, a "Continue →" button, and an inline feedback prompt for iterating before advancing.
- **UI: SVG layer toggling** — every floor-plan card includes a layer toolbar (Rooms, Walls, Columns, Furniture, Annotations, …) with per-layer and "All/None" toggle buttons; layers are discovered dynamically from the SVG's `<g id="…">` groups.
- **UI: thinking indicator** — animated three-dot bounce indicator with "Consulting the design team…" label appears while the crew is running.
- **UI: starter prompts** — four quick-start buttons (3-bedroom house, office layout, compliance check, export floor plans) appear on a fresh session before the first user message.
- **UI: rich Markdown rendering** — agent messages are rendered via `react-markdown` + `remark-gfm`, with styled headings, lists, tables, inline code, and code blocks.
- **UI: BIM Coordinator accent** — BIM Coordinator messages carry a `--datum` amber left-border accent to distinguish I/O and export events from design-team messages.
- **Agents: switched to `Process.sequential` + `planning=True`** — eliminates the CrewAI hierarchical delegation bug that caused `"tool_calls must be followed by tool messages"` 400 errors from OpenAI. The planning LLM (Project Manager model slot) analyses the full request before execution and injects a coherent plan into every specialist task.
- **Agents: native async** — `arun()` now uses `crew.akickoff()` directly instead of a thread wrapper, reducing latency for concurrent WebSocket sessions.
- **Agents: correct LLM import** — fixed `from crewai import LLM` (was `from crewai.llm import LLM`).
- **Docker: fixed extras installation** — archit-app extras (`io`, `image`, `pdf`, `analysis`) are now installed correctly on the `archit-app` package, ensuring `svgwrite`, `networkx`, `scipy`, and `pillow` are present at runtime.
- **SVG export: in-memory** — `level_to_svg()` is now called directly (no disk I/O), eliminating file permission issues in containers.

### 0.3.0
- Fix: CrewAI 400 `tool_calls` error — patch `_prepare_llm_call` to strip dangling tool_calls.
- Fix: session_id embedded in every agent's goal.
- Fix: SVG auto-export trigger includes walls.
- UI: Chainlit 2.x theme migration.

### 0.2.0
- Added 7-agent hierarchical CrewAI crew with specialist delegation.
- Chainlit 2.x UI with file upload, session management, inline SVG display.

### 0.1.x
- Initial release: single-agent crew, Docker support, basic Chainlit integration.

---

## Brand Colors

| Token | Hex | Use |
|-------|-----|-----|
| **Void** | `#0C1018` | Night sky — deep shadows, primary backgrounds |
| **Vellum** | `#E8EDF5` | Tracing paper — primary text on dark |
| **Blueprint** | `#3B82F6` | Technical lines — accents, links, user bubbles |
| **Datum** | `#F59E0B` | Reference point — BIM highlights, area stats |

---

## License

MIT — see [`archit-app/LICENSE`](../archit-app/LICENSE).
