mirror of
https://github.com/karpathy/nanochat.git
synced 2026-05-09 17:30:14 +00:00
Build services/frontend/ replacing the legacy nanochat/ui.html single-file UI. Landing, login, and chat pages ported with full design system: Devanagari + Great Vibes hero, samosa/chai/toran SVG animations, gold/cream palette. - App Router pages: / (hero + floating illustrations), /login (split-screen OAuth with mandala motif), /chat (260px collapsible sidebar, suggestion chips, markdown + code-copy, auto-expanding input, slash commands) - SSE streaming via useSSE hook and /api/chat/stream BFF route (proxies to CHAT_API_URL when set, falls back to mock echo for local dev) - NextAuth.js v5 with Google + GitHub providers; middleware gates /chat/* - Zustand store with localStorage persistence for conversations/settings - Tailwind theme carries all ui.html tokens + keyframes (pendulum, float, wobble, steamFloat, steamType); SVG assets componentized under components/svg - Multi-stage node:20-alpine Dockerfile with Next standalone output Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
export interface SlashResult {
|
|
handled: boolean;
|
|
consoleMessage?: string;
|
|
clear?: boolean;
|
|
setTemperature?: number;
|
|
setTopK?: number;
|
|
}
|
|
|
|
export function parseSlashCommand(
|
|
raw: string,
|
|
state: { temperature: number; topK: number },
|
|
): SlashResult {
|
|
const line = raw.trim();
|
|
if (!line.startsWith('/')) return { handled: false };
|
|
|
|
const [cmd, arg] = line.split(/\s+/);
|
|
switch (cmd.toLowerCase()) {
|
|
case '/temperature': {
|
|
if (arg === undefined) {
|
|
return { handled: true, consoleMessage: `Current temperature: ${state.temperature}` };
|
|
}
|
|
const t = parseFloat(arg);
|
|
if (isNaN(t) || t < 0 || t > 2) {
|
|
return { handled: true, consoleMessage: 'Invalid temperature. Must be between 0.0 and 2.0' };
|
|
}
|
|
return { handled: true, setTemperature: t, consoleMessage: `Temperature set to ${t}` };
|
|
}
|
|
case '/topk': {
|
|
if (arg === undefined) {
|
|
return { handled: true, consoleMessage: `Current top-k: ${state.topK}` };
|
|
}
|
|
const k = parseInt(arg, 10);
|
|
if (isNaN(k) || k < 1 || k > 200) {
|
|
return { handled: true, consoleMessage: 'Invalid top-k. Must be between 1 and 200' };
|
|
}
|
|
return { handled: true, setTopK: k, consoleMessage: `Top-k set to ${k}` };
|
|
}
|
|
case '/clear':
|
|
return { handled: true, clear: true };
|
|
case '/help':
|
|
return {
|
|
handled: true,
|
|
consoleMessage:
|
|
'Commands:\n/temperature [0-2] — sampling temperature\n/topk [1-200] — top-k sampling\n/clear — clear conversation\n/help — show this help',
|
|
};
|
|
default:
|
|
return { handled: true, consoleMessage: `Unknown command: ${cmd}` };
|
|
}
|
|
}
|