Skip to content

Commit cc493c1

Browse files
committed
Add detailed architecture/dev/agent-mode docs, rewrite READMEs
Add docs/ARCHITECTURE.md, docs/AGENT_MODE.md, and docs/DEVELOPMENT.md covering the Electron process model, IPC bridge, persistence pattern, native Rust addon, the full Agent mode tool catalog and sandboxing model, and the dev/build/release workflow. Update the root README and ml/hardware-recommender README to link to these, and correct the description of how the hardware-recommender model is actually wired into the app at runtime (a committed checkpoint + inference worker, not a standalone unused artifact).
1 parent 1553e2d commit cc493c1

5 files changed

Lines changed: 540 additions & 43 deletions

File tree

‎README.md‎

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Beyond chat, Modelforge includes an **agentic mode** — the model can read/writ
1818
- [Quick start](#quick-start-try-it-in-5-minutes)
1919
- [Agent mode](#agent-mode)
2020
- [Building from source](#building-from-source)
21-
- [Project structure](#project-structure)
21+
- [Documentation](#documentation)
2222
- [Testing](#testing)
2323
- [Security](#security)
2424
- [Contributing](#contributing)
@@ -140,31 +140,15 @@ If steps 2–3 work, the core app is functioning correctly — everything else l
140140

141141
## Agent mode
142142

143-
Click **Agent** in the chat toolbar and pick a folder — that becomes the model's sandboxed workspace for the rest of the conversation. The model can then call:
144-
145-
| Tool | What it does |
146-
|---|---|
147-
| `read_file` | Read a text file, optionally by line range |
148-
| `write_file` | Create or overwrite a file (creates parent directories as needed) |
149-
| `replace_in_file` | Replace an exact text block without rewriting the whole file; supports Undo |
150-
| `find_files`, `file_info` | Discover files by glob and inspect path metadata |
151-
| `list_dir` | List files and subdirectories |
152-
| `search_files` | Search for a text string across the workspace |
153-
| `make_directory`, `move_path`, `delete_path` | Organize workspace files with explicit approval for mutations |
154-
| `run_command` | Execute a shell command in the workspace (or a subfolder), with a 60s timeout |
155-
| `run_code` | Run a Python or JavaScript snippet — a convenience over shell-quoting multi-line code through `run_command`, not a new capability |
156-
| `git_status`, `git_diff`, `git_log` | Read-only git helpers (auto-approvable, like the file tools) so the model doesn't need to guess flag syntax |
157-
| `git_commit` | Stage everything and commit — requires approval, like `write_file` |
158-
| `github_list_repositories` | List repositories accessible to the linked GitHub account |
159-
| `github_repository_tree` | Inspect a repository's complete file structure before analysis |
160-
| `github_read_file` | Read selected files from public or private linked-account repositories |
143+
Click **Agent** in the chat toolbar and pick a folder — that becomes the model's sandboxed workspace for the rest of the conversation. The model can then call a wide catalog of tools: file read/write/search/patch, shell and background commands, an interactive terminal, read-only and commit git operations, and network tools (web search, arbitrary HTTP requests, linked-GitHub repo access). **See [docs/AGENT_MODE.md](docs/AGENT_MODE.md) for the full, current tool table** — the summary below covers the safety model, which is the part worth understanding before you use it.
161144

162145
**Safety model:**
163146
- Built-in filesystem tools are genuinely confined to the chosen workspace folder — path traversal (`../../etc`), absolute paths elsewhere on disk, and symlinks that resolve outside the workspace are rejected before anything runs.
164-
- `run_command` and `run_code` are different: a shell command (or a script `run_code` hands to `python3`/`node`) is opaque text that can reference any path on the system regardless of its working directory, so neither is sandboxed the way the file tools are. As a safety net, commands (and `run_code`'s source text) matching destructive or system-level patterns — deleting outside the workspace, formatting a drive, shutting down the machine, registry deletion, `sudo`/`runas`, piping a remote script into a shell — are **rejected outright**, even if already approved. This blocklist catches the common catastrophic cases, not everything a shell or script can do — only approve a command or snippet you actually understand.
165-
- Every call (including ones the blocklist doesn't catch) shows an **Allow / Deny** card before it executes — nothing runs without an explicit click. Read-only tools (`read_file`, `find_files`, `file_info`, `list_dir`, `search_files`, `git_status`, `git_diff`, `git_log`) can be marked "always allow this session" to cut down on repetitive approvals; filesystem mutations, `run_command`, `run_code`, and `git_commit` always require a fresh click, since they have real, potentially irreversible effects.
147+
- `run_command` and `run_code` are different: a shell command (or a script `run_code` hands to `python3`/`node`) is opaque text that can reference any path on the system regardless of its working directory, so neither is confined the way the file tools are. Where the OS supports it, commands run inside a real sandbox instead (bubblewrap on Linux, `sandbox-exec` on macOS — Windows has no equivalent). As a safety net everywhere, commands (and `run_code`'s source text) matching destructive or system-level patterns — deleting outside the workspace, formatting a drive, shutting down the machine, registry deletion, `sudo`/`runas`, piping a remote script into a shell — are **rejected outright**, even if already approved. This blocklist catches the common catastrophic cases, not everything a shell or script can do — only approve a command or snippet you actually understand.
148+
- Every call (including ones the blocklist doesn't catch) shows an **Allow / Deny** card before it executes — nothing runs without an explicit click. A narrow set of strictly read-only, no-network tools can be marked "always allow this session" to cut down on repetitive approvals; anything that mutates the workspace, runs code, or touches the network always requires a fresh click, since those have real, potentially irreversible or unattended-outbound-channel effects — see [docs/AGENT_MODE.md](docs/AGENT_MODE.md#safety-model) for exactly which tools qualify and why.
166149
- A per-turn step limit (25 tool-result → model-continuation round trips) stops a model from looping indefinitely without producing a final answer.
167150
- The trust list for "always allow" is in-memory only — closing and reopening a chat resets it.
151+
- A Settings toggle can disable every network-capable tool at once, for a fully offline, filesystem-and-shell-only workflow.
168152

169153
**Preview & Rollback:**
170154
- A pending `write_file` call shows a real **line-by-line diff** against the file's current content (or a "new file" badge if it doesn't exist yet) instead of a raw argument dump, so you can see exactly what would change before clicking Allow.
@@ -178,7 +162,7 @@ Click **Agent** in the chat toolbar and pick a folder — that becomes the model
178162

179163
Enabled servers reconnect automatically on launch; each server's tools appear in Agent mode's tool list prefixed with the server's name, going through the exact same Allow/Deny approval flow as built-in tools. (SSE and plain WebSocket transports aren't implemented — SSE is the legacy MCP HTTP transport, now superseded by Streamable HTTP, and WebSocket isn't part of the MCP spec itself.)
180164

181-
**Model choice matters.** Agent mode works with whatever model you point it at, but only actually produces tool calls if that model was trained for function/tool calling — a model without that training will just chat normally and never call a tool. The Settings model browser flags models with reliable tool-calling support with a 🔧 **Tool calling** badge (e.g. the Qwen3 family, Llama 3.1+, Mistral Nemo, Qwen2.5-Coder, Devstral).
165+
**Model choice matters.** Agent mode works with whatever model you point it at, but only actually produces tool calls if that model was trained for function/tool calling — a model without that training will just chat normally and never call a tool. The Settings model browser flags models with reliable tool-calling support with a 🔧 **Tool calling** badge (e.g. the Qwen3 family, Llama 3.1+, Mistral Nemo, Qwen2.5-Coder, Devstral). The llama.cpp backend doesn't have tool-calling wired up yet — see [Features](#features) above.
182166

183167
## Building from source
184168

@@ -199,26 +183,18 @@ npm run dev --prefix app
199183
npm run package --prefix app
200184
```
201185

202-
Packaged installers are written to `app/release/`.
186+
Packaged installers are written to `app/release/`. For the full development workflow (hot reload,
187+
rebuilding the native Rust addon, cross-platform packaging details, CI/release pipeline), see
188+
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
203189

204-
## Project structure
190+
## Documentation
205191

206-
```
207-
frontend/ React + Vite renderer (the UI)
208-
src/pages/ Chat and Settings screens
209-
src/components/ Shared UI (layout, command palette, markdown rendering, shadcn primitives)
210-
src/lib/ i18n, model catalogs, pricing estimates, provider helpers
211-
212-
app/ Electron main process
213-
src/main.ts Window management, IPC handler registration
214-
src/providers/ Ollama/OpenAI/Anthropic chat + tool-calling adapters
215-
src/agent-tools.ts Agent mode's file/shell tool implementations (workspace-sandboxed)
216-
src/*-store.ts Settings/sessions/projects/secrets persistence (atomic writes, corruption recovery)
217-
src/rag.ts Chunking + embedding + retrieval for large folder attachments
218-
src/logger.ts Rotating file logs surfaced via Settings → Data → Diagnostics
219-
```
192+
This README covers what the app does and how to install/build it. For anything deeper:
220193

221-
The frontend builds to a single inlined HTML file (`vite-plugin-singlefile`) so Electron can load it directly via `file://` in production, matching how the packaged app actually runs.
194+
- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — how the Electron main/renderer/preload split works, the IPC bridge, the native Rust downloader addon, the persistence pattern (atomic writes, corruption recovery), and the end-to-end data flow for sending a chat message.
195+
- **[docs/AGENT_MODE.md](docs/AGENT_MODE.md)** — the full Agent mode tool catalog, the workspace-sandboxing and OS-level command-sandboxing model, the tool-approval policy and exactly why each tool is or isn't auto-approvable, and MCP server integration.
196+
- **[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)** — prerequisites, running in dev mode, testing, building, packaging installers for each platform, and the project's directory layout.
197+
- **[ml/hardware-recommender/README.md](ml/hardware-recommender/README.md)** — the standalone Python project that trains the hardware/model-fit recommender. Its training pipeline isn't part of the app's build, but its trained checkpoint ships with the app and is used at runtime via a Python worker to enhance the Models & hardware recommendations mentioned above.
222198

223199
## Testing
224200

@@ -227,19 +203,19 @@ npm test --prefix frontend
227203
npm test --prefix app
228204
```
229205

230-
The `app` suite covers the store layer (atomic writes, corrupted-file recovery), the agent tools (including path-traversal rejection and shell command execution), and the RAG chunking/similarity logic. Both suites run in CI on every push and pull request via [`.github/workflows/ci.yml`](.github/workflows/ci.yml), which also lints, typechecks, and builds both packages.
206+
The `app` suite covers the store layer (atomic writes, corrupted-file recovery), the agent tools (including path-traversal rejection and shell command execution), and the RAG chunking/similarity logic. Both suites run in CI on every push and pull request via [`.github/workflows/ci.yml`](.github/workflows/ci.yml), which also lints, typechecks, and builds both packages. See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md#testing) for what each suite specifically exercises.
231207

232208
## Security
233209

234210
- **Process isolation**: `contextIsolation: true`, `nodeIntegration: false` — the renderer only ever talks to the main process through an explicit, typed preload bridge.
235211
- **Content Security Policy** restricting plugins, frames, and form submissions; external links open in your default browser instead of an unmanaged Electron window.
236212
- **API keys** are encrypted at rest via the OS credential store (`safeStorage`) and never leave the device.
237-
- **Agent mode** tool calls are workspace-sandboxed (path-traversal rejected) and require explicit per-call approval — see [Agent mode](#agent-mode) above.
213+
- **Agent mode** tool calls are workspace-sandboxed (path-traversal rejected) and require explicit per-call approval — see [Agent mode](#agent-mode) above and [docs/AGENT_MODE.md](docs/AGENT_MODE.md) for the full detail.
238214
- No telemetry, no analytics, no data sent anywhere except directly to whichever provider (Ollama, OpenAI, Anthropic) you've configured.
239215

240216
## Contributing
241217

242-
Issues and pull requests are welcome. Before opening a PR, please make sure:
218+
Issues and pull requests are welcome. See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the full setup and testing workflow. Before opening a PR, please make sure:
243219

244220
```sh
245221
npm run lint --prefix frontend

0 commit comments

Comments
 (0)