summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSebastian <[email protected]>2026-03-08 23:14:41 +0100
committerGitHub <[email protected]>2026-03-08 23:14:41 +0100
commit49a3a9fe365ab7c971220ac58572e34f2cc68897 (patch)
tree8e64a7cd245515837961a0eecae0bddbe0f6e5c4
parente51ed460a6d5392c67485a829e2b1991ec50dbe8 (diff)
downloadopencode-49a3a9fe365ab7c971220ac58572e34f2cc68897.tar.gz
opencode-49a3a9fe365ab7c971220ac58572e34f2cc68897.zip
guard tui exit (#16640)
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx2
-rw-r--r--packages/opencode/src/cli/cmd/tui/context/exit.tsx31
2 files changed, 18 insertions, 15 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index 97c910a47..3304d6be6 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -111,7 +111,6 @@ export function tui(input: {
fetch?: typeof fetch
headers?: RequestInit["headers"]
events?: EventSource
- onExit?: () => Promise<void>
}) {
// promise to prevent immediate exit
return new Promise<void>(async (resolve) => {
@@ -126,7 +125,6 @@ export function tui(input: {
const onExit = async () => {
unguard?.()
- await input.onExit?.()
resolve()
}
diff --git a/packages/opencode/src/cli/cmd/tui/context/exit.tsx b/packages/opencode/src/cli/cmd/tui/context/exit.tsx
index a6f775913..3ed4ae3d2 100644
--- a/packages/opencode/src/cli/cmd/tui/context/exit.tsx
+++ b/packages/opencode/src/cli/cmd/tui/context/exit.tsx
@@ -15,6 +15,7 @@ export const { use: useExit, provider: ExitProvider } = createSimpleContext({
init: (input: { onExit?: () => Promise<void> }) => {
const renderer = useRenderer()
let message: string | undefined
+ let task: Promise<void> | undefined
const store = {
set: (value?: string) => {
const prev = message
@@ -29,20 +30,24 @@ export const { use: useExit, provider: ExitProvider } = createSimpleContext({
get: () => message,
}
const exit: Exit = Object.assign(
- async (reason?: unknown) => {
- // Reset window title before destroying renderer
- renderer.setTerminalTitle("")
- renderer.destroy()
- win32FlushInputBuffer()
- if (reason) {
- const formatted = FormatError(reason) ?? FormatUnknownError(reason)
- if (formatted) {
- process.stderr.write(formatted + "\n")
+ (reason?: unknown) => {
+ if (task) return task
+ task = (async () => {
+ // Reset window title before destroying renderer
+ renderer.setTerminalTitle("")
+ renderer.destroy()
+ win32FlushInputBuffer()
+ if (reason) {
+ const formatted = FormatError(reason) ?? FormatUnknownError(reason)
+ if (formatted) {
+ process.stderr.write(formatted + "\n")
+ }
}
- }
- const text = store.get()
- if (text) process.stdout.write(text + "\n")
- await input.onExit?.()
+ const text = store.get()
+ if (text) process.stdout.write(text + "\n")
+ await input.onExit?.()
+ })()
+ return task
},
{
message: store,