feat(city-map): Add 2D City Map with coordinates and agent presence

- Add migration 013_city_map_coordinates.sql with map coordinates, zones, and agents table
- Add /city/map API endpoint in city-service
- Add /city/agents and /city/agents/online endpoints
- Extend presence aggregator to include agents[] in snapshot
- Add AgentsSource for fetching agent data from DB
- Create CityMap component with interactive room tiles
- Add useCityMap hook for fetching map data
- Update useGlobalPresence to include agents
- Add map/list view toggle on /city page
- Add agent badges to room cards and map tiles
This commit is contained in:
Apple
2025-11-27 07:00:47 -08:00
parent 3de3c8cb36
commit 6bd769ef40
258 changed files with 1747 additions and 79 deletions

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7005"]

View File

@@ -292,3 +292,4 @@ curl http://localhost:7004/internal/messaging/channels/{channel_id}/context

View File

@@ -16,3 +16,4 @@ rules:

View File

@@ -160,3 +160,4 @@ async def shutdown_event():

View File

@@ -36,3 +36,4 @@ class FilterContext(BaseModel):

View File

@@ -8,3 +8,4 @@ PyYAML==6.0.1

View File

@@ -115,3 +115,4 @@ class FilterRules:

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7006"]

View File

@@ -405,3 +405,4 @@ curl -X POST http://localhost:7006/internal/agent-runtime/test-channel \

View File

@@ -21,3 +21,4 @@ memory:

View File

@@ -72,3 +72,4 @@ async def post_message(agent_id: str, channel_id: str, text: str) -> bool:

View File

@@ -35,3 +35,4 @@ class LLMResponse(BaseModel):

View File

@@ -73,3 +73,4 @@ pep_client = PEPClient()

View File

@@ -8,3 +8,4 @@ PyYAML==6.0.1

View File

@@ -172,3 +172,4 @@ Connects to:

View File

@@ -218,3 +218,4 @@ docker run -p 7011:7011 \

View File

@@ -127,3 +127,4 @@ async def require_actor(

View File

@@ -1,32 +1,69 @@
"""
Auth Service Configuration
"""
from pydantic_settings import BaseSettings
from functools import lru_cache
from pydantic import AliasChoices, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""
Settings loader that supports both the new AUTH_* env vars and the legacy
ones used in docker-compose files (e.g. DATABASE_URL, JWT_SECRET).
"""
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
# Service
service_name: str = "auth-service"
service_version: str = "1.0.0"
port: int = 7020
debug: bool = False
service_name: str = Field(
default="auth-service",
validation_alias=AliasChoices("AUTH_SERVICE_NAME", "SERVICE_NAME"),
)
service_version: str = Field(
default="1.0.0",
validation_alias=AliasChoices("AUTH_SERVICE_VERSION", "SERVICE_VERSION"),
)
port: int = Field(
default=7020,
validation_alias=AliasChoices("AUTH_PORT", "PORT", "AUTH_SERVICE_PORT"),
)
debug: bool = Field(
default=False,
validation_alias=AliasChoices("AUTH_DEBUG", "DEBUG"),
)
# Database
database_url: str = "postgresql://postgres:postgres@localhost:5432/daarion"
database_url: str = Field(
default="postgresql://postgres:postgres@localhost:5432/daarion",
validation_alias=AliasChoices("AUTH_DATABASE_URL", "DATABASE_URL"),
)
# JWT
jwt_secret: str = "your-very-long-secret-key-change-in-production"
jwt_algorithm: str = "HS256"
access_token_ttl: int = 1800 # 30 minutes
refresh_token_ttl: int = 604800 # 7 days
jwt_secret: str = Field(
default="your-very-long-secret-key-change-in-production",
validation_alias=AliasChoices("AUTH_JWT_SECRET", "JWT_SECRET"),
)
jwt_algorithm: str = Field(
default="HS256",
validation_alias=AliasChoices(
"AUTH_JWT_ALGORITHM", "JWT_ALGO", "JWT_ALGORITHM"
),
)
access_token_ttl: int = Field(
default=1800,
validation_alias=AliasChoices("AUTH_ACCESS_TOKEN_TTL", "ACCESS_TOKEN_TTL"),
)
refresh_token_ttl: int = Field(
default=604800,
validation_alias=AliasChoices("AUTH_REFRESH_TOKEN_TTL", "REFRESH_TOKEN_TTL"),
)
# Security
bcrypt_rounds: int = 12
class Config:
env_prefix = "AUTH_"
env_file = ".env"
bcrypt_rounds: int = Field(
default=12,
validation_alias=AliasChoices("AUTH_BCRYPT_ROUNDS", "BCRYPT_ROUNDS"),
)
@lru_cache()

View File

@@ -228,3 +228,4 @@ class PasskeyStore:

View File

@@ -125,3 +125,4 @@ async def delete_api_key(

View File

@@ -327,3 +327,4 @@ async def authenticate_finish(

View File

@@ -127,3 +127,4 @@ async def logout(

View File

@@ -207,3 +207,4 @@ def hash_credential_id(credential_id: str) -> str:

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7001"]

View File

@@ -345,3 +345,4 @@ Proprietary — DAARION Ecosystem

View File

@@ -107,3 +107,66 @@ class WSPresenceMessage(BaseModel):
user_id: str
status: Optional[str] = None
# =============================================================================
# City Map (2D Map)
# =============================================================================
class CityMapRoom(BaseModel):
"""Room representation on 2D city map"""
id: str
slug: str
name: str
description: Optional[str] = None
room_type: str = "public"
zone: str = "central"
icon: Optional[str] = None
color: Optional[str] = None
# Map coordinates
x: int = 0
y: int = 0
w: int = 1
h: int = 1
# Matrix integration
matrix_room_id: Optional[str] = None
class CityMapConfig(BaseModel):
"""Global city map configuration"""
grid_width: int = 6
grid_height: int = 3
cell_size: int = 100
background_url: Optional[str] = None
class CityMapResponse(BaseModel):
"""Full city map response"""
config: CityMapConfig
rooms: List[CityMapRoom]
# =============================================================================
# Agents (for Agent Presence)
# =============================================================================
class AgentRead(BaseModel):
"""Agent representation"""
id: str
display_name: str
kind: str = "assistant" # assistant, civic, oracle, builder
avatar_url: Optional[str] = None
color: str = "cyan"
status: str = "offline" # online, offline, busy
current_room_id: Optional[str] = None
capabilities: List[str] = []
class AgentPresence(BaseModel):
"""Agent presence in a room"""
agent_id: str
display_name: str
kind: str
status: str
room_id: Optional[str] = None
color: Optional[str] = None

View File

@@ -226,3 +226,124 @@ async def create_feed_event(
row = await pool.fetchrow(query, event_id, kind, room_id, user_id, agent_id, payload_json)
return dict(row)
# =============================================================================
# City Map Repository
# =============================================================================
async def get_map_config() -> dict:
"""Отримати конфігурацію мапи міста"""
pool = await get_pool()
query = """
SELECT id, grid_width, grid_height, cell_size, background_url, updated_at
FROM city_map_config
WHERE id = 'default'
"""
row = await pool.fetchrow(query)
if row:
return dict(row)
# Повернути дефолтні значення якщо немає запису
return {
"id": "default",
"grid_width": 6,
"grid_height": 3,
"cell_size": 100,
"background_url": None
}
async def get_rooms_for_map() -> List[dict]:
"""Отримати кімнати з координатами для 2D мапи"""
pool = await get_pool()
query = """
SELECT
id, slug, name, description,
room_type, zone, icon, color,
map_x, map_y, map_w, map_h,
matrix_room_id
FROM city_rooms
ORDER BY map_y, map_x
"""
rows = await pool.fetch(query)
return [dict(row) for row in rows]
# =============================================================================
# Agents Repository
# =============================================================================
async def get_all_agents() -> List[dict]:
"""Отримати всіх агентів"""
pool = await get_pool()
query = """
SELECT id, display_name, kind, avatar_url, color, status,
current_room_id, capabilities, created_at, updated_at
FROM agents
ORDER BY display_name
"""
rows = await pool.fetch(query)
return [dict(row) for row in rows]
async def get_agents_by_room(room_id: str) -> List[dict]:
"""Отримати агентів у конкретній кімнаті"""
pool = await get_pool()
query = """
SELECT id, display_name, kind, avatar_url, color, status,
current_room_id, capabilities
FROM agents
WHERE current_room_id = $1 AND status != 'offline'
ORDER BY display_name
"""
rows = await pool.fetch(query, room_id)
return [dict(row) for row in rows]
async def get_online_agents() -> List[dict]:
"""Отримати всіх онлайн агентів"""
pool = await get_pool()
query = """
SELECT id, display_name, kind, avatar_url, color, status,
current_room_id, capabilities
FROM agents
WHERE status IN ('online', 'busy')
ORDER BY display_name
"""
rows = await pool.fetch(query)
return [dict(row) for row in rows]
async def update_agent_status(agent_id: str, status: str, room_id: Optional[str] = None) -> Optional[dict]:
"""Оновити статус агента"""
pool = await get_pool()
if room_id:
query = """
UPDATE agents
SET status = $2, current_room_id = $3, updated_at = NOW()
WHERE id = $1
RETURNING id, display_name, kind, status, current_room_id
"""
row = await pool.fetchrow(query, agent_id, status, room_id)
else:
query = """
UPDATE agents
SET status = $2, updated_at = NOW()
WHERE id = $1
RETURNING id, display_name, kind, status, current_room_id
"""
row = await pool.fetchrow(query, agent_id, status)
return dict(row) if row else None

View File

@@ -14,7 +14,12 @@ from models_city import (
CityRoomDetail,
CityRoomMessageRead,
CityRoomMessageCreate,
CityFeedEventRead
CityFeedEventRead,
CityMapRoom,
CityMapConfig,
CityMapResponse,
AgentRead,
AgentPresence
)
import repo_city
from common.redis_client import PresenceRedis, get_redis
@@ -412,3 +417,143 @@ async def get_city_feed(limit: int = 20, offset: int = 0):
logger.error(f"Failed to get city feed: {e}")
raise HTTPException(status_code=500, detail="Failed to get city feed")
# =============================================================================
# City Map API (2D Map)
# =============================================================================
@router.get("/map", response_model=CityMapResponse)
async def get_city_map():
"""
Отримати дані для 2D мапи міста.
Повертає:
- config: розміри сітки та налаштування
- rooms: список кімнат з координатами
"""
try:
# Отримати конфігурацію
config_data = await repo_city.get_map_config()
config = CityMapConfig(
grid_width=config_data.get("grid_width", 6),
grid_height=config_data.get("grid_height", 3),
cell_size=config_data.get("cell_size", 100),
background_url=config_data.get("background_url")
)
# Отримати кімнати з координатами
rooms_data = await repo_city.get_rooms_for_map()
rooms = []
for room in rooms_data:
rooms.append(CityMapRoom(
id=room["id"],
slug=room["slug"],
name=room["name"],
description=room.get("description"),
room_type=room.get("room_type", "public"),
zone=room.get("zone", "central"),
icon=room.get("icon"),
color=room.get("color"),
x=room.get("map_x", 0),
y=room.get("map_y", 0),
w=room.get("map_w", 1),
h=room.get("map_h", 1),
matrix_room_id=room.get("matrix_room_id")
))
return CityMapResponse(config=config, rooms=rooms)
except Exception as e:
logger.error(f"Failed to get city map: {e}")
raise HTTPException(status_code=500, detail="Failed to get city map")
# =============================================================================
# Agents API
# =============================================================================
@router.get("/agents", response_model=List[AgentRead])
async def get_agents():
"""
Отримати список всіх агентів
"""
try:
agents = await repo_city.get_all_agents()
result = []
for agent in agents:
capabilities = agent.get("capabilities", [])
if isinstance(capabilities, str):
import json
capabilities = json.loads(capabilities)
result.append(AgentRead(
id=agent["id"],
display_name=agent["display_name"],
kind=agent.get("kind", "assistant"),
avatar_url=agent.get("avatar_url"),
color=agent.get("color", "cyan"),
status=agent.get("status", "offline"),
current_room_id=agent.get("current_room_id"),
capabilities=capabilities
))
return result
except Exception as e:
logger.error(f"Failed to get agents: {e}")
raise HTTPException(status_code=500, detail="Failed to get agents")
@router.get("/agents/online", response_model=List[AgentPresence])
async def get_online_agents():
"""
Отримати список онлайн агентів (для presence)
"""
try:
agents = await repo_city.get_online_agents()
result = []
for agent in agents:
result.append(AgentPresence(
agent_id=agent["id"],
display_name=agent["display_name"],
kind=agent.get("kind", "assistant"),
status=agent.get("status", "offline"),
room_id=agent.get("current_room_id"),
color=agent.get("color", "cyan")
))
return result
except Exception as e:
logger.error(f"Failed to get online agents: {e}")
raise HTTPException(status_code=500, detail="Failed to get online agents")
@router.get("/rooms/{room_id}/agents", response_model=List[AgentPresence])
async def get_room_agents(room_id: str):
"""
Отримати агентів у конкретній кімнаті
"""
try:
agents = await repo_city.get_agents_by_room(room_id)
result = []
for agent in agents:
result.append(AgentPresence(
agent_id=agent["id"],
display_name=agent["display_name"],
kind=agent.get("kind", "assistant"),
status=agent.get("status", "offline"),
room_id=room_id,
color=agent.get("color", "cyan")
))
return result
except Exception as e:
logger.error(f"Failed to get room agents: {e}")
raise HTTPException(status_code=500, detail="Failed to get room agents")

View File

@@ -160,3 +160,4 @@ async def agents_presence_generator():

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7007"]

View File

@@ -332,3 +332,4 @@ Internal DAARION service

View File

@@ -58,3 +58,4 @@ logging:

View File

@@ -193,3 +193,4 @@ if __name__ == "__main__":

View File

@@ -100,3 +100,4 @@ class UsageTracker:

View File

@@ -59,3 +59,4 @@ class UsageLog(BaseModel):

View File

@@ -8,3 +8,4 @@ __all__ = ['BaseProvider', 'OpenAIProvider', 'DeepSeekProvider', 'LocalProvider'

View File

@@ -34,3 +34,4 @@ class BaseProvider(Protocol):

View File

@@ -73,3 +73,4 @@ class DeepSeekProvider:

View File

@@ -95,3 +95,4 @@ class LocalProvider:

View File

@@ -73,3 +73,4 @@ class OpenAIProvider:

View File

@@ -8,3 +8,4 @@ python-multipart==0.0.6

View File

@@ -73,3 +73,4 @@ class ModelRouter:

View File

@@ -644,3 +644,4 @@ Content-Type: application/json

View File

@@ -15,3 +15,4 @@ COPY app ./app
# Run the service
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8085"]

View File

@@ -0,0 +1,92 @@
"""Agents data source from PostgreSQL"""
from sqlalchemy import create_engine, text
from typing import List, Dict
import logging
logger = logging.getLogger(__name__)
class AgentsSource:
"""Fetches agent data from PostgreSQL"""
def __init__(self, db_dsn: str):
self.engine = create_engine(db_dsn)
def get_online_agents(self) -> List[Dict]:
"""
Get all online/busy agents.
Returns list of dicts with:
- agent_id
- display_name
- kind
- status
- room_id (current_room_id)
- color
"""
query = text("""
SELECT
id as agent_id,
display_name,
kind,
status,
current_room_id as room_id,
color
FROM agents
WHERE status IN ('online', 'busy')
ORDER BY display_name
""")
try:
with self.engine.connect() as conn:
rows = conn.execute(query).mappings().all()
return [dict(r) for r in rows]
except Exception as e:
logger.error(f"Failed to get online agents: {e}")
return []
def get_agents_by_room(self, room_id: str) -> List[Dict]:
"""Get agents in a specific room"""
query = text("""
SELECT
id as agent_id,
display_name,
kind,
status,
current_room_id as room_id,
color
FROM agents
WHERE current_room_id = :room_id AND status != 'offline'
ORDER BY display_name
""")
try:
with self.engine.connect() as conn:
rows = conn.execute(query, {"room_id": room_id}).mappings().all()
return [dict(r) for r in rows]
except Exception as e:
logger.error(f"Failed to get agents for room {room_id}: {e}")
return []
def get_all_agents(self) -> List[Dict]:
"""Get all agents (including offline)"""
query = text("""
SELECT
id as agent_id,
display_name,
kind,
status,
current_room_id as room_id,
color
FROM agents
ORDER BY display_name
""")
try:
with self.engine.connect() as conn:
rows = conn.execute(query).mappings().all()
return [dict(r) for r in rows]
except Exception as e:
logger.error(f"Failed to get all agents: {e}")
return []

View File

@@ -4,9 +4,10 @@ from datetime import datetime, timezone
from typing import List, Optional
import logging
from .models import PresenceSnapshot, RoomPresence, CityPresence
from .models import PresenceSnapshot, RoomPresence, CityPresence, AgentPresence
from .matrix_client import MatrixClient
from .rooms_source import RoomsSource
from .agents_source import AgentsSource
logger = logging.getLogger(__name__)
@@ -16,6 +17,7 @@ class PresenceAggregator:
Aggregates presence data from Matrix and broadcasts to subscribers.
- Periodically polls Matrix for room members and presence
- Fetches agent status from database
- Caches the latest snapshot
- Broadcasts updates to SSE subscribers
"""
@@ -24,10 +26,12 @@ class PresenceAggregator:
self,
matrix_client: MatrixClient,
rooms_source: RoomsSource,
agents_source: Optional[AgentsSource] = None,
poll_interval_seconds: int = 5,
):
self.matrix_client = matrix_client
self.rooms_source = rooms_source
self.agents_source = agents_source
self.poll_interval_seconds = poll_interval_seconds
self._snapshot: Optional[PresenceSnapshot] = None
@@ -62,18 +66,47 @@ class PresenceAggregator:
pass
async def _compute_snapshot(self) -> PresenceSnapshot:
"""Compute a new presence snapshot from Matrix"""
"""Compute a new presence snapshot from Matrix and agents DB"""
rooms = self.rooms_source.get_rooms()
if not rooms:
logger.warning("No rooms with matrix_room_id found")
# Fetch agents from database
all_agents: List[AgentPresence] = []
agents_by_room: dict = {}
if self.agents_source:
try:
online_agents = self.agents_source.get_online_agents()
for agent in online_agents:
ap = AgentPresence(
agent_id=agent["agent_id"],
display_name=agent["display_name"],
kind=agent.get("kind", "assistant"),
status=agent.get("status", "online"),
room_id=agent.get("room_id"),
color=agent.get("color", "cyan")
)
all_agents.append(ap)
# Group by room
room_id = agent.get("room_id")
if room_id:
if room_id not in agents_by_room:
agents_by_room[room_id] = []
agents_by_room[room_id].append(ap)
except Exception as e:
logger.error(f"Error fetching agents: {e}")
room_presences: List[RoomPresence] = []
city_online_total = 0
rooms_online = 0
for r in rooms:
matrix_room_id = r["matrix_room_id"]
room_id = r["room_id"]
try:
# Get room members
@@ -99,24 +132,30 @@ class PresenceAggregator:
city_online_total += online_count
# Get agents for this room
room_agents = agents_by_room.get(room_id, [])
room_presences.append(
RoomPresence(
room_id=r["room_id"],
room_id=room_id,
matrix_room_id=matrix_room_id,
online=online_count,
typing=typing_count,
agents=room_agents,
)
)
except Exception as e:
logger.error(f"Error processing room {r['room_id']}: {e}")
# Add room with 0 online
logger.error(f"Error processing room {room_id}: {e}")
# Add room with 0 online but include agents
room_agents = agents_by_room.get(room_id, [])
room_presences.append(
RoomPresence(
room_id=r["room_id"],
room_id=room_id,
matrix_room_id=matrix_room_id,
online=0,
typing=0,
agents=room_agents,
)
)
@@ -125,11 +164,13 @@ class PresenceAggregator:
city=CityPresence(
online_total=city_online_total,
rooms_online=rooms_online,
agents_online=len(all_agents),
),
rooms=room_presences,
agents=all_agents,
)
logger.info(f"Computed snapshot: {city_online_total} online in {rooms_online} rooms")
logger.info(f"Computed snapshot: {city_online_total} online, {len(all_agents)} agents in {rooms_online} rooms")
return snapshot
async def run_forever(self):
@@ -152,3 +193,4 @@ class PresenceAggregator:
self._running = False
logger.info("Stopping presence aggregator")

View File

@@ -34,3 +34,4 @@ def load_settings() -> Settings:
presence_daemon_user=os.getenv("PRESENCE_DAEMON_USER", "@presence_daemon:daarion.space"),
)

View File

@@ -13,6 +13,7 @@ import logging
from .config import load_settings
from .matrix_client import MatrixClient
from .rooms_source import RoomsSource, StaticRoomsSource
from .agents_source import AgentsSource
from .aggregator import PresenceAggregator
# Configure logging
@@ -58,9 +59,19 @@ else:
rooms_source = RoomsSource(db_dsn=settings.db_dsn or "postgresql://postgres:postgres@localhost:5432/postgres")
logger.warning("No rooms source configured, using default database")
# Initialize agents source (uses same DB as rooms)
agents_source = None
if settings.db_dsn:
try:
agents_source = AgentsSource(db_dsn=settings.db_dsn)
logger.info("Agents source initialized")
except Exception as e:
logger.warning(f"Failed to initialize agents source: {e}")
aggregator = PresenceAggregator(
matrix_client=matrix_client,
rooms_source=rooms_source,
agents_source=agents_source,
poll_interval_seconds=settings.poll_interval_seconds,
)
@@ -157,3 +168,4 @@ if __name__ == "__main__":
reload=True,
)

View File

@@ -92,3 +92,4 @@ class MatrixClient:
async def close(self):
await self._client.aclose()

View File

@@ -1,19 +1,31 @@
"""Data models for Presence Aggregator"""
from pydantic import BaseModel
from typing import List
from typing import List, Optional
from datetime import datetime
class AgentPresence(BaseModel):
"""Agent presence in a room"""
agent_id: str
display_name: str
kind: str = "assistant" # assistant, civic, oracle, builder
status: str = "offline" # online, offline, busy
room_id: Optional[str] = None
color: Optional[str] = None
class RoomPresence(BaseModel):
room_id: str # internal room id from DB
matrix_room_id: str # Matrix room ID (!xxx:domain)
online: int
typing: int
agents: List[AgentPresence] = [] # Agents present in this room
class CityPresence(BaseModel):
online_total: int
rooms_online: int
agents_online: int = 0
class PresenceSnapshot(BaseModel):
@@ -21,4 +33,6 @@ class PresenceSnapshot(BaseModel):
timestamp: datetime
city: CityPresence
rooms: List[RoomPresence]
agents: List[AgentPresence] = [] # All online agents

View File

@@ -67,3 +67,4 @@ class StaticRoomsSource:
def get_rooms(self) -> List[Dict]:
return self._rooms

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7008"]

View File

@@ -315,3 +315,4 @@ CREATE TABLE agent_memories_vector (

View File

@@ -7,3 +7,4 @@ __all__ = ['ShortTermBackend', 'VectorStoreBackend', 'KnowledgeBaseBackend']

View File

@@ -73,3 +73,4 @@ class KnowledgeBaseBackend:

View File

@@ -107,3 +107,4 @@ class ShortTermBackend:

View File

@@ -183,3 +183,4 @@ class VectorStoreBackend:

View File

@@ -30,3 +30,4 @@ limits:

View File

@@ -50,3 +50,4 @@ class EmbeddingClient:

View File

@@ -242,3 +242,4 @@ if __name__ == "__main__":

View File

@@ -49,3 +49,4 @@ class MemorySummarizeResponse(BaseModel):

View File

@@ -9,3 +9,4 @@ python-multipart==0.0.6

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7004"]

View File

@@ -359,3 +359,4 @@ DAARION Platform Team

View File

@@ -176,3 +176,4 @@ async def require_microdao_permission(

View File

@@ -228,3 +228,4 @@ def get_monitor_agent_file_urls(agent_id: str, base_url: str = "/") -> Dict[str,

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7012"]

View File

@@ -349,3 +349,4 @@ docker exec postgres psql -U postgres -d daarion \

View File

@@ -58,3 +58,4 @@ defaults:

View File

@@ -205,3 +205,4 @@ def evaluate_usage_access(request: PolicyRequest, policy_store: PolicyStore) ->

View File

@@ -158,3 +158,4 @@ if __name__ == "__main__":

View File

@@ -57,3 +57,4 @@ class PolicyDecision(BaseModel):

View File

@@ -99,3 +99,4 @@ class PolicyStore:

View File

@@ -8,3 +8,4 @@ python-multipart==0.0.6

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -209,3 +209,4 @@ curl -X POST http://localhost:8000/internal/router/test-messaging \

View File

@@ -209,3 +209,4 @@ async def shutdown_event():

View File

@@ -7,3 +7,4 @@ PyYAML==6.0.1

View File

@@ -9,3 +9,4 @@ messaging_inbound:

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7002"]

View File

@@ -256,3 +256,4 @@ Proprietary — DAARION Ecosystem

View File

@@ -237,3 +237,4 @@ if __name__ == "__main__":

View File

@@ -8,3 +8,4 @@ asyncio-nats-client==0.11.5

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7009"]

View File

@@ -302,3 +302,4 @@ Each tool has a `timeout` (seconds). If execution exceeds timeout, it fails grac

View File

@@ -78,3 +78,4 @@ logging:

View File

@@ -6,3 +6,4 @@ __all__ = ['HTTPExecutor', 'PythonExecutor']

View File

@@ -102,3 +102,4 @@ class HTTPExecutor:

View File

@@ -66,3 +66,4 @@ class PythonExecutor:

View File

@@ -195,3 +195,4 @@ if __name__ == "__main__":

View File

@@ -30,3 +30,4 @@ class ToolCallResult(BaseModel):

View File

@@ -77,3 +77,4 @@ class ToolRegistry:

View File

@@ -8,3 +8,4 @@ python-multipart==0.0.6

View File

@@ -22,3 +22,4 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7013"]

View File

@@ -361,3 +361,4 @@ await publish_nats_event("usage.agent", {

View File

@@ -237,3 +237,4 @@ class UsageAggregator:

View File

@@ -182,3 +182,4 @@ class UsageCollector:

View File

@@ -219,3 +219,4 @@ if __name__ == "__main__":

View File

@@ -159,3 +159,4 @@ class UsageQueryResponse(BaseModel):

View File

@@ -8,3 +8,4 @@ python-multipart==0.0.6

Some files were not shown because too many files have changed in this diff Show More