This commit is contained in:
Dax Raad 2025-11-20 10:04:33 -05:00
parent e3e840e08c
commit 22db2918c0
3 changed files with 38 additions and 19 deletions

View file

@ -3,7 +3,7 @@ import { useLocal } from "@tui/context/local"
import { useSync } from "@tui/context/sync"
import { map, pipe, flatMap, entries, filter, isDeepEqual, sortBy } from "remeda"
import { DialogSelect, type DialogSelectOption, type DialogSelectRef } from "@tui/ui/dialog-select"
import { useDialog } from "@tui/ui/dialog"
import { DialogProvider, useDialog } from "@tui/ui/dialog"
import { useTheme } from "../context/theme"
import { DialogPrompt } from "../ui/dialog-prompt"
import { useSDK } from "../context/sdk"
@ -108,7 +108,7 @@ export function DialogModel() {
sync.data.provider_next.all,
map((provider) => ({
title: provider.name,
category: "Connect a provider",
category: "Popular providers",
value: provider.id,
footer: {
opencode: "Recommended",
@ -137,5 +137,21 @@ export function DialogModel() {
]
})
return <DialogSelect ref={setRef} title="Select model" current={local.model.current()} options={options()} />
return (
<DialogSelect
keybind={[
{
keybind: { ctrl: true, name: "a", meta: false, shift: false, leader: false },
title: "Connect provider",
onTrigger(option) {
dialog.replace(() => <DialogProvider />)
},
},
]}
ref={setRef}
title="Select model"
current={local.model.current()}
options={options()}
/>
)
}

View file

@ -33,7 +33,12 @@ export function createDialogProviderOptions() {
anthropic: "Claude Max or API key",
}[provider.id],
async onSelect() {
const methods = sync.data.provider_auth[provider.id]
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<number | null>((resolve) => {
@ -55,7 +60,6 @@ export function createDialogProviderOptions() {
}
if (index == null) return
const method = methods[index]
if (method.type === "oauth") {
const result = await sdk.client.provider.oauth.authorize({
path: {
@ -65,9 +69,10 @@ export function createDialogProviderOptions() {
method: index,
},
})
if (result.data?.method === "code") {
if (result.data?.method === "code")
await DialogPrompt.show(dialog, result.data.url + " " + result.data.instructions)
if (result.data?.method === "auto")
await DialogPrompt.show(dialog, result.data.url + " " + result.data.instructions)
}
}
},
})),

View file

@ -534,7 +534,7 @@ export function Prompt(props: PromptProps) {
}
const highlight = createMemo(() => {
if (keybind.leader) return theme.accent
if (keybind.leader) return theme.border
if (store.mode === "shell") return theme.primary
return local.agent.color(local.agent.current().name)
})
@ -759,18 +759,16 @@ export function Prompt(props: PromptProps) {
/>
<box flexDirection="row" flexShrink={0} paddingTop={1} gap={1}>
<text fg={highlight()}>
{keybind.leader
? "Leader"
: store.mode === "shell"
? "Shell"
: Locale.titlecase(local.agent.current().name)}{" "}
{store.mode === "shell" ? "Shell" : Locale.titlecase(local.agent.current().name)}{" "}
</text>
<box flexDirection="row" gap={1}>
<text fg={theme.textMuted}>{local.model.parsed().provider}</text>
<text flexShrink={0} fg={theme.text}>
{local.model.parsed().model}
</text>
</box>
<Show when={store.mode === "normal"}>
<box flexDirection="row" gap={1}>
<text fg={theme.textMuted}>{local.model.parsed().provider}</text>
<text flexShrink={0} fg={theme.text}>
{local.model.parsed().model}
</text>
</box>
</Show>
</box>
</box>
</box>