mirror of
https://github.com/voideditor/void
synced 2026-05-23 09:28:23 +00:00
update styles and descs
This commit is contained in:
parent
702d11ed3e
commit
298423928e
6 changed files with 93 additions and 55 deletions
|
|
@ -36,7 +36,7 @@ const refreshBasedOn: { [k in RefreshableProviderName]: (keyof SettingsOfProvide
|
|||
openAICompatible: ['enabled', 'endpoint', 'apiKey'],
|
||||
}
|
||||
const REFRESH_INTERVAL = 5_000
|
||||
const COOLDOWN_TIMEOUT = 300
|
||||
// const COOLDOWN_TIMEOUT = 300
|
||||
|
||||
// element-wise equals
|
||||
function eq<T>(a: T[], b: T[]): boolean {
|
||||
|
|
@ -92,18 +92,23 @@ export class RefreshModelService extends Disposable implements IRefreshModelServ
|
|||
this.voidSettingsService.onDidChangeState(() => { // we might want to debounce this
|
||||
const newVals = relevantVals()
|
||||
if (!eq(prevVals, newVals)) {
|
||||
prevVals = newVals
|
||||
|
||||
const { enabled } = this.voidSettingsService.state.settingsOfProvider[providerName]
|
||||
if (enabled) {
|
||||
const prevEnabled = prevVals[0] as boolean
|
||||
const enabled = newVals[0] as boolean
|
||||
|
||||
// if it was just enabled, or there was a change and it wasn't to the enabled state, refresh
|
||||
if ((enabled && !prevEnabled) || (!enabled && !prevEnabled)) {
|
||||
// if user just clicked enable, refresh
|
||||
this.refreshModels(providerName, !enabled)
|
||||
}
|
||||
else {
|
||||
// else if user just clicked disable, give cooldown before re-enabling (or at least re-fetching)
|
||||
const timeoutId = setTimeout(() => this.refreshModels(providerName, !enabled), COOLDOWN_TIMEOUT)
|
||||
this._setTimeoutId(providerName, timeoutId)
|
||||
// else if user just clicked disable, don't refresh
|
||||
|
||||
// //give cooldown before re-enabling (or at least re-fetching)
|
||||
// const timeoutId = setTimeout(() => this.refreshModels(providerName, !enabled), COOLDOWN_TIMEOUT)
|
||||
// this._setTimeoutId(providerName, timeoutId)
|
||||
}
|
||||
prevVals = newVals
|
||||
}
|
||||
})
|
||||
)
|
||||
|
|
|
|||
|
|
@ -155,22 +155,47 @@ export type SettingName = keyof SettingsForProvider<ProviderName>
|
|||
|
||||
|
||||
|
||||
type DisplayInfoForProviderName = {
|
||||
title: string,
|
||||
}
|
||||
|
||||
export const titleOfProviderName = (providerName: ProviderName) => {
|
||||
if (providerName === 'anthropic')
|
||||
return 'Anthropic'
|
||||
else if (providerName === 'openAI')
|
||||
return 'OpenAI'
|
||||
else if (providerName === 'ollama')
|
||||
return 'Ollama'
|
||||
else if (providerName === 'openRouter')
|
||||
return 'OpenRouter'
|
||||
else if (providerName === 'openAICompatible')
|
||||
return 'OpenAI-Compatible'
|
||||
else if (providerName === 'gemini')
|
||||
return 'Gemini'
|
||||
else if (providerName === 'groq')
|
||||
return 'Groq'
|
||||
export const displayInfoOfProviderName = (providerName: ProviderName): DisplayInfoForProviderName => {
|
||||
if (providerName === 'anthropic') {
|
||||
return {
|
||||
title: 'Anthropic',
|
||||
}
|
||||
}
|
||||
else if (providerName === 'openAI') {
|
||||
return {
|
||||
title: 'OpenAI',
|
||||
}
|
||||
}
|
||||
else if (providerName === 'openRouter') {
|
||||
return {
|
||||
title: 'OpenRouter',
|
||||
}
|
||||
}
|
||||
else if (providerName === 'ollama') {
|
||||
return {
|
||||
title: 'Ollama',
|
||||
|
||||
}
|
||||
}
|
||||
else if (providerName === 'openAICompatible') {
|
||||
return {
|
||||
title: 'OpenAI-Compatible',
|
||||
}
|
||||
}
|
||||
else if (providerName === 'gemini') {
|
||||
return {
|
||||
title: 'Gemini',
|
||||
}
|
||||
}
|
||||
else if (providerName === 'groq') {
|
||||
return {
|
||||
title: 'Groq',
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`descOfProviderName: Unknown provider name: "${providerName}"`)
|
||||
}
|
||||
|
|
@ -178,9 +203,7 @@ export const titleOfProviderName = (providerName: ProviderName) => {
|
|||
type DisplayInfo = {
|
||||
title: string,
|
||||
placeholder: string,
|
||||
|
||||
helpfulUrl?: string,
|
||||
urlPurpose?: string,
|
||||
subTextMd?: string,
|
||||
}
|
||||
export const displayInfoOfSettingName = (providerName: ProviderName, settingName: SettingName): DisplayInfo => {
|
||||
if (settingName === 'apiKey') {
|
||||
|
|
@ -194,15 +217,13 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
|
|||
providerName === 'openAICompatible' ? 'sk-key...' :
|
||||
'(never)',
|
||||
|
||||
helpfulUrl: providerName === 'anthropic' ? 'https://console.anthropic.com/settings/keys' :
|
||||
providerName === 'openAI' ? 'https://platform.openai.com/api-keys' :
|
||||
providerName === 'openRouter' ? 'https://openrouter.ai/settings/keys' :
|
||||
providerName === 'gemini' ? 'https://aistudio.google.com/apikey' :
|
||||
providerName === 'groq' ? 'https://console.groq.com/keys' :
|
||||
subTextMd: providerName === 'anthropic' ? 'Get your [API Key here](https://console.anthropic.com/settings/keys).' :
|
||||
providerName === 'openAI' ? 'Get your [API Key here](https://platform.openai.com/api-keys).' :
|
||||
providerName === 'openRouter' ? 'Get your [API Key here](https://openrouter.ai/settings/keys).' :
|
||||
providerName === 'gemini' ? 'Get your [API Key here](https://aistudio.google.com/apikey).' :
|
||||
providerName === 'groq' ? 'Get your [API Key here](https://console.groq.com/keys).' :
|
||||
providerName === 'openAICompatible' ? undefined :
|
||||
undefined,
|
||||
|
||||
urlPurpose: 'to get your API key.',
|
||||
}
|
||||
}
|
||||
else if (settingName === 'endpoint') {
|
||||
|
|
@ -215,11 +236,8 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
|
|||
: providerName === 'openAICompatible' ? 'https://my-website.com/v1'
|
||||
: '(never)',
|
||||
|
||||
helpfulUrl: providerName === 'ollama' ? 'https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-expose-ollama-on-my-network'
|
||||
: providerName === 'openAICompatible' ? undefined
|
||||
: undefined,
|
||||
|
||||
urlPurpose: 'for more information.',
|
||||
subTextMd: providerName === 'ollama' ? 'Read about Ollama [Endpoints here](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-expose-ollama-on-my-network).' :
|
||||
undefined,
|
||||
}
|
||||
}
|
||||
else if (settingName === 'enabled') {
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ const RenderToken = ({ token, nested = false }: { token: Token | string, nested?
|
|||
|
||||
if (t.type === "link") {
|
||||
return (
|
||||
<a href={t.href} title={t.title ?? undefined}>
|
||||
<a className='underline' onClick={() => { window.open(t.href) }} href={t.href} title={t.title ?? undefined}>
|
||||
{t.text}
|
||||
</a>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@
|
|||
@tailwind utilities;
|
||||
|
||||
|
||||
@layer components {
|
||||
.select-ellipsis select {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-right: 24px;
|
||||
}
|
||||
.select-child-restyle select {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
* {
|
||||
|
|
@ -22,6 +20,7 @@
|
|||
|
||||
|
||||
|
||||
|
||||
/* html {
|
||||
font-size: var(--vscode-font-size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ export const VoidSelectBox = <T,>({ onChangeSelection, onCreateInstance, selectB
|
|||
let containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
return <WidgetComponent
|
||||
className='@@select-ellipsis'
|
||||
className='@@select-child-restyle'
|
||||
ctor={SelectBox}
|
||||
propsFn={useCallback((container) => {
|
||||
containerRef.current = container
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'
|
||||
import { ProviderName, SettingName, displayInfoOfSettingName, titleOfProviderName, providerNames, VoidModelInfo, featureFlagNames, displayInfoOfFeatureFlag, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
|
||||
import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidModelInfo, featureFlagNames, displayInfoOfFeatureFlag, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName } from '../../../../../../../platform/void/common/voidSettingsTypes.js'
|
||||
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
|
||||
import { VoidCheckBox, VoidInputBox, VoidSelectBox, VoidSwitch } from '../util/inputs.js'
|
||||
import { useIsDark, useRefreshModelListener, useRefreshModelState, useService, useSettingsState } from '../util/services.js'
|
||||
import { X, RefreshCw, Loader2, Check } from 'lucide-react'
|
||||
import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js'
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,12 +31,14 @@ const RefreshModelButton = ({ providerName }: { providerName: RefreshableProvide
|
|||
const { state } = refreshModelState[providerName]
|
||||
const isRefreshing = state === 'refreshing'
|
||||
|
||||
const providerTitle = titleOfProviderName(providerName)
|
||||
const { title: providerTitle } = displayInfoOfProviderName(providerName)
|
||||
return <div className='flex items-center py-1 px-3 rounded-sm overflow-hidden gap-2 hover:bg-black/10 dark:hover:bg-gray-200/10'>
|
||||
<button className='flex items-center' disabled={isRefreshing || justFinished} onClick={() => { refreshModelService.refreshModels(providerName) }}>
|
||||
{isRefreshing ? <Loader2 className='size-3 animate-spin' /> : (justFinished ? <Check className='stroke-green-500 size-3' /> : <RefreshCw className='size-3' />)}
|
||||
</button>
|
||||
<span className='opacity-50'>Refresh Default Models for {providerTitle}.</span>
|
||||
<span className='opacity-50'>{
|
||||
justFinished ? `${providerTitle} Models are up-to-date!` : `Refresh Models List for ${providerTitle}.`
|
||||
}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +68,8 @@ const AddModelMenu = ({ onSubmit }: { onSubmit: () => void }) => {
|
|||
|
||||
const [errorString, setErrorString] = useState('')
|
||||
|
||||
const providerOptions = useMemo(() => providerNames.map(providerName => ({ text: titleOfProviderName(providerName), value: providerName })), [providerNames])
|
||||
|
||||
const providerOptions = useMemo(() => providerNames.map(providerName => ({ text: displayInfoOfProviderName(providerName).title, value: providerName })), [providerNames])
|
||||
|
||||
return <>
|
||||
<div className='flex items-center gap-4'>
|
||||
|
|
@ -129,7 +133,7 @@ const AddModelMenu = ({ onSubmit }: { onSubmit: () => void }) => {
|
|||
const AddModelMenuFull = () => {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
return <div className='my-2 hover:bg-black/10 dark:hover:bg-gray-200/10 py-1 px-3 rounded-sm overflow-hidden '>
|
||||
return <div className='hover:bg-black/10 dark:hover:bg-gray-200/10 py-1 px-3 rounded-sm overflow-hidden '>
|
||||
{open ?
|
||||
<AddModelMenu onSubmit={() => { setOpen(false) }} />
|
||||
: <button
|
||||
|
|
@ -163,6 +167,8 @@ export const ModelDump = () => {
|
|||
{modelDump.map(m => {
|
||||
const { isHidden, isDefault, modelName, providerName, providerEnabled } = m
|
||||
|
||||
const disabled = !providerEnabled
|
||||
|
||||
return <div key={`${modelName}${providerName}`} className='flex items-center justify-between gap-4 hover:bg-black/10 dark:hover:bg-gray-200/10 py-1 px-3 rounded-sm overflow-hidden cursor-default'>
|
||||
{/* left part is width:full */}
|
||||
<div className={`w-full flex items-center gap-4`}>
|
||||
|
|
@ -173,9 +179,9 @@ export const ModelDump = () => {
|
|||
<span className='opacity-50 whitespace-nowrap'>{isDefault ? '' : '(custom model)'}</span>
|
||||
|
||||
<VoidSwitch
|
||||
value={!isHidden}
|
||||
value={disabled ? false : !isHidden}
|
||||
onChange={() => { settingsStateService.toggleModelHidden(providerName, modelName) }}
|
||||
disabled={!providerEnabled}
|
||||
disabled={disabled}
|
||||
size='sm'
|
||||
/>
|
||||
|
||||
|
|
@ -194,8 +200,10 @@ export const ModelDump = () => {
|
|||
|
||||
const ProviderSetting = ({ providerName, settingName }: { providerName: ProviderName, settingName: SettingName }) => {
|
||||
|
||||
const providerTitle = titleOfProviderName(providerName)
|
||||
const { title: settingTitle, placeholder, } = displayInfoOfSettingName(providerName, settingName)
|
||||
|
||||
const { title: providerTitle, } = displayInfoOfProviderName(providerName)
|
||||
|
||||
const { title: settingTitle, placeholder, subTextMd } = displayInfoOfSettingName(providerName, settingName)
|
||||
const voidSettingsService = useService('settingsStateService')
|
||||
|
||||
let weChangedTextRef = false
|
||||
|
|
@ -225,6 +233,10 @@ const ProviderSetting = ({ providerName, settingName }: { providerName: Provider
|
|||
}, [voidSettingsService, providerName, settingName])}
|
||||
multiline={false}
|
||||
/>
|
||||
{subTextMd === undefined ? null : <div className='py-1 px-3 opacity-50 text-xs'>
|
||||
<ChatMarkdownRender string={subTextMd} />
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
}
|
||||
|
|
@ -236,9 +248,12 @@ const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) =
|
|||
const { enabled } = voidSettingsState.settingsOfProvider[providerName]
|
||||
const settingNames = customSettingNamesOfProvider(providerName)
|
||||
|
||||
const { title: providerTitle } = displayInfoOfProviderName(providerName)
|
||||
|
||||
return <div className='my-4'>
|
||||
<div className='flex items-center w-full gap-4'>
|
||||
<h3 className='text-xl truncate'>{titleOfProviderName(providerName)}</h3>
|
||||
<h3 className='text-xl truncate'>{providerTitle}</h3>
|
||||
|
||||
{/* enable provider switch */}
|
||||
<VoidSwitch
|
||||
value={!!enabled}
|
||||
|
|
@ -250,6 +265,7 @@ const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) =
|
|||
size='sm+'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='px-0'>
|
||||
{/* settings besides models (e.g. api key) */}
|
||||
{settingNames.map((settingName, i) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue