Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3bcd209
feat: CUDA+TensorRT install UX, lock SM-floor drift, bound scroll ove…
tonythethompson Aug 4, 2026
3d832e1
fix: Use .venv-scoped CUDA readiness
qodo-code-review[bot] Aug 4, 2026
fd863fe
fix: Compute scroll position relative to container
qodo-code-review[bot] Aug 4, 2026
c3cca1a
feat: OpenVINO stack install button mirroring TensorRT UX
devin-ai-integration[bot] Aug 4, 2026
9e5f4c3
refactor(openvino): split probe script, parse and install logic to re…
devin-ai-integration[bot] Aug 4, 2026
a9ac4c1
fix: 2 findings — Unify shared venv install mutex; Rate-limit OpenVINO i
qodo-code-review[bot] Aug 4, 2026
6d81687
fix: 2 findings — Preserve partial OpenVINO probe results; Parallelize h
qodo-code-review[bot] Aug 4, 2026
9bfba42
fix: address Greptile review feedback
devin-ai-integration[bot] Aug 4, 2026
c469abc
Merge remote bot fixes; keep unified mutex, parallel probes, and Grep…
devin-ai-integration[bot] Aug 4, 2026
6cdc17d
Update src/server/services/olive/openvino.ts
tonythethompson Aug 4, 2026
e62ec23
Potential fix for pull request finding
tonythethompson Aug 4, 2026
a43b921
Update src/lib/cudaDeps.ts
tonythethompson Aug 4, 2026
4500760
Merge branch 'main' into freebuff/the-app-does-a-thing-where-if-you-s…
tonythethompson Aug 4, 2026
769fa60
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] Aug 4, 2026
3ca3f7a
fix: install and verify onnxruntime-openvino for OpenVINO EP
tonythethompson Aug 4, 2026
49c4086
fix: address PR #106 review feedback across 23 outstanding threads
tonythethompson Aug 4, 2026
c7e71d9
fix: add missing useOpenVinoInstall hook for CI typecheck
cursoragent Aug 4, 2026
cf63b25
fix: address follow-up review on tensorrt.ts pipInstall, install mute…
tonythethompson Aug 4, 2026
f52a342
Update src/components/features/IHVIntegrationPanel.tsx
tonythethompson Aug 4, 2026
27da917
fix: extract HardwareProviderCard to clear CodeFactor complexity
cursoragent Aug 4, 2026
163818d
Merge pull request #106 from tonythethompson/freebuff/the-app-does-a-…
tonythethompson Aug 4, 2026
3f0335c
fix: address CodeRabbit OpenVINO review findings
cursoragent Aug 4, 2026
39e2803
merge: integrate main (CUDA/ORT-GPU #106) with OpenVINO PR #108
cursoragent Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 248 additions & 0 deletions e2e/scroll-bounds-guardrail.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { test, expect } from "@playwright/test";

/**
* Guardrail for the scroll-bounds fix in src/index.css.
*
* The fix intentionally locks `html, body` to
* height: 100%; overflow: hidden; overscroll-behavior: none;
* but leaves `#root` alone. The reason: React Portals (Radix Tooltip,
* Select content, popovers, …) can target `#root` via `createPortal(node,
* document.getElementById('root'))`, and an `overflow: hidden` on `#root`
* would silently clip those portals to its box.
*
* This test mounts a Radix Tooltip hierarchy whose portal `container` is
* `#root`, renders its content far enough outside `#root`'s box that any
* overflow-clipping ancestor would hide it, then asserts both:
* (a) `#root` itself stays `overflow: visible`, and
* (b) the portal's content renders unclipped at paint time — verified
* via `document.elementFromPoint(...)` so we catch the case where an
* ancestor's `overflow: hidden` clips the box visually even though
* `getClientRects()` still returns the original coordinates.
*
* If a future change widens the lock to include `#root`, both assertions
* fail loudly — that is the whole point of the test.
*/
test.describe("Scroll-bounds fix — #root must not clip React Portals", () => {
test("Radix Tooltip portaled into #root renders unclipped at paint time", async ({ page }) => {
await page.goto("/");
// Wait for the dashboard to mount so React is hydrated and a real
// React tree is anchored on #root.
await page.locator("#node-btn-input").waitFor({ state: "visible", timeout: 30_000 });

// (a) Direct guardrail: the CSS-computed overflow of #root must
// remain `visible` (or any non-clipping value). If anyone adds
// `#root` to the `html, body { overflow: hidden }` lock, this
// assertion fails before any portal can be clipped.
const rootOverflow = await page.evaluate(
() => getComputedStyle(document.getElementById("root")!).overflow,
);
expect(
rootOverflow,
"#root must keep overflow:visible so React Portals targeting #root are not clipped",
).toBe("visible");

// (b) Mount a Radix Tooltip hierarchy whose portal `container` is
// `#root`. Earlier drafts called `RdxTooltip.Portal(...)` /
// `Content(...)` as plain functions outside the JSX reconciler,
// which silently missed Radix's Provider context and never mounted
// the sentinel. Drive the tree through `React.createElement` so
// every level participates in React reconciliation.
//
// The mount step also tries a direct-DOM fallback if the dev server
// cannot resolve bare ESM imports from inside the eval scope. Both
// branches must honour the same overflow-clipping contract.
const mount = await page.evaluate(async () => {
let mountError: string | null = null;
const root = document.getElementById("root")!;
if (!root) throw new Error("#root missing");

const host = document.createElement("div");
host.id = "portal-mount-host";
host.dataset.testSource = "guardrail";
root.appendChild(host);

const sentinelStyle: Record<string, string> = {
position: "absolute",
left: "-9999px",
top: "-9999px",
width: "180px",
height: "64px",
background: "rgb(141, 168, 64)",
color: "white",
padding: "8px 12px",
borderRadius: "3px",
font: "600 12px/1 system-ui",
zIndex: "2147483647",
pointerEvents: "none",
display: "flex",
alignItems: "center",
justifyContent: "center",
};

let ReactDOMClient: any = null;
let RdxTooltip: any = null;
let React: any = null;
try {
React = await import(/* @vite-ignore */ "react");
ReactDOMClient = await import(/* @vite-ignore */ "react-dom/client");
RdxTooltip = await import(/* @vite-ignore */ "@radix-ui/react-tooltip");
} catch (err) {
mountError = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
}

if (React && ReactDOMClient && RdxTooltip) {
const sub = ReactDOMClient.createRoot(host);
// Build the React element tree with createElement so it goes
// through the JSX reconciler — Radix rejects plain function
// calls because the Provider context never wires up.
sub.render(
React.createElement(
RdxTooltip.Provider,
null,
React.createElement(
RdxTooltip.Root,
{ open: true },
React.createElement(
RdxTooltip.Trigger,
{ asChild: true },
React.createElement("button", { type: "button" }, "open"),
),
React.createElement(
RdxTooltip.Portal,
{ container: root },
React.createElement(
RdxTooltip.Content,
{
"data-testid": "rdx-portal-sentinel",
style: sentinelStyle as unknown as React.CSSProperties,
side: "bottom",
sideOffset: 0,
},
"Portal into #root",
),
),
),
),
);
// Two ticks for Radix's Provider/effect chain to commit.
await new Promise((r) => setTimeout(r, 120));
return { mode: "radix" as const };
}
// Fallback: no Radix available in eval scope (typical for Vite
// dev — the runtime import map that resolves bare specifiers is
// not exposed to page.evaluate). Strategy B uses a direct-DOM
// sentinel and PRESERVES the real import-error string so a
// future failure is filed with enough context to triage at the
// source.
const probe = document.createElement("div");
probe.dataset.testid = "rdx-portal-sentinel";
probe.textContent = "Portal into #root";
Object.assign(probe.style, sentinelStyle);
root.appendChild(probe);
return {
mode: "dom-fallback" as const,
rdxError: mountError ?? "Radix bare imports did not resolve inside page.evaluate",
};
});

if (mount.mode === "dom-fallback") {
// eslint-disable-next-line no-console -- intentional guardrail diagnostic
console.warn(
`[scroll-bounds guardrail] Radix bare import unavailable in eval scope, ` +
`using direct-DOM sentinel. Reason: ${mount.rdxError}`,
);
}

// Force layout settle before measuring.
await page.evaluate(() => {
void document.body.offsetHeight;
});

// (c) The sentinel must exist, be a descendant of #root, and —
// most importantly — still be paint-hit-testable at its bbox
// position. An absolute-positioned child at translate(-9999,-9999)
// bleeds outside any parent's clip box; if #root had
// `overflow:hidden`, two things would happen:
// (1) getClientRects() / bbox still report the original
// coordinates (rects aren't affected by clip), so a
// rect-only check CANNOT detect clipping.
// (2) document.elementFromPoint(centerX, centerY) would return
// some other element (or null), because the clip hides the
// paint at that coordinate.
// So we layer both: a rect check (proves mounting succeeded) and a
// hit-test check (proves visibility through any clip path).
const probe = await page.evaluate(() => {
const el = document.querySelector(
'[data-testid="rdx-portal-sentinel"]',
) as HTMLElement | null;
if (!el) return null;
const rects = el.getClientRects();
const bbox = el.getBoundingClientRect();
return {
found: true,
inRoot: !!el.closest("#root"),
rectsCount: rects.length,
firstRect:
rects.length > 0
? { width: rects[0]!.width, height: rects[0]!.height }
: null,
bboxWidth: bbox.width,
bboxHeight: bbox.height,
};
});

expect(
probe,
`Sentinel element must exist in the DOM after the mount step (mode=${mount.mode})`,
).not.toBeNull();
expect(probe!.found).toBe(true);
expect(
probe!.inRoot,
"Sentinel must be a descendant of #root — proves the Radix portal container was honoured",
).toBe(true);
expect(
probe!.rectsCount,
`Sentinel must render ≥1 clientRect — empty clientRects() implies it never mounted. ` +
`Mount mode: ${mount.mode}`,
).toBeGreaterThan(0);
expect(probe!.bboxWidth).toBeGreaterThan(50);
expect(probe!.bboxHeight).toBeGreaterThan(20);

// Paint-time hit test. elementFromPoint at the bbox centre must
// resolve to either the sentinel itself or one of its ancestors up
// to #root (Radix may wrap the Content). NOT some other element in
// #root (or null) that has clipped over its top via an
// `overflow:hidden` ancestor.
const hitOk = await page.evaluate(() => {
const el = document.querySelector(
'[data-testid="rdx-portal-sentinel"]',
) as HTMLElement | null;
if (!el) return false;
const bbox = el.getBoundingClientRect();
const centerX = bbox.left + bbox.width / 2;
const centerY = bbox.top + bbox.height / 2;
const hit = document.elementFromPoint(centerX, centerY);
if (!hit) return false;
let cur: HTMLElement | null = hit as HTMLElement;
let depth = 0;
while (cur && depth < 6) {
if (cur === el) return true;
cur = cur.parentElement;
depth += 1;
}
return false;
});

expect(
hitOk,
`Sentinel must be the topmost element at its getBoundingClientRect centre. ` +
`If elementFromPoint(...) returns a different node, an ancestor of #root ` +
`now has overflow:hidden and is silently clipping the portal. ` +
`Mount mode: ${mount.mode}`,
).toBe(true);

await expect(
page.locator('[data-testid="rdx-portal-sentinel"]'),
).toBeAttached();
});
});
12 changes: 11 additions & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import express, { Router } from "express";
import path from "path";
import { createServer as createViteServer } from "vite";
import fs from "fs";
import { ANY_DOT_VENV_DIR } from "./src/server/shared/anyDotVenvDir.ts";

import { loadStudioEnv } from "./src/server/loadStudioEnv.ts";
import { mountSystemRoutes, type SystemProbeOptions } from "./src/server/routes/system.ts";
import { mountGithubRoutes } from "./src/server/routes/github.ts";
Expand All @@ -12,6 +14,7 @@ import { mountOliveRoutes } from "./src/server/routes/olive.ts";
import { mountArenaRoutes } from "./src/server/routes/arena.ts";
import { probeTensorRtLoadable } from "./src/server/services/olive/tensorrt.ts";
import { probeTensorRtRtxLoadable } from "./src/server/services/olive/tensorrt-rtx.ts";
import { probeOpenVino } from "./src/server/services/olive/openvino.ts";
import { staticServeRateLimit } from "./src/server/middleware/rateLimit.ts";

// After imports: hydrate .env / .env.local / Windows User+Machine API keys into process.env.
Expand Down Expand Up @@ -98,6 +101,7 @@ const systemRouter = Router();
const systemProbeOpts: SystemProbeOptions = {
probeTensorRtLoadable,
probeTensorRtRtxLoadable,
probeOpenVino,
};
mountSystemRoutes(systemRouter, systemProbeOpts);
app.use("/api", systemRouter);
Expand Down Expand Up @@ -159,7 +163,13 @@ async function startServer() {
server: {
middlewareMode: true,
watch: {
ignored: ["**/.venv/**", "**/node_modules/**", "**/models/**", "**/.cache/**"],
ignored: [
"**/.venv/**",
ANY_DOT_VENV_DIR,
"**/node_modules/**",
"**/models/**",
"**/.cache/**",
],
},
},
appType: "spa",
Expand Down
43 changes: 34 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,16 @@ function Dashboard() {
if (isOliveRunning && id !== "execute" && id !== "playground") return;
setActiveView(id);
scrollingToRef.current = id;
document.getElementById(id)?.scrollIntoView({ behavior: "smooth", block: "start" });
const main = mainRef.current;
const target = document.getElementById(id);
if (!main || !target) return;
// Resolve the target position relative to the scroll container. Using
// offsetTop here would depend on the element's offsetParent.
const mainTop = main.getBoundingClientRect().top;
const targetTop = target.getBoundingClientRect().top;
const top = targetTop - mainTop + main.scrollTop - 16;
const max = main.scrollHeight - main.clientHeight;
main.scrollTo({ top: Math.max(0, Math.min(top, max)), behavior: "smooth" });
window.setTimeout(() => {
if (scrollingToRef.current === id) scrollingToRef.current = null;
}, 900);
Expand Down Expand Up @@ -258,21 +267,36 @@ function Dashboard() {
<span className="hidden sm:inline">Assistant</span>
</button>
</div>
</header>

<main
</header> <main
ref={mainRef}
id="main"
className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-5 wide:px-6 wide:py-8 min-[1000px]:px-10 h-full min-w-0"
className="flex-1 overflow-x-hidden overflow-y-auto overscroll-contain px-3 py-5 wide:px-6 wide:py-8 min-[1000px]:px-10 h-full min-w-0"
>
<h1 className="sr-only">Olive Studio recipe builder</h1>
<div className="mx-auto w-full max-w-5xl min-w-0 pb-16">
{SECTIONS.map(({ id, step, label, desc }, index) => (
<div className="mx-auto w-full max-w-5xl min-w-0">
{SECTIONS.map(({ id, step, label, desc }, index) => {
const isLast = index === SECTIONS.length - 1;
return (
<section
key={id}
id={id}
aria-labelledby={`${id}-heading`}
className={cn("scroll-mt-4", index > 0 && "mt-12 pt-10 border-t border-slate-800")}
data-pipeline-section={id}
className={cn(
"scroll-mt-4",
index > 0 && "mt-12 pt-10 border-t border-slate-800",
// The final pipeline section must be tall enough that
// `scrollIntoView({block:"start"})` can land its top at
// the scroll-container's top without being clamped to
// `maxScroll`. Otherwise the user sees the tail of the
// previous section (visible as empty gray) above the
// playground header, which reads as "the app rolled
// past the section". Height covers title bar + header
// + post-section breathing room; uses the dynamic
// viewport unit so browser chrome (URL bar, devtools)
// does not leave the section short.
isLast && "min-h-[calc(100dvh-3rem)] pb-16",
)}
>
<header className="mb-5 pb-4 border-b border-slate-800/80">
<p className="text-xs text-electric-blue mb-1">{step}</p>
Expand Down Expand Up @@ -317,7 +341,8 @@ function Dashboard() {
</ErrorBoundary>
)}
</section>
))}
);
})}
</div>
</main>
</div>
Expand Down
Loading
Loading