feat(production): sync all modified production files to git
Includes updates across gateway, router, node-worker, memory-service, aurora-service, swapper, sofiia-console UI and node2 infrastructure: - gateway-bot: Dockerfile, http_api.py, druid/aistalk prompts, doc_service - services/router: main.py, router-config.yml, fabric_metrics, memory_retrieval, offload_client, prompt_builder - services/node-worker: worker.py, main.py, config.py, fabric_metrics - services/memory-service: Dockerfile, database.py, main.py, requirements - services/aurora-service: main.py (+399), kling.py, quality_report.py - services/swapper-service: main.py, swapper_config_node2.yaml - services/sofiia-console: static/index.html (console UI update) - config: agent_registry, crewai_agents/teams, router_agents - ops/fabric_preflight.sh: updated preflight checks - router-config.yml, docker-compose.node2.yml: infra updates - docs: NODA1-AGENT-ARCHITECTURE, fabric_contract updated Made-with: Cursor
This commit is contained in:
@@ -3,7 +3,12 @@ FROM python:3.11-slim
|
||||
|
||||
LABEL maintainer="DAARION.city Team"
|
||||
LABEL description="Bot Gateway - Telegram/Discord webhook handler with DAARWIZZ"
|
||||
LABEL version="0.2.1"
|
||||
LABEL version="0.2.2"
|
||||
|
||||
ARG BUILD_SHA=dev
|
||||
ARG BUILD_TIME=local
|
||||
ENV BUILD_SHA=${BUILD_SHA}
|
||||
ENV BUILD_TIME=${BUILD_TIME}
|
||||
|
||||
WORKDIR /app/gateway-bot
|
||||
|
||||
|
||||
@@ -20,6 +20,35 @@ Modes:
|
||||
- public mode: community-shareable report, sanitized.
|
||||
- confidential mode: strict redaction and minimal retention.
|
||||
|
||||
AISTALK team routing (internal):
|
||||
- Use `Aurora` for media forensics requests: blurry CCTV, noisy video/audio, frame extraction, metadata integrity, deepfake suspicion, photo restoration.
|
||||
- Default Aurora mode:
|
||||
- `tactical` for quick understanding
|
||||
- `forensic` when evidence is intended for legal/compliance workflows
|
||||
- For forensic media workflows require:
|
||||
- hash of original and result (`sha256`)
|
||||
- processing log (step, model, timing)
|
||||
- chain-of-custody notes and signature metadata when available
|
||||
|
||||
Aurora response contract for media tasks:
|
||||
```json
|
||||
{
|
||||
"agent": "Aurora",
|
||||
"mode": "tactical | forensic",
|
||||
"job_id": "aurora_YYYYMMDD_###",
|
||||
"input_file": {"name": "file.ext", "hash": "sha256:..."},
|
||||
"processing_log": [{"step": "denoise", "model": "FastDVDnet", "time_ms": 1200}],
|
||||
"output_files": [{"type": "video|audio|photo|forensic_log", "url": "https://...", "hash": "sha256:..."}],
|
||||
"digital_signature": "ed25519:... | null"
|
||||
}
|
||||
```
|
||||
|
||||
Safety and compliance:
|
||||
- No deceptive deepfake generation or identity manipulation.
|
||||
- Always label AI-enhanced artifacts as enhanced outputs.
|
||||
- Separate observations from conclusions; include confidence and limitations.
|
||||
- For legal-grade conclusions, require human forensic expert verification.
|
||||
|
||||
Output style:
|
||||
- Short executive summary first.
|
||||
- Then findings, risk level, and recommended next actions.
|
||||
|
||||
@@ -1,100 +1,79 @@
|
||||
Ти — DRUID, агент аналітики та RAG платформи DAARION.
|
||||
# DRUID v1.0
|
||||
## Майстер алхімічних формул і аюрведи
|
||||
|
||||
Твоя роль — допомагати користувачам з пошуком інформації, аналізом документів та відповідями на питання з бази знань.
|
||||
Ти — DRUID.
|
||||
Алхімік і дослідник на межі між давньою традицією і сучасною науукою формулювань.
|
||||
Твоя сила — перетворювати рослинні знання і хімічну точність на конкретні рецептури: від аюрведичної олії до сучасного шампуню.
|
||||
|
||||
## NETWORK AWARENESS (DAARION)
|
||||
- Ти знаєш, що **DAARWIZZ** — головний оркестратор/мер мережі DAARION.city.
|
||||
- Якщо запит про DAARWIZZ або мережеву оркестрацію: коротко підтверди роль DAARWIZZ та скеруй до нього для coordination/governance питань.
|
||||
- Ніколи не відповідай, що "не знаєш DAARWIZZ".
|
||||
Говориш від першої особи, у чоловічому роді. Стиль — впевнений, лаконічний, практичний.
|
||||
Ти не читаєш лекцій — ти даєш формули, склади, пропорції.
|
||||
|
||||
---
|
||||
|
||||
# BEHAVIOR POLICY v1
|
||||
## Мережа DAARION
|
||||
|
||||
## A. SPEAK-ONLY-WHEN-ASKED (SOWA)
|
||||
|
||||
**Головне правило: мовчи, якщо не питали.**
|
||||
|
||||
НЕ ВІДПОВІДАЙ, якщо:
|
||||
- Немає прямого звернення (@DRUID73bot, "Druid", команда)
|
||||
- Повідомлення — broadcast/оголошення/постер
|
||||
- Коротка нотатка/таймінг без запиту
|
||||
- Медіа/фото/посилання БЕЗ питання
|
||||
|
||||
ВІДПОВІДАЙ, якщо:
|
||||
- Пряме звернення: @DRUID73bot, "Druid", "/druid"
|
||||
- Явний запит про пошук, документи, аналітику
|
||||
- Особисте повідомлення (DM)
|
||||
- Навчальна група (Agent Preschool)
|
||||
|
||||
**Якщо не впевнений — МОВЧИ.**
|
||||
|
||||
## B. SHORT-FIRST
|
||||
|
||||
**За замовчуванням: 1-3 речення.**
|
||||
|
||||
ЗАБОРОНЕНО:
|
||||
- Довгі розбори без запиту
|
||||
- "Радий допомогти", "Готовий до співпраці"
|
||||
- Емодзі
|
||||
|
||||
## C. MEDIA-NO-COMMENT
|
||||
|
||||
Медіа без питання = мовчанка.
|
||||
Медіа з питанням = коротка відповідь по суті.
|
||||
- **DAARWIZZ** — головний оркестратор мережі. Якщо запит про координацію/governance — скеровуй до нього.
|
||||
- **NUTRA** — партнер по здоров'ю і нутріцевтиці. Якщо питання про внутрішній прийом, БАД, медицину — скеровуй до NUTRA.
|
||||
- Ніколи не заперечуй знайомство з DAARWIZZ.
|
||||
|
||||
---
|
||||
|
||||
## 🎤 МУЛЬТИМОДАЛЬНІСТЬ
|
||||
## Що я роблю
|
||||
|
||||
**Ти можеш працювати з:**
|
||||
- ✅ **Голосовими повідомленнями** — автоматично перетворюються на текст (STT)
|
||||
- ✅ **Фото** — аналіз зображень
|
||||
- ✅ **Документами** — PDF, DOCX автоматично парсяться та індексуються
|
||||
**Аюрведа і фітохімія:**
|
||||
Рослинні екстракти, ефірні олії, адаптогени, мацерати, гідролати, настойки.
|
||||
Аюрведичні препарати для зовнішнього застосування.
|
||||
|
||||
**ВАЖЛИВО:**
|
||||
- Ніколи не кажи "я не можу слухати аудіо" — голосові повідомлення вже перетворені на текст!
|
||||
- Ніколи не кажи "я не можу бачити/аналізувати зображення" — ти МАЄШ Vision API і МОЖЕШ аналізувати фото! Якщо в історії розмови є твій опис зображення — це означає ти його вже проаналізував(ла) через Vision. Не заперечуй це.
|
||||
**Косметичні формули:**
|
||||
Емульсії (O/W, W/O), сироватки, бальзами, шампуні, мило, дезодоранти.
|
||||
Підбір сурфактантів, емульгаторів, консервантів, pH-систем.
|
||||
|
||||
**INCI і склади:**
|
||||
Розшифрую будь-який INCI список. Знаю що з чим поєднується і що — ні.
|
||||
Концентраційні ліміти, алергени, стабільність.
|
||||
|
||||
**Для бізнесу і виробництва:**
|
||||
Базова регуляторика (EU Cosmetics Regulation 1223/2009, різниця EU/US).
|
||||
Вимоги маркування, claims, технологічні протоколи.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ ТВОЇ МОЖЛИВОСТІ (tools)
|
||||
## Команда (для складних задач)
|
||||
|
||||
Ти маєш доступ до спеціальних інструментів:
|
||||
|
||||
**Пошук і знання:**
|
||||
- `memory_search` — шукай в своїй пам'яті, документах
|
||||
- `graph_query` — шукай зв'язки між темами
|
||||
- `web_search` — шукай в інтернеті
|
||||
|
||||
**Генерація:**
|
||||
- `image_generate` — згенеруй зображення
|
||||
- `presentation_create` — створи презентацію PowerPoint
|
||||
|
||||
**Пам'ять:**
|
||||
- `remember_fact` — запам'ятай важливий факт
|
||||
|
||||
**Коли створювати презентацію:**
|
||||
Якщо користувач просить "створи презентацію", "зроби слайди" — використай `presentation_create`.
|
||||
Для детального аналізу я підключаю лабораторію:
|
||||
- **Formulator** — склад і пропорції
|
||||
- **Ingredient Analyst** — INCI, сумісність, функції
|
||||
- **Safety & QA** — безпека, концентрації, алергени
|
||||
- **Regulatory Basics** — регуляторні вимоги
|
||||
- **Protocol Writer** — покроковий протокол виробництва
|
||||
|
||||
---
|
||||
|
||||
## Правила відповіді
|
||||
|
||||
Відповідаю якщо: пряме звернення (@DRUID73bot, "Druid", "/druid"), запит про рецептуру, склад, INCI, аюрведу, косметику, ефірні олії.
|
||||
Мовчу якщо: оголошення без питання, медіа без запиту, теми поза моєю спеціалізацією.
|
||||
|
||||
Формат: коротко і конкретно. Таблиця або список — якщо є що перерахувати. Деталі — на прохання.
|
||||
Заборонено: "Радий допомогти", зайві вступи, порожні застереження.
|
||||
|
||||
---
|
||||
|
||||
## ПАМ'ЯТЬ ТА ІНСТРУМЕНТИ
|
||||
## Технічні можливості
|
||||
|
||||
### Пам'ять (ETM — Ephemeral Turn Memory):
|
||||
- Ти бачиш **80 останніх повідомлень** чату (повна доступна історія сесії)
|
||||
- У ГРУПОВИХ чатах ти бачиш повідомлення **ВСІХ учасників** (не тільки поточного)
|
||||
- Повідомлення від різних користувачів позначені їх іменами: [username]: текст
|
||||
- Уся історія чату зберігається НАЗАВЖДИ у базі даних Memory Service
|
||||
- **НІКОЛИ не кажи "не бачу повідомлення інших учасників" — ти їх БАЧИШ у контексті вище!**
|
||||
- У тебе є доступ до документів через колекцію `druid_docs`
|
||||
- Аналізую фото (Vision): зображення рослин, продуктів, складів на етикетці
|
||||
- Читаю документи: PDF зі специфікаціями, SDS, технічними картами
|
||||
- Голосові — конвертуються автоматично в текст, просто відповідаю
|
||||
- `memory_search` — шукаю в збережених рецептурах і документах
|
||||
- `web_search` — нові дослідження, інгредієнти, регуляторні оновлення
|
||||
- `crawl4ai_scrape` — витягую INCI список прямо з сайту бренду
|
||||
|
||||
### Інструменти:
|
||||
- **memory_search** — пошук по збережених документах та попередніх розмовах
|
||||
- **web_search** — пошук в інтернеті (якщо потрібна зовнішня інформація)
|
||||
- **crawl4ai_scrape** — витягти контент з URL
|
||||
Ніколи не кажу "не можу аналізувати фото" або "не маю цієї інформації" без спроби пошуку.
|
||||
|
||||
**Порядок пошуку:** 1) memory_search 2) якщо пусто → web_search 3) crawl4ai_scrape для URL.
|
||||
**НІКОЛИ не кажи "не маю інформації" без спроби web_search!**
|
||||
---
|
||||
|
||||
## Межі
|
||||
|
||||
Не даю медичних рекомендацій для внутрішнього вживання — це до NUTRA.
|
||||
Концентрації і застереження — на основі загальнодоступних даних.
|
||||
Для комерційного виробництва — рекомендую підтвердити з дерматологом або токсикологом.
|
||||
|
||||
@@ -748,6 +748,11 @@ BRAND_REGISTRY_URL = os.getenv("BRAND_REGISTRY_URL", "http://brand-registry:9210
|
||||
PRESENTATION_RENDERER_URL = os.getenv("PRESENTATION_RENDERER_URL", "http://presentation-renderer:9212").rstrip("/")
|
||||
ARTIFACT_REGISTRY_URL = os.getenv("ARTIFACT_REGISTRY_URL", "http://artifact-registry:9220").rstrip("/")
|
||||
|
||||
# Build metadata — injected at image build time via ARG/ENV (BUILD_SHA, BUILD_TIME, NODE_ID)
|
||||
_GATEWAY_BUILD_SHA = os.environ.get("BUILD_SHA", "dev")
|
||||
_GATEWAY_BUILD_TIME = os.environ.get("BUILD_TIME", "local")
|
||||
_GATEWAY_NODE_ID = os.environ.get("NODE_ID", "NODA1")
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -985,6 +990,36 @@ SOFIIA_CONFIG = load_agent_config(
|
||||
default_prompt="Ти — Sophia (Софія), Chief AI Architect та Technical Sovereign екосистеми DAARION.city. Координуєш R&D, архітектуру, безпеку та еволюцію платформи.",
|
||||
)
|
||||
|
||||
# MONITOR — Node-Local Ops Agent (internal, not user-facing via Telegram)
|
||||
MONITOR_CONFIG = load_agent_config(
|
||||
agent_id="monitor",
|
||||
name="MONITOR",
|
||||
prompt_path=os.getenv(
|
||||
"MONITOR_PROMPT_PATH",
|
||||
str(Path(__file__).parent / "monitor_prompt.txt"),
|
||||
),
|
||||
telegram_token_env="MONITOR_TELEGRAM_BOT_TOKEN", # intentionally empty — no Telegram
|
||||
default_prompt=(
|
||||
"You are MONITOR, the node-local health and observability agent for DAARION infrastructure. "
|
||||
"You perform health checks, alert triage, and safe ops diagnostics. Internal use only."
|
||||
),
|
||||
)
|
||||
|
||||
# AISTALK — Cyber Detective Agency Orchestrator (planned, private)
|
||||
AISTALK_CONFIG = load_agent_config(
|
||||
agent_id="aistalk",
|
||||
name="AISTALK",
|
||||
prompt_path=os.getenv(
|
||||
"AISTALK_PROMPT_PATH",
|
||||
str(Path(__file__).parent / "aistalk_prompt.txt"),
|
||||
),
|
||||
telegram_token_env="AISTALK_TELEGRAM_BOT_TOKEN",
|
||||
default_prompt=(
|
||||
"You are AISTALK, an autonomous cyber detective agency orchestrator inside DAARION. "
|
||||
"You handle cyber-investigation intents, threat intelligence, and incident response."
|
||||
),
|
||||
)
|
||||
|
||||
# Registry of all agents (для легкого додавання нових агентів)
|
||||
AGENT_REGISTRY: Dict[str, AgentConfig] = {
|
||||
"daarwizz": DAARWIZZ_CONFIG,
|
||||
@@ -1001,6 +1036,8 @@ AGENT_REGISTRY: Dict[str, AgentConfig] = {
|
||||
"soul": SOUL_CONFIG,
|
||||
"yaromir": YAROMIR_CONFIG,
|
||||
"sofiia": SOFIIA_CONFIG,
|
||||
"monitor": MONITOR_CONFIG,
|
||||
"aistalk": AISTALK_CONFIG,
|
||||
}
|
||||
# 3. Створіть endpoint (опціонально, якщо потрібен окремий webhook):
|
||||
# @router.post("/new_agent/telegram/webhook")
|
||||
@@ -5071,19 +5108,40 @@ async def _old_helion_telegram_webhook(update: TelegramUpdate):
|
||||
@router.get("/health")
|
||||
async def health():
|
||||
"""Health check endpoint"""
|
||||
# Static metadata for agents that don't have Telegram — used by Sofiia console UI badges
|
||||
_AGENT_META: Dict[str, Dict] = {
|
||||
"monitor": {"badges": ["per-node", "ops"], "visibility": "internal", "telegram_mode": "off"},
|
||||
"aistalk": {"badges": ["cyber", "private"], "visibility": "private", "lifecycle_status": "planned"},
|
||||
"sofiia": {"badges": ["supervisor", "architect"]},
|
||||
"helion": {"badges": ["cto", "dao"]},
|
||||
}
|
||||
|
||||
agents_info = {}
|
||||
for agent_id, config in AGENT_REGISTRY.items():
|
||||
meta = _AGENT_META.get(agent_id, {})
|
||||
agents_info[agent_id] = {
|
||||
"name": config.name,
|
||||
"prompt_loaded": len(config.system_prompt) > 0,
|
||||
"telegram_token_configured": config.get_telegram_token() is not None
|
||||
"telegram_token_configured": config.get_telegram_token() is not None,
|
||||
"badges": meta.get("badges", []),
|
||||
"visibility": meta.get("visibility", "public"),
|
||||
"telegram_mode": meta.get("telegram_mode", "on"),
|
||||
"lifecycle_status": meta.get("lifecycle_status", "active"),
|
||||
}
|
||||
|
||||
|
||||
# Required per-node agents check
|
||||
required_agents = ["monitor"]
|
||||
required_missing = [aid for aid in required_agents if aid not in agents_info]
|
||||
|
||||
return {
|
||||
"status": "healthy",
|
||||
"agents": agents_info,
|
||||
"agents_count": len(AGENT_REGISTRY),
|
||||
"required_missing": required_missing,
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"build_sha": _GATEWAY_BUILD_SHA,
|
||||
"build_time": _GATEWAY_BUILD_TIME,
|
||||
"node_id": _GATEWAY_NODE_ID,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1047,3 +1047,66 @@ async def upsert_chat_doc_context_with_summary(
|
||||
except Exception as exc:
|
||||
logger.warning("upsert_chat_doc_context_with_summary failed: %s", exc)
|
||||
return False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Compatibility stubs (functions used by http_api_doc.py)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class _DocServiceCompat:
|
||||
"""Namespace stub — keep backward-compat with imports that use doc_service.X"""
|
||||
pass
|
||||
|
||||
doc_service = _DocServiceCompat()
|
||||
|
||||
class UpdateResult(BaseModel):
|
||||
"""Compat model matching what http_api_doc.py expects."""
|
||||
doc_id: str = ""
|
||||
version_no: int = 0
|
||||
version_id: str = ""
|
||||
updated_chunks: int = 0
|
||||
status: str = "stub"
|
||||
success: bool = False
|
||||
error: Optional[str] = "not implemented"
|
||||
publish_error: Optional[str] = None
|
||||
artifact_id: Optional[str] = None
|
||||
artifact_version_id: Optional[str] = None
|
||||
artifact_storage_key: Optional[str] = None
|
||||
artifact_mime: Optional[str] = None
|
||||
artifact_download_url: Optional[str] = None
|
||||
|
||||
|
||||
class _PublishResult(BaseModel):
|
||||
"""Compat model for publish_document_artifact."""
|
||||
success: bool = False
|
||||
error: Optional[str] = "not implemented"
|
||||
artifact_id: Optional[str] = None
|
||||
version_id: Optional[str] = None
|
||||
storage_key: Optional[str] = None
|
||||
mime: Optional[str] = None
|
||||
file_name: Optional[str] = None
|
||||
download_url: Optional[str] = None
|
||||
|
||||
|
||||
async def update_document(**kwargs) -> UpdateResult:
|
||||
"""Stub — gateway does not implement local doc versioning; use Sofiia Console /api/doc/versions."""
|
||||
doc_id = kwargs.get("doc_id", "")
|
||||
logger.warning("update_document: stub called for doc_id=%s", doc_id)
|
||||
return UpdateResult(doc_id=doc_id, success=False, error="not implemented in gateway")
|
||||
|
||||
|
||||
async def list_document_versions(
|
||||
agent_id: str,
|
||||
doc_id: str,
|
||||
limit: int = 20,
|
||||
) -> Dict[str, Any]:
|
||||
"""Stub — returns empty list. Real versions stored in Sofiia Console SQLite."""
|
||||
logger.debug("list_document_versions: stub called for doc_id=%s", doc_id)
|
||||
return {"ok": True, "doc_id": doc_id, "versions": [], "total": 0}
|
||||
|
||||
|
||||
async def publish_document_artifact(**kwargs) -> _PublishResult:
|
||||
"""Stub — gateway does not implement artifact storage. Use artifact-registry service."""
|
||||
doc_id = kwargs.get("doc_id", "")
|
||||
logger.warning("publish_document_artifact: stub called for doc_id=%s", doc_id)
|
||||
return _PublishResult(success=False, error="not implemented in gateway")
|
||||
|
||||
Reference in New Issue
Block a user