From bb83bb414de0c84f570d7ac4a78423f24f220c8e Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Sun, 8 Dec 2024 03:48:44 +0530 Subject: [PATCH] feat(git): import from url --- app/components/git/GitUrlImport.client.tsx | 106 +++++++++++++++++++++ app/routes/git.tsx | 23 +++++ 2 files changed, 129 insertions(+) create mode 100644 app/components/git/GitUrlImport.client.tsx create mode 100644 app/routes/git.tsx diff --git a/app/components/git/GitUrlImport.client.tsx b/app/components/git/GitUrlImport.client.tsx new file mode 100644 index 0000000..47ed708 --- /dev/null +++ b/app/components/git/GitUrlImport.client.tsx @@ -0,0 +1,106 @@ +import { useSearchParams } from '@remix-run/react'; +import { generateId, type Message } from 'ai'; +import ignore from 'ignore'; +import { useEffect, useState } from 'react'; +import { ClientOnly } from 'remix-utils/client-only'; +import { BaseChat } from '~/components/chat/BaseChat'; +import { Chat } from '~/components/chat/Chat.client'; +import { useGit } from '~/lib/hooks/useGit'; +import { useChatHistory } from '~/lib/persistence'; + +const IGNORE_PATTERNS = [ + 'node_modules/**', + '.git/**', + '.github/**', + '.vscode/**', + '**/*.jpg', + '**/*.jpeg', + '**/*.png', + 'dist/**', + 'build/**', + '.next/**', + 'coverage/**', + '.cache/**', + '.vscode/**', + '.idea/**', + '**/*.log', + '**/.DS_Store', + '**/npm-debug.log*', + '**/yarn-debug.log*', + '**/yarn-error.log*', + '**/*lock.json', + '**/*lock.yaml', +]; + +export function GitUrlImport() { + const [searchParams] = useSearchParams(); + const { ready: historyReady, importChat } = useChatHistory(); + const { ready: gitReady, gitClone } = useGit(); + const [imported, setImported] = useState(false); + + const importRepo = async (repoUrl?: string) => { + if (!gitReady && !historyReady) { + return; + } + + if (repoUrl) { + const ig = ignore().add(IGNORE_PATTERNS); + const { workdir, data } = await gitClone(repoUrl); + + if (importChat) { + const filePaths = Object.keys(data).filter((filePath) => !ig.ignores(filePath)); + console.log(filePaths); + + const textDecoder = new TextDecoder('utf-8'); + const message: Message = { + role: 'assistant', + content: `Cloning the repo ${repoUrl} into ${workdir} + + ${filePaths + .map((filePath) => { + const { data: content, encoding } = data[filePath]; + + if (encoding === 'utf8') { + return ` +${content} +`; + } else if (content instanceof Uint8Array) { + return ` +${textDecoder.decode(content)} +`; + } else { + return ''; + } + }) + .join('\n')} + `, + id: generateId(), + createdAt: new Date(), + }; + console.log(JSON.stringify(message)); + + importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, [message]); + + // console.log(files); + } + } + }; + + useEffect(() => { + if (!historyReady || !gitReady || imported) { + return; + } + + const url = searchParams.get('url'); + + if (!url) { + window.location.href = '/'; + return; + } + + importRepo(url); + setImported(true); + }, [searchParams, historyReady, gitReady, imported]); + + return }>{() => }; +} diff --git a/app/routes/git.tsx b/app/routes/git.tsx new file mode 100644 index 0000000..aa1689a --- /dev/null +++ b/app/routes/git.tsx @@ -0,0 +1,23 @@ +import type { LoaderFunctionArgs } from '@remix-run/cloudflare'; +import { json, type MetaFunction } from '@remix-run/cloudflare'; +import { ClientOnly } from 'remix-utils/client-only'; +import { BaseChat } from '~/components/chat/BaseChat'; +import { GitUrlImport } from '~/components/git/GitUrlImport.client'; +import { Header } from '~/components/header/Header'; + +export const meta: MetaFunction = () => { + return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }]; +}; + +export async function loader(args: LoaderFunctionArgs) { + return json({ url: args.params.url }); +} + +export default function Index() { + return ( +
+
+ }>{() => } +
+ ); +}