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

tui: display 'Free' badge for zero-cost models in model selection dialog

Dax Raad 3 месяцев назад
Родитель
Сommit
ce9b758d0a

+ 9 - 0
packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx

@@ -4,12 +4,19 @@ import { useSync } from "@tui/context/sync"
 import { map, pipe, flatMap, entries, filter, isDeepEqual, sortBy } from "remeda"
 import { DialogSelect, type DialogSelectRef } from "@tui/ui/dialog-select"
 import { useDialog } from "@tui/ui/dialog"
+import { useTheme } from "../context/theme"
+
+function Free() {
+  const { theme } = useTheme()
+  return <span style={{ fg: theme.secondary }}>Free</span>
+}
 
 export function DialogModel() {
   const local = useLocal()
   const sync = useSync()
   const dialog = useDialog()
   const [ref, setRef] = createSignal<DialogSelectRef<unknown>>()
+  const { theme } = useTheme()
 
   const options = createMemo(() => {
     return [
@@ -29,6 +36,7 @@ export function DialogModel() {
                 title: model.name ?? item.modelID,
                 description: provider.name,
                 category: "Recent",
+                footer: model.cost.input === 0 && provider.id === "opencode" ? <Free /> : undefined,
               },
             ]
           })
@@ -51,6 +59,7 @@ export function DialogModel() {
               title: info.name ?? model,
               description: provider.name,
               category: provider.name,
+              footer: info.cost.input === 0 && provider.id === "opencode" ? <Free /> : undefined,
             })),
             filter((x) => Boolean(ref()?.filter) || !local.model.recent().find((y) => isDeepEqual(y, x.value))),
           ),

+ 2 - 3
packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx

@@ -30,7 +30,7 @@ export interface DialogSelectOption<T = any> {
   title: string
   value: T
   description?: string
-  footer?: string
+  footer?: JSX.Element | string
   category?: string
   disabled?: boolean
   bg?: RGBA
@@ -172,7 +172,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
                 props.onFilter?.(e)
               })
             }}
-            onKeyDown={(e) => {}}
             focusedBackgroundColor={theme.backgroundPanel}
             cursorColor={theme.primary}
             focusedTextColor={theme.textMuted}
@@ -256,7 +255,7 @@ function Option(props: {
   description?: string
   active?: boolean
   current?: boolean
-  footer?: string
+  footer?: JSX.Element | string
   onMouseOver?: () => void
 }) {
   const { theme } = useTheme()