fix(ai): replace static async_hooks require in eval context - #279
fix(ai): replace static async_hooks require in eval context#279gilfoyle-sre[bot] wants to merge 11 commits into
Conversation
commit: |
c5326aa to
e9b4bee
Compare
…9) @ 2026-03-06T01:04:17.656Z
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| return globalAsyncLocalStorage as AsyncLocalStorageLikeConstructor; | ||
| } | ||
|
|
||
| return undefined; |
There was a problem hiding this comment.
AsyncLocalStorage unavailable on Node 20 ESM after removing createRequire
Medium Severity
On Node.js 20 running ESM, process.getBuiltinModule is not available (added in v22.3.0, not backported to Node 20 LTS). In ESM mode, globalThis.require and process.mainModule.require are also unavailable. globalThis.AsyncLocalStorage is not a global in Node.js. All four strategies in getAsyncLocalStorageConstructor fail, silently falling back to the in-memory manager. The old code used createRequire from node:module which worked in ESM on all Node versions. Since the context manager is reachable from the main SDK entry points (via storage.ts → app-scope.ts / context.ts), this affects all users on Node 20 ESM, not just eval users — context propagation across await boundaries will silently break.


Summary
createRequireloading ofasync_hooksinpackages/ai/src/evals/context/manager.tswith a staticAsyncLocalStorageimportpackages/ai/tsup.config.tsexternals by removing shim-only entries (async_hooks,module,node:module) and keepingnode:async_hooksWhy
@axiomhq/consolehitDynamic require of "async_hooks" is not supportedon SDK0.48.0. The eval context manager was emitting runtimerequirelogic. Static import avoids that code path entirely.Validation
cd packages/ai && pnpm buildcd packages/ai && pnpm testcreateRequire, norequire("async_hooks")) indist/chunk-Z24VQAZC.jsNote
Medium Risk
Touches async-context propagation used by evals and changes fallback behavior to throw on concurrent async runs, which could surface new runtime errors in environments without
AsyncLocalStorage. Otherwise the change is localized and covered by new unit tests.Overview
Avoids dynamic
require/createRequirepatterns forAsyncLocalStorageby reworking eval context manager loading to preferprocess.getBuiltinModule, then legacyrequire/mainModule.require, then a globalAsyncLocalStorage, and finally a fallback manager.Strengthens the fallback context manager to correctly restore context for promise-like returns and to fail fast on concurrent/nested async runs to prevent context leakage, and adds Vitest coverage for the new resolution paths and fallback edge cases.
Updates
tsupconfig to keepnode:async_hooksexternal (dropping shim-only externals) and setsremoveNodeProtocol: falseto preservenode:builtin specifiers in the ESM build.Written by Cursor Bugbot for commit d4ed30c. This will update automatically on new commits. Configure here.