Adds an MCP tool wrapping the inventory-service /search/items endpoint with include_all_characters=true, so questions like 'find me a bracelet with Legendary Acid Ward on any unequipped char' resolve in ONE tool call instead of looping get_inventory over 60+ chars (which timed out at 120s). - agent/tools.py: search_items_global wrapper - agent/mcp_overlord.py: register new tool with detailed schema doc - agent/claude_wrapper.py: include in --allowed-tools whitelist; bump timeout 120s -> 240s - nginx/overlord.conf: bump /api/agent/ proxy timeout 180s -> 300s - CLAUDE.md: brief Claude to USE search_items for cross-char searches
9.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Dereth Tracker is a real-time telemetry service for game world tracking. It's a FastAPI-based WebSocket and HTTP API service that ingests player position/stats data via plugins and provides live map visualization through a web interface.
Key Components
Main Service (main.py)
- WebSocket endpoint
/ws/positionreceives telemetry and inventory events - Routes inventory events to inventory service via HTTP
- Handles real-time player tracking and map updates
Inventory Service (inventory-service/main.py)
- Separate FastAPI service for inventory management
- Processes inventory JSON into normalized PostgreSQL tables
- Provides search API with advanced filtering and sorting
- Uses comprehensive enum database for translating game IDs to readable names
Database Architecture
- Telemetry DB: TimescaleDB for time-series player tracking data
- Inventory DB: PostgreSQL with normalized schema for equipment data
items: Core item propertiesitem_combat_stats: Armor level, damage bonusesitem_enhancements: Material, item sets, tinkeringitem_spells: Spell names and categoriesitem_raw_data: Original JSON for complex queries
Memories and Known Bugs
- Fixed: Material names now properly display (e.g., "Gold Celdon Girth" instead of "Unknown_Material_Gold Celdon Girth")
- Fixed: Slot column shows "-" instead of "Unknown" for items without slot data
- Fixed: All 208 items in Larsson's inventory now process successfully (was 186 with 22 SQL type errors)
- Added: Type column in inventory search using object_classes enum for accurate item type classification
- Note: ItemType data is inconsistent in JSON - using ObjectClass as primary source for Type column
Recent Fixes (September 2025)
Portal Coordinate Rounding Fix ✅ RESOLVED
- Problem: Portal insertion failed with duplicate key errors due to coordinate rounding mismatch
- Root Cause: Code used 2 decimal places (
ROUND(ns::numeric, 2)) but database constraint used 1 decimal place - Solution: Changed all portal coordinate checks to use 1 decimal place to match DB constraint
- Result: 98% reduction in duplicate key errors (from 600+/min to ~11/min)
- Location:
main.pylines ~1989, 1996, 2025, 2047
Character Display Issues ✅ RESOLVED
- Problem: Some characters (e.g., "Crazed n Dazed") not appearing in frontend
- Root Cause: Database connection pool exhaustion from portal error spam
- Solution: Fixed portal errors to reduce database load
- Result: Characters now display correctly after portal fix
Docker Container Deployment
- Issue: Code changes require container rebuild with
--no-cacheflag - Command:
docker compose build --no-cache dereth-tracker - Reason: Docker layer caching can prevent updated source code from being copied
Current Known Issues
Minor Portal Race Conditions
- Status: ~11 duplicate key errors per minute (down from 600+)
- Cause: Multiple players discovering same portal simultaneously
- Impact: Minimal - errors are caught and handled gracefully
- Handling: Try/catch in code logs as debug messages and updates portal timestamp
- Potential Fix: PostgreSQL ON CONFLICT DO UPDATE (upsert pattern) would eliminate completely
Database Initialization Warnings
- TimescaleDB Hypertable:
telemetry_eventsfails to become hypertable due to primary key constraint - Impact: None - table works as regular PostgreSQL table
- Warning: "cannot create a unique index without the column 'timestamp'"
Connection Pool Under Load
- Issue: Database queries can timeout when connection pool is exhausted
- Symptom: Characters may not appear during high error load
- Mitigation: Portal error fix significantly reduced this issue
Equipment Suit Builder
Status: PRODUCTION READY
Real-time equipment optimization engine for building optimal character loadouts by searching across multiple characters' inventories (mules). Uses Mag-SuitBuilder constraint satisfaction algorithms.
Core Features:
- Multi-character inventory search across 100+ characters, 25,000+ items
- Armor set constraints (primary 5-piece + secondary 4-piece set support)
- Cantrip/ward spell optimization with bitmap-based overlap detection
- Crit damage rating optimization
- Locked slots with set/spell preservation across searches
- Real-time SSE streaming with progressive phase updates
- Suit summary with copy-to-clipboard functionality
- Stable deterministic sorting for reproducible results
Access: /suitbuilder.html
Architecture Details: See docs/plans/2026-02-09-suitbuilder-architecture.md
Known Limitations
- Slot-aware spell filtering not yet implemented (e.g., underclothes have limited spell pools but system treats all slots equally)
- All spells weighted equally (no priority/importance weighting yet)
- See architecture doc for future enhancement roadmap
Technical Notes for Development
Database Performance
- Connection pool: 5-20 connections (configured in
db_async.py) - Under heavy error load, pool exhaustion can cause 2-minute query timeouts
- Portal error fix significantly improved database performance
Docker Development Workflow
- Code Changes: Edit source files locally
- Rebuild:
docker compose build --no-cache dereth-tracker(required for code changes) - Deploy:
docker compose up -d dereth-tracker - Debug:
docker logs mosswartoverlord-dereth-tracker-1anddocker logs dereth-db
Frontend Architecture
- Main Map:
static/index.html- Real-time player tracking - Inventory Search:
static/inventory.html- Advanced item filtering - Suitbuilder:
static/suitbuilder.html- Equipment optimization interface - All static files: Served directly by FastAPI StaticFiles
DOM Optimization Status ✅ COMPLETE (September 2025)
- Achievement: 100% DOM element reuse with zero element creation after initial render
- Performance: ~5ms render time for 69 players, eliminated 4,140+ elements/minute creation
- Implementation: Element pooling system with player name mapping for O(1) lookup
- Monitoring: Color-coded console output (✨ green = optimized, ⚡ yellow = partial, 🔥 red = poor)
- Status: Production ready - achieving perfect element reuse consistently
Current Render Stats:
- ✅ This render: 0 dots created, 69 reused | 0 list items created, 69 reused
- ✅ Lifetime: 69 dots created, 800+ reused | 69 list items created, 800+ reused
Remaining TODO:
- ❌ Fix CSS Grid layout for player sidebar (deferred per user request)
- ❌ Extend optimization to trails and portal rendering
- ❌ Add memory usage tracking
WebSocket Endpoints
/ws/position: Plugin telemetry, inventory, portal, rare events (authenticated)/ws/live: Browser client commands and live updates (unauthenticated)
Overlord Assistant Mode
When invoked through the dashboard's chat window (the 🤖 Assistant button) or through /api/agent/ask, you are acting as the Overlord Assistant — answering ad-hoc questions for the user about their live multi-account Asheron's Call setup.
You have MCP tools (from .mcp.json) for live game data. Always use them instead of guessing or apologising for not having data:
get_live_players— current online characters with positions/kills/stateget_recent_rares— rare item finds in the last N hoursquery_telemetry_db— read-only SQL on the telemetry DB for ad-hoc analysissearch_items— cross-character inventory search (use this instead of loopingget_inventoryper character — single call is much faster)get_inventory/get_inventory_search— single-character inventoryget_player_state/get_combat_stats/get_equipment_cantrips— per-character lookupsget_quest_status/get_server_health— global statesuitbuilder_search— armor optimization (slow, only on explicit request)
Behaviour rules
- Use tools, don't speculate. If the user asks "how many chars are online" — call
get_live_players. Don't say "I'd need to check" — just check. 1a. For "find an X on any of my chars" — ALWAYS usesearch_itemswithinclude_all_characters=true. Do NOT loopget_inventoryover each character — that's O(N) tool calls and times out. - Be concise. The user is glancing at a chat window, not reading a report. 2-5 sentences for most answers. Use markdown tables for tabular data.
- No code unless asked. This mode is about operating the system, not editing it. Don't open files or write code unless the user explicitly asks.
- Real numbers, real names. Cite actual character names and counts from tools — never make up sample data.
- Read-only. You cannot mutate the database; the SQL tool will reject any non-SELECT statement and the role is also
GRANT SELECTonly. If a question requires a write, say so. - Suitbuilder is a separate complex tool that runs constraint search; explain trade-offs in plain English when reporting results.
- Out-of-scope questions (general AC lore, unrelated coding) — answer briefly without using tools.
Available data tables (for query_telemetry_db)
telemetry_events(hypertable, 30-day retention) — position/state snapshots every ~2s per characterrare_events— rare item find logspawn_events(hypertable, 7-day retention) — monster spawn observationsportals— discovered portal coords (1h dedup window)char_stats,rare_stats,rare_stats_sessions— lifetime/session aggregatescharacter_stats— latest full stats JSON per charactercombat_stats,combat_stats_sessions— combat trackingserver_status— current Coldeve game-server state (single row)
If asked about something not covered above, look in db_async.py for the schema or just try a query and report what you see.