Upgrade Node to 26.2.0 and refresh lockfile dependencies#15
Conversation
📝 WalkthroughWalkthroughThis PR updates Node.js to version 26.2.0 across configuration and dependencies, introduces a ChangesNode.js version upgrade across tooling and configuration
localStorage abstraction pattern
Socket data normalization
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Bump pinned Node version in `.mise.toml` and AGENTS docs from 24.13.1 to 26.2.0. - Update `bun.lock` to newer `oxfmt`, `oxlint`, `turbo`, `vitest`, and `@types/node` (plus `undici-types`) versions. - Refresh associated platform-specific lock entries for the updated tooling packages, including new `@turbo/*` variants and matching hashes.
- Convert incoming socket data chunks to `Buffer` in `handleSocketConnection` - Preserve existing close/pending logic while handling non-Buffer chunk payloads
2d1a817 to
21fda52
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
11-11:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate Node.js badge to reflect the version upgrade.
The badge still displays
Node.js-24but this PR upgrades Node to version 26.2.0. Update the badge to maintain consistency with the actual pinned version.📛 Proposed fix
- +🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` at line 11, Update the Node.js badge in README.md: locate the markdown image tag starting with "" and change the version label from "24" to the new pinned version "26.2.0" so the URL and visible badge reflect Node.js-26.2.0.
🧹 Nitpick comments (1)
apps/desktop/src/browserUsePipeServer.ts (1)
210-213: ⚡ Quick winConsider aligning with the defensive normalization pattern used elsewhere in desktop.
The current normalization works but differs slightly from the pattern in
captureBackendOutput(see context snippet frommain.ts:513-520), which explicitly converts toString(chunk)before creating the Buffer. That approach is more defensive against unexpected chunk types.♻️ Align with the established pattern
socket.on("data", (chunk) => { - const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); + const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk), "utf8"); this.handleSocketData(socket, buffer); });Based on learnings: this change keeps desktop behavior consistent with the normalization pattern shown in the relevant context snippet from
apps/desktop/src/main.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/desktop/src/browserUsePipeServer.ts` around lines 210 - 213, Normalize incoming socket chunks the same way as captureBackendOutput by converting chunk to a string first before creating a Buffer; in the socket.on("data", ...) handler use Buffer.from(String(chunk)) (instead of Buffer.from(chunk)) and pass that buffer into this.handleSocketData so the defensive normalization matches captureBackendOutput and handles unexpected chunk types consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/lib/storage.ts`:
- Around line 26-31: getLocalStorage currently checks typeof localStorage which
can return Node 26's globalThis.localStorage; update getLocalStorage to require
a browser window by checking that typeof window !== "undefined" and typeof
window.localStorage !== "undefined" before returning window.localStorage, and
throw when not present so zustand's createJSONStorage will disable persistence
in non-browser runtimes; reference the getLocalStorage function and ensure
callers (e.g., any use with createJSONStorage/zustand persistence) keep
expecting a throwing getter in non-browser environments.
In `@package.json`:
- Line 18: Update the devDependency version for the TypeScript Node typings:
replace occurrences of "`@types/node`": "^25.9.1" in package.json with a Node
26-compatible range such as "^26.0.0" (or "^26.x") so the project typings align
with Node 26; ensure you update every instance of the "`@types/node`" entry in
package.json and run your install to refresh lockfile.
---
Outside diff comments:
In `@README.md`:
- Line 11: Update the Node.js badge in README.md: locate the markdown image tag
starting with
""
and change the version label from "24" to the new pinned version "26.2.0" so the
URL and visible badge reflect Node.js-26.2.0.
---
Nitpick comments:
In `@apps/desktop/src/browserUsePipeServer.ts`:
- Around line 210-213: Normalize incoming socket chunks the same way as
captureBackendOutput by converting chunk to a string first before creating a
Buffer; in the socket.on("data", ...) handler use Buffer.from(String(chunk))
(instead of Buffer.from(chunk)) and pass that buffer into this.handleSocketData
so the defensive normalization matches captureBackendOutput and handles
unexpected chunk types consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c02bfd45-b751-4eda-b8d3-6b13860a6008
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (14)
.mise.tomlAGENTS.mdREADME.mdapps/desktop/src/browserUsePipeServer.tsapps/web/src/browserStateStore.tsapps/web/src/latestProjectStore.tsapps/web/src/lib/storage.tsapps/web/src/pinnedThreadsStore.tsapps/web/src/repoDiffScopeStore.tsapps/web/src/singleChatPanelStore.tsapps/web/src/splitViewStore.tsapps/web/src/terminalStateStore.tsapps/web/src/workspaceStore.tspackage.json
| export function getLocalStorage(): Storage { | ||
| if (typeof localStorage === "undefined") { | ||
| throw new Error("localStorage is not available"); | ||
| } | ||
| return localStorage; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Node.js v26.2.0, can globalThis.localStorage exist outside a browser runtime, and what are the documented conditions/limitations?
💡 Result:
In Node.js v26.2.0, globalThis.localStorage does exist as part of a browser-compatible implementation of the Web Storage API [1][2]. However, its availability and behavior depend on specific runtime conditions and CLI configurations: Conditions and Limitations 1. CLI Flag Requirement: To access localStorage, you must provide the --localstorage-file CLI flag, which specifies the file path where data is stored unencrypted [1][2]. 2. Error Handling: As of Node.js v26.0.0, attempting to access globalThis.localStorage without providing the --localstorage-file flag causes the runtime to throw a DOMException [1][2]. This change was introduced for compliance with the Web Storage specification [1]. 3. Nature of Storage: The data is not stored per-user or per-request; it is shared globally across all users and requests within the process context [1][2]. 4. Capacity: The implementation enforces a maximum storage limit of 10 MB [1][2]. 5. Stability: The API is marked as "Release candidate" (Stability: 1.2) and can be explicitly disabled using the --no-experimental-webstorage flag [1][2]. 6. Usage Note: Modifying the specified storage file outside of the Web Storage API is not supported [1][2]. Because this implementation is intended for specific use cases and has strict requirements, developers often continue to use user-land packages (such as node-localstorage) for legacy compatibility or when a different storage strategy is required [3][4]. Applications relying on localStorage should be aware that its presence in the global scope on Node.js can cause issues for code designed specifically for browser environments that check for typeof localStorage !== "undefined" without verifying the environment [5][6].
Citations:
- 1: https://nodejs.org/api/globals.html
- 2: https://nodejs.org/docs/latest-v26.x/api/globals.html
- 3: https://stackoverflow.com/questions/10358100/how-to-access-localstorage-in-node-js
- 4: https://rxdb.info/articles/localstorage.html
- 5: https://dev.to/gaurav101/internals-of-uselocalstoragestate-hook-2m93
- 6: [Bug]: localStorage.getItem is not a function on Node.js 25+ (window = globalThis breaks SSR guard) pacocoursey/next-themes#389
🌐 Web query:
In zustand v5 (createJSONStorage), what is the behavior when the provided storage getter throws?
💡 Result:
In Zustand v5, the createJSONStorage helper function includes a try-catch block around the provided storage getter [1][2]. If the getter function throws an error, the error is caught, and the function returns undefined [1][2]. This behavior is explicitly designed to handle environments where the intended storage might not be available, such as during server-side rendering (SSR) when attempting to access browser-specific APIs like localStorage or sessionStorage [1][2]. By returning undefined, the persist middleware will fail to initialize the storage, effectively bypassing persistence rather than crashing the application [1][2].
Citations:
- 1: https://github.com/pmndrs/zustand/blob/8e8156f1426105e75f4e041c92bb4561e7dd1e61/src/middleware/persist.ts
- 2: Persist storage save individual state items in a store as a new key-value pair (which in turn is serialized/deserialized) instead of entire state serialized/deserialized pmndrs/zustand#2849
Guard getLocalStorage() against Node 26 globalThis.localStorage by requiring window.
typeof localStorage === "undefined" is not a reliable browser check in Node.js 26: globalThis.localStorage can be present depending on runtime configuration, so this helper may return Node’s Web Storage and route zustand persistence unexpectedly. Throwing in non-browser runtimes is fine—zustand v5 createJSONStorage will catch a throwing getter and disable persistence.
🔧 Proposed fix
export function getLocalStorage(): Storage {
- if (typeof localStorage === "undefined") {
+ if (
+ typeof window === "undefined" ||
+ typeof window.localStorage === "undefined"
+ ) {
throw new Error("localStorage is not available");
}
- return localStorage;
+ return window.localStorage;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function getLocalStorage(): Storage { | |
| if (typeof localStorage === "undefined") { | |
| throw new Error("localStorage is not available"); | |
| } | |
| return localStorage; | |
| } | |
| export function getLocalStorage(): Storage { | |
| if ( | |
| typeof window === "undefined" || | |
| typeof window.localStorage === "undefined" | |
| ) { | |
| throw new Error("localStorage is not available"); | |
| } | |
| return window.localStorage; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/lib/storage.ts` around lines 26 - 31, getLocalStorage currently
checks typeof localStorage which can return Node 26's globalThis.localStorage;
update getLocalStorage to require a browser window by checking that typeof
window !== "undefined" and typeof window.localStorage !== "undefined" before
returning window.localStorage, and throw when not present so zustand's
createJSONStorage will disable persistence in non-browser runtimes; reference
the getLocalStorage function and ensure callers (e.g., any use with
createJSONStorage/zustand persistence) keep expecting a throwing getter in
non-browser environments.
| "@effect/language-service": "0.75.1", | ||
| "@types/bun": "^1.3.9", | ||
| "@types/node": "^24.10.13", | ||
| "@types/node": "^25.9.1", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Are @types/node version 25.9.1 and vitest version 4.1.7 compatible with Node.js 26.2.0?
💡 Result:
Answer: Not fully guaranteed. @types/node@25.9.1 is not the official type package line for Node.js 26.x, while vitest@4.1.7 should support Node.js 26.2.0 (because it requires Node.js >=20 with additional peer/engine constraints that Node 26 satisfies), but you may still hit type-level or runtime edge cases due to the @types/node mismatch. 1) Node.js 26.2.0 context Node.js 26 is a “Current” major line and is released as 26.0.0 (current) with later minors thereafter. [1][2] 2) @types/node@25.9.1 vs Node.js 26.2.0 @types/node versions track Node.js versions (DefinitelyTyped follows the corresponding library’s versioning scheme). [3] @types/node@25.9.1 is in the 25.x series, so it corresponds to Node 25.x API/type surface rather than Node 26.x. Based on the version-tracking behavior, it is not explicitly “compatible” for Node 26 specifically; the most accurate match would be @types/node@26.x. [3] 3) vitest@4.1.7 vs Node.js 26.2.0 Vitest 4.1’s published constraints indicate compatibility with Node.js >=20.0.0, and the package also lists peer compatibility for @types/node covering Node 20/22/24+/etc., which Node 26 satisfies. [4][5] Therefore, vitest@4.1.7 is expected to run on Node.js 26.2.0 (no Node-version exclusion is indicated by the sources), though you should still test in your project. Bottom line - vitest@4.1.7: expected compatible with Node.js 26.2.0. [4][5] - @types/node@25.9.1: not an official match for Node 26.x; use it at your own risk, and prefer the @types/node 26.x package for best type compatibility. [3]
Citations:
- 1: https://github.com/nodejs/node/releases/tag/v26.0.0
- 2: https://nodejs.org/en/blog/release/v26.0.0
- 3: https://stackoverflow.com/questions/42035263/relationship-between-the-version-of-node-js-and-the-version-of-types-node
- 4: https://vitest.dev/guide/migration.html
- 5: https://registry.npmjs.org/vitest
🌐 Web query:
What does vitest@4.1.7 declare for Node.js compatibility (engines/peerDependencies), and does it include Node 26?
💡 Result:
Vitest 4.1.7 declares Node.js compatibility as: 1) engines.node (from the published package’s compatibility listing): ^20.0.0 || ^22.0.0 || >=24.0.0 [1]. 2) peerDependencies: it lists peer deps for things like Vite, @types/node, and its companion @vitest/* packages (e.g., @vitest/ui 4.1.7), but it does not expand that peerDependencies section into additional Node “compat” rules beyond the engines requirement above [2]. Does it include Node 26? Yes. The declared engines range includes any Node version >=24.0.0, which covers Node 26 [1].
Citations:
🌐 Web query:
How does @types/nodeversioning relate to Node major versions (e.g., does@types/node 25.x target Node 25 APIs, and is 26.x needed for Node 26)?
💡 Result:
@types/node versioning generally tracks Node.js major versions: the major.minor line in @types/node corresponds to the Node.js major version it defines types for. For example, @types/node 25.x contains type definitions for Node.js 25 (not “Node 26”), and you would typically use @types/node 26.x when targeting Node 26 APIs. A key rule from DefinitelyTyped is that the versions of @types packages are aligned to the corresponding library’s versions (semver-style), and community answers point out that for @types/node specifically “the major version and minor version tagged in the semver string of @types/node is exactly corresponding to the node’s version” [1]. You can also see concrete evidence from the DefinitelyTyped @types/node sources: the package’s index.d.ts at the repo points at the Node.js version in the definitions header comment (e.g., “Type definitions for non-npm package Node.js 16.11”) [1]. For the specific versions you asked about: - The npm registry shows @types/node versions like 25.7.0 (published May 11, 2026) alongside other Node-major-aligned lines (e.g., 24.x, 22.x) [2][3]. - That implies that for Node 25 you should install an @types/node 25.x release, and for Node 26 you should install an @types/node 26.x release; @types/node 26.x is for Node 26 APIs, not optional for Node 25. One nuance: using an older @types/node with a newer Node runtime can still work for “common” APIs, but TypeScript may miss/incorrectly type newer/changed Node features. The @types/node package itself is meant to supply the correct typings for the Node version line you’re targeting [4], so aligning the @types/node major version with your Node major version is the safe default. Bottom line answer to your question: - Yes: @types/node 25.x is intended to target Node 25 APIs. - Yes: if you are targeting Node 26 and want accurate typings for Node 26, you should use @types/node 26.x (rather than relying on 25.x).
Citations:
- 1: https://stackoverflow.com/questions/42035263/relationship-between-the-version-of-node-js-and-the-version-of-types-node
- 2: https://registry.npmjs.org/@types/node
- 3: https://www.npmjs.com/package/@types/node?activeTab=versions
- 4: https://stackoverflow.com/questions/65103848/what-is-types-node-package-in-nodejs
Align @types/node with Node 26; vitest is already OK for Node 26.2.0.
vitest@^4.1.7declaresengines.nodeas>=24.0.0(plus ^20/^22), so Node26.2.0is covered.@types/node@^25.9.1is for the Node 25 typings; switch to@types/node@^26.xto avoid Node 26 type mismatches (lines 18-18; also applies to 21-21).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package.json` at line 18, Update the devDependency version for the TypeScript
Node typings: replace occurrences of "`@types/node`": "^25.9.1" in package.json
with a Node 26-compatible range such as "^26.0.0" (or "^26.x") so the project
typings align with Node 26; ensure you update every instance of the
"`@types/node`" entry in package.json and run your install to refresh lockfile.
Summary
.mise.tomlfrom24.13.1to26.2.0.AGENTS.mdenvironment note to document the new Node version.package.jsondependency versions for dev tooling (@types/node,@vitest/coverage-v8,oxfmt,oxlint,turbo,vitest).bun.lockto align transitive versions and package hashes, including platform-specific binaries foroxfmt,oxlint, andturbo.Testing
bun installand core checks on target branch, e.g.bun run --cwd apps/web test,bun run --cwd apps/web typecheck, andbun run lintper project scope.Summary by CodeRabbit
Chores
Documentation