summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHaris Gušić <[email protected]>2025-10-31 22:20:32 +0100
committerGitHub <[email protected]>2025-10-31 16:20:32 -0500
commit9e392f25a671c220b7eb8927673b42de4575adb6 (patch)
tree9bb7f1a344f497e6ed79f07ff9f4e47ca411870a
parent2cc4e6ad7c10852f328725820fb79ad48a8698b9 (diff)
downloadopencode-9e392f25a671c220b7eb8927673b42de4575adb6.tar.gz
opencode-9e392f25a671c220b7eb8927673b42de4575adb6.zip
feat: Improve error boundary add button to easily create issue in github (#3639)
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx51
1 files changed, 50 insertions, 1 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index cead812fd..1f1f9f63b 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -53,7 +53,7 @@ export function tui(input: {
render(
() => {
return (
- <ErrorBoundary fallback={<text>Something went wrong</text>}>
+ <ErrorBoundary fallback={(error, reset) => <ErrorComponent error={error} reset={reset} onExit={onExit} />}>
<ExitProvider onExit={onExit}>
<KVProvider>
<ToastProvider>
@@ -329,3 +329,52 @@ function App() {
</box>
)
}
+
+function ErrorComponent(props: { error: Error; reset: () => void, onExit: () => Promise<void> }) {
+ const term = useTerminalDimensions()
+ useKeyboard((evt) => {
+ if (evt.ctrl && evt.name === "c") {
+ props.onExit()
+ }
+ })
+ const [copied, setCopied] = createSignal(false)
+
+ const issueURL = new URL("https://github.com/sst/opencode/issues/new?template=bug-report.yml")
+
+ 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```")
+ }
+
+ const copyIssueURL = () => {
+ Clipboard.copy(issueURL.toString()).then(() => { setCopied(true) })
+ }
+
+ return (
+ <box flexDirection="column" gap={1}>
+ <box flexDirection="row" gap={1} alignItems="center">
+ <text attributes={TextAttributes.BOLD}>Please report an issue.</text>
+ <box onMouseUp={copyIssueURL} backgroundColor="#565f89" padding={1}>
+ <text attributes={TextAttributes.BOLD}>Copy issue URL (exception info pre-filled)</text>
+ </box>
+ {copied() && <text>Successfully copied</text>}
+ </box>
+ <box flexDirection="row" gap={2} alignItems="center">
+ <text>A fatal error occurred!</text>
+ <box onMouseUp={props.reset} backgroundColor="#565f89" padding={1}>
+ <text>Reset TUI</text>
+ </box>
+ <box onMouseUp={props.onExit} backgroundColor="#565f89" padding={1}>
+ <text>Exit</text>
+ </box>
+ </box>
+ <scrollbox height={Math.floor(term().height * 0.7)}>
+ <text>{props.error.stack}</text>
+ </scrollbox>
+ <text>{props.error.message}</text>
+ </box >
+ )
+}