Просмотр исходного кода

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

Aiden Cline 4 месяцев назад
Родитель
Сommit
3ef0aaf768

+ 28 - 18
packages/opencode/src/cli/cmd/providers.ts

@@ -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({
-        message: "Enter your API key",
-        validate: (x) => (x && x.length > 0 ? undefined : "Required"),
+    const key = await prompts.password({
+      message: "Enter your API key",
+      validate: (x) => (x && x.length > 0 ? undefined : "Required"),
+    })
+    if (prompts.isCancel(key)) throw new UI.CancelledError()
+
+    const metadata = Object.keys(inputs).length ? { metadata: inputs } : {}
+    if (!method.authorize) {
+      await put(provider, {
+        type: "api",
+        key,
+        ...metadata,
       })
       })
-      if (prompts.isCancel(key)) throw new UI.CancelledError()
-
-      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,
-        })
-        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

+ 26 - 0
packages/opencode/src/plugin/azure.ts

@@ -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,
+        },
+      ],
+    },
+  }
+}

+ 2 - 0
packages/opencode/src/plugin/index.ts

@@ -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 {

+ 26 - 7
packages/opencode/src/provider/provider.ts

@@ -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
-        if (typeof name === "string" && name.trim() !== "") return name
-        return env["AZURE_RESOURCE_NAME"]
+        return [
+          provider.options?.resourceName,
+          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: {},
-        vars(_options) {
-          return {
-            ...(resource && { AZURE_RESOURCE_NAME: resource }),
+        options: {
+          resourceName: resource,
+        },
+        vars(_options): Record<string, string> {
+          if (resource) {
+            return {
+              AZURE_RESOURCE_NAME: resource,
+            }
           }
           }
+          return {}
         },
         },
       }
       }
     }),
     }),