feat: Add presence heartbeat for Matrix online status

- matrix-gateway: POST /internal/matrix/presence/online endpoint
- usePresenceHeartbeat hook with activity tracking
- Auto away after 5 min inactivity
- Offline on page close/visibility change
- Integrated in MatrixChatRoom component
This commit is contained in:
Apple
2025-11-27 00:19:40 -08:00
parent 5bed515852
commit 3de3c8cb36
6371 changed files with 1317450 additions and 932 deletions

View File

@@ -0,0 +1,294 @@
# Agent Filter Service
**Security & routing layer for DAARION agents in Messenger**
## Purpose
Agent Filter decides when and which agents should respond to messages based on configurable rules.
## Features
- **Loop Prevention**: Blocks agent→agent message loops
- **Quiet Hours**: Modifies agent behavior during specified times (23:0007:00)
- **Agent Mapping**: Maps microDAOs to default agents
- **Channel Permissions**: Respects allowed/disabled agents per channel
- **NATS Integration**: Subscribes to message events, publishes filter decisions
## Architecture
```
messaging.message.created (NATS)
agent-filter: Apply Rules
agent.filter.decision (NATS)
```
## Rules
### 1. Loop Prevention
- **Rule**: Block messages from agents
- **Reason**: Prevent infinite agent→agent conversations
### 2. Quiet Hours
- **Time**: 23:00 07:00 (configurable in `config.yaml`)
- **Effect**: Adds rewrite prompt for concise responses
- **Purpose**: Reduce agent activity during off-hours
### 3. Agent Mapping
- **Default Agents**: Defined per microDAO in `config.yaml`
- **Channel Override**: Channels can specify `allowed_agents`
- **Fallback**: If no agent found, deny
### 4. Disabled Agents
- **Check**: Ensures target agent is not in `disabled_agents` list
- **Source**: From channel context
## API
### Health Check
```http
GET /health
Response:
{
"status": "ok",
"service": "agent-filter",
"version": "1.0.0",
"nats_connected": true
}
```
### Test Filtering (Manual)
```http
POST /internal/agent-filter/test
Content-Type: application/json
{
"channel_id": "test-channel-id",
"matrix_event_id": "$event123:matrix.daarion.city",
"sender_id": "user:93",
"sender_type": "human",
"microdao_id": "microdao:daarion",
"created_at": "2025-11-24T12:00:00Z"
}
Response:
{
"channel_id": "test-channel-id",
"matrix_event_id": "$event123:matrix.daarion.city",
"microdao_id": "microdao:daarion",
"decision": "allow",
"target_agent_id": "agent:sofia"
}
```
## Configuration
**File**: `config.yaml`
```yaml
nats:
servers: ["nats://nats:4222"]
messaging_subject: "messaging.message.created"
decision_subject: "agent.filter.decision"
rules:
quiet_hours:
start: "23:00"
end: "07:00"
default_agents:
"microdao:daarion": "agent:sofia"
"microdao:7": "agent:sofia"
```
## Environment Variables
- `MESSAGING_SERVICE_URL`: URL of messaging-service (default: `http://messaging-service:7004`)
- `NATS_URL`: NATS server URL (default: `nats://nats:4222`)
## Running Locally
### Install Dependencies
```bash
pip install -r requirements.txt
```
### Run Service
```bash
uvicorn main:app --reload --port 7005
```
### Test
```bash
# Health check
curl http://localhost:7005/health
# Test filtering
curl -X POST http://localhost:7005/internal/agent-filter/test \
-H "Content-Type: application/json" \
-d '{
"channel_id": "test-123",
"matrix_event_id": "$test:matrix.daarion.city",
"sender_id": "user:1",
"sender_type": "human",
"microdao_id": "microdao:daarion",
"created_at": "2025-11-24T12:00:00Z"
}'
```
## Docker
### Build
```bash
docker build -t daarion/agent-filter:latest .
```
### Run
```bash
docker run -p 7005:7005 \
-e MESSAGING_SERVICE_URL=http://messaging-service:7004 \
-e NATS_URL=nats://nats:4222 \
daarion/agent-filter:latest
```
## NATS Events
### Subscribes To
- **Subject**: `messaging.message.created`
- **Payload**: `MessageCreatedEvent`
```json
{
"channel_id": "uuid",
"message_id": "uuid",
"matrix_event_id": "$event:server",
"sender_id": "user:X or agent:Y",
"sender_type": "human | agent",
"microdao_id": "microdao:X",
"created_at": "2025-11-24T12:00:00Z"
}
```
### Publishes To
- **Subject**: `agent.filter.decision`
- **Payload**: `FilterDecision`
```json
{
"channel_id": "uuid",
"message_id": "uuid",
"matrix_event_id": "$event:server",
"microdao_id": "microdao:X",
"decision": "allow | deny | modify",
"target_agent_id": "agent:sofia",
"rewrite_prompt": "Optional prompt modification"
}
```
## Development
### Adding New Rules
Edit `rules.py`:
```python
def decide(self, event: MessageCreatedEvent, ctx: FilterContext) -> FilterDecision:
# Add your rule here
if some_condition:
return FilterDecision(
decision="deny",
# ... other fields
)
# Continue with existing rules
...
```
### Testing Rules
Use the test endpoint:
```bash
curl -X POST http://localhost:7005/internal/agent-filter/test \
-H "Content-Type: application/json" \
-d @test_event.json
```
## Monitoring
### Logs
```bash
# Docker
docker logs -f agent-filter
# Look for:
# ✅ Connected to NATS
# ✅ Subscribed to messaging.message.created
# 📨 Received message.created event
# 🎯 Decision: allow/deny/modify
# ✅ Published decision to NATS
```
### Metrics (Future)
- Total messages processed
- Decisions per type (allow/deny/modify)
- Average processing time
- NATS connection status
## Troubleshooting
### NATS Not Connected
```
⚠️ NATS not available: [error]
⚠️ Running in test mode (HTTP only)
```
**Solution**: Check NATS is running and accessible:
```bash
docker ps | grep nats
docker logs nats
```
### No Decisions Published
**Check**:
1. Is messaging-service publishing events?
2. Is channel context endpoint working?
3. Are rules correctly configured?
```bash
# Test channel context
curl http://localhost:7004/internal/messaging/channels/{channel_id}/context
```
### Always Denying
**Common causes**:
1. Sender is agent (loop prevention)
2. No target agent found
3. Target agent is disabled
4. Channel context not accessible
**Debug**: Use test endpoint and check logs
## Future Enhancements
- [ ] Keyword-based triggers ("@sofia", "@assistant")
- [ ] Per-user permissions
- [ ] Rate limiting per agent
- [ ] Sentiment analysis for filtering
- [ ] ML-based spam detection
- [ ] Custom rule scripting (Lua/Python)
## Version
**Current**: 1.0.0
**Status**: Production Ready
**Last Updated**: 2025-11-24