feat(tui): add agent picker preview
This commit is contained in:
parent
430750e2f8
commit
16255dd8b6
2 changed files with 83 additions and 11 deletions
|
|
@ -1,27 +1,71 @@
|
|||
import { createMemo } from "solid-js"
|
||||
import { useLocal } from "../context/local"
|
||||
import { DialogSelect } from "../ui/dialog-select"
|
||||
import { DialogSelect, type DialogSelectOption } from "../ui/dialog-select"
|
||||
import { useDialog } from "../ui/dialog"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { DialogModel } from "./dialog-model"
|
||||
|
||||
export function DialogAgent() {
|
||||
const local = useLocal()
|
||||
const dialog = useDialog()
|
||||
const { theme } = useTheme()
|
||||
|
||||
dialog.setSize("xlarge")
|
||||
|
||||
const options = createMemo(() =>
|
||||
local.agent.list().map((item) => {
|
||||
return {
|
||||
value: item.id,
|
||||
title: item.id,
|
||||
description: item.description,
|
||||
description: undefined,
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
function Preview(props: { option: DialogSelectOption<string> | undefined }) {
|
||||
const agent = createMemo(() => local.agent.list().find((item) => item.id === props.option?.value))
|
||||
const model = createMemo(() => {
|
||||
const value = agent()?.model
|
||||
if (value) return `${value.providerID}/${value.id}`
|
||||
return "Uses the current session model"
|
||||
})
|
||||
|
||||
return (
|
||||
<box gap={1}>
|
||||
<text fg={theme.text} attributes={TextAttributes.BOLD}>
|
||||
{agent()?.id}
|
||||
</text>
|
||||
<box>
|
||||
<text fg={theme.textMuted}>DESCRIPTION</text>
|
||||
<text fg={theme.text} wrapMode="word">
|
||||
{agent()?.description ?? "No description provided."}
|
||||
</text>
|
||||
</box>
|
||||
<box>
|
||||
<text fg={theme.textMuted}>MODEL</text>
|
||||
<text fg={agent()?.model ? theme.text : theme.textMuted}>{model()}</text>
|
||||
</box>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<DialogSelect
|
||||
title="Select agent"
|
||||
current={local.agent.current()?.id}
|
||||
options={options()}
|
||||
preview={(option) => <Preview option={option} />}
|
||||
actions={[
|
||||
{
|
||||
command: "model.list",
|
||||
title: "Choose model",
|
||||
onTrigger(option) {
|
||||
local.agent.set(option.value)
|
||||
dialog.replace(() => <DialogModel />)
|
||||
},
|
||||
},
|
||||
]}
|
||||
onSelect={(option) => {
|
||||
local.agent.set(option.value)
|
||||
dialog.clear()
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export interface DialogSelectProps<T> {
|
|||
label: string
|
||||
side?: "left" | "right"
|
||||
}[]
|
||||
preview?: (option: DialogSelectOption<T> | undefined) => JSX.Element
|
||||
bindings?: readonly Binding<Renderable, KeyEvent>[]
|
||||
current?: T
|
||||
}
|
||||
|
|
@ -557,17 +558,37 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
}
|
||||
|
||||
return (
|
||||
<box gap={1} paddingBottom={1} flexGrow={1}>
|
||||
<box paddingLeft={4} paddingRight={4}>
|
||||
<box gap={1} paddingBottom={1} flexGrow={1} minHeight={props.preview ? 18 : undefined} position="relative">
|
||||
<Show when={props.preview}>
|
||||
<box
|
||||
position="absolute"
|
||||
top={-1}
|
||||
bottom={0}
|
||||
right={0}
|
||||
width="58%"
|
||||
paddingLeft={4}
|
||||
paddingRight={4}
|
||||
backgroundColor={theme.backgroundElement}
|
||||
zIndex={2}
|
||||
>
|
||||
<text position="absolute" right={4} fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
{props.preview?.(selected())}
|
||||
</box>
|
||||
</Show>
|
||||
<box paddingLeft={4} paddingRight={props.preview ? 2 : 4} width={props.preview ? "42%" : "100%"}>
|
||||
<box flexDirection="row" justifyContent="space-between">
|
||||
{props.titleView ?? (
|
||||
<text fg={theme.text} attributes={TextAttributes.BOLD}>
|
||||
{props.title}
|
||||
</text>
|
||||
)}
|
||||
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
<Show when={!props.preview}>
|
||||
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
||||
esc
|
||||
</text>
|
||||
</Show>
|
||||
</box>
|
||||
<Show when={props.renderFilter !== false}>
|
||||
<box paddingTop={1}>
|
||||
|
|
@ -597,7 +618,7 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
</box>
|
||||
</Show>
|
||||
</box>
|
||||
<box flexGrow={1} flexShrink={1}>
|
||||
<box flexGrow={1} flexShrink={1} width={props.preview ? "42%" : "100%"}>
|
||||
<Show
|
||||
when={grouped().length > 0}
|
||||
fallback={
|
||||
|
|
@ -609,8 +630,8 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
}
|
||||
>
|
||||
<scrollbox
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
paddingLeft={props.preview ? 3 : 1}
|
||||
paddingRight={props.preview ? 3 : 1}
|
||||
scrollbarOptions={{ visible: false }}
|
||||
scrollAcceleration={scrollAcceleration()}
|
||||
ref={(r: ScrollBoxRenderable) => (scroll = r)}
|
||||
|
|
@ -721,7 +742,14 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
|||
</Show>
|
||||
</box>
|
||||
<Show when={props.footer || visibleActions().length} fallback={<box flexShrink={0} />}>
|
||||
<box paddingRight={2} paddingLeft={4} flexDirection="row" justifyContent="space-between" flexShrink={0}>
|
||||
<box
|
||||
paddingRight={2}
|
||||
paddingLeft={4}
|
||||
width={props.preview ? "42%" : "100%"}
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
flexShrink={0}
|
||||
>
|
||||
<box flexDirection="row" gap={2}>
|
||||
{props.footer}
|
||||
<For each={left()}>{(item) => <FooterAction item={item} />}</For>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue