Stage 3

Provider Ecosystem

2025-11-27 — 2025-12-09 v0.10.0 → v0.15.0 211 commits 9 contributors
agent-runtime cli devex tui llm-providers

Zeitgeist

Between v0.10.0 and v0.15.0 (November 27 - December 9, 2025), pi underwent a dual transformation: outward-facing expansion of the provider ecosystem and inward-facing restructuring of the coding agent's architecture. The 211 commits in this stage added standalone binary distribution, context compaction, the AgentSession abstraction, and a methodical 16-step refactoring plan that reorganized the entire coding-agent package. This was pi preparing for scale -- both in terms of the models it could talk to and the complexity of the codebase that powered it.

The provider work was not about adding more LLM vendors for the sake of breadth. Each addition solved a real problem: OpenAI compatibility overrides (87a1a9de) enabled LiteLLM and custom proxies, the OAuth login indicator (87b7343b) helped users understand their billing context, and the compat flags in models.json (#133) let pi talk to non-standard endpoints without provider-specific code. The philosophy was clear: pi should work with whatever model infrastructure you already have.

Simultaneously, the coding agent's internals were being torn apart and reassembled. The AgentSession class emerged through a disciplined work-package approach (WP1 through WP16), extracting concerns that had been tangled together: bash execution, compaction, model management, event subscription, and session persistence. This refactoring was driven by a specific need -- Mom needed to share the same session management logic, and the old monolithic main.ts made that impossible.

Key Developments

Standalone Binary Builds with Bun

Commits 4a60bffe and c4a65ad8 introduced Bun-based binary compilation, producing standalone executables for macOS, Linux, and Windows. The CI workflow (7cf3baeb) automated cross-platform builds, and subsequent fixes addressed Windows binary path resolution (ccae2200), macOS quarantine attributes (062edb47), and binary detection using URL-encoded %7EBUN markers (52f1a8cb). Shipping binaries eliminated the Node.js/npm dependency for end users -- you could download a single file and run pi immediately. This decision to compile via Bun rather than pkg or nexe reflected pi's bet on Bun as the TypeScript runtime.

Context Compaction

The compaction system (#92) was one of the most architecturally significant features in pi's history. Commit 6c2360af implemented the core logic: when a conversation approached the model's context window limit, pi would summarize older messages, keep recent turns, and continue seamlessly. The system handled auto-triggering (c89b1ec3), RPC support, and interaction with the /branch command. It required careful token counting -- commit 989af797 normalized OpenAI token counting and added branch source tracking. The compaction cut point was always at a user/assistant/bash boundary, never mid-tool-result, ensuring the summary captured complete interactions.

The AgentSession Refactoring

The most ambitious undertaking was the AgentSession extraction, executed through 16 numbered work packages visible in the commit messages. WP1 (3f305502) created bash-executor.ts; WP2 (29d96ab2) established the basic AgentSession structure; WP3 through WP8 added event subscription, prompting methods, model management, and compaction; WP9-WP10 (934c2bc5) added session management utilities; and WP14-WP15 created new entry points (main-new.ts, InteractiveMode) that used the new abstraction. The original files were kept alongside the new ones during the transition, following a "keep-old-code strategy" noted in WP2. This refactoring split main.ts into cli/args, cli/file-processor, cli/session-picker, core/system-prompt, and core/model-resolver (1a6a1a8a), producing the directory structure (core/, modes/, utils/, cli/) documented in a new DEVELOPMENT.md file.

Read-Only Exploration and Bash Mode

PR #112 (bd0d0676) added bash mode -- users could prefix input with ! to execute shell commands directly, bypassing the LLM. Output streamed in real-time, was added to the LLM context, and persisted in session history. Green borders distinguished bash execution from agent responses. This complemented the read-only tools from the previous stage: users could now do their own investigation inline without leaving pi, then hand findings back to the agent.

Tool Output Truncation and Result Streaming

The tool output truncation system (#134) imposed consistent limits across all tools: 2000 lines or 50KB, with actionable notices telling the LLM how to get more data. The read tool showed "Use offset=N to continue," while bash saved full output to a temp file. This was a practical response to context window pressure -- without truncation, a single find / could consume the entire context budget. Later, 7ac83258 added tool result streaming, letting the TUI show tool output progressively rather than waiting for completion.

Provider Ecosystem Expansion

Beyond the OpenAI compatibility layer, this stage saw OAuth login status indicators (bc838b02) showing (sub) in the footer when using subscription billing, fuzzy search for models and sessions (#122), prompt history navigation with Up/Down arrows (#121), and the /resume command (#117) for switching sessions mid-conversation. The model selector was refined to use only model ID for fuzzy filtering (#151), and circular wrap-around navigation appeared in all menus (#82).

Philosophy Shifts

AGENTS.md at v0.15.0 added several important rules that were absent at v0.10.0: explicit instructions about using GitHub CLI for issues and PRs, browser tools for frontend testing, and tmux for TUI interaction. The addition of DEVELOPMENT.md with a code map signaled that the project was complex enough to need architectural documentation for its own development agent. The changelog rules (4432fc9b) preventing modification of released versions introduced release discipline -- each version section became immutable once published.

The compaction research documents (5daef11b, 1c18b800) showed the project's approach to complex features: design first, implement second. The refactoring plan (1507f8b7) was similarly methodical, with work packages, dependency ordering, and an explicit strategy for migrating from old code to new without breaking the existing system.

Looking Forward

The AgentSession abstraction became the foundation that everything else built on: the SDK (Stage 5), the hooks system, and the extension architecture all operated through AgentSession's event-based API. The compaction system's tree-aware design anticipated the session tree that arrived in Stage 6. And the binary distribution pipeline established the release infrastructure that enabled pi's rapid version cadence -- 15 releases in 12 days during this stage alone.

Key changes

Major code refactoring

Restructured codebase for better maintainability and separation of concerns. Moved files into organized directories (`core/`, `modes/`, `utils/`, `cli/`). Extracted `AgentSession` class as central session management abstraction. Split `main.ts` and `tui-renderer.ts` into focused modules. See `DEVELOPMENT.md` for the new code map. ([#153](https://github.com/badlogic/pi-mono/issues/153))

From the changelog

**Major code refactoring**: Restructured codebase for better maintainability and separation of concerns. Moved files into organized directories (`core/`, `modes/`, `utils/`, `cli/`). Extracted `AgentSession` class as central session management abstraction. Split `main.ts` and `tui-renderer.ts` into focused modules. See `DEVELOPMENT.md` for the new code map. ([#153](https://github.com/badlogic/pi-mono/issues/153))

`/debug` command now includes agent messages as JSONL in the output

`/debug` command now includes agent messages as JSONL in the output

Custom themes require new color tokens

Themes must now include `thinkingXhigh` and `bashMode` color tokens. The theme loader provides helpful error messages listing missing tokens. See built-in themes (dark.json, light.json) for reference values.

From the changelog

**Custom themes require new color tokens**: Themes must now include `thinkingXhigh` and `bashMode` color tokens. The theme loader provides helpful error messages listing missing tokens. See built-in themes (dark.json, light.json) for reference values.

OpenAI compatibility overrides in models.json

Custom models using `openai-completions` API can now specify a `compat` object to override provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)

From the changelog

**OpenAI compatibility overrides in models.json**: Custom models using `openai-completions` API can now specify a `compat` object to override provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)

xhigh thinking level

Added `xhigh` thinking level for OpenAI codex-max models. Cycle through thinking levels with Shift+Tab; `xhigh` appears only when using a codex-max model. ([#143](https://github.com/badlogic/pi-mono/issues/143))

From the changelog

**xhigh thinking level**: Added `xhigh` thinking level for OpenAI codex-max models. Cycle through thinking levels with Shift+Tab; `xhigh` appears only when using a codex-max model. ([#143](https://github.com/badlogic/pi-mono/issues/143))

Collapse changelog setting

Add `"collapseChangelog": true` to `~/.pi/agent/settings.json` to show a condensed "Updated to vX.Y.Z" message instead of the full changelog after updates. Use `/changelog` to view the full changelog. ([#148](https://github.com/badlogic/pi-mono/issues/148))

From the changelog

**Collapse changelog setting**: Add `"collapseChangelog": true` to `~/.pi/agent/settings.json` to show a condensed "Updated to vX.Y.Z" message instead of the full changelog after updates. Use `/changelog` to view the full changelog. ([#148](https://github.com/badlogic/pi-mono/issues/148))

Bash mode

Execute shell commands directly from the editor by prefixing with `!` (e.g., `!ls -la`). Output streams in real-time, is added to the LLM context, and persists in session history. Supports multiline commands, cancellation (Escape), truncation for large outputs, and preview/expand toggle (Ctrl+O). Also available in RPC mode via `{"type":"bash","command":"..."}`. ([#112](https://github.com/badlogic/pi-mono/pull/112), original implementation by [@markusylisiurunen](https://github.com/markusylisiurunen))

From the changelog

**Bash mode**: Execute shell commands directly from the editor by prefixing with `!` (e.g., `!ls -la`). Output streams in real-time, is added to the LLM context, and persists in session history. Supports multiline commands, cancellation (Escape), truncation for large outputs, and preview/expand toggle (Ctrl+O). Also available in RPC mode via `{"type":"bash","command":"..."}`. ([#112](https://github.com/badlogic/pi-mono/pull/112), original implementation by [@markusylisiurunen](https://github.com/markusylisiurunen))

Tool output truncation

agent-runtime

All tools now enforce consistent truncation limits with actionable notices for the LLM. ([#134](https://github.com/badlogic/pi-mono/issues/134))

From the changelog

**Tool output truncation**: All tools now enforce consistent truncation limits with actionable notices for the LLM. ([#134](https://github.com/badlogic/pi-mono/issues/134))

packages/coding-agent/src/tools/truncate.ts L11–12
export const DEFAULT_MAX_LINES = 2000;
export const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB
definition in truncate.ts
packages/coding-agent/src/tools/bash.ts L143–157
export const bashTool: AgentTool<typeof bashSchema> = {
	name: "bash",
	label: "bash",
	description: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,
	parameters: bashSchema,
	execute: async (
		_toolCallId: string,
		{ command, timeout }: { command: string; timeout?: number },
		signal?: AbortSignal,
	) => {
		return new Promise((resolve, reject) => {
			const { shell, args } = getShellConfig();
			const child = spawn(shell, [...args, command], {
				detached: true,
				stdio: ["ignore", "pipe", "pipe"],
definition in bash.ts
packages/coding-agent/src/tools/find.ts L39–53
export const findTool: AgentTool<typeof findSchema> = {
	name: "find",
	label: "find",
	description: `Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,
	parameters: findSchema,
	execute: async (
		_toolCallId: string,
		{ pattern, path: searchDir, limit }: { pattern: string; path?: string; limit?: number },
		signal?: AbortSignal,
	) => {
		return new Promise((resolve, reject) => {
			if (signal?.aborted) {
				reject(new Error("Operation aborted"));
				return;
			}
definition in find.ts

Issues closed (10)