handle config errors gracefully

This commit is contained in:
Dax Raad
2025-11-13 18:59:09 -05:00
parent 92604b391b
commit 340966195b
4 changed files with 45 additions and 25 deletions

View File

@@ -1,13 +1,18 @@
import { useRenderer } from "@opentui/solid"
import { createSimpleContext } from "./helper"
import { FormatError } from "@/cli/error"
export const { use: useExit, provider: ExitProvider } = createSimpleContext({
name: "Exit",
init: (input: { onExit?: () => Promise<void> }) => {
const renderer = useRenderer()
return async () => {
return async (reason?: any) => {
renderer.destroy()
await input.onExit?.()
if (reason) {
const formatted = FormatError(reason) ?? JSON.stringify(reason)
process.stderr.write(formatted + "\n")
}
process.exit(0)
}
},

View File

@@ -17,6 +17,8 @@ import { useSDK } from "@tui/context/sdk"
import { Binary } from "@/util/binary"
import { createSimpleContext } from "./helper"
import type { Snapshot } from "@/snapshot"
import { useExit } from "./exit"
import { onMount } from "solid-js"
export const { use: useSync, provider: SyncProvider } = createSimpleContext({
name: "Sync",
@@ -215,28 +217,36 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
}
})
// blocking
Promise.all([
sdk.client.config.providers({ throwOnError: true }).then((x) => setStore("provider", x.data!.providers)),
sdk.client.app.agents({ throwOnError: true }).then((x) => setStore("agent", x.data ?? [])),
sdk.client.config.get({ throwOnError: true }).then((x) => setStore("config", x.data!)),
]).then(() => {
setStore("status", "partial")
// non-blocking
const exit = useExit()
onMount(() => {
// blocking
Promise.all([
sdk.client.session.list().then((x) =>
setStore(
"session",
(x.data ?? []).toSorted((a, b) => a.id.localeCompare(b.id)),
),
),
sdk.client.command.list().then((x) => setStore("command", x.data ?? [])),
sdk.client.lsp.status().then((x) => setStore("lsp", x.data!)),
sdk.client.mcp.status().then((x) => setStore("mcp", x.data!)),
sdk.client.formatter.status().then((x) => setStore("formatter", x.data!)),
]).then(() => {
setStore("status", "complete")
})
sdk.client.config.providers({ throwOnError: true }).then((x) => setStore("provider", x.data!.providers)),
sdk.client.app.agents({ throwOnError: true }).then((x) => setStore("agent", x.data ?? [])),
sdk.client.config.get({ throwOnError: true }).then((x) => setStore("config", x.data!)),
])
.then(() => {
setStore("status", "partial")
// non-blocking
Promise.all([
sdk.client.session.list().then((x) =>
setStore(
"session",
(x.data ?? []).toSorted((a, b) => a.id.localeCompare(b.id)),
),
),
sdk.client.command.list().then((x) => setStore("command", x.data ?? [])),
sdk.client.lsp.status().then((x) => setStore("lsp", x.data!)),
sdk.client.mcp.status().then((x) => setStore("mcp", x.data!)),
sdk.client.formatter.status().then((x) => setStore("formatter", x.data!)),
]).then(() => {
setStore("status", "complete")
})
})
.catch(async (e) => {
await exit(e)
})
})
const result = {

View File

@@ -43,6 +43,7 @@ export const rpc = {
}
},
async shutdown() {
Log.Default.info("worker shutting down")
await Instance.disposeAll()
await server.stop(true)
},

View File

@@ -53,10 +53,14 @@ export const Instance = {
await State.dispose(Instance.directory)
},
async disposeAll() {
Log.Default.info("disposing all instances")
for (const [_key, value] of cache) {
await context.provide(await value, async () => {
await Instance.dispose()
})
const awaited = await value.catch(() => {})
if (awaited) {
await context.provide(await value, async () => {
await Instance.dispose()
})
}
}
cache.clear()
},