diff --git a/backend/main.py b/backend/main.py index cc538e6..96a9418 100644 --- a/backend/main.py +++ b/backend/main.py @@ -40,10 +40,10 @@ async def chat(request: Request): async def stream(): async for token in stream_response(agent, messages): - chunk = json.dumps({"type": "text", "delta": token}) + chunk = json.dumps({"type": "text-delta", "textDelta": token}) yield f"data: {chunk}\n\n" yield "data: [DONE]\n\n" - + return StreamingResponse( stream(), media_type="text/event-stream", diff --git a/backend/mcp_server/__init__.py b/backend/mcp_server/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/backend/mcp_server/tools/judges.py b/backend/mcp_server/tools/judges.py index d5ad172..0ecf6ad 100644 --- a/backend/mcp_server/tools/judges.py +++ b/backend/mcp_server/tools/judges.py @@ -3,7 +3,6 @@ import httpx import json from fastmcp import FastMCP from typing import Optional -from pydantic import Field JUSTICE_API = "https://obcan.justice.sk/pilot/api/ress-isu-service" HEADERS = { @@ -29,7 +28,7 @@ def register_judge_tools(mcp: FastMCP): async def judge_autocomplete( query: str, court_id: Optional[str] = None, - limit: int = Field(default=10, description="Maximálny počet výsledkov"), + limit: int = 10, ) -> str: """ Autocomplete pre mená sudcov — použiť AKO PRVÝ krok @@ -48,8 +47,8 @@ def register_judge_tools(mcp: FastMCP): kraj: Optional[str] = None, court_id: Optional[str] = None, status: Optional[str] = None, - page: int = Field(default=0, description="Číslo stránky (začína od 0)"), - size: int = Field(default=20, description="Počet výsledkov na stránku"), + page: int = 0, + size: int = 20, ) -> str: """ Vyhľadávanie sudcov s filtrami. diff --git a/compose.yaml b/compose.yaml index 2f5e22e..1fc00b8 100644 --- a/compose.yaml +++ b/compose.yaml @@ -16,7 +16,7 @@ services: backend: build: context: . - dockerfile: /backend/Dockerfile + dockerfile: backend/Dockerfile restart: unless-stopped ports: - "8000:8000" @@ -40,9 +40,6 @@ services: - "4000:4000" env_file: - backend/.env - environment: - - GROQ_API_KEY=${GROQ_API_KEY} - - GEMINI_API_KEY=${GEMINI_API_KEY} volumes: - ./backend/config.yaml:/app/config.yaml:ro command: ['--config', '/app/config.yaml', '--port', '4000'] @@ -50,7 +47,7 @@ services: mcp: build: context: . - dockerfile: /backend/mcp_server/Dockerfile + dockerfile: backend/mcp_server/Dockerfile restart: unless-stopped ports: - "8001:8001" diff --git a/frontend/app/api/chat/route.ts b/frontend/app/api/chat/route.ts deleted file mode 100644 index 578c895..0000000 --- a/frontend/app/api/chat/route.ts +++ /dev/null @@ -1,19 +0,0 @@ -export async function POST(req: Request) { - const body = await req.json(); - - const response = await fetch("http://backend:8000/api/chat", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - }); - - return new Response(response.body, { - headers: { - "Content-Type": "text/event-stream", - "Cache-Control": "no-cache", - "X-Accel-Buffering": "no", - }, - }); -} \ No newline at end of file diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 04c459a..d053cc2 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -67,31 +67,7 @@ --ring: oklch(0.5 0.15 240); } -.dark { - --background: oklch(0.12 0.04 240); - --foreground: oklch(0.95 0.01 240); - --card: oklch(0.17 0.05 240); - --card-foreground: oklch(0.95 0.01 240); - --popover: oklch(0.17 0.05 240); - --popover-foreground: oklch(0.95 0.01 240); - --primary: oklch(0.6 0.18 240); - --primary-foreground: oklch(0.98 0 0); - --secondary: oklch(0.2 0.05 240); - --secondary-foreground: oklch(0.95 0.01 240); - --muted: oklch(0.2 0.05 240); - --muted-foreground: oklch(0.65 0.05 240); - --accent: oklch(0.22 0.06 240); - --accent-foreground: oklch(0.95 0.01 240); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 8%); - --input: oklch(1 0 0 / 12%); - --ring: oklch(0.5 0.15 240); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); -} + @layer base { * { diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 3813dcc..e73c9c4 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -14,8 +14,7 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "assistant-ui starter app", - description: "Generated by create-assistant-ui", + title: "Legal AI Assistant", }; export default function RootLayout({ @@ -24,7 +23,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + diff --git a/frontend/components/assistant-ui/header.tsx b/frontend/components/assistant-ui/header.tsx index c20d319..a514b15 100644 --- a/frontend/components/assistant-ui/header.tsx +++ b/frontend/components/assistant-ui/header.tsx @@ -16,10 +16,6 @@ export const ThreadHeader: FC = () => { - -
- -
); }; \ No newline at end of file diff --git a/frontend/components/assistant-ui/thread.tsx b/frontend/components/assistant-ui/thread.tsx index b218eee..6d970bb 100644 --- a/frontend/components/assistant-ui/thread.tsx +++ b/frontend/components/assistant-ui/thread.tsx @@ -57,9 +57,6 @@ export const Thread: FC = () => { -

- Právny AI Asistent môže robiť chyby. Overte dôležité informácie. -

diff --git a/frontend/components/assistant-ui/welcome.tsx b/frontend/components/assistant-ui/welcome.tsx index d87f589..c3ce66f 100644 --- a/frontend/components/assistant-ui/welcome.tsx +++ b/frontend/components/assistant-ui/welcome.tsx @@ -2,30 +2,22 @@ import { type FC } from "react"; -const SUGGESTIONS = [ +const STARTERS = [ { - icon: "🔍", - title: "Aké právne dáta", - description: "môže agent nájsť?", - prompt: "Aké právne dáta môžeš vyhľadať?", + icon: "/icons/magnifying-glass.svg", + description: "What legal data can the agent find?", }, { - icon: "🚫", - title: "Čo agent nesmie", - description: "robiť alebo používať?", - prompt: "Čo nie si oprávnený robiť alebo použiť?", + icon: "/icons/ban.svg", + description: "What are the agent's limitations?", }, { - icon: "🤖", - title: "Detaily AI modelu", - description: "aký model používaš?", - prompt: "Aké sú detaily tvojho AI modelu?", + icon: "/icons/hexagon.svg", + description: "What are the details of your AI model?", }, { - icon: "📊", - title: "Zdroje dát", - description: "odkiaľ čerpáš informácie?", - prompt: "Aké dátové zdroje agent využíva?", + icon: "/icons/database.svg", + description: "What are your data sources?", }, ]; @@ -47,16 +39,22 @@ const ThreadSuggestions: FC = () => { return (
- {SUGGESTIONS.map((s) => ( + {STARTERS.map((s) => ( ))}
@@ -65,17 +63,13 @@ const ThreadSuggestions: FC = () => { export const ThreadWelcome: FC = () => { return ( -
+
-
+
Legal AI { - e.currentTarget.style.display = "none"; - e.currentTarget.parentElement!.innerHTML = `
⚖️
`; - }} + className="w-50 h-50 object-cover" />
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 09f6508..8684999 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,8 +9,9 @@ "version": "0.1.0", "dependencies": { "@ai-sdk/openai": "^3.0.52", - "@assistant-ui/react": "latest", + "@assistant-ui/react": "^0.12.25", "@assistant-ui/react-ai-sdk": "latest", + "@assistant-ui/react-data-stream": "^0.12.11", "@assistant-ui/react-markdown": "latest", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-collapsible": "^1.1.12", @@ -227,6 +228,27 @@ } } }, + "node_modules/@assistant-ui/react-data-stream": { + "version": "0.12.11", + "resolved": "https://registry.npmjs.org/@assistant-ui/react-data-stream/-/react-data-stream-0.12.11.tgz", + "integrity": "sha512-DuCV1ILVJsJjl746Ly50jsyt1gUVp43E02Fbq3uau4LU9p3MhUP5CeCV0LLkdS80Hlu9X6xXc34tsL5BCyVzow==", + "license": "MIT", + "dependencies": { + "@ai-sdk/provider": "^3.0.8", + "@assistant-ui/core": "^0.1.14", + "assistant-cloud": "*", + "assistant-stream": "^0.3.11" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@assistant-ui/react-markdown": { "version": "0.12.9", "resolved": "https://registry.npmjs.org/@assistant-ui/react-markdown/-/react-markdown-0.12.9.tgz", @@ -7716,7 +7738,6 @@ "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz", "integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==", "license": "MIT", - "peer": true, "engines": { "node": ">=12.20.0" }, diff --git a/frontend/package.json b/frontend/package.json index f46b612..a67f9e7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,8 +13,9 @@ }, "dependencies": { "@ai-sdk/openai": "^3.0.52", - "@assistant-ui/react": "latest", + "@assistant-ui/react": "^0.12.25", "@assistant-ui/react-ai-sdk": "latest", + "@assistant-ui/react-data-stream": "^0.12.11", "@assistant-ui/react-markdown": "latest", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-collapsible": "^1.1.12", diff --git a/frontend/public/icons/ban.svg b/frontend/public/icons/ban.svg new file mode 100644 index 0000000..952620d --- /dev/null +++ b/frontend/public/icons/ban.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/icons/database.svg b/frontend/public/icons/database.svg new file mode 100644 index 0000000..eb8a528 --- /dev/null +++ b/frontend/public/icons/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/icons/hexagon.svg b/frontend/public/icons/hexagon.svg new file mode 100644 index 0000000..83ca571 --- /dev/null +++ b/frontend/public/icons/hexagon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/icons/magnifying-glass.svg b/frontend/public/icons/magnifying-glass.svg new file mode 100644 index 0000000..b18ce93 --- /dev/null +++ b/frontend/public/icons/magnifying-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file