From d5a5945c037b58984e9142de056359c46ca52bff Mon Sep 17 00:00:00 2001 From: Zoe <62722391+juls0730@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:16:06 -0600 Subject: [PATCH] streaming, markdown, model selecting, and lots more --- .env.example | 11 +- .gitignore | 3 + AGENTS.md | 46 +- BUGS.md | 29 + TODO.md | 4 +- app/app.vue | 42 +- app/assets/css/base.css | 351 ++---- app/assets/css/reset.css | 80 ++ app/components/ChatInput.vue | 174 ++- app/components/Dropdown.vue | 65 +- app/components/LoadingSpinner.vue | 13 - app/components/Logo/Gemini.vue | 58 + app/components/Logo/Grok.vue | 23 + app/components/Markdown/AstNode.vue | 40 + app/components/Markdown/Renderer.vue | 289 +++++ app/components/Markdown/ShikiHighlight.vue | 70 ++ app/components/Message.vue | 100 -- app/components/Message/Agent/Error.vue | 12 + app/components/Message/Agent/Reasoning.vue | 85 ++ app/components/Message/Agent/Text.vue | 12 + app/components/Message/Agent/Tool/Debug.vue | 177 +++ app/components/Message/Agent/Tool/index.vue | 64 + app/components/Message/Agent/index.vue | 55 + app/components/Message/User.vue | 13 + app/components/Message/index.vue | 21 + app/components/ModelIcon.vue | 20 + app/components/ModelSelector.vue | 181 +++ app/components/Settings/AIServiceProvider.vue | 333 +++++ app/components/Settings/Dialog.vue | 125 ++ app/components/Settings/GeneralSettings.vue | 6 + app/components/Settings/ProviderSettings.vue | 63 + app/components/Settings/ProviderSidebar.vue | 37 + app/components/SettingsDialog.vue | 91 -- app/components/Sidenav/Header.vue | 46 +- app/components/Sidenav/HeaderAgent.vue | 73 +- app/components/Sidenav/Item.vue | 50 +- app/components/Sidenav/NavAgent.vue | 135 +- app/components/Sidenav/NavAgentTopics.vue | 106 -- app/components/Sidenav/NavHome.vue | 86 +- app/components/Sidenav/index.vue | 125 +- app/components/Slider.vue | 77 ++ app/components/ThemeSwitcher.vue | 31 +- app/composables/auth.ts | 68 - app/composables/useAgents.ts | 113 +- app/composables/useAppState.ts | 90 -- app/composables/useAuth.ts | 66 + app/composables/useAutoScroll.ts | 64 + app/composables/useChat.ts | 232 ++++ app/composables/useClickOutside.ts | 28 +- app/composables/useFillIds.ts | 12 + app/composables/useKeyboardShortcuts.ts | 48 +- app/composables/useModels.ts | 51 + app/composables/useSettings.ts | 33 +- app/composables/useSidebar.ts | 54 +- app/composables/useTasks.ts | 21 - app/composables/useTheme.ts | 19 +- app/composables/useTopics.ts | 59 - app/layouts/default.vue | 13 +- app/middleware/auth.global.ts | 26 +- app/pages/agent/[id]/index.vue | 71 +- app/pages/agent/[id]/profile.vue | 42 +- app/pages/agent/[id]/topic/[topicId].vue | 309 ++--- app/pages/auth/login.vue | 118 +- app/pages/auth/register.vue | 151 ++- app/pages/index.vue | 102 +- app/plugins/auth.client.ts | 32 +- app/plugins/auth.server.ts | 22 +- app/plugins/remark.ts | 18 + app/plugins/sync-app-state.client.ts | 34 - app/plugins/sync-app-state.server.ts | 14 - app/types/dropdown.ts | 2 +- app/types/model.ts | 10 + app/types/settings.ts | 7 + app/utils/crypto.ts | 95 ++ app/utils/hash.ts | 20 + app/utils/model-mapping.ts | 33 + bun.lock | 1108 +++++++++++++---- db/auth/auth.schema.ts | 93 -- db/migrate.ts | 7 - db/schema.ts | 61 - docker-compose.dev.yml | 24 +- docs/encryption.md | 9 + drizzle.config.ts | 11 - generate-tokens.ts | 38 + lib/auth-client.ts | 3 + lib/auth.ts | 37 +- nuxt.config.ts | 51 +- package.json | 48 +- patches/@triplit%2Fclient@1.0.50.patch | 169 +++ patches/@triplit%2Fdb@1.1.10.patch | 15 + server/api/agents/[id]/index.patch.ts | 29 - server/api/agents/index.get.ts | 14 - server/api/agents/index.post.ts | 17 - server/api/auth/[...all].ts | 4 +- server/api/chat/cancel/[generationId].post.ts | 27 + server/api/chat/generate.post.ts | 660 +++++++++- server/api/chat/generations/[id].get.ts | 43 - server/api/chat/stream/[id].get.ts | 121 -- server/api/topics/[id]/index.get.ts | 42 - server/api/topics/[id]/messages/index.post.ts | 29 - server/api/topics/index.get.ts | 14 - server/api/topics/index.post.ts | 30 - server/lib/triplit.ts | 8 + server/plugins/database.ts | 14 - server/types/chat.ts | 29 - server/utils/auth.ts | 2 +- server/utils/drizzle.ts | 11 - server/utils/generation.ts | 305 ----- server/utils/generations.ts | 22 + triplit/auth-schema.ts | 90 ++ triplit/schema.ts | 312 +++++ tsconfig.json | 33 +- types/index.ts | 7 - uno.config.ts | 11 +- 114 files changed, 6109 insertions(+), 2938 deletions(-) create mode 100644 BUGS.md create mode 100644 app/assets/css/reset.css delete mode 100644 app/components/LoadingSpinner.vue create mode 100644 app/components/Logo/Gemini.vue create mode 100644 app/components/Logo/Grok.vue create mode 100644 app/components/Markdown/AstNode.vue create mode 100644 app/components/Markdown/Renderer.vue create mode 100644 app/components/Markdown/ShikiHighlight.vue delete mode 100644 app/components/Message.vue create mode 100644 app/components/Message/Agent/Error.vue create mode 100644 app/components/Message/Agent/Reasoning.vue create mode 100644 app/components/Message/Agent/Text.vue create mode 100644 app/components/Message/Agent/Tool/Debug.vue create mode 100644 app/components/Message/Agent/Tool/index.vue create mode 100644 app/components/Message/Agent/index.vue create mode 100644 app/components/Message/User.vue create mode 100644 app/components/Message/index.vue create mode 100644 app/components/ModelIcon.vue create mode 100644 app/components/ModelSelector.vue create mode 100644 app/components/Settings/AIServiceProvider.vue create mode 100644 app/components/Settings/Dialog.vue create mode 100644 app/components/Settings/GeneralSettings.vue create mode 100644 app/components/Settings/ProviderSettings.vue create mode 100644 app/components/Settings/ProviderSidebar.vue delete mode 100644 app/components/SettingsDialog.vue delete mode 100644 app/components/Sidenav/NavAgentTopics.vue create mode 100644 app/components/Slider.vue delete mode 100644 app/composables/auth.ts delete mode 100644 app/composables/useAppState.ts create mode 100644 app/composables/useAuth.ts create mode 100644 app/composables/useAutoScroll.ts create mode 100644 app/composables/useChat.ts create mode 100644 app/composables/useFillIds.ts create mode 100644 app/composables/useModels.ts delete mode 100644 app/composables/useTasks.ts delete mode 100644 app/composables/useTopics.ts create mode 100644 app/plugins/remark.ts delete mode 100644 app/plugins/sync-app-state.client.ts delete mode 100644 app/plugins/sync-app-state.server.ts create mode 100644 app/types/model.ts create mode 100644 app/types/settings.ts create mode 100644 app/utils/crypto.ts create mode 100644 app/utils/hash.ts create mode 100644 app/utils/model-mapping.ts delete mode 100644 db/auth/auth.schema.ts delete mode 100644 db/migrate.ts delete mode 100644 db/schema.ts create mode 100644 docs/encryption.md delete mode 100644 drizzle.config.ts create mode 100644 generate-tokens.ts create mode 100644 lib/auth-client.ts create mode 100644 patches/@triplit%2Fclient@1.0.50.patch create mode 100644 patches/@triplit%2Fdb@1.1.10.patch delete mode 100644 server/api/agents/[id]/index.patch.ts delete mode 100644 server/api/agents/index.get.ts delete mode 100644 server/api/agents/index.post.ts create mode 100644 server/api/chat/cancel/[generationId].post.ts delete mode 100644 server/api/chat/generations/[id].get.ts delete mode 100644 server/api/chat/stream/[id].get.ts delete mode 100644 server/api/topics/[id]/index.get.ts delete mode 100644 server/api/topics/[id]/messages/index.post.ts delete mode 100644 server/api/topics/index.get.ts delete mode 100644 server/api/topics/index.post.ts create mode 100644 server/lib/triplit.ts delete mode 100644 server/plugins/database.ts delete mode 100644 server/types/chat.ts delete mode 100644 server/utils/drizzle.ts delete mode 100644 server/utils/generation.ts create mode 100644 server/utils/generations.ts create mode 100644 triplit/auth-schema.ts create mode 100644 triplit/schema.ts delete mode 100644 types/index.ts diff --git a/.env.example b/.env.example index d63214a..950812e 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ -VERIDIAN_DB_NAME=veridian -POSTGRES_PASSWORD=password -NUXT_AUTH_SECRET="YOUR-SUPER-SECURE-SECRET" # openssl rand -base64 32 - -DATABASE_URL=postgresql://postgres:password@localhost:5432/veridian \ No newline at end of file +TRIPLIT_SERVICE_TOKEN="your-triplit-service-token" # given to you on startup, or by running `tsx generate-tokens.ts` +NUXT_TRIPLIT_ANON_TOKEN="your-anonymous-triplit-token" # also given to you on startup, or by running `tsx generate-tokens.ts` +BETTER_AUTH_SECRET="super-secret" # openssl rand -base64 32 +TRIPLIT_JWT_SECRET="super-secret" +EXTERNAL_JWT_SECRET=${BETTER_AUTH_SECRET} # no need to change this +NUXT_PUBLIC_TRIPLIT_URL="http://localhost:6543" # your triplit server url diff --git a/.gitignore b/.gitignore index 4a7f73a..60a72d1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,9 @@ logs .fleet .idea +# tunneling config +frpc.toml + # Local env files .env .env.* diff --git a/AGENTS.md b/AGENTS.md index 50f0033..4f4c5bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,11 +5,11 @@ the Veridian repository. ## Project Overview -Veridian is a Nuxt 4 application built with TypeScript, using PostgreSQL with -Drizzle ORM, better-auth for authentication, and UnoCSS for styling. The app is -an agnetic chat platform that is meant to provide a well rounded experience for -interacting with LLMs as well as providing a way to manage agents and provide -helpful tools like RAG (retrieval augmented generation) and web scraping/search. +Veridian is a Nuxt 4 application built with TypeScript, using Triplit with +better-auth for authentication, and UnoCSS for styling. The app is an agnetic +chat platform that is meant to provide a well rounded experience for interacting +with LLMs as well as providing a way to manage agents and provide helpful tools +like RAG (retrieval augmented generation) and web scraping/search. You should be connected to the Nuxt docs MCP server, if you need to reference the documentation or are unsure on how to implement something, consult the @@ -24,18 +24,14 @@ database commands. ### Database Commands -- `tsx db/migrate.ts` - Run database migrations -- `bun x @better-auth/cli@latest generate --output db/auth/auth.schema.ts` - - Generate authentication schema based on `lib/auth.ts` -- `bun x drizzle-kit generate` - Generate migration files -- `bun x drizzle-kit push` - Push schema changes to database -- `bun x drizzle-kit studio` - Open Drizzle Studio for database inspection +- `bunx triplit schema push` - Push schema changes to database ## Tech Stack & Dependencies - **Framework**: Nuxt 4 (SSR enabled) - **Language**: TypeScript with strict configuration -- **Database**: PostgreSQL with Drizzle ORM +- **Database**: Triplit (next generation fullstack syncing database, sort of + like convex) - **Auth**: better-auth with email/password and social providers - **Styling**: UnoCSS with presetMini - **Icons**: @nuxt/icon with Iconify, use Myna UI Icons @@ -116,12 +112,10 @@ the source is uniform and easy to follow.** ### Database Patterns -- Use Drizzle ORM with PostgreSQL -- Export all schemas from `db/schema.ts` +- Use Triplit for database operations +- Export all schemas from `triplit/schema.ts` - Use environment variables for database credentials -- `db/auth/auth.schema.ts` is a generated file, do not touch it. If you need to - change the authentication schema, edit `lib/auth.ts` and run the generation - script. +- Triplit schemas are defined in `triplit/schema.ts` and pushed using `bunx triplit schema push` ### Error Handling @@ -142,7 +136,7 @@ the source is uniform and easy to follow.** The app uses better-auth with: - Email/password authentication (configurable via env vars) -- Drizzle adapter for PostgreSQL +- Triplit adapter for authentication - Session management through cookies - Auth plugins in `app/plugins/` for client/server initialization - Global auth middleware in `app/middleware/auth.global.ts` @@ -165,10 +159,10 @@ user must be authenticated. │ \-- plugins/ # Vue/Nuxt plugins |-- server/ # Server-side code │ \-- api/ # API routes -|-- db/ # Database related files +|-- triplit/ # Database related files │ |-- schema.ts # Database schema -│ |-- migrate.ts # Migration runner -│ \-- migrations/ # Migration files +│ |-- client.ts # Interacts with the database on the client +│ \-- server.ts # Interacts with the database on the server \-- lib/ # Shared utilities ``` @@ -181,10 +175,12 @@ requirement. Key environment variables: -- `DATABASE_URL` - PostgreSQL connection string -- `BETTER_AUTH_SECRET` - Authentication secret -- `DISABLE_LOCAL_AUTH` - Disable email/password auth -- `DISABLE_SIGNUP` - Disable user registration +- `TRIPLIT_SERVICE_TOKEN` - Triplit service token (admin token. **SECRET**) +- `NUXT_TRIPLIT_ANON_TOKEN` - Triplit anonymous token (for anonymous access) +- `BETTER_AUTH_SECRET` - Authentication secret (for better-auth) +- `EXTERNAL_JWT_SECRET` - Will always be BETTER_AUTH_SECRET (used for + verifying JWT tokens from better-auth) +- `NUXT_PUBLIC_TRIPLIT_URL` - Triplit server URL ## Common Patterns diff --git a/BUGS.md b/BUGS.md new file mode 100644 index 0000000..fb73ab5 --- /dev/null +++ b/BUGS.md @@ -0,0 +1,29 @@ +# Known Bugs + +1. [ ] Occasionally, once in maybe 10 runs, triplit will make TWO connections to the backend. + I'm not entire sure why, I think its a race condition, but I'm not sure. + I _do not_ think that triplit-nuxt is the culprit, but I'm not sure. + +2. [ ] The logic to handle hovering over the sidebar is half-baked at best. On the + agents route, the back arrow sometimes stays full sized + +3. [ ] If you open the theme switcher on the sidenav then close it and re-open + it _without_ moving your mouse off of the sidenav, the agent button/dropdown + trigger will slowly crawl to the right (likely related to #2). + +4. [x] When navigating to different topics, or making a new topic, the page sort + of freezes but its not completely frozen? I think this was because of + page transitions + +5. [x] If you navigate from "/" to an agent, then navigate to topics, none of + the topic data is loaded. **This was a bug in the triplit-nuxt plugin.** + +6. [ ] Stop button showing when no generation + +7. [x] Sidenavs keep the overflow even if the lists are collapsed + +8. [ ] Sometimes the sidebar wont change views until you move your mouse off of the sidenav? + +9. [ ] ~~Sometimes on first page load, the message send button is on the left?~~ + If input was typed into the chat input **before hydation** the message send button + will be on the left. diff --git a/TODO.md b/TODO.md index 46b273c..ed12b3e 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,5 @@ # Todo -- [ ] Standardize on one icon set rather than 4 (lmao) +- [X] Standardize on one icon set rather than 4 (lmao) +- [ ] Make dropdowns a singleton component +- [ ] Make the sidebar better :kekdoggo:. It's annoying to manage across routes diff --git a/app/app.vue b/app/app.vue index 3e61c62..d54100a 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,29 +1,46 @@ \ No newline at end of file diff --git a/app/components/Markdown/ShikiHighlight.vue b/app/components/Markdown/ShikiHighlight.vue new file mode 100644 index 0000000..5fe1bd9 --- /dev/null +++ b/app/components/Markdown/ShikiHighlight.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/app/components/Message.vue b/app/components/Message.vue deleted file mode 100644 index cce9b7e..0000000 --- a/app/components/Message.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - \ No newline at end of file diff --git a/app/components/Message/Agent/Error.vue b/app/components/Message/Agent/Error.vue new file mode 100644 index 0000000..ca2c4d6 --- /dev/null +++ b/app/components/Message/Agent/Error.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/app/components/Message/Agent/Reasoning.vue b/app/components/Message/Agent/Reasoning.vue new file mode 100644 index 0000000..57f2bff --- /dev/null +++ b/app/components/Message/Agent/Reasoning.vue @@ -0,0 +1,85 @@ + + + + + \ No newline at end of file diff --git a/app/components/Message/Agent/Text.vue b/app/components/Message/Agent/Text.vue new file mode 100644 index 0000000..c9802fb --- /dev/null +++ b/app/components/Message/Agent/Text.vue @@ -0,0 +1,12 @@ + + + diff --git a/app/components/Message/Agent/Tool/Debug.vue b/app/components/Message/Agent/Tool/Debug.vue new file mode 100644 index 0000000..64955cf --- /dev/null +++ b/app/components/Message/Agent/Tool/Debug.vue @@ -0,0 +1,177 @@ + + + + + \ No newline at end of file diff --git a/app/components/Message/Agent/Tool/index.vue b/app/components/Message/Agent/Tool/index.vue new file mode 100644 index 0000000..65626fb --- /dev/null +++ b/app/components/Message/Agent/Tool/index.vue @@ -0,0 +1,64 @@ + + + diff --git a/app/components/Message/Agent/index.vue b/app/components/Message/Agent/index.vue new file mode 100644 index 0000000..47f4f10 --- /dev/null +++ b/app/components/Message/Agent/index.vue @@ -0,0 +1,55 @@ + + + diff --git a/app/components/Message/User.vue b/app/components/Message/User.vue new file mode 100644 index 0000000..6380ba4 --- /dev/null +++ b/app/components/Message/User.vue @@ -0,0 +1,13 @@ + + + diff --git a/app/components/Message/index.vue b/app/components/Message/index.vue new file mode 100644 index 0000000..dbc3242 --- /dev/null +++ b/app/components/Message/index.vue @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/app/components/ModelIcon.vue b/app/components/ModelIcon.vue new file mode 100644 index 0000000..2340122 --- /dev/null +++ b/app/components/ModelIcon.vue @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/app/components/ModelSelector.vue b/app/components/ModelSelector.vue new file mode 100644 index 0000000..acc1119 --- /dev/null +++ b/app/components/ModelSelector.vue @@ -0,0 +1,181 @@ + + + diff --git a/app/components/Settings/AIServiceProvider.vue b/app/components/Settings/AIServiceProvider.vue new file mode 100644 index 0000000..22f0e7d --- /dev/null +++ b/app/components/Settings/AIServiceProvider.vue @@ -0,0 +1,333 @@ + + + + + \ No newline at end of file diff --git a/app/components/Settings/Dialog.vue b/app/components/Settings/Dialog.vue new file mode 100644 index 0000000..b4317b5 --- /dev/null +++ b/app/components/Settings/Dialog.vue @@ -0,0 +1,125 @@ + + + diff --git a/app/components/Settings/GeneralSettings.vue b/app/components/Settings/GeneralSettings.vue new file mode 100644 index 0000000..7dfb5a9 --- /dev/null +++ b/app/components/Settings/GeneralSettings.vue @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/components/Settings/ProviderSettings.vue b/app/components/Settings/ProviderSettings.vue new file mode 100644 index 0000000..5698c8b --- /dev/null +++ b/app/components/Settings/ProviderSettings.vue @@ -0,0 +1,63 @@ + + + \ No newline at end of file diff --git a/app/components/Settings/ProviderSidebar.vue b/app/components/Settings/ProviderSidebar.vue new file mode 100644 index 0000000..bfb514f --- /dev/null +++ b/app/components/Settings/ProviderSidebar.vue @@ -0,0 +1,37 @@ + + + \ No newline at end of file diff --git a/app/components/SettingsDialog.vue b/app/components/SettingsDialog.vue deleted file mode 100644 index 987b386..0000000 --- a/app/components/SettingsDialog.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - diff --git a/app/components/Sidenav/Header.vue b/app/components/Sidenav/Header.vue index fb3529a..c3558cd 100644 --- a/app/components/Sidenav/Header.vue +++ b/app/components/Sidenav/Header.vue @@ -1,45 +1,61 @@