A general-purpose agent that thinks, remembers, and works with you
Writing · coding · reasoning · creative work — starting from one sentence
Getting started · Architecture · Roadmap · Changelog
- About
- Three deliverables
- Screenshots
- Capabilities
- Architecture
- Quick start
- Commands and configuration
- Roadmap
- Repository layout
- Contributing
Dream AI is an open-source general-purpose agent built from scratch. It reasons, remembers, calls tools, and plans multi-step goals — growing, phase by phase, into an assistant that can actually do the work for you.
The project rests on one belief: intelligence should belong to everyone. The code is MIT-licensed, the model backend is replaceable — any OpenAI-compatible endpoint or a local open-source model — and nothing in the core is tied to a vendor.
Status: early development (WIP). Capabilities ship phase by phase; anything described below as planned is not implemented yet. Current progress and acceptance criteria live in the roadmap.
Three deliverables share one design language and one set of DREAMAI_* conventions:
| Form | Entry point | Version | Best for |
|---|---|---|---|
| Command-line package | python -m dream_ai · dream_ai/ |
0.4.0 |
Local scripts, automation, extending the core |
| Web service | https://liguijiang.com · web/ |
2.0.0 |
Open and use, nothing to install; full cosmic motion system + animated docs at /docs.html |
| Windows desktop app | Download · desktop/ |
1.4.0 |
Local file workbench, document generation, coding mode, full-access consent mode, in-app update |
The three version numbers are independent by design, not by drift: see the version cross-reference and ADR 0001.
| Mode | Behaviour | Best for |
|---|---|---|
| Chat | One question, one answer | Writing, Q&A, translation, code snippets |
| Work | Drafts a 3–6 step plan, executes it, then summarises | Research, planning, multi-step tasks |
| Code (desktop) | Scaffolds a project, writes files, installs dependencies, starts the server; every command asks for approval | Building a small project from zero |
| Home | Chat |
|---|---|
![]() |
![]() |
| Work mode | Desktop |
|---|---|
![]() |
![]() |
图片由 GitHub 内置附件托管,避免仓库内图片域名不可达造成空白;若仍在加载,可直接访问 liguijiang.com。
The web surface is now a living cosmic interface: a starfield that follows the
pointer, a warp intro, a greeting that types and deletes itself, a terminal
prompt ticker, orbital cards with 3D spotlight, magnetic buttons, click sparks,
page transitions, scroll reveals and reading progress. Every effect can be
switched off in one click or via prefers-reduced-motion.
| Motion documentation | Motion download page |
|---|---|
![]() |
![]() |
The CLI has its own quieter motion layer: a launch wordmark, typed replies, a
live thinking spinner and /motion to turn it off mid-session.
| Capability | What it does | Phase |
|---|---|---|
| Replaceable backend | Any OpenAI-compatible endpoint (OpenAI, DeepSeek, Zhipu, Ollama, LM Studio); the core never assumes a vendor | v0.1 |
| Multiple key vaults | Web settings keep a separate key per provider for DeepSeek, OpenAI, 智谱 GLM, Moonshot/Kimi, 通义千问 and OpenRouter; keys stay in the browser | web 2.0 |
| Agent trace | Coding mode shows an expandable timeline of plans, files written, commands, exit codes, outputs and repair loops | desktop 1.3 |
| Full computer access | Desktop 1.4 “电脑” mode: explicit session consent plus a native confirmation for every command, with an expandable trace | desktop 1.4 |
| Session memory | History persisted as JSON and restored on restart; offline placeholder replies are filtered out | v0.2 |
| Long-term preferences | /remember writes into the system message, so it survives restarts |
v0.2 |
| Tool layer | Registry with JSON Schema, risk level, and a confirmation gate; calculator, clock, sandboxed file access, web search | v0.3 |
| Autonomous planning | think → act → observe → reflect loop with a step budget, retries, approval before protected actions, and a full trace | v0.4 |
| Streaming | SSE token streaming on the web, with collapsible reasoning output | web |
| Document generation | Export docx / xlsx / pptx / pdf from the desktop app | desktop |
| Living interface | Shared web motion engine with a persistent on/off switch, reduced-motion support and a dedicated animated docs page | web 2.0 |
| Terminal motion | Launch sequence, typed replies, live spinner, coloured trace, /motion, and plain-text fallback for redirected output |
v0.4 |
| Safe by default | Tools and autonomous actions require explicit approval; file tools stay inside a sandbox directory | v0.3 |
flowchart TB
subgraph entry["Entry points"]
CLI["CLI · dream_ai"]
WEB["Web · FastAPI + SSE"]
DESK["Desktop · Electron"]
end
subgraph core["Core"]
AGENT["DreamAIAgent<br/>reasoning loop"]
CONV["Conversation"]
AUTO["AutonomyEngine<br/>plan · act · trace"]
end
subgraph ports["Ports"]
PROV["LLMProvider"]
MEM["Memory"]
TOOL["ToolRegistry"]
end
subgraph impl["Implementations"]
P1["openai_compat"]
P2["local_echo"]
M1["InMemory"]
M2["Persistent JSON"]
T1["calculator / clock"]
T2["file_read / file_write"]
T3["web_search"]
end
CLI --> AGENT
WEB -.->|planned: reuse core| AGENT
DESK --> WEB
AGENT --> CONV
AGENT --> AUTO
AGENT --> PROV
CONV --> MEM
AGENT --> TOOL
AUTO --> TOOL
PROV -.-> P1
PROV -.-> P2
MEM -.-> M1
MEM -.-> M2
TOOL -.-> T1
TOOL -.-> T2
TOOL -.-> T3
The core depends on three narrow interfaces (LLMProvider, Memory, Tool), so swapping a model, a storage backend, or a tool never requires touching the agent. The web runtime currently has its own FastAPI streaming path (the dashed edge is planned work, not a shipped claim); the desktop app loads the web interface. Layer-by-layer detail and both data flows: architecture.
Dream AI is built and owned by one person, and that fact lives in code rather
than in a prompt somebody edited once: dream_ai/identity.py holds the owner
record, the answer style, and the privacy rules, and every surface reads the
prompt it renders.
| Behaviour | Where |
|---|---|
| Who owns / created / founded it | render_identity_block(), composed into DEFAULT_SYSTEM_PROMPT |
| Answer style (density, terminology, three copy voices) | render_style_block() |
| Dossier: school, duties, interests, situation | render_profile_block() |
| Contact masking on public surfaces | mask_contacts() + DreamAIAgent.public_surface |
Three commands are handled locally, before any model call:
【查看我的全部档案】 show the dossier and everything appended so far
【更新档案】<text> append a fact (kept in preferences.json, capped at 200)
【清空档案】 clear appended facts; the built-in identity stays
Typing 记住:<text> captures a fact mid-conversation, and the CLI mirrors the
dossier command as /profile. Contact details are deliberately absent from the
system prompt: they are rendered only by the dossier command, and model output on
a public surface passes through mask_contacts() before it is shown. See
ADR 0003.
Two things decide how a reply reads: what the prompt asks for, and how the text reaches the screen. Both are now explicit.
| Layer | What it does | Where |
|---|---|---|
| Reasoning | Fixed shape 理解 / 拆解 / 关键判断 / 自查, written to be read | render_reasoning_block() |
| Structure | Conclusion first, summary then expansion, no closing summary | render_structure_block() |
| Voice | Colleague tone, alternating sentence length, specifics over 若干 | render_tone_block() |
| Banned phrases | Sixteen strings that make text read as machine output | BANNED_PHRASES |
| Post-filter | Strips a trailing filler sentence if the model adds one anyway | strip_filler() |
| Streaming | 24-character delta coalescing, append-only text nodes | web/app/llm.py, app.js |
| Thinking panel | Live reasoning, then a collapsed 已思考(用时 X 秒) line |
app.js, app.css |
| Emoji | At most three, never inside code or a table; enforced after generation | EMOJI_POLICY, limit_emoji() |
| Turn planning | Question is rated light/standard/deep, then temperature and budget follow | classify_tier(), plan_generation() |
| History | Newest six turns kept, older ones folded into a digest for pronouns | compress_history() |
| Resilience | One retry for 408/425/429/5xx, never after the first token | stream_with_retry() |
| Answer shape | Six intents, each with its own outline appended for that turn | classify_intent() |
| Input hygiene | A huge paste is cut to head + error lines + tail | trim_long_input() |
| Repeats | A rephrased question is asked for a different angle, not the same answer | is_repeat() |
| Sampling | DREAMAI_TOP_P / DREAMAI_PRESENCE_PENALTY, unset by default |
web/app/config.py |
| Breaker | Opens after N failures, one probe after cooldown, refuses before the first byte | guard.py |
| Cache | Exact-match, TTL + LRU, only at temperature ≤ 0.3 | cache.py |
| Keep-alive | : ping every 12 s while the upstream is silent |
main.py |
| Tracing | req_xxxxxxxx in header and body, one TTFT line per turn |
telemetry.py |
| Injection | Override attempts harden the prompt and land in the log | safety.py |
| Routing | DREAMAI_MODEL_BY_TIER=light=...,deep=..., default on a miss |
routing.py |
| Cost | Per-turn USD from a dated price table; unknown models stay unknown | pricing.py |
| Failover | Second upstream, used only before the first token | DREAMAI_FALLBACK_* |
| Errors | One retry policy and one user-facing wording per status | errors.py |
| Error wording | Key, quota, address and length problems get their own sentence; JSON never reaches the bubble | final_message() |
| Local budget | The CLI and the desktop shell size a reply to the question too, via the same tiers | dream_ai/quality.py |
| Usage | Requests, per-model tokens and cost, average TTFT, local and blocked traffic | stats.py, /api/usage |
| Intent mix | Turn counts per question type, so the site's use is visible, not guessed | byIntent in /api/usage |
| Rate limit contract | X-RateLimit-Remaining on every reply, so a client slows down before being refused |
RateLimiter.hit() |
| Cache off switch | DREAMAI_CACHE_TTL=0 disables the cache without deleting code |
cache.py |
| Local folding | Long CLI sessions fold old turns into a digest instead of losing the subject | compress_history() |
| Session spend | /stats in the CLI: model turns, provider, last tier |
agent.turn_count |
| Local ledger | Turns, tokens and cost for a CLI session, with its unknowns named | dream_ai/usage.py, last_usage |
| Cached tokens | Prompt-cache hits reported per model, never added to the prompt twice | cachedTokens in /api/usage |
| Cache pricing | Cached input billed at its own per-model rate, not one global multiplier | CACHE_PRICES |
| Cache marker | Anthropic's system prompt is sent as an ephemeral cache block | DREAMAI_PROMPT_CACHE |
| Finish reason | All three streams report why the model stopped, in four shared words | finish_from_chunk() |
| Truncation | done.truncated, the finish mix and the truncation rate by tier |
/api/usage, truncatedByTier |
| Cache hygiene | A cut-off answer is never cached; cached bytes are reported | cache.py, adapters.py |
| Retry policy | Timeouts and dropped connections get a status and one retry before the first token | llm.py, errors.py |
| Slow upstreams | A configurable per-request read timeout, without rebuilding the pool | DREAMAI_UPSTREAM_READ_TIMEOUT |
| Breaker probes | Half-open is a real state, and a probe with no answer expires | guard.py |
| Durable counters | Optional aggregate-only snapshot; a restart no longer resets the totals | DREAMAI_USAGE_STATE, state_store.py |
| Config checks | Named, secret-free startup findings on /api/health |
validation.py, configChecks |
| Error contract | SSE errors carry code, status and retryable alongside the sentence |
errors.py, docs/API.md |
| Failure propagation | A failed upstream yields an error frame and counts toward the breaker | main.py, tests/test_error_events_route.py |
| Private cache isolation | Owner answers never enter the shared cache | main.py, owner_auth.py |
| Real usage | Token counts from all three wire formats, one usage event per stream | usage_from_chunk(), DREAMAI_STREAM_USAGE |
| Price corrections | DREAMAI_PRICE_OVERRIDES fixes a stale price without a release |
pricing.configure_prices() |
| Provider view | /api/usage groups turns per vendor, not just per model |
byProvider |
| Stream repair | An unclosed code fence gets one final closing delta | unclosed_fence() |
| Guarded turns | Injection attempts are graded and never cached | classify_injection() |
The same rules exist twice: dream_ai/identity.py for the CLI and the desktop
shell, and web/app/config.py for the service, which can run without the Python
package. A test walks BANNED_PHRASES and fails if either copy loses one.
git clone https://github.com/Li-Guijiang/DreamAI.git && cd DreamAI
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e . && python -m dream_aiNo API key needed to start: Dream AI falls back to offline demo mode, where replies come from a placeholder provider — enough to explore the commands and the loop. To connect a real model, copy the sample configuration and fill in your key:
cp .env.example .env # Windows: copy .env.example .env
# edit .env: DREAMAI_API_KEY / DREAMAI_BASE_URL / DREAMAI_MODELStep-by-step installation: SETUP.md. A guided walkthrough: GUIDE.md.
docker pull ghcr.io/li-guijiang/dream-ai:latest
docker run -it --rm -e DREAMAI_API_KEY=your-key ghcr.io/li-guijiang/dream-ai:latestlatest follows main; release tags carry the version. Tags, triggers, and how to
confirm an image matches a commit: docs/CONTAINER.md.
cd web && pip install -r requirements.txt && uvicorn app.main:app --port 8000 # Web
cd desktop && pnpm install && pnpm start # DesktopFive providers are wired in, each with its own key field. Visitors paste a key in settings; it stays in their browser and is forwarded per request.
| Provider | Wire format | Default models |
|---|---|---|
| DeepSeek | OpenAI-compatible | deepseek-chat, deepseek-reasoner |
| OpenAI | OpenAI-compatible | gpt-4o-mini, gpt-4o |
| Anthropic | /v1/messages |
claude-3-5-sonnet-latest, claude-3-5-haiku-latest |
| Google Gemini | :streamGenerateContent |
gemini-2.0-flash, gemini-1.5-pro |
| 智谱 GLM | OpenAI-compatible | glm-4-flash, glm-4-plus |
Adding a vendor is a data change in web/app/providers.py; the request shaping and
SSE parsing live in web/app/adapters.py and are covered by tests that need no
key or network.
Custom model ids. The model field accepts any string, so a gateway that exposes names this table does not list still works: pick the provider, type the exact id, paste the key.
In-chat commands (click to expand)
| Command | Action |
|---|---|
/help |
List every command |
/run <objective> |
Run a multi-step autonomous task and print the plan and result |
/trace |
Show the plan, step statuses, and full trace of the last task |
/tools |
List registered tools with risk level and required arguments |
/tool <name> <json> |
Call a tool directly, e.g. /tool calculator {"expression": "2 * (3 + 4)"} |
/remember <text> |
Store a long-term preference |
/memory |
Show remembered preferences |
/forget |
Clear all remembered preferences |
/clear |
Clear the current conversation |
/motion |
Toggle the terminal launch / typing / spinner effects for this session |
/about |
Show backend, tool count, autonomy status, and preference count |
Environment variables (click to expand; full list in .env.example)
| Variable | Default | Purpose |
|---|---|---|
DREAMAI_PROVIDER |
openai_compat |
Backend type: openai_compat or local |
DREAMAI_BASE_URL |
https://api.deepseek.com/v1 |
Any OpenAI-compatible endpoint |
DREAMAI_API_KEY |
empty | Empty switches to offline demo mode |
DREAMAI_MODEL |
deepseek-chat |
Model name |
DREAMAI_PERSISTENCE |
true |
Persist conversation and preferences |
DREAMAI_DATA_DIR |
~/.dream_ai |
Data directory |
DREAMAI_TOOLS_ENABLED |
true |
Master switch for the tool registry |
DREAMAI_FILE_ACCESS_ENABLED |
false |
Sandboxed file read/write |
DREAMAI_WEB_SEARCH_ENABLED |
false |
Web search |
DREAMAI_WORKSPACE_DIR |
<data_dir>/workspace |
File sandbox root |
DREAMAI_AUTONOMY_ENABLED |
true |
Master switch for autonomous mode |
DREAMAI_MAX_STEPS |
10 |
Tool-call budget per task |
DREAMAI_MAX_RETRIES |
2 |
Extra retries per failed step |
DREAMAI_AUTONOMY_VERBOSE |
false |
Print every phase event live |
DREAMAI_ANIMATIONS |
auto |
Terminal motion: auto only in a real TTY, false forces plain text |
DREAMAI_ANIMATION_SPEED |
1.0 |
Motion speed multiplier (0.25–4.0) |
| Version | Milestone | Goal | Status |
|---|---|---|---|
v0.1.0 |
Conversation | A working loop through a replaceable backend | Released |
v0.2.0 |
Memory | Sessions and preferences survive restarts | Released |
v0.3.0 |
Tools | A safe tool layer with a confirmation gate | Released |
v0.4.0 |
Autonomy | Multi-step planning with a reviewable trace | Released |
web 2.0.0 |
Living web surface | Full motion system, animated docs page, accessible motion switch | Live |
v1.0.0 |
Stable assistant | A reliable general-purpose personal agent | In progress |
Future |
Self-hosted | Fully local deployment on open-source models | Planned |
Task lists and acceptance criteria per phase: ROADMAP.md.
DreamAI/
├── dream_ai/ # CLI package (PyPI: dream-ai)
│ ├── cli.py # Argument parsing and the chat loop
│ ├── config.py # Environment → Settings
│ ├── agent_factory.py # Builds the agent from settings
│ ├── core/ # Agent and Conversation
│ ├── providers/ # Replaceable model backends
│ ├── memory/ # Sessions, preferences, atomic persistence
│ ├── tools/ # Registry, built-in tools, call parser
│ ├── autonomy/ # Planner, execution engine, trace models
│ └── ui/ # Terminal launch / typing / spinner effects
├── web/ # Web service and static site
│ ├── app/ # FastAPI (config / streaming client / routes)
│ ├── web/ # Browser assets
│ ├── deploy/ # nginx and systemd templates
│ ├── tools/ # Maintenance scripts (see tools/README.md)
│ └── docs/ # Screenshots used by the documentation
├── desktop/ # Electron desktop client
│ ├── electron/ # Main process, preload bridge, local tools
│ ├── test/ # Node tests and E2E helpers
│ └── build/ # Packaging resources (application icon)
├── docs/ # Documentation, entry point: docs/README.md
│ └── adr/ # Architecture Decision Records
├── tests/ # pytest suite
├── examples/ # Runnable examples
├── assets/ # Brand assets (see assets/README.md)
├── .github/workflows/ # CI / Release / PyPI / container
├── Dockerfile # Container image definition
├── .editorconfig # Editor indentation and encoding rules
├── pyproject.toml # Packaging metadata, dependencies, tool config
├── CHANGELOG.md # Versioned change history
└── LICENSE # MIT
Issues, suggestions, and pull requests are welcome. Read the contributing guide and the code of conduct first; for usage questions start with SUPPORT.md, and report vulnerabilities privately as described in SECURITY.md.
Run the same checks as CI before opening a pull request:
pytest
ruff check dream_ai tests examples web/app web/tools
ruff format --check dream_ai tests examples
for file in web/web/assets/js/*.js; do node --check "$file"; done| Document | Contents |
|---|---|
| docs/README.md | Index of every document and the version cross-reference |
| docs/GUIDE.md | Guided walkthrough: setup, every command, common errors |
| docs/ARCHITECTURE.md | Layers, module responsibilities, data flow |
| docs/ROADMAP.md | Phase tasks and acceptance criteria |
| docs/CONTAINER.md | Container image, tag scheme, build triggers |
| docs/SUPPORT.md | Self-check order and where to ask for help |
| web/README.md | Web features, API, deployment |
| desktop/README.md | Desktop development, packaging, security model |
MIT License · Copyright (c) 2026 Li Guijiang · Designed, built and maintained by Li Guijiang
From a shared dream to a world that understands itself — one step at a time.







