Skip to content

bug(install): gentle-pi hard-depends on host-provided @earendil-works/pi-tui (and pi-ai on main), tripping the extension-loader warning and hoisting a stale duplicate #1564

Description

@Leoglez10

Problem

Pi's extension loader warns about gentle-pi/package.json on every startup:

Warning: Extension package "…/node_modules/gentle-pi/package.json":
 Host-provided extension packages must be declared in peerDependencies with a "*" range, not dependencies:
 @earendil-works/pi-tui. Installed copies can bypass the extension loader and create duplicate runtime modules.

@earendil-works/pi-tui is in the host's own allowlist of host-provided extension packages (the HOST_PROVIDED_EXTENSION_PACKAGES set in the Pi coding agent's resource loader), together with @earendil-works/pi-ai, @earendil-works/pi-coding-agent, typebox, @sinclair/typebox, and the @mariozechner/* equivalents. Pi already supplies every one of them to extensions.

Published gentle-pi@3.7.0 (current latest) declares:

"dependencies": {
  "@earendil-works/pi-tui": "0.85.1",
  "@heyhuynhgiabuu/pi-pretty": "0.6.27"
},
"peerDependencies": {
  "@earendil-works/pi-coding-agent": ">=0.85.1",
  "typebox": "*"
}

@earendil-works/pi-coding-agent and typebox are already declared correctly as peers, so the remaining hard dependency on a host-provided module reads as an oversight rather than intent. @heyhuynhgiabuu/pi-pretty is genuinely third-party and correctly stays a regular dependency.

package.json on main has the same problem and is worse: it also hard-depends on @earendil-works/pi-ai, which is in the same host-provided allowlist, so the same warning and the same hoisting will ship with the next release.

Why this matters beyond the warning

Declaring a host-provided package as a dependency gives npm a reason to hoist the extension-local copy into the shared tree root, where it is resolved instead of the host's. Observed in a ~/.pi/agent/npm tree, same session:

module tree copy host copy (pi-coding-agent 0.99.1)
@earendil-works/pi-tui 0.85.1 0.99.1

require.resolve("@earendil-works/pi-tui") executed from the tree root returns the tree copy, not the host's, so the tree copy is the one on the resolution path for anything inside that tree. gentle-pi imports @earendil-works/pi-tui from 61 sites, which is what turns a 14-minor version skew into a live divergence rather than a theoretical one; the loader's own warning wording ("bypass the extension loader and create duplicate runtime modules") is describing exactly this.

Steps to reproduce

  1. Install gentle-pi@3.7.0 into a Pi agent npm tree managed by npm (~/.pi/agent/npm), e.g. as a dependency of that tree's root package.json.
  2. Start pi.
  3. Observe the loader warning naming @earendil-works/pi-tui.
  4. Compare the hoisted copy against the host's:
    • from the tree root: node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"
    • from the pi-coding-agent install tree: node -p "require('./node_modules/@earendil-works/pi-tui/package.json').version"

Expected and actual behavior

Expected: no loader warning, and gentle-pi resolving the host's single @earendil-works/pi-tui and @earendil-works/pi-ai instances, with no extension-local copy hoisted into the shared tree.

Actual: the loader warns on every startup, and the tree root holds a @earendil-works/pi-tui copy at 0.85.1 while the host runs 0.99.1.

gentle-pi version

3.7.0 (published, current latest)

Pi version

0.99.1 (host ships @earendil-works/pi-tui 0.99.1)

Operating system

macOS

Relevant logs or error output (optional)

Warning: Extension package "…/node_modules/gentle-pi/package.json":
 Host-provided extension packages must be declared in peerDependencies with a "*" range, not dependencies:
 @earendil-works/pi-tui. Installed copies can bypass the extension loader and create duplicate runtime modules.
{
  "dependencies": { "@earendil-works/pi-tui": "0.85.1", "@heyhuynhgiabuu/pi-pretty": "0.6.27" },
  "peerDependencies": { "typebox": "*", "@earendil-works/pi-coding-agent": ">=0.85.1" }
}

Suggested fix

Move @earendil-works/pi-tui — and @earendil-works/pi-ai on main — from dependencies to peerDependencies, mirroring how @earendil-works/pi-coding-agent and typebox are already declared here. Add peerDependenciesMeta.optional for both if gentle-pi should stay installable outside a Pi host.

This is the same defect class as Gentleman-Programming/engram#853, which was fixed for gentle-engram's @earendil-works/pi-tui; the identical remaining entry for gentle-engram's typebox is noted there.

Before submitting

  • I searched open and closed issues and did not find a report of this problem.
  • I reviewed this report and removed credentials, tokens, private paths, hostnames, and other sensitive data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstatus:needs-reviewAwaiting maintainer review/approvaltype:bugBug fix

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions