dostuff 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dostuff-0.2.0 → dostuff-0.2.1}/PKG-INFO +81 -26
- {dostuff-0.2.0 → dostuff-0.2.1}/README.md +80 -25
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/__init__.py +5 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/agent/call_agent.py +2 -2
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/agent/loop.py +18 -12
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/agent/permissions.py +47 -5
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/agent/run_tool.py +2 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/cli.py +69 -51
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/cli_tui.py +412 -29
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/config.py +49 -5
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/headless.py +56 -13
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/constants.py +7 -2
- dostuff-0.2.1/dostuff/helpers/agent/context_usage.py +85 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/get_model_token_limit.py +2 -2
- dostuff-0.2.1/dostuff/helpers/agent/quick_memory.py +33 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/models/list_models.py +13 -1
- dostuff-0.2.1/dostuff/helpers/models/opencode.py +76 -0
- dostuff-0.2.1/dostuff/helpers/skills/custom_commands.py +51 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/skills/skill_command.py +12 -6
- dostuff-0.2.1/dostuff/helpers/ui/doctor.py +47 -0
- dostuff-0.2.1/dostuff/helpers/ui/terminal_signals.py +50 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/session_store.py +14 -0
- dostuff-0.2.1/dostuff/lib/model.py +60 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/setup_wizard.py +13 -3
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/templates/config.example.yaml +11 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/templates/env.example +1 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/settings.py +2 -2
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/PKG-INFO +81 -26
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/SOURCES.txt +9 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/pyproject.toml +1 -1
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_checkpoints_todos_caching.py +0 -1
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_cli_commands.py +50 -1
- dostuff-0.2.1/tests/test_opencode.py +81 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_permissions.py +35 -0
- dostuff-0.2.1/tests/test_roadmap_021.py +84 -0
- dostuff-0.2.1/tests/test_terminal_signals.py +57 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_tui.py +166 -0
- dostuff-0.2.0/dostuff/lib/model.py +0 -36
- {dostuff-0.2.0 → dostuff-0.2.1}/LICENSE +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/__main__.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/agent/instructions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/append_step.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/consume_stream.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/environment_context.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/file_mentions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/load_identity.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/load_project_instructions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/loop_check_cancelled.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/loop_emit.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/manage_context.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/model_cost.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/pastes.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/slash_suggestion.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/agent/tool_output.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/mcp/load_mcp_config.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/mcp/mcp_oauth.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/mcp/server_config.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/mcp/token_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/memory/export_session.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/memory/resolve_memory_operation.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/memory/shell_step.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/models/add_model_entry.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/skills/discover_skills.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/tools/diff.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/tools/generate_tool_schema.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/tools/project_root.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/tools/resolve_safe_path.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/ui/__init__.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/ui/emit.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/helpers/ui/prompt_history.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/checkpoints.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/exceptions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/mcp/mcp_client.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/mcp/mcp_client_registration_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/mcp/mcp_tool_registry_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/chroma.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/episodic_memory_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/semantic_memory_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/stores.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/memory/types.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/tracing.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/lib/worktree.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/memory/__init__.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/skills.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/__init__.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/bash/bash_command.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/definitions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/delegate_to_subagent.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/files/delete_file.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/files/edit_file.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/files/list_files.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/files/read_file.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/files/write_file.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/get_current_datetime.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/mcp/call_mcp_tool.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/mcp/get_mcp_tool_details.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/mcp/search_mcp_tools.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/memory/save_episode.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/memory/save_memory.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/search/glob.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/search/grep.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/search/walk.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/todo_write.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/web_fetch.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff/tools/web_search.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/dependency_links.txt +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/entry_points.txt +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/requires.txt +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/dostuff.egg-info/top_level.txt +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/setup.cfg +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_config_memory_mcp.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_file_mentions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_file_tools.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_loop.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_mcp_e2e.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_mcp_oauth.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_optional_memory_and_instructions.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_pastes.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_session_store.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_settings_tools.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_setup_wizard.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_skill_command.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_slash_suggestion.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_subagent.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_tool_schemas.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_web_fetch.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_web_search.py +0 -0
- {dostuff-0.2.0 → dostuff-0.2.1}/tests/test_worktree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dostuff
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: DoStuff - a terminal coding agent for any LLM: TUI and headless mode, permissions, MCP, skills, web tools, sessions and git worktrees
|
|
5
5
|
Author-email: Varun Kumawat <varunkumawatleap2@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -74,26 +74,28 @@ DoStuff is a terminal AI agent that runs anywhere `pip` runs. It gives you a ful
|
|
|
74
74
|
|
|
75
75
|
## Features
|
|
76
76
|
|
|
77
|
-
- **Textual TUI** with
|
|
78
|
-
- **
|
|
79
|
-
- **
|
|
77
|
+
- **Textual TUI** with a `/` command menu, `@file` completion, `!shell` commands, an in-app config editor, a configurable status bar and a live turn timer
|
|
78
|
+
- **Headless mode** — `dostuff -p "<prompt>"` runs one prompt and prints the answer (`--output-format json|stream-json`, `--max-turns`, `--allowed-tools` for scripts and CI)
|
|
79
|
+
- **Multi-provider LLMs** via [litellm](https://docs.litellm.ai/docs/providers) — OpenAI, Anthropic, Gemini, Groq, Mistral, Ollama, OpenRouter, OpenCode Zen / Go
|
|
80
|
+
- **Persistent sessions** in SQLite; resume with `dostuff -c`, `dostuff resume` or `dostuff --session <id>`, branch one off with `/fork`
|
|
81
|
+
- **Git worktrees** — `/worktree` or `dostuff -w` runs a session on its own branch and checkout; subagents can run in their own worktree too
|
|
80
82
|
- **Long-term memory** (semantic + episodic) backed by ChromaDB — optional, `pip install "dostuff[memory]"`
|
|
81
83
|
- **MCP server support** — stdio (npx, uvx) and HTTP transports
|
|
82
84
|
- **`@file` mentions** — type `@` in the prompt to pick a file or folder; its content (or listing) is sent with the message
|
|
83
85
|
- **Project instructions** — `AGENTS.md` / `CLAUDE.md` from `~/.dostuff/`, the repo root and every folder down to the current one, combined
|
|
84
86
|
- **Coding tools** — `read_file` (line numbers, offset/limit), `edit_file` (exact replacement), `write_file`, `grep`, `glob`, `list_files`, `delete_file`, `bash_command`, `web_fetch` (read a URL as text), `web_search` (free, no API key)
|
|
85
|
-
- **Permission layer** — mutating tool calls ask for approval (
|
|
87
|
+
- **Permission layer** — mutating tool calls ask for approval (allow once / always this session / deny with a note); read-only shell commands run without asking; modes `ask` / `allowlist` / `auto`; `/undo` reverts the agent's file changes
|
|
86
88
|
- **File sandbox** — file tools stay inside the project directory and never read `.env*` files or `~/.dostuff/`
|
|
87
89
|
- **Skills loader** — drop a `SKILL.md` in the right folder, restart, done; run one with `/<skill-name> [args]`
|
|
88
90
|
- **Subagents** — `delegate_to_subagent` runs a bounded task with a restricted tool set; its approval prompts and ESC go through the same TUI
|
|
89
91
|
- **Per-tool timeout** (120s) to prevent hung servers; long tool output is truncated (head + tail) before it reaches the model
|
|
90
92
|
- **Retries with backoff** for rate limits, timeouts and 5xx errors (6 by default, exponential with jitter, honors `Retry-After`; `loop.max_retries` / `loop.retry_max_delay`); auth / bad-request errors fail fast
|
|
91
|
-
- **Token and cost tracking** — per-turn and cumulative totals in `/status` and the line after each turn (`✻ Worked for 1m 5s · $0.01`); cost in USD from litellm's price table (hidden when the model has no known price)
|
|
93
|
+
- **Token and cost tracking** — per-turn and cumulative totals in `/status` and the line after each turn (`✻ Worked for 1m 5s · $0.01`); cost in USD from litellm's price table (hidden when the model has no known price). The table bundled with litellm is used, so startup doesn't wait on a download; set `LITELLM_LOCAL_MODEL_COST_MAP=False` to fetch the latest one from GitHub instead
|
|
92
94
|
- **Long-term memory tools** — the agent saves facts (`save_memory`) and notable moments (`save_episode`) as they come up; both are recalled in later sessions
|
|
93
95
|
- **Graceful exit** — `Ctrl+Q` or `/exit` saves the session, cleans up, and stops background workers
|
|
94
96
|
- **Clean Cancellation** — `Escape` can cancel in-flight agent turns cleanly without corrupting the session
|
|
95
97
|
- **2-state session split** — `session_steps` (full audit) / `working_history` (LLM payload); DB persists both plus `compaction_notes` + `last_input_tokens`
|
|
96
|
-
- **Auto & Manual Compaction** — Manual `/compact` runs compaction and saves it. Auto-compaction triggers automatically during the agent loop if context usage (`last_input_tokens`) exceeds 50% of the model's token limit. It keeps at least 15% or 20k tokens of the most recent steps in the working history, summarizing the rest into `compaction_notes` which are appended to system instructions.
|
|
98
|
+
- **Auto & Manual Compaction** — Manual `/compact` runs compaction and saves it. Auto-compaction triggers automatically during the agent loop if context usage (`last_input_tokens`) exceeds `loop.auto_compact_threshold` (default 50%) of the model's token limit; `off` disables it (an overflowing window is still compacted), and `/compact auto <N|off>` changes it for the session. It keeps at least 15% or 20k tokens of the most recent steps in the working history, summarizing the rest into `compaction_notes` which are appended to system instructions.
|
|
97
99
|
- **Tracing (opt-in)** — OTLP tracing support built into `lib/tracing.py`; prompt and tool content are redacted from spans by default
|
|
98
100
|
|
|
99
101
|
---
|
|
@@ -129,8 +131,8 @@ pipx install dostuff
|
|
|
129
131
|
For development (editable mode, from a clone):
|
|
130
132
|
|
|
131
133
|
```bash
|
|
132
|
-
git clone https://github.com
|
|
133
|
-
cd
|
|
134
|
+
git clone https://github.com/kVarunkk/DoStuff.git
|
|
135
|
+
cd DoStuff
|
|
134
136
|
pip install -e . # core
|
|
135
137
|
pip install -e ".[memory]" # + long-term memory (chromadb)
|
|
136
138
|
pip install -e ".[full]" # + memory + onnxruntime + grpcio
|
|
@@ -185,17 +187,19 @@ In the TUI:
|
|
|
185
187
|
| `dostuff` | Launch the interactive TUI |
|
|
186
188
|
| `dostuff --version` | Print the version (`-V`) |
|
|
187
189
|
| `dostuff --session <id>` | Resume a prior session (asks before starting a new one if the ID is unknown) |
|
|
190
|
+
| `dostuff -c` / `--continue` | Resume the latest session in the current directory (same as `dostuff resume`; works with `-p` too) |
|
|
191
|
+
| `dostuff -w` / `--worktree-name <name>` | Start the session in a new git worktree (`.dostuff/worktrees/<name>`, branch `dostuff/<name>`) |
|
|
188
192
|
| `dostuff init [--force]` | Create `.dostuff/` config/skills in current dir (won't overwrite without `--force`) |
|
|
189
193
|
| `dostuff setup` | Pick a model, save its API key, write `~/.dostuff/config.yaml` (runs automatically on first launch) |
|
|
190
194
|
| `dostuff config` | Show resolved config paths and values |
|
|
191
195
|
| `dostuff doctor` | Health check: config, API key, MCP, data dir; prints a fix for each problem |
|
|
192
|
-
| `dostuff resume [<id>]` | Resume the latest session started in the current directory (or the given one; a unique ID prefix is enough) |
|
|
196
|
+
| `dostuff resume [<id>]` | Resume the latest session started in the current directory (or the given one; a unique ID prefix is enough). `--fork` resumes a copy, `--worktree` moves it into a new worktree |
|
|
193
197
|
| `dostuff sessions [--all] [-n N]` | List sessions in the current directory with their title or first prompt (`--all`: every directory) |
|
|
194
198
|
| `dostuff sessions rename <id> <title>` | Name a session |
|
|
195
199
|
| `dostuff sessions rm <id>... [-y]` | Delete sessions and their `/undo` checkpoints |
|
|
196
200
|
| `dostuff sessions prune [--older-than 30d] [--dry-run] [-y]` | Delete empty sessions, and sessions not used for the given time (`45m`, `12h`, `30d`, `2w`) |
|
|
197
201
|
| `dostuff export [<id>] [-o file\|-]` | Save a session (default: latest here) as Markdown: prompts, answers, tool calls and results |
|
|
198
|
-
| `dostuff -p "<prompt>"` | Headless: run one prompt, print the answer to stdout, exit. Progress goes to stderr. Piped stdin is appended to the prompt (`-p -` reads the prompt from stdin). `--session <id>` continues a session, `--json` prints `{result, session_id, usage, ...}`, `-q` hides progress, `--permission-mode ask\|allowlist\|auto`. Without a terminal, calls that need approval are denied |
|
|
202
|
+
| `dostuff -p "<prompt>"` | Headless: run one prompt, print the answer to stdout, exit. Progress goes to stderr. Piped stdin is appended to the prompt (`-p -` reads the prompt from stdin). `--session <id>` continues a session, `--output-format json` (or `--json`) prints `{result, session_id, usage, ...}`, `--output-format stream-json` prints one JSON event per line (`init`, `assistant`, `tool_call`, `tool_result`, `usage`, `error`, then `result`), `-q` hides progress, `--permission-mode ask\|allowlist\|auto\|plan`. `--max-turns N` stops after N model calls (exit code 1). `--allowed-tools` (comma-separated or repeated) runs matching calls without asking in any mode, in the `permissions.allow` syntax (`"npm test"`, `web_fetch:docs.python.org`) or a tool name for every call of it (`write_file`, `bash_command`). Without a terminal, other calls that need approval are denied |
|
|
199
203
|
| `dostuff mcp list` | Show MCP servers and the file each comes from |
|
|
200
204
|
| `dostuff mcp add <name> [-e K=V] -- <command> [args...]` | Add a stdio server; `--url <url> [-H "Name: value"]` for HTTP; `--project` writes `./.dostuff/mcp_config.json` |
|
|
201
205
|
| `dostuff mcp remove <name> [--project]` | Remove a server |
|
|
@@ -209,23 +213,39 @@ In the TUI:
|
|
|
209
213
|
| Key / command | Action |
|
|
210
214
|
| ------------- | ----------------------------------- |
|
|
211
215
|
| `Enter` | Submit message |
|
|
216
|
+
| `/` | Open the command menu (type to filter, `Tab` completes, `Enter` runs) |
|
|
217
|
+
| `!<command>` | Run a shell command directly (no approval); the command and its output are shown to the model on the next turn |
|
|
218
|
+
| `# <note>` | Add `- <note>` to `AGENTS.md`: you pick this project's or the global one (`~/.dostuff/AGENTS.md`); the agent follows it from the next message |
|
|
212
219
|
| `Shift+Enter` | Insert a newline (multi-line input). If your terminal sends it as plain Enter, use `\` then `Enter`, `Ctrl+Enter`, `Alt+Enter` or `Ctrl+J` |
|
|
213
220
|
| `@path` | Attach a file (numbered lines) or a folder listing to the message. Typing `@` lists matching project paths: `Tab` / `Enter` completes, a folder opens for the next part. `@"a b.txt"` for spaces. Also works with `dostuff -p`. `.env` files and binaries are never attached |
|
|
214
221
|
| `Tab` | While typing a slash command, accept the dim ghost text after the cursor: the rest of the command name, then its flag (`/model ` → `--active`, `/fork ` → `--worktree`). `Right` accepts it too |
|
|
215
222
|
| Paste | A paste over 10 lines (`ui.paste_collapse_lines`) or 2,000 chars shows as `[Pasted text #1 +243 lines]` and is expanded when you send it. Over 200 lines (`loop.paste_file_lines`) it's saved to `.dostuff/pastes/` and the model reads it from there, so it doesn't fill the context; files are removed after `loop.paste_retention_days` (7) |
|
|
216
223
|
| `Up` / `Down` | On the first / last line of the input: previous / next prompt typed in this directory (saved in `~/.dostuff/data/prompt_history.jsonl`) |
|
|
224
|
+
| `Ctrl+R` | Search the prompts typed in this directory (type to filter, `Enter` puts the prompt in the input) |
|
|
225
|
+
| `Esc` `Esc` | With an empty input: take back your last prompt. It and everything after it (answer, tool calls) leave the conversation and the prompt goes back in the input to edit and resend. Files that turn changed stay as they are; `/undo` restores them |
|
|
217
226
|
| `Ctrl+O` | Expand / collapse every truncated tool and shell result (click one to toggle just that one) |
|
|
227
|
+
| `Shift+Tab` | Cycle the permission mode for this session: ask → auto → plan → allowlist (shown in the status bar) |
|
|
228
|
+
| `Ctrl+Backspace` / `Ctrl+W` / `Alt+Backspace` | Delete the previous word; `Ctrl+Delete` / `Alt+Delete` the next one |
|
|
218
229
|
| `/exit` | Save the session and quit |
|
|
219
230
|
| `/clear` | Start a new session; the old one stays resumable |
|
|
220
231
|
| `/resume [<id>]` | Pick another session from this directory (or switch to the given one) |
|
|
232
|
+
| `/fork [title] [--worktree]` | Copy this session into a new one and switch to it; the original is unchanged |
|
|
233
|
+
| `/worktree [name]` / `/worktree exit` | Move the session into a new git worktree on branch `dostuff/<name>` / leave it (removed if unchanged, otherwise keep or remove) |
|
|
234
|
+
| `/permissions [mode]` | Show or change the permission mode for this session (`ask`, `allowlist`, `auto`, `plan`) |
|
|
235
|
+
| `/copy` | Copy the model's last answer to the clipboard |
|
|
236
|
+
| `/notifications [on\|off\|bell\|osc9]` | Turn turn-finished / approval notifications on or off for this session (default from `ui.notifications`) |
|
|
221
237
|
| `/model [<provider/model>] [--active]` | Pick a model: your saved ones (`models:` in config.yaml) first, then "More <provider> models…" for each provider's list (type to filter; Enter on no match uses what you typed). A model that isn't saved yet is added to `~/.dostuff/config.yaml`. A plain `/model` switch lasts only for this session; add `--active` (e.g. `/model --active`, or `/model anthropic/claude-sonnet-5-5 --active`) to make it the default that new sessions start with |
|
|
222
238
|
| `/config [mcp] [project]` | Edit a settings file right in the TUI: pick `config.yaml` or the MCP servers, user (`~/.dostuff`) or project (`./.dostuff`), or name one (`/config mcp project`). `Ctrl+S` checks the file, saves it and applies it without a restart (an invalid file stays open with the error); `Esc` closes, twice if there are unsaved changes. A new file starts with every option commented out. `.env` files aren't offered |
|
|
223
239
|
| `/status` | Session, directory, model, permission mode, tokens, context use, MCP servers |
|
|
240
|
+
| `/context` | What fills the context window: system prompt, tools, MCP tools, project instructions, compaction summary and messages, with tokens, % and a bar |
|
|
241
|
+
| `/memory [project\|global]` | Edit `AGENTS.md` (this project's or `~/.dostuff/AGENTS.md`) in the same editor as `/config`; `Ctrl+S` saves and the agent follows it from the next message |
|
|
242
|
+
| `/doctor` | The `dostuff doctor` checks (config, API key, MCP config, memory), with a fix for each problem |
|
|
224
243
|
| `/<skill> [args]` | Run a skill: every discovered skill is a command (listed in the `/` menu and `/help`). See [Skills](#skills) |
|
|
244
|
+
| `/<command> [args]` | Run a custom command from `.dostuff/commands/` or `~/.dostuff/commands/`. See [Custom commands](#custom-commands) |
|
|
225
245
|
| `/rename <title>` | Name this session (shown by `dostuff sessions`) |
|
|
226
246
|
| `/export [<path>]` | Save this session as Markdown (default `dostuff-session-<id>.md`) |
|
|
227
247
|
| `/undo [force]` | Revert the agent's file changes from its last file-editing turn |
|
|
228
|
-
| `/compact` | Manually trigger context compaction |
|
|
248
|
+
| `/compact` | Manually trigger context compaction; `/compact auto <1-100\|off>` sets the auto-compaction threshold for this session |
|
|
229
249
|
| `/memories` | List the facts saved about you (and where each came from) |
|
|
230
250
|
| `/episodes` | List saved episodes (decisions, corrections, fixes) recalled here, newest first |
|
|
231
251
|
| `/forget <key or id>` | Delete a saved fact (by key) or episode (by the id shown in `/episodes`) |
|
|
@@ -235,14 +255,15 @@ In the TUI:
|
|
|
235
255
|
|
|
236
256
|
**Visual elements:**
|
|
237
257
|
|
|
238
|
-
- **
|
|
239
|
-
- **
|
|
240
|
-
- **
|
|
241
|
-
- **Confirmations** — yellow background (respond `y` = allow once, `a` = always this session, anything else = deny)
|
|
258
|
+
- **Messages** — `>` for your prompts (on a grey band), `●` for agent replies and tool calls, `⎿` for tool results; the terminal background shows through
|
|
259
|
+
- **Approvals** — a selector (arrows, a number, or `y` = allow once, `a` = always this session, `n` = deny with an optional note); several calls in one response can be approved together
|
|
260
|
+
- **Turn summary** — `✻ Worked for 1m 5s · $0.01 · done 12:59 PM` after each turn
|
|
242
261
|
- **Diffs** — `write_file` / `edit_file` changes shown as a coloured diff
|
|
243
262
|
- **Errors** — red background
|
|
244
263
|
- **Status bar** — `cwd • model • permission mode • context usage %` by default; `help`, `session`, `tokens` and `cost` can be added. Choose and order the items with `ui.status_bar` in `config.yaml`; when the terminal is too narrow (or zoomed in), long items are shortened and the least important dropped (help, session, cwd, tokens, cost, model, context, mode) instead of being cut off
|
|
245
264
|
- **Loading** — bold `Working...` with a live elapsed timer and queued-prompt count, or streamed thoughts displayed live
|
|
265
|
+
- **Terminal title** — the tab / window title shows the run status: `⏳ dostuff · <folder>` while working, `✋` while an approval waits, `✓` when done; the old title comes back on exit. `ui.terminal_title: false` turns it off
|
|
266
|
+
- **Notifications** (off by default) — `ui.notifications: bell` (terminal bell) or `osc9` (desktop notification in iTerm2, WezTerm, Ghostty, kitty …) when a turn finishes or an approval is waiting, if it took longer than `ui.notify_after_seconds` (30) or the terminal is in the background. `/notifications` switches it per session
|
|
246
267
|
|
|
247
268
|
---
|
|
248
269
|
|
|
@@ -265,6 +286,9 @@ In the TUI:
|
|
|
265
286
|
- `ask` (default) — as in the table above.
|
|
266
287
|
- `allowlist` — as `ask`, plus the patterns in `permissions.allow` run without asking (a shell command prefix such as `npm test`, a tool name such as `write_file`, `call_mcp_tool:<server>__<tool>`, `web_fetch:<domain>`, or `web_search`).
|
|
267
288
|
- `auto` — nothing asks. A red warning is shown at startup.
|
|
289
|
+
- `plan` — read-only: reads and read-only shell commands run; file changes, other shell commands and settings changes are denied with a "plan mode" note, and the model is told to investigate and answer with a plan. Web and MCP calls ask as in `ask`.
|
|
290
|
+
|
|
291
|
+
In the TUI, `Shift+Tab` cycles the mode for the session (ask → auto → plan → allowlist); `/permissions <mode>` picks one.
|
|
268
292
|
|
|
269
293
|
Answering `a` (always) approves that tool, or for the shell those commands, for the rest of the session.
|
|
270
294
|
|
|
@@ -333,7 +357,7 @@ memory:
|
|
|
333
357
|
episodic_scope: project # recall past episodes from this directory (project) or anywhere (user)
|
|
334
358
|
|
|
335
359
|
permissions:
|
|
336
|
-
mode: ask # ask | allowlist | auto
|
|
360
|
+
mode: ask # ask | allowlist | auto | plan
|
|
337
361
|
allow: []
|
|
338
362
|
```
|
|
339
363
|
|
|
@@ -367,10 +391,12 @@ The model resolution maps model names (using [litellm format](https://docs.litel
|
|
|
367
391
|
| Provider | Example Model name | API key env |
|
|
368
392
|
| --------- | -------------------------------------- | ------------------- |
|
|
369
393
|
| OpenAI | `openai/gpt-4o-mini` | `OPENAI_API_KEY` |
|
|
370
|
-
| Anthropic | `anthropic/claude-
|
|
394
|
+
| Anthropic | `anthropic/claude-sonnet-5-5` | `ANTHROPIC_API_KEY` |
|
|
371
395
|
| Gemini | `gemini/gemini-3.1-flash-lite` | `GEMINI_API_KEY` |
|
|
372
396
|
| Groq | `groq/llama-3.1-70b-versatile` | `GROQ_API_KEY` |
|
|
373
397
|
| Ollama | `ollama/llama3.1` | _(none)_ |
|
|
398
|
+
| OpenCode Zen | `opencode/claude-sonnet-5-5` | `OPENCODE_API_KEY` |
|
|
399
|
+
| OpenCode Go | `opencode-go/kimi-k3` | `OPENCODE_API_KEY` |
|
|
374
400
|
|
|
375
401
|
If `name` has no `/`, the provider prefix is dynamically inferred from the model name prefix or configured `provider` fields.
|
|
376
402
|
|
|
@@ -382,7 +408,9 @@ dostuff models add anthropic/claude-sonnet-5-5 # add it (pick it with
|
|
|
382
408
|
dostuff models add groq/llama-3.3-70b-versatile --active # add it and make it the default
|
|
383
409
|
```
|
|
384
410
|
|
|
385
|
-
or `/model` inside the TUI. Model lists come from litellm's catalog (chat models, without dated snapshots that have an alias), from OpenRouter's public model
|
|
411
|
+
or `/model` inside the TUI. Model lists come from litellm's catalog (chat models, without dated snapshots that have an alias), from OpenRouter's and OpenCode's public model lists, and for Ollama from the models you've pulled (the server must be running). A name that isn't listed still works. Then put the provider's key in `~/.dostuff/.env`. A project's `./.dostuff/config.yaml` with its own `models:` list replaces the global list in that directory.
|
|
412
|
+
|
|
413
|
+
OpenCode models (`opencode/<id>` for Zen, `opencode-go/<id>` for a Go subscription) use the ids from the [OpenCode docs](https://opencode.ai/docs/zen/). litellm has no OpenCode provider, so DoStuff sends each model to the gateway endpoint for its family: Claude models (and a few Qwen / MiniMax models) to the Anthropic Messages endpoint, GPT / Grok / Muse models to the Responses endpoint, Gemini models to the Gemini endpoint, and all other models to chat completions. One console key in `OPENCODE_API_KEY` works for Zen and Go. OpenCode only allows its free models from its own app, so use paid models or Go.
|
|
386
414
|
|
|
387
415
|
---
|
|
388
416
|
|
|
@@ -452,7 +480,8 @@ added to the system prompt, most general first, so the closest one wins where th
|
|
|
452
480
|
1. `~/.dostuff/AGENTS.md` — your instructions for every project
|
|
453
481
|
2. one per folder from the top of the path down to the current directory (e.g. the repo root, then a sub-package)
|
|
454
482
|
|
|
455
|
-
In a folder with both, `AGENTS.md` is used. They're read once at startup
|
|
483
|
+
In a folder with both, `AGENTS.md` is used. They're read once at startup, and again after you change
|
|
484
|
+
one from the TUI: `# <note>` adds a line to this project's or the global file, and `/memory` opens one in an editor.
|
|
456
485
|
|
|
457
486
|
---
|
|
458
487
|
|
|
@@ -470,8 +499,6 @@ Skills are directories containing a `SKILL.md` (frontmatter with `name` and `des
|
|
|
470
499
|
|
|
471
500
|
**Conflict resolution:** No deduplication in the system prompt. If two skills share the same name (from different directories), both are loaded and passed to the model — the agent may see the same skill twice with different `location` paths. To avoid confusion, keep names unique across the search paths.
|
|
472
501
|
|
|
473
|
-
**Running a skill:** every skill is also a slash command, `/<name> [args]` (shown in the `/` menu marked `(skill)` and in `/help`). It runs a turn with the skill's `SKILL.md` body plus your arguments; `@mentions` in the arguments are expanded. Also works headless: `dostuff -p "/my-skill fix the tests"`. Built-in commands win a name clash, the first skill found (in the order above) wins between skills, and names with spaces get no command.
|
|
474
|
-
|
|
475
502
|
**Example structure:**
|
|
476
503
|
|
|
477
504
|
```text
|
|
@@ -493,10 +520,28 @@ description: One-line description of what this skill does
|
|
|
493
520
|
Detailed instructions for the agent go here.
|
|
494
521
|
```
|
|
495
522
|
|
|
496
|
-
**Running a skill yourself:** each skill is also a slash command, `/<name> [arguments]` (e.g. `/my-skill src/app.py`), in the TUI and with `dostuff -p "/my-skill ..."`. The turn's message is the skill's `SKILL.md` body plus your arguments (which can use `@path` mentions), so the model follows it straight away instead of deciding whether to read it. Built-in commands win a name clash, and names with spaces can't be run this way; the model can still use those skills on its own.
|
|
523
|
+
**Running a skill yourself:** each skill is also a slash command, `/<name> [arguments]` (e.g. `/my-skill src/app.py`), in the TUI and with `dostuff -p "/my-skill ..."`. The turn's message is the skill's `SKILL.md` body plus your arguments (which can use `@path` mentions), so the model follows it straight away instead of deciding whether to read it. The command shows in the `/` menu marked `(skill)` and in `/help`. Built-in commands win a name clash, the first skill found (in the order above) wins between skills, and names with spaces can't be run this way; the model can still use those skills on its own.
|
|
497
524
|
|
|
498
525
|
Run `dostuff init` to bootstrap a local `.dostuff/skills/` folder. Restart the agent after adding new skills.
|
|
499
526
|
|
|
527
|
+
### Custom commands
|
|
528
|
+
|
|
529
|
+
A Markdown file in `.dostuff/commands/` (this project) or `~/.dostuff/commands/` (every project) is a slash
|
|
530
|
+
command named after the file: `.dostuff/commands/review.md` is `/review`. Running `/review src/app.py` sends the
|
|
531
|
+
file's text as your message, with `$ARGUMENTS` replaced by `src/app.py` (with no `$ARGUMENTS` in the file, the
|
|
532
|
+
arguments are added at the end). An optional frontmatter `description:` is shown in the `/` menu, otherwise the
|
|
533
|
+
first line is. Works in the TUI and with `dostuff -p "/review src/app.py"`.
|
|
534
|
+
|
|
535
|
+
```markdown
|
|
536
|
+
---
|
|
537
|
+
description: Review a file for bugs
|
|
538
|
+
---
|
|
539
|
+
Review $ARGUMENTS for bugs and missing tests. List problems by severity.
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Built-in commands win a name clash, then project commands, then user commands, then skills. Restart dostuff
|
|
543
|
+
after adding a command.
|
|
544
|
+
|
|
500
545
|
---
|
|
501
546
|
|
|
502
547
|
## Sessions and memory
|
|
@@ -599,23 +644,31 @@ dostuff/
|
|
|
599
644
|
├── helpers/ # sub-modules for agent, mcp, memory, skills, tools, ui
|
|
600
645
|
│ ├── agent/ # state, exit handlers, system prompts, token limit utilities
|
|
601
646
|
│ ├── mcp/ # config loading, oauth
|
|
602
|
-
│ ├── memory/ #
|
|
647
|
+
│ ├── memory/ # memory resolver, session export, shell steps
|
|
603
648
|
│ ├── skills/ # skill discovery logic
|
|
604
649
|
│ ├── tools/ # schemas and path resolution
|
|
605
650
|
│ └── ui/ # event emission shims
|
|
606
651
|
├── lib/ # core logic
|
|
652
|
+
│ ├── checkpoints.py # per-turn file checkpoints for /undo
|
|
607
653
|
│ ├── exceptions.py # validation, confirmation, and workflow exceptions
|
|
608
654
|
│ ├── mcp/ # mcp transport client & local registrations
|
|
609
655
|
│ ├── memory/ # semantic, episodic, and session stores
|
|
610
656
|
│ ├── model.py # model and provider resolution
|
|
611
|
-
│
|
|
657
|
+
│ ├── tracing.py # opentelemetry tracing bootstrap
|
|
658
|
+
│ └── worktree.py # git worktree create / exit / cleanup
|
|
612
659
|
├── memory/ # DB management
|
|
613
660
|
│ └── __init__.py # DB initiation exports
|
|
614
661
|
├── tools/ # defined tools
|
|
615
662
|
│ ├── bash/ # terminal command execution tools
|
|
616
663
|
│ ├── files/ # read, write, edit, delete, list
|
|
617
664
|
│ ├── search/ # grep and glob (pure Python, default excludes)
|
|
618
|
-
│
|
|
665
|
+
│ ├── mcp/ # mcp tool search, detail, and execution wrappers
|
|
666
|
+
│ ├── memory/ # save_memory / save_episode
|
|
667
|
+
│ ├── settings.py # read_settings, edit_config, set/remove_mcp_server
|
|
668
|
+
│ ├── web_fetch.py # read a URL as text
|
|
669
|
+
│ ├── web_search.py # free web search (SearXNG / ddgs / DuckDuckGo)
|
|
670
|
+
│ ├── todo_write.py # visible task list
|
|
671
|
+
│ └── delegate_to_subagent.py # bounded subagents (optionally in a worktree)
|
|
619
672
|
├── cli.py # CLI typer entrypoints and doctor checkup utilities
|
|
620
673
|
├── cli_tui.py # Textual TUI Application and adapter translates state
|
|
621
674
|
├── config.py # layered config loader supporting project/global yaml and multi-model configuration
|
|
@@ -631,3 +684,5 @@ dostuff/
|
|
|
631
684
|
- **Author:** [varun](mailto:varunkumawatleap2@gmail.com)
|
|
632
685
|
- **Repository:** https://github.com/kVarunkk/DoStuff
|
|
633
686
|
- **Issues:** https://github.com/kVarunkk/DoStuff/issues
|
|
687
|
+
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
|
|
688
|
+
- **PyPI:** https://pypi.org/project/dostuff/
|
|
@@ -25,26 +25,28 @@ DoStuff is a terminal AI agent that runs anywhere `pip` runs. It gives you a ful
|
|
|
25
25
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
|
-
- **Textual TUI** with
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
28
|
+
- **Textual TUI** with a `/` command menu, `@file` completion, `!shell` commands, an in-app config editor, a configurable status bar and a live turn timer
|
|
29
|
+
- **Headless mode** — `dostuff -p "<prompt>"` runs one prompt and prints the answer (`--output-format json|stream-json`, `--max-turns`, `--allowed-tools` for scripts and CI)
|
|
30
|
+
- **Multi-provider LLMs** via [litellm](https://docs.litellm.ai/docs/providers) — OpenAI, Anthropic, Gemini, Groq, Mistral, Ollama, OpenRouter, OpenCode Zen / Go
|
|
31
|
+
- **Persistent sessions** in SQLite; resume with `dostuff -c`, `dostuff resume` or `dostuff --session <id>`, branch one off with `/fork`
|
|
32
|
+
- **Git worktrees** — `/worktree` or `dostuff -w` runs a session on its own branch and checkout; subagents can run in their own worktree too
|
|
31
33
|
- **Long-term memory** (semantic + episodic) backed by ChromaDB — optional, `pip install "dostuff[memory]"`
|
|
32
34
|
- **MCP server support** — stdio (npx, uvx) and HTTP transports
|
|
33
35
|
- **`@file` mentions** — type `@` in the prompt to pick a file or folder; its content (or listing) is sent with the message
|
|
34
36
|
- **Project instructions** — `AGENTS.md` / `CLAUDE.md` from `~/.dostuff/`, the repo root and every folder down to the current one, combined
|
|
35
37
|
- **Coding tools** — `read_file` (line numbers, offset/limit), `edit_file` (exact replacement), `write_file`, `grep`, `glob`, `list_files`, `delete_file`, `bash_command`, `web_fetch` (read a URL as text), `web_search` (free, no API key)
|
|
36
|
-
- **Permission layer** — mutating tool calls ask for approval (
|
|
38
|
+
- **Permission layer** — mutating tool calls ask for approval (allow once / always this session / deny with a note); read-only shell commands run without asking; modes `ask` / `allowlist` / `auto`; `/undo` reverts the agent's file changes
|
|
37
39
|
- **File sandbox** — file tools stay inside the project directory and never read `.env*` files or `~/.dostuff/`
|
|
38
40
|
- **Skills loader** — drop a `SKILL.md` in the right folder, restart, done; run one with `/<skill-name> [args]`
|
|
39
41
|
- **Subagents** — `delegate_to_subagent` runs a bounded task with a restricted tool set; its approval prompts and ESC go through the same TUI
|
|
40
42
|
- **Per-tool timeout** (120s) to prevent hung servers; long tool output is truncated (head + tail) before it reaches the model
|
|
41
43
|
- **Retries with backoff** for rate limits, timeouts and 5xx errors (6 by default, exponential with jitter, honors `Retry-After`; `loop.max_retries` / `loop.retry_max_delay`); auth / bad-request errors fail fast
|
|
42
|
-
- **Token and cost tracking** — per-turn and cumulative totals in `/status` and the line after each turn (`✻ Worked for 1m 5s · $0.01`); cost in USD from litellm's price table (hidden when the model has no known price)
|
|
44
|
+
- **Token and cost tracking** — per-turn and cumulative totals in `/status` and the line after each turn (`✻ Worked for 1m 5s · $0.01`); cost in USD from litellm's price table (hidden when the model has no known price). The table bundled with litellm is used, so startup doesn't wait on a download; set `LITELLM_LOCAL_MODEL_COST_MAP=False` to fetch the latest one from GitHub instead
|
|
43
45
|
- **Long-term memory tools** — the agent saves facts (`save_memory`) and notable moments (`save_episode`) as they come up; both are recalled in later sessions
|
|
44
46
|
- **Graceful exit** — `Ctrl+Q` or `/exit` saves the session, cleans up, and stops background workers
|
|
45
47
|
- **Clean Cancellation** — `Escape` can cancel in-flight agent turns cleanly without corrupting the session
|
|
46
48
|
- **2-state session split** — `session_steps` (full audit) / `working_history` (LLM payload); DB persists both plus `compaction_notes` + `last_input_tokens`
|
|
47
|
-
- **Auto & Manual Compaction** — Manual `/compact` runs compaction and saves it. Auto-compaction triggers automatically during the agent loop if context usage (`last_input_tokens`) exceeds 50% of the model's token limit. It keeps at least 15% or 20k tokens of the most recent steps in the working history, summarizing the rest into `compaction_notes` which are appended to system instructions.
|
|
49
|
+
- **Auto & Manual Compaction** — Manual `/compact` runs compaction and saves it. Auto-compaction triggers automatically during the agent loop if context usage (`last_input_tokens`) exceeds `loop.auto_compact_threshold` (default 50%) of the model's token limit; `off` disables it (an overflowing window is still compacted), and `/compact auto <N|off>` changes it for the session. It keeps at least 15% or 20k tokens of the most recent steps in the working history, summarizing the rest into `compaction_notes` which are appended to system instructions.
|
|
48
50
|
- **Tracing (opt-in)** — OTLP tracing support built into `lib/tracing.py`; prompt and tool content are redacted from spans by default
|
|
49
51
|
|
|
50
52
|
---
|
|
@@ -80,8 +82,8 @@ pipx install dostuff
|
|
|
80
82
|
For development (editable mode, from a clone):
|
|
81
83
|
|
|
82
84
|
```bash
|
|
83
|
-
git clone https://github.com
|
|
84
|
-
cd
|
|
85
|
+
git clone https://github.com/kVarunkk/DoStuff.git
|
|
86
|
+
cd DoStuff
|
|
85
87
|
pip install -e . # core
|
|
86
88
|
pip install -e ".[memory]" # + long-term memory (chromadb)
|
|
87
89
|
pip install -e ".[full]" # + memory + onnxruntime + grpcio
|
|
@@ -136,17 +138,19 @@ In the TUI:
|
|
|
136
138
|
| `dostuff` | Launch the interactive TUI |
|
|
137
139
|
| `dostuff --version` | Print the version (`-V`) |
|
|
138
140
|
| `dostuff --session <id>` | Resume a prior session (asks before starting a new one if the ID is unknown) |
|
|
141
|
+
| `dostuff -c` / `--continue` | Resume the latest session in the current directory (same as `dostuff resume`; works with `-p` too) |
|
|
142
|
+
| `dostuff -w` / `--worktree-name <name>` | Start the session in a new git worktree (`.dostuff/worktrees/<name>`, branch `dostuff/<name>`) |
|
|
139
143
|
| `dostuff init [--force]` | Create `.dostuff/` config/skills in current dir (won't overwrite without `--force`) |
|
|
140
144
|
| `dostuff setup` | Pick a model, save its API key, write `~/.dostuff/config.yaml` (runs automatically on first launch) |
|
|
141
145
|
| `dostuff config` | Show resolved config paths and values |
|
|
142
146
|
| `dostuff doctor` | Health check: config, API key, MCP, data dir; prints a fix for each problem |
|
|
143
|
-
| `dostuff resume [<id>]` | Resume the latest session started in the current directory (or the given one; a unique ID prefix is enough) |
|
|
147
|
+
| `dostuff resume [<id>]` | Resume the latest session started in the current directory (or the given one; a unique ID prefix is enough). `--fork` resumes a copy, `--worktree` moves it into a new worktree |
|
|
144
148
|
| `dostuff sessions [--all] [-n N]` | List sessions in the current directory with their title or first prompt (`--all`: every directory) |
|
|
145
149
|
| `dostuff sessions rename <id> <title>` | Name a session |
|
|
146
150
|
| `dostuff sessions rm <id>... [-y]` | Delete sessions and their `/undo` checkpoints |
|
|
147
151
|
| `dostuff sessions prune [--older-than 30d] [--dry-run] [-y]` | Delete empty sessions, and sessions not used for the given time (`45m`, `12h`, `30d`, `2w`) |
|
|
148
152
|
| `dostuff export [<id>] [-o file\|-]` | Save a session (default: latest here) as Markdown: prompts, answers, tool calls and results |
|
|
149
|
-
| `dostuff -p "<prompt>"` | Headless: run one prompt, print the answer to stdout, exit. Progress goes to stderr. Piped stdin is appended to the prompt (`-p -` reads the prompt from stdin). `--session <id>` continues a session, `--json` prints `{result, session_id, usage, ...}`, `-q` hides progress, `--permission-mode ask\|allowlist\|auto`. Without a terminal, calls that need approval are denied |
|
|
153
|
+
| `dostuff -p "<prompt>"` | Headless: run one prompt, print the answer to stdout, exit. Progress goes to stderr. Piped stdin is appended to the prompt (`-p -` reads the prompt from stdin). `--session <id>` continues a session, `--output-format json` (or `--json`) prints `{result, session_id, usage, ...}`, `--output-format stream-json` prints one JSON event per line (`init`, `assistant`, `tool_call`, `tool_result`, `usage`, `error`, then `result`), `-q` hides progress, `--permission-mode ask\|allowlist\|auto\|plan`. `--max-turns N` stops after N model calls (exit code 1). `--allowed-tools` (comma-separated or repeated) runs matching calls without asking in any mode, in the `permissions.allow` syntax (`"npm test"`, `web_fetch:docs.python.org`) or a tool name for every call of it (`write_file`, `bash_command`). Without a terminal, other calls that need approval are denied |
|
|
150
154
|
| `dostuff mcp list` | Show MCP servers and the file each comes from |
|
|
151
155
|
| `dostuff mcp add <name> [-e K=V] -- <command> [args...]` | Add a stdio server; `--url <url> [-H "Name: value"]` for HTTP; `--project` writes `./.dostuff/mcp_config.json` |
|
|
152
156
|
| `dostuff mcp remove <name> [--project]` | Remove a server |
|
|
@@ -160,23 +164,39 @@ In the TUI:
|
|
|
160
164
|
| Key / command | Action |
|
|
161
165
|
| ------------- | ----------------------------------- |
|
|
162
166
|
| `Enter` | Submit message |
|
|
167
|
+
| `/` | Open the command menu (type to filter, `Tab` completes, `Enter` runs) |
|
|
168
|
+
| `!<command>` | Run a shell command directly (no approval); the command and its output are shown to the model on the next turn |
|
|
169
|
+
| `# <note>` | Add `- <note>` to `AGENTS.md`: you pick this project's or the global one (`~/.dostuff/AGENTS.md`); the agent follows it from the next message |
|
|
163
170
|
| `Shift+Enter` | Insert a newline (multi-line input). If your terminal sends it as plain Enter, use `\` then `Enter`, `Ctrl+Enter`, `Alt+Enter` or `Ctrl+J` |
|
|
164
171
|
| `@path` | Attach a file (numbered lines) or a folder listing to the message. Typing `@` lists matching project paths: `Tab` / `Enter` completes, a folder opens for the next part. `@"a b.txt"` for spaces. Also works with `dostuff -p`. `.env` files and binaries are never attached |
|
|
165
172
|
| `Tab` | While typing a slash command, accept the dim ghost text after the cursor: the rest of the command name, then its flag (`/model ` → `--active`, `/fork ` → `--worktree`). `Right` accepts it too |
|
|
166
173
|
| Paste | A paste over 10 lines (`ui.paste_collapse_lines`) or 2,000 chars shows as `[Pasted text #1 +243 lines]` and is expanded when you send it. Over 200 lines (`loop.paste_file_lines`) it's saved to `.dostuff/pastes/` and the model reads it from there, so it doesn't fill the context; files are removed after `loop.paste_retention_days` (7) |
|
|
167
174
|
| `Up` / `Down` | On the first / last line of the input: previous / next prompt typed in this directory (saved in `~/.dostuff/data/prompt_history.jsonl`) |
|
|
175
|
+
| `Ctrl+R` | Search the prompts typed in this directory (type to filter, `Enter` puts the prompt in the input) |
|
|
176
|
+
| `Esc` `Esc` | With an empty input: take back your last prompt. It and everything after it (answer, tool calls) leave the conversation and the prompt goes back in the input to edit and resend. Files that turn changed stay as they are; `/undo` restores them |
|
|
168
177
|
| `Ctrl+O` | Expand / collapse every truncated tool and shell result (click one to toggle just that one) |
|
|
178
|
+
| `Shift+Tab` | Cycle the permission mode for this session: ask → auto → plan → allowlist (shown in the status bar) |
|
|
179
|
+
| `Ctrl+Backspace` / `Ctrl+W` / `Alt+Backspace` | Delete the previous word; `Ctrl+Delete` / `Alt+Delete` the next one |
|
|
169
180
|
| `/exit` | Save the session and quit |
|
|
170
181
|
| `/clear` | Start a new session; the old one stays resumable |
|
|
171
182
|
| `/resume [<id>]` | Pick another session from this directory (or switch to the given one) |
|
|
183
|
+
| `/fork [title] [--worktree]` | Copy this session into a new one and switch to it; the original is unchanged |
|
|
184
|
+
| `/worktree [name]` / `/worktree exit` | Move the session into a new git worktree on branch `dostuff/<name>` / leave it (removed if unchanged, otherwise keep or remove) |
|
|
185
|
+
| `/permissions [mode]` | Show or change the permission mode for this session (`ask`, `allowlist`, `auto`, `plan`) |
|
|
186
|
+
| `/copy` | Copy the model's last answer to the clipboard |
|
|
187
|
+
| `/notifications [on\|off\|bell\|osc9]` | Turn turn-finished / approval notifications on or off for this session (default from `ui.notifications`) |
|
|
172
188
|
| `/model [<provider/model>] [--active]` | Pick a model: your saved ones (`models:` in config.yaml) first, then "More <provider> models…" for each provider's list (type to filter; Enter on no match uses what you typed). A model that isn't saved yet is added to `~/.dostuff/config.yaml`. A plain `/model` switch lasts only for this session; add `--active` (e.g. `/model --active`, or `/model anthropic/claude-sonnet-5-5 --active`) to make it the default that new sessions start with |
|
|
173
189
|
| `/config [mcp] [project]` | Edit a settings file right in the TUI: pick `config.yaml` or the MCP servers, user (`~/.dostuff`) or project (`./.dostuff`), or name one (`/config mcp project`). `Ctrl+S` checks the file, saves it and applies it without a restart (an invalid file stays open with the error); `Esc` closes, twice if there are unsaved changes. A new file starts with every option commented out. `.env` files aren't offered |
|
|
174
190
|
| `/status` | Session, directory, model, permission mode, tokens, context use, MCP servers |
|
|
191
|
+
| `/context` | What fills the context window: system prompt, tools, MCP tools, project instructions, compaction summary and messages, with tokens, % and a bar |
|
|
192
|
+
| `/memory [project\|global]` | Edit `AGENTS.md` (this project's or `~/.dostuff/AGENTS.md`) in the same editor as `/config`; `Ctrl+S` saves and the agent follows it from the next message |
|
|
193
|
+
| `/doctor` | The `dostuff doctor` checks (config, API key, MCP config, memory), with a fix for each problem |
|
|
175
194
|
| `/<skill> [args]` | Run a skill: every discovered skill is a command (listed in the `/` menu and `/help`). See [Skills](#skills) |
|
|
195
|
+
| `/<command> [args]` | Run a custom command from `.dostuff/commands/` or `~/.dostuff/commands/`. See [Custom commands](#custom-commands) |
|
|
176
196
|
| `/rename <title>` | Name this session (shown by `dostuff sessions`) |
|
|
177
197
|
| `/export [<path>]` | Save this session as Markdown (default `dostuff-session-<id>.md`) |
|
|
178
198
|
| `/undo [force]` | Revert the agent's file changes from its last file-editing turn |
|
|
179
|
-
| `/compact` | Manually trigger context compaction |
|
|
199
|
+
| `/compact` | Manually trigger context compaction; `/compact auto <1-100\|off>` sets the auto-compaction threshold for this session |
|
|
180
200
|
| `/memories` | List the facts saved about you (and where each came from) |
|
|
181
201
|
| `/episodes` | List saved episodes (decisions, corrections, fixes) recalled here, newest first |
|
|
182
202
|
| `/forget <key or id>` | Delete a saved fact (by key) or episode (by the id shown in `/episodes`) |
|
|
@@ -186,14 +206,15 @@ In the TUI:
|
|
|
186
206
|
|
|
187
207
|
**Visual elements:**
|
|
188
208
|
|
|
189
|
-
- **
|
|
190
|
-
- **
|
|
191
|
-
- **
|
|
192
|
-
- **Confirmations** — yellow background (respond `y` = allow once, `a` = always this session, anything else = deny)
|
|
209
|
+
- **Messages** — `>` for your prompts (on a grey band), `●` for agent replies and tool calls, `⎿` for tool results; the terminal background shows through
|
|
210
|
+
- **Approvals** — a selector (arrows, a number, or `y` = allow once, `a` = always this session, `n` = deny with an optional note); several calls in one response can be approved together
|
|
211
|
+
- **Turn summary** — `✻ Worked for 1m 5s · $0.01 · done 12:59 PM` after each turn
|
|
193
212
|
- **Diffs** — `write_file` / `edit_file` changes shown as a coloured diff
|
|
194
213
|
- **Errors** — red background
|
|
195
214
|
- **Status bar** — `cwd • model • permission mode • context usage %` by default; `help`, `session`, `tokens` and `cost` can be added. Choose and order the items with `ui.status_bar` in `config.yaml`; when the terminal is too narrow (or zoomed in), long items are shortened and the least important dropped (help, session, cwd, tokens, cost, model, context, mode) instead of being cut off
|
|
196
215
|
- **Loading** — bold `Working...` with a live elapsed timer and queued-prompt count, or streamed thoughts displayed live
|
|
216
|
+
- **Terminal title** — the tab / window title shows the run status: `⏳ dostuff · <folder>` while working, `✋` while an approval waits, `✓` when done; the old title comes back on exit. `ui.terminal_title: false` turns it off
|
|
217
|
+
- **Notifications** (off by default) — `ui.notifications: bell` (terminal bell) or `osc9` (desktop notification in iTerm2, WezTerm, Ghostty, kitty …) when a turn finishes or an approval is waiting, if it took longer than `ui.notify_after_seconds` (30) or the terminal is in the background. `/notifications` switches it per session
|
|
197
218
|
|
|
198
219
|
---
|
|
199
220
|
|
|
@@ -216,6 +237,9 @@ In the TUI:
|
|
|
216
237
|
- `ask` (default) — as in the table above.
|
|
217
238
|
- `allowlist` — as `ask`, plus the patterns in `permissions.allow` run without asking (a shell command prefix such as `npm test`, a tool name such as `write_file`, `call_mcp_tool:<server>__<tool>`, `web_fetch:<domain>`, or `web_search`).
|
|
218
239
|
- `auto` — nothing asks. A red warning is shown at startup.
|
|
240
|
+
- `plan` — read-only: reads and read-only shell commands run; file changes, other shell commands and settings changes are denied with a "plan mode" note, and the model is told to investigate and answer with a plan. Web and MCP calls ask as in `ask`.
|
|
241
|
+
|
|
242
|
+
In the TUI, `Shift+Tab` cycles the mode for the session (ask → auto → plan → allowlist); `/permissions <mode>` picks one.
|
|
219
243
|
|
|
220
244
|
Answering `a` (always) approves that tool, or for the shell those commands, for the rest of the session.
|
|
221
245
|
|
|
@@ -284,7 +308,7 @@ memory:
|
|
|
284
308
|
episodic_scope: project # recall past episodes from this directory (project) or anywhere (user)
|
|
285
309
|
|
|
286
310
|
permissions:
|
|
287
|
-
mode: ask # ask | allowlist | auto
|
|
311
|
+
mode: ask # ask | allowlist | auto | plan
|
|
288
312
|
allow: []
|
|
289
313
|
```
|
|
290
314
|
|
|
@@ -318,10 +342,12 @@ The model resolution maps model names (using [litellm format](https://docs.litel
|
|
|
318
342
|
| Provider | Example Model name | API key env |
|
|
319
343
|
| --------- | -------------------------------------- | ------------------- |
|
|
320
344
|
| OpenAI | `openai/gpt-4o-mini` | `OPENAI_API_KEY` |
|
|
321
|
-
| Anthropic | `anthropic/claude-
|
|
345
|
+
| Anthropic | `anthropic/claude-sonnet-5-5` | `ANTHROPIC_API_KEY` |
|
|
322
346
|
| Gemini | `gemini/gemini-3.1-flash-lite` | `GEMINI_API_KEY` |
|
|
323
347
|
| Groq | `groq/llama-3.1-70b-versatile` | `GROQ_API_KEY` |
|
|
324
348
|
| Ollama | `ollama/llama3.1` | _(none)_ |
|
|
349
|
+
| OpenCode Zen | `opencode/claude-sonnet-5-5` | `OPENCODE_API_KEY` |
|
|
350
|
+
| OpenCode Go | `opencode-go/kimi-k3` | `OPENCODE_API_KEY` |
|
|
325
351
|
|
|
326
352
|
If `name` has no `/`, the provider prefix is dynamically inferred from the model name prefix or configured `provider` fields.
|
|
327
353
|
|
|
@@ -333,7 +359,9 @@ dostuff models add anthropic/claude-sonnet-5-5 # add it (pick it with
|
|
|
333
359
|
dostuff models add groq/llama-3.3-70b-versatile --active # add it and make it the default
|
|
334
360
|
```
|
|
335
361
|
|
|
336
|
-
or `/model` inside the TUI. Model lists come from litellm's catalog (chat models, without dated snapshots that have an alias), from OpenRouter's public model
|
|
362
|
+
or `/model` inside the TUI. Model lists come from litellm's catalog (chat models, without dated snapshots that have an alias), from OpenRouter's and OpenCode's public model lists, and for Ollama from the models you've pulled (the server must be running). A name that isn't listed still works. Then put the provider's key in `~/.dostuff/.env`. A project's `./.dostuff/config.yaml` with its own `models:` list replaces the global list in that directory.
|
|
363
|
+
|
|
364
|
+
OpenCode models (`opencode/<id>` for Zen, `opencode-go/<id>` for a Go subscription) use the ids from the [OpenCode docs](https://opencode.ai/docs/zen/). litellm has no OpenCode provider, so DoStuff sends each model to the gateway endpoint for its family: Claude models (and a few Qwen / MiniMax models) to the Anthropic Messages endpoint, GPT / Grok / Muse models to the Responses endpoint, Gemini models to the Gemini endpoint, and all other models to chat completions. One console key in `OPENCODE_API_KEY` works for Zen and Go. OpenCode only allows its free models from its own app, so use paid models or Go.
|
|
337
365
|
|
|
338
366
|
---
|
|
339
367
|
|
|
@@ -403,7 +431,8 @@ added to the system prompt, most general first, so the closest one wins where th
|
|
|
403
431
|
1. `~/.dostuff/AGENTS.md` — your instructions for every project
|
|
404
432
|
2. one per folder from the top of the path down to the current directory (e.g. the repo root, then a sub-package)
|
|
405
433
|
|
|
406
|
-
In a folder with both, `AGENTS.md` is used. They're read once at startup
|
|
434
|
+
In a folder with both, `AGENTS.md` is used. They're read once at startup, and again after you change
|
|
435
|
+
one from the TUI: `# <note>` adds a line to this project's or the global file, and `/memory` opens one in an editor.
|
|
407
436
|
|
|
408
437
|
---
|
|
409
438
|
|
|
@@ -421,8 +450,6 @@ Skills are directories containing a `SKILL.md` (frontmatter with `name` and `des
|
|
|
421
450
|
|
|
422
451
|
**Conflict resolution:** No deduplication in the system prompt. If two skills share the same name (from different directories), both are loaded and passed to the model — the agent may see the same skill twice with different `location` paths. To avoid confusion, keep names unique across the search paths.
|
|
423
452
|
|
|
424
|
-
**Running a skill:** every skill is also a slash command, `/<name> [args]` (shown in the `/` menu marked `(skill)` and in `/help`). It runs a turn with the skill's `SKILL.md` body plus your arguments; `@mentions` in the arguments are expanded. Also works headless: `dostuff -p "/my-skill fix the tests"`. Built-in commands win a name clash, the first skill found (in the order above) wins between skills, and names with spaces get no command.
|
|
425
|
-
|
|
426
453
|
**Example structure:**
|
|
427
454
|
|
|
428
455
|
```text
|
|
@@ -444,10 +471,28 @@ description: One-line description of what this skill does
|
|
|
444
471
|
Detailed instructions for the agent go here.
|
|
445
472
|
```
|
|
446
473
|
|
|
447
|
-
**Running a skill yourself:** each skill is also a slash command, `/<name> [arguments]` (e.g. `/my-skill src/app.py`), in the TUI and with `dostuff -p "/my-skill ..."`. The turn's message is the skill's `SKILL.md` body plus your arguments (which can use `@path` mentions), so the model follows it straight away instead of deciding whether to read it. Built-in commands win a name clash, and names with spaces can't be run this way; the model can still use those skills on its own.
|
|
474
|
+
**Running a skill yourself:** each skill is also a slash command, `/<name> [arguments]` (e.g. `/my-skill src/app.py`), in the TUI and with `dostuff -p "/my-skill ..."`. The turn's message is the skill's `SKILL.md` body plus your arguments (which can use `@path` mentions), so the model follows it straight away instead of deciding whether to read it. The command shows in the `/` menu marked `(skill)` and in `/help`. Built-in commands win a name clash, the first skill found (in the order above) wins between skills, and names with spaces can't be run this way; the model can still use those skills on its own.
|
|
448
475
|
|
|
449
476
|
Run `dostuff init` to bootstrap a local `.dostuff/skills/` folder. Restart the agent after adding new skills.
|
|
450
477
|
|
|
478
|
+
### Custom commands
|
|
479
|
+
|
|
480
|
+
A Markdown file in `.dostuff/commands/` (this project) or `~/.dostuff/commands/` (every project) is a slash
|
|
481
|
+
command named after the file: `.dostuff/commands/review.md` is `/review`. Running `/review src/app.py` sends the
|
|
482
|
+
file's text as your message, with `$ARGUMENTS` replaced by `src/app.py` (with no `$ARGUMENTS` in the file, the
|
|
483
|
+
arguments are added at the end). An optional frontmatter `description:` is shown in the `/` menu, otherwise the
|
|
484
|
+
first line is. Works in the TUI and with `dostuff -p "/review src/app.py"`.
|
|
485
|
+
|
|
486
|
+
```markdown
|
|
487
|
+
---
|
|
488
|
+
description: Review a file for bugs
|
|
489
|
+
---
|
|
490
|
+
Review $ARGUMENTS for bugs and missing tests. List problems by severity.
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Built-in commands win a name clash, then project commands, then user commands, then skills. Restart dostuff
|
|
494
|
+
after adding a command.
|
|
495
|
+
|
|
451
496
|
---
|
|
452
497
|
|
|
453
498
|
## Sessions and memory
|
|
@@ -550,23 +595,31 @@ dostuff/
|
|
|
550
595
|
├── helpers/ # sub-modules for agent, mcp, memory, skills, tools, ui
|
|
551
596
|
│ ├── agent/ # state, exit handlers, system prompts, token limit utilities
|
|
552
597
|
│ ├── mcp/ # config loading, oauth
|
|
553
|
-
│ ├── memory/ #
|
|
598
|
+
│ ├── memory/ # memory resolver, session export, shell steps
|
|
554
599
|
│ ├── skills/ # skill discovery logic
|
|
555
600
|
│ ├── tools/ # schemas and path resolution
|
|
556
601
|
│ └── ui/ # event emission shims
|
|
557
602
|
├── lib/ # core logic
|
|
603
|
+
│ ├── checkpoints.py # per-turn file checkpoints for /undo
|
|
558
604
|
│ ├── exceptions.py # validation, confirmation, and workflow exceptions
|
|
559
605
|
│ ├── mcp/ # mcp transport client & local registrations
|
|
560
606
|
│ ├── memory/ # semantic, episodic, and session stores
|
|
561
607
|
│ ├── model.py # model and provider resolution
|
|
562
|
-
│
|
|
608
|
+
│ ├── tracing.py # opentelemetry tracing bootstrap
|
|
609
|
+
│ └── worktree.py # git worktree create / exit / cleanup
|
|
563
610
|
├── memory/ # DB management
|
|
564
611
|
│ └── __init__.py # DB initiation exports
|
|
565
612
|
├── tools/ # defined tools
|
|
566
613
|
│ ├── bash/ # terminal command execution tools
|
|
567
614
|
│ ├── files/ # read, write, edit, delete, list
|
|
568
615
|
│ ├── search/ # grep and glob (pure Python, default excludes)
|
|
569
|
-
│
|
|
616
|
+
│ ├── mcp/ # mcp tool search, detail, and execution wrappers
|
|
617
|
+
│ ├── memory/ # save_memory / save_episode
|
|
618
|
+
│ ├── settings.py # read_settings, edit_config, set/remove_mcp_server
|
|
619
|
+
│ ├── web_fetch.py # read a URL as text
|
|
620
|
+
│ ├── web_search.py # free web search (SearXNG / ddgs / DuckDuckGo)
|
|
621
|
+
│ ├── todo_write.py # visible task list
|
|
622
|
+
│ └── delegate_to_subagent.py # bounded subagents (optionally in a worktree)
|
|
570
623
|
├── cli.py # CLI typer entrypoints and doctor checkup utilities
|
|
571
624
|
├── cli_tui.py # Textual TUI Application and adapter translates state
|
|
572
625
|
├── config.py # layered config loader supporting project/global yaml and multi-model configuration
|
|
@@ -582,3 +635,5 @@ dostuff/
|
|
|
582
635
|
- **Author:** [varun](mailto:varunkumawatleap2@gmail.com)
|
|
583
636
|
- **Repository:** https://github.com/kVarunkk/DoStuff
|
|
584
637
|
- **Issues:** https://github.com/kVarunkk/DoStuff/issues
|
|
638
|
+
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
|
|
639
|
+
- **PyPI:** https://pypi.org/project/dostuff/
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# Package init — lazy, doesn't pull agent loop on import
|
|
2
|
+
import os
|
|
2
3
|
from importlib.metadata import PackageNotFoundError, version
|
|
3
4
|
|
|
5
|
+
# litellm fetches its price list from GitHub on import (retrying, with warnings on timeout);
|
|
6
|
+
# use the copy bundled with litellm instead. Set before any submodule imports litellm.
|
|
7
|
+
os.environ.setdefault("LITELLM_LOCAL_MODEL_COST_MAP", "True")
|
|
8
|
+
|
|
4
9
|
try:
|
|
5
10
|
# Single version source: pyproject.toml, via the installed distribution metadata
|
|
6
11
|
__version__ = version("dostuff")
|
|
@@ -3,7 +3,7 @@ from typing import Any
|
|
|
3
3
|
import litellm
|
|
4
4
|
from litellm import acompletion
|
|
5
5
|
from dostuff.tools.definitions import TOOL_SCHEMAS, default_tool_names
|
|
6
|
-
from dostuff.lib.model import completion_kwargs,
|
|
6
|
+
from dostuff.lib.model import completion_kwargs, uses_explicit_prompt_caching
|
|
7
7
|
from dostuff.lib.tracing import content_attr, tracer
|
|
8
8
|
from opentelemetry.trace import Status, StatusCode
|
|
9
9
|
|
|
@@ -30,7 +30,7 @@ def build_request_kwargs(stream: bool) -> dict[str, Any]:
|
|
|
30
30
|
kwargs["stream"] = stream
|
|
31
31
|
if stream:
|
|
32
32
|
kwargs["stream_options"] = {"include_usage": True}
|
|
33
|
-
if _supports_reasoning(kwargs["model"]) and
|
|
33
|
+
if _supports_reasoning(kwargs["model"]) and kwargs["model"].startswith(("gemini/", "vertex_ai/")):
|
|
34
34
|
# Ask Gemini to stream its thoughts (rendered as partial_thought)
|
|
35
35
|
kwargs["thinking_config"] = {"include_thoughts": True}
|
|
36
36
|
if uses_explicit_prompt_caching():
|