Skip to content

Commit c9d1242

Browse files
committed
Extract provider/model selection to ProviderModelPicker
- Consolidate provider and model selection into reusable component - Replace getAppModelOptions with getCustomModelOptionsByProvider - Simplifies settings UI and enables reuse across the app
1 parent dcad93f commit c9d1242

File tree

1 file changed

+25
-79
lines changed

1 file changed

+25
-79
lines changed

apps/web/src/routes/_chat.settings.tsx

Lines changed: 25 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { createFileRoute } from "@tanstack/react-router";
22
import { useQuery } from "@tanstack/react-query";
33
import { useCallback, useState } from "react";
44
import {
5+
type ModelSlug,
56
type ProviderKind,
67
DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER,
78
} from "@t3tools/contracts";
89
import { getModelOptions, normalizeModelSlug } from "@t3tools/shared/model";
910
import {
10-
getAppModelOptions,
11+
getCustomModelOptionsByProvider,
1112
getCustomModelsForProvider,
1213
getDefaultCustomModelsForProvider,
1314
MAX_CUSTOM_MODEL_LENGTH,
@@ -31,6 +32,7 @@ import {
3132
} from "../components/ui/select";
3233
import { Switch } from "../components/ui/switch";
3334
import { APP_VERSION } from "../branding";
35+
import { ProviderModelPicker } from "../components/chat/ProviderModelPicker";
3436
import { SidebarInset } from "~/components/ui/sidebar";
3537

3638
const THEME_OPTIONS = [
@@ -80,16 +82,8 @@ function SettingsRouteView() {
8082

8183
const textGenProvider = settings.textGenerationProvider;
8284
const textGenDefaultModel = DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER[textGenProvider];
83-
const gitTextGenerationModelOptions = getAppModelOptions(
84-
textGenProvider,
85-
textGenProvider === "codex" ? settings.customCodexModels : settings.customClaudeModels,
86-
settings.textGenerationModel,
87-
);
88-
const selectedGitTextGenerationModelLabel =
89-
gitTextGenerationModelOptions.find(
90-
(option) =>
91-
option.slug === (settings.textGenerationModel ?? textGenDefaultModel),
92-
)?.name ?? settings.textGenerationModel;
85+
const textGenModel = (settings.textGenerationModel ?? textGenDefaultModel) as ModelSlug;
86+
const gitModelOptionsByProvider = getCustomModelOptionsByProvider(settings);
9387

9488
const openKeybindingsFile = useCallback(() => {
9589
if (!keybindingsConfigPath) return;
@@ -490,75 +484,27 @@ function SettingsRouteView() {
490484
</p>
491485
</div>
492486

493-
<div className="flex flex-col gap-4">
494-
<div className="flex flex-col gap-4 rounded-lg border border-border bg-background px-3 py-3 sm:flex-row sm:items-center sm:justify-between">
495-
<div className="min-w-0 flex-1">
496-
<p className="text-sm font-medium text-foreground">
497-
Text generation provider
498-
</p>
499-
<p className="text-xs text-muted-foreground">
500-
Which AI provider to use for auto-generated git content.
501-
</p>
502-
</div>
503-
<Select
504-
value={textGenProvider}
505-
onValueChange={(value) => {
506-
if (value === "codex" || value === "claudeAgent") {
507-
updateSettings({
508-
textGenerationProvider: value,
509-
textGenerationModel:
510-
DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER[value],
511-
});
512-
}
513-
}}
514-
>
515-
<SelectTrigger
516-
className="w-full shrink-0 sm:w-48"
517-
aria-label="Git text generation provider"
518-
>
519-
<SelectValue>
520-
{textGenProvider === "claudeAgent" ? "Claude" : "Codex"}
521-
</SelectValue>
522-
</SelectTrigger>
523-
<SelectPopup align="end">
524-
<SelectItem value="codex">Codex</SelectItem>
525-
<SelectItem value="claudeAgent">Claude</SelectItem>
526-
</SelectPopup>
527-
</Select>
528-
</div>
529-
530-
<div className="flex flex-col gap-4 rounded-lg border border-border bg-background px-3 py-3 sm:flex-row sm:items-center sm:justify-between">
531-
<div className="min-w-0 flex-1">
532-
<p className="text-sm font-medium text-foreground">Text generation model</p>
533-
<p className="text-xs text-muted-foreground">
534-
Model used for auto-generated git content.
535-
</p>
536-
</div>
537-
<Select
538-
value={settings.textGenerationModel ?? textGenDefaultModel}
539-
onValueChange={(value) => {
540-
if (value) {
541-
updateSettings({
542-
textGenerationModel: value,
543-
});
544-
}
545-
}}
546-
>
547-
<SelectTrigger
548-
className="w-full shrink-0 sm:w-48"
549-
aria-label="Git text generation model"
550-
>
551-
<SelectValue>{selectedGitTextGenerationModelLabel}</SelectValue>
552-
</SelectTrigger>
553-
<SelectPopup align="end">
554-
{gitTextGenerationModelOptions.map((option) => (
555-
<SelectItem key={option.slug} value={option.slug}>
556-
{option.name}
557-
</SelectItem>
558-
))}
559-
</SelectPopup>
560-
</Select>
487+
<div className="flex flex-col gap-4 rounded-lg border border-border bg-background px-3 py-3 sm:flex-row sm:items-center sm:justify-between">
488+
<div className="min-w-0 flex-1">
489+
<p className="text-sm font-medium text-foreground">
490+
Text generation model
491+
</p>
492+
<p className="text-xs text-muted-foreground">
493+
Provider and model used for auto-generated git content.
494+
</p>
561495
</div>
496+
<ProviderModelPicker
497+
provider={textGenProvider}
498+
model={textGenModel}
499+
lockedProvider={null}
500+
modelOptionsByProvider={gitModelOptionsByProvider}
501+
onProviderModelChange={(provider, model) => {
502+
updateSettings({
503+
textGenerationProvider: provider,
504+
textGenerationModel: model,
505+
});
506+
}}
507+
/>
562508
</div>
563509

564510
{(settings.textGenerationModel !== defaults.textGenerationModel ||

0 commit comments

Comments
 (0)