a3acdbe70b
Sweep brand mentions of `DeepSeek TUI` / `deepseek-tui` / bare `deepseek` (the dispatcher binary) across all user-facing docs to the new `codewhale` brand. The DeepSeek **provider** integration is left untouched throughout: env vars (`DEEPSEEK_*`), model IDs (`deepseek-v4-pro`, `deepseek-v4-flash`, `deepseek-chat`, `deepseek-reasoner`), the `api.deepseek.com` host, the `~/.deepseek/` config dir, and the `--provider deepseek` argument value all keep the legacy spelling. Anti-scope items deliberately left as the legacy `deepseek-tui`: - Homebrew tap and formula (`Hmbown/homebrew-deepseek-tui`, `brew install deepseek-tui`, `scoop install deepseek-tui`). The tap rename ships separately. - Docker image (`ghcr.io/hmbown/deepseek-tui`). Image-tag rename ships separately. - CNB mirror namespace (`cnb.cool/deepseek-tui.com/DeepSeek-TUI`). Third-party hosted path. - Security contact email (`security@deepseek-tui.com`). - GitHub repo URL (`Hmbown/DeepSeek-TUI`). New artifact: - `docs/REBRAND.md` documents what changed, what didn't, the deprecation window, and migration commands for npm / Cargo / Homebrew / manual installs. CHANGELOG entries: - Root `CHANGELOG.md` and `crates/tui/CHANGELOG.md` both gain a new `[Unreleased]` section describing the rename and the one- release deprecation window. Historical entries are untouched. Issue templates: - `.github/ISSUE_TEMPLATE/bug_report.md` and `feature_request.md` refer to "codewhale" / `codewhale --version` instead of the old brand name in their environment fields. The rebrand sweep was driven by a perl script with bulk patterns (`deepseek-tui` -> `codewhale-tui`, `DeepSeek TUI` -> `codewhale`, bare `deepseek` -> `codewhale` with provider/model/host/env-var/ config-path negative lookbehind/lookahead) followed by targeted reverts for the anti-scope items above. Output was visually reviewed file-by-file before committing. Verified: - `cargo check --workspace --all-targets --locked` — pass. - `cargo test --workspace --all-features --locked` — pass (no test source touched here; suite stayed green to confirm no doc-from-string assertions broke). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
306 lines
18 KiB
Markdown
306 lines
18 KiB
Markdown
# codewhale Architecture
|
|
|
|
This document provides an overview of the codewhale architecture for developers and contributors.
|
|
|
|
Current boundary note (v0.8.6):
|
|
- `crates/tui` is still the live end-user runtime for the TUI, runtime API, task manager, and tool execution loop.
|
|
- Other workspace crates are being split out incrementally, but they are not yet the sole runtime source of truth.
|
|
- The LSP subsystem (`crates/tui/src/lsp/`) is fully wired into the engine's post-tool-execution path
|
|
(`core/engine/lsp_hooks.rs`), providing inline diagnostics after every edit_file/apply_patch/write_file.
|
|
- The swarm agent system was removed in v0.8.5. The active v0.8.35 orchestration surface is persistent sub-agent sessions (`agent_open` / `agent_eval` / `agent_close`) and persistent RLM sessions (`rlm_open` / `rlm_eval` / `rlm_configure` / `rlm_close`).
|
|
No model-visible swarm tool remains in the active codebase.
|
|
|
|
## High-Level Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ User Interface │
|
|
│ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │
|
|
│ │ TUI (ratatui) │ │ One-shot Mode │ │ Config/CLI │ │
|
|
│ └────────┬────────┘ └────────┬────────┘ └────────┬───────┘ │
|
|
└───────────┼─────────────────────┼────────────────────┼──────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Core Engine │
|
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
│ │ Agent Loop (core/engine.rs) │ │
|
|
│ │ ┌─────────┐ ┌─────────────┐ ┌──────────────────────┐ │ │
|
|
│ │ │ Session │ │ Turn Mgmt │ │ Tool Orchestration │ │ │
|
|
│ │ └─────────┘ └─────────────┘ └──────────────────────┘ │ │
|
|
│ └─────────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Tool & Extension Layer │
|
|
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌────────────────┐ │
|
|
│ │ Tools │ │ Skills │ │ Hooks │ │ MCP Servers │ │
|
|
│ │ (shell, │ │ (plugins)│ │ (pre/ │ │ (external) │ │
|
|
│ │ file) │ │ │ │ post) │ │ │ │
|
|
│ └──────────┘ └──────────┘ └─────────┘ └────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Runtime API + Task Management │
|
|
│ ┌─────────────────────────────┐ ┌──────────────────────────┐ │
|
|
│ │ HTTP/SSE Runtime API │ │ Persistent Task Manager │ │
|
|
│ │ (runtime_api.rs) │ │ (task_manager.rs) │ │
|
|
│ └─────────────────────────────┘ └──────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ LLM Layer │
|
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
│ │ LLM Client Abstraction (llm_client.rs) │ │
|
|
│ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
|
|
│ │ │ DeepSeek Client │ │ Compatible Client (DeepSeek)│ │ │
|
|
│ │ │ (client.rs) │ │ (client.rs) │ │ │
|
|
│ │ └─────────────────┘ └─────────────────────────────┘ │ │
|
|
│ └──────────────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Module Organization
|
|
|
|
### Entry Point
|
|
|
|
- **`main.rs`** - CLI argument parsing (clap), configuration loading, entry point routing
|
|
|
|
### Core Components
|
|
|
|
- **`core/`** - Main engine components
|
|
- `engine.rs` - Engine state, operation handling, message processing
|
|
- `engine/turn_loop.rs` - Streaming turn loop and tool execution orchestration
|
|
- `engine/capacity_flow.rs` - Capacity guardrail checkpoints and interventions
|
|
- `session.rs` - Session state management
|
|
- `turn.rs` - Turn-based conversation handling
|
|
- `events.rs` - Event system for UI updates
|
|
- `ops.rs` - Core operations
|
|
|
|
### Configuration
|
|
|
|
- **`config.rs`** - Configuration loading, profiles, environment variables
|
|
- **`settings.rs`** - Runtime settings management
|
|
|
|
### Workspace Crates
|
|
|
|
- **`crates/tools`** - Shared tool invocation primitives, including tool result/error/capability types used by the TUI runtime.
|
|
- **`crates/agent`** - Model/provider registry (ModelRegistry) for resolving model IDs to provider endpoints.
|
|
- **`crates/app-server`** - HTTP/SSE + JSON-RPC app server transport for headless agent workflows.
|
|
- **`crates/config`** - Config loading, profiles, environment variable precedence, CLI runtime overrides.
|
|
- **`crates/core`** - Agent loop, session management, turn orchestration, capacity flow guardrails.
|
|
- **`crates/execpolicy`** - Approval/sandbox policy engine for tool execution decisions.
|
|
- **`crates/hooks`** - Lifecycle hooks (stdout, jsonl, webhook) for pre/post tool events.
|
|
- **`crates/mcp`** - MCP client + stdio server for Model Context Protocol tool servers.
|
|
- **`crates/protocol`** - Request/response framing and protocol types.
|
|
- **`crates/secrets`** - OS keyring integration for API key storage.
|
|
- **`crates/state`** - SQLite thread/session persistence layer.
|
|
- **`crates/tui-core`** - Event-driven TUI state machine scaffold.
|
|
|
|
### LLM Integration
|
|
|
|
- **`client.rs`** - HTTP client for DeepSeek's documented OpenAI-compatible Chat Completions API
|
|
- **`llm_client.rs`** - Abstract LLM client trait with retry logic
|
|
- **`models.rs`** - Data structures for API requests/responses
|
|
|
|
#### DeepSeek API Endpoints
|
|
|
|
DeepSeek exposes OpenAI-compatible endpoints. The CLI uses:
|
|
- `https://api.deepseek.com/beta/chat/completions` - default v0.8.16 DeepSeek model turns
|
|
- `https://api.deepseek.com/beta/models` - default v0.8.16 live model discovery and health checks
|
|
|
|
`https://api.deepseek.com/v1` is accepted for OpenAI SDK compatibility, and
|
|
can still be configured explicitly to opt out of beta-only features such as
|
|
strict tool mode, chat prefix completion, and FIM completion. The public
|
|
DeepSeek docs do not document a Responses API path for this workflow; the engine
|
|
drives turns through Chat Completions.
|
|
|
|
### Tool System
|
|
|
|
- **`tools/`** - Built-in tool implementations
|
|
- `mod.rs` - Tool registry and common types
|
|
- `shell.rs` - Shell command execution
|
|
- `file.rs` - File read/write operations
|
|
- `todo.rs` - Checklist tools plus legacy todo aliases
|
|
- `tasks.rs` - Model-visible durable task, gate, background shell, and PR-attempt tools
|
|
- `github.rs` - Read-only GitHub context and guarded comment/closure tools backed by `gh`
|
|
- `automation.rs` - Model-visible scheduling tools over `AutomationManager`
|
|
- `plan.rs` - Planning tools
|
|
- `subagent.rs` - Persistent sub-agent sessions (replaces the removed `agent_swarm` surface)
|
|
- `spec.rs` - Tool specifications
|
|
- `rlm.rs` - Persistent Recursive Language Model (RLM) sessions — sandboxed Python REPLs with semantic helper calls and `var_handle` output support
|
|
|
|
### Extension Systems
|
|
|
|
- **`mcp.rs`** - Model Context Protocol client for external tool servers
|
|
- **`skills.rs`** - Plugin/skill loading and execution
|
|
- **`hooks.rs`** - Pre/post execution hooks with conditions
|
|
|
|
### User Interface
|
|
|
|
- **`tui/`** - Terminal UI components (ratatui-based)
|
|
- `app.rs` - Application state and message handling
|
|
- `ui.rs` - Event handling, streaming state, and rendering logic
|
|
- `approval.rs` - Tool approval dialog
|
|
- `clipboard.rs` - Clipboard handling
|
|
- `streaming.rs` - Streaming text collector
|
|
|
|
- **`ui.rs`** - Legacy/simple UI utilities
|
|
|
|
### LSP Integration
|
|
|
|
- **`lsp/`** - Post-edit diagnostics injection (#136)
|
|
- `mod.rs` - `LspManager` — lazy per-language transport pool + config
|
|
- `client.rs` - `StdioLspTransport` — JSON-RPC over stdio with `didOpen`/`didChange`/`publishDiagnostics`
|
|
- `diagnostics.rs` - Diagnostic types, severity, and HTML-block renderer
|
|
- `registry.rs` - Language detection and default server map (rust-analyzer, pyright, gopls, clangd, typescript-language-server)
|
|
- Wired into the engine via `core/engine/lsp_hooks.rs` — called after every successful edit
|
|
|
|
### Security
|
|
|
|
- **`sandbox/`** - platform sandbox policy preparation and denial reporting
|
|
- `mod.rs` - Sandbox type definitions
|
|
- `policy.rs` - Sandbox policy configuration
|
|
- `seatbelt.rs` - macOS Seatbelt profile generation
|
|
- `landlock.rs` - Linux Landlock detection and future helper contract
|
|
- `windows.rs` - Windows helper contract; not advertised until a Job
|
|
Object process-containment helper exists
|
|
|
|
### Utilities
|
|
|
|
- **`utils.rs`** - Common utilities
|
|
- **`logging.rs`** - Logging infrastructure
|
|
- **`compaction.rs`** - Context compaction for long conversations
|
|
- **`pricing.rs`** - Cost estimation
|
|
- **`prompts.rs`** - System prompt templates
|
|
- **`project_doc.rs`** - Project documentation handling
|
|
- **`session.rs`** - Session serialization
|
|
- **`runtime_api.rs`** - HTTP/SSE runtime API (`codewhale serve --http`)
|
|
- **`runtime_threads.rs`** - Durable thread/turn/item store + replayable event timeline
|
|
- **`task_manager.rs`** - Durable queue, worker pool, task timelines and artifacts
|
|
|
|
## Data Flow
|
|
|
|
### Interactive Session
|
|
|
|
1. User input received in TUI
|
|
2. Input processed by `core/engine.rs`
|
|
3. Message sent to LLM via `llm_client.rs`
|
|
4. Response streamed back, parsed in `client.rs`
|
|
5. Tool calls extracted and executed via `tools/`
|
|
6. Hooks triggered before/after tool execution
|
|
7. Results aggregated and sent back to LLM
|
|
8. Final response rendered in TUI
|
|
|
|
### Crash Recovery + Offline Queue
|
|
|
|
1. Before sending user input, the TUI writes a checkpoint snapshot to `~/.deepseek/sessions/checkpoints/latest.json`
|
|
2. Startup remains fresh by default; prior sessions are resumed explicitly via `--resume`/`--continue` (or `Ctrl+R` in TUI)
|
|
3. While degraded/offline, new prompts are queued in-memory and mirrored to `~/.deepseek/sessions/checkpoints/offline_queue.json`
|
|
4. Queue edits (`/queue ...`) are persisted continuously so drafts and queued prompts survive restarts
|
|
5. Successful turn completion clears the active checkpoint and writes a durable session snapshot
|
|
6. Agent/Yolo turns also take pre/post-turn side-git workspace snapshots under `~/.deepseek/snapshots/<project_hash>/<worktree_hash>/.git`; `/restore N` and `revert_turn` restore file state without changing conversation history or the user's `.git`
|
|
|
|
### Tool Execution
|
|
|
|
1. LLM requests tool via `tool_use` content block
|
|
2. Tool registry looks up handler
|
|
3. Pre-execution hooks run
|
|
4. Approval requested if needed (non-yolo mode)
|
|
5. Tool executed (possibly sandboxed on macOS)
|
|
6. Post-execution hooks run
|
|
7. Result metadata is retained on runtime item records
|
|
8. **LSP post-edit hook** (v0.8.6): if the tool was `edit_file`/`apply_patch`/`write_file` and LSP is enabled, the engine runs `run_post_edit_lsp_hook()` to collect diagnostics
|
|
9. **Diagnostics flush** (v0.8.6): before the next API request, `flush_pending_lsp_diagnostics()` injects any collected errors as a synthetic user message
|
|
10. Result returned to agent loop
|
|
|
|
### Background Tasks
|
|
|
|
1. Client enqueues task (`/task add ...` or `POST /v1/tasks`)
|
|
2. `task_manager.rs` persists task + queue entry under `~/.deepseek/tasks`
|
|
3. Worker picks queued task (bounded pool), transitions to `running`
|
|
4. Task creates/uses a runtime thread and starts a runtime turn
|
|
5. `runtime_threads.rs` persists thread/turn/item records + monotonic event sequence
|
|
6. Timeline/tool summaries/artifact references are persisted incrementally
|
|
7. Checklist state, verifier gates, PR attempts, and guarded GitHub events are applied from tool metadata to the active task
|
|
8. Final state (`completed|failed|canceled`) is durable and queryable via TUI/API
|
|
|
|
Model-visible durable task tools are a surface over this same manager. They do
|
|
not introduce a parallel work system: `task_create` enqueues normal tasks,
|
|
`checklist_*` updates task-local progress, `task_gate_run` and completed
|
|
`task_shell_wait` attach verification evidence, and automation runs enqueue
|
|
ordinary durable tasks.
|
|
|
|
### Runtime Thread/Turn Timeline
|
|
|
|
1. API/TUI creates or resumes a thread (`/v1/threads*`)
|
|
2. Turn starts on the thread (`/v1/threads/{id}/turns`)
|
|
3. Engine events are mapped to item lifecycle events (`item.started|item.delta|item.completed`)
|
|
4. Interrupt/steer operations apply to the active turn only
|
|
5. Compaction (auto/manual) is emitted as `context_compaction` item lifecycle
|
|
6. Clients replay history and resume with `/v1/threads/{id}/events?since_seq=<n>`
|
|
|
|
### Durable Schema Gates
|
|
|
|
- `session_manager.rs`, `runtime_threads.rs`, and `task_manager.rs` embed `schema_version` on persisted records.
|
|
- On load, newer schema versions are rejected with explicit errors instead of silently truncating/overwriting data.
|
|
- This allows safe forward migrations and prevents corruption when binaries and stored state are out of sync.
|
|
|
|
## Extension Points
|
|
|
|
### Adding a New Tool
|
|
|
|
1. Create handler in `tools/`
|
|
2. Register in `tools/registry.rs`
|
|
3. Add tool specification (name, description, input schema)
|
|
|
|
### Adding an MCP Server
|
|
|
|
1. Configure in `~/.deepseek/mcp.json`
|
|
2. Server auto-discovered at startup
|
|
3. Tools exposed to LLM automatically
|
|
|
|
### Creating a Skill
|
|
|
|
1. Create skill directory with `SKILL.md`
|
|
2. Define skill prompt and optional scripts
|
|
3. Place in `~/.deepseek/skills/`
|
|
|
|
### Adding Hooks
|
|
|
|
Configure in `~/.deepseek/config.toml`:
|
|
|
|
```toml
|
|
[[hooks]]
|
|
event = "tool_call_before"
|
|
command = "echo 'Running tool: $TOOL_NAME'"
|
|
```
|
|
|
|
## Key Design Decisions
|
|
|
|
1. **Streaming-first**: All LLM responses stream for responsiveness
|
|
2. **Tool safety**: Non-YOLO mode requires approval for destructive operations, including side-effectful MCP tools
|
|
3. **Extensibility**: MCP, skills, and hooks allow customization without code changes
|
|
4. **Cross-platform**: Core works on Linux/macOS/Windows. Sandbox guarantees
|
|
are platform-specific: macOS Seatbelt is the active policy path; Linux and
|
|
Windows require helper enforcement before they should be treated as full OS
|
|
sandboxing.
|
|
5. **Minimal dependencies**: Careful dependency selection for build speed
|
|
6. **Local-first runtime API**: HTTP/SSE endpoints are intended for trusted localhost access and are served by the `crates/tui` runtime today
|
|
|
|
## Configuration Files
|
|
|
|
- `~/.deepseek/config.toml` - Main configuration
|
|
- `/etc/deepseek/managed_config.toml` - Optional managed defaults layer (Unix)
|
|
- `/etc/deepseek/requirements.toml` - Optional allowed-policy constraints (Unix)
|
|
- `~/.deepseek/mcp.json` - MCP server configuration
|
|
- `~/.deepseek/skills/` - User skills directory
|
|
- `~/.deepseek/sessions/` - Session history
|
|
- `~/.deepseek/sessions/checkpoints/` - Crash checkpoint + offline queue persistence
|
|
- `~/.deepseek/snapshots/` - Side-git pre/post-turn workspace snapshots for `/restore` and `revert_turn`
|
|
- `~/.deepseek/tasks/` - Background task records, queue, timelines, artifacts
|
|
- `~/.deepseek/audit.log` - Append-only audit events for credential + approval/elevation actions
|