Procházet zdrojové kódy

handle config errors gracefully

Dax Raad před 3 měsíci
rodič
revize
340966195b

+ 6 - 1
packages/opencode/src/cli/cmd/tui/context/exit.tsx

@@ -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)
     }
   },

+ 31 - 21
packages/opencode/src/cli/cmd/tui/context/sync.tsx

@@ -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 = {

+ 1 - 0
packages/opencode/src/cli/cmd/tui/worker.ts

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

+ 7 - 3
packages/opencode/src/project/instance.ts

@@ -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()
   },