+
+Thanks to all our contributors! Your contributions make this project better every day.
+
+[](https://github.com/Huynhthuongg/AGENTS.md/graphs/contributors)
+
+
+
+
+
+---
+
+## ๐ Documentation
+
+- ๐ [**Product Specification**](docs/SPECIFICATION.md)
+- ๐๏ธ [**Architecture Overview**](docs/ARCHITECTURE.md)
+- ๐ [**API Examples**](#-api-examples)
+- ๐ [**Changelog**](docs/CHANGELOG.md)
+
+---
+
+## ๐ Issues & Feedback
+
+Found a bug? Have a feature request? We'd love to hear from you!
+
+- ๐ [Report a Bug](https://github.com/Huynhthuongg/AGENTS.md/issues/new?template=bug_report.md)
+- โจ [Request a Feature](https://github.com/Huynhthuongg/AGENTS.md/issues/new?template=feature_request.md)
+- ๐ฌ [Start a Discussion](https://github.com/Huynhthuongg/AGENTS.md/discussions/new)
+
+---
+
+## ๐ License
+
+This project is licensed under the **GNU Affero General Public License v3.0** (AGPL-3.0).
+
+This means:
+- โ You can use, modify, and distribute this software
+- โ You must share your modifications if you use it
+- โ You must include the original license
+
+See [LICENSE](LICENSE) for full details.
+
+---
+
+
+
+### ๐ Ready to Get Started?
+
+[๐ Read the Docs](docs/SPECIFICATION.md) โข [๐ป Clone the Repo](https://github.com/Huynhthuongg/AGENTS.md) โข [โญ Star on GitHub](https://github.com/Huynhthuongg/AGENTS.md)
+
+**Made with โค๏ธ by [Huynhthuongg](https://github.com/Huynhthuongg)**
-- Never hardcode secrets in generated output.
-- Redact common API key, token, secret, and password patterns from persisted requirement snapshots.
-- Reject unsafe generated paths and unsafe API `output_dir` values.
-- Add conservative HTTP headers to API responses.
+
-## License
+
+
+
-AGPL-3.0-only. See [LICENSE](LICENSE).
+
diff --git a/README_WEATHER.md b/README_WEATHER.md
new file mode 100644
index 0000000..6f769ee
--- /dev/null
+++ b/README_WEATHER.md
@@ -0,0 +1,230 @@
+# ๐ค๏ธ Weather Dashboard
+
+A modern, responsive weather dashboard that fetches real-time weather data from OpenWeatherMap API.
+
+## โจ Features
+
+- ๐ **Search Cities Worldwide** - Find weather for any city globally
+- ๐ค๏ธ **Real-time Weather Data** - Current conditions with temperature, humidity, wind, pressure
+- โญ **Save Favorites** - Bookmark your favorite cities to SQLite
+- ๐ฑ **Responsive Design** - Works perfectly on mobile, tablet, and desktop
+- ๐ **Security** - HTTP security headers, input validation
+- โก **Fast & Async** - Built with FastAPI and aiohttp
+- ๐จ **Modern UI** - Beautiful gradient design with smooth animations
+
+## ๐ Quick Start
+
+### Prerequisites
+
+- Python 3.10+
+- OpenWeatherMap API key (free tier available)
+
+### Installation
+
+1. Clone and setup
+```bash
+git clone https://github.com/Huynhthuongg/AGENTS.md.git
+cd AGENTS.md
+git checkout feature/weather-dashboard
+```
+
+2. Install dependencies
+```bash
+pip install fastapi uvicorn aiohttp
+```
+
+3. Get your free OpenWeatherMap API key
+- Visit https://openweathermap.org/api
+- Sign up for a free account
+- Generate an API key
+
+4. Set up environment
+```bash
+cp config/weather.env.example .env
+# Edit .env and add your OpenWeatherMap API key
+```
+
+5. Run the application
+```bash
+export OPENWEATHER_API_KEY="your_api_key_here"
+python -m weather_dashboard.app
+```
+
+Open your browser: **http://127.0.0.1:8001**
+
+## ๐ API Endpoints
+
+### `GET /`
+Serves the main dashboard HTML.
+
+### `GET /health`
+Health check endpoint.
+```json
+{"status": "ok", "version": "1.0.0"}
+```
+
+### `GET /api/weather`
+Get current weather for coordinates.
+
+**Parameters:**
+- `lat` (float, required) - Latitude
+- `lon` (float, required) - Longitude
+
+**Response:**
+```json
+{
+ "city": "London",
+ "country": "GB",
+ "temperature": 15.5,
+ "feels_like": 14.2,
+ "temp_min": 13.0,
+ "temp_max": 17.0,
+ "humidity": 72,
+ "pressure": 1013,
+ "wind_speed": 3.5,
+ "wind_deg": 240,
+ "cloudiness": 60,
+ "description": "partly cloudy",
+ "icon": "02d",
+ "icon_url": "https://openweathermap.org/img/wn/02d@2x.png",
+ "sunrise": "2026-06-03T05:30:00",
+ "sunset": "2026-06-03T21:15:00"
+}
+```
+
+### `GET /api/search`
+Search for cities.
+
+**Parameters:**
+- `q` (string, required, min 2 chars) - City name
+- `limit` (int, optional, default 5) - Max results (1-20)
+
+**Response:**
+```json
+[
+ {
+ "name": "London",
+ "latitude": 51.5085,
+ "longitude": -0.1257,
+ "country": "GB",
+ "state": null
+ }
+]
+```
+
+### `GET /api/saved-cities`
+Get all saved cities.
+
+**Response:**
+```json
+[
+ {
+ "id": 1,
+ "city_name": "London",
+ "latitude": 51.5085,
+ "longitude": -0.1257,
+ "added_at": "2026-06-03T10:30:00"
+ }
+]
+```
+
+### `POST /api/saved-cities`
+Save a city to favorites.
+
+**Parameters:**
+- `city_name` (string, required) - City name
+- `latitude` (float, required) - Latitude
+- `longitude` (float, required) - Longitude
+
+### `DELETE /api/saved-cities/{city_id}`
+Delete a saved city.
+
+## ๐ ๏ธ Development
+
+### Project Structure
+
+```
+weather_dashboard/
+โโโ __init__.py # Package initialization
+โโโ app.py # FastAPI application
+โโโ config.py # Configuration management
+โโโ models.py # Data models
+โโโ weather_service.py # OpenWeatherMap integration
+โโโ database.py # SQLite operations
+โโโ templates.py # HTML templates
+```
+
+### Configuration
+
+Edit `.env` file to customize settings:
+
+```bash
+# OpenWeatherMap API
+OPENWEATHER_API_KEY=your_key
+
+# Server
+WEATHER_HOST=127.0.0.1
+WEATHER_PORT=8001
+
+# Database
+DATABASE_URL=sqlite:///weather_dashboard.db
+```
+
+## ๐ Security
+
+- โ HTTP security headers (X-Content-Type-Options, X-Frame-Options, etc.)
+- โ Input validation with Pydantic
+- โ Safe path validation
+- โ Error handling and logging
+- โ CORS-friendly
+
+## ๐ฑ Responsive Design
+
+- Desktop: 2-column grid layout
+- Tablet: Responsive grid
+- Mobile: Single column stack
+
+## ๐จ UI Features
+
+- Beautiful gradient background
+- Smooth animations and transitions
+- Loading spinner
+- Error messages
+- Real-time weather icons
+- Weather details cards
+
+## ๐ Troubleshooting
+
+### "OPENWEATHER_API_KEY environment variable is required"
+```bash
+export OPENWEATHER_API_KEY="your_api_key"
+```
+
+### Search returns empty results
+- Check your internet connection
+- Verify OpenWeatherMap API key is valid
+- Try searching for a major city first
+
+### Port 8001 already in use
+```bash
+export WEATHER_PORT=8002
+```
+
+## ๐ฆ Dependencies
+
+- **FastAPI** - Web framework
+- **Uvicorn** - ASGI server
+- **aiohttp** - Async HTTP client
+- **Pydantic** - Data validation
+
+## ๐ License
+
+AGPL-3.0-only
+
+## ๐ค Contributing
+
+Contributions welcome! Please create a pull request.
+
+---
+
+**Made with โค๏ธ by Huynhthuongg**
diff --git a/app/universal_compiler_agent/__init__.py b/app/universal_compiler_agent/__init__.py
index 04fee82..adaab43 100644
--- a/app/universal_compiler_agent/__init__.py
+++ b/app/universal_compiler_agent/__init__.py
@@ -1,4 +1,4 @@
"""Universal Project Compiler Agent package."""
__all__ = ["__version__"]
-__version__ = "0.1.0"
+__version__ = "0.1.1"
diff --git a/app/universal_compiler_agent/cli.py b/app/universal_compiler_agent/cli.py
index 41d8ca0..d2457ad 100644
--- a/app/universal_compiler_agent/cli.py
+++ b/app/universal_compiler_agent/cli.py
@@ -19,6 +19,14 @@ def _read_input(args: argparse.Namespace) -> str:
return "Universal Project Compiler Agent"
+def _safe_output_dir(value: str) -> Path:
+ output_dir = Path(value)
+ if output_dir.is_absolute() or ".." in output_dir.parts:
+ msg = "output_dir must be a safe relative path"
+ raise argparse.ArgumentTypeError(msg)
+ return output_dir
+
+
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Compile requirements into a runnable project scaffold."
@@ -37,7 +45,15 @@ def build_parser() -> argparse.ArgumentParser:
compile_cmd.add_argument("--text", help="Inline requirements text.")
compile_cmd.add_argument("--name", help="Override generated project name.")
compile_cmd.add_argument(
- "--output-dir", default="generated", help="Directory that will receive output."
+ "--dry-run",
+ action="store_true",
+ help="Print the generated plan as JSON without writing files.",
+ )
+ compile_cmd.add_argument(
+ "--output-dir",
+ default=Path("generated"),
+ type=_safe_output_dir,
+ help="Safe relative directory that will receive output.",
)
return parser
@@ -47,12 +63,12 @@ def main(argv: list[str] | None = None) -> int:
args = parser.parse_args(argv)
requirements = _read_input(args)
- if args.command == "plan":
+ if args.command == "plan" or args.dry_run:
plan = build_plan(requirements, args.name)
print(json.dumps(asdict(plan), indent=2))
return 0
- result = compile_project(requirements, Path(args.output_dir), args.name)
+ result = compile_project(requirements, args.output_dir, args.name)
print(f"Generated {result.file_count} files in {result.root}")
return 0
diff --git a/app/universal_compiler_agent/server.py b/app/universal_compiler_agent/server.py
index aff944b..1bf05b7 100644
--- a/app/universal_compiler_agent/server.py
+++ b/app/universal_compiler_agent/server.py
@@ -11,6 +11,9 @@
from .compiler import compile_project
from .planner import build_plan
+from .templates import INDEX_HTML
+
+APP_VERSION = "0.1.1"
class PlanRequest(BaseModel):
@@ -22,8 +25,15 @@ class CompileRequest(PlanRequest):
output_dir: str = Field(default="generated", max_length=240)
+def _safe_output_dir(value: str) -> Path:
+ output_dir = Path(value)
+ if output_dir.is_absolute() or ".." in output_dir.parts:
+ raise HTTPException(status_code=400, detail="output_dir must be a safe relative path")
+ return output_dir
+
+
def create_app() -> FastAPI:
- app = FastAPI(title="Universal Project Compiler Agent", version="0.1.0")
+ app = FastAPI(title="Universal Project Compiler Agent", version=APP_VERSION)
@app.middleware("http")
async def security_headers(request: Request, call_next): # type: ignore[no-untyped-def]
@@ -36,38 +46,7 @@ async def security_headers(request: Request, call_next): # type: ignore[no-unty
@app.get("/", response_class=HTMLResponse)
def index() -> str:
- return """
-
-
-
-
-
- Universal Project Compiler Agent
-
-
-
-
-