feat(doctor): add Pi agent detection, install fixes, and update flows - #900
Open
matt2e wants to merge 2 commits into
Open
feat(doctor): add Pi agent detection, install fixes, and update flows#900matt2e wants to merge 2 commits into
matt2e wants to merge 2 commits into
Conversation
Fill in the ai-agent-pi stub with full support for every realistic Pi
install method:
- agents.rs: install/bridge commands for the ai-agent-pi check
(npm install -g --ignore-scripts @earendil-works/pi-coding-agent /
npm install -g pi-acp), so a missing bridge reports fixType bridge
and berd can route both through the configured registry. New
per-agent self_update_command ("pi update --self"): a curl-installed
Pi does not auto-update, but ships an updater that infers its own
prefix and package manager, so a CurlPipe main readout keeps the
update nag and surfaces that command instead of a broken npm recipe.
- types.rs/resolve.rs: new Pnpm and Bun install sources. Both link
global bins into node_modules trees, so without them the classifier
called these installs Npm and nagged with a command that would not
update them. Classification reads $PNPM_HOME/$BUN_INSTALL from the
probe env with platform defaults. Pi's curl installer footprint
(~/.local/lib/node_modules tree or ~/.local/share/pi-node) classifies
as CurlPipe ahead of the npm-layout check.
- freshness.rs: Pnpm/Bun readouts resolve installed versions from
package.json like Npm. pnpm global bins are generated shim scripts
(not symlinks), so the canonicalize-and-walk probe now falls back to
parsing the shim's embedded entrypoint path, then to scanning the
global/<layout-version> trees (pnpm <= 10 flat and pnpm 11 hashed
layouts).
- package_ids.rs: Pi main/bridge package ids for Npm, Pnpm, Bun, and
CurlPipe (main only) sources.
- lib.rs: apply_freshness threads the agent's self-update command into
main readouts; derive_update_command emits pnpm add -g / bun add -g
recipes for the new sources.
Every scenario was live-verified on a real machine through
run_checks_with_options and execute_fix_streaming_with_env_options:
not-installed, main-only + bridge fix, bridge-only, curl ~/.local
layout + pi update --self, npm and pnpm outdated-to-updated flows
(0.82.1 -> 0.83.0, pi-acp 0.0.32 -> 0.0.33), with and without a
registry override. Bun coverage is unit-test only (not installed here).
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
`CURL_INSTALLER_FOOTPRINTS` decided a binary was curl-installed by checking
whether some path existed under `$HOME`. That answers a question about the
machine, not about the binary PATH resolved to: with amp installed both ways
(curl at `~/.amp/bin`, npm-global on a user-configured prefix) the marker is
present either way, so a user-managed npm install could be labelled `CurlPipe`
and have its update nag silenced. Delete the heuristic and fix the *action* it
was standing in for.
- resolve.rs: drop `CurlInstallerFootprint`, `CURL_INSTALLER_FOOTPRINTS`,
`matches_curl_installer_footprint`, its early promotion in
`detect_install_source_inner`, and signal 1 of `fingerprint_curl_pipe`.
The fingerprint itself stays: signal 2 (a `~/.local/bin` entry symlinked into
a versioned install dir) is the sole positive classifier for cursor-agent's
and the native claude's layouts.
- resolve.rs: repair signal 2's home gate, which compared a canonicalized
symlink target against a non-canonicalized `$HOME` — any home reached through
a symlinked ancestor never matched, and the footprint was masking it.
- resolve.rs: add `npm_prefix_for_binary`, deriving `<prefix>` from the package
tree the bin entry canonicalizes into (`<prefix>/lib/node_modules/<pkg>/…`),
anchored on the first `lib`/`node_modules` pair so nested dependency trees
still yield the outer prefix.
- agents.rs/lib.rs: `derive_update_command` takes that prefix and emits
`npm install -g --prefix <P> <pkg>@latest` (shell-quoted — the command runs
under `sh -c`). npm installs into whichever prefix npm is *configured* with,
which is not always the one the resolved binary lives in; without this, an
install made with an explicit `--prefix`, or one under a node version the user
has since switched away from, gets "updated" by a second copy landing
elsewhere while the stale binary keeps resolving. Where the two agree the flag
is a no-op, and an underivable prefix falls back to the bare command. Main and
bridge readouts derive independently.
- Pi's `~/.local` installer fallback now classifies `Npm` — honestly, since the
installer runs `npm install -g --ignore-scripts --prefix ~/.local` — and
updates through the npm recipe. That makes the `CurlPipe`-gated
`self_update_command` path unreachable, so drop the field, its `pi update
--self` entry, and `agent_self_update_command`. `pi update --self` is not a
drop-in replacement in the general case: it errors out on a pnpm-managed
install ("not managed by a global npm install"), so gating on it per source
would reintroduce the same species of per-agent table.
- package_ids.rs: add Amp's npm main package `@ampcode/cli` (canonical;
`@sourcegraph/amp` is the renamed alias). Correct but inert behind a mirror
that filters young versions — Amp publishes continuously, so Block's
Artifactory serves both packages with no `latest` dist-tag; the comment says
so.
Live-verified through `run_checks_with_options` and
`execute_fix_streaming_with_env_options`: pi at `~/.local` classifies `Npm`,
gets `--prefix '/Users/…/.local'`, and upgrades 0.82.1 -> 0.83.0 in place with
no second install in any other prefix; pi at the configured prefix emits a
prefix equal to `npm prefix -g` (a no-op) and upgrades in place, main and
bridge (pi-acp 0.0.32 -> 0.0.33); a pi under a prefix that differs from the
configured one upgrades in place while the configured prefix stays untouched.
cursor-agent and the native claude still classify `CurlPipe`; curl-installed
amp still reports `Unknown` raw and `CurlPipe` via its per-agent override. All
with the Artifactory registry override appended.
Note for berd: `InstallSource` is a cross-repo wire contract and the `pnpm`/
`bun` variants added by e84c6df are still missing from berd's TS union and its
exhaustive `SOURCE_LABEL_KEYS`, so those installs render a broken "installed
via …" line. That remains outstanding and must land with the doctor rev bump.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fills in the
ai-agent-pistub in doctor's agent/provider catalog so Pi isdetected, fixable, and updatable across every realistic install method.
Changes
agents.rs— install and bridge commands for theai-agent-picheck(
npm install -g --ignore-scripts @earendil-works/pi-coding-agent/npm install -g pi-acp), so a missing bridge reportsfixType: bridgeandberd can route both through the configured registry. Adds a per-agent
self_update_command(pi update --self): a curl-installed Pi doesn'tauto-update but ships an updater that infers its own prefix and package
manager, so a
CurlPipemain readout keeps the update nag and surfaces thatcommand instead of a broken npm recipe.
types.rs/resolve.rs— newPnpmandBuninstall sources. Bothlink global bins into
node_modulestrees, so previously the classifiercalled them
Npmand suggested an update command that wouldn't work.Classification reads
$PNPM_HOME/$BUN_INSTALLfrom the probe env withplatform defaults. Pi's curl-installer footprint
(
~/.local/lib/node_modulestree or~/.local/share/pi-node) classifies asCurlPipeahead of the npm-layout check.freshness.rs—Pnpm/Bunreadouts resolve installed versions frompackage.jsonlikeNpm. pnpm global bins are generated shim scripts ratherthan symlinks, so the canonicalize-and-walk probe now falls back to parsing
the shim's embedded entrypoint path, then to scanning the
global/<layout-version>trees (pnpm ≤ 10 flat and pnpm 11 hashed layouts).package_ids.rs— Pi main/bridge package ids forNpm,Pnpm,Bun,and
CurlPipe(main only).lib.rs—apply_freshnessthreads the agent's self-update command intomain readouts;
derive_update_commandemitspnpm add -g/bun add -grecipes for the new sources.
Testing
Unit tests cover the new sources, package-id lookups, pnpm layout probing, and
fix/update command derivation (140 doctor tests passing).
Every scenario was also live-verified on a real machine through
run_checks_with_optionsandexecute_fix_streaming_with_env_options:not-installed, main-only + bridge fix, bridge-only, curl
~/.locallayout +pi update --self, and npm and pnpm outdated-to-updated flows(0.82.1 → 0.83.0,
pi-acp0.0.32 → 0.0.33), with and without a registryoverride. Bun coverage is unit-test only (bun not installed on the test
machine).