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

@@ -237,3 +237,4 @@ COMMENT ON SCHEMA public IS 'Messenger schema v1 - Matrix-aware implementation';

View File

@@ -153,3 +153,4 @@ ON CONFLICT (id) DO NOTHING;

View File

@@ -144,3 +144,4 @@ EXECUTE FUNCTION update_timestamp();

View File

@@ -0,0 +1,134 @@
-- Migration 013: City Map Coordinates
-- 2D City Map - add spatial coordinates and visual properties to city_rooms
-- =============================================================================
-- Add map coordinates and visual properties
-- =============================================================================
ALTER TABLE city_rooms
ADD COLUMN IF NOT EXISTS map_x INTEGER DEFAULT 0,
ADD COLUMN IF NOT EXISTS map_y INTEGER DEFAULT 0,
ADD COLUMN IF NOT EXISTS map_w INTEGER DEFAULT 1,
ADD COLUMN IF NOT EXISTS map_h INTEGER DEFAULT 1,
ADD COLUMN IF NOT EXISTS room_type TEXT DEFAULT 'public',
ADD COLUMN IF NOT EXISTS zone TEXT DEFAULT 'central',
ADD COLUMN IF NOT EXISTS icon TEXT,
ADD COLUMN IF NOT EXISTS color TEXT;
-- Create index for spatial queries
CREATE INDEX IF NOT EXISTS ix_city_rooms_map_coords ON city_rooms(map_x, map_y);
CREATE INDEX IF NOT EXISTS ix_city_rooms_zone ON city_rooms(zone);
CREATE INDEX IF NOT EXISTS ix_city_rooms_type ON city_rooms(room_type);
-- Add comments
COMMENT ON COLUMN city_rooms.map_x IS 'X coordinate on 2D city map (grid units)';
COMMENT ON COLUMN city_rooms.map_y IS 'Y coordinate on 2D city map (grid units)';
COMMENT ON COLUMN city_rooms.map_w IS 'Width on 2D city map (grid units)';
COMMENT ON COLUMN city_rooms.map_h IS 'Height on 2D city map (grid units)';
COMMENT ON COLUMN city_rooms.room_type IS 'Room type: public, governance, science, social, etc.';
COMMENT ON COLUMN city_rooms.zone IS 'City zone: central, north, south, east, west';
COMMENT ON COLUMN city_rooms.icon IS 'Icon identifier for UI (lucide icon name)';
COMMENT ON COLUMN city_rooms.color IS 'Primary color for room card/tile (hex or tailwind class)';
-- =============================================================================
-- Update existing rooms with map coordinates
-- Layout: 5x3 grid (central area)
-- =============================================================================
UPDATE city_rooms SET
map_x = 2, map_y = 0, map_w = 2, map_h = 2,
room_type = 'public', zone = 'central',
icon = 'message-square', color = 'cyan'
WHERE id = 'room_city_general';
UPDATE city_rooms SET
map_x = 0, map_y = 0, map_w = 2, map_h = 1,
room_type = 'social', zone = 'west',
icon = 'hand-wave', color = 'green'
WHERE id = 'room_city_welcome';
UPDATE city_rooms SET
map_x = 4, map_y = 0, map_w = 2, map_h = 1,
room_type = 'builders', zone = 'east',
icon = 'hammer', color = 'orange'
WHERE id = 'room_city_builders';
UPDATE city_rooms SET
map_x = 0, map_y = 1, map_w = 2, map_h = 1,
room_type = 'science', zone = 'west',
icon = 'flask-conical', color = 'purple'
WHERE id = 'room_city_science';
UPDATE city_rooms SET
map_x = 4, map_y = 1, map_w = 2, map_h = 1,
room_type = 'energy', zone = 'east',
icon = 'zap', color = 'yellow'
WHERE id = 'room_city_energy';
-- =============================================================================
-- City Map Config (global settings)
-- =============================================================================
CREATE TABLE IF NOT EXISTS city_map_config (
id TEXT PRIMARY KEY DEFAULT 'default',
grid_width INTEGER NOT NULL DEFAULT 6,
grid_height INTEGER NOT NULL DEFAULT 3,
cell_size INTEGER NOT NULL DEFAULT 100,
background_url TEXT,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
INSERT INTO city_map_config (id, grid_width, grid_height, cell_size) VALUES
('default', 6, 3, 100)
ON CONFLICT (id) DO NOTHING;
COMMENT ON TABLE city_map_config IS 'Global configuration for 2D city map rendering';
-- =============================================================================
-- Agents table (for Agent Presence on map)
-- =============================================================================
CREATE TABLE IF NOT EXISTS agents (
id TEXT PRIMARY KEY, -- ag_atlas, ag_oracle, etc.
display_name TEXT NOT NULL,
kind TEXT NOT NULL DEFAULT 'assistant', -- assistant, civic, oracle, builder
avatar_url TEXT,
color TEXT DEFAULT 'cyan',
status TEXT DEFAULT 'offline', -- online, offline, busy
current_room_id TEXT REFERENCES city_rooms(id) ON DELETE SET NULL,
capabilities JSONB DEFAULT '[]',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS ix_agents_status ON agents(status);
CREATE INDEX IF NOT EXISTS ix_agents_room ON agents(current_room_id) WHERE current_room_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS ix_agents_kind ON agents(kind);
COMMENT ON TABLE agents IS 'AI Agents registry for DAARION City';
-- =============================================================================
-- Seed default agents
-- =============================================================================
INSERT INTO agents (id, display_name, kind, color, status, current_room_id, capabilities) VALUES
('ag_atlas', 'Atlas', 'civic', 'cyan', 'online', 'room_city_general',
'["chat", "moderation", "onboarding"]'),
('ag_oracle', 'Oracle', 'oracle', 'purple', 'online', 'room_city_science',
'["research", "analysis", "predictions"]'),
('ag_builder', 'Builder Bot', 'builder', 'orange', 'offline', 'room_city_builders',
'["code", "automation", "integration"]'),
('ag_greeter', 'Greeter', 'social', 'green', 'online', 'room_city_welcome',
'["welcome", "help", "faq"]')
ON CONFLICT (id) DO UPDATE SET
display_name = EXCLUDED.display_name,
kind = EXCLUDED.kind,
color = EXCLUDED.color,
current_room_id = EXCLUDED.current_room_id,
capabilities = EXCLUDED.capabilities,
updated_at = NOW();
-- =============================================================================
-- END OF MIGRATION 013
-- =============================================================================