pdo-agent 2.0.0__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.
Files changed (65) hide show
  1. pdo_agent-2.0.0/LICENSE +21 -0
  2. pdo_agent-2.0.0/PKG-INFO +456 -0
  3. pdo_agent-2.0.0/README.md +426 -0
  4. pdo_agent-2.0.0/pyproject.toml +69 -0
  5. pdo_agent-2.0.0/setup.cfg +4 -0
  6. pdo_agent-2.0.0/src/pdo/__init__.py +21 -0
  7. pdo_agent-2.0.0/src/pdo/agent/__init__.py +6 -0
  8. pdo_agent-2.0.0/src/pdo/agent/core.py +275 -0
  9. pdo_agent-2.0.0/src/pdo/agent/delegate.py +56 -0
  10. pdo_agent-2.0.0/src/pdo/agent/executor.py +87 -0
  11. pdo_agent-2.0.0/src/pdo/agent/memory.py +191 -0
  12. pdo_agent-2.0.0/src/pdo/agent/messages.py +87 -0
  13. pdo_agent-2.0.0/src/pdo/agent/planner.py +38 -0
  14. pdo_agent-2.0.0/src/pdo/agent/reviewer.py +25 -0
  15. pdo_agent-2.0.0/src/pdo/agent/router.py +37 -0
  16. pdo_agent-2.0.0/src/pdo/api.py +65 -0
  17. pdo_agent-2.0.0/src/pdo/banner.py +53 -0
  18. pdo_agent-2.0.0/src/pdo/config.py +151 -0
  19. pdo_agent-2.0.0/src/pdo/llm.py +211 -0
  20. pdo_agent-2.0.0/src/pdo/logging_setup.py +34 -0
  21. pdo_agent-2.0.0/src/pdo/main.py +961 -0
  22. pdo_agent-2.0.0/src/pdo/mcp.py +264 -0
  23. pdo_agent-2.0.0/src/pdo/prompts/system.md +46 -0
  24. pdo_agent-2.0.0/src/pdo/providers.py +86 -0
  25. pdo_agent-2.0.0/src/pdo/rag.py +191 -0
  26. pdo_agent-2.0.0/src/pdo/serve.py +124 -0
  27. pdo_agent-2.0.0/src/pdo/skills.py +59 -0
  28. pdo_agent-2.0.0/src/pdo/theme.py +47 -0
  29. pdo_agent-2.0.0/src/pdo/tools/__init__.py +6 -0
  30. pdo_agent-2.0.0/src/pdo/tools/base.py +89 -0
  31. pdo_agent-2.0.0/src/pdo/tools/code.py +48 -0
  32. pdo_agent-2.0.0/src/pdo/tools/data.py +57 -0
  33. pdo_agent-2.0.0/src/pdo/tools/edit.py +55 -0
  34. pdo_agent-2.0.0/src/pdo/tools/filesystem.py +175 -0
  35. pdo_agent-2.0.0/src/pdo/tools/git.py +44 -0
  36. pdo_agent-2.0.0/src/pdo/tools/memory.py +70 -0
  37. pdo_agent-2.0.0/src/pdo/tools/rag.py +60 -0
  38. pdo_agent-2.0.0/src/pdo/tools/registry.py +203 -0
  39. pdo_agent-2.0.0/src/pdo/tools/search.py +83 -0
  40. pdo_agent-2.0.0/src/pdo/tools/shell.py +125 -0
  41. pdo_agent-2.0.0/src/pdo/tools/web.py +163 -0
  42. pdo_agent-2.0.0/src/pdo_agent.egg-info/PKG-INFO +456 -0
  43. pdo_agent-2.0.0/src/pdo_agent.egg-info/SOURCES.txt +63 -0
  44. pdo_agent-2.0.0/src/pdo_agent.egg-info/dependency_links.txt +1 -0
  45. pdo_agent-2.0.0/src/pdo_agent.egg-info/entry_points.txt +2 -0
  46. pdo_agent-2.0.0/src/pdo_agent.egg-info/requires.txt +9 -0
  47. pdo_agent-2.0.0/src/pdo_agent.egg-info/top_level.txt +1 -0
  48. pdo_agent-2.0.0/tests/test_agent.py +73 -0
  49. pdo_agent-2.0.0/tests/test_api.py +53 -0
  50. pdo_agent-2.0.0/tests/test_attachments.py +67 -0
  51. pdo_agent-2.0.0/tests/test_cli.py +46 -0
  52. pdo_agent-2.0.0/tests/test_config.py +50 -0
  53. pdo_agent-2.0.0/tests/test_delegate.py +115 -0
  54. pdo_agent-2.0.0/tests/test_extra_tools.py +81 -0
  55. pdo_agent-2.0.0/tests/test_filesystem.py +54 -0
  56. pdo_agent-2.0.0/tests/test_mcp.py +94 -0
  57. pdo_agent-2.0.0/tests/test_permissions.py +48 -0
  58. pdo_agent-2.0.0/tests/test_plugins.py +54 -0
  59. pdo_agent-2.0.0/tests/test_rag.py +83 -0
  60. pdo_agent-2.0.0/tests/test_registry.py +60 -0
  61. pdo_agent-2.0.0/tests/test_serve.py +97 -0
  62. pdo_agent-2.0.0/tests/test_sessions.py +45 -0
  63. pdo_agent-2.0.0/tests/test_shell.py +54 -0
  64. pdo_agent-2.0.0/tests/test_skills.py +34 -0
  65. pdo_agent-2.0.0/tests/test_summarize.py +36 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PDO Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,456 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdo-agent
3
+ Version: 2.0.0
4
+ Summary: PDO (Python Do) — a terminal-first AI agent that reasons, plans, and safely executes real tasks.
5
+ Author: PDO Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/uaedoom/pdo
8
+ Project-URL: Repository, https://github.com/uaedoom/pdo
9
+ Project-URL: Issues, https://github.com/uaedoom/pdo/issues
10
+ Keywords: ai,agent,terminal,cli,llm,openai,automation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: openai<2,>=1.30
22
+ Requires-Dist: python-dotenv<2,>=1.0
23
+ Requires-Dist: rich<14,>=13.7
24
+ Requires-Dist: pydantic<3,>=2.6
25
+ Requires-Dist: prompt_toolkit<4,>=3.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest<9,>=8.0; extra == "dev"
28
+ Requires-Dist: ruff>=0.4; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ <h1 align="center">PDO — Python Do</h1>
32
+
33
+ <div align="center">
34
+ <pre>
35
+ ████████ ██████ ████████
36
+ ██ ██ ██ ██ ██ ██
37
+ ████████ ██ ██ ██ ██
38
+ ██ ██ ██ ██ ██
39
+ ██ ██████ ████████
40
+ </pre>
41
+ </div>
42
+
43
+ <p align="center"><b>Think. Plan. Do.</b><br/><sub>The same pixel-art logo greets you on every launch.</sub></p>
44
+
45
+ <p align="center">
46
+ <img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-green.svg">
47
+ <img alt="Python 3.12+" src="https://img.shields.io/badge/Python-3.12%2B-blue.svg">
48
+ <img alt="Open Source" src="https://img.shields.io/badge/Open%20Source-%E2%9D%A4-red.svg">
49
+ </p>
50
+
51
+ > **PDO is free and open source** (MIT licensed). Contributions are welcome —
52
+ > see [CONTRIBUTING.md](CONTRIBUTING.md). Star the repo if you find it useful! ⭐
53
+
54
+ PDO is a terminal-first AI agent that completes real tasks — it doesn't just
55
+ answer questions. Give it a goal and it reasons about it, plans the steps,
56
+ decides whether tools are needed, executes them **safely**, reviews the result,
57
+ and replies clearly. When a plain answer is enough, it just answers; it never
58
+ reaches for a tool it doesn't need.
59
+
60
+ ```
61
+ you ▸ list all markdown files in this repo and summarise the README
62
+ 🔧 run_shell(command='find . -name "*.md"')
63
+ 🔧 read_file(path='README.md')
64
+ PDO Here are the Markdown files… and a three-line summary of the README…
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Features
70
+
71
+ - **ReAct-style agent loop** built on the LLM's **native function/tool calling** —
72
+ the model picks tools and arguments; PDO executes them and feeds results back
73
+ until the task is done. Tool calls are never parsed out of free text.
74
+ - **Many providers** — OpenAI, Anthropic, OpenRouter, local **Ollama**, or any
75
+ OpenAI-compatible endpoint. Switch provider and model at runtime with `/models`
76
+ (live model listing). The core depends only on an `LLMClient` interface.
77
+ - **18 built-in tools** — filesystem (read / write / append / **edit** / list /
78
+ mkdir), shell (dangerous-command guard), code search (**glob** / **grep**),
79
+ **git**, **web search & fetch**, **HTTP**, **Python exec**, **SQLite**, and
80
+ long-term memory (save / search / delete).
81
+ - **Extensible** three ways without touching the core:
82
+ - **Plugins** — drop a `Tool` subclass in `<PDO_HOME>/plugins/` (or ship one via
83
+ the `pdo.plugins` entry-point group).
84
+ - **Skills** — Markdown prompt recipes become slash commands (`/review`, …).
85
+ - **MCP** — connect any Model Context Protocol server; its tools appear as
86
+ `mcp__<server>__<tool>`.
87
+ - **Conversation management** — named **sessions** (`/new`, `/resume`), automatic
88
+ **summarisation** of long history, `@file` references (text **and images** for
89
+ vision models), and `/export`.
90
+ - **Sub-agents** — a `delegate_task` tool spawns a fresh child agent for
91
+ self-contained subtasks, keeping the main context small on big jobs.
92
+ - **Codebase search** — `/index` builds a local BM25 index of your project; the
93
+ agent then uses `codebase_search` to find relevant code with `path:line` refs
94
+ (no embeddings API needed — works fully offline).
95
+ - **Safety & control** — typed confirmation for destructive commands, working-dir
96
+ write sandbox, per-tool **permission policies**, and a structured **audit log**.
97
+ - **Polished terminal UX** — pixel-art splash, a bordered input box with slash
98
+ autocomplete, Markdown rendering, a thinking spinner, color **themes**, and a
99
+ live token-usage footer.
100
+ - **Scriptable** — one-shot mode (`pdo "prompt"`), `--json` output, and a Docker
101
+ image.
102
+ - **Tested & CI-ready** — a `pytest` suite that mocks the LLM (no API key needed)
103
+ and a GitHub Actions workflow.
104
+
105
+ ---
106
+
107
+ ## Installation
108
+
109
+ > [!IMPORTANT]
110
+ > **PDO requires Python 3.12+.** Create the virtual environment with a 3.12
111
+ > interpreter explicitly — don't rely on the system `python3` (macOS ships 3.9,
112
+ > which will not work).
113
+
114
+ ```bash
115
+ # 1. Clone
116
+ git clone https://github.com/uaedoom/pdo.git
117
+ cd pdo
118
+
119
+ # 2. Create a virtual environment WITH Python 3.12+
120
+ python3.12 -m venv .venv # macOS (Homebrew): brew install python@3.12
121
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
122
+
123
+ # 3. Upgrade pip, then install (editable, with dev extras)
124
+ python -m pip install --upgrade pip
125
+ pip install -e ".[dev]"
126
+ ```
127
+
128
+ This installs the `pdo` console command. Verify with `python --version`
129
+ (should be 3.12.x) and `pdo --version`.
130
+
131
+ ### Notes for users / troubleshooting
132
+
133
+ - **`ERROR: ... Directory cannot be installed in editable mode` / "requires a
134
+ setuptools-based build"** — your virtual environment is on an old Python (and
135
+ old pip). Recreate it with Python 3.12 and upgrade pip:
136
+ ```bash
137
+ deactivate; rm -rf .venv
138
+ python3.12 -m venv .venv && source .venv/bin/activate
139
+ python -m pip install --upgrade pip
140
+ pip install -e ".[dev]"
141
+ ```
142
+ - **No `python3.12`?** Install it first: macOS `brew install python@3.12`,
143
+ Ubuntu `sudo apt install python3.12 python3.12-venv`.
144
+ - **Not yet on PyPI** — install by cloning as above (`pip install pdo` isn't
145
+ available yet).
146
+ - **Tested on macOS and Linux.** Windows should work but is less tested.
147
+ - Runtime data (memory, sessions, logs) lives in `~/.pdo` if you set
148
+ `PDO_HOME=~/.pdo`; otherwise it defaults to the package directory.
149
+
150
+ ---
151
+
152
+ ## Quick Start
153
+
154
+ ```bash
155
+ # Set your API key (or copy .env.example to .env and fill it in)
156
+ export OPENAI_API_KEY=sk-...
157
+
158
+ # Optionally choose a model (gpt-4.1-mini is the default)
159
+ export OPENAI_MODEL=gpt-4.1-mini
160
+
161
+ # Run it interactively
162
+ pdo
163
+
164
+ # …or one-shot (great for scripts / pipes)
165
+ pdo "list all markdown files and summarise the README"
166
+ pdo --json "what is 2+2" # machine-readable output
167
+ pdo --version
168
+ ```
169
+
170
+ Interactive mode gives you a prompt; type a goal, or a slash command (`/help`).
171
+ Replies render as Markdown, with a thinking spinner and a Codex-style activity
172
+ log. Switch colors live with `/theme green` (or set `PDO_THEME`).
173
+
174
+ ### Configuration
175
+
176
+ All configuration is read from the environment (a `.env` file is auto-loaded):
177
+
178
+ | Variable | Default | Description |
179
+ | ----------------- | ---------------- | --------------------------------------------- |
180
+ | `OPENAI_API_KEY` | *(required)* | Your API key (OpenAI **or** OpenRouter, etc.). |
181
+ | `OPENAI_MODEL` | `gpt-4.1-mini` | Model to use. |
182
+ | `OPENAI_BASE_URL` | *(OpenAI)* | API endpoint. Set to use an OpenAI-compatible provider. |
183
+ | `TEMPERATURE` | `0.2` | Sampling temperature (0–2). |
184
+ | `PDO_HOME` | package dir | Where memory and logs are stored (e.g. `~/.pdo`). |
185
+
186
+ PDO fails fast with a friendly message if `OPENAI_API_KEY` is missing.
187
+
188
+ ### Using OpenRouter (or other OpenAI-compatible APIs)
189
+
190
+ PDO talks to any OpenAI-compatible endpoint — just point `OPENAI_BASE_URL` at it
191
+ and use that provider's key and model names. For [OpenRouter](https://openrouter.ai):
192
+
193
+ ```bash
194
+ export OPENAI_API_KEY=sk-or-... # your OpenRouter key
195
+ export OPENAI_BASE_URL=https://openrouter.ai/api/v1
196
+ export OPENAI_MODEL=openai/gpt-4.1-mini # any OpenRouter model id
197
+ pdo
198
+ ```
199
+
200
+ The same pattern works for local servers (e.g. Ollama/LM Studio at
201
+ `http://localhost:11434/v1`). The model must support **tool/function calling**
202
+ for PDO's agent loop to use tools.
203
+
204
+ ---
205
+
206
+ ## Example Usage
207
+
208
+ ```text
209
+ you ▸ build a minimal Flask API in ./hello-api
210
+ you ▸ explain this repository
211
+ you ▸ fix this Python error: <paste traceback>
212
+ you ▸ list all markdown files
213
+ you ▸ create a README for this project
214
+ ```
215
+
216
+ ### Terminal commands
217
+
218
+ | Command | What it does |
219
+ | ----------- | ------------------------------------- |
220
+ | `/help` | Show available commands |
221
+ | `/models` | Switch provider & model (OpenAI / Anthropic / OpenRouter / Ollama) |
222
+ | `/tools` | List registered tools |
223
+ | `/mcp` | Show connected MCP servers and their tools |
224
+ | `/theme` | Change the color theme (e.g. `/theme green`) |
225
+ | `/export` | Save the conversation to a Markdown file |
226
+ | `/sessions` | List saved conversation sessions |
227
+ | `/new` | Start a new session (e.g. `/new feature-x`) |
228
+ | `/resume` | Switch to another session (e.g. `/resume default`) |
229
+ | `/memory` | Show saved facts and preferences |
230
+ | `/history` | Show recent conversation history |
231
+ | `/clear` | Clear the current session's history |
232
+ | `/version` | Show the PDO version |
233
+ | `/exit` | Quit |
234
+
235
+ ### Switching models at runtime
236
+
237
+ Type `/models` to pick a provider (OpenAI, Anthropic, or OpenRouter) and a model
238
+ interactively — the change applies immediately for the rest of the session. If a
239
+ key for the chosen provider isn't in your environment, PDO prompts for one and
240
+ keeps it in memory for the session only (never written to disk). Set
241
+ `ANTHROPIC_API_KEY` / `OPENROUTER_API_KEY` in your `.env` to skip the prompt.
242
+
243
+ ---
244
+
245
+ ## Project Structure
246
+
247
+ ```
248
+ pdo/
249
+ ├─ pyproject.toml # Packaging + console script (pdo = pdo.main:main)
250
+ ├─ requirements.txt # Convenience mirror of runtime deps
251
+ ├─ .env.example # Sample configuration
252
+ ├─ .github/workflows/ci.yml
253
+ ├─ src/pdo/
254
+ │ ├─ main.py # Terminal entry point + REPL + slash commands
255
+ │ ├─ config.py # Env-based config, validated with pydantic
256
+ │ ├─ llm.py # LLMClient interface + OpenAI implementation
257
+ │ ├─ logging_setup.py # Rotating file logging for the `pdo` namespace
258
+ │ ├─ agent/
259
+ │ │ ├─ core.py # Coordinates components; runs the ReAct loop
260
+ │ │ ├─ planner.py # Breaks a goal into steps (thin, advisory)
261
+ │ │ ├─ router.py # Plain chat vs. tool use (thin; model decides)
262
+ │ │ ├─ executor.py # Runs approved tool calls, safely
263
+ │ │ ├─ reviewer.py # Sanity-checks the final answer
264
+ │ │ ├─ memory.py # Local JSON memory store
265
+ │ │ └─ messages.py # Message/ToolCall dataclasses
266
+ │ ├─ tools/
267
+ │ │ ├─ base.py # Tool base class + confirmation helper
268
+ │ │ ├─ registry.py # The single tool registry + auto-registration
269
+ │ │ ├─ filesystem.py # read / write / append / list / mkdir
270
+ │ │ ├─ shell.py # run command + dangerous-command detector
271
+ │ │ └─ memory.py # save / search / delete memory tools
272
+ │ ├─ prompts/system.md # The system prompt
273
+ │ ├─ data/ # Runtime JSON state (memory.json, history.json)
274
+ │ └─ logs/ # Rotating logs (pdo.log)
275
+ ├─ tests/ # pytest suite (LLM is mocked)
276
+ └─ docs/ # Architecture notes
277
+ ```
278
+
279
+ > **Where is my data?** By default PDO stores `memory.json`, `history.json` and
280
+ > logs inside the installed package directory so a fresh clone works immediately.
281
+ > Set `PDO_HOME=~/.pdo` to keep that state in your home directory instead.
282
+
283
+ ---
284
+
285
+ ## Adding New Tools
286
+
287
+ A tool is a small class. Subclass `Tool`, declare a JSON parameter schema, and
288
+ decorate it with `@register_tool` — that's it. The agent picks it up
289
+ automatically; you never touch the core.
290
+
291
+ ```python
292
+ # src/pdo/tools/clock.py
293
+ from datetime import datetime
294
+ from typing import Any
295
+
296
+ from .base import Tool
297
+ from .registry import register_tool
298
+
299
+
300
+ @register_tool
301
+ class CurrentTimeTool(Tool):
302
+ name = "current_time"
303
+ description = "Return the current local date and time."
304
+ parameters = {"type": "object", "properties": {}}
305
+
306
+ def run(self, **_: Any) -> str:
307
+ return datetime.now().isoformat(timespec="seconds")
308
+ ```
309
+
310
+ For a built-in tool, add the module to the lazy import in
311
+ `tools/registry.py:get_registry`. For tools that perform sensitive actions,
312
+ accept an injectable `confirm` callback (see `tools/filesystem.py`) so they can
313
+ be tested deterministically and prompt the user when needed.
314
+
315
+ ### Plugins (no fork required)
316
+
317
+ You don't have to edit PDO to add a tool. PDO **auto-discovers plugins** on
318
+ startup from two places:
319
+
320
+ 1. **A plugins directory** — drop a `.py` file defining a `Tool` subclass into
321
+ your plugins folder (run `/tools` to see its path; default
322
+ `<PDO_HOME>/plugins`). The `@register_tool` decorator is optional there — PDO
323
+ finds `Tool` subclasses automatically. A ready-made example lives in
324
+ [`examples/plugins/current_time_tool.py`](examples/plugins/current_time_tool.py):
325
+
326
+ ```bash
327
+ mkdir -p ~/.pdo/plugins # if you run with PDO_HOME=~/.pdo
328
+ cp examples/plugins/current_time_tool.py ~/.pdo/plugins/
329
+ pdo # the `current_time` tool is now available
330
+ ```
331
+
332
+ 2. **Installed packages** — a third-party package can advertise tools via the
333
+ `pdo.plugins` entry-point group. Each entry point may resolve to a `Tool`
334
+ subclass or a `register(registry)` callable:
335
+
336
+ ```toml
337
+ # in the plugin package's pyproject.toml
338
+ [project.entry-points."pdo.plugins"]
339
+ my_tool = "my_package.tools:MyTool"
340
+ ```
341
+
342
+ A broken plugin is logged and skipped — it never crashes PDO.
343
+
344
+ ### Skills (reusable prompt commands)
345
+
346
+ Drop a Markdown file in your skills directory (`<PDO_HOME>/skills/`) and it
347
+ becomes a slash command named after the file. An optional first line
348
+ `description: …` (or `# Title`) sets the menu text, and `{{args}}` interpolates
349
+ whatever you type after the command. Example
350
+ [`examples/skills/review.md`](examples/skills/review.md) becomes `/review`:
351
+
352
+ ```bash
353
+ mkdir -p ~/.pdo/skills
354
+ cp examples/skills/review.md ~/.pdo/skills/
355
+ pdo # now type: /review the auth module
356
+ ```
357
+
358
+ ### Referencing files with `@`
359
+
360
+ In any message, mention a file with `@path` and PDO inlines its contents for the
361
+ model — e.g. `explain @src/pdo/main.py` or `fix the bug in @app.py`.
362
+
363
+ **Images too:** `@screenshot.png` (png/jpg/gif/webp) attaches the image itself,
364
+ so vision-capable models can see it — e.g. `what's wrong in this UI? @shot.png`.
365
+
366
+ ### Multi-line input
367
+
368
+ Press **Enter** to send. Press **Option/Alt+Enter** (⌥⏎) to insert a newline and
369
+ compose a multi-line message before sending.
370
+
371
+ ### MCP servers (Model Context Protocol)
372
+
373
+ PDO is an MCP client: connect any MCP server and its tools become available to
374
+ the agent automatically (named `mcp__<server>__<tool>`). Declare servers in
375
+ `<PDO_HOME>/mcp.json` using the standard format (see
376
+ [`examples/mcp.json`](examples/mcp.json)):
377
+
378
+ ```json
379
+ {
380
+ "mcpServers": {
381
+ "filesystem": {
382
+ "command": "npx",
383
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
384
+ }
385
+ }
386
+ }
387
+ ```
388
+
389
+ Servers start on launch (over the stdio transport); run `/mcp` to see what's
390
+ connected. A server that fails to start is reported and skipped — it never
391
+ crashes PDO. No extra Python dependencies are required.
392
+
393
+ ### PDO *as* an MCP server / SDK
394
+
395
+ It works both ways — `pdo --serve` exposes the whole agent as an **MCP server**
396
+ over stdio, so Claude Desktop, Claude Code, or any MCP client can call its
397
+ `run_task` tool and get back the agent's final answer (with all of PDO's tools,
398
+ sub-agents, and codebase search behind it). For example, in a client's
399
+ `mcp.json`:
400
+
401
+ ```json
402
+ { "mcpServers": { "pdo": { "command": "pdo", "args": ["--serve"] } } }
403
+ ```
404
+
405
+ In serve mode nothing is printed to stdout and interactive confirmations are
406
+ auto-denied (dangerous commands are refused rather than prompted).
407
+
408
+ And from Python scripts, embed the agent directly:
409
+
410
+ ```python
411
+ from pdo import run_agent
412
+
413
+ answer = run_agent("list the markdown files here and summarise the README")
414
+ ```
415
+
416
+ `run_agent` accepts overrides (`model=`, `base_url=`, `api_key=`,
417
+ `temperature=`, or a custom `llm=` client) and uses an ephemeral memory so it
418
+ never touches your interactive sessions.
419
+
420
+ ---
421
+
422
+ ## Roadmap
423
+
424
+ **v1 — done**
425
+ - Native tool-calling agent loop; multi-provider (OpenAI / Anthropic / OpenRouter
426
+ / Ollama); 18 built-in tools; plugins, skills, and MCP client; named sessions +
427
+ auto-summary; permission policies + audit log; themed TUI with one-shot/JSON
428
+ modes; tests + CI; Docker.
429
+
430
+ **v2 (this release) — done**
431
+ - Multi-line input and image/vision attachments (`@image.png`).
432
+ - Sub-agents (`delegate_task`) and codebase retrieval (`/index` +
433
+ `codebase_search`, BM25 — fully offline).
434
+ - `pdo --serve` (PDO as an MCP server) and the `run_agent` Python API.
435
+
436
+ **Next**
437
+ - Embedding-based retrieval as an optional upgrade to the BM25 index.
438
+ - Streamed responses inside serve mode; richer sub-agent orchestration.
439
+ - PyPI publication and a Homebrew formula.
440
+
441
+ Each of these arrives as a new `Tool` (or `LLMClient`) — by design, none require
442
+ changes to the core.
443
+
444
+ ---
445
+
446
+ ## Contributing
447
+
448
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for setup,
449
+ coding standards, and how to add tools. Please run `ruff check .` and `pytest`
450
+ before opening a pull request.
451
+
452
+ ---
453
+
454
+ ## License
455
+
456
+ [MIT](LICENSE) © PDO Contributors