mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-24 06:33:01 -04:00
fix(tui): contain MCP sidebar errors (#44003)
This commit is contained in:
@@ -33,14 +33,23 @@ function Status(props: { status: McpServer["status"]; loading: boolean }) {
|
||||
return <>Disabled ○</>
|
||||
}
|
||||
|
||||
export function DialogMcp() {
|
||||
export function DialogMcp(props: { initialServer?: string; details?: boolean } = {}) {
|
||||
const data = useData()
|
||||
const dialog = useDialog()
|
||||
const client = useClient()
|
||||
const toast = useToast()
|
||||
const theme = useTheme("elevated")
|
||||
const [focused, setFocused] = createSignal<string>()
|
||||
const [detail, setDetail] = createSignal<McpServer>()
|
||||
const servers = createMemo(() =>
|
||||
pipe(
|
||||
data.location.mcp.server.list() ?? [],
|
||||
sortBy((server) => server.name),
|
||||
),
|
||||
)
|
||||
const initial = props.initialServer ? servers().find((server) => server.name === props.initialServer) : undefined
|
||||
const [focused, setFocused] = createSignal<string | undefined>(props.initialServer)
|
||||
const [detail, setDetail] = createSignal<McpServer | undefined>(
|
||||
props.details && initial?.status.status === "failed" ? initial : undefined,
|
||||
)
|
||||
const [loading, setLoading] = createSignal<string | null>(null)
|
||||
|
||||
const statusColor = (status: McpServer["status"]) => {
|
||||
@@ -50,13 +59,6 @@ export function DialogMcp() {
|
||||
return theme.text.subdued
|
||||
}
|
||||
|
||||
const servers = createMemo(() =>
|
||||
pipe(
|
||||
data.location.mcp.server.list() ?? [],
|
||||
sortBy((server) => server.name),
|
||||
),
|
||||
)
|
||||
|
||||
createEffect(() => {
|
||||
if (focused()) return
|
||||
const first = servers()[0]
|
||||
@@ -153,7 +155,7 @@ export function DialogMcp() {
|
||||
title={`MCP server: ${server().name}`}
|
||||
error={statusError(server().status) ?? "Unknown MCP connection error"}
|
||||
onBack={() => {
|
||||
setDetail()
|
||||
setDetail(undefined)
|
||||
dialog.setSize("medium")
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Plugin } from "@opencode-ai/plugin/tui"
|
||||
import { createMemo, For, Match, Show, Switch, createSignal } from "solid-js"
|
||||
import { DialogMcp } from "../../component/dialog-mcp"
|
||||
|
||||
function View(props: { context: Plugin.Context; sessionID: string }) {
|
||||
const [open, setOpen] = createSignal(true)
|
||||
@@ -39,7 +40,16 @@ function View(props: { context: Plugin.Context; sessionID: string }) {
|
||||
<Show when={list().length <= 2 || open()}>
|
||||
<For each={list()}>
|
||||
{(item) => (
|
||||
<box flexDirection="row" gap={1}>
|
||||
<box
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
minWidth={0}
|
||||
onMouseUp={() =>
|
||||
props.context.ui.dialog.show(() => (
|
||||
<DialogMcp initialServer={item.name} details={item.status.status === "failed"} />
|
||||
))
|
||||
}
|
||||
>
|
||||
<text
|
||||
flexShrink={0}
|
||||
style={{
|
||||
@@ -48,18 +58,21 @@ function View(props: { context: Plugin.Context; sessionID: string }) {
|
||||
>
|
||||
•
|
||||
</text>
|
||||
<text fg={theme.text.default} wrapMode="word">
|
||||
{item.name}{" "}
|
||||
<span style={{ fg: theme.text.subdued }}>
|
||||
<Switch fallback={item.status.status}>
|
||||
<Match when={item.status.status === "connected"}>Connected</Match>
|
||||
<Match when={item.status.status === "failed"}>
|
||||
<i>{item.status.status === "failed" ? item.status.error : undefined}</i>
|
||||
</Match>
|
||||
<Match when={item.status.status === "disabled"}>Disabled</Match>
|
||||
<Match when={item.status.status === "needs_auth"}>Needs auth</Match>
|
||||
</Switch>
|
||||
</span>
|
||||
<text fg={theme.text.default} wrapMode="none" truncate flexGrow={1} flexShrink={1} minWidth={0}>
|
||||
<b>{item.name}</b>
|
||||
</text>
|
||||
<text
|
||||
fg={item.status.status === "failed" ? theme.text.feedback.error.default : theme.text.subdued}
|
||||
wrapMode="none"
|
||||
flexShrink={0}
|
||||
>
|
||||
<Switch fallback={item.status.status}>
|
||||
<Match when={item.status.status === "connected"}>Connected</Match>
|
||||
<Match when={item.status.status === "pending"}>Connecting</Match>
|
||||
<Match when={item.status.status === "failed"}>Error</Match>
|
||||
<Match when={item.status.status === "disabled"}>Disabled</Match>
|
||||
<Match when={item.status.status === "needs_auth"}>Sign in</Match>
|
||||
</Switch>
|
||||
</text>
|
||||
</box>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user