Skip to content

bug(install): gentle-pi ships host-provided @earendil-works/pi-tui as a dependency, hoisting a duplicate 0.85.1 copy over the host 0.99.0 #1559

Description

@nicoarias81

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.

Problem

gentle-pi@3.7.0 declares @earendil-works/pi-tui in dependencies:

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

pi-tui is a host-provided module: the Pi installation always supplies it, and this package already peer-declares pi-coding-agent for exactly the same reason. Declaring it as a hard dependency gives npm a legal reason to install a second copy into the extension tree, and Pi's extension loader reports it on every startup:

Warning: Extension package "<npm-root>/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.

The duplicate is not inert — it shadows the host's copy at import time, and the two copies are different versions:

module resolved from gentle-pi host copy
@earendil-works/pi-tui 0.85.1 0.99.0

The package imports pi-tui directly in roughly 20 modules (extensions/gentle-ai.ts:33, the other extensions under extensions/, and lib/agents-view.ts, lib/shell-bar.ts, lib/native-choice-list.ts, lib/questionnaire/questionnaire-view.ts, lib/review-consent-component.ts). Symbols crossing that boundary — Key constants, matchesKey, KeybindingsManager, truncateToWidth — come from a different module instance than the one rendering the UI, which is precisely the duplicate-runtime-module failure the warning describes.

Steps to reproduce

  1. Install gentle-pi@3.7.0 into a Pi npm extension tree (~/.pi/agent/npm).
  2. Start Pi.
  3. Observe the Host-provided extension packages ... @earendil-works/pi-tui warning on stderr.
  4. Confirm that bare imports resolve the duplicate, not the host copy:
$ cd ~/.pi/agent/npm/node_modules/gentle-pi
$ node -e "console.log(require.resolve('@earendil-works/pi-tui'))"
<npm-root>/node_modules/@earendil-works/pi-tui/dist/index.js
$ node -e "console.log(require(require.resolve('@earendil-works/pi-tui/package.json')).version)"
0.85.1
$ node -e "console.log(require('<pi-install-root>/node_modules/@earendil-works/pi-tui/package.json').version)"
0.99.0

Expected and actual behavior

Expected: @earendil-works/pi-tui is declared in peerDependencies with a "*" range and never in dependencies — exactly how this package already declares typebox. npm installs no second copy, the host's pi-tui is the only one in the module graph, and the loader emits no warning.

Actual: npm installs @earendil-works/pi-tui@0.85.1 into the extension tree, it shadows the host's 0.99.0 copy for every bare import in the package, and the extension loader emits the duplicate-runtime-module warning on every startup.

gentle-pi version

3.7.0 (npm view gentle-pi version -> 3.7.0)

Pi version

0.99.0

Operating system

Windows

Relevant logs or error output (optional)

Warning: Extension package "<npm-root>/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.

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 workingduplicateThis issue or pull request already existsstatus: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