- Created sync-node2-dagi-agents.py script to sync agents from agents_city_mapping.yaml - Synced 50 DAGI agents across 10 districts: - Leadership Hall (4): Solarius, Sofia, PrimeSynth, Nexor - System Control (6): Monitor, Strategic Sentinels, Vindex, Helix, Aurora, Arbitron - Engineering Lab (5): ByteForge, Vector, ChainWeaver, Cypher, Canvas - Marketing Hub (6): Roxy, Mira, Tempo, Harmony, Faye, Storytelling - Finance Office (4): Financial Analyst, Accountant, Budget Planner, Tax Advisor - Web3 District (5): Smart Contract Dev, DeFi Analyst, Tokenomics Expert, NFT Specialist, DAO Governance - Security Bunker (7): Shadelock, Exor, Penetration Tester, Security Monitor, Incident Responder, Shadelock Forensics, Exor Forensics - Vision Studio (4): Iris, Lumen, Spectra, Video Analyzer - R&D Lab (6): ProtoMind, LabForge, TestPilot, ModelScout, BreakPoint, GrowCell - Memory Vault (3): Somnia, Memory Manager, Knowledge Indexer - Fixed Swapper config to use swapper_config_node2.yaml with 8 models - Created TASK_PHASE_NODE2_FULL_DAGI_INTEGRATION_v1.md NODE2 now shows: - 50 agents in DAGI Router Card - 8 models in Swapper Service (gpt-oss, phi3, starcoder2, mistral-nemo, gemma2, deepseek-coder, qwen2.5-coder, deepseek-r1) - Full isolation from NODE1
267 lines
9.6 KiB
Python
267 lines
9.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Sync NODE2 DAGI Agents from agents_city_mapping.yaml to database.
|
|
|
|
This script reads the agent configuration from agents_city_mapping.yaml
|
|
and syncs all 50 agents to the database with node_id = 'node-2-macbook-m4max'.
|
|
|
|
Usage:
|
|
python scripts/sync-node2-dagi-agents.py --dry-run # Preview changes
|
|
python scripts/sync-node2-dagi-agents.py # Apply changes
|
|
"""
|
|
|
|
import argparse
|
|
import asyncio
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
# Add project root to path
|
|
PROJECT_ROOT = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
# Database connection
|
|
DATABASE_URL = os.getenv(
|
|
"DATABASE_URL",
|
|
"postgresql://postgres:postgres@144.76.224.179:5432/daarion"
|
|
)
|
|
|
|
NODE2_ID = "node-2-macbook-m4max"
|
|
CONFIG_PATH = PROJECT_ROOT / "config" / "agents_city_mapping.yaml"
|
|
|
|
|
|
def load_agents_config() -> dict:
|
|
"""Load agents configuration from YAML file."""
|
|
if not CONFIG_PATH.exists():
|
|
print(f"❌ Config file not found: {CONFIG_PATH}")
|
|
sys.exit(1)
|
|
|
|
with open(CONFIG_PATH, 'r', encoding='utf-8') as f:
|
|
config = yaml.safe_load(f)
|
|
|
|
return config
|
|
|
|
|
|
def parse_agent(agent_data: dict, districts: list) -> dict:
|
|
"""Parse agent data from YAML to database format."""
|
|
# Find district info
|
|
district_id = agent_data.get('district', '')
|
|
district_info = next((d for d in districts if d['id'] == district_id), None)
|
|
|
|
return {
|
|
'id': agent_data['agent_id'],
|
|
'slug': agent_data['agent_id'],
|
|
'display_name': agent_data['display_name'],
|
|
'kind': agent_data.get('kind', 'assistant'),
|
|
'role': agent_data.get('role', ''),
|
|
'model': agent_data.get('model', ''),
|
|
'node_id': agent_data.get('node_id', NODE2_ID),
|
|
'district': district_id,
|
|
'primary_room_slug': agent_data.get('primary_room_slug', ''),
|
|
'avatar_url': agent_data.get('avatar_url', ''),
|
|
'color_hint': agent_data.get('color_hint', ''),
|
|
'priority': agent_data.get('priority', 'medium'),
|
|
'is_active': True,
|
|
'status': 'offline',
|
|
'is_public': True,
|
|
'public_slug': agent_data['agent_id'],
|
|
'public_title': agent_data['display_name'],
|
|
'public_tagline': agent_data.get('role', ''),
|
|
'public_district': district_info['name'] if district_info else '',
|
|
'public_primary_room_slug': agent_data.get('primary_room_slug', ''),
|
|
'is_listed_in_directory': True,
|
|
'visibility_scope': 'global',
|
|
'is_orchestrator': agent_data.get('kind') == 'orchestrator',
|
|
'home_node_id': agent_data.get('node_id', NODE2_ID),
|
|
}
|
|
|
|
|
|
async def sync_agents(dry_run: bool = True):
|
|
"""Sync agents to database."""
|
|
import asyncpg
|
|
|
|
print(f"📂 Loading config from: {CONFIG_PATH}")
|
|
config = load_agents_config()
|
|
|
|
districts = config.get('districts', [])
|
|
agents_data = config.get('agents', [])
|
|
|
|
print(f"📊 Found {len(agents_data)} agents in config")
|
|
print(f"📊 Found {len(districts)} districts")
|
|
|
|
# Parse agents
|
|
agents = [parse_agent(a, districts) for a in agents_data]
|
|
|
|
# Group by district for summary
|
|
by_district = {}
|
|
for agent in agents:
|
|
d = agent['district']
|
|
if d not in by_district:
|
|
by_district[d] = []
|
|
by_district[d].append(agent['display_name'])
|
|
|
|
print("\n📋 Agents by district:")
|
|
for district_id, agent_names in sorted(by_district.items()):
|
|
district_info = next((d for d in districts if d['id'] == district_id), None)
|
|
district_name = district_info['name'] if district_info else district_id
|
|
print(f" {district_name}: {len(agent_names)} agents")
|
|
for name in agent_names:
|
|
print(f" - {name}")
|
|
|
|
if dry_run:
|
|
print("\n🔍 DRY RUN - No changes will be made")
|
|
print(f"Would sync {len(agents)} agents to NODE2")
|
|
return
|
|
|
|
# Connect to database
|
|
print(f"\n🔗 Connecting to database...")
|
|
conn = await asyncpg.connect(DATABASE_URL)
|
|
|
|
try:
|
|
# Start transaction
|
|
async with conn.transaction():
|
|
inserted = 0
|
|
updated = 0
|
|
|
|
for agent in agents:
|
|
# Check if agent exists
|
|
existing = await conn.fetchrow(
|
|
"SELECT id FROM agents WHERE id = $1",
|
|
agent['id']
|
|
)
|
|
|
|
if existing:
|
|
# Update existing agent
|
|
await conn.execute("""
|
|
UPDATE agents SET
|
|
display_name = $2,
|
|
kind = $3,
|
|
role = $4,
|
|
model = $5,
|
|
node_id = $6,
|
|
district = $7,
|
|
primary_room_slug = $8,
|
|
avatar_url = $9,
|
|
color_hint = $10,
|
|
priority = $11,
|
|
is_active = $12,
|
|
is_public = $13,
|
|
public_slug = $14,
|
|
public_title = $15,
|
|
public_tagline = $16,
|
|
public_district = $17,
|
|
public_primary_room_slug = $18,
|
|
is_listed_in_directory = $19,
|
|
visibility_scope = $20,
|
|
is_orchestrator = $21,
|
|
home_node_id = $22,
|
|
slug = $23,
|
|
updated_at = NOW()
|
|
WHERE id = $1
|
|
""",
|
|
agent['id'],
|
|
agent['display_name'],
|
|
agent['kind'],
|
|
agent['role'],
|
|
agent['model'],
|
|
agent['node_id'],
|
|
agent['district'],
|
|
agent['primary_room_slug'],
|
|
agent['avatar_url'],
|
|
agent['color_hint'],
|
|
agent['priority'],
|
|
agent['is_active'],
|
|
agent['is_public'],
|
|
agent['public_slug'],
|
|
agent['public_title'],
|
|
agent['public_tagline'],
|
|
agent['public_district'],
|
|
agent['public_primary_room_slug'],
|
|
agent['is_listed_in_directory'],
|
|
agent['visibility_scope'],
|
|
agent['is_orchestrator'],
|
|
agent['home_node_id'],
|
|
agent['slug'],
|
|
)
|
|
updated += 1
|
|
else:
|
|
# Insert new agent
|
|
await conn.execute("""
|
|
INSERT INTO agents (
|
|
id, display_name, kind, role, model, node_id, district,
|
|
primary_room_slug, avatar_url, color_hint, priority,
|
|
is_active, status, is_public, public_slug, public_title,
|
|
public_tagline, public_district, public_primary_room_slug,
|
|
is_listed_in_directory, visibility_scope, is_orchestrator,
|
|
home_node_id, slug
|
|
) VALUES (
|
|
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13,
|
|
$14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24
|
|
)
|
|
""",
|
|
agent['id'],
|
|
agent['display_name'],
|
|
agent['kind'],
|
|
agent['role'],
|
|
agent['model'],
|
|
agent['node_id'],
|
|
agent['district'],
|
|
agent['primary_room_slug'],
|
|
agent['avatar_url'],
|
|
agent['color_hint'],
|
|
agent['priority'],
|
|
agent['is_active'],
|
|
agent['status'],
|
|
agent['is_public'],
|
|
agent['public_slug'],
|
|
agent['public_title'],
|
|
agent['public_tagline'],
|
|
agent['public_district'],
|
|
agent['public_primary_room_slug'],
|
|
agent['is_listed_in_directory'],
|
|
agent['visibility_scope'],
|
|
agent['is_orchestrator'],
|
|
agent['home_node_id'],
|
|
agent['slug'],
|
|
)
|
|
inserted += 1
|
|
|
|
print(f"\n✅ Sync complete!")
|
|
print(f" Inserted: {inserted} agents")
|
|
print(f" Updated: {updated} agents")
|
|
|
|
# Verify count
|
|
count = await conn.fetchval(
|
|
"SELECT COUNT(*) FROM agents WHERE node_id = $1 AND deleted_at IS NULL",
|
|
NODE2_ID
|
|
)
|
|
print(f" Total NODE2 agents: {count}")
|
|
|
|
finally:
|
|
await conn.close()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Sync NODE2 DAGI agents from config to database"
|
|
)
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
help="Preview changes without applying them"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print("=" * 60)
|
|
print("🤖 NODE2 DAGI Agent Sync")
|
|
print("=" * 60)
|
|
|
|
asyncio.run(sync_agents(dry_run=args.dry_run))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|