Skip to content

feat(providers): add Pi coding agent - #7211

Open
StiensWout wants to merge 76 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/pi-provider
Open

feat(providers): add Pi coding agent#7211
StiensWout wants to merge 76 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/pi-provider

Conversation

@StiensWout

@StiensWout StiensWout commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Problem

Pi users depend on their existing models, auth, extensions, skills, context files, and native session history. T3 Code did not have a Pi provider, and a shallow CLI wrapper would lose the customization and session behavior that make Pi useful.

Solution

This adds Pi as an Early Access provider on Orchestrator V2:

  • T3 speaks Pi's stdio JSONL RPC protocol through the user's own installation and discovers models, thinking levels, commands, skills, and auth from Pi itself.
  • Pi 0.80.5 is the minimum supported version. It is the first published release with the entry and settlement hooks T3 needs for rollback boundaries and reliable turn terminalization.
  • Pi owns native extension, package, and project-trust discovery. T3 injects only its namespaced MCP bridge. Blocking startup, extension, and permission requests use the shared T3 request UI; terminal-only decoration remains Pi terminal UI.
  • Supervised, Auto-accept edits, and Full access retain their shared T3 meanings through Pi's public blocking tool hook. Pi declares that compatible set once in its provider presentation, so web and mobile both hide Auto because Pi has no AI approval reviewer.
  • T3's shared delegate_task tool creates durable child threads in the existing subagent UI. User-installed Pi subagent extensions also project progress cards there, without inventing resumable child sessions that Pi does not provide.
  • Pi session files back native resume and rollback. App thread forks and provider switches use T3's portable handoff summaries, including delta handoffs when returning to an existing Pi session.
  • Launch arguments can configure models, tools, resources, trust, storage, and extension flags. T3 rejects arguments that replace RPC execution mode or native session ownership.
  • Provider discovery falls back to Pi default when optional model and command discovery cannot complete. The live interactive session remains authoritative and can handle startup prompts.
  • Every thinking choice is a real Pi level, with Pi's configured level tagged as the default. Returning to Pi default restores Pi's own model and thinking level.
  • $ skill chips are hoisted to Pi's leading /skill:name form (all of them, not only the first), and catalog entries without a filesystem path stay listed. Pi's global skill location maps to the personal scope.
  • Session statistics ride on the settled provider turn as tokenUsage, the same per-turn report the base branch added for Codex (feat(claude): compact old threads before they burn through usage #8144), so the shared context meter needs no Pi-specific plumbing.
  • Auto-retries and compactions show up as work-log activity like they do for OpenCode, including a compaction that runs after the answer and a retry that is already exhausted.
  • agent_settled is not always idle: an extension can start a detached compaction as it fires. The adapter confirms Pi is idle before terminalizing so that recovery stays inside the same turn, and Stop terminates the process once settlement has begun because Pi's generic abort does not cancel detached work.
  • Early Pi exits report the process exit code instead of an unexplained stdout close (stderr stays out of the public error), and failed turns land in the session's lastError so the banner is not blank.
  • Provider startup, Stop, active steering (including native slash commands), rollback, handoff, extension requests, and teardown use the shared V2 lifecycle and user-facing error surfaces. Deferred prompt acknowledgements stay bound to their originating turn and cannot settle a normal agent turn early.

The MCP bridge, Pi subagent investigation, and per-model thinking support originated in @mwolson's stacked contribution and retain that authorship. The exit-code diagnostics, explicit thinking levels, $ skill hoisting, retry and compaction work-log items, and idle confirmation before terminalization come from @mwolson's follow-up branch and keep that authorship too. The per-model reasoning-effort memory from that branch is a cross-provider web and mobile change and is left for its own PR.

Related work

Closes #397.
Closes #402.
Addresses #6685.

This supersedes the Pi implementations in #2211, #2748, #2800, #2812, #2831, #2856, #3818, #3947, #4355, #4445, #5688, #5882, and #6319.

This incorporates StiensWout#34 by @mwolson.

Validation

  • 44 focused tests across the Pi adapter, Pi commands and skills, provider discovery, MCP injection, and thinking capabilities, plus the provider session lifecycle, OpenCode thread adoption, user-facing error, provider registry, contracts, web context-window, and mobile model-option suites.
  • Server, web, mobile, and contracts typechecks. The only server diagnostics are the pre-existing unknown error-channel warnings in ProviderSessionManager.test.ts, which the base branch has as well.
  • Real Pi RPC checks for rejected Supervised writes and unprompted Auto-accept edits.
  • Real web-client check that Pi shows only Supervised, Auto-accept edits, and Full access.
  • Targeted formatting and git diff --check.
  • Complete PR diff reviewed against the current t3code/codex-turn-mapping (0ae375b).

Proof

Provider discovery

Pi provider discovery

End-to-end Pi turn

Pi end-to-end turn

Context meter persists across turns

The active context stays at 21k/272k while Pi's cumulative session total rises from 90k to 111k after the next completed turn.

Pi context meter persistence

Configured thinking default

Pi's effective setting appears as the labeled default while the internal selection continues to inherit from Pi.

Pi configured thinking default

Native steering

Pi steering

Checkpoint and Pi session-tree rollback

Pi rollback

Clean Stop

Stopping an active Pi turn leaves the expected interrupted terminal and no provider stream error.

Pi Stop completes without a provider error

Stacked on #2829 (t3code/codex-turn-mapping) until that branch lands.

Built by GPT-5.6 Sol in T3 Code through Codex. Rebase onto the current base, the per-turn usage alignment, and review-feedback integration by Claude Fable 5 in Claude Code.


Note

High Risk
Introduces a large new provider adapter and changes OpenCode thread/session binding and prompt admission, which are security- and orchestration-critical paths; mobile persistence changes affect model/runtime selection across threads.

Overview
Adds Pi as a first-class mobile provider (icon, display label) and ships extensive PiAdapterV2 coverage for RPC turns, MCP injection, skills, compaction, retries, steering, rollback, and session adoption.

Mobile composer now remembers provider option choices per instance/model, persists them in the composer drafts document, and reapplies them when switching models in thread settings, the composer, and new-task flow. Runtime mode pickers are filtered to each model’s supportedRuntimeModes, with a safe fallback when none are advertised.

OpenCodeAdapterV2 treats a completed assistant message as prompt admission when the SDK ignores client message IDs, and binds newly created native sessions to orchestrator placeholder provider-thread rows instead of minting duplicate rows (Pi tests assert the same adoption pattern).

Reviewed by Cursor Bugbot for commit 727d4f6. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add pi provider with RPC adapter, text generation, and session event handling

  • Adds a complete pi provider stack: stdio JSONL RPC transport (PiRpc.ts), orchestration adapter (PiAdapterV2.ts), provider driver (PiDriver.ts), status/health checks with minimum version 0.80.5 (PiProvider.ts), text generation (PiTextGeneration.ts), command/skill translation (PiCommands.ts), thinking capabilities (piThinkingCapabilities.ts), and PiSettings schema (settings.ts).
  • A T3 MCP bridge extension is injected into Pi processes via piT3McpExtensionSource.ts and piT3McpInjection.ts, routing MCP tool calls to T3's HTTP endpoint.
  • ProviderSessionManager now detects session-scoped runtime request events (no providerTurnId/runId) and ingests them through ProviderEventIngestorV2 instead of publishing to subscribers. When the provider reports status=stopped, it gracefully drains subscribers then releases the session with manual_shutdown.
  • OpenCodeAdapterV2.ensureThread now only resumes when an existing provider thread has a nativeThreadRef; placeholder rows without one trigger session.create and bind the new native session to the handed-over row.
  • Web and mobile composers gain per-model sticky option memory (stickyOptionsByModelByProvider / modelOptionMemoryAtom) and runtime mode filtering based on supportedRuntimeModes declared by the provider.
  • Behavioral Change: ProviderSessionManager event pump routes session-scoped runtime request events to ProviderEventIngestorV2.ingestNormalized instead of subscriber queues; subscriber drain on provider-stop changes release timing. OpenCodeAdapterV2.ensureThread resume condition changed from any defined existingProviderThread to requiring nativeThreadRef.

Macroscope summarized 727d4f6.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: c00ad526-8b4c-49ef-904e-cc074f248b93

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice.


Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 16, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the new Pi provider code. Two error-modeling issues found; everything else (namespace subpath imports, Effect.catchTags usage, layer/driver construction acquiring ChildProcessSpawner/FileSystem/IdAllocatorV2/ServerConfig from the environment, Schema.TaggedErrorClass failures) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts
Comment thread apps/server/src/provider/Drivers/PiDriver.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One consistency finding on the new web provider icon wiring. Everything else in the web scope (providerDriverMeta.ts, ProviderModelsSection.tsx, contextWindow.ts, session-logic.ts, AddProviderInstanceDialog.tsx) is registry/data-only and matches the existing per-driver patterns.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/chat/providerIconUtils.ts
Comment thread apps/server/src/provider/Layers/PiProvider.ts Outdated
Comment thread apps/server/src/textGeneration/PiTextGeneration.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/provider/Layers/PiProvider.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This XXL PR adds a complete Pi provider with subprocess RPC, MCP credentials, permission handling, session lifecycle, text generation, and cross-platform UI/state changes. It also modifies shared orchestration behavior and has unresolved resource, permission, correctness, and lifecycle risks that require human review.

Not approved because:

  • 8 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the Pi icon geometry after the tile removal. Everything else in the web scope (provider icon map, driver meta, model placeholder, display-name and picker option entries) follows the existing per-provider patterns.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Icons.tsx Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions: one finding — a raw child-process stderr payload is copied into a log annotation. Elsewhere in this repo process output is reported as lengths only (stdoutLength/stderrLength, lineLength), with explicit tests asserting stderr is not retained in diagnostics.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two log annotations in the new Pi adapter copy Pi's raw wire error text into the observability stream. Everything else in the Pi files (error attributes, cause handling, driver/layer shape, dependency acquisition) matches the repo's adapter conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiRpc.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
Comment thread apps/server/src/orchestration-v2/UserFacingErrors.ts
Comment thread apps/server/src/orchestration-v2/Adapters/piT3SubagentExtensionSource.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/piT3McpInjection.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/PiAdapterV2.ts Outdated
mwolson and others added 11 commits September 1, 2026 07:43
The default thinking level was advertised with the sentinel id "inherit",
so re-picking the Default-tagged choice sent "do not change" and silently
kept the previously applied level. Give every choice its real level id and
apply it explicitly; Pi's discovered default keeps only the Default tag.
The Pi default model advertises no thinking choices, so an unqualified
return kept the effort a previous pick had applied. Re-capture the
configured thinking baseline and restore it alongside the baseline model
replay, with a high-to-default adapter regression test.
The base branch now carries live context usage on provider turns
(tokenUsage, pingdotgg#8144) and the web meter reads it from the projection. Pi
kept a second owner for the same data: a contextUsage snapshot on the
provider thread, refreshed after terminalization and invalidated by hand
on rollback.

Read Pi's session stats while the turn settles and attach them to the
completed provider turn instead, then drop the provider-thread field and
its generation bookkeeping. A turn without usable stats simply carries no
report, so the meter keeps the last reported turn without adapter-side
retention logic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Switching models kept the previous model's option selections, so an effort
picked for one model silently applied to the next. Record sticky options per
model slug and resolve them on model switch, falling back to the target
model's default instead of carrying anything over.
Storage written before per-model memory existed hydrated an empty map, so
the first model switch after upgrading cleared the one remembered effort.
Seed the map from each persisted sticky selection that carries options.
Mobile model picks already reset to the target model's advertised default,
but nothing remembered an effort you had picked for a specific model.
Record explicit option choices per instance and model in a small persisted
map, restore them when that model is picked again, and land pending writes
on app-update restarts.
Pi RPC get_commands omits TUI builtins, so /compact never appeared in the
composer. Advertise it and send {type: compact} instead of a prompt.
Stop during compact terminates the process because Pi abort does not
cancel manual compaction.
Comment thread apps/server/src/orchestration-v2/ProviderSessionManager.ts
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/mobile/src/state/use-model-option-memory.ts Outdated
Comment thread apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 423ab37. Configure here.

Comment thread apps/server/src/orchestration-v2/Adapters/OpenCodeAdapterV2.ts Outdated
Comment thread apps/web/src/components/chat/ChatComposer.tsx Outdated
@VinhLe1410

VinhLe1410 commented Sep 1, 2026

Copy link
Copy Markdown

Pi 0.84.4 live-test findings

Tested #7211 at 727d4f6a0c98 using the packaged macOS arm64 desktop build.

1. Pi default does not show the active model or reasoning level

My Pi default is GPT-5.6 Sol with High reasoning. Pi RPC returns:

{
  "provider": "openai-codex",
  "modelId": "gpt-5.6-sol",
  "modelName": "GPT-5.6 Sol",
  "thinkingLevel": "high"
}

T3 Code displays only Pi default, without the active model or reasoning level.

Pi default model selection

I see that PI_DEFAULT_MODEL has empty capabilities, so I'm just flagging this FYI.

2. Project skills and prompt templates are missing from the composer

The trusted project contains Pi resources such as:

.pi/prompts/opsx-apply.md
.pi/prompts/opsx-propose.md
.pi/skills/openspec-apply-change/SKILL.md
.pi/skills/openspec-propose/SKILL.md

Pi loads them when started from the project. RPC get_commands also returns them:

{"name":"opsx-apply","source":"prompt"}
{"name":"opsx-propose","source":"prompt"}
{"name":"skill:openspec-apply-change","source":"skill"}
{"name":"skill:openspec-propose","source":"skill"}

They are missing from T3 Code's / prompt menu and $ skill menu for a Pi thread using the same project.

Project commands available in Pi Project commands missing in T3 Code

docs/user/providers-pi.md says project skills loaded for the current workspace should appear in the composer.

The provider catalog is discovered using the server cwd rather than the active project workspace. The live adapter also calls get_commands, but only uses the result to recognize skill references during prompt expansion. It does not update the composer command list.

If per-workspace discovery is the right fix, I can attempt a stacked PR against StiensWout/t3code:t3code/pi-provider.

mwolson added a commit to mwolson/t3code that referenced this pull request Sep 1, 2026
Trial layer for pingdotgg#7211 pi-provider. Net of the 18 unique CTM commits at
aa38c5d, replayed onto the published trial tip. Adds Pi as an Early
Access built-in provider (pi --mode rpc) with native steer, abort-based
Stop, official-extension subagent projection, and session-tree rollback.

Adapted the replay for this line's older CTM pin: thread fixtures include
settledOverrideAt, and Pi select/input/editor questions set multiSelect
to false. Shared registry files keep the existing OpenCode 2 entries.

Not published to origin/trial/orchestrator-v2.1.
mwolson added a commit to mwolson/t3code that referenced this pull request Sep 1, 2026
Bring trial Pi spawn discovery in line with the current pingdotgg#7211
pi-provider tip plus StiensWout#35 diagnose-early-pi-rpc-exits git
and project package loading.
mwolson pushed a commit to mwolson/t3code that referenced this pull request Sep 1, 2026
A first run creates a placeholder provider thread with no native identity,
but ensureThread never handed that row to the adapter, so the Pi adapter
registered a second row keyed by the session file. Both rows then received
updates at turn end, and last-writer-wins on activeProviderThreadId decided
at random whether the row carrying contextUsage was active — hiding the
composer's context meter on most turns.

Pass the run's provider thread through existingProviderThread at both
ensureThread call sites so the adapter adopts the orchestration-owned row
id (Pi's adopt branch already handles a row without a native ref). The
replacement path after a failed resume drops the dead native ref so a
fresh session still binds to the same row. OpenCode now only takes its
resume path for rows that actually carry a native session, which keeps
its behavior unchanged for these new inputs.

Reported by @astarktc in pingdotgg#7211.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mwolson pushed a commit to mwolson/t3code that referenced this pull request Sep 1, 2026
discoverPiUserExtensions passed any *.ts/*.js directory entry as an
explicit --extension path, including macOS AppleDouble sidecars like
"._name.ts". Pi treats a parse failure on an explicit extension path as
fatal, so one stale sidecar in ~/.pi/agent/extensions killed every Pi
turn with an opaque "pi process closed stdout" error while interactive
pi kept working. Skip dot entries, matching pi's own loader.

Reported by @astarktc in pingdotgg#7211.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants