import { createMemo, createSignal, onMount, Show } from "solid-js" import { useSync } from "@tui/context/sync" import { map, pipe, sortBy } from "remeda" import { DialogSelect } from "@tui/ui/dialog-select" import { useDialog } from "@tui/ui/dialog" import { useSDK } from "../context/sdk" import { DialogPrompt } from "../ui/dialog-prompt" import { Link } from "../ui/link" import { useTheme } from "../context/theme" import { TextAttributes } from "@opentui/core" import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2" import { DialogModel } from "./dialog-model" const PROVIDER_PRIORITY: Record = { opencode: 0, anthropic: 1, "github-copilot": 2, openai: 3, google: 4, } export function createDialogProviderOptions() { const sync = useSync() const dialog = useDialog() const sdk = useSDK() const options = createMemo(() => { return pipe( sync.data.provider_next.all, sortBy((x) => PROVIDER_PRIORITY[x.id] ?? 99), map((provider) => ({ title: provider.name, value: provider.id, description: { opencode: "(Recommended)", anthropic: "(Claude Max or API key)", }[provider.id], category: provider.id in PROVIDER_PRIORITY ? "Popular" : "Other", async onSelect() { const methods = sync.data.provider_auth[provider.id] ?? [ { type: "api", label: "API key", }, ] let index: number | null = 0 if (methods.length > 1) { index = await new Promise((resolve) => { dialog.replace( () => ( ({ title: x.label, value: index, }))} onSelect={(option) => resolve(option.value)} /> ), () => resolve(null), ) }) } if (index == null) return const method = methods[index] if (method.type === "oauth") { const result = await sdk.client.provider.oauth.authorize({ providerID: provider.id, method: index, }) if (result.data?.method === "code") { dialog.replace(() => ( )) } if (result.data?.method === "auto") { dialog.replace(() => ( )) } } if (method.type === "api") { return dialog.replace(() => ) } }, })), ) }) return options } export function DialogProvider() { const options = createDialogProviderOptions() return } interface AutoMethodProps { index: number providerID: string title: string authorization: ProviderAuthAuthorization } function AutoMethod(props: AutoMethodProps) { const { theme } = useTheme() const sdk = useSDK() const dialog = useDialog() const sync = useSync() onMount(async () => { const result = await sdk.client.provider.oauth.callback({ providerID: props.providerID, method: props.index, }) if (result.error) { dialog.clear() return } await sdk.client.instance.dispose() await sync.bootstrap() dialog.replace(() => ) }) return ( {props.title} esc {props.authorization.instructions} Waiting for authorization... ) } interface CodeMethodProps { index: number title: string providerID: string authorization: ProviderAuthAuthorization } function CodeMethod(props: CodeMethodProps) { const { theme } = useTheme() const sdk = useSDK() const sync = useSync() const dialog = useDialog() const [error, setError] = createSignal(false) return ( { const { error } = await sdk.client.provider.oauth.callback({ providerID: props.providerID, method: props.index, code: value, }) if (!error) { await sdk.client.instance.dispose() await sync.bootstrap() dialog.replace(() => ) return } setError(true) }} description={() => ( {props.authorization.instructions} Invalid code )} /> ) } interface ApiMethodProps { providerID: string title: string } function ApiMethod(props: ApiMethodProps) { const dialog = useDialog() const sdk = useSDK() const sync = useSync() const { theme } = useTheme() return ( OpenCode Zen gives you access to all the best coding models at the cheapest prices with a single API key. Go to https://opencode.ai/zen to get a key ) : undefined } onConfirm={async (value) => { if (!value) return sdk.client.auth.set({ providerID: props.providerID, auth: { type: "api", key: value, }, }) await sdk.client.instance.dispose() await sync.bootstrap() dialog.replace(() => ) }} /> ) }