feat: OpenVINO hardware-panel install flow mirroring TensorRT UX - #108
Conversation
…rshoot Provider compat & install - CUDA gets the same one-click install UX TRT/TRT-RTX already have: dedicated /api/env/install-onnxruntime-gpu route pip-installs the pinned 1.26.0 wheel into .venv with NDJSON progress, alongside the existing tensorrt / tensorrt- rtx routes (src/server/routes/env.ts, src/server/services/olive/cuda.ts). - IHV panel surfaces the right CTA per state: external link to NVIDIA's CUDA Toolkit archive (system-level install), pip button for onnxruntime-gpu, or rose terminator for pre-Maxwell GPUs that no install can recover. - Probe split into 4 user-facing states: no GPU / pre-Maxwell / driver+wheel missing / driver+toolkit+EP mismatch — the hidden one-line "NVIDIA CUDA was not detected" is gone. Hardware probe + recipe compat - Add cudaToolkit? and cuda? fields to HardwareProbeResult, with cudaLoadable gate on mergeDetectedProviders so recipe compat and IHV panel install button fire in lockstep. - Pre-Maxwell SM 5.0 short-circuit on CUDA recipes, mirroring the existing pre-Turing SM 7.5 short-circuit: never advertise an install on a card that cannot run the EP. - Center the SM floors in cudaDeps.ts and tensorrtRtxDeps so they're the single source of truth and importable by tests. SM-floor drift guards (NEW) - providerCatalog.ts TRT-RTX chip: chip + tooltip.requirements both cite 7.5 numerically, name Turing / RTX 20xx, call out Maxwell/Pascal/Kepler. - providerCatalog.ts full-TensorRT chip: same treatment — previously had no numeric anchor, just "Turing or newer (GeForce RTX 20xx+)". - recipeHardwareCompatibility pre-Turing reason: drift-guard describe block imports the constant and asserts it appears in BOTH TRT and TRT-RTX reasons; locks the "Turing / RTX 20xx+" tie-in phrase and ensures the install hint stays undefined on pre-Turing boxes. - providerCatalog.test.ts: full sibling describe block for the full-TensorRT half of the family, including a cross-family lockstep assertion (both halves must contain the same numeric constant). - Future Bump of TENSORRT_FAMILY_MIN_COMPUTE_CAPABILITY fails CI in 3 test files (hardwareProbe / providerCatalog / recipeHardwareCompatibility) and forces all 4 user-facing surfaces to update atomically. Scroll bound + Vite watcher - App-level, IHV panel, and InputEnvironmentPanel clipped to min-h-0 overflow-hidden under a properly bounded scroll container so the page can't be scrolled past the end into empty space (CSS-only, no JS). - e2e/scroll-bounds-guardrail.spec.ts mounts a Radix portal at #root and asserts it isn't clipped — guards the next person from re-applying the #root overflow lock that would break portals. - vite.config.ts: ignore .venv*, .venv.bak, .venv.old, .venv-renamed so venv tooling (renames, swaps) no longer triggers page reloads. Tests - src/lib/cudaDeps.test.ts (18) — SM 5.0 floor lock + pre-Maxwell classification + pinned install command. - src/lib/tensorrtRtxDeps.test.ts — RTF EP-ABI install command shape. - src/lib/__tests__/providerCatalog.test.ts (16) — SM 7.5 lockstep across catalog chip and hardware-probe reason for BOTH halves of the family. - src/lib/__tests__/recipeHardwareCompatibility.test.ts (23) — full SM-floor drift-guard describe block plus install-needed scenarios for CUDA/TRT/ TRT-RTX on supported and pre-floor hardware. - src/lib/hardwareProbe.test.ts + tensorrtDeps.test.ts — extended for CUDA 4-state branching and TRT/TRT-RTX install-hint gating. Verified - pnpm exec tsc --noEmit: clean - pnpm lint: 9 pre-existing warnings, 0 new, 0 errors - pnpm vitest run --config vitest.config.ts: 731/731 passing - Live preview at http://127.0.0.1:3000/ verified wiring (cudaToolkit field now surfaces on /api/system/hardware-probe).
- Add openvino + optimum-intel[openvino] install via NDJSON /api/env/install-openvino into .venv - Probe openvino version, Core().available_devices and optimum.intel availability - Wire requiresInstall/openvinoNeedsInstall badge and install button in IHVIntegrationPanel - Link to Intel GPU/NPU driver docs when discrete devices are absent - Update recipe inference and hardwareProbe/pickRecommendedProvider for OpenVINO - Add unit test for openvino stack install args
There was a problem hiding this comment.
Sorry @tonythethompson, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 17 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (34)
📝 WalkthroughWalkthroughOpenVINO support now covers dependency metadata, runtime probing, virtual-environment installation, provider selection, serialized server routes, and hardware-panel controls. ChangesOpenVINO integration
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 8✅ Passed checks (8 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Warning Review ran into problems🔥 ProblemsLinked repositories: Public OSS repositories can only analyze public repositories installed in this organization. Analyzed 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 |
PR Summary by QodoAdd OpenVINO stack install button + NDJSON install/probe flow in Hardware panel
AI Description
Diagram
High-Level Assessment
Files changed (10)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3cca1a423
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code Review by Qodo
1.
|
- Unify shared venv install mutex - Rate-limit OpenVINO installation
- Preserve partial OpenVINO probe results - Parallelize hardware probe calls
Greptile SummaryThis PR adds an OpenVINO stack install flow (openvino + optimum-intel[openvino] + onnxruntime-openvino) to the Hardware panel, mirroring the existing TensorRT UX: a new
Confidence Score: 5/5Safe to merge; the core install flow, probe logic, and UI gating are all correct. All five concerns raised in prior review rounds are addressed in the current code. The only new finding is the dead openvino import check left inside probePythonRuntime after the refactor — it spawns an extra Python process per candidate whose result is immediately discarded, but does not corrupt output or affect install behaviour. Files Needing Attention: src/server/routes/system.ts — the openvino probe block inside probePythonRuntime (lines 154-178) is now dead code and can be removed.
|
| Filename | Overview |
|---|---|
| src/server/services/olive/openvino.ts | New service implementing probeOpenVino and ensureOpenVino, mirroring the TensorRT pattern; openvinoRuntimeOk gated on both acc.version and acc.devices (fixes the Core() failure path); optimum_intel_error correctly surfaces to acc.detail. |
| src/server/routes/env.ts | New /env/install-openvino route added with heavyCommandRateLimit and the shared venvPipInstallMutex, consistent with TensorRT install routes. |
| src/server/routes/system.ts | Injected probeOpenVino into the Python candidate loop alongside probePythonRuntime, but the openvino block inside probePythonRuntime is now dead code — pyResult.openvino is never consumed. |
| src/lib/hardwareProbe.ts | Added computeOpenVinoCompatibleHardware (Intel CPU/GPU regex), OpenVinoProbeResult, and TENSORRT_FAMILY_MIN_COMPUTE_CAPABILITY; mergeDetectedProviders and pickRecommendedProvider updated to handle OpenVINO loadability. |
| src/lib/openvinoDeps.ts | New metadata module centralising install args, labels, conflicting ORT packages, and Intel driver doc URLs; straightforward and correct. |
| src/components/features/IHVIntegrationPanel.tsx | openvinoNeedsInstall gating is correct (requires probe complete + compatible hardware detected + not yet loadable); openvinoInstall state wired cleanly through useOpenVinoInstall. |
| src/components/features/HardwareProviderCard.tsx | OpenVINO PluginInstallBlock and OpenVinoDeviceHint added correctly; needsPluginInstall includes OpenVINO flag; driver doc links for GPU/NPU are present. |
| src/components/features/useOpenVinoInstall.ts | Install hook correctly guards against reentrant calls and concurrent installs; probe refresh only on success; error handling mirrors TRT pattern. |
| src/server/services/olive/recipe.ts | OpenVINO EP path now adds three import-check entries (onnxruntime, openvino, optimum.intel) all pointing to openvinoStackInstallArgs; deduplication by importName is correct. |
Reviews (7): Last reviewed commit: "merge: integrate main (CUDA/ORT-GPU #106..." | Re-trigger Greptile
- Add optimum.intel import check in recipe inference - Restrict OpenVINO hardware detection to Intel-branded CPUs - Surface optimum.intel import errors in probe detail - Apply heavyCommandRateLimit to all venv install routes
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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 `@src/components/features/IHVIntegrationPanel.tsx`:
- Around line 316-318: Extract the OpenVINO installation lifecycle from
IHVIntegrationPanel into a dedicated feature component or hook, including its
state, stream handling, probe refresh, and error handling. Add colocated tests
for the extracted flow, then keep IHVIntegrationPanel limited to composing the
new feature and passing required inputs or callbacks.
- Line 790: Update the OpenVINO hardware guidance rendering in
IHVIntegrationPanel so “Only CPU detected” and related GPU/NPU guidance appear
only when the device enumeration succeeded via Core().available_devices. Treat
missing or empty openvino.devices as an unsuccessful probe, preserving the
existing version/device label behavior without inferring CPU-only hardware from
absent device data.
- Around line 326-329: Separate OpenVINO execution-provider loadability from the
existing hardware/software availability field in the hardware probe contract.
Update the auto-selection logic around openvinoNeedsInstall and
isProviderDetectedLocally so Auto apply recommended provider requires the new
loadable/EP flag, while installation is shown for detected Intel
hardware/platform when OpenVINO is not loadable. Preserve the exclusion for
cross-compile and remote targets.
In `@src/server/routes/openvino.ts`:
- Around line 1-7: Remove the unused openvino route shim and its re-exports from
the server routes. Move ensureOpenVino into the env route implementation and
move probeOpenVino into the probe-injection path, updating their imports and
call sites while preserving existing behavior.
In `@src/server/routes/system.ts`:
- Around line 230-237: Update the hardware detection around
hasOpenVinoCompatibleHardware and mergeDetectedProviders to probe Intel
accelerators independently of platform.cpuModel, including Intel Arc GPUs and
NPUs or an equivalent Intel-compatible platform flag. Ensure the resulting
hasOpenVino value is true for configurations such as an AMD CPU paired with an
Intel Arc GPU, and add coverage for that scenario.
🪄 Autofix
✅ Autofix completed
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 81e9d777-d7e7-4c10-bfc7-e46241c76c97
📒 Files selected for processing (10)
server.tssrc/components/features/IHVIntegrationPanel.tsxsrc/lib/hardwareProbe.tssrc/lib/openvinoDeps.test.tssrc/lib/openvinoDeps.tssrc/server/routes/env.tssrc/server/routes/openvino.tssrc/server/routes/system.tssrc/server/services/olive/openvino.tssrc/server/services/olive/recipe.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Greptile Review
- GitHub Check: python-tests
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns insrc/.
Put shared recipe logic insrc/lib/, especiallypipelineValidation.ts,oliveRecipeBuilder.ts, andrecipePipeline.ts.
src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split theInputEnvironmentPanel,IHVIntegrationPanel, andExecutionWorkspacemega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage forrecipe-graph/,passCatalog,oliveRecipeHub,jobHistoryStore, andvramEstimate, and strengthen component tests for the large panels.
src/**/*.{ts,tsx}: All UI state mutations must go throughcommitUiStateUpdateto enforce invariants; useusePipelineState()for state access andreplaceStatefor recipe imports or preset loads.
UseusePipelineStoreas the single Zustand store for application state; do not introduce separate UI state stores without an architectural reason.
Use the module-level running-state singleton insrc/lib/pipelineNavigation.tsto block navigation while an Olive job is active.
Avoidexport *barrel imports; import directly from the actual module file.
Do not trigger live Olive executions or batch runs in CI or VM environments; recipe building, JSON export, and validation must remain CPU-only.
Do not assume APIs based on prior React or Vite conventions; account for React 19 and Vite 8 breaking changes.
src/**/*.{ts,tsx}: Do not trigger actual Olive optimization runs, including Execute Live or batch runs, in CI or VM environments; use CPU-only recipe building, JSON export, and validation flows instead.
Treat ESLint warnings as acceptable up to the configured limit; only non-zero exits or reported errors are failures.
Do not implement the listed backburner AI p...
Files:
src/server/routes/openvino.tssrc/lib/openvinoDeps.tssrc/server/services/olive/recipe.tssrc/lib/openvinoDeps.test.tssrc/server/routes/env.tssrc/server/routes/system.tssrc/server/services/olive/openvino.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.Target Node.js >=22.16 for JavaScript and TypeScript code.
Files:
src/server/routes/openvino.tssrc/lib/openvinoDeps.tssrc/server/services/olive/recipe.tsserver.tssrc/lib/openvinoDeps.test.tssrc/server/routes/env.tssrc/server/routes/system.tssrc/server/services/olive/openvino.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsx
src/server/routes/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Each API route file must export a
mountXxxRoutes(router)function and be wired intoserver.ts.Organize Express server routes under
src/server/routes/, includingai.ts,mcp.ts,olive.ts,env.ts,system.ts, andgithub.ts.
Files:
src/server/routes/openvino.tssrc/server/routes/env.tssrc/server/routes/system.ts
src/server/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Integration tests must mock child_process, AI providers, and fetch while starting a real Express server on a random port.
Files:
src/server/routes/openvino.tssrc/server/services/olive/recipe.tssrc/server/routes/env.tssrc/server/routes/system.tssrc/server/services/olive/openvino.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
In React code, eliminate request waterfalls, avoid barrel imports, and defer non-critical third-party libraries.
Files:
src/server/routes/openvino.tssrc/lib/openvinoDeps.tssrc/server/services/olive/recipe.tsserver.tssrc/lib/openvinoDeps.test.tssrc/server/routes/env.tssrc/server/routes/system.tssrc/server/services/olive/openvino.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsx
src/server/services/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Organize server-side services under
src/server/services/, including AI providers, Olive/virtual-environment services, and the job registry.
Files:
src/server/services/olive/recipe.tssrc/server/services/olive/openvino.ts
server.ts
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Keep Olive spawning, dependency installation, and PATH handling in
server.ts.
server.ts: Default the Express API bind address to127.0.0.1; do not expose it to a LAN or public internet without authentication and binding fixes.
Add global Express error middleware so unhandled errors are consistently handled without leaking stack traces.
Files:
server.ts
src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use the appropriate Vitest configuration for test scope:
src/libunit tests,src/serverserver tests, integration tests with mocked externals, and component tests with jsdom and Testing Library.
Files:
src/lib/openvinoDeps.test.ts
src/server/routes/{ai,mcp,olive,env}.ts
📄 CodeRabbit inference engine (REVIEW.md)
Apply rate limits to heavy, costly, or secret-mutating endpoints, including AI chat, Codex requests, Ollama pulls, HF token updates, and MCP tool execution.
Files:
src/server/routes/env.ts
src/components/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Use the documented React best practices from
docs/REACT_BEST_PRACTICES.md, particularly avoiding waterfalls, barrel imports, and eagerly loading non-critical third-party libraries.
Files:
src/components/features/IHVIntegrationPanel.tsx
🧠 Learnings (1)
📚 Learning: 2026-08-04T12:36:02.655Z
Learnt from: tonythethompson
Repo: tonythethompson/Olive-Studio PR: 97
File: src/components/features/BatchProcessingPanel.tsx:0-0
Timestamp: 2026-08-04T12:36:02.655Z
Learning: When updating pipeline state through usePipelineState().setState in React components, do not wrap the update in another commitUiStateUpdate call. PipelineStore.setState already invokes commitUiStateUpdate(store.state, partial) to enforce UI state invariants; a second commit can duplicate the operation and merge against a stale component state snapshot.
Applied to files:
src/components/features/IHVIntegrationPanel.tsx
🪛 ast-grep (0.45.0)
src/server/services/olive/openvino.ts
[warning] 6-6: Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🔍 Remote MCP Context7, GitHub Copilot
Relevant review context
- PR
#108adds OpenVINO probing, installation, UI integration, and recipe dependency inference. The server injectsprobeOpenVino; environment installs use a shared venv mutex and rate limiting. - Important unresolved risk: OpenVINO readiness currently means
openvinoplusoptimum.intelimport successfully. The probe does not verify thatonnxruntimeexposesOpenVINOExecutionProvider, and the installer does not install an ONNX Runtime OpenVINO package. This can report success while OpenVINO recipes still fail at execution. - The dependency names and imports are otherwise consistent with current Optimum Intel documentation:
optimum-intel[openvino],from openvino import Core, andfrom optimum.intel import .... OpenVINO documentation demonstrates device enumeration viaCore().get_available_devices(); the PR usesCore().available_devices, which should be validated against the supported runtime version. - The earlier modularization PR established the relevant architectural boundaries:
server.tswiring, route modules, andsrc/server/services/olivecanonical services. - Earlier review concerns about sequential probing, cross-install mutexes, missing rate limiting, and missing
optimum.intelinference checks are marked outdated or resolved; the current diff includes corresponding changes. - CI checks reported success for CodeQL, validation, security, Docker, Python tests, and CodeFactor; Greptile review remained in progress.
🔇 Additional comments (6)
src/components/features/IHVIntegrationPanel.tsx (3)
37-40: LGTM!
320-325: LGTM!Also applies to: 330-330, 387-387, 407-407, 908-908, 949-949
426-445: 🎯 Functional CorrectnessComplete the required UI smoke test for the OpenVINO flow.
In a development environment, manually verify startup, recipe loading and building, validation banners, OpenVINO installation, probe refresh, and local execution. Do not run live Olive executions in CI or VM environments. Automated checks do not verify browser NDJSON handling or post-install execution.
As per coding guidelines, UI changes require these manual smoke tests when execution behavior is touched.
Also applies to: 972-1038
Source: Coding guidelines
src/server/services/olive/openvino.ts (2)
107-110: 🩺 Stability & AvailabilityVerify a timeout and child cleanup for the probe.
Line 109 is awaited by
GET /system/hardware-probe. IfexecFileAsyncdoes not enforce a timeout and terminate the child, a stalled OpenVINO plugin initialization leaves the request pending and prevents cache refresh. Enforce the bound insrc/server/services/shared/exec.tsor pass it here. Add a hanging-child test.
107-117: 🎯 Functional CorrectnessManual verification needed.
src/server/routes/env.ts (1)
106-107: 🔒 Security & PrivacyCSRF (CWE-352): Cross-Site Request Forgery (CSRF)
Reachability path
● Entry server.ts │ ▼ ● Hop src/server/services/olive/openvino.ts:128 pipInstall │ ▼ ● Sink src/server/routes/env.tsVerify origin protection for the installation endpoint.
Lines 106-107 accept a state-changing request without inspecting caller identity or request origin. The route starts a shared-venv pip install.
heavyCommandRateLimitlimits request count, but it does not authenticate the caller or validate origin. Verify that global middleware rejects untrustedOriginorSec-Fetch-Siterequests, or requires a CSRF token, before this router is mounted.#!/bin/bash set -euo pipefail # Inspect listener binding and global origin/authentication middleware. ast-grep outline server.ts --items all rg -n -C 5 'mountEnvRoutes|csrf|Origin|Sec-Fetch-Site|cors|listen\s*\(' server.ts src/server
There was a problem hiding this comment.
Pull request overview
Adds an OpenVINO install/probe UX path that mirrors the existing TensorRT NDJSON “install into .venv then re-probe” workflow, wiring the result into both the server-side hardware probe and the Hardware (IHV) panel.
Changes:
- Introduces an OpenVINO stack service (
probeOpenVino/ensureOpenVino) and exposes an NDJSON install endpoint (POST /api/env/install-openvino) serialized alongside other.venvpip installs. - Extends the hardware probe model and detection/recommendation logic to incorporate OpenVINO device + Optimum-Intel status and “compatible hardware” detection.
- Adds UI affordances in the Hardware panel (install button, logs/errors, and Intel GPU/NPU driver doc links) plus shared dependency metadata + unit tests.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/server/services/olive/recipe.ts | Updates inferred recipe package requirements to use centralized OpenVINO stack install args/label. |
| src/server/services/olive/openvino.ts | New OpenVINO probe + install implementation (ensure .venv, probe, pip install, re-probe). |
| src/server/routes/system.ts | Injects OpenVINO probing via SystemProbeOptions and enriches HardwareProbeResult.openvino; updates detection/recommendation inputs. |
| src/server/routes/openvino.ts | Route shim re-exporting OpenVINO service helpers for DI and env routes. |
| src/server/routes/env.ts | Adds /env/install-openvino, rate-limits heavy installs, and serializes all .venv pip installs behind a shared mutex. |
| src/lib/openvinoDeps.ts | Centralizes OpenVINO stack pip args/label and Intel driver documentation URLs. |
| src/lib/openvinoDeps.test.ts | Adds unit coverage for OpenVINO stack args and labeling. |
| src/lib/hardwareProbe.ts | Extends probe types for OpenVINO details and updates detected/recommended provider logic to reflect OpenVINO loadability. |
| src/components/features/IHVIntegrationPanel.tsx | Adds OpenVINO install UX mirroring TensorRT cards, including NDJSON logs/errors and driver-doc links. |
| server.ts | Wires probeOpenVino into the system probe DI options. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Codex P1: openvino + optimum-intel alone do not register OpenVINOExecutionProvider. Install onnxruntime-openvino, remove conflicting ORT wheels with a warning, and gate readiness on the EP. P2 (shared venv pip mutex) was already unified on this branch. Co-authored-by: Cursor <cursoragent@cursor.com>
CUDA install UX (#12, #13, #16, #17, #18, #19, #21, #22, #25) - hardwareProbe.mergeDetectedProviders: simplify cudaOk ternary to `input.cudaLoadable !== false` — same semantic, half the surface. - hardwareProbe's pre-Maxwell box reason + recipeHardwareCompatibility's CUDA-floor reason now name Maxwell SM 5.0 as 'GeForce GTX 750 Ti or GTX 9xx series' instead of mistakenly borrowing 'GeForce RTX 20xx+' (RTX 20xx is Turing SM 7.5 — the floor above — which previously implied a Pascal SM 6.x owner had an unsupported card). - recipeHardwareCompatibility widens tensorRtInstallHint to ePInstallHint and routes the onnxruntime-gpu install hint through it so the probe's detail string (driver/wheel mismatch, missing module, etc.) is preserved end-to-end. - IHVIntegrationPanel gates the CUDA toolkit download-link paragraph on `cudaEpInVenv` so it only renders when the EP is actually registered — removes the contradictory 'CUDA EP detected / install button shown' state. - InputEnvironmentPanel renders the requiresInstall hint directly so the label and the pip-install command can never disagree again (the old code branched on `kind` and silently printed the TensorRT label next to the onnxruntime install command). Drop the now-dead pinnedTensorRtLabel + tensorrtRtxEpAbiLabel imports. - system.ts hardens the ORT GPU probe with an explicit 30 s timeout (a broken driver install can leave the onnxruntime import hanging and bind the HTTP request) and derives the pinned-version string from pinnedOrtGpuLabel() instead of hardcoding '1.26.0' — a wheel bump in oliveGpuRuntime now propagates to every error message and install hint without further edits. - system.ts notes generator now derives its suggested pip command from pinnedOrtGpuInstallCommand() instead of a literal 'pip install onnxruntime-gpu==1.26.0' string. Shared install helpers (#23, #24, #26) - src/server/services/shared/pipInstall.ts is the single NDJSON-aware pip install helper used by every install route; the local copies in cuda.ts + tensorrt-rtx.ts deleted (kept the exact byte-shape so the UIs NDJSON parser keeps working unchanged). - cuda.ts exports ensureOnnxRuntimeGpu; tensorrt-rtx.ts calls it directly instead of carrying a private duplicate (mirror drift was the actual bug — they were diverging in subtle ways). - cuda.ts ensureOnnxRuntimeGpu explicitly returns libsDir: null on success so the documented return-type contract is honoured and external callers can distinguish "no library directory available" from "field not set". - tensorrt-rtx.ts uses platform-appropriate native-lib extensions: onnxruntime_providers_nv_tensorrt_rtx.dll on win32, libonnxruntime_providers_nv_tensorrt_rtx.so on Linux, .dylib on Darwin (a hardcoded .dll hides the real reason an import fails on non-Windows platforms). The probe script picks the right extension at runtime. Manifest / dedupe (#5, #20, #6) - cudaDeps.cudaDownloadUrlForOs routes darwin to the archive landing page (Apple dropped CUDA toolkit support after CUDA 11.6) and uses word-boundary regexes so 'darwin' no longer accidentally hits the Windows branch via the substring 'win'. - tensorrtRtxDeps.tensorrtRtxEpAbiInstallCommand now derives the manual pip command from the args list (same delegation pattern pinnedTensorRtInstallCommand uses), so an index/version bump cannot desync the server-side install and the user-facing fallback hint. - src/server/shared/anyDotVenvDir.ts is the single chokidar ANY_DOT_VENV_DIR regex; vite.config.ts and server.ts both import from here so a rename/back-up of the venv directory is filtered out by both Vite watchlists in lockstep. Test fixtures (#14, #15) - cudaDeps.test isPreMaxwellNvidiaBox describe block: split the mislabeled 'every card is at or above the floor' assertion into two focused tests (every-card-above-floor / every-card-below-floor); add a darwin routing suite (asserts darwin does NOT hit the Windows branch via substring 'win' and lands on the archive landing page). - providerCatalog.test cross-family lockstep test title now uses a template literal so the floor number interpolates into the test name (was a verbatim '$floor' string). e2e/scroll-bounds-guardrail.spec.ts (#7, #8, #9) - Page.evaluate wraps Radix Tooltip elements in the full Provider/Root/Trigger/Portal/Content hierarchy using React.createElement so the elements go through the JSX reconciler (plain RdxTooltip.Portal(...) / Content(...) function calls were missing Radix's Provider context and the sentinel never mounted). - DOM-fallback branch preserves the actual import-error string so a future failure is filed with the real reason, not a synthetic 'Radix bare imports did not resolve' placeholder. - Added paint-time hit-test: document.elementFromPoint at the bbox centre must resolve to the sentinel (or one of its ancestors up to #root). getClientRects alone cannot detect overflow:hidden clipping because clip preserves the rect coordinates; the hit-test is the actual guardrail. - Restrict the lint-disable comment to the placeholder line so the prettier/sonar warnings stay clean. Verified: tsc clean, 734/734 unit tests + 229/229 server tests pass, pnpm validate:recipe ok, pnpm lint 9 pre-existing warnings / 0 new errors, live /api/system/hardware-probe?refresh=1 reflects the updated probe fields.
CodeRabbit's auto-fix imported @/components/features/useOpenVinoInstall but never added the module, so pnpm lint (tsc) failed with TS2307. Co-authored-by: Anthony Thompson <github@trackdub.com>
…x, state-4 test - tensorrt.ts: extract private pipInstall to ../shared/pipInstall.ts; local spawn-based copy removed, all 4 install call-sites now route through the shared helper so cuda/tensorrt/tensorrt-rtx agree on error contract and the '[deps]' output prefix. - IHVIntegrationPanel.tsx: replace installingTrt | installingTrtRtx | installingOrtGpu trio of mutex flags with a single installInProgress derived from all three. The three handler guards, setInstalling(true) cleanup, and React Button disabled props all use the unified flag so a concurrent pip install can no longer race the shared .venv. - hardwareProbe.test.ts: state-4 fixture now passes cuda.loadable:true so the install-hint branch (state 3) is bypassed and the cascade reaches the state-4 driver/wheel mismatch reason. Without cuda.loadable the fixture was exercising state 3 instead of state 4, so the assertion originally committed failed to validate the intended branch. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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 `@src/components/features/IHVIntegrationPanel.tsx`:
- Around line 997-999: Update the OpenVINO provider condition in the JSX to
compare the device count explicitly against zero, preventing an empty devices
array from rendering numeric 0. Preserve the existing GPU/NPU detection and
provider-id checks; optionally narrow hardwareProbe.openvino.devices once before
JSX and reuse the resulting boolean.
In `@src/components/features/useOpenVinoInstall.ts`:
- Around line 23-75: The NDJSON install reader is duplicated and drops a final
unterminated frame. In src/components/features/useOpenVinoInstall.ts lines
23-75, move runNdjsonInstall into a shared helper such as
src/lib/ndjsonInstall.ts, flush and parse residual buffer content after reader
completion, and import the helper. In
src/components/features/IHVIntegrationPanel.tsx lines 358-410, remove the local
runNdjsonInstall and import the shared helper used by handleInstallTensorRtRtx
and handleInstallTensorRt.
- Around line 1-15: Add src/components/features/useOpenVinoInstall.test.ts with
isolated tests for the useOpenVinoInstall hook: verify the concurrent-install
guard prevents a second install, map a fetch rejection with “Failed to fetch” to
the expected user-facing message, and confirm successful installation invokes
onProbeRefresh(true). Follow the existing feature test setup and mock the
install request/NDJSON stream as needed.
In `@src/lib/hardwareProbe.test.ts`:
- Around line 77-85: Replace the misleading mergeDetectedProviders test with
coverage for the hasOpenVinoCompatibleHardware computation in the system
hardware-detection flow, using an AMD CPU and an Intel Arc GPU entry in
nvidia.gpus. Assert that Arc detection sets the flag and results in OpenVINO
support, rather than testing mergeDetectedProviders with a precomputed flag.
In `@src/lib/openvinoDeps.test.ts`:
- Around line 12-19: Update the test for openvinoStackInstallArgs to assert the
complete expected array in its exact order, including the
--upgrade-strategy/eager pair and all three OpenVINO package constants. Replace
the individual toContain assertions so missing, extra, or reordered arguments
fail the contract.
In `@src/lib/openvinoDeps.ts`:
- Around line 42-50: Update openvinoStackInstallArgs() to include the --upgrade
pip argument alongside --upgrade-strategy eager, ensuring already-installed
OpenVINO packages are upgraded while preserving the existing eager dependency
strategy.
In `@src/server/routes/system.ts`:
- Around line 236-240: Correct the hardware detection in the system route by
restricting hasIntelCpu to explicit Intel vendor/model identifiers rather than
generic “Core” or similar matches, and replace the nvidia?.gpus-based
hasIntelArcGpu check with the available Intel GPU/device enumeration. Keep
hasIntelOpenVinoDevices based on actual detected OpenVINO GPU/NPU devices so
hasOpenVinoCompatibleHardware is only true for genuine Intel-compatible
hardware.
In `@src/server/services/olive/openvino.ts`:
- Around line 257-261: Update ensureOpenVino so pipUninstall for
OPENVINO_CONFLICTING_ORT_PACKAGES runs only when openvinoExecutionProvider is
missing; retain the uninstall before installing the OpenVINO stack in that case.
Wrap pipInstall with error handling and return a recovery error that instructs
users to reinstall onnxruntime-gpu if the ORT swap removed the working
CUDA/TensorRT wheel.
🪄 Autofix
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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 5dd6d7ff-8570-452f-94da-25400a227404
📒 Files selected for processing (10)
src/components/features/IHVIntegrationPanel.tsxsrc/components/features/useOpenVinoInstall.tssrc/lib/hardwareProbe.test.tssrc/lib/hardwareProbe.tssrc/lib/openvinoDeps.test.tssrc/lib/openvinoDeps.tssrc/server/routes/env.tssrc/server/routes/system.tssrc/server/services/olive/openvino.tssrc/server/services/olive/recipe.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
tonythethompson/QuickShell(manual)tonythethompson/numan(manual)tonythethompson/dependency-chain-substrate(manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Greptile Review
- GitHub Check: docker-build
- GitHub Check: python-tests
🧰 Additional context used
📓 Path-based instructions (9)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns insrc/.
Put shared recipe logic insrc/lib/, especiallypipelineValidation.ts,oliveRecipeBuilder.ts, andrecipePipeline.ts.
src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split theInputEnvironmentPanel,IHVIntegrationPanel, andExecutionWorkspacemega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage forrecipe-graph/,passCatalog,oliveRecipeHub,jobHistoryStore, andvramEstimate, and strengthen component tests for the large panels.
src/**/*.{ts,tsx}: All UI state mutations must go throughcommitUiStateUpdateto enforce invariants; useusePipelineState()for state access andreplaceStatefor recipe imports or preset loads.
UseusePipelineStoreas the single Zustand store for application state; do not introduce separate UI state stores without an architectural reason.
Use the module-level running-state singleton insrc/lib/pipelineNavigation.tsto block navigation while an Olive job is active.
Avoidexport *barrel imports; import directly from the actual module file.
Do not trigger live Olive executions or batch runs in CI or VM environments; recipe building, JSON export, and validation must remain CPU-only.
Do not assume APIs based on prior React or Vite conventions; account for React 19 and Vite 8 breaking changes.
src/**/*.{ts,tsx}: Do not trigger actual Olive optimization runs, including Execute Live or batch runs, in CI or VM environments; use CPU-only recipe building, JSON export, and validation flows instead.
Treat ESLint warnings as acceptable up to the configured limit; only non-zero exits or reported errors are failures.
Do not implement the listed backburner AI p...
Files:
src/lib/hardwareProbe.test.tssrc/components/features/useOpenVinoInstall.tssrc/server/services/olive/recipe.tssrc/server/routes/system.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsxsrc/server/routes/env.tssrc/lib/openvinoDeps.tssrc/server/services/olive/openvino.tssrc/lib/openvinoDeps.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.Target Node.js >=22.16 for JavaScript and TypeScript code.
Files:
src/lib/hardwareProbe.test.tssrc/components/features/useOpenVinoInstall.tssrc/server/services/olive/recipe.tssrc/server/routes/system.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsxsrc/server/routes/env.tssrc/lib/openvinoDeps.tssrc/server/services/olive/openvino.tssrc/lib/openvinoDeps.test.ts
src/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use the appropriate Vitest configuration for test scope:
src/libunit tests,src/serverserver tests, integration tests with mocked externals, and component tests with jsdom and Testing Library.
Files:
src/lib/hardwareProbe.test.tssrc/lib/openvinoDeps.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
In React code, eliminate request waterfalls, avoid barrel imports, and defer non-critical third-party libraries.
Files:
src/lib/hardwareProbe.test.tssrc/components/features/useOpenVinoInstall.tssrc/server/services/olive/recipe.tssrc/server/routes/system.tssrc/lib/hardwareProbe.tssrc/components/features/IHVIntegrationPanel.tsxsrc/server/routes/env.tssrc/lib/openvinoDeps.tssrc/server/services/olive/openvino.tssrc/lib/openvinoDeps.test.ts
src/server/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Integration tests must mock child_process, AI providers, and fetch while starting a real Express server on a random port.
Files:
src/server/services/olive/recipe.tssrc/server/routes/system.tssrc/server/routes/env.tssrc/server/services/olive/openvino.ts
src/server/services/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Organize server-side services under
src/server/services/, including AI providers, Olive/virtual-environment services, and the job registry.
Files:
src/server/services/olive/recipe.tssrc/server/services/olive/openvino.ts
src/server/routes/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Each API route file must export a
mountXxxRoutes(router)function and be wired intoserver.ts.Organize Express server routes under
src/server/routes/, includingai.ts,mcp.ts,olive.ts,env.ts,system.ts, andgithub.ts.
Files:
src/server/routes/system.tssrc/server/routes/env.ts
src/components/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Use the documented React best practices from
docs/REACT_BEST_PRACTICES.md, particularly avoiding waterfalls, barrel imports, and eagerly loading non-critical third-party libraries.
Files:
src/components/features/IHVIntegrationPanel.tsx
src/server/routes/{ai,mcp,olive,env}.ts
📄 CodeRabbit inference engine (REVIEW.md)
Apply rate limits to heavy, costly, or secret-mutating endpoints, including AI chat, Codex requests, Ollama pulls, HF token updates, and MCP tool execution.
Files:
src/server/routes/env.ts
🧠 Learnings (1)
📚 Learning: 2026-08-04T12:36:02.655Z
Learnt from: tonythethompson
Repo: tonythethompson/Olive-Studio PR: 97
File: src/components/features/BatchProcessingPanel.tsx:0-0
Timestamp: 2026-08-04T12:36:02.655Z
Learning: When updating pipeline state through usePipelineState().setState in React components, do not wrap the update in another commitUiStateUpdate call. PipelineStore.setState already invokes commitUiStateUpdate(store.state, partial) to enforce UI state invariants; a second commit can duplicate the operation and merge against a stale component state snapshot.
Applied to files:
src/components/features/IHVIntegrationPanel.tsx
🪛 GitHub Check: CodeFactor
src/components/features/useOpenVinoInstall.ts
[notice] 23-75: src/components/features/useOpenVinoInstall.ts#L23-L75
Complex Method
🪛 React Doctor (0.9.3)
src/components/features/IHVIntegrationPanel.tsx
[error] 998-998: React renders a literal 0 into your page when this count is 0 instead of nothing — compare it explicitly (count > 0 && <X/>) or use a ternary (count ? <X/> : null).
In {items.length && <List/>} React renders a literal 0 when the count is 0. Compare explicitly (items.length > 0 && <List/>) or use a ternary (items.length ? <List/> : null).
(jsx-numeric-and-leaked-render)
🔍 Remote MCP Context7, GitHub Copilot
Relevant review context
- OpenVINO supports both
Core().available_devicesandCore().get_available_devices()in its documented Python APIs; the PR’s device enumeration is valid. - The PR’s probe correctly treats
OpenVINOExecutionProvideras a separate requirement and installsonnxruntime-openvinowhen it is missing. recipe.tsadds the same full OpenVINO install arguments under three package entries (onnxruntime,openvino, andoptimum.intel). This may cause duplicate installation/inference entries and should be checked against the package-install consumer.- Installing
onnxruntime-openvinoexplicitly uninstallsonnxruntime,onnxruntime-gpu, andonnxruntime-directml; the UI warns that CUDA/TensorRT providers will become unavailable until the GPU wheel is reinstalled.
🔇 Additional comments (16)
src/lib/hardwareProbe.ts (1)
11-12: LGTM!Also applies to: 21-22
src/lib/openvinoDeps.ts (1)
2-26: LGTM!Also applies to: 52-54
src/lib/openvinoDeps.test.ts (1)
21-38: LGTM!src/server/services/olive/openvino.ts (3)
37-42: LGTM!Also applies to: 56-67
103-112: LGTM!
139-163: LGTM!src/server/routes/system.ts (2)
171-179: LGTM!Also applies to: 257-257, 266-266
220-234: LGTM!src/lib/hardwareProbe.test.ts (1)
56-75: LGTM!Also applies to: 87-96
src/server/services/olive/recipe.ts (2)
102-133: LGTM!
136-147: 🚀 Performance & ScalabilityNo change needed.
openvinoandoptimum.intelare separate import names and both need the full OpenVINO stack, so keeping these entries is consistent with the deduplication and install semantics.> Likely an incorrect or invalid review comment.src/server/routes/env.ts (1)
16-16: LGTM!Also applies to: 20-31, 39-41, 98-108
src/components/features/IHVIntegrationPanel.tsx (3)
320-356: LGTM!
549-549: LGTM!Also applies to: 731-734, 955-996
772-773: LGTM!src/components/features/useOpenVinoInstall.ts (1)
87-109: LGTM!
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Move the provider-card map (Very Complex Method) out of IHVIntegrationPanel into a dedicated component with chrome helpers and install/conflict subcomponents so CodeFactor can pass on PR 108. Co-authored-by: Anthony Thompson <github@trackdub.com>
…thing-where-if-you-scroll-all-the-w-53d82d3d-abf4-4750-960f-ef4a09e0fe94 feat: CUDA+TensorRT install UX, lock SM-floor drift, bound scroll overshoot
Share NDJSON install helper with residual-frame flush, add hook tests, require --upgrade with eager strategy, tighten Intel hardware detection via computeOpenVinoCompatibleHardware + lspci/Win32 probe, and gate ORT wheel uninstall with install-failure recovery messaging. Co-authored-by: Anthony Thompson <github@trackdub.com>
Resolve conflicts by keeping both feature sets: shared venv pip mutex covers TRT/OpenVINO/ORT-GPU installs, system probe retains CUDA SM gating plus Intel OpenVINO hardware detection, and HardwareProviderCard hosts CUDA install/toolkit UI alongside OpenVINO. Co-authored-by: Anthony Thompson <github@trackdub.com>
Summary
Adds a single Install OpenVINO stack button in the Hardware panel that pip-installs
openvinoandoptimum-intel[openvino]into the project.venv, then re-probes — matching the existing TensorRT NDJSON install flow.What changed
POST /api/env/install-openvino(src/server/routes/env.ts)withOpenvinoInstallMutex).streamNdjsonInstall(now generic over{ ok, error?, ... }).src/server/services/olive/openvino.ts)probeOpenVino(python)readsopenvino.__version__,Core().available_devices, andoptimum.intelavailability.ensureOpenVino(onLine)ensures.venvexists, probes, runspip install --upgrade-strategy eager openvino "optimum-intel[openvino]", and re-probes.src/server/routes/system.ts)SystemProbeOptionsnow acceptsprobeOpenVino(injected fromserver.ts).HardwareProbeResult.openvinonow carriesversion,devices,optimumIntel, anddetail.mergeDetectedProviders/pickRecommendedProvidertreat OpenVINO as detected when compatible hardware is present, and recommended only when the stack actually loads.src/components/features/IHVIntegrationPanel.tsx)openvinoNeedsInstallbadge and an inline Install OpenVINO stack into .venv button with logs/error affordances, paralleling the TensorRT cards.CPUis reported, shows driver-doc links for Intel GPU/NPU.src/server/services/olive/recipe.ts)openvino + optimum-intel[openvino]install args.src/lib/openvinoDeps.ts)src/lib/openvinoDeps.test.tscovering install args and labeling.Verification
pnpm lintpasses (only pre-existing warnings remain).pnpm buildsucceeds for both Vite client and esbuild server bundles.pnpm test:serverpasses all server tests except one pre-existingarenaOliveOutputs.test.tstemp-dir teardown flake.pnpm testruns 611 unit tests; two jsdom/undici worker-start errors are unrelated to this change (existing Node 24/jsdom compatibility).vitest run src/lib/openvinoDeps.test.ts src/lib/hardwareProbe.test.tspasses.Notes / open follow-up