Files
microdao-daarion/services/brand-registry/app/main.py
Apple 0c8bef82f4 feat: Add Alateya, Clan, Eonarch agents + fix gateway-router connection
## Agents Added
- Alateya: R&D, biotech, innovations
- Clan (Spirit): Community spirit agent
- Eonarch: Consciousness evolution agent

## Changes
- docker-compose.node1.yml: Added tokens for all 3 new agents
- gateway-bot/http_api.py: Added configs and webhook endpoints
- gateway-bot/clan_prompt.txt: New prompt file
- gateway-bot/eonarch_prompt.txt: New prompt file

## Fixes
- Fixed ROUTER_URL from :9102 to :8000 (internal container port)
- All 9 Telegram agents now working

## Documentation
- Created PROJECT-MASTER-INDEX.md - single entry point
- Added various status documents and scripts

Tokens configured:
- Helion, NUTRA, Agromatrix (existing)
- Alateya, Clan, Eonarch (new)
- Druid, GreenFood, DAARWIZZ (configured)
2026-01-28 06:40:34 -08:00

134 lines
3.9 KiB
Python

"""
Brand Registry Service
- Stores Theme Packs (theme.json + assets refs)
- Serves immutable theme versions by brand_id
"""
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Any, Dict, Optional
from datetime import datetime
import json
import logging
import os
import uuid
from pathlib import Path
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
DATA_DIR = Path(os.getenv("BRAND_REGISTRY_DATA", "/data/brand-registry"))
THEMES_DIR = DATA_DIR / "brands"
app = FastAPI(
title="Brand Registry Service",
description="Single source of truth for brand themes",
version="0.1.0"
)
class ThemePublishRequest(BaseModel):
theme: Dict[str, Any]
theme_version: Optional[str] = None
metadata: Optional[Dict[str, Any]] = None
class ThemeResponse(BaseModel):
brand_id: str
theme_version: str
theme: Dict[str, Any]
metadata: Optional[Dict[str, Any]] = None
created_at: str
def _ensure_dirs() -> None:
THEMES_DIR.mkdir(parents=True, exist_ok=True)
def _theme_path(brand_id: str, theme_version: str) -> Path:
return THEMES_DIR / brand_id / "themes" / theme_version / "theme.json"
def _meta_path(brand_id: str, theme_version: str) -> Path:
return THEMES_DIR / brand_id / "themes" / theme_version / "meta.json"
def _list_versions(brand_id: str) -> list:
base = THEMES_DIR / brand_id / "themes"
if not base.exists():
return []
versions = [p.name for p in base.iterdir() if p.is_dir()]
return sorted(versions)
@app.get("/")
async def root() -> Dict[str, Any]:
_ensure_dirs()
return {
"service": "brand-registry",
"status": "running",
"data_dir": str(DATA_DIR),
"version": "0.1.0"
}
@app.get("/health")
async def health() -> Dict[str, Any]:
_ensure_dirs()
return {"status": "healthy"}
@app.post("/brands/{brand_id}/themes", response_model=ThemeResponse)
async def publish_theme(brand_id: str, payload: ThemePublishRequest) -> ThemeResponse:
_ensure_dirs()
theme_version = payload.theme_version or f"v1-{uuid.uuid4().hex[:8]}"
theme_path = _theme_path(brand_id, theme_version)
theme_path.parent.mkdir(parents=True, exist_ok=True)
created_at = datetime.utcnow().isoformat() + "Z"
meta = {
"brand_id": brand_id,
"theme_version": theme_version,
"created_at": created_at,
"metadata": payload.metadata or {}
}
theme_path.write_text(json.dumps(payload.theme, ensure_ascii=False, indent=2), encoding="utf-8")
_meta_path(brand_id, theme_version).write_text(json.dumps(meta, ensure_ascii=False, indent=2), encoding="utf-8")
logger.info("Published theme: %s/%s", brand_id, theme_version)
return ThemeResponse(
brand_id=brand_id,
theme_version=theme_version,
theme=payload.theme,
metadata=payload.metadata or {},
created_at=created_at
)
@app.get("/brands/{brand_id}/themes/{theme_version}", response_model=ThemeResponse)
async def get_theme(brand_id: str, theme_version: str) -> ThemeResponse:
theme_path = _theme_path(brand_id, theme_version)
if not theme_path.exists():
raise HTTPException(status_code=404, detail="Theme not found")
theme = json.loads(theme_path.read_text(encoding="utf-8"))
meta_path = _meta_path(brand_id, theme_version)
meta = json.loads(meta_path.read_text(encoding="utf-8")) if meta_path.exists() else {}
return ThemeResponse(
brand_id=brand_id,
theme_version=theme_version,
theme=theme,
metadata=meta.get("metadata"),
created_at=meta.get("created_at", "")
)
@app.get("/brands/{brand_id}/latest", response_model=ThemeResponse)
async def get_latest(brand_id: str) -> ThemeResponse:
versions = _list_versions(brand_id)
if not versions:
raise HTTPException(status_code=404, detail="No themes for brand")
return await get_theme(brand_id, versions[-1])