From 5c490c51edd5a8e3953fcc439d46c0e138294073 Mon Sep 17 00:00:00 2001 From: Amadeus Demarzi Date: Wed, 17 Dec 2025 05:33:46 -0800 Subject: [PATCH] Diffs Performance Improvements (#5653) Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> --- packages/desktop/src/pages/layout.tsx | 4 +- packages/desktop/src/pages/session.tsx | 9 +- .../enterprise/src/routes/share/[shareID].tsx | 474 +++++++++--------- packages/ui/package.json | 1 + packages/ui/src/components/diff-ssr.tsx | 23 +- packages/ui/src/components/diff.css | 2 + packages/ui/src/components/session-review.css | 1 + packages/ui/src/context/worker-pool.tsx | 10 + packages/ui/src/custom-elements.d.ts | 5 +- packages/ui/src/pierre/worker.ts | 36 +- 10 files changed, 305 insertions(+), 260 deletions(-) create mode 100644 packages/ui/src/context/worker-pool.tsx diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 618b84840..540c5d778 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -613,7 +613,7 @@ export default function Layout(props: ParentProps) { classList={{ "relative @container w-12 pb-5 shrink-0 bg-background-base": true, "flex flex-col gap-5.5 items-start self-stretch justify-between": true, - "border-r border-border-weak-base": true, + "border-r border-border-weak-base contain-strict": true, }} style={{ width: layout.sidebar.opened() ? `${layout.sidebar.width()}px` : undefined }} > @@ -755,7 +755,7 @@ export default function Layout(props: ParentProps) { -
{props.children}
+
{props.children}
diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 3415d0c4e..7d1392c20 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -578,7 +578,10 @@ export default function Page() { - +
- +
import("@opencode-ai/ui/diff").then((m) => ({ default: m.Diff }))) const ClientOnlyCode = clientOnly(() => import("@opencode-ai/ui/code").then((m) => ({ default: m.Code }))) +const ClientOnlyWorkerPoolProvider = clientOnly(() => + import("@opencode-ai/ui/pierre/worker").then((m) => ({ + default: (props: { children: any }) => ( + {props.children} + ), + })), +) const SessionDataMissingError = NamedError.create( "SessionDataMissingError", @@ -197,256 +205,260 @@ export default function () { - - - - {iife(() => { - const [store, setStore] = createStore({ - messageId: undefined as string | undefined, - }) - const messages = createMemo(() => - data().sessionID - ? (data().message[data().sessionID]?.filter((m) => m.role === "user") ?? []).sort( - (a, b) => a.time.created - b.time.created, - ) - : [], - ) - const firstUserMessage = createMemo(() => messages().at(0)) - const activeMessage = createMemo( - () => messages().find((m) => m.id === store.messageId) ?? firstUserMessage(), - ) - function setActiveMessage(message: UserMessage | undefined) { - if (message) { - setStore("messageId", message.id) - } else { - setStore("messageId", undefined) + + + + + {iife(() => { + const [store, setStore] = createStore({ + messageId: undefined as string | undefined, + }) + const messages = createMemo(() => + data().sessionID + ? (data().message[data().sessionID]?.filter((m) => m.role === "user") ?? []).sort( + (a, b) => a.time.created - b.time.created, + ) + : [], + ) + const firstUserMessage = createMemo(() => messages().at(0)) + const activeMessage = createMemo( + () => messages().find((m) => m.id === store.messageId) ?? firstUserMessage(), + ) + function setActiveMessage(message: UserMessage | undefined) { + if (message) { + setStore("messageId", message.id) + } else { + setStore("messageId", undefined) + } } - } - const provider = createMemo(() => activeMessage()?.model?.providerID) - const modelID = createMemo(() => activeMessage()?.model?.modelID) - const model = createMemo(() => data().model[data().sessionID]?.find((m) => m.id === modelID())) - const diffs = createMemo(() => { - const diffs = data().session_diff[data().sessionID] ?? [] - const preloaded = data().session_diff_preload[data().sessionID] ?? [] - return diffs.map((diff) => ({ - ...diff, - preloaded: preloaded.find((d) => d.newFile.name === diff.file), - })) - }) - const splitDiffs = createMemo(() => { - const diffs = data().session_diff[data().sessionID] ?? [] - const preloaded = data().session_diff_preload_split[data().sessionID] ?? [] - return diffs.map((diff) => ({ - ...diff, - preloaded: preloaded.find((d) => d.newFile.name === diff.file), - })) - }) + const provider = createMemo(() => activeMessage()?.model?.providerID) + const modelID = createMemo(() => activeMessage()?.model?.modelID) + const model = createMemo(() => data().model[data().sessionID]?.find((m) => m.id === modelID())) + const diffs = createMemo(() => { + const diffs = data().session_diff[data().sessionID] ?? [] + const preloaded = data().session_diff_preload[data().sessionID] ?? [] + return diffs.map((diff) => ({ + ...diff, + preloaded: preloaded.find((d) => d.newFile.name === diff.file), + })) + }) + const splitDiffs = createMemo(() => { + const diffs = data().session_diff[data().sessionID] ?? [] + const preloaded = data().session_diff_preload_split[data().sessionID] ?? [] + return diffs.map((diff) => ({ + ...diff, + preloaded: preloaded.find((d) => d.newFile.name === diff.file), + })) + }) - const title = () => ( -
-
-
- -
v{info().version}
-
-
- -
{model()?.name ?? modelID()}
-
-
- {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} -
-
-
{info().title}
-
- ) - - const turns = () => ( -
-
{title()}
-
- - {(message) => ( - ( +
+
+
+ +
v{info().version}
+
+
+ - )} - -
-
- -
-
- ) - - const wide = createMemo(() => diffs().length === 0) - - return ( -
-
-
- - - +
{model()?.name ?? modelID()}
+
+
+ {DateTime.fromMillis(info().time.created).toFormat("dd MMM yyyy, HH:mm")} +
-
- - +
{info().title}
+
+ ) + + const turns = () => ( +
+
{title()}
+
+ + {(message) => ( + + )} +
- -
-
+
+ +
+
+ ) + + const wide = createMemo(() => diffs().length === 0) + + return ( +
+
+
+ + + +
+
+ + +
+
+
1, - "px-6": !wide() && messages().length === 1, + "@container relative shrink-0 pt-14 flex flex-col gap-10 min-h-0 w-full": true, + "mx-auto max-w-200": !wide(), }} > - {title()} -
-
- - 1 - ? "pr-6 pl-18" - : "px-6"), +
1, + "px-6": !wide() && messages().length === 1, }} > -
- -
- -
-
- 0}> - -
- -
-
-
-
- - 0}> - - - - Session - - + + 1 + ? "pr-6 pl-18" + : "px-6"), + }} > - {diffs().length} Files Changed - - - - {turns()} - - - - - -
- {turns()} +
+ +
+ +
- - + 0}> + +
+ +
+
+
+
+ + 0}> + + + + Session + + + {diffs().length} Files Changed + + + + {turns()} + + + + + +
+ {turns()} +
+
+
+
-
- ) - })} - - - + ) + })} + + + + ) }} diff --git a/packages/ui/package.json b/packages/ui/package.json index b2e7e331d..618dbf1f0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -5,6 +5,7 @@ "exports": { "./*": "./src/components/*.tsx", "./pierre": "./src/pierre/index.ts", + "./pierre/*": "./src/pierre/*.ts", "./hooks": "./src/hooks/index.ts", "./context": "./src/context/index.ts", "./context/*": "./src/context/*.tsx", diff --git a/packages/ui/src/components/diff-ssr.tsx b/packages/ui/src/components/diff-ssr.tsx index b38b4a34f..e367a4fbe 100644 --- a/packages/ui/src/components/diff-ssr.tsx +++ b/packages/ui/src/components/diff-ssr.tsx @@ -1,8 +1,9 @@ -import { FileDiff } from "@pierre/diffs" +import { DIFFS_TAG_NAME, FileDiff } from "@pierre/diffs" import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr" import { onCleanup, onMount, Show, splitProps } from "solid-js" -import { isServer } from "solid-js/web" +import { Dynamic, isServer } from "solid-js/web" import { createDefaultOptions, styleVariables, type DiffProps } from "../pierre" +import { useWorkerPool } from "../context/worker-pool" export type SSRDiffProps = DiffProps & { preloadedDiff: PreloadMultiFileDiffResult @@ -12,17 +13,21 @@ export function Diff(props: SSRDiffProps) { let container!: HTMLDivElement let fileDiffRef!: HTMLElement const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"]) + const workerPool = useWorkerPool() let fileDiffInstance: FileDiff | undefined const cleanupFunctions: Array<() => void> = [] onMount(() => { if (isServer || !props.preloadedDiff) return - fileDiffInstance = new FileDiff({ - ...createDefaultOptions(props.diffStyle), - ...others, - ...props.preloadedDiff, - }) + fileDiffInstance = new FileDiff( + { + ...createDefaultOptions(props.diffStyle), + ...others, + ...props.preloadedDiff, + }, + workerPool, + ) // @ts-expect-error - fileContainer is private but needed for SSR hydration fileDiffInstance.fileContainer = fileDiffRef fileDiffInstance.hydrate({ @@ -65,11 +70,11 @@ export function Diff(props: SSRDiffProps) { return (
- +