tweak: make azure onboarding ux a bit better (#25057)

This commit is contained in:
Aiden Cline
2026-04-29 23:35:59 -05:00
committed by GitHub
parent d7701dbfb6
commit 3ef0aaf768
4 changed files with 82 additions and 25 deletions

View File

@@ -156,28 +156,38 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string,
} }
if (method.type === "api") { if (method.type === "api") {
if (method.authorize) { const key = await prompts.password({
const key = await prompts.password({ message: "Enter your API key",
message: "Enter your API key", validate: (x) => (x && x.length > 0 ? undefined : "Required"),
validate: (x) => (x && x.length > 0 ? undefined : "Required"), })
}) if (prompts.isCancel(key)) throw new UI.CancelledError()
if (prompts.isCancel(key)) throw new UI.CancelledError()
const result = await method.authorize(inputs) const metadata = Object.keys(inputs).length ? { metadata: inputs } : {}
if (result.type === "failed") { if (!method.authorize) {
prompts.log.error("Failed to authorize") await put(provider, {
} type: "api",
if (result.type === "success") { key,
const saveProvider = result.provider ?? provider ...metadata,
await put(saveProvider, { })
type: "api",
key: result.key ?? key,
})
prompts.log.success("Login successful")
}
prompts.outro("Done") prompts.outro("Done")
return true return true
} }
const result = await method.authorize(inputs)
if (result.type === "failed") {
prompts.log.error("Failed to authorize")
}
if (result.type === "success") {
const saveProvider = result.provider ?? provider
await put(saveProvider, {
type: "api",
key: result.key ?? key,
...metadata,
})
prompts.log.success("Login successful")
}
prompts.outro("Done")
return true
} }
return false return false

View File

@@ -0,0 +1,26 @@
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
export async function AzureAuthPlugin(_input: PluginInput): Promise<Hooks> {
const prompts = []
if (!process.env.AZURE_RESOURCE_NAME) {
prompts.push({
type: "text" as const,
key: "resourceName",
message: "Enter Azure Resource Name",
placeholder: "e.g. my-models",
})
}
return {
auth: {
provider: "azure",
methods: [
{
type: "api",
label: "API key",
prompts,
},
],
},
}
}

View File

@@ -17,6 +17,7 @@ import { CopilotAuthPlugin } from "./github-copilot/copilot"
import { gitlabAuthPlugin as GitlabAuthPlugin } from "opencode-gitlab-auth" import { gitlabAuthPlugin as GitlabAuthPlugin } from "opencode-gitlab-auth"
import { PoeAuthPlugin } from "opencode-poe-auth" import { PoeAuthPlugin } from "opencode-poe-auth"
import { CloudflareAIGatewayAuthPlugin, CloudflareWorkersAuthPlugin } from "./cloudflare" import { CloudflareAIGatewayAuthPlugin, CloudflareWorkersAuthPlugin } from "./cloudflare"
import { AzureAuthPlugin } from "./azure"
import { Effect, Layer, Context, Stream } from "effect" import { Effect, Layer, Context, Stream } from "effect"
import { EffectBridge } from "@/effect/bridge" import { EffectBridge } from "@/effect/bridge"
import { InstanceState } from "@/effect/instance-state" import { InstanceState } from "@/effect/instance-state"
@@ -61,6 +62,7 @@ const INTERNAL_PLUGINS: PluginInstance[] = [
PoeAuthPlugin, PoeAuthPlugin,
CloudflareWorkersAuthPlugin, CloudflareWorkersAuthPlugin,
CloudflareAIGatewayAuthPlugin, CloudflareAIGatewayAuthPlugin,
AzureAuthPlugin,
] ]
function isServerPlugin(value: unknown): value is PluginInstance { function isServerPlugin(value: unknown): value is PluginInstance {

View File

@@ -199,12 +199,26 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
}), }),
azure: Effect.fnUntraced(function* (provider: Info) { azure: Effect.fnUntraced(function* (provider: Info) {
const env = yield* dep.env() const env = yield* dep.env()
const auth = yield* dep.auth(provider.id)
const resource = iife(() => { const resource = iife(() => {
const name = provider.options?.resourceName return [
if (typeof name === "string" && name.trim() !== "") return name provider.options?.resourceName,
return env["AZURE_RESOURCE_NAME"] auth?.type === "api" ? auth.metadata?.resourceName : undefined,
env["AZURE_RESOURCE_NAME"],
].find((name) => typeof name === "string" && name.trim() !== "")
}) })
if (!resource && !provider.options?.baseURL) {
return {
autoload: false,
async getModel() {
throw new Error(
"AZURE_RESOURCE_NAME is missing, set it using env var or reconnecting the azure provider and setting it",
)
},
}
}
return { return {
autoload: false, autoload: false,
async getModel(sdk: any, modelID: string, options?: Record<string, any>) { async getModel(sdk: any, modelID: string, options?: Record<string, any>) {
@@ -215,11 +229,16 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
return sdk.responses(modelID) return sdk.responses(modelID)
} }
}, },
options: {}, options: {
vars(_options) { resourceName: resource,
return { },
...(resource && { AZURE_RESOURCE_NAME: resource }), vars(_options): Record<string, string> {
if (resource) {
return {
AZURE_RESOURCE_NAME: resource,
}
} }
return {}
}, },
} }
}), }),