diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..8fa55101 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +DESCOPE_PROJECT_ID= +ANTHROPIC_API_KEY= +LANGSMITH_API_KEY= +LANGSMITH_ENDPOINT=https://eu.api.smith.langchain.com +AUTH_TRUST_HOST=true +AUTH_DESCOPE_ID= +AUTH_DESCOPE_SECRET= +AUTH_SECRET=# Generate with `npx auth`. Read more: https://cli.authjs.dev +PUBLIC_LANGCHAIN_API_KEY= +PUBLIC_LANGGRAPH_API_URL=http://127.0.0.1:2024 diff --git a/.gitignore b/.gitignore index e5a35cc6..edf70975 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .env __pycache__/ .langgraph_api/ + +# moon +.moon/cache +.moon/docker diff --git a/.moon/tasks.yaml b/.moon/tasks.yaml new file mode 100644 index 00000000..a853e5b1 --- /dev/null +++ b/.moon/tasks.yaml @@ -0,0 +1,5 @@ +# https://moonrepo.dev/docs/config/tasks +$schema: "https://moonrepo.dev/schemas/tasks.json" + +taskOptions: + envFile: .env diff --git a/.moon/toolchain.yml b/.moon/toolchain.yml new file mode 100644 index 00000000..baae0a19 --- /dev/null +++ b/.moon/toolchain.yml @@ -0,0 +1,11 @@ +# https://moonrepo.dev/docs/config/toolchain +$schema: "https://moonrepo.dev/schemas/toolchain.json" + +python: + version: "3.12" + packageManager: "uv" + +node: + version: "24" + packageManager: "pnpm" + inferTasksFromScripts: true diff --git a/.moon/workspace.yml b/.moon/workspace.yml new file mode 100644 index 00000000..342bc14e --- /dev/null +++ b/.moon/workspace.yml @@ -0,0 +1,12 @@ +# https://moonrepo.dev/docs/config/workspace +$schema: "./cache/schemas/workspace.json" + +# extends: './shared/workspace.yml' + +projects: + - "apps/*" + - "packages/*" + +vcs: + manager: "git" + defaultBranch: "main" diff --git a/.prototools b/.prototools new file mode 100644 index 00000000..305e5b18 --- /dev/null +++ b/.prototools @@ -0,0 +1 @@ +moon = "1.38.5" diff --git a/.python-version b/.python-version deleted file mode 100644 index 24ee5b1b..00000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.13 diff --git a/README.md b/README.md index f711791a..2f0c6ca3 100644 --- a/README.md +++ b/README.md @@ -11,39 +11,35 @@ Opinionated SvelteKit/Flowbite based LLM frontend for LangGraph server. ## Prerequisites -- Python 3.12 -- Node.js 24 LTS -- [uv](https://docs.astral.sh/uv/) (Python package manager) -- pnpm (Node.js package manager) +- [Install moonrepo](https://moonrepo.dev/docs/install), which installs all other dependencies: + + * Python 3.12 + * Node.js 24 LTS + * [uv](https://docs.astral.sh/uv/) (Python package manager) + * pnpm (Node.js package manager) ## Configuration Both the frontend and backend require environment variables to be configured. Copy the example files and update them with your values: -### Backend Environment Variables +### Environment Variables Copy the example file: ```bash -cd apps/backend cp .env.example .env ``` -Configure the following variables in `apps/backend/.env`: +#### Backend +Configure the following variables in `.env`: - `DESCOPE_PROJECT_ID` - Your Descope project ID for authentication - `ANTHROPIC_API_KEY` - Your Anthropic API key for Claude integration - `LANGSMITH_API_KEY` - Your LangSmith API key for tracing (optional) - `LANGSMITH_ENDPOINT` - LangSmith endpoint URL (defaults to EU region) -### Frontend Environment Variables - -Copy the example file: -```bash -cd apps/frontend -cp .env.example .env -``` +#### Frontend -Configure the following variables in `apps/frontend/.env`: +Configure the following variables in `.env`: - `AUTH_TRUST_HOST=true` - Enable auth trust host for development - `AUTH_DESCOPE_ID` - Your Descope project ID @@ -54,43 +50,23 @@ Configure the following variables in `apps/frontend/.env`: ## Getting Started -### Backend Setup - -Navigate to the backend directory and install dependencies: - -```bash -cd apps/backend -uv sync -``` +### Start dev servers -Start the development server: +The following command ensures dependencies are installed and starts dev servers for frontend and backend, with hot reload: ```bash -uv run langgraph dev +moon :dev ``` -### Frontend Setup +### Run local checks -Navigate to the frontend directory and install dependencies: +Run all checks (linting, type checking, formatting): ```bash -cd apps/frontend -pnpm install +moon check --all ``` -Start the development server: - -```bash -npm run dev -``` - -Or open the app in a new browser tab: - -```bash -npm run dev -- --open -``` - -## Development +## Tooling ### Backend Development @@ -108,17 +84,6 @@ The frontend is built with modern web technologies: - Playwright for end-to-end testing - Vitest for unit testing -#### Available Scripts - -- `npm run dev` - Start development server -- `npm run build` - Build for production -- `npm run preview` - Preview production build -- `npm run test` - Run all tests -- `npm run test:unit` - Run unit tests -- `npm run test:e2e` - Run end-to-end tests -- `npm run lint` - Lint code -- `npm run format` - Format code - ## Production ### Frontend Build @@ -147,4 +112,4 @@ svelte-langgraph/ │ ├── messages/ # Internationalization files │ └── e2e/ # End-to-end tests └── README.md -``` \ No newline at end of file +``` diff --git a/apps/backend/moon.yml b/apps/backend/moon.yml new file mode 100644 index 00000000..4cdad5c8 --- /dev/null +++ b/apps/backend/moon.yml @@ -0,0 +1,21 @@ +# https://moonrepo.dev/docs/config/project +$schema: "https://moonrepo.dev/schemas/project.json" + +language: python +stack: backend +type: application + +tasks: + format: + command: "ruff format" + lint: + command: "ruff check" + lint-fix: + extends: lint + args: "--fix" + local: true + typecheck: + command: "pyright" + dev: + command: "langgraph dev --no-browser" + preset: "watcher" diff --git a/apps/backend/src/auth.py b/apps/backend/src/auth.py index eb65f1fa..d62765cd 100644 --- a/apps/backend/src/auth.py +++ b/apps/backend/src/auth.py @@ -1,15 +1,14 @@ import logging -import os +# import os -from descope import AuthException from langgraph_sdk import Auth from langgraph_sdk.auth.types import MinimalUserDict -from descope import DescopeClient +# from descope import DescopeClient logger = logging.getLogger(__name__) -descope_client = DescopeClient(project_id=os.getenv("DESCOPE_PROJECT_ID", "")) +# descope_client = DescopeClient(project_id=os.getenv("DESCOPE_PROJECT_ID", "")) # The "Auth" object is a container that LangGraph will use to mark our authentication function auth = Auth() @@ -54,7 +53,7 @@ async def get_current_user(authorization: str | None) -> MinimalUserDict: # permissions=claims["permissions"], # ) - return user + # return user @auth.on diff --git a/apps/backend/src/graph.py b/apps/backend/src/graph.py index d13e4efa..891080f3 100755 --- a/apps/backend/src/graph.py +++ b/apps/backend/src/graph.py @@ -73,10 +73,10 @@ def make_graph(config: RunnableConfig) -> CompiledStateGraph: async def main(): load_dotenv() - agent = make_graph() - config = RunnableConfig(configurable={"thread_id": "1"}) + agent = make_graph(config) + user_input = input(f"{INITIAL_MESSAGE}\n") while True: diff --git a/apps/frontend/README.md b/apps/frontend/README.md index 460af5a6..824c7e6e 100644 --- a/apps/frontend/README.md +++ b/apps/frontend/README.md @@ -1,13 +1,16 @@ # sv + Svelte frontend project. ## Getting started ### Requirements -* pnpm -* Node 24 LTS + +- pnpm +- Node 24 LTS ### Install deps + ```bash pnpm install ``` diff --git a/apps/frontend/moon.yml b/apps/frontend/moon.yml new file mode 100644 index 00000000..53dc1860 --- /dev/null +++ b/apps/frontend/moon.yml @@ -0,0 +1,6 @@ +# https://moonrepo.dev/docs/config/project +$schema: 'https://moonrepo.dev/schemas/project.json' + +language: typescript +stack: frontend +type: application diff --git a/apps/frontend/src/app.html b/apps/frontend/src/app.html index 2a13dee2..f7989f72 100644 --- a/apps/frontend/src/app.html +++ b/apps/frontend/src/app.html @@ -1,15 +1,13 @@ + + + + + %sveltekit.head% + - - - - - %sveltekit.head% - - - -
%sveltekit.body%
- - + +
%sveltekit.body%
+ diff --git a/apps/frontend/src/app.tailwind.css b/apps/frontend/src/app.tailwind.css index a9ebb9ff..a393ca3e 100644 --- a/apps/frontend/src/app.tailwind.css +++ b/apps/frontend/src/app.tailwind.css @@ -1,4 +1,4 @@ -@import "tailwindcss"; +@import 'tailwindcss'; @plugin '@tailwindcss/forms'; @plugin '@tailwindcss/typography'; @@ -36,9 +36,8 @@ @source '../node_modules/flowbite-svelte-blocks/dist'; @layer base { - /* disable chrome cancel button */ - input[type="search"]::-webkit-search-cancel-button { + input[type='search']::-webkit-search-cancel-button { display: none; } } diff --git a/apps/frontend/src/auth.ts b/apps/frontend/src/auth.ts index 4039ef7a..b50fe49c 100644 --- a/apps/frontend/src/auth.ts +++ b/apps/frontend/src/auth.ts @@ -1,6 +1,6 @@ -import { SvelteKitAuth } from "@auth/sveltekit" -import Descope from "@auth/sveltekit/providers/descope" +import { SvelteKitAuth } from '@auth/sveltekit'; +import Descope from '@auth/sveltekit/providers/descope'; export const { handle, signIn, signOut } = SvelteKitAuth({ - providers: [Descope], -}) + providers: [Descope] +}); diff --git a/apps/frontend/src/hooks.server.ts b/apps/frontend/src/hooks.server.ts index 2beaefb8..8e806b2b 100644 --- a/apps/frontend/src/hooks.server.ts +++ b/apps/frontend/src/hooks.server.ts @@ -1,7 +1,7 @@ import type { Handle } from '@sveltejs/kit'; import { sequence } from '@sveltejs/kit/hooks'; import { paraglideMiddleware } from '$lib/paraglide/server'; -import { handle as handleAuth } from "./auth"; +import { handle as handleAuth } from './auth'; const handleParaglide: Handle = ({ event, resolve }) => paraglideMiddleware(event.request, ({ request, locale }) => { diff --git a/apps/frontend/src/routes/+layout.server.ts b/apps/frontend/src/routes/+layout.server.ts index 54c76a3d..6a306f19 100644 --- a/apps/frontend/src/routes/+layout.server.ts +++ b/apps/frontend/src/routes/+layout.server.ts @@ -1,9 +1,9 @@ -import type { LayoutServerLoad } from "./$types" +import type { LayoutServerLoad } from './$types'; export const load: LayoutServerLoad = async (event) => { - const session = await event.locals.auth() + const session = await event.locals.auth(); return { - session, - } -} + session + }; +}; diff --git a/apps/frontend/src/routes/+layout.svelte b/apps/frontend/src/routes/+layout.svelte index bd2711b1..4dabd7df 100644 --- a/apps/frontend/src/routes/+layout.svelte +++ b/apps/frontend/src/routes/+layout.svelte @@ -5,11 +5,7 @@ import { page } from '$app/state'; import { MessagesOutline } from 'flowbite-svelte-icons'; - import { - UserCircleSolid, - ClipboardListSolid, - ArrowRightAltSolid - } from 'flowbite-svelte-icons'; + import { UserCircleSolid, ClipboardListSolid, ArrowRightAltSolid } from 'flowbite-svelte-icons'; import { Button, Navbar, @@ -29,60 +25,63 @@ - + My AI Chat UI -
+
{#if page.data.session} - +
{page.data.session.user?.name ?? 'User'} - + {page.data.session.user?.email ?? 'email@example.com'}
- + Dashboard - + Profile - + Sign out diff --git a/apps/frontend/src/routes/+page.svelte b/apps/frontend/src/routes/+page.svelte index 9a8d9bca..3258b615 100644 --- a/apps/frontend/src/routes/+page.svelte +++ b/apps/frontend/src/routes/+page.svelte @@ -41,7 +41,7 @@
@@ -59,7 +59,7 @@ {#snippet head()}FEATURED IN{/snippet}
- + - + - + = 0; i--) { @@ -154,7 +153,7 @@ break; } } - + if (aiMessageIndex !== -1) { // Update the AI message in place and force reactivity messages[aiMessageIndex] = { ...aimessage }; @@ -178,51 +177,14 @@ } - - {#if !chat_started} -
-
+
+
-
+
-

+

{#if page.data.session?.user?.name} Hey {page.data.session.user.name}, how can I help you today? {:else if page.data.session?.user?.email} @@ -231,53 +193,63 @@ How can I help you today? {/if}

-

- I'm here to assist with your questions, provide information, help with tasks, or engage in conversation. +

+ I'm here to assist with your questions, provide information, help with tasks, or + engage in conversation.

- + -
- - - - - - -
-
- -
-
+ +
+