mirror of
https://github.com/zadam/trilium.git
synced 2026-07-04 11:37:25 +02:00
feat(llm): display cost next to the title
This commit is contained in:
@@ -5,16 +5,27 @@ interface FormDropdownList<T> extends Omit<DropdownProps, "children"> {
|
||||
values: T[];
|
||||
keyProperty: keyof T;
|
||||
titleProperty: keyof T;
|
||||
/** Property to show as a small suffix next to the title */
|
||||
titleSuffixProperty?: keyof T;
|
||||
descriptionProperty?: keyof T;
|
||||
currentValue: string;
|
||||
onChange(newValue: string): void;
|
||||
}
|
||||
|
||||
export default function FormDropdownList<T>({ values, keyProperty, titleProperty, descriptionProperty, currentValue, onChange, ...restProps }: FormDropdownList<T>) {
|
||||
export default function FormDropdownList<T>({ values, keyProperty, titleProperty, titleSuffixProperty, descriptionProperty, currentValue, onChange, ...restProps }: FormDropdownList<T>) {
|
||||
const currentValueData = values.find(value => value[keyProperty] === currentValue);
|
||||
|
||||
const renderTitle = (item: T) => {
|
||||
const title = item[titleProperty] as string;
|
||||
const suffix = titleSuffixProperty ? item[titleSuffixProperty] as string : null;
|
||||
if (suffix) {
|
||||
return <>{title} <small>{suffix}</small></>;
|
||||
}
|
||||
return title;
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown text={currentValueData?.[titleProperty] ?? ""} {...restProps}>
|
||||
<Dropdown text={currentValueData ? renderTitle(currentValueData) : ""} {...restProps}>
|
||||
{values.map(item => (
|
||||
<FormListItem
|
||||
onClick={() => onChange(item[keyProperty] as string)}
|
||||
@@ -22,9 +33,9 @@ export default function FormDropdownList<T>({ values, keyProperty, titleProperty
|
||||
description={descriptionProperty && item[descriptionProperty] as string}
|
||||
selected={currentValue === item[keyProperty]}
|
||||
>
|
||||
{item[titleProperty] as string}
|
||||
{renderTitle(item)}
|
||||
</FormListItem>
|
||||
))}
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { RefObject } from "preact";
|
||||
import type { UseLlmChatReturn } from "./useLlmChat.js";
|
||||
|
||||
import { t } from "../../../services/i18n.js";
|
||||
import FormDropdownList from "../../react/FormDropdownList.js";
|
||||
import Dropdown from "../../react/Dropdown.js";
|
||||
import { FormListItem } from "../../react/FormList.js";
|
||||
import type { UseLlmChatReturn } from "./useLlmChat.js";
|
||||
|
||||
/** Format token count with thousands separators */
|
||||
function formatTokenCount(tokens: number): string {
|
||||
@@ -88,16 +90,21 @@ export default function ChatInputBar({
|
||||
<div className="llm-chat-options">
|
||||
<div className="llm-chat-model-selector">
|
||||
<span className="bx bx-chip" />
|
||||
<FormDropdownList
|
||||
values={chat.availableModels}
|
||||
keyProperty="id"
|
||||
titleProperty="name"
|
||||
descriptionProperty="costDescription"
|
||||
currentValue={chat.selectedModel}
|
||||
onChange={handleModelSelect}
|
||||
<Dropdown
|
||||
text={<>{currentModel?.name}</>}
|
||||
disabled={chat.isStreaming}
|
||||
buttonClassName="llm-chat-model-select"
|
||||
/>
|
||||
>
|
||||
{chat.availableModels.map(model => (
|
||||
<FormListItem
|
||||
key={model.id}
|
||||
onClick={() => handleModelSelect(model.id)}
|
||||
checked={chat.selectedModel === model.id}
|
||||
>
|
||||
{model.name}<small>({model.costDescription})</small>
|
||||
</FormListItem>
|
||||
))}
|
||||
</Dropdown>
|
||||
</div>
|
||||
<label className="llm-chat-toggle">
|
||||
<input
|
||||
|
||||
@@ -320,6 +320,11 @@
|
||||
|
||||
.llm-chat-model-selector .dropdown {
|
||||
display: flex;
|
||||
|
||||
small {
|
||||
margin-left: 0.5em;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.llm-chat-model-select.select-button {
|
||||
|
||||
@@ -96,7 +96,7 @@ export function useLlmChat(
|
||||
getAvailableModels().then(models => {
|
||||
const modelsWithDescription = models.map(m => ({
|
||||
...m,
|
||||
costDescription: m.costMultiplier ? `${m.costMultiplier}x cost` : undefined
|
||||
costDescription: m.costMultiplier ? `${m.costMultiplier}x` : undefined
|
||||
}));
|
||||
setAvailableModels(modelsWithDescription);
|
||||
if (!selectedModel) {
|
||||
|
||||
Reference in New Issue
Block a user