Spaces:
Running
Running
File size: 12,450 Bytes
81aa0b5 fc74cc0 81aa0b5 873734c 81aa0b5 fc74cc0 81aa0b5 873734c 81aa0b5 fc74cc0 873734c 81aa0b5 fc74cc0 873734c b87f702 fc74cc0 873734c b87f702 81aa0b5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | # SoniCoder β Project Memory
> This file is the project's persistent memory. The agent reads it on every session.
> Edit it freely β it overrides defaults.
## What is SoniCoder?
SoniCoder is a local-first AI coding agent that can:
- Generate complete fullstack applications in any language/framework
- Read, write, and edit files in a sandboxed workspace
- Run shell commands (git, npm, pip, tests)
- Apply specialized skills (frontend-design, feature-dev, code-review, debugging, fullstack-scaffold, commit-workflow)
- Respond to slash commands (/commit, /review, /feature, /design, /explain, /test, /refactor, /skill, /help)
- Deploy to HuggingFace Spaces with one click
## Architecture
```
app.py β Entry point: launches Gradio Server
code/
βββ config/constants.py β App config, system prompt, language options
βββ model/
β βββ loader.py β Dual model loading (text + VLM)
β βββ inference.py β Streaming inference (text + VLM)
βββ agent/__init__.py β Agent loop (model β tools, supports custom agents)
βββ tools/
β βββ fs.py β read_file, write_file, edit_file, glob, grep, list_dir
β βββ bash.py β Sandboxed shell execution
β βββ todos.py β Todo list management
β βββ github.py β GitHub repo import (shallow clone + strip heavy dirs)
βββ skills/
β βββ __init__.py β Skill discovery + loading
β βββ builtins/ β Built-in skills (markdown)
βββ agents/ β Custom Agent system (AI-generated personas)
β βββ __init__.py β Agent CRUD + system-prompt builder
β βββ builtins/ β Built-in agents (code-reviewer, test-writer)
βββ commands/
β βββ __init__.py β Slash command parser + expander
β βββ builtins/ β Built-in commands (markdown, includes /agent and /github)
βββ hooks/
β βββ __init__.py β Hook rule engine
β βββ builtins/ β Built-in hook rules (markdown)
βββ execution/
β βββ code_extractor.py β Code extraction from model output
β βββ python_runner.py β Sandboxed Python execution
β βββ gradio_runner.py β Gradio app subprocess runner
βββ huggingface/
β βββ dockerfile_gen.py β Auto Dockerfile/package.json for JS
β βββ push.py β HF Hub push + ZIP packaging
βββ websearch/google_scraper.py β DuckDuckGo + Google scraping (no API)
βββ server/
βββ chat_helpers.py β Chat history + prompt building
βββ routes.py β All HTTP + API endpoints
index.html β Frontend (single-file SPA)
workspace/ β Sandboxed agent workspace (auto-created)
```
## Conventions
- **Python**: 3.11+, type hints everywhere, `from __future__ import annotations`
- **Style**: Black formatting, 4-space indent, 100 char line limit
- **Docstrings**: Google style for modules, functions, classes
- **Error handling**: catch specific exceptions, never bare `except:`
- **Logging**: use `logging.getLogger(__name__)`, never `print()`
- **Tests**: pytest, in `tests/` directory, `test_*.py` naming
- **Frontend**: single-file HTML with inline CSS/JS, no build step
## Server rules
- All servers bind to `0.0.0.0` (never `localhost`)
- Default port: `7860` (HF Spaces convention)
- Sub-servers use `7861`, `7862`, etc.
## Model
- Default: `openbmb/MiniCPM5-1B` (text-only, 2.17 GB)
- Optional: `openbmb/MiniCPM-V-4.6` (vision + text, 2.8 GB)
- Loaded in background thread on startup
- Streaming inference via `TextIteratorStreamer`
## Tool call format
The model calls tools by emitting fenced code blocks with `tool` as the language:
```tool
read_file
path: src/app.py
```
Multi-line values use YAML block scalars:
```tool
write_file
path: src/new.py
content: |
import os
def main():
pass
```
## Slash commands
| Command | Description |
|---------|-------------|
| `/commit` | Create a git commit with a generated message |
| `/review` | Review current changes for bugs and quality |
| `/feature <desc>` | Guided feature development workflow |
| `/design <brief>` | Generate a distinctive frontend design |
| `/explain <target>` | Explain how code works |
| `/test <target>` | Generate tests |
| `/refactor <target>` | Refactor code for clarity |
| `/skill <name>` | Load and apply a skill |
| `/agent create <desc>` | AI generates a custom agent from natural-language description |
| `/agent use <name>` | Activate a saved agent |
| `/agent list` | List all saved agents |
| `/agent show <name>` | Show an agent's full definition |
| `/agent delete <name>` | Delete a user-defined agent |
| `/agent reset` | Reset to default SoniCoder persona |
| `/github <url> [subdir] [--branch <name>] [--into <path>]` | Import a GitHub repo into the workspace |
| `/help` | Show available commands and skills |
## Custom Agents
Custom agents are AI-generated personas layered on top of the base SoniCoder
system prompt. They can restrict the tool whitelist, auto-load skills, and
override temperature / max-iterations.
### Agent file format
Agents live in `workspace/.sonicoder/agents/<name>/AGENT.md` (built-ins in
`code/agents/builtins/<name>/AGENT.md`). Format:
```markdown
---
name: my-agent
description: One-line description
tools: read_file, list_dir, grep, bash
skills: code-review
temperature: 0.2
max_iterations: 12
tags: review, quality
author: AI-generated
created: 2026-06-20
---
# My Agent
Full system-prompt extension here. Define the persona, workflow, output format,
and any hard rules.
```
### How `/agent create` works
1. User runs `/agent create a security reviewer that flags hardcoded secrets`.
2. The slash-command expansion substitutes `AGENT_GENERATION_PROMPT` (defined
in `code/agents/__init__.py`) into the prompt.
3. The base SoniCoder model (NOT a custom agent) authors an `AGENT.md` file
via `write_file` and saves it under `.sonicoder/agents/<name>/`.
4. The user can then `/agent use <name>` or click the agent in the UI.
### Built-in agents
| Agent | Description |
|-------|-------------|
| `code-reviewer` | Read-only reviewer, structured issues table output |
| `test-writer` | Generates pytest/jest tests, runs them, iterates until green |
### API endpoints
| Endpoint | Description |
|----------|-------------|
| `list_agents` | List all agents (builtins + user) and the active one |
| `get_agent(name)` | Get a single agent's full definition |
| `save_agent(...)` | Create or overwrite a user agent (manual save) |
| `delete_agent(name)` | Delete a user agent (built-ins protected) |
| `set_active_agent(name)` | Set/clear the active agent for subsequent prompts |
| `import_github(url, branch, subdir, target_subdir, depth, timeout)` | Clone a GitHub repo into the workspace (shallow, heavy dirs stripped) |
| `github_url_examples()` | Return accepted GitHub URL formats |
| `push_github(repo_name, github_token, username, branch?, commit_message?, timeout?)` | Snapshot workspace β commit β push to a GitHub repo |
The `agent_run` endpoint also intercepts `/agent use|reset|delete|list` and
dispatches them directly to the agents module, bypassing the model entirely
for instant session-state updates.
## GitHub Import
SoniCoder can clone any public GitHub repo into the workspace, allowing the
agent to read, edit, extend, or refactor real-world code.
### How it works
1. User submits a GitHub URL via the Agent tab UI box (or via `/github <url>`
slash command in chat while Agent mode is ON).
2. The backend (`code/tools/github.py::import_github_repo`) parses the URL
(supports HTTPS, SSH, and `/tree/<branch>/<subdir>` forms) and validates
that the host is `github.com`.
3. The repo is shallow-cloned (`git clone --depth 1 --single-branch`) into a
temp directory.
4. Files are *copied* into the workspace (root or `target_subdir`) with these
directories stripped: `.git`, `.hg`, `.svn`, `node_modules`, `__pycache__`,
`.venv`, `venv`, `env`, `.tox`, `.mypy_cache`, `.pytest_cache`,
`.ruff_cache`, `dist`, `build`, `.next`, `.nuxt`, `.cache`, `.gradle`,
`target`, `Pods`. `.DS_Store` and `Thumbs.db` are also dropped.
5. The workspace tree refreshes; Agent mode auto-enables if it wasn't already.
### Security
- Only `github.com` URLs are accepted (HTTPS or SSH form).
- `target_subdir` is sanitized β no path escapes.
- The upstream repo is never modified (clone happens in temp dir, then
copied). The `.git` directory is stripped so the agent doesn't walk it.
- Default clone timeout: 120s (UI uses 180s). Max: 600s.
### Slash command
```
/github <url> [subdir] [--branch <name>] [--into <path>] [--depth <N>] [--timeout <s>]
```
The slash command (defined in `code/commands/builtins/github.md`) instructs
the agent to invoke `import_github_repo` via bash, then list the top-level
files and suggest next steps based on what was imported.
## GitHub Push
Push the current workspace back to a GitHub repo as a commit. Only 3 inputs
are required: repo name, GitHub token, username.
### How it works (`code/tools/github.py::push_to_github`)
1. Snapshot the workspace via `snapshot_workspace()` (returns a
`{relative_path: content}` dict).
2. Create a temp dir, `git init -b <branch>` inside it, write the snapshot
files in, `git add -A` + `git commit -m <message>`.
3. Build a push URL of the form
`https://<username>:<token>@github.com/<owner>/<repo>.git` and run
`git push --force-with-lease <url> <branch>`.
4. If `--force-with-lease` fails because the remote has no refs yet
(brand-new empty repo), retry with a plain `git push`.
5. Delete the temp dir. The token is never logged; error messages scrub it
before being returned.
### Why `--force-with-lease`
SoniCoder treats the workspace as the source of truth. `--force-with-lease`
replaces the remote tip with the workspace snapshot, but fails loudly (rather
than silently clobbering) if someone else pushed commits in the meantime β
because the temp repo has no reflog of the remote tip, the lease fails and
the user is told to pull first.
### UI
Located in the **Deploy** tab, in a "Push Update to GitHub" section below the
HuggingFace section. Only 3 fields are required: repo name, token, username.
An "Advanced" `<details>` exposes optional `branch` and `commit_message`
fields.
### Security
- Token is sent over HTTPS to the SoniCoder backend, used once for the push,
then dropped (not stored, not logged).
- Error messages are scrubbed to remove the token before being returned.
- The temp repo is deleted at the end of the call (context manager).
- The local SoniCoder workspace is never turned into a git repo; the
workspace's `.git` (if any, e.g. after an import β though imports strip
`.git`) is never read.
## Skills
| Skill | Description |
|-------|-------------|
| `frontend-design` | Distinctive visual design guidance |
| `feature-dev` | Guided feature implementation workflow |
| `code-review` | High-signal code review |
| `debugging` | Systematic debugging workflow |
| `fullstack-scaffold` | Project structure scaffolding rules |
| `commit-workflow` | Git commit best practices |
## Hooks
Hooks are markdown rules that fire on events (`bash`, `file`, `prompt`, `stop`).
They can `warn` (show a message) or `block` (prevent the action).
Built-in hooks:
- `block-dangerous-rm` β blocks `rm -rf /`, `~`, `$HOME`, `..`
- `warn-debug-code` β warns on `console.log`, `debugger`, `print`, `alert`
- `warn-secrets-in-code` β warns on hardcoded API_KEY/SECRET/TOKEN/PASSWORD
- `warn-eval-exec` β warns on `eval()` and `exec()`
Users can add custom hooks in `workspace/.sonicoder/hooks/*.local.md`.
## Workspace
The agent's sandboxed filesystem lives at `./workspace/` (configurable via
`SONICODER_WORKSPACE` env var). All file tools refuse paths that escape this root.
## Deploy
Generated projects can be pushed to HuggingFace Spaces via the Deploy tab.
Supported SDKs:
- `static` β HTML/CSS/JS
- `gradio` β Python Gradio apps
- `streamlit` β Python Streamlit apps
- `docker` β JS/TS frameworks (auto-generates Dockerfile + package.json)
|