More free models (#1244)

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

## Summary by cubic
Adds support for free OpenRouter models and a new “Free (OpenRouter)”
auto option that fails over across free models for reliability. Improves
setup flow and UI with provider cards, a “Free” price badge, and an
OpenRouter setup prompt in chat.

- **New Features**
- Added OpenRouter free models: Qwen3 Coder (free), DeepSeek v3 (free),
DeepSeek v3.1 (free), marked with dollarSigns=0 and a “Free” badge.
- New auto model: “Free (OpenRouter)” that uses a fallback client to
cycle through free models with smart retry on transient errors.
- New SetupProviderCard component and updated SetupBanner with dedicated
Google and OpenRouter setup cards.
- Chat shows an OpenRouter setup prompt when “Free (OpenRouter)” is
selected and OpenRouter isn’t configured.
- New PriceBadge component in ModelPicker to display “Free” or price
tier.
- E2E: added setup flow test and option to show the setup screen in
tests.
- Model updates: added DeepSeek v3.1, updated Kimi K2 to kimi-k2-0905,
migrated providers to LanguageModelV2.

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Will Chen
2025-09-10 14:20:17 -07:00
committed by GitHub
parent 7150082f5a
commit 72acb31d59
11 changed files with 573 additions and 72 deletions

View File

@@ -133,9 +133,7 @@ export function SetupBanner() {
return (
<>
<p className="text-xl text-zinc-700 dark:text-zinc-300 p-4">
Follow these steps and you'll be ready to start building with Dyad...
</p>
<p className="text-xl text-zinc-700 dark:text-zinc-300 p-4">Setup Dyad</p>
<div className={bannerClasses}>
<Accordion
type="multiple"
@@ -367,3 +365,36 @@ function NodeInstallButton({
const _exhaustiveCheck: never = nodeInstallStep;
}
}
export const OpenRouterSetupBanner = ({
className,
}: {
className?: string;
}) => {
const posthog = usePostHog();
const navigate = useNavigate();
return (
<SetupProviderCard
className={cn("mt-2", className)}
variant="openrouter"
onClick={() => {
posthog.capture("setup-flow:ai-provider-setup:openrouter:click");
navigate({
to: providerSettingsRoute.id,
params: { provider: "openrouter" },
});
}}
tabIndex={0}
leadingIcon={
<Sparkles className="w-4 h-4 text-purple-600 dark:text-purple-400" />
}
title="Setup OpenRouter API Key"
subtitle={
<>
<GiftIcon className="w-3 h-3" />
Free models available
</>
}
/>
);
};