mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-05-19 11:08:47 +02:00
Migrate frontend to Vite + Hono CopilotKit runtime
Replaces the Next.js scaffold with a Vite SPA paired with a Hono sidecar that hosts the CopilotKit runtime and proxies AG-UI traffic to the MAF backend. Adds dev/prod Dockerfile, .dockerignore, .gitignore, pnpm workspace config, and updates entrypoints (main.tsx / App.tsx / index.css / index.html) plus the service worker accordingly. Server middleware reconciles MAF MESSAGES_SNAPSHOT id mismatches so post-tool-call assistant text doesn't render twice, suppresses duplicate text emitted alongside render tools, and strips OpenAI training-token leaks from streamed deltas. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,30 +1,34 @@
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import { AuthProvider, useAuth } from './AuthContext';
|
||||
import { ThemeProvider } from './ThemeContext';
|
||||
import { PrivacyProvider } from './PrivacyContext';
|
||||
import Layout from './components/Layout';
|
||||
import Login from './pages/Login';
|
||||
import Dashboard from './pages/Dashboard';
|
||||
import Budget from './pages/Budget';
|
||||
import Analytics from './pages/Analytics';
|
||||
import Salarios from './pages/Salarios';
|
||||
import Pensions from './pages/Pensions';
|
||||
import Proyecciones from './pages/Proyecciones';
|
||||
import ServiciosMunicipales from './pages/ServiciosMunicipales';
|
||||
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
|
||||
import { CopilotKit } from "@copilotkit/react-core";
|
||||
import { AuthProvider, useAuth } from "./AuthContext";
|
||||
import { ThemeProvider } from "./contexts/theme-context";
|
||||
import { PrivacyProvider } from "./contexts/privacy-context";
|
||||
import Layout from "./components/Layout";
|
||||
import LoginPage from "./pages/Login";
|
||||
import Asistente from "./pages/Asistente";
|
||||
import Analytics from "./pages/Analytics";
|
||||
import Budget from "./pages/Budget";
|
||||
import Salarios from "./pages/Salarios";
|
||||
import Pensions from "./pages/Pensions";
|
||||
import Proyecciones from "./pages/Proyecciones";
|
||||
import ServiciosMunicipales from "./pages/ServiciosMunicipales";
|
||||
|
||||
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
if (isLoading) return null;
|
||||
return isAuthenticated ? <>{children}</> : <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
|
||||
if (isLoading) return null;
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/login"
|
||||
element={isAuthenticated ? <Navigate to="/" replace /> : <Login />}
|
||||
element={isAuthenticated ? <Navigate to="/asistente" replace /> : <LoginPage />}
|
||||
/>
|
||||
<Route
|
||||
element={
|
||||
@@ -33,14 +37,14 @@ function AppRoutes() {
|
||||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route index element={<Navigate to="/asistente" replace />} />
|
||||
<Route path="/asistente" element={<Asistente />} />
|
||||
<Route path="/budget" element={<Budget />} />
|
||||
<Route path="/analytics" element={<Analytics />} />
|
||||
<Route path="/proyecciones" element={<Proyecciones />} />
|
||||
<Route path="/salarios" element={<Salarios />} />
|
||||
<Route path="/pensions" element={<Pensions />} />
|
||||
<Route path="/servicios-municipales" element={<ServiciosMunicipales />} />
|
||||
{/* Redirect old routes */}
|
||||
<Route path="/transactions" element={<Navigate to="/budget" replace />} />
|
||||
<Route path="/transfers" element={<Navigate to="/budget" replace />} />
|
||||
</Route>
|
||||
@@ -54,7 +58,9 @@ export default function App() {
|
||||
<ThemeProvider>
|
||||
<PrivacyProvider>
|
||||
<AuthProvider>
|
||||
<AppRoutes />
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" agent="wealthysmart" a2ui={{}}>
|
||||
<AppRoutes />
|
||||
</CopilotKit>
|
||||
</AuthProvider>
|
||||
</PrivacyProvider>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import "shadcn/tailwind.css";
|
||||
@import "@fontsource-variable/noto-sans";
|
||||
@import "@fontsource-variable/ibm-plex-sans";
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import "@copilotkit/react-core/v2/styles.css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--font-sans: "Noto Sans Variable", sans-serif;
|
||||
--font-heading: "IBM Plex Sans Variable", sans-serif;
|
||||
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.141 0.005 285.823);
|
||||
--card: oklch(1 0 0);
|
||||
@@ -39,6 +42,8 @@
|
||||
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
||||
--sidebar-border: oklch(0.92 0.004 286.32);
|
||||
--sidebar-ring: oklch(0.705 0.015 286.067);
|
||||
|
||||
--copilot-kit-primary-color: var(--primary);
|
||||
}
|
||||
|
||||
.dark {
|
||||
@@ -73,11 +78,39 @@
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.552 0.016 285.938);
|
||||
|
||||
--copilot-kit-primary-color: var(--primary);
|
||||
}
|
||||
|
||||
/* Wire CopilotKit v2 CSS variables to WealthySmart's dark palette.
|
||||
The v2 CSS sets --background/--muted/etc directly on [data-copilotkit]
|
||||
elements (unlayered), overriding inherited values from .dark on <html>.
|
||||
Using html.dark [data-copilotkit] (specificity 0,2,1) beats the v2's
|
||||
own .dark [data-copilotkit] (specificity 0,2,0) and restores dark mode. */
|
||||
html.dark [data-copilotkit] {
|
||||
--background: oklch(0.141 0.005 285.823);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.21 0.006 285.885);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.21 0.006 285.885);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.437 0.078 188.216);
|
||||
--primary-foreground: oklch(0.984 0.014 180.72);
|
||||
--secondary: oklch(0.274 0.006 286.033);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.274 0.006 286.033);
|
||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||
--accent: oklch(0.274 0.006 286.033);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.552 0.016 285.938);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: 'Noto Sans Variable', sans-serif;
|
||||
--font-heading: 'IBM Plex Sans Variable', sans-serif;
|
||||
--font-sans: var(--font-sans);
|
||||
--font-heading: var(--font-heading);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
@@ -121,13 +154,11 @@
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
html {
|
||||
@apply font-sans;
|
||||
}
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
}
|
||||
|
||||
/* Privacy mode: blur sensitive financial data */
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./App";
|
||||
import "./index.css";
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user