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:
240
docs/tools.md
Normal file
240
docs/tools.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Tool Reference
|
||||
|
||||
SneakyCode provides 11 agent-callable tools organized into 5 categories. All file path arguments must be **relative to the workspace root**.
|
||||
|
||||
## Permission Tiers
|
||||
|
||||
| Tier | Behavior | Tools |
|
||||
|---------------|---------------------------------------|----------------------------------------------------------------|
|
||||
| Auto-approved | Executed without user confirmation | `read_file`, `list_dir`, `grep_files`, `find_files`, `finish` |
|
||||
| User confirm | Prompts user before execution | `write_file`, `make_dir`, `delete_file`, `str_replace`, `patch_apply`, `run_command` |
|
||||
| Denied | Blocked entirely (configurable) | Any tool added to `permissions.deny` in config |
|
||||
|
||||
---
|
||||
|
||||
## Read Tools
|
||||
|
||||
### read_file
|
||||
|
||||
Read the full contents of a text file.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|------|----------|------------------------------------------------|
|
||||
| `file_path` | str | Yes | Path to the file to read (relative to workspace) |
|
||||
|
||||
**Permission:** Auto-approved
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"file_path": "app/main.py"}
|
||||
```
|
||||
|
||||
**Notes:** Binary files are detected and rejected. Files exceeding `max_file_size_bytes` (default 1 MB) are rejected.
|
||||
|
||||
---
|
||||
|
||||
### list_dir
|
||||
|
||||
List the contents of a directory. Directories are suffixed with `/`. Results are sorted with directories first, then files.
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|------------------|------|----------|---------|--------------------------------------|
|
||||
| `directory_path` | str | No | `"."` | Path to directory (relative) |
|
||||
| `recursive` | bool | No | `false` | If true, list entries recursively |
|
||||
|
||||
**Permission:** Auto-approved
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"directory_path": "app/tools", "recursive": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Search Tools
|
||||
|
||||
### grep_files
|
||||
|
||||
Search for a regex pattern in file contents. Returns matching lines with file paths and line numbers.
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|----------------|------------|----------|---------|------------------------------------------|
|
||||
| `pattern` | str | Yes | | Regular expression pattern to search for |
|
||||
| `path` | str | No | `"."` | Directory or file to search in |
|
||||
| `file_pattern` | str\|null | No | `null` | Glob pattern to filter files (e.g. `*.py`) |
|
||||
|
||||
**Permission:** Auto-approved
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"pattern": "def main", "path": "app/", "file_pattern": "*.py"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### find_files
|
||||
|
||||
Search for files matching a name pattern. Returns relative file paths.
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|-----------|------|----------|---------|---------------------------------------------------|
|
||||
| `pattern` | str | Yes | | File name pattern (e.g. `*.py`, `config.yaml`) |
|
||||
| `path` | str | No | `"."` | Directory to search in |
|
||||
|
||||
**Permission:** Auto-approved
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"pattern": "*.yaml", "path": "config/"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Write Tools
|
||||
|
||||
### write_file
|
||||
|
||||
Write text content to a file. Creates parent directories if needed. Overwrites existing file content.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|------|----------|---------------------------------|
|
||||
| `file_path` | str | Yes | Path to the file to write |
|
||||
| `content` | str | Yes | Content to write to the file |
|
||||
|
||||
**Permission:** User confirmation required
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"file_path": "app/utils/helpers.py", "content": "def greet():\n return 'hello'\n"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### make_dir
|
||||
|
||||
Create a directory and any necessary parent directories.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|------------------|------|----------|----------------------------------|
|
||||
| `directory_path` | str | Yes | Path to the directory to create |
|
||||
|
||||
**Permission:** User confirmation required
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"directory_path": "app/services/new_module"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### delete_file
|
||||
|
||||
Delete a single file. Does not delete directories.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|------|----------|---------------------------------|
|
||||
| `file_path` | str | Yes | Path to the file to delete |
|
||||
|
||||
**Permission:** User confirmation required
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"file_path": "app/utils/deprecated.py"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Edit Tools
|
||||
|
||||
### str_replace
|
||||
|
||||
Replace exactly one occurrence of `old_str` with `new_str` in a file. Fails if `old_str` is not found or appears more than once.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|------|----------|----------------------------------------------------|
|
||||
| `file_path` | str | Yes | Path to the file to edit |
|
||||
| `old_str` | str | Yes | The exact string to find and replace (must be unique) |
|
||||
| `new_str` | str | Yes | The replacement string |
|
||||
|
||||
**Permission:** User confirmation required
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"file_path": "app/main.py",
|
||||
"old_str": "def old_function():",
|
||||
"new_str": "def new_function():"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### patch_apply
|
||||
|
||||
Apply a unified diff (patch) to a file. The patch must be in standard unified diff format.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|------|----------|--------------------------------------------|
|
||||
| `file_path` | str | Yes | Path to the file to patch |
|
||||
| `patch` | str | Yes | Unified diff format patch to apply |
|
||||
|
||||
**Permission:** User confirmation required
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"file_path": "app/main.py",
|
||||
"patch": "--- a/app/main.py\n+++ b/app/main.py\n@@ -1,3 +1,3 @@\n-old line\n+new line\n"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shell Tools
|
||||
|
||||
### run_command
|
||||
|
||||
Run a shell command in the workspace directory. Only allowed commands may be executed; dangerous commands are blocked.
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|-----------|----------|----------|---------|-----------------------------------|
|
||||
| `command` | str | Yes | | Shell command to execute |
|
||||
| `timeout` | int\|null | No | `30` | Timeout in seconds |
|
||||
|
||||
**Permission:** User confirmation required. Subject to `tools.shell.allowed_commands` and `tools.shell.denied_commands` in config.
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"command": "git status", "timeout": 10}
|
||||
```
|
||||
|
||||
**Notes:** Output is truncated to `max_output_bytes` (default 64 KB). The command's first word is checked against allow/deny lists.
|
||||
|
||||
---
|
||||
|
||||
## Control Tools
|
||||
|
||||
### finish
|
||||
|
||||
Signal that the task is complete. Terminates the agent loop.
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|-----------|------|----------|--------------------|------------------------------|
|
||||
| `message` | str | No | `"Task complete."` | Final message to the user |
|
||||
|
||||
**Permission:** Auto-approved
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{"message": "Created the new module with tests."}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- All file paths are resolved against `workspace_root` with path traversal protection
|
||||
- Binary file detection prevents reading/writing binary files
|
||||
- File size limits prevent reading/writing excessively large files
|
||||
- Shell commands are validated against configurable allow/deny lists
|
||||
- Tool call arguments from the LLM are validated against JSON schema before execution
|
||||
Reference in New Issue
Block a user