feat(app): autocomplete mcp resources (#34597)
This commit is contained in:
parent
3ca89ac796
commit
06cb0de0b1
10 changed files with 191 additions and 23 deletions
|
|
@ -36,6 +36,7 @@ describe("bootstrapDirectory", () => {
|
|||
question: {},
|
||||
mcp_ready: true,
|
||||
mcp: {},
|
||||
mcp_resource: {},
|
||||
lsp_ready: true,
|
||||
lsp: [],
|
||||
vcs: undefined,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import type { ServerSession } from "../server-session"
|
|||
import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
|
||||
import { formatServerError } from "@/utils/server-errors"
|
||||
import { QueryClient, queryOptions } from "@tanstack/solid-query"
|
||||
import { loadMcpQuery } from "../server-sync"
|
||||
import { loadMcpQuery, loadMcpResourcesQuery } from "../server-sync"
|
||||
import { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
|
||||
import { ScopedKey, type ServerScope } from "@/utils/server-scope"
|
||||
|
||||
|
|
@ -348,6 +348,7 @@ export async function bootstrapDirectory(input: {
|
|||
),
|
||||
() => Promise.resolve(input.loadSessions(input.directory)),
|
||||
input.mcp && (() => input.queryClient.fetchQuery(loadMcpQuery(input.scope, input.directory, input.sdk))),
|
||||
input.mcp && (() => input.queryClient.fetchQuery(loadMcpResourcesQuery(input.scope, input.directory, input.sdk))),
|
||||
() =>
|
||||
input.queryClient.fetchQuery(loadProvidersQuery(input.scope, input.directory, input.sdk)).catch((err) => {
|
||||
const project = getFilename(input.directory)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ const queryOptionsApi = {
|
|||
}),
|
||||
agents: (directory: string) => ({ queryKey: [directory, "agents"], queryFn: async () => [] }),
|
||||
mcp: (directory: string) => ({ queryKey: [directory, "mcp"], queryFn: async () => ({}) }),
|
||||
mcpResources: (directory: string) => ({ queryKey: [directory, "mcpResources"], queryFn: async () => ({}) }),
|
||||
lsp: (directory: string) => ({ queryKey: [directory, "lsp"], queryFn: async () => [] }),
|
||||
references: (directory: string) => ({ queryKey: [directory, "references"], queryFn: async () => [] }),
|
||||
sessions: (directory: string) => ({ queryKey: [directory, "loadSessions"] as const }),
|
||||
} as unknown as QueryOptionsApi
|
||||
|
||||
|
|
@ -197,14 +199,18 @@ describe("createChildStoreManager", () => {
|
|||
try {
|
||||
if (!manager) throw new Error("manager required")
|
||||
const [store, setStore] = manager.child("/project", { bootstrap: false })
|
||||
expect(querySingles.length - offset).toBe(4)
|
||||
expect(querySingles.length - offset).toBe(6)
|
||||
const query = querySingles[offset + 1]
|
||||
const resourceQuery = querySingles[offset + 2]
|
||||
if (!query) throw new Error("query required")
|
||||
if (!resourceQuery) throw new Error("resource query required")
|
||||
expect(query().enabled).toBe(false)
|
||||
expect(resourceQuery().enabled).toBe(false)
|
||||
|
||||
setStore("status", "complete")
|
||||
manager.child("/project", { bootstrap: false, mcp: true })
|
||||
expect(query().enabled).toBe(true)
|
||||
expect(resourceQuery().enabled).toBe(true)
|
||||
expect(store.mcp).toEqual({ demo: { status: "disabled" } })
|
||||
expect(mcpLoads).toEqual(["/project"])
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ export function createChildStoreManager(input: {
|
|||
|
||||
const pathQuery = useQuery(() => input.queryOptions.path(key))
|
||||
const mcpQuery = useQuery(() => ({ ...input.queryOptions.mcp(key), enabled: mcpEnabled() }))
|
||||
const mcpResourceQuery = useQuery(() => ({ ...input.queryOptions.mcpResources(key), enabled: mcpEnabled() }))
|
||||
const lspQuery = useQuery(() => input.queryOptions.lsp(key))
|
||||
const providerQuery = useQuery(() => input.queryOptions.providers(key))
|
||||
const referenceQuery = useQuery(() => input.queryOptions.references(key))
|
||||
|
|
@ -231,6 +232,9 @@ export function createChildStoreManager(input: {
|
|||
get mcp() {
|
||||
return mcpQuery.isLoading ? {} : (mcpQuery.data ?? {})
|
||||
},
|
||||
get mcp_resource() {
|
||||
return mcpResourceQuery.isLoading ? {} : (mcpResourceQuery.data ?? {})
|
||||
},
|
||||
get lsp_ready() {
|
||||
return !lspQuery.isLoading
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type {
|
|||
Command,
|
||||
Config,
|
||||
LspStatus,
|
||||
McpResource,
|
||||
McpStatus,
|
||||
Message,
|
||||
Part,
|
||||
|
|
@ -65,6 +66,9 @@ export type State = {
|
|||
mcp: {
|
||||
[name: string]: McpStatus
|
||||
}
|
||||
mcp_resource: {
|
||||
[key: string]: McpResource
|
||||
}
|
||||
lsp_ready: boolean
|
||||
lsp: LspStatus[]
|
||||
vcs: VcsInfo | undefined
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { useTabs, type Tab } from "./tabs"
|
|||
import { ServerConnection } from "./server"
|
||||
import { requireServerKey } from "@/utils/session-route"
|
||||
import { useSettings } from "./settings"
|
||||
import type { FilePartSource } from "@opencode-ai/sdk/v2/client"
|
||||
|
||||
interface PartBase {
|
||||
content: string
|
||||
|
|
@ -29,6 +30,8 @@ export interface FileAttachmentPart extends PartBase {
|
|||
selection?: FileSelection
|
||||
mime?: string
|
||||
filename?: string
|
||||
url?: string
|
||||
source?: FilePartSource
|
||||
}
|
||||
|
||||
export interface AgentPart extends PartBase {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { Config, OpencodeClient, Path, Project, ProviderAuthResponse } from "@opencode-ai/sdk/v2/client"
|
||||
import type { Config, McpResource, OpencodeClient, Path, Project, ProviderAuthResponse } from "@opencode-ai/sdk/v2/client"
|
||||
import { showToast } from "@/utils/toast"
|
||||
import { getFilename } from "@opencode-ai/core/util/path"
|
||||
import { type Accessor, batch, createMemo, getOwner, onCleanup, onMount, untrack } from "solid-js"
|
||||
|
|
@ -57,6 +57,13 @@ export const loadMcpQuery = (scope: ServerScope, directory: string, sdk: Opencod
|
|||
queryFn: () => sdk.mcp.status().then((r) => r.data ?? {}),
|
||||
})
|
||||
|
||||
export const loadMcpResourcesQuery = (scope: ServerScope, directory: string, sdk: OpencodeClient) =>
|
||||
queryOptions<Record<string, McpResource>>({
|
||||
queryKey: [scope, directory, "mcpResources"] as const,
|
||||
queryFn: () => sdk.experimental.resource.list().then((r) => r.data ?? {}),
|
||||
placeholderData: {},
|
||||
})
|
||||
|
||||
export const loadLspQuery = (scope: ServerScope, directory: string, sdk: OpencodeClient) =>
|
||||
queryOptions({
|
||||
queryKey: [scope, directory, "lsp"] as const,
|
||||
|
|
@ -78,6 +85,7 @@ function makeQueryOptionsApi(
|
|||
agents: (directory: PathKey) => loadAgentsQuery(scope, directory, sdkFor(directory)),
|
||||
references: (directory: PathKey) => loadReferencesQuery(scope, directory, sdkFor(directory)),
|
||||
mcp: (directory: PathKey) => loadMcpQuery(scope, directory, sdkFor(directory)),
|
||||
mcpResources: (directory: PathKey) => loadMcpResourcesQuery(scope, directory, sdkFor(directory)),
|
||||
lsp: (directory: PathKey) => loadLspQuery(scope, directory, sdkFor(directory)),
|
||||
sessions: (directory: PathKey) => ({ queryKey: [scope, directory, "loadSessions"] as const }),
|
||||
}
|
||||
|
|
@ -489,6 +497,7 @@ export function createServerSyncContextInner(serverSDK: ServerSDK) {
|
|||
},
|
||||
refresh: async () => {
|
||||
await queryClient.refetchQueries(queryOptionsApi.mcp(key))
|
||||
await queryClient.refetchQueries(queryOptionsApi.mcpResources(key))
|
||||
},
|
||||
})
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue