Skip to content

Upgrade Node to 26.2.0 and refresh lockfile dependencies#15

Merged
Jay1 merged 5 commits into
mainfrom
jcode/upgrade-dependencies
May 28, 2026
Merged

Upgrade Node to 26.2.0 and refresh lockfile dependencies#15
Jay1 merged 5 commits into
mainfrom
jcode/upgrade-dependencies

Conversation

@Jay1
Copy link
Copy Markdown
Owner

@Jay1 Jay1 commented May 28, 2026

Summary

  • Bumped pinned Node toolchain in .mise.toml from 24.13.1 to 26.2.0.
  • Updated AGENTS.md environment note to document the new Node version.
  • Refreshed package.json dependency versions for dev tooling (@types/node, @vitest/coverage-v8, oxfmt, oxlint, turbo, vitest).
  • Regenerated bun.lock to align transitive versions and package hashes, including platform-specific binaries for oxfmt, oxlint, and turbo.

Testing

  • Not run (no commands executed in this PR content-generation step).
  • Recommended follow-up: run bun install and core checks on target branch, e.g. bun run --cwd apps/web test, bun run --cwd apps/web typecheck, and bun run lint per project scope.

Summary by CodeRabbit

  • Chores

    • Updated Node.js environment to version 26.2.0
    • Bumped development dependencies including vitest, oxlint, oxfmt, and turbo
  • Documentation

    • Clarified Windows installation instructions for Winget package manager

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

📝 Walkthrough

Walkthrough

This PR updates Node.js to version 26.2.0 across configuration and dependencies, introduces a getLocalStorage() helper to abstract localStorage access in eight Zustand stores, restructures README installation documentation, and normalizes socket data to Buffer type in the desktop pipe server.

Changes

Node.js version upgrade across tooling and configuration

Layer / File(s) Summary
Environment configuration files
.mise.toml, AGENTS.md
Environment tool versions updated to pin Node.js to 26.2.0.
Package dependencies and Node.js constraint
package.json
Catalog versions for @types/node and vitest bumped; devDependencies tools (@vitest/coverage-v8, oxfmt, oxlint, turbo) updated; engines.node constraint changed to ^26.2.0.
Installation documentation updates
README.md
Winget Windows installation subsection and macOS/Linux download formatting restructured.

localStorage abstraction pattern

Layer / File(s) Summary
Storage helper definition
apps/web/src/lib/storage.ts
New getLocalStorage() function exported, which verifies localStorage availability and throws if undefined.
Zustand store persistence integration
apps/web/src/browserStateStore.ts, apps/web/src/latestProjectStore.ts, apps/web/src/pinnedThreadsStore.ts, apps/web/src/repoDiffScopeStore.ts, apps/web/src/singleChatPanelStore.ts, apps/web/src/splitViewStore.ts, apps/web/src/terminalStateStore.ts, apps/web/src/workspaceStore.ts
Eight Zustand stores updated to import and use getLocalStorage() helper in their persist middleware configuration instead of direct localStorage reference.

Socket data normalization

Layer / File(s) Summary
Socket data handler Buffer normalization
apps/desktop/src/browserUsePipeServer.ts
Pipe server socket.on("data") callback now explicitly normalizes incoming chunk to Buffer type before passing to handleSocketData.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

size:XL

🐰 A rabbit hops through the storage aisles,
Node two-six leaps with practiced smiles,
Buffers buffed and stores abstracted clean,
The smoothest update ever seen!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: upgrading Node to 26.2.0 and refreshing dependencies.
Description check ✅ Passed The description covers the Summary and Why sections adequately, documenting all major changes and rationale for the upgrade and dependency refresh.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jcode/upgrade-dependencies

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jay1 Jay1 self-assigned this May 28, 2026
@github-actions github-actions Bot added size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels May 28, 2026
Jay1 added 4 commits May 28, 2026 12:57
- 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
@Jay1 Jay1 force-pushed the jcode/upgrade-dependencies branch from 2d1a817 to 21fda52 Compare May 28, 2026 16:58
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 win

Update Node.js badge to reflect the version upgrade.

The badge still displays Node.js-24 but this PR upgrades Node to version 26.2.0. Update the badge to maintain consistency with the actual pinned version.

📛 Proposed fix
-![Node.js](https://img.shields.io/badge/Node.js-24-5FA04E?logo=nodedotjs&logoColor=white)
+![Node.js](https://img.shields.io/badge/Node.js-26-5FA04E?logo=nodedotjs&logoColor=white)
🤖 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
"![Node.js](https://img.shields.io/badge/Node.js-24-5FA04E?logo=nodedotjs&logoColor=white)"
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 win

Consider 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 from main.ts:513-520), which explicitly converts to String(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
"![Node.js](https://img.shields.io/badge/Node.js-24-5FA04E?logo=nodedotjs&logoColor=white)"
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

📥 Commits

Reviewing files that changed from the base of the PR and between fb865f3 and 33785b3.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • .mise.toml
  • AGENTS.md
  • README.md
  • apps/desktop/src/browserUsePipeServer.ts
  • apps/web/src/browserStateStore.ts
  • apps/web/src/latestProjectStore.ts
  • apps/web/src/lib/storage.ts
  • apps/web/src/pinnedThreadsStore.ts
  • apps/web/src/repoDiffScopeStore.ts
  • apps/web/src/singleChatPanelStore.ts
  • apps/web/src/splitViewStore.ts
  • apps/web/src/terminalStateStore.ts
  • apps/web/src/workspaceStore.ts
  • package.json

Comment on lines +26 to +31
export function getLocalStorage(): Storage {
if (typeof localStorage === "undefined") {
throw new Error("localStorage is not available");
}
return localStorage;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 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:


🌐 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:


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.

Suggested change
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.

Comment thread package.json
"@effect/language-service": "0.75.1",
"@types/bun": "^1.3.9",
"@types/node": "^24.10.13",
"@types/node": "^25.9.1",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 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:


🌐 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:


Align @types/node with Node 26; vitest is already OK for Node 26.2.0.

  • vitest@^4.1.7 declares engines.node as >=24.0.0 (plus ^20/^22), so Node 26.2.0 is covered.
  • @types/node@^25.9.1 is for the Node 25 typings; switch to @types/node@^26.x to 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.

@Jay1 Jay1 merged commit 72de055 into main May 28, 2026
8 checks passed
@Jay1 Jay1 deleted the jcode/upgrade-dependencies branch May 28, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant