fix(workflow-executor): enforce a minimum Node.js version - #1641
Conversation
|
[claude-opus-4-8] Review resolution summary — flagging 3 points for your call before this advances Addressed in Three points I'm pushing back on rather than changing — paused for your decision:
Happy to apply any of these if you'd prefer — none are blockers, just judgment calls I wanted your eyes on. |
|
[claude-opus-4-8] Resolution update — the three flagged points are now closed:
Floor behaviour is unchanged (Node 20). 13 tests pass; ESLint + Prettier clean on the changed files. Nothing left open from this round. |
On an unsupported Node.js runtime the executor crashed with a cryptic low-level error from its dependencies, with no hint that the Node version was the cause. A preflight guard now fails fast with a clear message before the heavy imports (koa, @langchain/openai) load, and the engines field declares the requirement. Minimum is Node 20, the floor required by @langchain/openai. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Trim the test header to the essential rationale and remove the it.todo placeholders: malformed input is unreachable since process.version is always well-formed, and the import-ordering invariant is covered by manual verification on an old runtime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address review feedback on the node-version guard: shorten the cli.ts and README notes, clarify the test header on fixture-vs-floor usage, and assert minor/patch versions at the floor major. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Read MINIMUM_NODE_MAJOR from the package.json engines range instead of hardcoding it, so the runtime guard and the install-time engines declaration share one source and cannot drift. Tests reference the derived constant rather than literal majors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the deferred require() + eslint-disable in the bin with typed `await import()`, which compiles to the same deferred require under CommonJS but needs no disable and carries the module types. Trim the guard module comment, and drop the README Node-version note now that package.json engines is the single source of truth. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Use the single regex-based parseMajor for both the engines range and the runtime version, removing the duplicate major-parsing logic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump engines.node from >=20.0.0 to >=22.12.0; MINIMUM_NODE_MAJOR derives to 22 accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compare the full major.minor.patch against engines.node (>=22.12.0) instead of the major only, so e.g. Node 22.11 is correctly rejected. MINIMUM_NODE_MAJOR becomes MINIMUM_NODE_VERSION. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the hardcoded floor assertion (toBe("22.12.0")) with a shape
check so it no longer needs editing on every version bump, and drop a
redundant comment on parseVersion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3d27771 to
c4f7173
Compare
|
Coverage Impact ⬆️ Merging this pull request will increase total coverage on Modified Files with Diff Coverage (1)
🛟 Help
|
qlty diff coverage flagged the changed lines. Mark the CLI entrypoint with /* istanbul ignore file */ (side effects, not unit-testable; its guard and run wiring are unit-tested in check-node-version and cli-core) and add tests for the default printError/exit path and unparseable input, taking check-node-version.ts to 100% line coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
beed3fb to
8577b19
Compare
## @forestadmin/workflow-executor [1.0.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/workflow-executor@1.0.0...@forestadmin/workflow-executor@1.0.1) (2026-06-10) ### Bug Fixes * **workflow-executor:** enforce a minimum Node.js version ([#1641](#1641)) ([23c594a](23c594a))

Summary
The workflow-executor did not declare or enforce a minimum Node.js version. On a too-old runtime it crashed with a cryptic low-level error from its dependencies, giving the user no hint that the Node version was the cause.
This adds:
src/check-node-version.ts) that fails fast with a clear message and a non-zero exit code.engines: { "node": ">=20.0.0" }inpackage.json— install-time signal.cli.tsruns the guard before loading the heavy CLI modules, sokoa/@langchain/openaiare never evaluated on a runtime too old to load them. Without this ordering the transitive imports crash first and the user never sees the version message. (Typed via erasedimport type * asso type safety is preserved.)Why Node 20
20 is the real hard dependency floor (
@langchain/openairequires>=20, koa>=18) and an active LTS — the lowest version that actually works, so the executor fails fast below it without rejecting versions that would otherwise run. Trivially overridable viaMINIMUM_NODE_MAJOR+ the engines string; the tests are floor-agnostic.Tests
v-prefix, major-only), the message wording, the print +exit(1)behaviour, idempotency, andengines/floor consistency.cli.test.tsregression passes.it.todoplaceholders flag deliberately-deferred items: malformed-version policy (a decision;process.versionis always well-formed) and the before-heavy-imports ordering (best verified end-to-end on a real old runtime).Notes for the reviewer
tscerrors in@forestadmin/ai-proxy/datasource-toolkit(BaseChatModel,Collection.getOne) — these are present onmainand clear once the workspace deps are rebuilt; this PR does not touch those packages.fixes PRD-496
🤖 Generated with Claude Code
Note
Enforce a minimum Node.js version (>=22.12.0) in the workflow-executor CLI
checkNodeVersionguard incheck-node-version.tsthat comparesprocess.versionagainst the minimum declared inpackage.json; exits with code 1 and a descriptive stderr message on unsupported runtimes.cli.tsbefore any other module loads; subsequent imports are made dynamic so the check runs first."engines": { "node": ">=22.12.0" }inpackage.jsonso package managers can also warn or reject installs on unsupported runtimes.Macroscope summarized 8577b19.