import { TextAttributes } from "@opentui/core" import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid" import * as Clipboard from "@tui/util/clipboard" import { createSignal } from "solid-js" import { InstallationVersion } from "@opencode-ai/core/installation/version" import { win32FlushInputBuffer } from "../win32" import { getScrollAcceleration } from "../util/scroll" export function ErrorComponent(props: { error: Error reset: () => void onBeforeExit?: () => Promise onExit: () => Promise mode?: "dark" | "light" }) { const term = useTerminalDimensions() const renderer = useRenderer() const handleExit = async () => { await props.onBeforeExit?.() renderer.setTerminalTitle("") renderer.destroy() win32FlushInputBuffer() await props.onExit() } useKeyboard((evt) => { if (evt.ctrl && evt.name === "c") { void handleExit() } }) const [copied, setCopied] = createSignal(false) const issueURL = new URL("https://github.com/anomalyco/opencode/issues/new?template=bug-report.yml") // Choose safe fallback colors per mode since theme context may not be available const isLight = props.mode === "light" const colors = { bg: isLight ? "#ffffff" : "#0a0a0a", text: isLight ? "#1a1a1a" : "#eeeeee", muted: isLight ? "#8a8a8a" : "#808080", primary: isLight ? "#3b7dd8" : "#fab283", } if (props.error.message) { issueURL.searchParams.set("title", `opentui: fatal: ${props.error.message}`) } if (props.error.stack) { issueURL.searchParams.set( "description", "```\n" + props.error.stack.substring(0, 6000 - issueURL.toString().length) + "...\n```", ) } issueURL.searchParams.set("opencode-version", InstallationVersion) const copyIssueURL = () => { void Clipboard.copy(issueURL.toString()).then(() => { setCopied(true) }) } return ( Please report an issue. Copy issue URL (exception info pre-filled) {copied() && Successfully copied} A fatal error occurred! Reset TUI Exit {props.error.stack} {props.error.message} ) }