Download packages/app/src/components/debug-bar.tsx from SaylorTwift/opencode: direct link, hf CLI and curl.
- Browser
- Download file 17.5 kB
-
https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/app/src/components/debug-bar.tsx
- Command line
-
hf download hf://SaylorTwift/opencode/packages/app/src/components/debug-bar.tsx
-
curl -L -o debug-bar.tsx https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/app/src/components/debug-bar.tsx
17.5 kB
| import { useIsRouting, useLocation } from "@solidjs/router" | |
| import { batch, createEffect, onCleanup, onMount } from "solid-js" | |
| import { createStore } from "solid-js/store" | |
| import { makeEventListener } from "@solid-primitives/event-listener" | |
| import { Tooltip } from "@opencode-ai/ui/tooltip" | |
| import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2" | |
| import { useLanguage } from "@/context/language" | |
| import { usePlatform } from "@/context/platform" | |
| type Mem = Performance & { | |
| memory?: { | |
| usedJSHeapSize: number | |
| jsHeapSizeLimit: number | |
| } | |
| } | |
| type Evt = PerformanceEntry & { | |
| interactionId?: number | |
| processingStart?: number | |
| } | |
| type Shift = PerformanceEntry & { | |
| hadRecentInput: boolean | |
| value: number | |
| } | |
| type Obs = PerformanceObserverInit & { | |
| durationThreshold?: number | |
| } | |
| const span = 5000 | |
| const ms = (n?: number, d = 0) => { | |
| if (n === undefined || Number.isNaN(n)) return | |
| return `${n.toFixed(d)}ms` | |
| } | |
| const time = (n?: number) => { | |
| if (n === undefined || Number.isNaN(n)) return | |
| return `${Math.round(n)}` | |
| } | |
| const mb = (n?: number) => { | |
| if (n === undefined || Number.isNaN(n)) return | |
| const v = n / 1024 / 1024 | |
| return `${v >= 1024 ? v.toFixed(0) : v.toFixed(1)}MB` | |
| } | |
| const bad = (n: number | undefined, limit: number, low = false) => { | |
| if (n === undefined || Number.isNaN(n)) return false | |
| return low ? n < limit : n > limit | |
| } | |
| const session = (path: string) => path.includes("/session") | |
| function Cell(props: { | |
| bad?: boolean | |
| dim?: boolean | |
| inline?: boolean | |
| label: string | |
| tip: string | |
| value: string | |
| span?: 2 | 3 | |
| }) { | |
| const content = () => ( | |
| <div | |
| classList={{ | |
| "flex min-w-0 items-center": true, | |
| "min-h-[20px] w-fit justify-start px-1.5 py-0.5 text-left": !!props.inline, | |
| "justify-center text-center": !props.inline, | |
| "min-h-[42px] w-full flex-col rounded-[8px] px-0.5 py-1": !props.inline, | |
| "col-span-2": props.span === 2 && !props.inline, | |
| "col-span-3": props.span === 3 && !props.inline, | |
| }} | |
| > | |
| <div | |
| classList={{ | |
| "flex min-w-0": true, | |
| "-translate-y-px items-baseline gap-1.5": !!props.inline, | |
| "flex-col items-center": !props.inline, | |
| }} | |
| > | |
| <div | |
| classList={{ | |
| "text-[10px] leading-none font-black uppercase tracking-[0.04em] opacity-70": true, | |
| }} | |
| > | |
| {props.label} | |
| </div> | |
| <div | |
| classList={{ | |
| "uppercase leading-none font-bold tabular-nums": true, | |
| "text-[11px]": !!props.inline, | |
| "text-[13px] sm:text-[14px]": !props.inline, | |
| "text-text-on-critical-base": !!props.bad, | |
| "opacity-70": !!props.dim, | |
| }} | |
| > | |
| {props.value} | |
| </div> | |
| </div> | |
| </div> | |
| ) | |
| if (props.inline) { | |
| return ( | |
| <TooltipV2 value={props.tip} placement="top"> | |
| {content()} | |
| </TooltipV2> | |
| ) | |
| } | |
| return ( | |
| <Tooltip value={props.tip} placement="top"> | |
| {content()} | |
| </Tooltip> | |
| ) | |
| } | |
| function ToggleCell(props: { | |
| active: boolean | |
| inline?: boolean | |
| label: string | |
| onClick: () => void | |
| tip: string | |
| value: string | |
| }) { | |
| const content = () => ( | |
| <button | |
| type="button" | |
| aria-label={`${props.label}: ${props.value}`} | |
| aria-pressed={props.active} | |
| classList={{ | |
| "flex min-w-0 items-center font-mono uppercase hover:bg-surface-raised-base focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-border-focus": true, | |
| "min-h-[20px] w-fit justify-start rounded px-1.5 py-0.5 text-left": !!props.inline, | |
| "min-h-[42px] w-full flex-col justify-center rounded-[8px] px-0.5 py-1 text-center": !props.inline, | |
| "bg-surface-raised-base text-text-strong": props.active, | |
| }} | |
| onClick={props.onClick} | |
| > | |
| <span | |
| classList={{ | |
| flex: true, | |
| "-translate-y-px items-baseline gap-1.5": !!props.inline, | |
| "flex-col items-center": !props.inline, | |
| }} | |
| > | |
| <span class="text-[10px] leading-none font-black tracking-[0.04em] opacity-70">{props.label}</span> | |
| <span class="text-[11px] leading-none font-bold">{props.value}</span> | |
| </span> | |
| </button> | |
| ) | |
| if (props.inline) { | |
| return ( | |
| <TooltipV2 value={props.tip} placement="top"> | |
| {content()} | |
| </TooltipV2> | |
| ) | |
| } | |
| return ( | |
| <Tooltip value={props.tip} placement="top"> | |
| {content()} | |
| </Tooltip> | |
| ) | |
| } | |
| export function DebugBar(props: { inline?: boolean } = {}) { | |
| const language = useLanguage() | |
| const platform = usePlatform() | |
| const location = useLocation() | |
| const routing = useIsRouting() | |
| const [state, setState] = createStore({ | |
| cls: undefined as number | undefined, | |
| delay: undefined as number | undefined, | |
| fps: undefined as number | undefined, | |
| gap: undefined as number | undefined, | |
| focus: false, | |
| heap: { | |
| limit: undefined as number | undefined, | |
| used: undefined as number | undefined, | |
| }, | |
| inp: undefined as number | undefined, | |
| jank: undefined as number | undefined, | |
| long: { | |
| block: undefined as number | undefined, | |
| count: undefined as number | undefined, | |
| max: undefined as number | undefined, | |
| }, | |
| nav: { | |
| dur: undefined as number | undefined, | |
| pending: false, | |
| }, | |
| }) | |
| const na = () => language.t("debugBar.na").toUpperCase() | |
| const heap = () => (state.heap.limit ? (state.heap.used ?? 0) / state.heap.limit : undefined) | |
| const heapv = () => { | |
| const value = heap() | |
| if (value === undefined) return na() | |
| return `${Math.round(value * 100)}%` | |
| } | |
| const longv = () => (state.long.count === undefined ? na() : `${time(state.long.block) ?? na()}/${state.long.count}`) | |
| const navv = () => (state.nav.pending ? "..." : (time(state.nav.dur) ?? na())) | |
| const toggleFocus = async () => { | |
| if (!platform.setForceFocus) return | |
| const enabled = !state.focus | |
| await platform.setForceFocus(enabled) | |
| setState("focus", enabled) | |
| } | |
| onCleanup(() => { | |
| if (state.focus) void platform.setForceFocus?.(false).catch(() => undefined) | |
| }) | |
| let prev = "" | |
| let start = 0 | |
| let init = false | |
| let one = 0 | |
| let two = 0 | |
| createEffect(() => { | |
| const busy = routing() | |
| const next = `${location.pathname}${location.search}` | |
| if (!init) { | |
| init = true | |
| prev = next | |
| return | |
| } | |
| if (busy) { | |
| if (one !== 0) cancelAnimationFrame(one) | |
| if (two !== 0) cancelAnimationFrame(two) | |
| one = 0 | |
| two = 0 | |
| if (start !== 0) return | |
| start = performance.now() | |
| if (session(prev)) setState("nav", { dur: undefined, pending: true }) | |
| return | |
| } | |
| if (start === 0) { | |
| prev = next | |
| return | |
| } | |
| const at = start | |
| const from = prev | |
| start = 0 | |
| prev = next | |
| if (!(session(from) || session(next))) return | |
| if (one !== 0) cancelAnimationFrame(one) | |
| if (two !== 0) cancelAnimationFrame(two) | |
| one = requestAnimationFrame(() => { | |
| one = 0 | |
| two = requestAnimationFrame(() => { | |
| two = 0 | |
| setState("nav", { dur: performance.now() - at, pending: false }) | |
| }) | |
| }) | |
| }) | |
| onMount(() => { | |
| const obs: PerformanceObserver[] = [] | |
| const fps: Array<{ at: number; dur: number }> = [] | |
| const long: Array<{ at: number; dur: number }> = [] | |
| const seen = new Map<number | string, { at: number; delay: number; dur: number }>() | |
| let hasLong = false | |
| let poll: number | undefined | |
| let raf = 0 | |
| let last = 0 | |
| let snap = 0 | |
| const trim = (list: Array<{ at: number; dur: number }>, span: number, at: number) => { | |
| while (list[0] && at - list[0].at > span) list.shift() | |
| } | |
| const syncFrame = (at: number) => { | |
| trim(fps, span, at) | |
| const total = fps.reduce((sum, entry) => sum + entry.dur, 0) | |
| const gap = fps.reduce((max, entry) => Math.max(max, entry.dur), 0) | |
| const jank = fps.filter((entry) => entry.dur > 32).length | |
| batch(() => { | |
| setState("fps", total > 0 ? (fps.length * 1000) / total : undefined) | |
| setState("gap", gap > 0 ? gap : undefined) | |
| setState("jank", jank) | |
| }) | |
| } | |
| const syncLong = (at = performance.now()) => { | |
| if (!hasLong) return | |
| trim(long, span, at) | |
| const block = long.reduce((sum, entry) => sum + Math.max(0, entry.dur - 50), 0) | |
| const max = long.reduce((hi, entry) => Math.max(hi, entry.dur), 0) | |
| setState("long", { block, count: long.length, max }) | |
| } | |
| const syncInp = (at = performance.now()) => { | |
| for (const [key, entry] of seen) { | |
| if (at - entry.at > span) seen.delete(key) | |
| } | |
| let delay = 0 | |
| let inp = 0 | |
| for (const entry of seen.values()) { | |
| delay = Math.max(delay, entry.delay) | |
| inp = Math.max(inp, entry.dur) | |
| } | |
| batch(() => { | |
| setState("delay", delay > 0 ? delay : undefined) | |
| setState("inp", inp > 0 ? inp : undefined) | |
| }) | |
| } | |
| const syncHeap = () => { | |
| const mem = (performance as Mem).memory | |
| if (!mem) return | |
| setState("heap", { limit: mem.jsHeapSizeLimit, used: mem.usedJSHeapSize }) | |
| } | |
| const reset = () => { | |
| fps.length = 0 | |
| long.length = 0 | |
| seen.clear() | |
| last = 0 | |
| snap = 0 | |
| batch(() => { | |
| setState("fps", undefined) | |
| setState("gap", undefined) | |
| setState("jank", undefined) | |
| setState("delay", undefined) | |
| setState("inp", undefined) | |
| if (hasLong) setState("long", { block: 0, count: 0, max: 0 }) | |
| }) | |
| } | |
| const watch = (type: string, init: Obs, fn: (entries: PerformanceEntry[]) => void) => { | |
| if (typeof PerformanceObserver === "undefined") return false | |
| if (!(PerformanceObserver.supportedEntryTypes ?? []).includes(type)) return false | |
| const ob = new PerformanceObserver((list) => fn(list.getEntries())) | |
| try { | |
| ob.observe(init) | |
| obs.push(ob) | |
| return true | |
| } catch { | |
| ob.disconnect() | |
| return false | |
| } | |
| } | |
| if ( | |
| watch("layout-shift", { buffered: true, type: "layout-shift" }, (entries) => { | |
| const add = entries.reduce((sum, entry) => { | |
| const item = entry as Shift | |
| if (item.hadRecentInput) return sum | |
| return sum + item.value | |
| }, 0) | |
| if (add === 0) return | |
| setState("cls", (value) => (value ?? 0) + add) | |
| }) | |
| ) { | |
| setState("cls", 0) | |
| } | |
| if ( | |
| watch("longtask", { buffered: true, type: "longtask" }, (entries) => { | |
| const at = performance.now() | |
| long.push(...entries.map((entry) => ({ at: entry.startTime, dur: entry.duration }))) | |
| syncLong(at) | |
| }) | |
| ) { | |
| hasLong = true | |
| setState("long", { block: 0, count: 0, max: 0 }) | |
| } | |
| watch("event", { buffered: true, durationThreshold: 16, type: "event" }, (entries) => { | |
| for (const raw of entries) { | |
| const entry = raw as Evt | |
| if (entry.duration < 16) continue | |
| const key = | |
| entry.interactionId && entry.interactionId > 0 | |
| ? entry.interactionId | |
| : `${entry.name}:${Math.round(entry.startTime)}` | |
| const prev = seen.get(key) | |
| const delay = Math.max(0, (entry.processingStart ?? entry.startTime) - entry.startTime) | |
| seen.set(key, { | |
| at: entry.startTime, | |
| delay: Math.max(prev?.delay ?? 0, delay), | |
| dur: Math.max(prev?.dur ?? 0, entry.duration), | |
| }) | |
| if (seen.size <= 200) continue | |
| const first = seen.keys().next().value | |
| if (first !== undefined) seen.delete(first) | |
| } | |
| syncInp() | |
| }) | |
| const loop = (at: number) => { | |
| if (document.visibilityState !== "visible") { | |
| raf = 0 | |
| return | |
| } | |
| if (last === 0) { | |
| last = at | |
| raf = requestAnimationFrame(loop) | |
| return | |
| } | |
| fps.push({ at, dur: at - last }) | |
| last = at | |
| if (at - snap >= 250) { | |
| snap = at | |
| syncFrame(at) | |
| } | |
| raf = requestAnimationFrame(loop) | |
| } | |
| const stop = () => { | |
| if (raf !== 0) cancelAnimationFrame(raf) | |
| raf = 0 | |
| if (poll === undefined) return | |
| clearInterval(poll) | |
| poll = undefined | |
| } | |
| const start = () => { | |
| if (document.visibilityState !== "visible") return | |
| if (poll === undefined) { | |
| poll = window.setInterval(() => { | |
| syncLong() | |
| syncInp() | |
| syncHeap() | |
| }, 1000) | |
| } | |
| if (raf !== 0) return | |
| raf = requestAnimationFrame(loop) | |
| } | |
| const vis = () => { | |
| if (document.visibilityState !== "visible") { | |
| stop() | |
| return | |
| } | |
| reset() | |
| start() | |
| } | |
| syncHeap() | |
| start() | |
| makeEventListener(document, "visibilitychange", vis) | |
| onCleanup(() => { | |
| if (one !== 0) cancelAnimationFrame(one) | |
| if (two !== 0) cancelAnimationFrame(two) | |
| stop() | |
| for (const ob of obs) ob.disconnect() | |
| }) | |
| }) | |
| return ( | |
| <aside | |
| aria-label={language.t("debugBar.ariaLabel")} | |
| classList={{ | |
| "pointer-events-auto hidden overflow-hidden text-text-strong md:block": true, | |
| "mt-[-6px] w-full shrink-0 px-3 py-1": !!props.inline, | |
| "fixed bottom-3 right-3 z-50 w-[308px] max-w-[calc(100vw-1.5rem)] rounded-xl border border-border-base bg-surface-raised-stronger-non-alpha p-0.5 shadow-[var(--shadow-lg-border-base)] sm:bottom-4 sm:right-4 sm:w-[324px]": | |
| !props.inline, | |
| }} | |
| > | |
| <div | |
| classList={{ | |
| "font-mono": true, | |
| "gap-[9px]": !!props.inline, | |
| "gap-px": !props.inline, | |
| "flex w-full flex-nowrap items-center justify-start": !!props.inline, | |
| "grid-cols-4": !props.inline, | |
| grid: !props.inline, | |
| }} | |
| > | |
| <Cell | |
| label={language.t("debugBar.nav.label")} | |
| tip={language.t("debugBar.nav.tip")} | |
| value={navv()} | |
| bad={bad(state.nav.dur, 400)} | |
| dim={state.nav.dur === undefined && !state.nav.pending} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.fps.label")} | |
| tip={language.t("debugBar.fps.tip")} | |
| value={state.fps === undefined ? na() : `${Math.round(state.fps)}`} | |
| bad={bad(state.fps, 50, true)} | |
| dim={state.fps === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.frame.label")} | |
| tip={language.t("debugBar.frame.tip")} | |
| value={time(state.gap) ?? na()} | |
| bad={bad(state.gap, 50)} | |
| dim={state.gap === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.jank.label")} | |
| tip={language.t("debugBar.jank.tip")} | |
| value={state.jank === undefined ? na() : `${state.jank}`} | |
| bad={bad(state.jank, 8)} | |
| dim={state.jank === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.long.label")} | |
| tip={language.t("debugBar.long.tip", { max: ms(state.long.max) ?? na() })} | |
| value={longv()} | |
| bad={bad(state.long.block, 200)} | |
| dim={state.long.count === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.delay.label")} | |
| tip={language.t("debugBar.delay.tip")} | |
| value={time(state.delay) ?? na()} | |
| bad={bad(state.delay, 100)} | |
| dim={state.delay === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.inp.label")} | |
| tip={language.t("debugBar.inp.tip")} | |
| value={time(state.inp) ?? na()} | |
| bad={bad(state.inp, 200)} | |
| dim={state.inp === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.cls.label")} | |
| tip={language.t("debugBar.cls.tip")} | |
| value={state.cls === undefined ? na() : state.cls.toFixed(2)} | |
| bad={bad(state.cls, 0.1)} | |
| dim={state.cls === undefined} | |
| inline={props.inline} | |
| /> | |
| <Cell | |
| label={language.t("debugBar.mem.label")} | |
| tip={ | |
| state.heap.used === undefined | |
| ? language.t("debugBar.mem.tipUnavailable") | |
| : language.t("debugBar.mem.tip", { | |
| used: mb(state.heap.used) ?? na(), | |
| limit: mb(state.heap.limit) ?? na(), | |
| }) | |
| } | |
| value={heapv()} | |
| bad={bad(heap(), 0.8)} | |
| dim={state.heap.used === undefined} | |
| inline={props.inline} | |
| span={platform.setForceFocus ? 2 : 3} | |
| /> | |
| <ToggleCell | |
| active={language.direction() === "rtl"} | |
| inline={props.inline} | |
| label={language.t("debugBar.direction.label")} | |
| tip={language.t("debugBar.direction.tip")} | |
| value={language.t(`debugBar.direction.${language.direction()}`)} | |
| onClick={() => language.setDirection(language.direction() === "rtl" ? "ltr" : "rtl")} | |
| /> | |
| {platform.setForceFocus && ( | |
| <ToggleCell | |
| active={state.focus} | |
| inline={props.inline} | |
| label={language.t("debugBar.focus.label")} | |
| tip={language.t("debugBar.focus.tip")} | |
| value={language.t(state.focus ? "debugBar.focus.on" : "debugBar.focus.off")} | |
| onClick={() => void toggleFocus()} | |
| /> | |
| )} | |
| </div> | |
| </aside> | |
| ) | |
| } | |