1
0

feat: complete Event Log, Ledger, Memory, Cascade Router, Upgrade Queue, Activity Feed

This commit implements six major features:

1. Event Log System (src/swarm/event_log.py)
   - SQLite-based audit trail for all swarm events
   - Task lifecycle tracking (created, assigned, completed, failed)
   - Agent lifecycle tracking (joined, left, status changes)
   - Integrated with coordinator for automatic logging
   - Dashboard page at /swarm/events

2. Lightning Ledger (src/lightning/ledger.py)
   - Transaction tracking for Lightning Network payments
   - Balance calculations (incoming, outgoing, net, available)
   - Integrated with payment_handler for automatic logging
   - Dashboard page at /lightning/ledger

3. Semantic Memory / Vector Store (src/memory/vector_store.py)
   - Embedding-based similarity search for Echo agent
   - Fallback to keyword matching if sentence-transformers unavailable
   - Personal facts storage and retrieval
   - Dashboard page at /memory

4. Cascade Router Integration (src/timmy/cascade_adapter.py)
   - Automatic LLM failover between providers (Ollama → AirLLM → API)
   - Circuit breaker pattern for failing providers
   - Metrics tracking per provider (latency, error rates)
   - Dashboard status page at /router/status

5. Self-Upgrade Approval Queue (src/upgrades/)
   - State machine for self-modifications: proposed → approved/rejected → applied/failed
   - Human approval required before applying changes
   - Git integration for branch management
   - Dashboard queue at /self-modify/queue

6. Real-Time Activity Feed (src/events/broadcaster.py)
   - WebSocket-based live activity streaming
   - Bridges event_log to dashboard clients
   - Activity panel on /swarm/live

Tests:
- 101 unit tests passing
- 4 new E2E test files for Selenium testing
- Run with: SELENIUM_UI=1 pytest tests/functional/ -v --headed

Documentation:
- 6 ADRs (017-022) documenting architecture decisions
- Implementation summary in docs/IMPLEMENTATION_SUMMARY.md
- Architecture diagram in docs/architecture-v2.md
This commit is contained in:
Alexander Payne
2026-02-26 08:01:01 -05:00
parent 8d85f95ee5
commit d8d976aa60
41 changed files with 6735 additions and 254 deletions

View File

@@ -0,0 +1,98 @@
"""Memory (vector store) routes for browsing and searching memories."""
from pathlib import Path
from typing import Optional
from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from memory.vector_store import (
store_memory,
search_memories,
get_memory_stats,
recall_personal_facts,
store_personal_fact,
)
router = APIRouter(prefix="/memory", tags=["memory"])
templates = Jinja2Templates(directory=str(Path(__file__).parent.parent / "templates"))
@router.get("", response_class=HTMLResponse)
async def memory_page(
request: Request,
query: Optional[str] = None,
context_type: Optional[str] = None,
agent_id: Optional[str] = None,
):
"""Memory browser and search page."""
results = []
if query:
results = search_memories(
query=query,
context_type=context_type,
agent_id=agent_id,
limit=20,
)
stats = get_memory_stats()
facts = recall_personal_facts(limit=10)
return templates.TemplateResponse(
request,
"memory.html",
{
"page_title": "Memory Browser",
"query": query,
"results": results,
"stats": stats,
"facts": facts,
"filter_type": context_type,
"filter_agent": agent_id,
},
)
@router.post("/search", response_class=HTMLResponse)
async def memory_search(
request: Request,
query: str = Form(...),
context_type: Optional[str] = Form(None),
):
"""Search memories (form submission)."""
results = search_memories(
query=query,
context_type=context_type,
limit=20,
)
# Return partial for HTMX
return templates.TemplateResponse(
request,
"partials/memory_results.html",
{
"query": query,
"results": results,
},
)
@router.post("/fact", response_class=HTMLResponse)
async def add_fact(
request: Request,
fact: str = Form(...),
agent_id: Optional[str] = Form(None),
):
"""Add a personal fact to memory."""
store_personal_fact(fact, agent_id=agent_id)
# Return updated facts list
facts = recall_personal_facts(limit=10)
return templates.TemplateResponse(
request,
"partials/memory_facts.html",
{
"facts": facts,
},
)