Skip to content

fix(opencode): remove install-breaking upper bounds on shared deps - #12

Merged
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/opentui-peer-range
Aug 7, 2026
Merged

fix(opencode): remove install-breaking upper bounds on shared deps#12
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/opentui-peer-range

Conversation

@iceteaSA

@iceteaSA iceteaSA commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Installing 2.0.0 fails outright on a current host. Reported in Discord by two users; the trigger is anything that rebuilds the plugin cache (rm -rf ~/.cache/opencode, a fresh machine, a new install).

npm error ERESOLVE unable to resolve dependency tree
npm error Found: @opentui/core@0.5.1
npm error peer @opentui/core@"^0.4.5" from @cortexkit/opencode-antigravity-auth@2.0.0

The failure does not look like a failure. npm aborts, the plugin is never installed, and the user sees:

ProviderModelNotFoundError: Model not found: google/antigravity-claude-opus-4-6-thinking

Cause

2.0.0 declared @opentui/* as peer dependencies at ^0.4.5. On a 0.x version, caret is minor-locked — ^0.4.5 means >=0.4.5 <0.5.0. OpenTUI has since released 0.5.0 and 0.5.1.

@opencode-ai/plugin declares the same three packages as optional peers at >=0.4.5, so the host resolves 0.5.1 happily. Our range rejects it, and no single version satisfies both — hence ERESOLVE.

This was a 2.0.0 regression. 1.1.0 declared neither the OpenTUI peers nor a host-version ceiling.

Fix

Match the shape the sibling openai-auth plugin already uses:

   "peerDependencies": {
-    "@opencode-ai/plugin": "^1.17.13",
-    "@opentui/core": "^0.4.5",
-    "@opentui/keymap": "^0.4.5",
-    "@opentui/solid": "^0.4.5",
+    "@opencode-ai/plugin": "*",
     "typescript": "^5 || ^6"
   },
   "dependencies": {
+    "@opentui/core": ">=0.4.5",
+    "@opentui/keymap": ">=0.4.5",
+    "@opentui/solid": ">=0.4.5",

The ^1.17.13 ceiling on the host goes too. It is not biting yet — 1.18.11 satisfies it — but it is the same defect one major bump away, and both sibling plugins use *.

I also tested keeping the OpenTUI packages as peers marked optional. That installs cleanly but leaves them uninstalled, and the ./tui entry then fails to import. Ordinary dependencies is the correct shape for a package that imports them at runtime.

engines.opencode still reads >=1.17.13 <2. Left alone deliberately: it is advisory rather than resolver input, so it does not cause this failure, and tightening or loosening it is a separate call.

Verification

Installed the packed tarball against the exact host from the report:

$ npm i @opencode-ai/plugin@1.18.11 ./cortexkit-opencode-antigravity-auth-2.0.0.tgz
install exit=0   ERESOLVE lines=0

opentui/core : 0.5.1
opentui/solid: 0.5.1
host plugin  : 1.18.11
server entry : AntigravityCLIOAuthPlugin,GoogleOAuthPlugin
tui entry    : resolves (src/tui/entry.mjs + src/tui-compiled/tui.tsx present)

npm ls shows one hoisted copy — @opentui/core@0.5.1 with keymap and solid both deduped, so no duplicate runtime.

Gates: 1830 unit / 0 fail · 28 e2e / 0 fail · typecheck · format · lint · build · smoke:tui.

Regression guard

packages/opencode/src/package-manifest.test.ts fails when any range we publish for one of the host's own peer dependencies rejects a future version, since those must resolve to a single shared copy. It reads the host manifest from the installed tree rather than hardcoding a version, and asserts directly that 0.4.5 / 0.5.0 / 0.5.1 / 1.0.0 are all accepted.

Restoring the 2.0.0 ranges turns all three tests red:

(fail) declares no upper bound on the host's own peer dependencies
(fail) declares no upper bound on the host plugin itself
(fail) accepts the OpenTUI versions the host accepts
0 pass, 3 fail

The host's ordinary dependencies are deliberately not flagged — those can nest a second copy, so a bound there is not an install hazard. Scoping to peers only was a correction: the first version of the guard flagged zod and would have been wrong.

For affected users before a release

npm i --legacy-peer-deps

or legacy-peer-deps=true in .npmrc. Both verified — the plugin installs and the server entry loads.

This needs a patch release to reach anyone; the fix has no effect until 2.0.1 is on npm.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fix npm install failures on fresh hosts by removing upper bounds on shared OpenTUI packages and making them direct dependencies. Adds a guard test to block future ceilings and duplicated installs so one version is shared with the host.

  • Bug Fixes
    • Moved @opentui/core, @opentui/keymap, @opentui/solid from peerDeps ^0.4.5 to deps >=0.4.5 to allow 0.5.x+ and match the host.
    • Relaxed @opencode-ai/plugin peer range to *.
    • Added package-manifest.test.ts to fail on any ceilings, assert OpenTUI 0.4.5/0.5.x/1.x are accepted, and verify exactly one installed copy across ancestor and nested trees (hardlinks handled).

Written for commit a4761e7. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/src/package-manifest.test.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 1 file (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/src/package-manifest.test.ts Outdated
`@opentui/*` was declared as a peer at `^0.4.5`. On a 0.x version that caret
means `>=0.4.5 <0.5.0`, so once OpenTUI released 0.5.0 the range stopped
matching what the host resolves. `@opencode-ai/plugin` declares the same
packages as optional peers at `>=0.4.5` and happily takes 0.5.x, leaving npm
with no satisfiable tree:

    npm error Found: @opentui/core@0.5.1
    npm error peer @opentui/core@"^0.4.5" from @cortexkit/opencode-antigravity-auth@2.0.0

The install aborts, so the plugin is simply absent — which surfaces to users as
`ProviderModelNotFoundError: Model not found: google/antigravity-*` rather than
as an install failure. Anyone whose plugin cache was rebuilt hit it.

Declare the OpenTUI packages as ordinary dependencies at `>=0.4.5` (the shape
the sibling openai-auth plugin already uses) and drop the `^1.17.13` ceiling on
the host plugin, which would have caused the same class of break at 2.x.

Add a manifest guard covering both halves of the failure. Statically: no range
we publish for one of the host's own peer dependencies may reject a future
version, since those must resolve to one shared copy. Against the installed
tree: exactly one distinct copy of each such package, satisfying our range and
the host's at once. The static half matters because a ceiling is wrong the day
it is written but stays green until the ecosystem crosses it — which is how
this reached users.

Copy detection scans one nested level (`node_modules/<dep>/node_modules/<name>`,
scoped owners included) as well as the ancestor chain, because npm parks a
forced duplicate under the dependent that caused it. Identity is `dev:inode`,
not path or realpath: Bun's store hardlinks packages, so realpath neither
collapses every alias nor separates two physically distinct files.
@iceteaSA
iceteaSA force-pushed the fix/opentui-peer-range branch from 4731b29 to a4761e7 Compare August 5, 2026 05:43
@ualtinok
ualtinok merged commit 3f465da into cortexkit:main Aug 7, 2026
5 checks passed
ualtinok pushed a commit that referenced this pull request Aug 7, 2026
P3 #11: the e2e mock's quotaSummaryWindow fixture dropped fixture
headers before writing the body. Apply them via the shared
applyHeaders seam so cache-bust and trace-header tests have a path.

P3 #12: the quota-manager 'back-compat' test loaded a windows-shaped
fixture rather than exercising a windows-less legacy shape through
the real read path. Rewire it through a hand-rolled
RetrieveUserQuotaSummaryResponse that omits per-window data.

P3 #13: account-manager 'remove-during-refresh' test never
attempted the quota write, so the expectedRefreshToken guard wasn't
exercised. Call updateQuotaCache(0, …, refreshTokenForA) after the
removal so the assertion covers the actual cross-account guard.

P3 #14: the sidebar-state 'half-missing stamp' test covered only
the cachedQuotaAccountId-only case. Add the symmetric
currentQuotaAccountId-only case so legacy snapshots missing the
persisted stamp don't silently drop quota.

P3 #15: account-command-oauth failure messages said 'Please try
again' even though the pending entry was consumed and the same code
could not be redeemed. Update the messages to 'start a new OAuth
flow' so the operator knows the OAuth session is gone.

P3 #16: tighten the account-command-oauth test assertions — pin
the failed-exchange response, pin the full persisted success object
(not just label), assert 'Work account' renders in the
add-oauth-finish dialog, and restore an explicit unknown-key legacy
fixture for the renderer.

The tui-compiled mirror of command-data.ts is regenerated by the
build:tui gate so the bundled TUI payload matches the source.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants