codacus commited on
Commit
bb83bb4
·
1 Parent(s): 83d201a

feat(git): import from url

Browse files
app/components/git/GitUrlImport.client.tsx ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useSearchParams } from '@remix-run/react';
2
+ import { generateId, type Message } from 'ai';
3
+ import ignore from 'ignore';
4
+ import { useEffect, useState } from 'react';
5
+ import { ClientOnly } from 'remix-utils/client-only';
6
+ import { BaseChat } from '~/components/chat/BaseChat';
7
+ import { Chat } from '~/components/chat/Chat.client';
8
+ import { useGit } from '~/lib/hooks/useGit';
9
+ import { useChatHistory } from '~/lib/persistence';
10
+
11
+ const IGNORE_PATTERNS = [
12
+ 'node_modules/**',
13
+ '.git/**',
14
+ '.github/**',
15
+ '.vscode/**',
16
+ '**/*.jpg',
17
+ '**/*.jpeg',
18
+ '**/*.png',
19
+ 'dist/**',
20
+ 'build/**',
21
+ '.next/**',
22
+ 'coverage/**',
23
+ '.cache/**',
24
+ '.vscode/**',
25
+ '.idea/**',
26
+ '**/*.log',
27
+ '**/.DS_Store',
28
+ '**/npm-debug.log*',
29
+ '**/yarn-debug.log*',
30
+ '**/yarn-error.log*',
31
+ '**/*lock.json',
32
+ '**/*lock.yaml',
33
+ ];
34
+
35
+ export function GitUrlImport() {
36
+ const [searchParams] = useSearchParams();
37
+ const { ready: historyReady, importChat } = useChatHistory();
38
+ const { ready: gitReady, gitClone } = useGit();
39
+ const [imported, setImported] = useState(false);
40
+
41
+ const importRepo = async (repoUrl?: string) => {
42
+ if (!gitReady && !historyReady) {
43
+ return;
44
+ }
45
+
46
+ if (repoUrl) {
47
+ const ig = ignore().add(IGNORE_PATTERNS);
48
+ const { workdir, data } = await gitClone(repoUrl);
49
+
50
+ if (importChat) {
51
+ const filePaths = Object.keys(data).filter((filePath) => !ig.ignores(filePath));
52
+ console.log(filePaths);
53
+
54
+ const textDecoder = new TextDecoder('utf-8');
55
+ const message: Message = {
56
+ role: 'assistant',
57
+ content: `Cloning the repo ${repoUrl} into ${workdir}
58
+ <boltArtifact id="imported-files" title="Git Cloned Files" type="bundled" >
59
+ ${filePaths
60
+ .map((filePath) => {
61
+ const { data: content, encoding } = data[filePath];
62
+
63
+ if (encoding === 'utf8') {
64
+ return `<boltAction type="file" filePath="${filePath}">
65
+ ${content}
66
+ </boltAction>`;
67
+ } else if (content instanceof Uint8Array) {
68
+ return `<boltAction type="file" filePath="${filePath}">
69
+ ${textDecoder.decode(content)}
70
+ </boltAction>`;
71
+ } else {
72
+ return '';
73
+ }
74
+ })
75
+ .join('\n')}
76
+ </boltArtifact>`,
77
+ id: generateId(),
78
+ createdAt: new Date(),
79
+ };
80
+ console.log(JSON.stringify(message));
81
+
82
+ importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, [message]);
83
+
84
+ // console.log(files);
85
+ }
86
+ }
87
+ };
88
+
89
+ useEffect(() => {
90
+ if (!historyReady || !gitReady || imported) {
91
+ return;
92
+ }
93
+
94
+ const url = searchParams.get('url');
95
+
96
+ if (!url) {
97
+ window.location.href = '/';
98
+ return;
99
+ }
100
+
101
+ importRepo(url);
102
+ setImported(true);
103
+ }, [searchParams, historyReady, gitReady, imported]);
104
+
105
+ return <ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>;
106
+ }
app/routes/git.tsx ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { LoaderFunctionArgs } from '@remix-run/cloudflare';
2
+ import { json, type MetaFunction } from '@remix-run/cloudflare';
3
+ import { ClientOnly } from 'remix-utils/client-only';
4
+ import { BaseChat } from '~/components/chat/BaseChat';
5
+ import { GitUrlImport } from '~/components/git/GitUrlImport.client';
6
+ import { Header } from '~/components/header/Header';
7
+
8
+ export const meta: MetaFunction = () => {
9
+ return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];
10
+ };
11
+
12
+ export async function loader(args: LoaderFunctionArgs) {
13
+ return json({ url: args.params.url });
14
+ }
15
+
16
+ export default function Index() {
17
+ return (
18
+ <div className="flex flex-col h-full w-full">
19
+ <Header />
20
+ <ClientOnly fallback={<BaseChat />}>{() => <GitUrlImport />}</ClientOnly>
21
+ </div>
22
+ );
23
+ }