diff --git a/.gitignore b/.gitignore index 09354cfc..5a85ea38 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,10 @@ env/ .env .env.* !.env.example +discord_credentials.txt + +# Backup / temp files +*~ # SQLite — never commit databases or WAL/SHM artifacts *.db @@ -55,6 +59,19 @@ src/data/ *.swo .claude/ +# Local content — user-specific or generated +MEMORY.md +memory/self/user_profile.md +TIMMYTIME +introduction.txt +messages.txt +morning_briefing.txt +markdown_report.md +data/timmy_soul.jsonl +scripts/migrate_to_zeroclaw.py +src/infrastructure/db_pool.py +workspace/ + # macOS .DS_Store .AppleDouble diff --git a/MEMORY.md b/MEMORY.md deleted file mode 100644 index 5fccd07f..00000000 --- a/MEMORY.md +++ /dev/null @@ -1,52 +0,0 @@ -# Timmy Hot Memory - -> Working RAM — always loaded, ~300 lines max, pruned monthly -> Last updated: 2026-02-26 - ---- - -## Current Status - -**Agent State:** Operational -**Mode:** Development -**Active Tasks:** 0 -**Pending Decisions:** None - ---- - -## Standing Rules - -1. **Sovereignty First** — No cloud dependencies -2. **Local-Only Inference** — Ollama on localhost -3. **Privacy by Design** — Telemetry disabled -4. **Tool Minimalism** — Use tools only when necessary -5. **Memory Discipline** — Write handoffs at session end - ---- - -## Agent Roster - -| Agent | Role | Status | -|-------|------|--------| -| Timmy | Core | Active | - ---- - -## User Profile - -**Name:** Not - - -## Key Decisions - -(none yet) - ---- - -## Pending Actions - -- [ ] Learn user's name - ---- - -*Prune date: 2026-02-25* diff --git a/memory/self/user_profile.md b/memory/self/user_profile.md deleted file mode 100644 index 2c09340a..00000000 --- a/memory/self/user_profile.md +++ /dev/null @@ -1,43 +0,0 @@ -# User Profile - -> Learned information about the user. Updated continuously. - -## Basic Information - -**Name:** Not -**Location:** (unknown) -**Occupation:** (unknown) -**Technical Level:** (to be assessed) - -## Interests & Expertise - -- (to be learned from conversations) - -## Preferences - -### Communication -- Response style: (default: concise, technical) -- Detail level: (default: medium) -- Humor: (default: minimal) - -### Tools -- Auto-tool usage: (default: minimal) -- Confirmation required for: shell commands, file writes - -### Memory -- Personalization: Enabled -- Context retention: 20 messages (working), 100 (short-term) - -## Important Facts - -- (to be extracted from conversations) - -## Relationship History - -- First session: 2026-02-25 -- Total sessions: 1 -- Key milestones: (none yet) - ---- - -*Last updated: 2026-02-27* diff --git a/src/dashboard/routes/marketplace.py b/src/dashboard/routes/marketplace.py index 64e50d7b..7afa6847 100644 --- a/src/dashboard/routes/marketplace.py +++ b/src/dashboard/routes/marketplace.py @@ -47,28 +47,41 @@ async def api_list_agents(): @router.get("/marketplace") +async def marketplace_json(request: Request): + """Marketplace JSON API (backward compat).""" + return await api_list_agents() + + +@router.get("/marketplace/ui", response_class=HTMLResponse) async def marketplace_ui(request: Request): - """Marketplace page — returns JSON for API requests, HTML for browser.""" - # Check if client wants JSON (common test clients don't set Accept header) - accept = request.headers.get("accept", "") - # Return JSON if Accept header indicates JSON OR if no preference (default to JSON for API) - if "application/json" in accept or accept == "*/*" or not accept: - return await api_list_agents() - - # Browser request - return HTML + """Marketplace HTML page.""" try: brain = BrainClient() tasks = await brain.get_pending_tasks(limit=20) except Exception: tasks = [] - + + # Enrich agents with fields the template expects + enriched = [] + for agent in AGENT_CATALOG: + a = dict(agent) + a.setdefault("status", a.get("default_status", "active")) + a.setdefault("tasks_completed", 0) + a.setdefault("total_earned", 0) + enriched.append(a) + + active = sum(1 for a in enriched if a["status"] == "active") + return templates.TemplateResponse( request, "marketplace.html", { - "agents": AGENT_CATALOG, + "agents": enriched, "pending_tasks": tasks, "message": "Personas deprecated — use Brain Task Queue", + "page_title": "Agent Marketplace", + "active_count": active, + "planned_count": 0, } ) diff --git a/src/dashboard/routes/swarm.py b/src/dashboard/routes/swarm.py index 21b0e607..67b81daf 100644 --- a/src/dashboard/routes/swarm.py +++ b/src/dashboard/routes/swarm.py @@ -4,11 +4,12 @@ import json import logging from typing import Optional -from fastapi import APIRouter, Request +from fastapi import APIRouter, Request, WebSocket, WebSocketDisconnect from fastapi.responses import HTMLResponse from spark.engine import spark_engine from dashboard.templating import templates +from infrastructure.ws_manager.handler import ws_manager logger = logging.getLogger(__name__) @@ -31,13 +32,13 @@ async def swarm_events( if agent_id: events = [e for e in events if e.agent_id == agent_id] if event_type: - events = [e for e in events if e.event_type.value == event_type] + events = [e for e in events if e.event_type == event_type] # Prepare summary and event types for template summary = {} event_types = set() for e in events: - etype = e.event_type.value + etype = e.event_type event_types.add(etype) summary[etype] = summary.get(etype, 0) + 1 @@ -60,7 +61,7 @@ async def swarm_live(request: Request): """Live swarm activity page.""" status = spark_engine.status() events = spark_engine.get_timeline(limit=20) - + return templates.TemplateResponse( request, "swarm_live.html", @@ -69,3 +70,34 @@ async def swarm_live(request: Request): "events": events, }, ) + + +@router.websocket("/live") +async def swarm_ws(websocket: WebSocket): + """WebSocket endpoint for live swarm updates.""" + await ws_manager.connect(websocket) + try: + while True: + await websocket.receive_text() + except WebSocketDisconnect: + ws_manager.disconnect(websocket) + + +@router.get("/agents/sidebar", response_class=HTMLResponse) +async def agents_sidebar(request: Request): + """Sidebar partial showing agent status for the home page.""" + from config import settings + + agents = [ + { + "id": "default", + "name": settings.agent_name, + "status": "idle", + "type": "local", + "capabilities": "chat,reasoning,research,planning", + "last_seen": None, + } + ] + return templates.TemplateResponse( + request, "partials/swarm_agents_sidebar.html", {"agents": agents} + ) diff --git a/src/dashboard/routes/system.py b/src/dashboard/routes/system.py index 84e49bd5..3651bc5b 100644 --- a/src/dashboard/routes/system.py +++ b/src/dashboard/routes/system.py @@ -89,7 +89,9 @@ async def mission_control(request: Request): @router.get("/bugs", response_class=HTMLResponse) async def bugs_page(request: Request): - return templates.TemplateResponse(request, "bugs.html", {"bugs": []}) + return templates.TemplateResponse(request, "bugs.html", { + "bugs": [], "total": 0, "stats": {}, "filter_status": None, + }) @router.get("/self-coding", response_class=HTMLResponse) diff --git a/src/dashboard/templates/base.html b/src/dashboard/templates/base.html index 984ee5f3..0fb7e3a2 100644 --- a/src/dashboard/templates/base.html +++ b/src/dashboard/templates/base.html @@ -15,6 +15,14 @@ {% block extra_styles %}{% endblock %} + diff --git a/src/dashboard/templates/events.html b/src/dashboard/templates/events.html index 72753edd..915f0061 100644 --- a/src/dashboard/templates/events.html +++ b/src/dashboard/templates/events.html @@ -63,14 +63,14 @@
{% for event in events %} -