Skip to content

fix(config): extract package name from node_modules file:// URLs in getPluginName#17718

Closed
yufeikang wants to merge 1 commit intoanomalyco:devfrom
yufeikang:fix/getPluginName-file-url-dedup
Closed

fix(config): extract package name from node_modules file:// URLs in getPluginName#17718
yufeikang wants to merge 1 commit intoanomalyco:devfrom
yufeikang:fix/getPluginName-file-url-dedup

Conversation

@yufeikang
Copy link
Copy Markdown

@yufeikang yufeikang commented Mar 16, 2026

Issue for this PR

Closes #17716

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

getPluginName returns path.parse(url.pathname).name for file:// URLs, which yields "index" for any plugin whose entry point is index.js/index.ts (the vast majority of npm packages). When load() resolves two npm plugins to file:// paths via import.meta.resolve, deduplicatePlugins sees them both as "index" and silently drops one.

This fix detects /node_modules/ in the file path and extracts the actual npm package name (including scoped packages) instead of the bare filename.

file:///config/node_modules/oh-my-opencode/dist/index.js     → "oh-my-opencode"
file:///config/node_modules/@scope/plugin/dist/index.js      → "@scope/plugin"
file:///path/to/plugin/foo.js                                → "foo" (unchanged)

How did you verify your code works?

  • Added unit tests for getPluginName with node_modules paths (unscoped and scoped packages)
  • Added unit test for deduplicatePlugins confirming distinct node_modules/*/index.js entries are no longer treated as duplicates
  • All existing and new tests pass: bun test test/config/config.test.ts -t "getPluginName|deduplicatePlugins" (10 pass, 0 fail)
  • Reproduced the original issue locally: confirmed oh-my-opencode was being dropped due to name collision with opencode-openai-codex-auth (both resolved to "index")

Screenshots / recordings

N/A - no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…etPluginName

getPluginName returned the bare filename (e.g. 'index') for file:// URLs
resolved from node_modules, causing deduplicatePlugins to treat unrelated
plugins with index.js entry points as identical and silently drop all but
one.

Now detects '/node_modules/' in the path and extracts the npm package name
(including scoped packages) instead of the filename.
@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

I found several related PRs addressing similar issues with plugin deduplication and file:// URL handling:

Potential Related/Duplicate PRs:

  1. fix(opencode): prevent plugin deduplication collision for index.js entry points #11161 - fix(opencode): prevent plugin deduplication collision for index.js entry points

  2. fix(config): avoid dedup collisions for file:// plugins in node_modules #15598 - fix(config): avoid dedup collisions for file:// plugins in node_modules

  3. fix(config): use package.json name for file:// plugin identity #16200 - fix(config): use package.json name for file:// plugin identity

These PRs appear to be addressing the same or very similar issues with plugin deduplication when resolving file:// URLs in node_modules. Check if any of these were previously closed or merged without fully resolving the issue (issue #17716).

@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

Bug: getPluginName returns 'index' for file:// resolved plugins, causing deduplicatePlugins to silently drop unrelated plugins

1 participant