Show configured plugins in status panels
This commit is contained in:
@@ -6,7 +6,7 @@ import { getLogger } from "../lib/logger"
|
|||||||
|
|
||||||
const log = getLogger("session")
|
const log = getLogger("session")
|
||||||
|
|
||||||
type ServiceSection = "lsp" | "mcp"
|
type ServiceSection = "lsp" | "mcp" | "plugins"
|
||||||
|
|
||||||
interface InstanceServiceStatusProps {
|
interface InstanceServiceStatusProps {
|
||||||
sections?: ServiceSection[]
|
sections?: ServiceSection[]
|
||||||
@@ -51,20 +51,25 @@ const InstanceServiceStatus: Component<InstanceServiceStatusProps> = (props) =>
|
|||||||
})
|
})
|
||||||
const isLoading = metadataContext?.isLoading ?? (() => false)
|
const isLoading = metadataContext?.isLoading ?? (() => false)
|
||||||
const refreshMetadata = metadataContext?.refreshMetadata ?? (async () => Promise.resolve())
|
const refreshMetadata = metadataContext?.refreshMetadata ?? (async () => Promise.resolve())
|
||||||
const sections = createMemo<ServiceSection[]>(() => props.sections ?? ["lsp", "mcp"])
|
const sections = createMemo<ServiceSection[]>(() => props.sections ?? ["lsp", "mcp", "plugins"])
|
||||||
const includeLsp = createMemo(() => sections().includes("lsp"))
|
const includeLsp = createMemo(() => sections().includes("lsp"))
|
||||||
const includeMcp = createMemo(() => sections().includes("mcp"))
|
const includeMcp = createMemo(() => sections().includes("mcp"))
|
||||||
|
const includePlugins = createMemo(() => sections().includes("plugins"))
|
||||||
const showHeadings = () => props.showSectionHeadings !== false
|
const showHeadings = () => props.showSectionHeadings !== false
|
||||||
|
|
||||||
const metadataAccessor = metadataContext?.metadata ?? (() => instance().metadata)
|
const metadataAccessor = metadataContext?.metadata ?? (() => instance().metadata)
|
||||||
const metadata = createMemo(() => metadataAccessor())
|
const metadata = createMemo(() => metadataAccessor())
|
||||||
const hasLspMetadata = () => metadata()?.lspStatus !== undefined
|
const hasLspMetadata = () => metadata()?.lspStatus !== undefined
|
||||||
const hasMcpMetadata = () => metadata()?.mcpStatus !== undefined
|
const hasMcpMetadata = () => metadata()?.mcpStatus !== undefined
|
||||||
|
const hasPluginsMetadata = () => metadata()?.plugins !== undefined
|
||||||
|
|
||||||
const lspServers = createMemo(() => metadata()?.lspStatus ?? [])
|
const lspServers = createMemo(() => metadata()?.lspStatus ?? [])
|
||||||
const mcpServers = createMemo(() => parseMcpStatus(metadata()?.mcpStatus ?? undefined))
|
const mcpServers = createMemo(() => parseMcpStatus(metadata()?.mcpStatus ?? undefined))
|
||||||
|
const plugins = createMemo(() => metadata()?.plugins ?? [])
|
||||||
|
|
||||||
const isLspLoading = () => isLoading() || !hasLspMetadata()
|
const isLspLoading = () => isLoading() || !hasLspMetadata()
|
||||||
const isMcpLoading = () => isLoading() || !hasMcpMetadata()
|
const isMcpLoading = () => isLoading() || !hasMcpMetadata()
|
||||||
|
const isPluginsLoading = () => isLoading() || !hasPluginsMetadata()
|
||||||
|
|
||||||
|
|
||||||
const [pendingMcpActions, setPendingMcpActions] = createSignal<Record<string, "connect" | "disconnect">>({})
|
const [pendingMcpActions, setPendingMcpActions] = createSignal<Record<string, "connect" | "disconnect">>({})
|
||||||
@@ -213,10 +218,35 @@ const InstanceServiceStatus: Component<InstanceServiceStatusProps> = (props) =>
|
|||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const renderPluginsSection = () => (
|
||||||
|
<section class="space-y-1.5">
|
||||||
|
<Show when={showHeadings()}>
|
||||||
|
<div class="text-xs font-medium text-muted uppercase tracking-wide">
|
||||||
|
Plugins
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
<Show
|
||||||
|
when={!isPluginsLoading() && plugins().length > 0}
|
||||||
|
fallback={renderEmptyState(isPluginsLoading() ? "Loading plugins..." : "No plugins configured.")}
|
||||||
|
>
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<For each={plugins()}>
|
||||||
|
{(plugin) => (
|
||||||
|
<div class="px-2 py-1.5 rounded border bg-surface-secondary border-base">
|
||||||
|
<div class="text-xs text-primary font-medium break-words whitespace-normal">{plugin}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={props.class}>
|
<div class={props.class}>
|
||||||
<Show when={includeLsp()}>{renderLspSection()}</Show>
|
<Show when={includeLsp()}>{renderLspSection()}</Show>
|
||||||
<Show when={includeMcp()}>{renderMcpSection()}</Show>
|
<Show when={includeMcp()}>{renderMcpSection()}</Show>
|
||||||
|
<Show when={includePlugins()}>{renderPluginsSection()}</Show>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
|||||||
const [activeResizeSide, setActiveResizeSide] = createSignal<"left" | "right" | null>(null)
|
const [activeResizeSide, setActiveResizeSide] = createSignal<"left" | "right" | null>(null)
|
||||||
const [resizeStartX, setResizeStartX] = createSignal(0)
|
const [resizeStartX, setResizeStartX] = createSignal(0)
|
||||||
const [resizeStartWidth, setResizeStartWidth] = createSignal(0)
|
const [resizeStartWidth, setResizeStartWidth] = createSignal(0)
|
||||||
const [rightPanelExpandedItems, setRightPanelExpandedItems] = createSignal<string[]>(["lsp", "mcp"])
|
const [rightPanelExpandedItems, setRightPanelExpandedItems] = createSignal<string[]>(["plan", "mcp", "lsp", "plugins"])
|
||||||
|
|
||||||
const messageStore = createMemo(() => messageStoreBus.getOrCreate(props.instance.id))
|
const messageStore = createMemo(() => messageStoreBus.getOrCreate(props.instance.id))
|
||||||
|
|
||||||
@@ -855,16 +855,9 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
|||||||
|
|
||||||
const sections = [
|
const sections = [
|
||||||
{
|
{
|
||||||
id: "lsp",
|
id: "plan",
|
||||||
label: "LSP Servers",
|
label: "Plan",
|
||||||
render: () => (
|
render: renderPlanSectionContent,
|
||||||
<InstanceServiceStatus
|
|
||||||
initialInstance={props.instance}
|
|
||||||
sections={["lsp"]}
|
|
||||||
showSectionHeadings={false}
|
|
||||||
class="space-y-2"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mcp",
|
id: "mcp",
|
||||||
@@ -879,9 +872,28 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "plan",
|
id: "lsp",
|
||||||
label: "Plan",
|
label: "LSP Servers",
|
||||||
render: renderPlanSectionContent,
|
render: () => (
|
||||||
|
<InstanceServiceStatus
|
||||||
|
initialInstance={props.instance}
|
||||||
|
sections={["lsp"]}
|
||||||
|
showSectionHeadings={false}
|
||||||
|
class="space-y-2"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "plugins",
|
||||||
|
label: "Plugins",
|
||||||
|
render: () => (
|
||||||
|
<InstanceServiceStatus
|
||||||
|
initialInstance={props.instance}
|
||||||
|
sections={["plugins"]}
|
||||||
|
showSectionHeadings={false}
|
||||||
|
class="space-y-2"
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const pendingMetadataRequests = new Set<string>()
|
|||||||
|
|
||||||
function hasMetadataLoaded(metadata?: Instance["metadata"]): boolean {
|
function hasMetadataLoaded(metadata?: Instance["metadata"]): boolean {
|
||||||
if (!metadata) return false
|
if (!metadata) return false
|
||||||
return "project" in metadata && "mcpStatus" in metadata && "lspStatus" in metadata
|
return "project" in metadata && "mcpStatus" in metadata && "lspStatus" in metadata && "plugins" in metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadInstanceMetadata(instance: Instance, options?: { force?: boolean }): Promise<void> {
|
export async function loadInstanceMetadata(instance: Instance, options?: { force?: boolean }): Promise<void> {
|
||||||
@@ -30,15 +30,18 @@ export async function loadInstanceMetadata(instance: Instance, options?: { force
|
|||||||
pendingMetadataRequests.add(instance.id)
|
pendingMetadataRequests.add(instance.id)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [projectResult, mcpResult, lspResult] = await Promise.allSettled([
|
const [projectResult, mcpResult, lspResult, configResult] = await Promise.allSettled([
|
||||||
client.project.current(),
|
client.project.current(),
|
||||||
client.mcp.status(),
|
client.mcp.status(),
|
||||||
fetchLspStatus(instance.id),
|
fetchLspStatus(instance.id),
|
||||||
|
client.config.get(),
|
||||||
])
|
])
|
||||||
|
|
||||||
const project = projectResult.status === "fulfilled" ? projectResult.value.data : undefined
|
const project = projectResult.status === "fulfilled" ? projectResult.value.data : undefined
|
||||||
const mcpStatus = mcpResult.status === "fulfilled" ? (mcpResult.value.data as RawMcpStatus) : undefined
|
const mcpStatus = mcpResult.status === "fulfilled" ? (mcpResult.value.data as RawMcpStatus) : undefined
|
||||||
const lspStatus = lspResult.status === "fulfilled" ? lspResult.value ?? [] : undefined
|
const lspStatus = lspResult.status === "fulfilled" ? lspResult.value ?? [] : undefined
|
||||||
|
const config = configResult.status === "fulfilled" ? (configResult.value.data as { plugin?: unknown } | undefined) : undefined
|
||||||
|
const plugins = Array.isArray(config?.plugin) ? (config?.plugin as string[]) : undefined
|
||||||
|
|
||||||
const updates: Instance["metadata"] = { ...(currentMetadata ?? {}) }
|
const updates: Instance["metadata"] = { ...(currentMetadata ?? {}) }
|
||||||
|
|
||||||
@@ -54,10 +57,15 @@ export async function loadInstanceMetadata(instance: Instance, options?: { force
|
|||||||
updates.lspStatus = lspStatus ?? []
|
updates.lspStatus = lspStatus ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configResult.status === "fulfilled") {
|
||||||
|
updates.plugins = plugins ?? []
|
||||||
|
}
|
||||||
|
|
||||||
if (!updates?.version && instance.binaryVersion) {
|
if (!updates?.version && instance.binaryVersion) {
|
||||||
updates.version = instance.binaryVersion
|
updates.version = instance.binaryVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mergeInstanceMetadata(instance.id, updates)
|
mergeInstanceMetadata(instance.id, updates)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Failed to load instance metadata", error)
|
log.error("Failed to load instance metadata", error)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export interface InstanceMetadata {
|
|||||||
project?: ProjectInfo | null
|
project?: ProjectInfo | null
|
||||||
mcpStatus?: RawMcpStatus | null
|
mcpStatus?: RawMcpStatus | null
|
||||||
lspStatus?: LspStatus[] | null
|
lspStatus?: LspStatus[] | null
|
||||||
|
plugins?: string[] | null
|
||||||
version?: string
|
version?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user