Skip to content

Commit 548f911

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 0d340da + 0b01bc5 commit 548f911

File tree

71 files changed

+8763
-6476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+8763
-6476
lines changed

.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ FEATURE_TOOLS_ENABLED=false # MCP / tools panel
6060
FEATURE_MARKETPLACE_ENABLED=false # Marketplace browsing (disabled)
6161
FEATURE_FILES_PANEL_ENABLED=false # Uploaded/session files panel
6262
FEATURE_CHAT_HISTORY_ENABLED=false # Previous chat history list
63+
FEATURE_COMPLIANCE_LEVELS_ENABLED=false # Compliance level filtering for MCP servers and data sources
6364

6465
# (Adjust above to stage rollouts. For a bare-bones chat set them all to false.)
6566

@@ -91,4 +92,8 @@ S3_ACCESS_KEY=minioadmin
9192
S3_SECRET_KEY=minioadmin
9293
S3_REGION=us-east-1
9394
S3_TIMEOUT=30
94-
S3_USE_SSL=false
95+
96+
S3_USE_SSL=false
97+
98+
99+
SECURITY_CSP_VALUE="default-src 'self'; img-src 'self' data: blob:; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; frame-src 'self' blob: data:; frame-ancestors 'self'"

.github/copilot-instructions.md

Lines changed: 60 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,71 @@
1-
# Chat UI Development Instructions
1+
# AI Agent Guide: Atlas UI 3
22

3-
**ALWAYS follow these instructions first and fallback to additional search and context gathering only if the information in these instructions is incomplete or found to be in error.**
3+
Concise rules for getting productive fast in this repo. Prefer these over exploration; fall back to code/docs only if something is missing.
44

5-
## Working Effectively
6-
7-
### Prerequisites and Setup
8-
- **CRITICAL**: Install `uv` Python package manager - this project requires `uv`, NOT pip or conda:
9-
```bash
10-
# Install uv (required)
11-
curl -LsSf https://astral.sh/uv/install.sh | sh
12-
# OR as fallback: pip install uv
13-
uv --version # Verify installation
14-
```
15-
- **Node.js 18+** and npm for frontend development
16-
- **Python 3.12+** for backend
17-
18-
### Initial Environment Setup
19-
```bash
20-
# Create Python virtual environment (takes ~1 second)
21-
uv venv
22-
source .venv/bin/activate # Windows: .venv\Scripts\activate
23-
24-
# Install Python dependencies (takes ~2-3 minutes)
25-
uv pip install -r requirements.txt
26-
27-
# Setup environment configuration
28-
cp .env.example .env
29-
# Edit .env and set DEBUG_MODE=true for development
30-
31-
# Create required directories
32-
mkdir -p logs
33-
```
34-
35-
### Build Process
36-
```bash
37-
# Install frontend dependencies (takes ~15 seconds)
38-
cd frontend
39-
npm install
40-
41-
# Build frontend (takes ~5 seconds)
42-
# CRITICAL: Use npm run build, NOT npm run dev (WebSocket issues)
43-
npm run build
44-
45-
# Verify build output exists
46-
ls -la dist/ # Should contain index.html and assets/
47-
```
48-
49-
### Running the Application
50-
```bash
51-
# Start backend (Terminal 1)
52-
cd backend
53-
python main.py
54-
# Server starts on http://localhost:8000
55-
# NEVER use uvicorn --reload (causes problems)
56-
57-
# Frontend is already built and served by backend
58-
# Open http://localhost:8000 to access application
59-
```
60-
61-
## Testing
62-
63-
### Run All Tests (NEVER CANCEL - takes up to 2 minutes total)
64-
```bash
65-
# Backend tests (takes ~5 seconds) - NEVER CANCEL, set timeout 60+ seconds
66-
./test/run_tests.sh backend
67-
68-
# Frontend tests (takes ~6 seconds) - NEVER CANCEL, set timeout 60+ seconds
69-
./test/run_tests.sh frontend
70-
71-
# E2E tests (may fail if auth not configured, takes ~70 seconds) - NEVER CANCEL, set timeout 120+ seconds
72-
./test/run_tests.sh e2e
5+
## Do this first
6+
- Use uv (not pip/conda). One-time: install uv. Then:
7+
```bash
8+
uv venv && source .venv/bin/activate
9+
uv pip install -r requirements.txt
10+
bash agent_start.sh # builds frontend, starts backend, seeds/mocks
11+
```
12+
- Manual quick run (alternative):
13+
```bash
14+
(frontend) cd frontend && npm install && npm run build
15+
(backend) cd backend && python main.py # don’t use uvicorn --reload
16+
```
7317

74-
# All tests together - NEVER CANCEL, set timeout 180+ seconds
75-
./test/run_tests.sh all
18+
## Architecture (big picture)
7619
```
77-
78-
### Code Quality and Linting
79-
```bash
80-
# Python linting (install ruff first if not available)
81-
source .venv/bin/activate
82-
uv pip install ruff
83-
ruff check backend/ # Takes ~1 second
84-
85-
# Frontend linting (takes ~1 second)
86-
cd frontend
87-
npm run lint
20+
backend/ FastAPI app + WebSocket
21+
main.py → /ws, serves frontend/dist, includes /api/* routes
22+
infrastructure/app_factory.py → wires LLM (LiteLLM), MCP, RAG, files, config
23+
application/chat/service.py → ChatService orchestrator and streaming
24+
modules/mcp_tools/ → FastMCP client, tool/prompt discovery, auth filtering
25+
modules/config/manager.py → Pydantic configs + layered search
26+
domain/rag_mcp_service.py → RAG over MCP discovery/search/synthesis
27+
core/compliance.py → compliance-levels load/validate/allowlist
28+
frontend/ React 19 + Vite + Tailwind; state via contexts (Chat/WS/Marketplace)
8829
```
8930

90-
## Validation Scenarios
91-
92-
### Manual Application Testing
93-
After making changes, ALWAYS validate by running through these scenarios:
94-
95-
1. **Basic Application Load**:
31+
## Configuration & feature flags
32+
- Layering (in priority): env vars → config/overrides → config/defaults → legacy backend/configfiles*. Env vars APP_CONFIG_OVERRIDES/DEFAULTS control search roots.
33+
- Files: llmconfig.yml, mcp.json, mcp-rag.json, help-config.json; environment in .env (copy .env.example).
34+
- Feature flags (AppSettings): FEATURE_TOOLS_ENABLED, FEATURE_RAG_MCP_ENABLED, FEATURE_COMPLIANCE_LEVELS_ENABLED, FEATURE_AGENT_MODE_AVAILABLE.
35+
36+
## MCP + RAG conventions
37+
- MCP servers live in mcp.json (tools/prompts) and mcp-rag.json (RAG-only inventory). Fields: groups, is_exclusive, transport|type, url|command/cwd, compliance_level.
38+
- Transport detection order: explicit transport → command (stdio) → URL protocol (http/sse) → type fallback.
39+
- Tool names exposed to LLM are fully-qualified: server_toolName. “canvas_canvas” is a pseudo-tool always available.
40+
- RAG over MCP tools expected: rag_discover_resources, rag_get_raw_results, optional rag_get_synthesized_results. RAG resources and servers may include complianceLevel.
41+
42+
## Compliance levels (explicit allowlist)
43+
- Definitions in config/(overrides|defaults)/compliance-levels.json. core/compliance.py loads, normalizes aliases, and enforces allowed_with.
44+
- Validated on load for LLM models, MCP servers, and RAG MCP servers. When FEATURE_COMPLIANCE_LEVELS_ENABLED=true:
45+
- /api/config includes model and server compliance_level
46+
- domain/rag_mcp_service filters servers and per-resource „complianceLevel“ using ComplianceLevelManager.is_accessible(user, resource)
47+
48+
## Key APIs/contracts
49+
- WebSocket: /ws. Messages: chat, download_file, reset_session, attach_file. Backend streams token_stream, tool_use, canvas_content, intermediate_update.
50+
- REST: /api/config (models/tools/prompts/data_sources/rag_servers/features), /api/compliance-levels, /admin/* for configs/logs (admin group required).
51+
52+
## Developer workflows
53+
- Tests (don’t cancel):
9654
```bash
97-
# Test homepage loads
98-
curl -s http://localhost:8000/ | grep "Chat UI"
99-
100-
# Test API responds
101-
curl -s http://localhost:8000/api/config | jq .app_name
55+
./test/run_tests.sh backend | frontend | e2e | all
10256
```
57+
- Lint: uv pip install ruff && ruff check backend/; frontend: npm run lint.
58+
- Logs: project_root/logs/app.jsonl (override with APP_LOG_DIR). Use /admin/logs/*.
10359

104-
2. **Chat Interface Testing**:
105-
- Open http://localhost:8000 in browser
106-
- Verify page loads without console errors
107-
- Test sending a simple message: "Hello, how are you?"
108-
- Verify WebSocket connection works (real-time response)
109-
- Test settings panel opens without errors
110-
111-
3. **MCP Tools Testing** (if enabled):
112-
- Open settings panel
113-
- Verify MCP servers are discovered
114-
- Test a simple tool like calculator: "What's 2+2?"
115-
116-
## Important Development Notes
117-
118-
### Critical Restrictions
119-
- **NEVER use `uvicorn --reload`** - it causes development problems
120-
- **NEVER use `npm run dev`** - it has WebSocket connection issues
121-
- **ALWAYS use `npm run build`** for frontend development
122-
- **ALWAYS use `uv`** for Python package management, not pip
123-
- **NEVER CANCEL builds or tests** - they may take time but must complete
124-
125-
### Key File Locations
126-
- **Backend**: `/backend/` - FastAPI application with WebSocket support
127-
- **Frontend**: `/frontend/` - React + Vite application
128-
- **Build Output**: `/frontend/dist/` - served by backend
129-
- **Configuration**: `.env` file (copy from `.env.example`)
130-
- **Tests**: `/test/` directory with individual test scripts
131-
- **Documentation**: `/docs/` directory
132-
133-
### Project Architecture
134-
- **Backend**: FastAPI serving both API and static frontend files
135-
- **Frontend**: React 19 with Vite, Tailwind CSS, builds to `dist/`
136-
- **Communication**: WebSocket for real-time chat, REST API for configuration
137-
- **MCP Integration**: Model Context Protocol for extensible tool support
138-
- **Authentication**: Configurable, set `DEBUG_MODE=true` to skip for development
139-
140-
### Common Issues and Solutions
141-
142-
1. **"uv not found"**: Install uv package manager (most common issue)
143-
2. **WebSocket connection fails**: Use `npm run build` instead of `npm run dev`
144-
3. **Backend won't start**: Check `.env` file exists and `APP_LOG_DIR` path is valid
145-
4. **Frontend not loading**: Ensure `npm run build` completed successfully
146-
5. **Tests failing**: Ensure all dependencies installed and environment configured
147-
148-
### Performance Expectations
149-
- **Python venv creation**: ~1 second
150-
- **Python dependencies**: ~2-3 minutes
151-
- **Frontend dependencies**: ~15 seconds
152-
- **Frontend build**: ~5 seconds
153-
- **Backend tests**: ~5 seconds
154-
- **Frontend tests**: ~6 seconds
155-
- **E2E tests**: ~70 seconds (may fail without proper auth config)
156-
- **Python linting**: ~1 second
157-
- **Frontend linting**: ~1 second
158-
159-
### Container Development
160-
The project supports containerized development:
161-
```bash
162-
# Build test container (may take 5-10 minutes first time)
163-
docker build -f Dockerfile-test -t atlas-ui-3-test .
164-
165-
# Run tests in container - NEVER CANCEL, set timeout 300+ seconds
166-
docker run --rm atlas-ui-3-test bash /app/test/run_tests.sh all
167-
```
168-
169-
**Note**: Docker builds may fail in some environments due to SSL certificate issues with package repositories. If Docker builds fail, use the local development approach instead.
170-
171-
## Validation Workflow
60+
## Repo conventions (important)
61+
- Use uv; do not use npm run dev; do not use uvicorn --reload.
62+
- File naming: avoid generic names (utils.py, helpers.py). Prefer descriptive names; backend/main.py is the entry-point exception.
63+
- No emojis in code or docs. Prefer files ≤ ~400 lines when practical.
64+
- Auth assumption: in prod, reverse proxy injects X-Authenticated-User; dev falls back to test user.
17265

173-
Before committing changes:
174-
1. **Build**: Ensure both frontend and backend build successfully
175-
2. **Test**: Run test suite - `./test/run_tests.sh all`
176-
3. **Lint**: Run both Python and frontend linting
177-
4. **Manual**: Test key application scenarios in browser
178-
5. **Exercise**: Test specific functionality you modified
66+
## Extend by example
67+
- Add a tool server: edit config/overrides/mcp.json (set groups, transport, url/command, compliance_level). Restart or call discovery on startup.
68+
- Add a RAG provider: edit config/overrides/mcp-rag.json; ensure it exposes rag_* tools; UI consumes /api/config.rag_servers.
69+
- Change agent loop: set AGENT_LOOP_STRATEGY to react | think-act | act; ChatService uses app_settings.agent_loop_strategy.
17970

180-
**ALWAYS** set appropriate timeouts for long-running operations and NEVER cancel builds or tests prematurely.
71+
Common pitfalls: “uv not found” → install uv; frontend not loading → npm run build; missing tools → check MCP transport/URL and server logs; empty lists → check auth groups and compliance filtering.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ A modern LLM chat interface with MCP (Model Context Protocol) integration.
88

99
This App is still under development. Not all features work well.
1010

11+
## Read this first (for contributors)
12+
13+
For the most current, concise guidance on how to work in this repository, read:
14+
- CLAUDE.md — architecture, workflows, and conventions verified against code
15+
- .github/copilot-instructions.md — a compact “AI agent guide” for getting productive fast
16+
17+
These two docs are kept up-to-date more frequently than long-form docs. Start there before exploring the wider docs or codebase.
18+
1119
## Features
1220

1321
- **Multi-LLM Support**: OpenAI GPT, Anthropic Claude, Google Gemini

backend/application/chat/agent/react_loop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from modules.prompts.prompt_provider import PromptProvider
1010

1111
from .protocols import AgentContext, AgentEvent, AgentEventHandler, AgentLoopProtocol, AgentResult
12-
from ..utilities import file_utils, notification_utils, error_utils, tool_utils
12+
from ..utilities import file_utils, error_utils, tool_utils
1313
from domain.messages.models import ToolResult
1414

1515

backend/application/chat/agent/think_act_loop.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import asyncio
43
from typing import Any, Dict, List, Optional
54

65
from interfaces.llm import LLMProtocol, LLMResponse

backend/application/chat/service.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
from typing import Any, Dict, List, Optional, Callable, Awaitable
77
from uuid import UUID
88

9-
from domain.errors import SessionError, ValidationError
109
from domain.messages.models import (
11-
ConversationHistory,
1210
Message,
1311
MessageRole,
1412
MessageType,
15-
ToolCall,
1613
ToolResult
1714
)
1815
from domain.sessions.models import Session
@@ -28,8 +25,8 @@
2825
from .utilities import tool_utils, file_utils, notification_utils, error_utils
2926
from .agent import AgentLoopFactory
3027
from .agent.protocols import AgentContext, AgentEvent
31-
from core.prompt_risk import calculate_prompt_injection_risk, log_high_risk_event
3228
from core.auth_utils import create_authorization_manager
29+
from core.utils import sanitize_for_logging
3330

3431
# Import new refactored modules
3532
from .policies.tool_authorization import ToolAuthorizationService
@@ -196,7 +193,7 @@ async def create_session(
196193
self.sessions[session_id] = session
197194
await self.session_repository.create(session)
198195

199-
logger.info(f"Created session {session_id} for user {user_email}")
196+
logger.info(f"Created session {sanitize_for_logging(str(session_id))} for user {sanitize_for_logging(user_email)}")
200197
return session
201198

202199
async def handle_chat_message(
@@ -278,7 +275,7 @@ async def handle_reset_session(
278275
# Create a new session
279276
await self.create_session(session_id, user_email)
280277

281-
logger.info(f"Reset session {session_id} for user {user_email}")
278+
logger.info(f"Reset session {sanitize_for_logging(str(session_id))} for user {sanitize_for_logging(user_email)}")
282279

283280
return {
284281
"type": "session_reset",
@@ -450,4 +447,4 @@ def end_session(self, session_id: UUID) -> None:
450447
"""End a session."""
451448
if session_id in self.sessions:
452449
self.sessions[session_id].active = False
453-
logger.info(f"Ended session {session_id}")
450+
logger.info(f"Ended session {sanitize_for_logging(str(session_id))}")

backend/application/chat/utilities/file_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ async def ingest_v2_artifacts(
319319
mime_type = artifact.get("mime")
320320

321321
if not name or not b64_content:
322-
logger.warning(f"Skipping artifact with missing name or content")
322+
logger.warning("Skipping artifact with missing name or content")
323323
continue
324324

325325
files_to_upload.append({

backend/application/chat/utilities/tool_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import logging
1010
from typing import Any, Dict, List, Optional, Callable, Awaitable
1111

12-
from domain.messages.models import ToolCall, ToolResult, Message, MessageRole
12+
from domain.messages.models import ToolCall, ToolResult
1313
from interfaces.llm import LLMResponse
1414
from core.capabilities import create_download_url
1515
from .notification_utils import _sanitize_filename_value # reuse same filename sanitizer for UI args

0 commit comments

Comments
 (0)