snapshot: NODE1 production state 2026-02-09

Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.

Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles

Excluded from snapshot: venv/, .env, data/, backups, .tgz archives

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Apple
2026-02-09 08:46:46 -08:00
parent 134c044c21
commit ef3473db21
9473 changed files with 408933 additions and 2769877 deletions

View File

@@ -86,7 +86,7 @@ class MemoryClient:
agent_id: str,
team_id: str,
channel_id: Optional[str] = None,
limit: int = 10
limit: int = 80
) -> Dict[str, Any]:
"""
Отримати контекст пам'яті для діалогу.
@@ -119,6 +119,18 @@ class MemoryClient:
events,
key=lambda e: e.get("timestamp", ""),
)
# Build user_id -> username mapping from all events (newer events may have metadata)
_uid_to_name = {}
for e in events:
uid = e.get("user_id", "")
md = e.get("metadata", {})
uname = md.get("username") or ""
if uid and uname and uid not in _uid_to_name:
_uid_to_name[uid] = uname
# Also try sender_name
sn = e.get("sender_name", "")
if uid and sn and not sn.startswith("tg:") and uid not in _uid_to_name:
_uid_to_name[uid] = sn
recent_events = [
{
"body_text": e.get("content", ""),
@@ -134,7 +146,22 @@ class MemoryClient:
content = e.get("content", "")
if not content:
continue
role = "User" if e.get("role") == "user" else "Assistant"
if e.get("role") == "user":
# Show sender name for group chats
sender = e.get("sender_name", "")
if not sender:
md = e.get("metadata", {})
sender = md.get("username") or md.get("first_name") or ""
# Resolve tg:IDs using the mapping
if not sender or sender.startswith("tg:"):
uid = e.get("user_id", "")
sender = _uid_to_name.get(uid, sender)
if sender:
role = f"[{sender}]"
else:
role = "User"
else:
role = "Assistant"
lines.append(f"{role}: {content}")
result = {
"facts": [],
@@ -148,7 +175,7 @@ class MemoryClient:
logger.debug(f"Memory Service context fetch failed, using local: {e}")
# FALLBACK: локальний контекст (in-memory)
local_messages = local_context.get_context(str(channel_id or user_id), limit)
local_messages = local_context.get_context(f"{agent_id}:{channel_id or user_id}", limit)
local_events = [
{"body_text": msg["text"], "kind": "message", "type": "user" if msg["role"] == "user" else "agent"}
for msg in local_messages
@@ -158,7 +185,7 @@ class MemoryClient:
"facts": [],
"recent_events": local_events,
"dialog_summaries": [],
"local_context_text": local_context.format_for_prompt(str(channel_id or user_id), limit),
"local_context_text": local_context.format_for_prompt(f"{agent_id}:{channel_id or user_id}", limit),
}
self._context_cache[cache_key] = (now, result)
return result
@@ -173,13 +200,14 @@ class MemoryClient:
channel_id: Optional[str] = None,
scope: str = "short_term",
save_agent_response: bool = True,
agent_metadata: Optional[Dict[str, Any]] = None
agent_metadata: Optional[Dict[str, Any]] = None,
username: Optional[str] = None
) -> bool:
"""
Зберегти один turn діалогу (повідомлення + відповідь).
Завжди зберігає в локальний контекст + намагається зберегти в Memory Service.
"""
chat_key = str(channel_id or user_id)
chat_key = f"{agent_id}:{channel_id or user_id}"
# ЗАВЖДИ зберігаємо в локальний контекст
local_context.add_message(chat_key, "user", message)
@@ -199,7 +227,7 @@ class MemoryClient:
"scope": scope,
"kind": "message",
"body_text": message,
"body_json": {"type": "user_message", "source": "telegram"}
"body_json": {"type": "user_message", "source": "telegram", "username": username or ""}
}
await client.post(