Conversation
- Replace dynamic `esmRequire()` calls with static ES imports in anthropic, gemini, and openai factory modules - Add conditional spread operator for optional `defaults` field to avoid undefined values in provider config - Expand E2E test scope to verify published package works as both MCP server and library - Add consumer script generator to test all public exports, type declarations, and factory functions - Document why dynamic requires break in esbuild bundles and how this test catches such issues - Improve test clarity with detailed pipeline steps and verification checklist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #27.
Provider factories (
openAI,anthropic,gemini) usedcreateRequire(import.meta.url)with relative paths to load internal provider classes (../providers/OpenAIProvider.js). esbuild cannot statically analyzeesmRequire(...)calls — they are opaque function calls, notimport/requirestatements — so it leaves them as-is in the bundle. In the published package,out/dist/index.jsis a single bundled file. The relative path../providers/OpenAIProvider.jsdoes not exist on disk, causingMODULE_NOT_FOUNDat runtime for any consumer who calls a factory.esmRequireremains correct for external peer dependencies (openai,@anthropic-ai/sdk,@google/generative-ai) — these are markedexternalin esbuild config and must resolve at runtime from the consumer'snode_modules.Root cause
createRequire(import.meta.url)('../providers/OpenAIProvider.js')insidecreate:callback of each factory. esbuild bundles all internal modules into one file but cannot trace dynamicesmRequire(...)calls, so the require to an internal module survives into the bundle as a broken runtime path.Fix
Replace
esmRequire('../providers/XxxProvider.js')with static ESMimport { XxxProvider }at module top level. Internal modules are part of the bundle — esbuild inlines them. No lazy loading benefit was lost becausesrc/provider/index.tsalready statically exports all three provider classes, meaning they were already in the bundle regardless.Also fixes a latent
exactOptionalPropertyTypestype error that was hidden by theany-typedesmRequirereturn:defaults: options.defaultspassedundefinedto an optional property. Fixed via conditional spread.Changes
src/provider/factories/openai.tsesmRequire('../providers/OpenAIProvider.js')→ staticimport { OpenAIProvider }src/provider/factories/anthropic.tsesmRequire('../providers/AnthropicProvider.js')→ staticimport { AnthropicProvider }src/provider/factories/gemini.tsesmRequire('../providers/GoogleGeminiProvider.js')→ staticimport { GoogleGeminiProvider }src/provider/factories/openai.tsdefaults: options.defaults→ conditional spread forexactOptionalPropertyTypessrc/provider/factories/anthropic.tsdefaultsfixsrc/provider/factories/gemini.tsdefaultsfixtest/e2e/mcp-agentic-pack-e2e.tsWhy the pack e2e test didn't catch this
The previous
mcp-agentic-pack-e2e.tstested only the CLI binary (mcp-agentic) — it started the bare server, connected via stdio, and verified 8 tools respond. The CLI binary does not import provider factories. No test exercisedimport { openAI } from '@stdiobus/mcp-agentic'from an installed tarball — the exact path that breaks.New pack e2e coverage (66 checks)
mcp-agentic, 8 tools, health checkopenAI(),anthropic(),gemini()without SDK → BridgeError CONFIGdefineProvider→createMultiProviderAgent→McpAgenticServer→ session → prompt.d.tsfiles existVerified
npm run typechecknpm run test:unitnpm run test:e2enpm run buildproviders/references inout/dist/index.jsScope
4 source files changed (3 factory files + 1 e2e test). Net logic change: 3 lines replaced per factory (import + conditional spread). No public API changes. No behavior changes.