diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 1cf9930..08389df 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,39 +1,45 @@ import { NextRequest, NextResponse } from "next/server"; +<<<<<<< HEAD const HF_MODELS: Record = { "yuuki-v0.1": "YuuKi-OS/Yuuki-v0.1", "yuuki-3.7": "YuuKi-OS/Yuuki-3.7", "yuuki-best": "YuuKi-OS/Yuuki-best", }; +======= +const YUUKI_API_URL = "https://opceanai-yuuki-api.hf.space/generate"; +>>>>>>> fe68380 (uwu) -const YUUKI_API_MODELS: Record = { - "yuuki-v0.1": "yuuki-v0.1", - "yuuki-3.7": "yuuki-3.7", - "yuuki-best": "yuuki-best", -}; +const VALID_MODELS = ["yuuki-best", "yuuki-3.7", "yuuki-v0.1"]; /** - * Calls the Yuuki API (yuuki-api.vercel.app) with a yk- token. - * This is an OpenAI-compatible endpoint. + * Calls the Yuuki API hosted on HuggingFace Spaces. + * Open platform — no token required. */ -async function callYuukiApi( - token: string, - model: string, - messages: { role: string; content: string }[] +async function callYuukiAPI( + messages: { role: string; content: string }[], + model: string ) { - const modelId = YUUKI_API_MODELS[model] || "yuuki-best"; + // Build a prompt from the message history + const prompt = messages + .map((m) => { + if (m.role === "system") return `System: ${m.content}`; + if (m.role === "user") return `User: ${m.content}`; + if (m.role === "assistant") return `Assistant: ${m.content}`; + return m.content; + }) + .join("\n") + "\nAssistant:"; - const response = await fetch("https://yuuki-api.vercel.app/api/chat", { + const response = await fetch(YUUKI_API_URL, { method: "POST", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${token}`, }, body: JSON.stringify({ - model: modelId, - messages, - max_tokens: 1024, + prompt, + max_new_tokens: 512, temperature: 0.7, + model, }), }); @@ -45,11 +51,8 @@ async function callYuukiApi( } const data = await response.json(); - const content = - data.choices?.[0]?.message?.content || data.content || "No response"; - return { content, id: data.id || `chatcmpl-${Date.now()}`, model: modelId }; -} +<<<<<<< HEAD /** * Calls HuggingFace Inference API via the new router.huggingface.co endpoint. * Uses the OpenAI-compatible chat completions format. @@ -87,6 +90,31 @@ async function callHuggingFace( const data = await response.json(); const content = data.choices?.[0]?.message?.content?.trim() || "No response generated."; +======= + // Handle various response formats from the HF Space + let generatedText = ""; + + if (typeof data === "string") { + generatedText = data.trim(); + } else if (data?.generated_text) { + generatedText = data.generated_text.trim(); + } else if (data?.response) { + generatedText = data.response.trim(); + } else if (data?.output) { + generatedText = data.output.trim(); + } else if (Array.isArray(data) && data[0]?.generated_text) { + generatedText = data[0].generated_text.trim(); + } else { + generatedText = JSON.stringify(data); + } + + // Clean up conversational artifacts + const cutoffs = ["User:", "System:", "\nUser", "\nSystem"]; + for (const cutoff of cutoffs) { + const idx = generatedText.indexOf(cutoff); + if (idx > 0) generatedText = generatedText.substring(0, idx).trim(); + } +>>>>>>> fe68380 (uwu) return { content, @@ -98,7 +126,7 @@ async function callHuggingFace( export async function POST(req: NextRequest) { try { const body = await req.json(); - const { messages, model, token, tokenSource } = body; + const { messages, model } = body; if (!messages || !Array.isArray(messages)) { return NextResponse.json( @@ -108,47 +136,11 @@ export async function POST(req: NextRequest) { } const modelKey = model || "yuuki-best"; - if (!HF_MODELS[modelKey]) { + if (!VALID_MODELS.includes(modelKey)) { return NextResponse.json({ error: "Invalid model" }, { status: 400 }); } - let result; - - if (tokenSource === "demo") { - // Demo mode: use server-side HF_DEMO_TOKEN directly against HuggingFace - const demoToken = process.env.HF_DEMO_TOKEN; - if (!demoToken) { - return NextResponse.json( - { error: "Demo token not configured on server" }, - { status: 500 } - ); - } - result = await callHuggingFace(demoToken, modelKey, messages); - } else if (tokenSource === "yuuki-api") { - // Yuuki API: yk- tokens go to yuuki-api.vercel.app - if (!token) { - return NextResponse.json( - { error: "No API token provided" }, - { status: 401 } - ); - } - result = await callYuukiApi(token, modelKey, messages); - } else if (tokenSource === "huggingface") { - // HuggingFace: hf_ tokens go directly to HF Inference API - if (!token) { - return NextResponse.json( - { error: "No API token provided" }, - { status: 401 } - ); - } - result = await callHuggingFace(token, modelKey, messages); - } else { - return NextResponse.json( - { error: "Invalid token source" }, - { status: 400 } - ); - } - + const result = await callYuukiAPI(messages, modelKey); return NextResponse.json(result); } catch (error) { const message = error instanceof Error ? error.message : "Unknown error"; diff --git a/app/page.tsx b/app/page.tsx index 244a3f7..21c4b13 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,15 +1,7 @@ "use client"; -import { useAuth } from "@/lib/auth-context"; -import { TokenScreen } from "@/components/token-screen"; import { ChatWindow } from "@/components/chat-window"; export default function Home() { - const { isAuthenticated } = useAuth(); - - if (!isAuthenticated) { - return ; - } - return ; } diff --git a/components/chat-window.tsx b/components/chat-window.tsx index 37bf7ef..7414234 100644 --- a/components/chat-window.tsx +++ b/components/chat-window.tsx @@ -1,7 +1,6 @@ "use client"; import React, { useState, useRef, useEffect, useCallback } from "react"; -import { useAuth } from "@/lib/auth-context"; import { useYuukiTheme } from "@/lib/theme-context"; import { ChatMessage, type ChatMsg } from "./chat-message"; import { ModelSelector } from "./model-selector"; @@ -9,7 +8,6 @@ import { ThemePanel } from "./theme-panel"; import { Send, Palette, - LogOut, Globe, Youtube, Loader2, @@ -28,7 +26,6 @@ interface Conversation { } export function ChatWindow() { - const { token, tokenSource, logout } = useAuth(); const { accentColor } = useYuukiTheme(); const [conversations, setConversations] = useState([ @@ -177,8 +174,6 @@ export function ChatWindow() { body: JSON.stringify({ messages: newMessages.map((m) => ({ role: m.role, content: m.content })), model, - token: tokenSource === "demo" ? null : token, - tokenSource, }), }); @@ -316,14 +311,7 @@ export function ChatWindow() { Theme - + @@ -341,11 +329,7 @@ export function ChatWindow() { - {tokenSource === "demo" - ? "demo" - : tokenSource === "yuuki-api" - ? "yk-api" - : "hf"} + open diff --git a/components/token-screen.tsx b/components/token-screen.tsx deleted file mode 100644 index 7223fc1..0000000 --- a/components/token-screen.tsx +++ /dev/null @@ -1,178 +0,0 @@ -"use client"; - -import React, { useState } from "react"; -import { MacOSWindow } from "./macos-window"; -import { useAuth, type TokenSource } from "@/lib/auth-context"; -import { Key, ExternalLink, Sparkles, Eye, EyeOff, ArrowRight } from "lucide-react"; - -export function TokenScreen() { - const { setAuth } = useAuth(); - const [step, setStep] = useState<"choose" | "input">("choose"); - const [selectedSource, setSelectedSource] = useState(null); - const [tokenValue, setTokenValue] = useState(""); - const [showToken, setShowToken] = useState(false); - const [error, setError] = useState(""); - const [loading, setLoading] = useState(false); - - const handleSourceSelect = (source: TokenSource) => { - if (source === "demo") { - setLoading(true); - // Demo mode: token is managed server-side via HF_DEMO_TOKEN env var - setAuth("__demo__", "demo"); - return; - } - setSelectedSource(source); - setStep("input"); - }; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (!tokenValue.trim()) { - setError("Please enter your API token"); - return; - } - if (!selectedSource) return; - setAuth(tokenValue.trim(), selectedSource); - }; - - return ( -
- {/* Background pattern */} -
-
-
-
- -
- {step === "choose" ? ( - -
- {/* Logo and title */} -
-
- Y -
-
-

- Welcome to Yuuki Chat -

-

- Choose how to authenticate to start chatting -

-
-
- - {/* Two big buttons */} -
- - - -
- - {/* Small demo button */} - -
-
- ) : ( - { setStep("choose"); setError(""); setTokenValue(""); }} - > -
-
-
- {selectedSource === "yuuki-api" ? ( - - ) : ( - - )} -
-
-

- {selectedSource === "yuuki-api" ? "Enter Yuuki API Token" : "Enter Hugging Face Token"} -

-

- {selectedSource === "yuuki-api" - ? "Get your token from yuuki-api.vercel.app" - : "Get your token from huggingface.co/settings/tokens"} -

-
-
- -
-
- { setTokenValue(e.target.value); setError(""); }} - placeholder={selectedSource === "yuuki-api" ? "yk-xxxxxxxxxx" : "hf_xxxxxxxxxx"} - className="w-full rounded-lg border border-border bg-background px-4 py-3 pr-10 text-sm text-foreground font-mono placeholder:text-muted-foreground/50 focus:outline-none focus:ring-2 focus:ring-ring/20 focus:border-foreground/30" - autoFocus - /> - -
- {error &&

{error}

} -
- -
- - -
-
-
- )} -
-
- ); -} diff --git a/lib/auth-context.tsx b/lib/auth-context.tsx index b3a5ff2..2d63715 100644 --- a/lib/auth-context.tsx +++ b/lib/auth-context.tsx @@ -1,89 +1,22 @@ "use client"; -import React, { - createContext, - useContext, - useState, - useCallback, - useEffect, -} from "react"; - -export type TokenSource = "yuuki-api" | "huggingface" | "demo"; +import React, { createContext, useContext } from "react"; interface AuthContextValue { - token: string | null; - tokenSource: TokenSource | null; - setAuth: (token: string, source: TokenSource) => void; logout: () => void; - isAuthenticated: boolean; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { - const [token, setToken] = useState(null); - const [tokenSource, setTokenSource] = useState(null); - const [mounted, setMounted] = useState(false); - - useEffect(() => { - const stored = localStorage.getItem("yuuki-token"); - const storedSource = localStorage.getItem( - "yuuki-token-source" - ) as TokenSource | null; - if (stored && storedSource) { - setToken(stored); - setTokenSource(storedSource); - } - setMounted(true); - }, []); - - const setAuth = useCallback((t: string, source: TokenSource) => { - setToken(t); - setTokenSource(source); - if (source === "demo") { - // Don't persist demo sessions for security - localStorage.setItem("yuuki-token", "__demo__"); - localStorage.setItem("yuuki-token-source", "demo"); - } else { - localStorage.setItem("yuuki-token", t); - localStorage.setItem("yuuki-token-source", source); - } - }, []); - - const logout = useCallback(() => { - setToken(null); - setTokenSource(null); - localStorage.removeItem("yuuki-token"); - localStorage.removeItem("yuuki-token-source"); - }, []); - - // Prevent flash of token screen before localStorage is read - if (!mounted) { - return ( - - {null} - - ); - } + const logout = () => { + // No-op since there's no authentication needed. + // Kept for compatibility with components that reference it. + window.location.reload(); + }; return ( - + {children} ); diff --git a/public/apple-icon.png b/public/apple-icon.png deleted file mode 100644 index 5ff82df..0000000 --- a/public/apple-icon.png +++ /dev/null @@ -1 +0,0 @@ -iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAACXBIWXMAAAAAAAAAAQCEeRdzAAAJ9ElEQVR4nO3deYhNfRwG8Gvftxm77NmiJMYepYTIkkRS1j+QKIRkiRTKHkrKGhJisu8pW9m3CNllm0Fo7PN7fc9r9L5j7p1z7u97znPuzPOtz59zzzO/88yde+9ZbiQSiRiiPAQegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngAIk3wAESa4AGINMEDEGmCByDSBA9ApAkegEgTPACRJngA+qVIkSKmbdu2pnPnzqZTp06BSklJMQ0bNjRlypSBr4MCeAD6pUqVKiY9Pd0gJjMz03z69Mk8fvzYHD9+3MybN8907NjR+SNDr0sc4AHol8qVK5sXL15ACh1tbty4YaZMmWKSk5Ph6+MBPABFwlnorHn+/LlT7GLFisHXyQV4AIqEu9BZc/XqVed1PnqtcgEPQJHEKLTM169fzZgxY+DrFQM8AEUSp9BZM3fuXPiaRQEPQJHEK7TMnDlz4OuWA3gAiiRmoWXGjh0LX7ts4AEokriF/vbtm+nQoQN8/f4DHoB+kc96X716he5nXHP9+nVTsmRJ+Br+FtzGihYtamrVqmWqVasWl+rVq5ty5cr5njMpKcnZlttcOR14KFCggClbtqwpX758rkqXLm3q169v7t69az5+/GjevXvnu/fv35s3b96Yt2/fqpR61qxZ6CIHX2g5lLplyxbz/fv3uHbChw8fzKNHj0yLFi18zblnzx7z5csXV5kyMjLMiRMnTMGCBf/3GPKHd+nSpT/FiUVKdefOHdOkSRNToUIFU7FiRV9VqlTJ+WOrWbOmk11j0tLSnCeBfFVoIQsqH9DbzL1795xner8yet3Jly9f/qvQ8sz79OlT148hhZCiBbUfChcubFJTU70ufcwJyacewW9UnhkePHhg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 \ No newline at end of file diff --git a/public/icon-dark-32x32.png b/public/icon-dark-32x32.png deleted file mode 100644 index 9bbaddd..0000000 --- a/public/icon-dark-32x32.png +++ /dev/null @@ -1 +0,0 @@ -iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHeSURBVHgB7ZftcYJAEIZXJwVQgh1IKhAq0A7QCqIVABWAFUQrkFQAVgAdaAfQwWVfIswhh5/Ey488M6uct9y+t+ytSiQhhLDYPtly0T/5aW2TVPBEIF6Hex7cFa8nQOyB+ElJSnqwh/zyQfpwkIGcLwzSQwEBgjQyJM1oF/BGPbFYLJSfG4ZBpmnSZDKh0WjUdhA9gaUuGQcXu92udV9dhEVRlFahUiv7YF4e27ZNKmQfZCOO4zIjrQwcDodSZaV4Npu11HqeV8/zQmI+n9djFWmaCg7ayATukRnKO4a6audRFNFqtaJHybKszIq8e5AkScOvcQoQnJ9T7RyGIfm+T88GdxyHOKNK39YxxPOBiApOO63Xa3om+Gaz6fRX9gHLsigIgnq8XC5pu93SNeBzT/AScQHXdeviQTGhMKmjCDlQo9g4eGOtyheFLnO1D/DulecaArrmIPychwUA7EYlAHZL8KcF5HkuuDhbAgDXS6vjqQyPCL0GdreASoTcqKqF8C7XRpdBgIq7fg8cj8fySI7HY+KUNubQYPb7fee90+m02YJP/P8g+RMCCtJHAQFfpI8IRWjxRUx6eB8OBoOEL27/uusPn2Nn9Ygz4YnXESol8YTJhpb1m3/PLTnmN3V7EsupRFPpAAAAAElFTkSuQmCC \ No newline at end of file diff --git a/public/icon-light-32x32.png b/public/icon-light-32x32.png deleted file mode 100644 index 88e3657..0000000 --- a/public/icon-light-32x32.png +++ /dev/null @@ -1 +0,0 @@ -iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHLSURBVHgB7VfblYIwEJ19FEAJlkAJsQOtQEvQCuBvP6EDsAKhAu1ArUA7gA6yc9kNJ4HEN2Y/9p4zcEKG3JvJzBwgMiHYMraKTT7Zqt+1Q3IgGYDUZVGXPHohubJEkYceyJWJD7580ZlzGRpv9JMcAflBDQGSPOKdPMO7gE96ErIssz6v65oOhwNtt1s6nU5Wn6eU1CUcj0c5mUx677VJGARBYwo2tboP5vXxZrMhG3QfRGM8HtN+v+9HYDQaNSoV1ut1T20cx+28EELmed6ObVEJw1BWVWVEgo/K8HnXdwx1auccLkqShO4FkzdR0XcPsHDDz6gCkE+n09Z5sVhQFEX0KPlqtaKyLK2+vTLE+UCEAoe9EfII+Xw+d/pb+wBKZrlctmMcxWw2o0uAzy3kCs7S0pMOyYTEdCUhkxvJhjl9LeWLRO/wnK/vNE2lDRDgmoPw7jp3C9Bf7gqAXUP+sAA+U7nb7XoCMMdnbjwHgc04F5peA7tZgBKhNyq1EO56brgAAbZ1b/oeYLKmJFGqHFJjDg2m22R0FEXRa8HA/wfJnxBQkz/UEFCSPxS4CLqyFAew9n8k9UAed8MRv5A8JQcQkpyG/T0XOuE3m1c0JyJn8sIAAAAASUVORK5CYII= \ No newline at end of file diff --git a/public/placeholder-logo.png b/public/placeholder-logo.png deleted file mode 100644 index 9e6f3e4..0000000 --- a/public/placeholder-logo.png +++ /dev/null @@ -1 +0,0 @@ -iVBORw0KGgoAAAANSUhEUgAAAQAAAACQBAMAAAAVTaiiAAAAMFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABaPxwLAAAAD3RSTlMA3yCAQMAQ759gUDBwkK/koHcMAAABqElEQVR42u3YvUozURAG4Dcnuvoln3w/hSAWuxaCnQFFywRsBYM34IIXoChY2ETtBMGAjY2od2DuwMLCW/AqdP3HwvFEg6ybbUSYAX0fmOY0Oww77J4XREREREREREREREREXxOcX8Sw1BIZhiHXEHmIYKdfvDrs9Im3DDt/xLvCJ3y3CQyItwE7LhRJIhgaEZmHqZkzGCo14fWcwErhMQLcwiCsVKUCFOUGRgJJ4IUJrIw9wZsz3IMavDJ+qmIFHYunsDCeHOFVOVyBhV3pNNAjdzDgwkd0XCYxDBTfBz8yBRMxLAXWzfRvIWW0Dm2H0sS7UuMW2sL0hcQ11Pcg2L1BSvU5grJSHSm9NfwwLkZGEEFTYQgZx4PQVJUjfPBL98/QSZK3loqmn5AxtwpNromM3xH0zE4ix8wklIyK/EeXVvtUhQvbyVReXqXzQegkU7mnFWgoiLeWGxf9hYK3R11jbyJK17heXtUn3j0WpJauJb0JDIhXzzbQq5dXtd93qWHz34cqi15e1RJZR5djxdz6YCdGF7e/HYOIiIiIiIiIiIiIiOjzXgA1X7Msl1OuJQAAAABJRU5ErkJggg== \ No newline at end of file diff --git a/public/placeholder-user.jpg b/public/placeholder-user.jpg deleted file mode 100644 index c97e74f..0000000 --- a/public/placeholder-user.jpg +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/public/placeholder.jpg b/public/placeholder.jpg deleted file mode 100644 index 87c415d..0000000 --- a/public/placeholder.jpg +++ /dev/null @@ -1 +0,0 @@ -/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAAGgAwAEAAAAAQAAAAEAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/CABEIAAEAAQMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAADAgQBBQAGBwgJCgv/xADDEAABAwMCBAMEBgQHBgQIBnMBAgADEQQSIQUxEyIQBkFRMhRhcSMHgSCRQhWhUjOxJGIwFsFy0UOSNIII4VNAJWMXNfCTc6JQRLKD8SZUNmSUdMJg0oSjGHDiJ0U3ZbNVdaSVw4Xy00Z2gONHVma0CQoZGigpKjg5OkhJSldYWVpnaGlqd3h5eoaHiImKkJaXmJmaoKWmp6ipqrC1tre4ubrAxMXGx8jJytDU1dbX2Nna4OTl5ufo6erz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAECAAMEBQYHCAkKC//EAMMRAAICAQMDAwIDBQIFAgQEhwEAAhEDEBIhBCAxQRMFMCIyURRABjMjYUIVcVI0gVAkkaFDsRYHYjVT8NElYMFE4XLxF4JjNnAmRVSSJ6LSCAkKGBkaKCkqNzg5OkZHSElKVVZXWFlaZGVmZ2hpanN0dXZ3eHl6gIOEhYaHiImKkJOUlZaXmJmaoKOkpaanqKmqsLKztLW2t7i5usDCw8TFxsfIycrQ09TV1tfY2drg4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwALCAgKCAcLCgkKDQwLDREcEhEPDxEiGRoUHCkkKyooJCcnLTJANy0wPTAnJzhMOT1DRUhJSCs2T1VORlRAR0hF/9sAQwEMDQ0RDxEhEhIhRS4nLkVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF/9oADAMBAAIRAxEAAAHqa//aAAgBAQABBQJ//9oACAEDEQE/AX//2gAIAQIRAT8Bf//aAAgBAQAGPwJ//8QAMxABAAMAAgICAgIDAQEAAAILAREAITFBUWFxgZGhscHw0RDh8SAwQFBgcICQoLDA0OD/2gAIAQEAAT8hv//aAAwDAQACEQMRAAAQH//EADMRAQEBAAMAAQIFBQEBAAEBCQEAESExEEFRYSBx8JGBobHRweHxMEBQYHCAkKCwwNDg/9oACAEDEQE/EL//2gAIAQIRAT8Qv//aAAgBAQABPxC//9k= \ No newline at end of file