mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
fix(cli): distinguish MCP servers in auth login
This commit is contained in:
@@ -74,30 +74,40 @@ const findIntegration = Effect.fn("cli.auth.login.integration")(function* (clien
|
||||
}
|
||||
const integrations = yield* loadIntegrations(client)
|
||||
if (target) return yield* resolveIntegration(integrations, target)
|
||||
const available = integrations
|
||||
const options = loginOptions(integrations)
|
||||
if (options.length === 0) return yield* Effect.fail(new Error("No authentication integrations are available"))
|
||||
const id = yield* prompt<string>(() =>
|
||||
autocomplete({
|
||||
message: "Select an AI provider or MCP server",
|
||||
maxItems: 8,
|
||||
options,
|
||||
}),
|
||||
)
|
||||
return yield* resolveIntegration(integrations, id)
|
||||
})
|
||||
|
||||
export function loginOptions(integrations: IntegrationInfo[]) {
|
||||
return integrations
|
||||
.filter((integration) => connectMethods(integration).length > 0)
|
||||
.toSorted(
|
||||
(a, b) =>
|
||||
Number(b.metadata?.source === "mcp") - Number(a.metadata?.source === "mcp") ||
|
||||
(integrationPriority.get(a.id) ?? integrationPriority.size) -
|
||||
(integrationPriority.get(b.id) ?? integrationPriority.size) ||
|
||||
a.name.localeCompare(b.name) ||
|
||||
a.id.localeCompare(b.id),
|
||||
)
|
||||
if (available.length === 0) return yield* Effect.fail(new Error("No authentication integrations are available"))
|
||||
const id = yield* prompt<string>(() =>
|
||||
autocomplete({
|
||||
message: "Select integration",
|
||||
maxItems: 8,
|
||||
options: available.map((integration) => {
|
||||
const option = { value: integration.id, label: integration.name, hint: integration.id }
|
||||
if (integration.connections.length > 0) return { ...option, hint: "connected" }
|
||||
if (integration.id === "opencode") return { ...option, hint: "recommended" }
|
||||
return option
|
||||
}),
|
||||
}),
|
||||
)
|
||||
return yield* resolveIntegration(available, id)
|
||||
})
|
||||
.map((integration) => ({
|
||||
value: integration.id,
|
||||
label: `${integration.metadata?.source === "mcp" ? "MCP server" : "AI provider"} · ${integration.name}`,
|
||||
hint:
|
||||
integration.connections.length > 0
|
||||
? "connected"
|
||||
: integration.id === "opencode"
|
||||
? "recommended"
|
||||
: integration.id,
|
||||
}))
|
||||
}
|
||||
|
||||
const chooseMethod = Effect.fn("cli.auth.login.method")(function* (methods: ConnectMethod[], target?: string) {
|
||||
if (target) return yield* resolveMethod(methods, target)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import type { IntegrationInfo } from "@opencode/client"
|
||||
import { loginOptions } from "../src/commands/handlers/auth/login"
|
||||
|
||||
const integration = (value: Partial<IntegrationInfo> & Pick<IntegrationInfo, "id" | "name">): IntegrationInfo => ({
|
||||
methods: [{ type: "key" }],
|
||||
connections: [],
|
||||
...value,
|
||||
})
|
||||
|
||||
test("distinguishes MCP servers from AI providers while retaining login targets and status", () => {
|
||||
expect(
|
||||
loginOptions([
|
||||
integration({ id: "openai", name: "OpenAI" }),
|
||||
integration({ id: "linear", name: "Linear", metadata: { source: "mcp" } }),
|
||||
integration({ id: "opencode", name: "OpenCode Zen" }),
|
||||
integration({ id: "opencode-go", name: "OpenCode Go", connections: [{ type: "env", name: "GO_KEY" }] }),
|
||||
integration({ id: "unused", name: "Unused", methods: [{ type: "env", names: ["UNUSED_KEY"] }] }),
|
||||
]),
|
||||
).toEqual([
|
||||
{ value: "linear", label: "MCP server · Linear", hint: "linear" },
|
||||
{ value: "opencode-go", label: "AI provider · OpenCode Go", hint: "connected" },
|
||||
{ value: "opencode", label: "AI provider · OpenCode Zen", hint: "recommended" },
|
||||
{ value: "openai", label: "AI provider · OpenAI", hint: "openai" },
|
||||
])
|
||||
})
|
||||
|
||||
test("sorts MCP servers by name ahead of providers regardless of ID", () => {
|
||||
expect(
|
||||
loginOptions([
|
||||
integration({ id: "openai", name: "OpenAI" }),
|
||||
integration({ id: "zulu", name: "Zulu", metadata: { source: "mcp" } }),
|
||||
integration({ id: "alpha", name: "Alpha", metadata: { source: "mcp" } }),
|
||||
]).map((option) => option.value),
|
||||
).toEqual(["alpha", "zulu", "openai"])
|
||||
})
|
||||
Reference in New Issue
Block a user