Files

126 lines
5.9 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
# Install dependencies
uv sync
# Install with PDF/HTML export support
uv sync --extra export
# Run the server (opens on http://localhost:8080)
uv run deepresearch
# Start Excalidraw canvas (separate terminal)
docker compose up -d excalidraw-canvas
# Run without Excalidraw
EXCALIDRAW_ENABLED=0 uv run deepresearch
```
No tests, linters, or formatters are configured in this project.
## Environment
Copy `.env.example` to `.env` and configure:
- `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` — LLM provider
- At least one search API key: `TAVILY_API_KEY`, `BRAVE_API_KEY`, or `JINA_API_KEY`
- Default model is `openai-responses:o4-mini` (override via `MODEL_NAME`)
- When `LLM_BASE_URL` is set, uses a local OpenAI-compatible endpoint instead
## Architecture
**Stack:** Python 3.12+ / FastAPI / WebSocket / pydantic-ai + pydantic-deep
### Source Layout
```
src/deepresearch/
app.py # FastAPI server, WebSocket /ws/chat, REST endpoints
agent.py # Agent factory — assembles the research agent with all toolsets
config.py # MCP server creation, model config, path constants
prompts.py # System prompt for the research agent (~300 lines of instructions)
middleware.py # Three capabilities: AuditCapability, PermissionCapability, RateLimitRetryCapability
todo_toolset.py # ForgiveWriteTodosCapability — handles malformed tool calls from local LLMs
types.py # Pydantic models: Source, Finding, ReportSection, ResearchReport
static/
index.html # Single-page frontend
app.js # WebSocket client, tool rendering, file preview, Excalidraw iframe
styles.css # Dark theme UI
skills/
research-methodology/SKILL.md # Loaded agent skill: source evaluation, search strategy
report-writing/SKILL.md # Loaded agent skill: report structure, citation format
diagram-design/SKILL.md # Loaded agent skill: Excalidraw diagram best practices
workspace/
DEEP.md # Context file injected into every session (file organization conventions)
MEMORY.md # Persistent agent memory (written via `remember()` tool)
workspaces/ # Per-session data: history.json, meta.json, events.jsonl, canvas.json
```
### Runtime Flow
1. **Lifespan startup** (`app.py:lifespan`): Creates MCP servers (Tavily, Brave, Jina, Excalidraw, Playwright, Firecrawl per API keys in env) and the research agent. Retry loop drops failing MCP servers and restarts.
2. **WebSocket session** (`/ws/chat`): Each browser tab connects with a session UUID. A per-user Docker sandbox container is created (python-datascience runtime). Message history persists to `workspaces/<uuid>/history.json`.
3. **Agent execution** (`run_agent_with_streaming`): Uses `agent.iter()` for streaming — processes nodes (ModelRequest → stream text deltas, CallTools → stream tool calls/results) and sends WebSocket JSON events to the frontend.
4. **Approval flow**: Tools like `execute` trigger `DeferredToolRequests` — the frontend shows an approval dialog, and the agent resumes with `DeferredToolResults`.
5. **Checkpointing**: Auto-saves after every turn to `InMemoryCheckpointStore`. Supports `rewind` and `fork` via REST endpoints.
### Agent Architecture
The agent (`create_research_agent` in `agent.py`) uses **pydantic-deep**'s `create_deep_agent` with:
- **Toolsets**: MCP servers (search/browser/diagrams) + filesystem + execute + subagents + teams + TODO + skills + checkpoints + agent-factory + remember
- **Subagents**: `general-purpose` (research executor), `planner` (plan mode), `code-reviewer`, plus dynamic agents via factory
- **Hooks**: `audit_logger` (POST_TOOL_USE, background) + `safety_gate` (PRE_TOOL_USE on `execute`, blocks rm -rf /, mkfs, dd, etc.)
- **Middleware stack**: `ForgiveWriteTodosCapability``AuditCapability``PermissionCapability` → optionally `RateLimitRetryCapability`
- **Context management**: Sliding window (50 msg trigger, keep 30), token eviction (20k limit), context files from `/workspace/DEEP.md` and `/workspace/MEMORY.md`
### MCP Servers (config.py)
All optional, enabled by API key presence:
- **Tavily** — AI search (`npx tavily-mcp`)
- **Brave Search** — web search (`npx @anthropic-ai/brave-search-mcp`)
- **Jina** — URL→markdown reader (HTTP MCP at `https://mcp.jina.ai/v1`)
- **Excalidraw** — live diagrams (Podman container, requires `podman` binary)
- **Playwright** — browser automation (requires `PLAYWRIGHT_MCP=1`)
- **Firecrawl** — web scraping/crawling (`npx firecrawl-mcp`)
### Research Workflow (prompts.py)
The system prompt encodes a detailed 7-step research workflow:
1. **Plan** — dispatch planner subagent for complex topics
2. **Todo** — create progress tracking with `write_todos`
3. **Parallel subagents** — dispatch all research tasks async
4. **Wait**`wait_tasks` for results
5. **Handle failures** — never stop, use own knowledge as fallback
6. **Write iteratively** — chapter by chapter via `edit_file`
7. **Present** — summarize and offer deeper analysis
### REST Endpoints
| Endpoint | Purpose |
|---|---|
| `GET /` | Serves `static/index.html` |
| `GET /health` | Health check with agent/session status |
| `GET /config` | Full feature configuration |
| `POST /upload` | File upload to sandbox |
| `GET /files?session_id=` | List files in sandbox |
| `GET /files/content/...` | Read file content |
| `GET /files/binary/...` | Read binary files (images) |
| `GET /todos?session_id=` | Get current TODOs |
| `GET /checkpoints?session_id=` | List checkpoints |
| `POST /checkpoints/:id/rewind` | Rewind to checkpoint |
| `POST /checkpoints/:id/fork` | Fork new session from checkpoint |
| `GET /history?session_id=` | Get conversation history |
| `GET /sessions` | List all sessions |
| `DELETE /sessions/:id` | Delete session |
| `GET /export/:fmt` | Export report (md/html/pdf) |
| `GET /preview/:session_id/...` | Serve raw files from container |