Add Phase 7: polish and hardening — retry, truncation, sessions, shutdown
- Config extensions: retry backoff, truncation threshold, session persistence - LLM retry with exponential backoff + jitter on transient errors (5xx, connection) - Conversation truncation: drops oldest messages preserving first user + recent N - Session persistence: auto-save/restore with atomic writes, cleanup of old files - Graceful shutdown: SIGTERM handler, cancel() on AgentLoop, save-on-exit - Partial message recovery on mid-stream interruption - New slash commands: /save, /session - 18 new tests (5 retry, 5 truncation, 4 session, 4 integration workflows) - README.md and docs/tools.md documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
147
README.md
Normal file
147
README.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# SneakyCode
|
||||
|
||||
A privacy-first, locally-running Python coding agent that uses a local LLM (via Ollama) to perform autonomous coding tasks inside a project directory.
|
||||
|
||||
SneakyCode accepts natural language tasks and executes them using a defined toolset for filesystem operations, shell execution, code search, and file manipulation. It runs a ReAct-style tool-call loop: send conversation history to the LLM, receive tool calls, execute them with permission checks, and feed results back until the task is complete.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.11+
|
||||
- [Ollama](https://ollama.ai/) running locally with a model that supports function calling (e.g., `qwen3.5`, `llama3.1`, `mistral-nemo`)
|
||||
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone <repo-url>
|
||||
cd SneakyCode
|
||||
|
||||
# Install dependencies
|
||||
uv sync --dev
|
||||
|
||||
# Or with pip
|
||||
pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `config/config.yaml` to configure the agent. Key settings:
|
||||
|
||||
```yaml
|
||||
llm:
|
||||
model: "qwen3.5:latest" # Ollama model name
|
||||
endpoint: "http://localhost:11434" # Ollama endpoint
|
||||
max_retries: 3 # Retry attempts on transient errors
|
||||
retry_backoff_base: 1.0 # Exponential backoff base (seconds)
|
||||
|
||||
agent:
|
||||
max_iterations: 25 # Max tool-call iterations per turn
|
||||
max_conversation_tokens: 32000 # Token budget for conversation
|
||||
workspace_root: "." # Project directory for file operations
|
||||
truncation_keep_recent: 10 # Messages preserved during truncation
|
||||
truncation_threshold: 0.85 # Budget fraction that triggers truncation
|
||||
|
||||
session:
|
||||
auto_save: true # Save session after each turn
|
||||
max_session_age_hours: 72 # Auto-cleanup old sessions
|
||||
offer_resume: true # Offer to resume on startup
|
||||
|
||||
permissions:
|
||||
auto_approve: [read_file, list_dir, grep_files, find_files, finish]
|
||||
prompt_user: [write_file, delete_file, run_command, str_replace, patch_apply, make_dir]
|
||||
deny: []
|
||||
```
|
||||
|
||||
Environment variable `SNEAKYCODE_CONFIG` can override the config file path.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Start the interactive REPL
|
||||
sneakycode
|
||||
|
||||
# Or run directly
|
||||
python -m app.main
|
||||
|
||||
# With options
|
||||
sneakycode --config path/to/config.yaml --verbose --log-file sneakycode.log
|
||||
```
|
||||
|
||||
### REPL Commands
|
||||
|
||||
| Command | Description |
|
||||
|------------|--------------------------------------|
|
||||
| `/quit` | Save session and exit |
|
||||
| `/history` | Show conversation history |
|
||||
| `/clear` | Clear conversation history |
|
||||
| `/save` | Manually save session |
|
||||
| `/session` | Show session info (messages, tokens) |
|
||||
|
||||
### Session Persistence
|
||||
|
||||
Sessions are automatically saved after each agent turn and on exit. On startup, SneakyCode offers to resume the most recent session for the current workspace.
|
||||
|
||||
Session files are stored in `.sneakycode/sessions/` within the workspace root.
|
||||
|
||||
## Available Tools
|
||||
|
||||
SneakyCode provides 11 tools across 5 categories. See [docs/tools.md](docs/tools.md) for the full reference.
|
||||
|
||||
| Category | Tools | Permission |
|
||||
|------------|-------------------------------------------------|---------------|
|
||||
| Read | `read_file`, `list_dir` | Auto-approved |
|
||||
| Search | `grep_files`, `find_files` | Auto-approved |
|
||||
| Write | `write_file`, `make_dir`, `delete_file` | User confirm |
|
||||
| Edit | `str_replace`, `patch_apply` | User confirm |
|
||||
| Shell | `run_command` | User confirm |
|
||||
| Control | `finish` | Auto-approved |
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
.venv/bin/python -m pytest tests/ -v
|
||||
|
||||
# Run with coverage
|
||||
.venv/bin/python -m pytest tests/ --cov=app
|
||||
|
||||
# Lint
|
||||
.venv/bin/ruff check app/ tests/
|
||||
|
||||
# Format
|
||||
.venv/bin/ruff format app/ tests/
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
app/
|
||||
├── agent/ # Agent loop and session context
|
||||
├── models/ # Pydantic config and message schemas
|
||||
├── services/ # LLM client, streaming, permissions, session persistence
|
||||
├── tools/ # Tool implementations (one file per group)
|
||||
└── utils/ # Logging, display, file helpers, token counter
|
||||
config/
|
||||
└── config.yaml # Application configuration
|
||||
tests/
|
||||
├── unit/ # Unit tests for individual components
|
||||
└── integration/ # End-to-end workflow tests with mocked LLM
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
SneakyCode follows a **ReAct-style** agent pattern:
|
||||
|
||||
1. User provides a task in natural language
|
||||
2. Agent sends conversation history + tool schemas to the LLM
|
||||
3. LLM responds with either text (task complete) or tool calls
|
||||
4. Agent executes tool calls with permission checks
|
||||
5. Results are fed back to the LLM for the next iteration
|
||||
6. Loop continues until the LLM produces a plain-text response or calls `finish`
|
||||
|
||||
The LLM client is abstracted behind an OpenAI-compatible interface, so any endpoint implementing the `/v1/chat/completions` SSE streaming protocol works as a backend.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user