Turbo models (#1249)

<!-- This is an auto-generated description by cubic. -->

## Summary by cubic
Adds “Dyad Turbo” models for Pro users and centralizes model/provider
constants. Pro users can pick fast, cost‑effective models directly from
the ModelPicker, with clearer labels and gating.

- **New Features**
- Added Dyad Turbo provider in ModelPicker with Qwen3 Coder and Kimi K2
(Pro only).
- Turbo options are hidden for non‑Pro users; “Pro only” badge shown
where applicable.
- “Smart Auto” label now applies only to the Auto model to avoid
confusion.

- **Refactors**
- Moved all model/provider constants into language_model_constants.ts
and updated imports (helpers, client, thinking utils).

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Will Chen
2025-09-10 15:59:54 -07:00
committed by GitHub
parent 9bc5e1387a
commit a8e9caf7b0
5 changed files with 497 additions and 447 deletions

View File

@@ -25,6 +25,7 @@ import { LocalModel } from "@/ipc/ipc_types";
import { useLanguageModelProviders } from "@/hooks/useLanguageModelProviders";
import { useSettings } from "@/hooks/useSettings";
import { PriceBadge } from "@/components/PriceBadge";
import { TURBO_MODELS } from "@/ipc/shared/language_model_constants";
export function ModelPicker() {
const { settings, updateSettings } = useSettings();
@@ -108,6 +109,13 @@ export function ModelPicker() {
const autoModels =
!loading && modelsByProviders && modelsByProviders["auto"]
? modelsByProviders["auto"].filter((model) => {
if (
settings &&
!isDyadProEnabled(settings) &&
model.apiName === "turbo"
) {
return false;
}
if (
settings &&
isDyadProEnabled(settings) &&
@@ -144,6 +152,9 @@ export function ModelPicker() {
const provider = providers?.find((p) => p.id === providerId);
return !(provider && provider.secondary);
});
if (settings && isDyadProEnabled(settings)) {
primaryProviders.unshift(["auto", TURBO_MODELS]);
}
const secondaryProviders = providerEntries.filter(([providerId, models]) => {
if (models.length === 0) return false;
const provider = providers?.find((p) => p.id === providerId);
@@ -220,7 +231,7 @@ export function ModelPicker() {
<div className="flex justify-between items-start w-full">
<span className="flex flex-col items-start">
<span>
{isSmartAutoEnabled
{isSmartAutoEnabled && model.apiName === "auto"
? "Smart Auto"
: model.displayName}
</span>
@@ -228,7 +239,7 @@ export function ModelPicker() {
<div className="flex items-center gap-1.5">
{isSmartAutoEnabled && (
<span className="text-[10px] bg-gradient-to-r from-indigo-600 via-indigo-500 to-indigo-600 bg-[length:200%_100%] animate-[shimmer_5s_ease-in-out_infinite] text-white px-1.5 py-0.5 rounded-full font-medium">
Dyad Pro
Pro only
</span>
)}
{model.tag && (
@@ -241,7 +252,7 @@ export function ModelPicker() {
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="right">
{isSmartAutoEnabled ? (
{isSmartAutoEnabled && model.apiName === "auto" ? (
<p>
<strong>Smart Auto</strong> uses a cheaper model for
easier tasks
@@ -274,12 +285,16 @@ export function ModelPicker() {
return true;
});
const provider = providers?.find((p) => p.id === providerId);
const providerDisplayName =
provider?.id === "auto"
? "Dyad Turbo"
: (provider?.name ?? providerId);
return (
<DropdownMenuSub key={providerId}>
<DropdownMenuSubTrigger className="w-full font-normal">
<div className="flex flex-col items-start w-full">
<div className="flex items-center gap-2">
<span>{provider?.name ?? providerId}</span>
<span>{providerDisplayName}</span>
{provider?.type === "cloud" &&
!provider?.secondary &&
isDyadProEnabled(settings) && (
@@ -300,7 +315,7 @@ export function ModelPicker() {
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="w-56">
<DropdownMenuLabel>
{(provider?.name ?? providerId) + " Models"}
{providerDisplayName + " Models"}
</DropdownMenuLabel>
<DropdownMenuSeparator />
{models.map((model) => (