Skip to content

Commit 25e8cd6

Browse files
Hk-Gosutoclaude
andauthored
feat: enhance model selector and improve UI accessibility (ChatGPTNextWeb#378)
Co-authored-by: Claude <[email protected]>
1 parent 1176375 commit 25e8cd6

18 files changed

Lines changed: 5089 additions & 105 deletions

AGENTS.md

Lines changed: 428 additions & 0 deletions
Large diffs are not rendered by default.

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# In ./CLAUDE.md
2+
@AGENTS.md

app/client/platforms/openai.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,6 @@ export class ChatGPTApi implements LLMApi {
301301
// Please do not ask me why not send max_tokens, no reason, this param is just shit, I dont want to explain anymore.
302302
};
303303

304-
305304
// add max_tokens to vision model
306305
// O系列 使用 max_completion_tokens 控制token数 (https://platform.openai.com/docs/guides/reasoning#controlling-costs)
307306
if (visionModel) {
@@ -752,6 +751,13 @@ export class ChatGPTApi implements LLMApi {
752751
});
753752

754753
const resJson = (await res.json()) as OpenAIListModelResponse;
754+
755+
// 检查响应数据是否有效
756+
if (!resJson.data || !Array.isArray(resJson.data)) {
757+
console.warn("[Models] Invalid response from OpenAI API:", resJson);
758+
return [];
759+
}
760+
755761
// const chatModels = resJson.data?.filter(
756762
// (m) => m.id.startsWith("gpt-") || m.id.startsWith("chatgpt-"),
757763
// );

app/components/button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function IconButton(props: {
2121
autoFocus?: boolean;
2222
loding?: boolean;
2323
style?: CSSProperties;
24-
aria?: string;
24+
ariaLabel?: string;
2525
}) {
2626
return (
2727
<button
@@ -38,7 +38,7 @@ export function IconButton(props: {
3838
tabIndex={props.tabIndex}
3939
autoFocus={props.autoFocus}
4040
style={props.style}
41-
aria-label={props.aria}
41+
aria-label={props.ariaLabel}
4242
>
4343
{props.icon && !props.loding && (
4444
<div

app/components/chat.tsx

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ import {
114114
List,
115115
ListItem,
116116
Modal,
117-
SearchSelector,
117+
ModelSelectorModal,
118118
Selector,
119119
showConfirm,
120120
showPrompt,
@@ -599,12 +599,11 @@ export function ChatActions(props: {
599599

600600
const currentModelName = useMemo(() => {
601601
const model = models.find(
602-
(m) =>
603-
m.name == currentModel &&
604-
m?.provider?.providerName == currentProviderName,
602+
(m) => m.name == currentModel,
603+
// && m?.provider?.providerName == currentProviderName,
605604
);
606605
return model?.displayName ?? "";
607-
}, [models, currentModel, currentProviderName]);
606+
}, [models, currentModel]);
608607
const [showModelSelector, setShowModelSelector] = useState(false);
609608
const [showPluginSelector, setShowPluginSelector] = useState(false);
610609
const [showUploadImage, setShowUploadImage] = useState(false);
@@ -831,16 +830,8 @@ export function ChatActions(props: {
831830
)}
832831

833832
{showModelSelector && (
834-
<SearchSelector
833+
<ModelSelectorModal
835834
defaultSelectedValue={`${currentModel}@${currentProviderName}`}
836-
items={models.map((m) => ({
837-
title: `${m.displayName}${
838-
m?.provider?.providerName && !isDisableModelProviderDisplay
839-
? "(" + m?.provider?.providerName + ")"
840-
: ""
841-
}`,
842-
value: `${m.name}@${m?.provider?.providerName}`,
843-
}))}
844835
onClose={() => setShowModelSelector(false)}
845836
onSelection={(s) => {
846837
if (s.length === 0) return;
@@ -1996,7 +1987,7 @@ function Chat() {
19961987
icon={<RenameIcon />}
19971988
bordered
19981989
title={Locale.Chat.EditMessage.Title}
1999-
aria={Locale.Chat.EditMessage.Title}
1990+
ariaLabel={Locale.Chat.EditMessage.Title}
20001991
onClick={() => setIsEditingMessage(true)}
20011992
/>
20021993
</div>
@@ -2017,7 +2008,7 @@ function Chat() {
20172008
icon={config.tightBorder ? <MinIcon /> : <MaxIcon />}
20182009
bordered
20192010
title={Locale.Chat.Actions.FullScreen}
2020-
aria={Locale.Chat.Actions.FullScreen}
2011+
ariaLabel={Locale.Chat.Actions.FullScreen}
20212012
onClick={() => {
20222013
config.update(
20232014
(config) => (config.tightBorder = !config.tightBorder),
@@ -2073,7 +2064,7 @@ function Chat() {
20732064
<div className={styles["chat-message-edit"]}>
20742065
<IconButton
20752066
icon={<EditIcon />}
2076-
aria={Locale.Chat.Actions.Edit}
2067+
ariaLabel={Locale.Chat.Actions.Edit}
20772068
onClick={async () => {
20782069
const newMessage = await showPrompt(
20792070
Locale.Chat.Actions.Edit,

app/components/input-range.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface InputRangeProps {
99
min: string;
1010
max: string;
1111
step: string;
12-
aria: string;
12+
ariaLabel: string;
1313
}
1414

1515
export function InputRange({
@@ -20,13 +20,13 @@ export function InputRange({
2020
min,
2121
max,
2222
step,
23-
aria,
23+
ariaLabel,
2424
}: InputRangeProps) {
2525
return (
2626
<div className={styles["input-range"] + ` ${className ?? ""}`}>
2727
{title || value}
2828
<input
29-
aria-label={aria}
29+
aria-label={ariaLabel}
3030
type="range"
3131
title={title}
3232
value={value}

app/components/markdown.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export function PreCode(props: { children: any }) {
142142
renderArtifacts();
143143
return () => observer.disconnect();
144144
}
145-
}, []);
145+
}, [renderArtifacts]);
146146

147147
return (
148148
<>
@@ -292,16 +292,18 @@ function MarkDownContent(props: {
292292
return (
293293
<ReactMarkdown
294294
remarkPlugins={[RemarkMath, RemarkGfm, RemarkBreaks]}
295-
rehypePlugins={[
296-
RehypeKatex,
295+
rehypePlugins={
297296
[
298-
RehypeHighlight,
299-
{
300-
detect: false,
301-
ignoreMissing: true,
302-
},
303-
],
304-
]}
297+
RehypeKatex as any,
298+
[
299+
RehypeHighlight as any,
300+
{
301+
detect: false,
302+
ignoreMissing: true,
303+
},
304+
],
305+
] as any
306+
}
305307
components={{
306308
pre: PreCode,
307309
code: CustomCode,

app/components/model-config.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function ModelConfigList(props: {
5454
subTitle={Locale.Settings.Temperature.SubTitle}
5555
>
5656
<InputRange
57-
aria={Locale.Settings.Temperature.Title}
57+
ariaLabel={Locale.Settings.Temperature.Title}
5858
value={props.modelConfig.temperature?.toFixed(1)}
5959
min="0"
6060
max="1" // lets limit it to 0-1
@@ -74,7 +74,7 @@ export function ModelConfigList(props: {
7474
subTitle={Locale.Settings.TopP.SubTitle}
7575
>
7676
<InputRange
77-
aria={Locale.Settings.TopP.Title}
77+
ariaLabel={Locale.Settings.TopP.Title}
7878
value={(props.modelConfig.top_p ?? 1).toFixed(1)}
7979
min="0"
8080
max="1"
@@ -140,7 +140,7 @@ export function ModelConfigList(props: {
140140
subTitle={Locale.Settings.PresencePenalty.SubTitle}
141141
>
142142
<InputRange
143-
aria={Locale.Settings.PresencePenalty.Title}
143+
ariaLabel={Locale.Settings.PresencePenalty.Title}
144144
value={props.modelConfig.presence_penalty?.toFixed(1)}
145145
min="-2"
146146
max="2"
@@ -162,7 +162,7 @@ export function ModelConfigList(props: {
162162
subTitle={Locale.Settings.FrequencyPenalty.SubTitle}
163163
>
164164
<InputRange
165-
aria={Locale.Settings.FrequencyPenalty.Title}
165+
ariaLabel={Locale.Settings.FrequencyPenalty.Title}
166166
value={props.modelConfig.frequency_penalty?.toFixed(1)}
167167
min="-2"
168168
max="2"
@@ -219,7 +219,7 @@ export function ModelConfigList(props: {
219219
subTitle={Locale.Settings.HistoryCount.SubTitle}
220220
>
221221
<InputRange
222-
aria={Locale.Settings.HistoryCount.Title}
222+
ariaLabel={Locale.Settings.HistoryCount.Title}
223223
title={props.modelConfig.historyMessageCount.toString()}
224224
value={props.modelConfig.historyMessageCount}
225225
min="0"

app/components/realtime-chat/realtime-config.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export function RealtimeConfigList(props: {
116116
subTitle={Locale.Settings.Realtime.ApiKey.SubTitle}
117117
>
118118
<PasswordInput
119-
aria={Locale.Settings.ShowPassword}
119+
ariaLabel={Locale.Settings.ShowPassword}
120120
aria-label={Locale.Settings.Realtime.ApiKey.Title}
121121
value={props.realtimeConfig.apiKey}
122122
type="text"
@@ -153,7 +153,7 @@ export function RealtimeConfigList(props: {
153153
subTitle={Locale.Settings.Realtime.Temperature.SubTitle}
154154
>
155155
<InputRange
156-
aria={Locale.Settings.Temperature.Title}
156+
ariaLabel={Locale.Settings.Temperature.Title}
157157
value={props.realtimeConfig?.temperature?.toFixed(1)}
158158
min="0.6"
159159
max="1"

app/components/settings.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ function DangerItems() {
254254
subTitle={Locale.Settings.Danger.Reset.SubTitle}
255255
>
256256
<IconButton
257-
aria={Locale.Settings.Danger.Reset.Title}
257+
ariaLabel={Locale.Settings.Danger.Reset.Title}
258258
text={Locale.Settings.Danger.Reset.Action}
259259
onClick={async () => {
260260
if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
@@ -269,7 +269,7 @@ function DangerItems() {
269269
subTitle={Locale.Settings.Danger.Clear.SubTitle}
270270
>
271271
<IconButton
272-
aria={Locale.Settings.Danger.Clear.Title}
272+
ariaLabel={Locale.Settings.Danger.Clear.Title}
273273
text={Locale.Settings.Danger.Clear.Action}
274274
onClick={async () => {
275275
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
@@ -523,7 +523,7 @@ function SyncItems() {
523523
>
524524
<div style={{ display: "flex" }}>
525525
<IconButton
526-
aria={Locale.Settings.Sync.CloudState + Locale.UI.Config}
526+
ariaLabel={Locale.Settings.Sync.CloudState + Locale.UI.Config}
527527
icon={<ConfigIcon />}
528528
text={Locale.UI.Config}
529529
onClick={() => {
@@ -554,15 +554,15 @@ function SyncItems() {
554554
>
555555
<div style={{ display: "flex" }}>
556556
<IconButton
557-
aria={Locale.Settings.Sync.LocalState + Locale.UI.Export}
557+
ariaLabel={Locale.Settings.Sync.LocalState + Locale.UI.Export}
558558
icon={<UploadIcon />}
559559
text={Locale.UI.Export}
560560
onClick={() => {
561561
syncStore.export();
562562
}}
563563
/>
564564
<IconButton
565-
aria={Locale.Settings.Sync.LocalState + Locale.UI.Import}
565+
ariaLabel={Locale.Settings.Sync.LocalState + Locale.UI.Import}
566566
icon={<DownloadIcon />}
567567
text={Locale.UI.Import}
568568
onClick={() => {
@@ -736,7 +736,7 @@ export function Settings() {
736736
subTitle={Locale.Settings.Access.OpenAI.ApiKey.SubTitle}
737737
>
738738
<PasswordInput
739-
aria={Locale.Settings.ShowPassword}
739+
ariaLabel={Locale.Settings.ShowPassword}
740740
aria-label={Locale.Settings.Access.OpenAI.ApiKey.Title}
741741
value={accessStore.openaiApiKey}
742742
type="text"
@@ -1450,7 +1450,7 @@ export function Settings() {
14501450
<div className="window-action-button"></div>
14511451
<div className="window-action-button">
14521452
<IconButton
1453-
aria={Locale.UI.Close}
1453+
ariaLabel={Locale.UI.Close}
14541454
icon={<CloseIcon />}
14551455
onClick={() => navigate(Path.Home)}
14561456
bordered
@@ -1577,7 +1577,7 @@ export function Settings() {
15771577
subTitle={Locale.Settings.FontSize.SubTitle}
15781578
>
15791579
<InputRange
1580-
aria={Locale.Settings.FontSize.Title}
1580+
ariaLabel={Locale.Settings.FontSize.Title}
15811581
title={`${config.fontSize ?? 14}px`}
15821582
value={config.fontSize}
15831583
min="12"
@@ -1746,7 +1746,9 @@ export function Settings() {
17461746
)}
17471747
>
17481748
<IconButton
1749-
aria={Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit}
1749+
ariaLabel={
1750+
Locale.Settings.Prompt.List + Locale.Settings.Prompt.Edit
1751+
}
17501752
icon={<EditIcon />}
17511753
text={Locale.Settings.Prompt.Edit}
17521754
onClick={() => setShowPromptModal(true)}

0 commit comments

Comments
 (0)