AI-powered tool for analyzing GitHub files and solving issues. Supports 20+ languages.
git clone https://github.com/akramcodez/osfit.git
cd osfit
npm installCreate .env.local:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key SUPABASE_SERVICE_ROLE_KEY=your_service_role_key ENCRYPTION_SECRET=your_32_character_secret_key # Required: Choose ONE AI provider GEMINI_API_KEY=your_gemini_key # OR GROQ_API_KEY=your_groq_key # Optional: For better GitHub content fetching APIFY_API_KEY=your_apify_key # Optional: For translating app's content in multiple languages (fallback uses Gemini) LINGO_API_KEY=your_lingo_key
Minimal setup requires Supabase + one AI key (Gemini or Groq). Add Apify for better file/issue analysis. Add Lingo for professional translations for app's every component.
Note: This app uses:
- multilingual-github-scraper Apify actor for fetching GitHub content
- Lingo for localizing app text in multiple languages
Run these SQL queries in your Supabase SQL Editor:
Show SQL schema
-- Enable gen_random_uuid() CREATE EXTENSION IF NOT EXISTS pgcrypto; -- Tables (unchanged) CREATE TABLE IF NOT EXISTS public.profiles ( id uuid NOT NULL, username text NOT NULL UNIQUE, created_at timestamp with time zone DEFAULT now(), CONSTRAINT profiles_pkey PRIMARY KEY (id), CONSTRAINT profiles_id_fkey FOREIGN KEY (id) REFERENCES auth.users(id) ); CREATE TABLE IF NOT EXISTS public.chat_sessions ( id uuid NOT NULL DEFAULT gen_random_uuid(), session_token text NOT NULL UNIQUE, created_at timestamp without time zone DEFAULT now(), last_active timestamp without time zone DEFAULT now(), title text, user_id uuid, mode text DEFAULT 'mentor'::text, CONSTRAINT chat_sessions_pkey PRIMARY KEY (id), CONSTRAINT chat_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.profiles(id) ); CREATE TABLE IF NOT EXISTS public.messages ( id uuid NOT NULL DEFAULT gen_random_uuid(), session_id uuid, role text NOT NULL CHECK (role = ANY (ARRAY['user'::text, 'assistant'::text, 'system'::text])), content text NOT NULL, metadata jsonb DEFAULT '{}'::jsonb, created_at timestamp without time zone DEFAULT now(), CONSTRAINT messages_pkey PRIMARY KEY (id), CONSTRAINT messages_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.chat_sessions(id) ); CREATE TABLE IF NOT EXISTS public.file_explanations ( id uuid NOT NULL DEFAULT gen_random_uuid(), session_id uuid, role text NOT NULL CHECK (role = ANY (ARRAY['user'::text, 'assistant'::text])), file_url text, file_path text, file_content text, language text, explanation text, created_at timestamp with time zone DEFAULT now(), metadata jsonb DEFAULT '{}'::jsonb, flowchart text, CONSTRAINT file_explanations_pkey PRIMARY KEY (id), CONSTRAINT file_explanations_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.chat_sessions(id) ); CREATE TABLE IF NOT EXISTS public.issue_solutions ( id uuid NOT NULL DEFAULT gen_random_uuid(), session_id uuid, created_at timestamp with time zone DEFAULT now(), issue_url text, issue_title text, issue_body text, explanation text, solution_plan text, git_diff text, pr_title text, pr_description text, current_step text DEFAULT 'issue_input'::text, issue_labels text, pr_solution text, pr_files_changed text, status text DEFAULT 'in_progress'::text, role text DEFAULT 'assistant'::text, metadata jsonb, CONSTRAINT issue_solutions_pkey PRIMARY KEY (id), CONSTRAINT issue_solutions_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.chat_sessions(id) ); CREATE TABLE IF NOT EXISTS public.user_api_keys ( id uuid NOT NULL DEFAULT gen_random_uuid(), user_id uuid NOT NULL UNIQUE, gemini_key_encrypted text, apify_key_encrypted text, lingo_key_encrypted text, created_at timestamp with time zone DEFAULT now(), updated_at timestamp with time zone DEFAULT now(), openai_key_encrypted text, claude_key_encrypted text, grok_key_encrypted text, selected_ai_provider text DEFAULT 'gemini'::text, groq_key text, ai_provider text DEFAULT 'gemini'::text, groq_key_encrypted text, preferred_language text DEFAULT 'en'::text, CONSTRAINT user_api_keys_pkey PRIMARY KEY (id), CONSTRAINT user_api_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ); -- Enable RLS ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE public.chat_sessions ENABLE ROW LEVEL SECURITY; ALTER TABLE public.messages ENABLE ROW LEVEL SECURITY; ALTER TABLE public.file_explanations ENABLE ROW LEVEL SECURITY; ALTER TABLE public.issue_solutions ENABLE ROW LEVEL SECURITY; ALTER TABLE public.user_api_keys ENABLE ROW LEVEL SECURITY; -- Idempotent policy creation: check pg_policies then CREATE if missing DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'profiles' AND policyname = 'users_can_view_own_profile' ) THEN CREATE POLICY users_can_view_own_profile ON public.profiles FOR SELECT USING ((SELECT auth.uid()) = id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'profiles' AND policyname = 'users_can_insert_own_profile' ) THEN CREATE POLICY users_can_insert_own_profile ON public.profiles FOR INSERT WITH CHECK ((SELECT auth.uid()) = id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'profiles' AND policyname = 'users_can_update_own_profile' ) THEN CREATE POLICY users_can_update_own_profile ON public.profiles FOR UPDATE USING ((SELECT auth.uid()) = id) WITH CHECK ((SELECT auth.uid()) = id); END IF; -- chat_sessions IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'chat_sessions' AND policyname = 'users_can_view_own_sessions' ) THEN CREATE POLICY users_can_view_own_sessions ON public.chat_sessions FOR SELECT USING ((SELECT auth.uid()) = user_id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'chat_sessions' AND policyname = 'users_can_insert_own_sessions' ) THEN CREATE POLICY users_can_insert_own_sessions ON public.chat_sessions FOR INSERT WITH CHECK ((SELECT auth.uid()) = user_id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'chat_sessions' AND policyname = 'users_can_delete_own_sessions' ) THEN CREATE POLICY users_can_delete_own_sessions ON public.chat_sessions FOR DELETE USING ((SELECT auth.uid()) = user_id); END IF; -- messages IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'messages' AND policyname = 'users_can_view_own_messages' ) THEN CREATE POLICY users_can_view_own_messages ON public.messages FOR SELECT USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = messages.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'messages' AND policyname = 'users_can_insert_own_messages' ) THEN CREATE POLICY users_can_insert_own_messages ON public.messages FOR INSERT WITH CHECK ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = messages.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'messages' AND policyname = 'users_can_delete_own_messages' ) THEN CREATE POLICY users_can_delete_own_messages ON public.messages FOR DELETE USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = messages.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; -- file_explanations IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'file_explanations' AND policyname = 'users_can_view_own_file_explanations' ) THEN CREATE POLICY users_can_view_own_file_explanations ON public.file_explanations FOR SELECT USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = file_explanations.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'file_explanations' AND policyname = 'users_can_insert_own_file_explanations' ) THEN CREATE POLICY users_can_insert_own_file_explanations ON public.file_explanations FOR INSERT WITH CHECK ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = file_explanations.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'file_explanations' AND policyname = 'users_can_delete_own_file_explanations' ) THEN CREATE POLICY users_can_delete_own_file_explanations ON public.file_explanations FOR DELETE USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = file_explanations.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; -- issue_solutions IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'issue_solutions' AND policyname = 'users_can_view_own_issue_solutions' ) THEN CREATE POLICY users_can_view_own_issue_solutions ON public.issue_solutions FOR SELECT USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = issue_solutions.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'issue_solutions' AND policyname = 'users_can_insert_own_issue_solutions' ) THEN CREATE POLICY users_can_insert_own_issue_solutions ON public.issue_solutions FOR INSERT WITH CHECK ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = issue_solutions.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'issue_solutions' AND policyname = 'users_can_update_own_issue_solutions' ) THEN CREATE POLICY users_can_update_own_issue_solutions ON public.issue_solutions FOR UPDATE USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = issue_solutions.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'issue_solutions' AND policyname = 'users_can_delete_own_issue_solutions' ) THEN CREATE POLICY users_can_delete_own_issue_solutions ON public.issue_solutions FOR DELETE USING ( EXISTS ( SELECT 1 FROM public.chat_sessions cs WHERE cs.id = issue_solutions.session_id AND cs.user_id = (SELECT auth.uid()) ) ); END IF; -- user_api_keys IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'user_api_keys' AND policyname = 'users_can_view_own_api_keys' ) THEN CREATE POLICY users_can_view_own_api_keys ON public.user_api_keys FOR SELECT USING ((SELECT auth.uid()) = user_id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'user_api_keys' AND policyname = 'users_can_insert_own_api_keys' ) THEN CREATE POLICY users_can_insert_own_api_keys ON public.user_api_keys FOR INSERT WITH CHECK ((SELECT auth.uid()) = user_id); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_policies WHERE schemaname = 'public' AND tablename = 'user_api_keys' AND policyname = 'users_can_update_own_api_keys' ) THEN CREATE POLICY users_can_update_own_api_keys ON public.user_api_keys FOR UPDATE USING ((SELECT auth.uid()) = user_id) WITH CHECK ((SELECT auth.uid()) = user_id); END IF; END $$;
Run:
npm run dev
Next.js 16, TypeScript, Supabase, Gemini/Groq AI, Tailwind CSS
MIT