Repository: ibelick/zola
Pull request #57: Add DeepSeek Model Support via OpenRouter Integration
Author: login: yguo
Created: 2025-04-15T13:13:00Z | Merged: 2025-04-21T20:06:39Z

# Add DeepSeek Model Support via OpenRouter Integration

## Overview
This PR adds support for the DeepSeek model through OpenRouter integration, expanding the available AI model options in Zola.

## Changes
- Integrated DeepSeek model via OpenRouter API
- Added configuration for DeepSeek model in the model selection system
- Implemented necessary API handlers for DeepSeek interactions

## Technical Details
- Added DeepSeek as a new model option in the model configuration
- Integrated with OpenRouter's API for DeepSeek model access
- Ensured proper error handling and response parsing

## Testing
- Verified DeepSeek model responses through OpenRouter
- Tested model switching functionality
- Confirmed proper error handling and user feedback

## Dependencies
- Requires OpenRouter API configuration
- Compatible with existing model selection infrastructure



Diff:
diff --git a/.env.example b/.env.example
index aa9d1b623..8e9349ac2 100644
--- a/.env.example
+++ b/.env.example
@@ -6,6 +6,9 @@ SUPABASE_SERVICE_ROLE=your_supabase_service_role_key
 # OpenAI
 OPENAI_API_KEY=your_openai_api_key
 
+# OpenRouter
+OPENROUTER_API_KEY=your_openrouter_api_key
+
 # Mistral
 MISTRAL_API_KEY=your_mistral_api_key
 
diff --git a/.gitignore b/.gitignore
index 34cabb372..a54fc2cf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,9 +36,18 @@ yarn-error.log*
 .env.test.local
 .env.production.local
 
+
 # vercel
 .vercel
 
 # typescript
 *.tsbuildinfo
 next-env.d.ts
+
+# env
+.env
+
+# bun
+bun.lockb
+bun.lock
+
diff --git a/INSTALL.md b/INSTALL.md
index 45ecab880..5e700a7dc 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -28,6 +28,9 @@ OPENAI_API_KEY=your_openai_api_key
 # Mistral
 MISTRAL_API_KEY=your_mistral_api_key
 
+# OpenRouter
+OPENROUTER_API_KEY=your_openrouter_api_key
+
 # CSRF Protection
 CSRF_SECRET=your_csrf_secret_key
 
@@ -59,6 +62,35 @@ python -c "import secrets; print(secrets.token_hex(32))"
 
 Copy the generated value and add it to your `.env.local` file as the `CSRF_SECRET` value.
 
+#### Google OAuth Authentication
+
+1. Go to your Supabase project dashboard
+2. Navigate to Authentication > Providers
+3. Find the "Google" provider
+4. Enable it by toggling the switch
+5. Configure the Google OAuth credentials:
+    - You'll need to set up OAuth 2.0 credentials in the Google Cloud Console
+    - Add your application's redirect URL: https://[YOUR_PROJECT_REF].supabase.co/auth/v1/callback
+    - Get the Client ID and Client Secret from Google Cloud Console
+    - Add these credentials to the Google provider settings in Supabase
+
+Here are the detailed steps to set up Google OAuth:
+
+1. Go to the Google Cloud Console
+2. Create a new project or select an existing one
+3. Enable the Google+ API
+4. Go to Credentials > Create Credentials > OAuth Client ID
+5. Configure the OAuth consent screen if you haven't already
+6. Set the application type as "Web application"
+7. Add these authorized redirect URIs:
+  - https://[YOUR_PROJECT_REF].supabase.co/auth/v1/callback
+  - http://localhost:3000/auth/callback (for local development)
+8. Copy the Client ID and Client Secret
+9. Go back to your Supabase dashboard
+10. Paste the Client ID and Client Secret in the Google provider settings
+11. Save the changes
+
+
 ## Local Installation
 
 ### macOS / Linux
@@ -118,8 +150,8 @@ CREATE TABLE users (
   preferred_model TEXT,
   premium BOOLEAN DEFAULT false,
   profile_image TEXT,
-  created_at TIMESTAMPTZ DEFAULT NOW()
-  last_active_at: TIMESTAMPTZ DEFAULT NOW()
+  created_at TIMESTAMPTZ DEFAULT NOW(),
+  last_active_at TIMESTAMPTZ DEFAULT NOW()
 );
 
 -- Chats table
diff --git a/README.md b/README.md
index 237a7949a..ef0b01691 100644
--- a/README.md
+++ b/README.md
@@ -39,4 +39,4 @@ Apache License 2.0
 
 ## Notes
 
-This is a beta release. The codebase is evolving and may change.
+This is a beta release. The codebase is evolving and may change.
\ No newline at end of file
diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts
index 39822f39d..2bf95f6f0 100644
--- a/app/api/chat/route.ts
+++ b/app/api/chat/route.ts
@@ -5,6 +5,8 @@ import { sanitizeUserInput } from "@/lib/sanitize"
 import { validateUserIdentity } from "@/lib/server/api"
 import { Attachment } from "@ai-sdk/ui-utils"
 import { Message as MessageAISDK, streamText } from "ai"
+import { createOpenRouter } from "@openrouter/ai-sdk-provider"
+
 
 // Maximum allowed duration for streaming (in seconds)
 export const maxDuration = 30
@@ -79,8 +81,22 @@ export async function POST(req: Request) {
       }
     }
 
+    const modelConfig = MODELS.find((m) => m.id === model)
+    if (!modelConfig){
+      throw new Error(`Model ${model} not found`)
+    }
+    let modelInstance
+    if (modelConfig.provider === 'openrouter') {
+      const openRouter = createOpenRouter({
+        apiKey: process.env.OPENROUTER_API_KEY,
+      })
+      modelInstance = openRouter.chat(modelConfig.api_sdk) // this is a special case for openrouter. Normal openrouter models are not supported.
+    } else {
+      modelInstance = modelConfig.api_sdk
+    }
+
     const result = streamText({
-      model: MODELS.find((m) => m.id === model)?.api_sdk!,
+      model: modelInstance,
       system: effectiveSystemPrompt,
       messages,
       // When the response finishes, insert the assistant messages to supabase
diff --git a/app/api/rate-limits/route.ts b/app/api/rate-limits/route.ts
index 036c83b75..122e0cc88 100644
--- a/app/api/rate-limits/route.ts
+++ b/app/api/rate-limits/route.ts
@@ -4,36 +4,42 @@ import {
 } from "@/lib/config"
 import { validateUserIdentity } from "../../../lib/server/api"
 
+
 export async function GET(req: Request) {
-  const { searchParams } = new URL(req.url)
-  const userId = searchParams.get("userId")
-  const isAuthenticated = searchParams.get("isAuthenticated") === "true"
-  if (!userId) {
-    return new Response(JSON.stringify({ error: "Missing userId" }), {
-      status: 400,
-    })
-  }
-  const supabase = await validateUserIdentity(userId, isAuthenticated)
-
-  const { data, error } = await supabase
-    .from("users")
-    .select("daily_message_count")
-    .eq("id", userId)
-    .maybeSingle()
-
-  if (error || !data) {
-    return new Response(JSON.stringify({ error: error?.message }), {
-      status: 500,
+  
+    const { searchParams } = new URL(req.url)
+    const userId = searchParams.get("userId")
+    const isAuthenticated = searchParams.get("isAuthenticated") === "true"
+    
+    if (!userId) {
+      return new Response(JSON.stringify({error: "Missing userId"}), {
+        status: 400,
+      })
+    }
+
+    const supabase = await validateUserIdentity(userId, isAuthenticated)
+
+    const { data, error } = await supabase
+      .from("users")
+      .select("daily_message_count")
+      .eq("id", userId)
+      .maybeSingle()
+
+    if (error || !data){
+      return new Response(JSON.stringify({ error: error?.message }), {
+        status: 500,
+      })
+    }
+
+    const dailyLimit = isAuthenticated
+      ? AUTH_DAILY_MESSAGE_LIMIT
+      : NON_AUTH_DAILY_MESSAGE_LIMIT
+    const dailyCount = data.daily_message_count || 0
+    const remaining = dailyLimit - dailyCount
+
+    return new Response(JSON.stringify({ dailyCount, dailyLimit, remaining }), {
+      status: 200,
     })
-  }
-
-  const dailyLimit = isAuthenticated
-    ? AUTH_DAILY_MESSAGE_LIMIT
-    : NON_AUTH_DAILY_MESSAGE_LIMIT
-  const dailyCount = data.daily_message_count || 0
-  const remaining = dailyLimit - dailyCount
-
-  return new Response(JSON.stringify({ dailyCount, dailyLimit, remaining }), {
-    status: 200,
-  })
-}
+  } 
+  
+
diff --git a/components/icons/openrouter.tsx b/components/icons/openrouter.tsx
new file mode 100644
index 000000000..42ea0c6e8
--- /dev/null
+++ b/components/icons/openrouter.tsx
@@ -0,0 +1,20 @@
+import * as React from "react"
+import type { SVGProps } from "react"
+
+const Icon = (props: SVGProps<SVGSVGElement>) => (
+    <svg fill="none" 
+        fillRule="evenodd"
+        style={{ flex: "none", lineHeight: "1" }}
+         height={64} 
+         width={64}
+        viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" {...props}>
+
+        <path fill="#000"
+            fillRule="evenodd"          
+            d="M42.01 4.893l18.05 10.263v0.218l-18.235 10.153 0.043-5.293-2.053-0.075c-2.648-0.07-4.028 0.005-5.67 0.275-2.66 0.438-5.095 1.443-7.868 3.38l-5.415 3.743c-0.71 0.488-1.238 0.84-1.7 1.138l-1.288 0.805-0.993 0.585 0.963 0.575 1.325 0.845c1.19 0.785 2.925 1.99 6.753 4.665 2.775 1.938 5.208 2.943 7.868 3.38l0.75 0.113c1.735 0.228 3.438 0.235 7.063 0.083l0.055-5.398 18.05 10.263v0.218L41.473 55l0.035-4.655-1.588 0.055c-3.465 0.105-5.343 0.005-7.845-0.405-4.235-0.7-8.15-2.315-12.203-5.148l-5.395-3.75a54.993 54.993 0 01-1.888-1.245l-1.168-0.7a139.818 139.818 0 01-1.9-1.075C7.27 36.825 1.408 35.29 0 35.29V24.72l0.35 0.01c1.41-0.018 7.275-1.555 9.523-2.81l2.54-1.45 1.095-0.685c1.07-0.7 2.68-1.815 6.715-4.633 4.053-2.833 7.965-4.45 12.203-5.148 2.88-0.475 4.935-0.533 9.535-0.345l0.05-4.768z"
+            clipRule="evenodd">
+        </path>
+    </svg>
+)
+
+export default Icon
diff --git a/lib/config.ts b/lib/config.ts
index 11a74fc30..81385971a 100644
--- a/lib/config.ts
+++ b/lib/config.ts
@@ -4,6 +4,7 @@ import Gemini from "@/components/icons/gemini"
 import Grok from "@/components/icons/grok"
 import Mistral from "@/components/icons/mistral"
 import OpenAI from "@/components/icons/openai"
+import OpenRouter from "@/components/icons/openrouter"
 import { mistral } from "@ai-sdk/mistral"
 import { openai } from "@ai-sdk/openai"
 import {
@@ -41,19 +42,7 @@ export type Model = {
 }
 
 export const MODELS_NOT_AVAILABLE = [
-  {
-    id: "deepseek-r1",
-    name: "DeepSeek R1",
-    provider: "deepseek",
-    available: false,
-    api_sdk: false,
-    features: [
-      {
-        id: "file-upload",
-        enabled: false,
-      },
-    ],
-  },
+  
   {
     id: "gemini-1.5-pro",
     name: "Gemini 1.5 Pro",
@@ -205,8 +194,22 @@ export const MODELS = [
       },
     ],
     api_sdk: mistral("mistral-large-latest"),
+    icon: Mistral,
+    description: "Fine-tuned for chat. A lighter, faster option for everyday use.",
+  },
+  {
+    id: "deepseek-r1",
+    name: "DeepSeek R1",
+    provider: "openrouter",
+    features: [
+      {
+        id: "file-upload",
+        enabled: true,
+      },
+    ],
+    api_sdk: "deepseek/deepseek-r1:free", // this is a special case for openrouter
     description:
-      "Fine-tuned for chat. A lighter, faster option for everyday use.",
+      "A reasoning-first model trained with reinforcement learning, built for math, code, and complex problem solving",
   },
 ] as Model[]
 
@@ -253,6 +256,11 @@ const PROVIDERS_NOT_AVAILABLE = [
 ] as Provider[]
 
 export const PROVIDERS = [
+  {
+    id: "openrouter",
+    name: "OpenRouter",
+    icon: OpenRouter,
+  },
   {
     id: "openai",
     name: "OpenAI",
@@ -410,7 +418,7 @@ export const SUGGESTIONS = [
     highlight: "Explain",
     prompt: `Explain`,
     items: [
-      "Explain quantum physics like I’m 10",
+      "Explain quantum physics like I'm 10",
       "Explain stoicism in simple terms",
       "Explain how a neural network works",
       "Explain the difference between AI and AGI",
diff --git a/package.json b/package.json
index 0f4649156..40d44d60d 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "chat-ai",
+  "name": "zola",
   "version": "0.1.0",
   "private": true,
   "scripts": {
@@ -11,6 +11,7 @@
   "dependencies": {
     "@ai-sdk/mistral": "^1.2.0",
     "@ai-sdk/openai": "^1.3.12",
+    "@openrouter/ai-sdk-provider": "^0.4.5",
     "@phosphor-icons/react": "^2.1.7",
     "@radix-ui/react-alert-dialog": "^1.1.6",
     "@radix-ui/react-avatar": "^1.1.3",
diff --git a/supabase/seed.sql b/supabase/seed.sql
new file mode 100644
index 000000000..775a0b65c
--- /dev/null
+++ b/supabase/seed.sql
@@ -0,0 +1,199 @@
+-- Insert initial agents
+INSERT INTO public.agents (
+  id,
+  name,
+  slug,
+  description,
+  avatar_url,
+  system_prompt,
+  model_preference,
+  is_public,
+  remixable,
+  tools_enabled,
+  example_inputs,
+  tags,
+  category,
+  creator_id,
+  created_at,
+  updated_at
+) VALUES
+  (
+    'tweet-vibe-checker',
+    'Tweet Vibe Checker',
+    'tweet-vibe-checker',
+    'Analyzes the tone and potential impact of your tweets before posting.',
+    '/agents/tweet-vibe-checker.png',
+    'You are a tweet analyzer who helps users craft and analyze tweets. You understand Twitter culture, engagement patterns, and how to make tweets more effective while staying true to the user''s voice. Analyze tone, potential engagement, and suggest improvements when asked.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Is this tweet too aggressive?', 'How can I make this tweet more engaging?', 'Check the tone of this thread'],
+    ARRAY['social', 'writing', 'analysis'],
+    'social',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'clear-ux-copywriter',
+    'Clear UX Copywriter',
+    'clear-ux-copywriter',
+    'Crafts clear, user-friendly copy for interfaces and product experiences.',
+    '/agents/clear-ux-copywriter.png',
+    'You are a UX writing specialist who helps create clear, concise, and user-friendly copy for digital interfaces. Focus on clarity, consistency, and appropriate tone while maintaining brand voice. Consider context and user needs in all suggestions.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Write error message for failed payment', 'Improve this onboarding flow copy', 'Make this button text clearer'],
+    ARRAY['ux', 'writing', 'product'],
+    'product',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    '0-to-1-advisor',
+    '0 to 1 Advisor',
+    '0-to-1-advisor',
+    'Helps validate and refine early-stage product ideas and strategies.',
+    '/agents/0-to-1-advisor.png',
+    'You are a product strategy advisor specializing in early-stage ventures and 0 to 1 product development. Help users validate ideas, identify potential pitfalls, and develop actionable strategies. Draw from startup methodology and product development best practices.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Validate my product idea', 'What should I build first?', 'How to find early adopters?'],
+    ARRAY['startup', 'product', 'strategy'],
+    'business',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'pull-check',
+    'Pull Check',
+    'pull-check',
+    'Reviews pull requests for code quality, security, and best practices.',
+    '/agents/pull-check.png',
+    'You are a code review specialist who analyzes pull requests for quality, security, and adherence to best practices. Provide constructive feedback while considering maintainability, performance, and potential edge cases.',
+    'gpt-4',
+    true,
+    false,
+    true,
+    ARRAY['Review this PR for security issues', 'Check code style and best practices', 'Suggest performance improvements'],
+    ARRAY['dev', 'code', 'review'],
+    'dev',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'blog-draft',
+    'Blog Draft',
+    'blog-draft',
+    'Helps outline and draft engaging blog posts and articles.',
+    '/agents/blog-draft.png',
+    'You are a blog writing assistant who helps users create engaging and well-structured content. Help with outlines, drafts, and revisions while maintaining the user''s voice and style. Consider SEO best practices and reader engagement.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Create an outline for my post', 'Help me write an intro', 'Review my draft for clarity'],
+    ARRAY['writing', 'content', 'blog'],
+    'content',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'inbox-fix',
+    'Inbox Fix',
+    'inbox-fix',
+    'Helps compose and improve email responses for better communication.',
+    '/agents/inbox-fix.png',
+    'You are an email communication specialist who helps users craft effective and appropriate email responses. Consider tone, clarity, and professionalism while maintaining the user''s voice. Help with both business and personal communication.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Make this email more professional', 'Help me say no politely', 'Draft a follow-up email'],
+    ARRAY['writing', 'communication', 'email'],
+    'communication',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'name-vibe-check',
+    'Name Vibe Check',
+    'name-vibe-check',
+    'Analyzes and suggests names for products, features, or companies.',
+    '/agents/name-vibe-check.png',
+    'You are a naming specialist who helps evaluate and generate names for products, features, and companies. Consider memorability, domain availability, and brand fit. Provide analysis of existing names and creative suggestions for new ones.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Suggest names for my app', 'Is this name too similar to competitors?', 'Check if this name works internationally'],
+    ARRAY['branding', 'product', 'naming'],
+    'branding',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'tiny-essay',
+    'Tiny Essay',
+    'tiny-essay',
+    'Helps write concise, thoughtful essays on any topic.',
+    '/agents/tiny-essay.png',
+    'You are a writing assistant specializing in concise essays. Help users express complex ideas clearly and engagingly in a limited space. Focus on clarity, structure, and impactful conclusions.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Write a tiny essay about creativity', 'Help me structure my thoughts', 'Make this explanation clearer'],
+    ARRAY['writing', 'essay', 'content'],
+    'content',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'solene',
+    'Solene',
+    'solene',
+    'Your thoughtful companion for deep conversations and reflection.',
+    '/agents/solene.png',
+    'You are Solene, a thoughtful and empathetic conversation partner. Help users explore ideas, reflect on experiences, and gain new perspectives. Engage in meaningful dialogue while maintaining a supportive and non-judgmental presence.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Let''s talk about personal growth', 'Help me reflect on this situation', 'Explore this idea with me'],
+    ARRAY['companion', 'reflection', 'conversation'],
+    'personal',
+    'zola',
+    NOW(),
+    NOW()
+  ),
+  (
+    'eloi',
+    'Eloi',
+    'eloi',
+    'Your creative partner for exploring ideas and possibilities.',
+    '/agents/eloi.png',
+    'You are Eloi, a creative thinking partner who helps users explore and develop ideas. Encourage imaginative thinking while providing practical insights. Help users see new possibilities and connections in their creative work.',
+    'gpt-4',
+    true,
+    false,
+    false,
+    ARRAY['Brainstorm creative solutions', 'Help me think differently about this', 'Explore this concept further'],
+    ARRAY['creativity', 'ideation', 'innovation'],
+    'creative',
+    'zola',
+    NOW(),
+    NOW()
+  ); 
\ No newline at end of file


Reviews:
user: login: ibelick
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-15T14:46:48Z
user: login: ibelick
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-15T15:41:16Z
user: login: ibelick
state: APPROVED
author_association: OWNER
submitted_at: 2025-04-21T20:06:29Z

Review comments:
diff_hunk: @@ -14,7 +14,7 @@ let dbInitPromise: Promise<void> | null = null
 let stores: Record<string, any> = {}
 
 const isClient = typeof window !== "undefined"
-const DB_NAME = "zola-db"
path: lib/chat-store/persist.ts
user: login: ibelick
body: keep `zola-db` please
created_at: 2025-04-15T14:39:25Z
author_association: OWNER
diff_hunk: @@ -1,4 +1,4 @@
-# Zola
path: README.md
user: login: ibelick
body: keep Zola
created_at: 2025-04-15T14:39:40Z
author_association: OWNER
diff_hunk: @@ -22,8 +23,8 @@ import {
   Sparkle,
 } from "@phosphor-icons/react/dist/ssr"
 
-export const NON_AUTH_DAILY_MESSAGE_LIMIT = 5
-export const AUTH_DAILY_MESSAGE_LIMIT = 100
+export const NON_AUTH_DAILY_MESSAGE_LIMIT = 500
path: lib/config.ts
user: login: ibelick
body: remove
created_at: 2025-04-15T14:44:33Z
author_association: OWNER
diff_hunk: @@ -22,8 +23,8 @@ import {
   Sparkle,
 } from "@phosphor-icons/react/dist/ssr"
 
-export const NON_AUTH_DAILY_MESSAGE_LIMIT = 5
-export const AUTH_DAILY_MESSAGE_LIMIT = 100
+export const NON_AUTH_DAILY_MESSAGE_LIMIT = 500
+export const AUTH_DAILY_MESSAGE_LIMIT = 1000
path: lib/config.ts
user: login: ibelick
body: same
created_at: 2025-04-15T14:44:38Z
author_association: OWNER
diff_hunk: @@ -273,12 +280,13 @@ export const PROVIDERS_OPTIONS = [
   ...PROVIDERS_NOT_AVAILABLE,
 ] as Provider[]
 
-export const MODEL_DEFAULT = "pixtral-large-latest"
+// export const MODEL_DEFAULT = "pixtral-large-latest"
+export const MODEL_DEFAULT = "deepseek-r1"
path: lib/config.ts
user: login: ibelick
body: remove 
created_at: 2025-04-15T14:45:54Z
author_association: OWNER
diff_hunk: @@ -273,12 +280,13 @@ export const PROVIDERS_OPTIONS = [
   ...PROVIDERS_NOT_AVAILABLE,
 ] as Provider[]
 
-export const MODEL_DEFAULT = "pixtral-large-latest"
+// export const MODEL_DEFAULT = "pixtral-large-latest"
+export const MODEL_DEFAULT = "deepseek-r1"
 
-export const APP_NAME = "Zola"
+export const APP_NAME = "Zola Chat"
path: lib/config.ts
user: login: ibelick
body: remove
created_at: 2025-04-15T14:45:57Z
author_association: OWNER
diff_hunk: @@ -273,12 +280,13 @@ export const PROVIDERS_OPTIONS = [
   ...PROVIDERS_NOT_AVAILABLE,
 ] as Provider[]
 
-export const MODEL_DEFAULT = "pixtral-large-latest"
+// export const MODEL_DEFAULT = "pixtral-large-latest"
+export const MODEL_DEFAULT = "deepseek-r1"
 
-export const APP_NAME = "Zola"
+export const APP_NAME = "Zola Chat"
 export const APP_DOMAIN = "https://zola.chat"
 export const APP_DESCRIPTION =
-  "Zola is a free, open-source AI chat app with multi-model support."
+  "Zola Chat is a free, open-source AI chat app with multi-model support."
path: lib/config.ts
user: login: ibelick
body: same
created_at: 2025-04-15T14:46:03Z
author_association: OWNER
diff_hunk: @@ -1,5 +1,5 @@
 {
-  "name": "chat-ai",
+  "name": "zola-chat",
path: package.json
user: login: ibelick
body: nice catch, can you update it to "zola"? thank you
created_at: 2025-04-15T14:46:29Z
author_association: OWNER
diff_hunk: @@ -36,9 +36,23 @@ yarn-error.log*
 .env.test.local
 .env.production.local
 
+
 # vercel
 .vercel
 
 # typescript
 *.tsbuildinfo
 next-env.d.ts
+
+# env
+.env
+
+# bun
+bun.lockb
+bun.lock
+
+# vscode
+.vscode/
+
+# .idea
path: .gitignore
user: login: ibelick
body: remove
created_at: 2025-04-15T15:31:29Z
author_association: OWNER
diff_hunk: @@ -5,33 +5,33 @@ import {
 import { validateUserIdentity } from "../../../lib/server/api"
 
 export async function GET(req: Request) {
-  const { searchParams } = new URL(req.url)
-  const userId = searchParams.get("userId")
-  const isAuthenticated = searchParams.get("isAuthenticated") === "true"
-  if (!userId) {
+    const { searchParams } = new URL(req.url)
path: app/api/rate-limits/route.ts
user: login: ibelick
body: remove all changes here 
created_at: 2025-04-15T15:31:36Z
author_association: OWNER
diff_hunk: @@ -111,11 +111,11 @@ export function Chat() {
         errorMsg = parsed.error || errorMsg
path: app/components/chat/chat.tsx
user: login: ibelick
body: remove changes here too
created_at: 2025-04-15T15:31:37Z
author_association: OWNER
diff_hunk: @@ -205,6 +194,19 @@ export const MODELS = [
       },
     ],
     api_sdk: mistral("mistral-large-latest"),
+    icon: Mistral,
path: lib/config.ts
user: login: ibelick
body: keep `mistral-large-latest` description 
```ts
    description:
      "Fine-tuned for chat. A lighter, faster option for everyday use.",
```
created_at: 2025-04-15T15:40:27Z
author_association: OWNER
diff_hunk: @@ -205,6 +194,19 @@ export const MODELS = [
       },
     ],
     api_sdk: mistral("mistral-large-latest"),
+    icon: Mistral,
+  },
+  {
+    id: "deepseek-r1",
+    name: "DeepSeek R1",
+    provider: "openrouter",
+    features: [
+      {
+        id: "file-upload",
+        enabled: true,
+      },
+    ],
+    api_sdk: "deepseek/deepseek-r1:free", // this is a special case for openrouter
     description:
path: lib/config.ts
user: login: ibelick
body: add description for `deepseek-r1`, like: `A reasoning-first model trained with reinforcement learning, built for math, code, and complex problem solving.`

created_at: 2025-04-15T15:41:07Z
author_association: OWNER

PR comments:
user: login: vercel[bot]
created_at: 2025-04-15T13:13:05Z
body: @yguo is attempting to deploy a commit to the **julienthibeaut's projects** Team on [Vercel](https://vercel.com).

A member of the Team first needs to [authorize it](https://vercel.com/git/authorize?team=julienthibeaut's%20projects&type=github&job=%7B%22headInfo%22%3A%7B%22sha%22%3A%2216088d5d02c1af8304d3be6780f3a6866a44af02%22%7D%2C%22id%22%3A%22QmWip6xkBHo6uJnURZvXHTkJAz4hxzRpA5sMCugFetNZbG%22%2C%22org%22%3A%22ibelick%22%2C%22prId%22%3A57%2C%22repo%22%3A%22zola%22%7D).


author_association: NONE
user: login: ibelick
created_at: 2025-04-15T14:52:10Z
body: @yguo thank you for the PR! can you update your branch with `main`? also, check my comments
author_association: OWNER
user: login: yguo
created_at: 2025-04-15T15:07:43Z
body: Hi @ibelick Thanks for your review. I address the review feedback and push it into the feat branch. and also update my branch with main. Cheers
author_association: CONTRIBUTOR
user: login: ibelick
created_at: 2025-04-15T15:44:26Z
body: @yguo just added a few new comments, then we're good, thank you!
author_association: OWNER
user: login: yguo
created_at: 2025-04-15T16:27:08Z
body: the review feedback is addressed. Thanks 
author_association: CONTRIBUTOR
user: login: vercel[bot]
created_at: 2025-04-15T19:16:25Z
body: [vc]: #DovQn3RfIdNKgifWbpQZ4Fif2Zyzit/PpNgxewwXyhw=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJ6b2xhIiwicm9vdERpcmVjdG9yeSI6bnVsbCwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2p1bGllbnRoaWJlYXV0cy1wcm9qZWN0cy96b2xhLzVoYjNja2JONkdDeG9NdGJSQjF2a3ZQZWJ2QXYiLCJwcmV2aWV3VXJsIjoiem9sYS1naXQtZm9yay15Z3VvLWZlYXQtb3BlbnJvdS1iYzAzNTAtanVsaWVudGhpYmVhdXRzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiem9sYS1naXQtZm9yay15Z3VvLWZlYXQtb3BlbnJvdS1iYzAzNTAtanVsaWVudGhpYmVhdXRzLXByb2plY3RzLnZlcmNlbC5hcHAifX1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **zola** | ✅ Ready ([Inspect](https://vercel.com/julienthibeauts-projects/zola/5hb3ckbN6GCxoMtbRB1vkvPebvAv)) | [Visit Preview](https://zola-git-fork-yguo-feat-openrou-bc0350-julienthibeauts-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/zola-git-fork-yguo-feat-openrou-bc0350-julienthibeauts-projects.vercel.app?via=pr-comment-feedback-link) | Apr 15, 2025 7:19pm |


author_association: NONE