Skip to content

fix(plugin-runner): emit ESM bundles for Node plugins - #627

Closed
mikemikimike wants to merge 6 commits into
lmstudio-ai:mainfrom
mikemikimike:codex/fix-586-esm-output
Closed

fix(plugin-runner): emit ESM bundles for Node plugins#627
mikemikimike wants to merge 6 commits into
lmstudio-ai:mainfrom
mikemikimike:codex/fix-586-esm-output

Conversation

@mikemikimike

@mikemikimike mikemikimike commented Aug 12, 2026

Copy link
Copy Markdown

Summary

  • Emit Node plugin bundles as ESM.
  • Add regression coverage for the shared esbuild arguments.

Problem

Node plugins with "type": "module" failed at runtime because esbuild's default Node format generated CommonJS require calls for .lmstudio/dev.js and .lmstudio/production.js.

Call graph

packages/lms-es-plugin-runner/src/esbuildArgs.ts:16 (createEsBuildArgs)
NodePluginInstaller / NodePluginRunnerWatcher
→ esbuild output .lmstudio/dev.js or .lmstudio/production.js

The shared argument builder now passes --format=esm, so the generated files load correctly in ESM plugin packages.

Tests

  • npm test -- --runInBand --coverage=false --silent
  • npx turbo run build --filter=@lmstudio/lms-es-plugin-runner...
  • npx tsc --build packages/lms-es-plugin-runner/tsconfig.json
  • npx prettier --check packages/lms-es-plugin-runner/src/esbuildArgs.ts packages/lms-es-plugin-runner/src/esbuildArgs.test.ts
  • npx eslint packages/lms-es-plugin-runner/src/esbuildArgs.ts packages/lms-es-plugin-runner/src/esbuildArgs.test.ts
  • git diff --check

Fixes #586

Review update validation

  • npm test -- --runInBand --coverage=false --silent packages/lms-es-plugin-runner/src/esbuildArgs.test.ts — 2 passed
  • npx prettier --check packages/lms-es-plugin-runner/src/esbuildArgs.ts packages/lms-es-plugin-runner/src/esbuildArgs.test.ts — passed
  • npx eslint packages/lms-es-plugin-runner/src/esbuildArgs.ts packages/lms-es-plugin-runner/src/esbuildArgs.test.ts — passed
  • git diff --check — passed
  • npx tsc --build packages/lms-es-plugin-runner/tsconfig.json — not completed in this clean checkout because npm ci's repository postinstall could not find the @lmstudio/lms-cli workspace, leaving @lmstudio/lms-common and @lmstudio/lms-common-server unlinked; the focused test compiles and executes the banner under Node.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bcfcb3810c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/lms-es-plugin-runner/src/esbuildArgs.ts
@mikemikimike

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@github-actions github-actions Bot added the CLA signed Indicates if all contributors have signed the CLA label Aug 23, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bcc0370a3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/lms-es-plugin-runner/src/esbuildArgs.ts
@mikemikimike
mikemikimike force-pushed the codex/fix-586-esm-output branch from 548f126 to 144a693 Compare August 23, 2026 16:05

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 144a69372f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/lms-es-plugin-runner/src/esbuildArgs.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1fd6d1714

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

"--bundle",
"--format=esm",
// Keep CommonJS plugin sources that use Node's module and file globals working in the ESM bundle.
'--banner:js=import { createRequire as __lmsCreateRequire } from "module"; import { fileURLToPath as __lmsFileURLToPath } from "url"; import { dirname as __lmsDirname } from "path"; const require = __lmsCreateRequire(import.meta.url); const __filename = __lmsFileURLToPath(import.meta.url); const __dirname = __lmsDirname(__filename);',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid redeclaring plugin-provided ESM globals

When an ESM plugin already defines the customary createRequire/fileURLToPath polyfills for require, __filename, or __dirname, this banner is inserted verbatim without participating in esbuild's symbol renaming. The bundled plugin declarations can therefore share the output scope with these const declarations, causing the generated dev.js or production.js to fail parsing with an identifier-already-declared error; inject collision-safe symbols or only provide these bindings when the bundle does not define them.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 6f27c2f. The ESM banner no longer declares top-level require, __filename, or __dirname; it defines missing bindings on globalThis instead, so plugin-provided ESM polyfills do not cause duplicate declaration errors while CommonJS globals remain available. Added a runtime regression that executes the banner alongside plugin-provided bindings. Focused Jest: 3 passed; ESLint: passed; git diff --check: passed. TypeScript build remains blocked by the existing clean-checkout workspace-link issue for @lmstudio/lms-common and @lmstudio/lms-common-server.

@mikemikimike
mikemikimike deleted the codex/fix-586-esm-output branch August 31, 2026 12:48
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 31, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

CLA signed Indicates if all contributors have signed the CLA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP's don't work because require() is used instead of import

1 participant