diff --git a/docs/prds/0058-pi-agent-provider.md b/docs/prds/0058-pi-agent-provider.md new file mode 100644 index 0000000..30c39d5 --- /dev/null +++ b/docs/prds/0058-pi-agent-provider.md @@ -0,0 +1,103 @@ +# PRD 0058: Add built-in Pi agent provider + +- **Status:** Draft +- **Author:** codex +- **Created:** 2026-06-09 +- **Issue:** #221 + +## Summary + +Add `pi` as a built-in `agent_provider.template`. The provider runs the Pi +coding-agent CLI, provisions its agent config under `~/.pi/agent`, and writes a +provider settings file that targets an unauthenticated Ollama-compatible server. + +The default settings assume an Ollama server at `http://ollama:11434/v1`, using +the `openai-completions` API with a dummy API key because Ollama ignores it. +Users can override the base URL, model list, API key, API type, and compatibility +flags through a new `agent_provider.settings` object. + +## Problem + +bot-bottle currently ships Claude and Codex as built-in agent providers. Pi is a +useful third harness, but using it today requires a custom provider plugin and a +custom image. That repeats boilerplate for prompt copying, skill copying, +provider config, and runtime registration. + +Pi's local-model path is also easy to misconfigure: its custom-model docs require +`~/.pi/agent/models.json`, an API entry, at least one model id, and a dummy +`apiKey` for Ollama even though the server does not authenticate. bot-bottle +should generate that shape consistently. + +## Goals / Success Criteria + +- `agent_provider.template: pi` is accepted as a built-in provider. +- `bot_bottle/contrib/pi/` provides a Pi image and `PiAgentProvider`. +- Pi receives the bot-bottle prompt at `~/.bot-bottle-prompt.txt` and starts in + print-mode prompt delivery like Codex. +- Pi skills are copied into `~/.pi/agent/skills//`. +- Pi provider settings are configurable from the bottle manifest via + `agent_provider.settings`. +- The default Pi provider settings configure an unauthenticated Ollama-compatible + server. +- Unit tests cover manifest parsing, runtime selection, plan generation, prompt, + skills, and provider provisioning. + +## Non-goals + +- Managing or launching an Ollama server. +- Authenticating to Ollama or any remote Pi provider. +- Forwarding host Pi credentials. +- Implementing Pi extensions or MCP registration. +- Changing Claude or Codex provider behavior. + +## Design + +### Manifest + +Extend `agent_provider` with an optional `settings` object. It is currently only +supported for built-in `pi`. + +Supported keys: + +- `base_url`: string, defaults to `http://ollama:11434/v1` +- `api`: string, defaults to `openai-completions` +- `api_key`: string, defaults to `ollama` +- `models`: non-empty array of strings, defaults to `["qwen2.5-coder:7b"]` +- `supports_developer_role`: boolean, defaults to `false` +- `supports_reasoning_effort`: boolean, defaults to `false` + +The snake-case manifest keys are converted into Pi's JSON field names: +`baseUrl`, `apiKey`, `supportsDeveloperRole`, and +`supportsReasoningEffort`. + +### Provider + +`PiAgentProvider.provision_plan` writes `models.json` into the per-launch state +directory and returns an `AgentProvisionPlan` that copies it to +`~/.pi/agent/models.json`. The provider also declares an unauthenticated egress +route for the configured base URL host so the egress layer can allow the Ollama +endpoint. + +The Pi runtime uses: + +- `command="pi"` +- `prompt_mode="read_prompt_file"` +- `image="bot-bottle-pi:latest"` +- `bypass_args=()` +- `resume_args=()` +- `remote_control_args=()` + +The Dockerfile installs `@earendil-works/pi-coding-agent` globally from npm and +keeps the same Debian/node base shape as the existing provider images. + +### Supervise MCP + +Pi does not have built-in MCP support in the current public docs, so +`provision_supervise_mcp` is a no-op. This keeps Pi bottles launchable with +`supervise: true` while preserving the explicit non-goal of implementing Pi +extensions. + +## Merge rule(s) + +This PR can merge when the focused unit tests pass and the PRD status is flipped +from Draft to Active in the final implementation commit.