diff --git a/packages/supabase/chart/templates/uds-package.yaml b/packages/supabase/chart/templates/uds-package.yaml index 2f12f6029..4802f3bea 100644 --- a/packages/supabase/chart/templates/uds-package.yaml +++ b/packages/supabase/chart/templates/uds-package.yaml @@ -4,7 +4,7 @@ metadata: name: {{ .Values.leapfrogai.package.name }} spec: sso: - - name: Supabase + - name: Leapfrog AI description: Client for logging into Supabase clientId: {{ .Values.leapfrogai.sso.clientId }} redirectUris: diff --git a/packages/supabase/migrations/20240322174521_ui_sql_schema.sql b/packages/supabase/migrations/20240322174521_ui_sql_schema.sql index ce4438a5b..15abee1bf 100644 --- a/packages/supabase/migrations/20240322174521_ui_sql_schema.sql +++ b/packages/supabase/migrations/20240322174521_ui_sql_schema.sql @@ -1,149 +1,94 @@ +-- Create tables create table conversations ( - id uuid primary key DEFAULT uuid_generate_v4(), - user_id uuid references auth.users not null, - label text, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null + id uuid primary key DEFAULT uuid_generate_v4(), + user_id uuid references auth.users not null, + label text, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null ); - create table messages ( - id uuid primary key DEFAULT uuid_generate_v4(), - user_id uuid references auth.users not null, - conversation_id uuid references conversations on delete cascade not null, - role text check (role in ('system', 'user', 'assistant', 'function', 'data', 'tool')), - content text, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null + id uuid primary key DEFAULT uuid_generate_v4(), + user_id uuid references auth.users not null, + conversation_id uuid references conversations on delete cascade not null, + role text check (role in ('system', 'user', 'assistant', 'function', 'data', 'tool')), + content text, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null ); --- Create a table for public profiles + create table profiles ( - id uuid references auth.users not null primary key, - updated_at timestamp with time zone, - username text unique, - full_name text, - avatar_url text, - website text, - - constraint username_length check (char_length(username) >= 3) + id uuid references auth.users not null primary key, + updated_at timestamp with time zone, + username text unique, + full_name text, + avatar_url text, + website text, + constraint username_length check (char_length(username) >= 3) ); -alter table conversations enable row level security; - -alter table messages enable row level security; - -alter table profiles enable row level security; - --- Policies for conversations -create policy "Individuals can create conversations." on conversations for - insert with check (auth.uid() = user_id); -create policy "Individuals can view their own conversations. " on conversations for - select using (auth.uid() = user_id); -create policy "Individuals can update their own conversations." on conversations for - update using (auth.uid() = user_id); -create policy "Individuals can delete their own conversations." on conversations for - delete using (auth.uid() = user_id); - --- Policies for messages -create policy "Individuals can view their own messages." on messages for - select using (auth.uid() = user_id); -create policy "Individuals can create messages." on messages for - insert with check (auth.uid() = user_id); -create policy "Individuals can update their own messages." on messages for - update using (auth.uid() = user_id); -create policy "Individuals can delete their own messages." on messages for - delete using (auth.uid() = user_id); - --- Policies for profiles -create policy "Public profiles are viewable by everyone." on profiles - for select using (true); - -create policy "Users can insert their own profile." on profiles - for insert with check (auth.uid() = id); - -create policy "Users can update own profile." on profiles - for update using (auth.uid() = id); - --- Set up access controls for storage. --- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details. -create policy "Avatar images are publicly accessible." on storage.objects - for select using (bucket_id = 'avatars'); - -create policy "Anyone can upload an avatar." on storage.objects - for insert with check (bucket_id = 'avatars'); - -create policy "Anyone can update their own avatar." on storage.objects - for update using (auth.uid() = owner) with check (bucket_id = 'avatars'); - - --- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. --- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. -create function public.handle_new_user() -returns trigger as $$ -begin - insert into public.profiles (id, full_name, avatar_url) - values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); - return new; -end; -$$ language plpgsql security definer; -create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); +create table assistants ( + id uuid primary key DEFAULT uuid_generate_v4(), + object text check (object in ('assistant')), + name varchar(255), + description varchar(512), + model varchar(255) not null, + instructions TEXT, + tools jsonb, + tool_resources jsonb, + metadata jsonb, + temperature float, + top_p float, + response_format jsonb, + created_at timestamp with time zone default timezone('utc'::text, now()) not null +); -- Set up Storage! +insert into storage.buckets +(id, name, public) +values + ('assistant_avatars', 'assistant_avatars', true); + +-- These are user profiles avatars, currently not used by app and will be removed soon insert into storage.buckets (id, name) - values ('avatars', 'avatars'); +values ('avatars', 'avatars'); +-- RLS policies alter table conversations enable row level security; - alter table messages enable row level security; - alter table profiles enable row level security; +alter table assistants enable row level security; -- Policies for conversations create policy "Individuals can create conversations." on conversations for insert with check (auth.uid() = user_id); create policy "Individuals can view their own conversations. " on conversations for - select using (auth.uid() = user_id); +select using (auth.uid() = user_id); create policy "Individuals can update their own conversations." on conversations for - update using (auth.uid() = user_id); +update using (auth.uid() = user_id); create policy "Individuals can delete their own conversations." on conversations for delete using (auth.uid() = user_id); -- Policies for messages create policy "Individuals can view their own messages." on messages for - select using (auth.uid() = user_id); +select using (auth.uid() = user_id); create policy "Individuals can create messages." on messages for insert with check (auth.uid() = user_id); create policy "Individuals can update their own messages." on messages for - update using (auth.uid() = user_id); +update using (auth.uid() = user_id); create policy "Individuals can delete their own messages." on messages for delete using (auth.uid() = user_id); -- Policies for profiles create policy "Public profiles are viewable by everyone." on profiles for select using (true); - create policy "Users can insert their own profile." on profiles for insert with check (auth.uid() = id); - create policy "Users can update own profile." on profiles for update using (auth.uid() = id); --- Set up access controls for storage. --- See https://supabase.com/docs/guides/storage/security/access-control#policy-examples for more details. -create policy "Avatar images are publicly accessible." on storage.objects - for select using (bucket_id = 'avatars'); - -create policy "Anyone can upload an avatar." on storage.objects - for insert with check (bucket_id = 'avatars'); - -create policy "Anyone can update their own avatar." on storage.objects - for update using (auth.uid() = owner) with check (bucket_id = 'avatars'); - - -- Policies for assistants -CREATE POLICY "Individuals can view their own assistants." ON assistants -FOR SELECT USING ((metadata ->> 'created_by') = auth.uid()::text); +create policy "Individuals can view their own assistants." ON assistants +for select using ((metadata ->> 'created_by') = auth.uid()::text); create policy "Individuals can create assistants." on assistants for insert with check ((metadata ->> 'created_by') = auth.uid()::text); create policy "Individuals can update their own assistants." on assistants for @@ -151,38 +96,29 @@ update using ((metadata ->> 'created_by') = auth.uid()::text); create policy "Individuals can delete their own assistants." on assistants for delete using ((metadata ->> 'created_by') = auth.uid()::text); +-- Policies for storage. +create policy "Avatar images are publicly accessible." on storage.objects + for select using (bucket_id = 'avatars'); +create policy "Anyone can upload an avatar." on storage.objects + for insert with check (bucket_id = 'avatars'); +create policy "Anyone can update their own avatar." on storage.objects + for update using (auth.uid() = owner) with check (bucket_id = 'avatars'); + +create policy "Anyone can upload an assistant avatar." on storage.objects + for insert with check (bucket_id = 'assistant_avatars'); -- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. -- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. create function public.handle_new_user() -returns trigger as $$ + returns trigger as $$ begin - insert into public.profiles (id, full_name, avatar_url) - values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); - return new; +insert into public.profiles (id, full_name, avatar_url) +values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); +return new; end; $$ language plpgsql security definer; create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); + after insert on auth.users + for each row execute procedure public.handle_new_user(); + --- Set up Storage! -insert into storage.buckets (id, name) - values ('avatars', 'avatars'); - - -CREATE TABLE Assistants ( - id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), - object text CHECK (object in ('assistant')), - name VARCHAR(255), - description VARCHAR(512), - model VARCHAR(255) NOT NULL, - instructions TEXT, - tools jsonb, - tool_resources jsonb, - metadata jsonb, - temperature FLOAT, - top_p FLOAT, - response_format jsonb, - created_at timestamp with time zone default timezone('utc'::text, now()) not null -); diff --git a/src/leapfrogai_ui/.env.example b/src/leapfrogai_ui/.env.example index 00ccd6d57..9a87b587c 100644 --- a/src/leapfrogai_ui/.env.example +++ b/src/leapfrogai_ui/.env.example @@ -1,5 +1,5 @@ # PUBLIC DYNAMIC -PUBLIC_SUPABASE_URL=http://localhost:54321 +PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0 PUBLIC_DISABLE_KEYCLOAK=false PUBLIC_MESSAGE_LENGTH_LIMIT=10000 diff --git a/src/leapfrogai_ui/package-lock.json b/src/leapfrogai_ui/package-lock.json index e5f239324..fa32efacf 100644 --- a/src/leapfrogai_ui/package-lock.json +++ b/src/leapfrogai_ui/package-lock.json @@ -8,6 +8,7 @@ "name": "leapfrogai-ui", "version": "0.0.1", "dependencies": { + "@carbon/colors": "^11.21.0", "@carbon/layout": "^11.20.0", "@carbon/themes": "^11.32.0", "@carbon/type": "^11.26.0", @@ -18,6 +19,7 @@ "@sveltejs/vite-plugin-svelte": "^3.1.0", "@testing-library/user-event": "^14.5.2", "ai": "^3.0.13", + "carbon-pictograms-svelte": "^12.10.0", "concurrently": "^8.2.2", "fuse.js": "^7.0.0", "msw": "^2.2.14", @@ -3193,6 +3195,11 @@ "integrity": "sha512-tw5jUSASVfdZ30CcynKWwQalkUIn3I2OFKvyormaoNH6bWjtXp21ESqDSuZ0RgZbxzaeBoUJaEJpsSTX5YjElA==", "dev": true }, + "node_modules/carbon-pictograms-svelte": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/carbon-pictograms-svelte/-/carbon-pictograms-svelte-12.10.0.tgz", + "integrity": "sha512-DPt6HRn7J8/vXTwIhtNq4VLfftS9BGeWxR1aJjHOzPkHBSooBy7SeUQK1BGJSIb/X5x3Plemq6TSBMlzvQdpbA==" + }, "node_modules/carbon-preprocess-svelte": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/carbon-preprocess-svelte/-/carbon-preprocess-svelte-0.11.0.tgz", @@ -4059,9 +4066,9 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.38.0.tgz", - "integrity": "sha512-IwwxhHzitx3dr0/xo0z4jjDlb2AAHBPKt+juMyKKGTLlKi1rZfA4qixMwnveU20/JTHyipM6keX4Vr7LZFYc9g==", + "version": "2.39.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.39.0.tgz", + "integrity": "sha512-FXktBLXsrxbA+6ZvJK2z/sQOrUKyzSg3fNWK5h0reSCjr2fjAsc9ai/s/JvSl4Hgvz3nYVtTIMwarZH5RcB7BA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -4069,13 +4076,13 @@ "debug": "^4.3.4", "eslint-compat-utils": "^0.5.0", "esutils": "^2.0.3", - "known-css-properties": "^0.30.0", + "known-css-properties": "^0.31.0", "postcss": "^8.4.38", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.0.16", "semver": "^7.6.0", - "svelte-eslint-parser": ">=0.35.0 <1.0.0" + "svelte-eslint-parser": ">=0.36.0 <1.0.0" }, "engines": { "node": "^14.17.0 || >=16.0.0" @@ -5492,9 +5499,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", - "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz", + "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==", "dev": true }, "node_modules/levn": { diff --git a/src/leapfrogai_ui/package.json b/src/leapfrogai_ui/package.json index 2834bceee..14157a696 100644 --- a/src/leapfrogai_ui/package.json +++ b/src/leapfrogai_ui/package.json @@ -60,6 +60,7 @@ }, "type": "module", "dependencies": { + "@carbon/colors": "^11.21.0", "@carbon/layout": "^11.20.0", "@carbon/themes": "^11.32.0", "@carbon/type": "^11.26.0", @@ -70,6 +71,7 @@ "@sveltejs/vite-plugin-svelte": "^3.1.0", "@testing-library/user-event": "^14.5.2", "ai": "^3.0.13", + "carbon-pictograms-svelte": "^12.10.0", "concurrently": "^8.2.2", "fuse.js": "^7.0.0", "msw": "^2.2.14", diff --git a/src/leapfrogai_ui/src/lib/components/AssistantAvatar.svelte b/src/leapfrogai_ui/src/lib/components/AssistantAvatar.svelte new file mode 100644 index 000000000..7f697b559 --- /dev/null +++ b/src/leapfrogai_ui/src/lib/components/AssistantAvatar.svelte @@ -0,0 +1,243 @@ + + +