codacus commited on
Commit
e6ed210
·
1 Parent(s): 7fc8e40

work in progress poc git import

Browse files
app/components/chat/BaseChat.tsx CHANGED
@@ -18,6 +18,8 @@ import Cookies from 'js-cookie';
18
 
19
  import styles from './BaseChat.module.scss';
20
  import type { ProviderInfo } from '~/utils/types';
 
 
21
 
22
  const EXAMPLE_PROMPTS = [
23
  { text: 'Build a todo app in React using Tailwind' },
@@ -208,6 +210,9 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
208
  },
209
  )}
210
  >
 
 
 
211
  <ModelSelector
212
  key={provider?.name + ':' + modelList.length}
213
  model={model}
 
18
 
19
  import styles from './BaseChat.module.scss';
20
  import type { ProviderInfo } from '~/utils/types';
21
+ import GitCloneButton from './GitCloneButton';
22
+ import * as Separator from '@radix-ui/react-separator';
23
 
24
  const EXAMPLE_PROMPTS = [
25
  { text: 'Build a todo app in React using Tailwind' },
 
210
  },
211
  )}
212
  >
213
+ <GitCloneButton />
214
+ <Separator.Root className="my-[15px] bg-gray6 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px"/>
215
+ <div className="flex items-center gap-3"></div>
216
  <ModelSelector
217
  key={provider?.name + ':' + modelList.length}
218
  model={model}
app/components/chat/GitCloneButton.tsx ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { IconButton } from '../ui/IconButton'
2
+ import git from 'isomorphic-git'
3
+ import http from 'isomorphic-git/http/web'
4
+ import { useGit } from '~/lib/hooks/useGit'
5
+
6
+ export default function GitCloneButton() {
7
+ const {ready,gitClone} = useGit()
8
+ const onClick= async(e:any)=>{
9
+ if (!ready) return
10
+ let repoUrl=prompt("Enter the Git url")
11
+ if (repoUrl) {
12
+ await gitClone(repoUrl)
13
+ }
14
+ }
15
+ return (
16
+ <IconButton onClick={e=>{
17
+ onClick(e)
18
+
19
+ }} className="w-full justify-center" title="Clone A Git Repo">
20
+ <span className="mr-2 text-xs lg:text-sm">Clone A Git Repo</span>
21
+ <div className='i-ph:git-branch' />
22
+ </IconButton>
23
+ )
24
+ }
app/lib/hooks/useGit.ts ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { WebContainer,FileSystemAPI } from "@webcontainer/api";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import { webcontainer as webcontainerPromise } from "~/lib/webcontainer";
4
+ import git, { type PromiseFsClient } from 'isomorphic-git'
5
+ import http from 'isomorphic-git/http/web'
6
+ import Cookies from 'js-cookie';
7
+
8
+
9
+
10
+
11
+ export function useGit() {
12
+ const [ready, setReady] = useState(false);
13
+ const [webcontainer, setWebcontainer] = useState<WebContainer>();
14
+ const [fs, setFs] = useState<PromiseFsClient>();
15
+ const lookupSavedPassword=(url:string)=>{
16
+ try {
17
+
18
+ // Save updated API keys to cookies with 30 day expiry and secure settings
19
+ let creds=Cookies.get(`git:${url}`);
20
+
21
+ if (creds) {
22
+ const parsedCreds = JSON.parse(creds);
23
+
24
+ if (typeof parsedCreds === 'object' && parsedCreds !== null) {
25
+ return parsedCreds
26
+ }
27
+ }
28
+ return;
29
+
30
+ } catch (error) {
31
+ console.error('Error saving API keys to cookies:', error);
32
+ return;
33
+ }
34
+ }
35
+ useEffect(()=>{
36
+ webcontainerPromise.then(container=>{
37
+ setWebcontainer(container);
38
+ setFs(getFs(container));
39
+ setReady(true);
40
+ })
41
+ },[])
42
+
43
+ const gitClone= useCallback(async (url:string)=>{
44
+ if (!webcontainer||!fs||!ready) {
45
+ return;
46
+ }
47
+ let repo = await git.clone({
48
+ fs,
49
+ http,
50
+ dir: webcontainer.workdir,
51
+ url: url,
52
+ depth: 1,
53
+ singleBranch: true,
54
+ corsProxy: 'https://cors.isomorphic-git.org',
55
+ onAuth: url => {
56
+ let auth = lookupSavedPassword(url)
57
+ if (auth) return auth
58
+
59
+ if (confirm('This repo is password protected. Ready to enter a username & password?')) {
60
+ auth = {
61
+ username: prompt('Enter username'),
62
+ password: prompt('Enter password'),
63
+ }
64
+ return auth
65
+ } else {
66
+ return { cancel: true }
67
+ }
68
+ }
69
+ })
70
+ console.log(repo)
71
+ }, [webcontainer])
72
+ return {ready,gitClone}
73
+ }
74
+
75
+
76
+ interface IFS{
77
+ promises:{
78
+ readFile: PromiseFsClient['promises']['readFile'];
79
+ writeFile: PromiseFsClient['promises']['writeFile'];
80
+ mkdir:FileSystemAPI['mkdir'];
81
+ readdir:FileSystemAPI['readdir'];
82
+ rm:FileSystemAPI['rm'];
83
+ unlink(path: string): Promise<void>;
84
+ stat(path: string): Promise<any>;
85
+ lstat(path: string): Promise<any>;
86
+ rmdir(path: string): Promise<void>;
87
+ readlink?(path: string): Promise<string>;
88
+ symlink?(target: string, path: string): Promise<void>;
89
+ chmod?(path: string, mode: number): Promise<void>;
90
+ }
91
+ }
92
+ const getFs: (c: WebContainer) => PromiseFsClient = (webcontainer: WebContainer)=> ({
93
+ promises:{
94
+ readFile: async (path: string, options: any) => {
95
+ let encoding = options.encoding;
96
+ let relativePath = pathUtils.relative(webcontainer.workdir,path);
97
+ console.log('readFile', relativePath, encoding);
98
+ return await webcontainer.fs.readFile(relativePath,encoding);
99
+ },
100
+ writeFile: async (path: string, data: any, options: any) => {
101
+ let encoding = options.encoding;
102
+ let relativePath = pathUtils.relative(webcontainer.workdir,path);
103
+ console.log('writeFile', {relativePath,data,encoding});
104
+ return await webcontainer.fs.writeFile(relativePath, data, { ...options,encoding});
105
+ },
106
+ mkdir: async (path: string, options: any) => {
107
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
108
+ console.log('mkdir', relativePath,options);
109
+ return await webcontainer.fs.mkdir(relativePath,{...options,recursive:true})
110
+ },
111
+ readdir: async (path: string,options:any) => {
112
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
113
+ console.log('readdir', relativePath,options);
114
+ return await webcontainer.fs.readdir(relativePath,options)
115
+ },
116
+ rm: async (path: string,options:any) => {
117
+
118
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
119
+ console.log('rm', relativePath,options);
120
+
121
+ return await webcontainer.fs.rm(relativePath, { ...options||{} })
122
+ },
123
+ rmdir: async (path: string,options:any) => {
124
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
125
+ console.log('rmdir', relativePath, options);
126
+ return await webcontainer.fs.rm(relativePath, { recursive: true,...options})
127
+ },
128
+
129
+ // Mock implementations for missing functions
130
+ unlink: async (path: string) => {
131
+ // unlink is just removing a single file
132
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
133
+ return await webcontainer.fs.rm(relativePath, { recursive: false });
134
+ },
135
+
136
+ stat: async (path: string) => {
137
+ try {
138
+ let relativePath = pathUtils.relative(webcontainer.workdir, path);
139
+ let resp = await webcontainer.fs.readdir(pathUtils.dirname(relativePath),{withFileTypes:true})
140
+ let name = pathUtils.basename(relativePath)
141
+ let fileInfo=resp.find(x=>x.name==name)
142
+ if(!fileInfo){
143
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
144
+ }
145
+ return {
146
+ isFile: () => fileInfo.isFile(),
147
+ isDirectory: () => fileInfo.isDirectory(),
148
+ isSymbolicLink: () => false,
149
+ size: 1,
150
+ mode: 0o666, // Default permissions
151
+ mtimeMs: Date.now(),
152
+ uid: 1000,
153
+ gid: 1000
154
+ };
155
+ } catch (error) {
156
+ const err = new Error(`ENOENT: no such file or directory, stat '${path}'`) as NodeJS.ErrnoException;
157
+ err.code = 'ENOENT';
158
+ err.errno = -2;
159
+ err.syscall = 'stat';
160
+ err.path = path;
161
+ throw err;
162
+ }
163
+ },
164
+
165
+ lstat: async (path: string) => {
166
+ // For basic usage, lstat can return the same as stat
167
+ // since we're not handling symbolic links
168
+ return await getFs(webcontainer).promises.stat(path);
169
+ },
170
+
171
+ readlink: async (path: string) => {
172
+ // Since WebContainer doesn't support symlinks,
173
+ // we'll throw a "not a symbolic link" error
174
+ throw new Error(`EINVAL: invalid argument, readlink '${path}'`);
175
+ },
176
+
177
+ symlink: async (target: string, path: string) => {
178
+ // Since WebContainer doesn't support symlinks,
179
+ // we'll throw a "operation not supported" error
180
+ throw new Error(`EPERM: operation not permitted, symlink '${target}' -> '${path}'`);
181
+ },
182
+
183
+ chmod: async (path: string, mode: number) => {
184
+ // WebContainer doesn't support changing permissions,
185
+ // but we can pretend it succeeded for compatibility
186
+ return await Promise.resolve();
187
+ }
188
+ }
189
+ })
190
+
191
+ const pathUtils = {
192
+ dirname: (path: string) => {
193
+ // Handle empty or just filename cases
194
+ if (!path || !path.includes('/')) return '.';
195
+
196
+ // Remove trailing slashes
197
+ path = path.replace(/\/+$/, '');
198
+
199
+ // Get directory part
200
+ return path.split('/').slice(0, -1).join('/') || '/';
201
+ },
202
+
203
+ basename: (path: string, ext?: string) => {
204
+ // Remove trailing slashes
205
+ path = path.replace(/\/+$/, '');
206
+
207
+ // Get the last part of the path
208
+ const base = path.split('/').pop() || '';
209
+
210
+ // If extension is provided, remove it from the result
211
+ if (ext && base.endsWith(ext)) {
212
+ return base.slice(0, -ext.length);
213
+ }
214
+
215
+ return base;
216
+ },
217
+ relative: (from: string, to: string): string => {
218
+ // Handle empty inputs
219
+ if (!from || !to) return '.';
220
+
221
+ // Normalize paths by removing trailing slashes and splitting
222
+ const normalizePathParts = (p: string) =>
223
+ p.replace(/\/+$/, '')
224
+ .split('/')
225
+ .filter(Boolean);
226
+
227
+ const fromParts = normalizePathParts(from);
228
+ const toParts = normalizePathParts(to);
229
+
230
+ // Find common parts at the start of both paths
231
+ let commonLength = 0;
232
+ const minLength = Math.min(fromParts.length, toParts.length);
233
+
234
+ for (let i = 0; i < minLength; i++) {
235
+ if (fromParts[i] !== toParts[i]) break;
236
+ commonLength++;
237
+ }
238
+
239
+ // Calculate the number of "../" needed
240
+ const upCount = fromParts.length - commonLength;
241
+
242
+ // Get the remaining path parts we need to append
243
+ const remainingPath = toParts.slice(commonLength);
244
+
245
+ // Construct the relative path
246
+ const relativeParts = [
247
+ ...Array(upCount).fill('..'),
248
+ ...remainingPath
249
+ ];
250
+
251
+ // Handle empty result case
252
+ return relativeParts.length === 0 ? '.' : relativeParts.join('/');
253
+ }
254
+ }
package.json CHANGED
@@ -55,6 +55,7 @@
55
  "@openrouter/ai-sdk-provider": "^0.0.5",
56
  "@radix-ui/react-dialog": "^1.1.1",
57
  "@radix-ui/react-dropdown-menu": "^2.1.1",
 
58
  "@radix-ui/react-tooltip": "^1.1.4",
59
  "@remix-run/cloudflare": "^2.10.2",
60
  "@remix-run/cloudflare-pages": "^2.10.2",
@@ -71,6 +72,7 @@
71
  "file-saver": "^2.0.5",
72
  "framer-motion": "^11.2.12",
73
  "isbot": "^4.1.0",
 
74
  "istextorbinary": "^9.5.0",
75
  "jose": "^5.6.3",
76
  "js-cookie": "^3.0.5",
@@ -103,6 +105,7 @@
103
  "fast-glob": "^3.3.2",
104
  "is-ci": "^3.0.1",
105
  "node-fetch": "^3.3.2",
 
106
  "prettier": "^3.3.2",
107
  "sass-embedded": "^1.80.3",
108
  "typescript": "^5.5.2",
 
55
  "@openrouter/ai-sdk-provider": "^0.0.5",
56
  "@radix-ui/react-dialog": "^1.1.1",
57
  "@radix-ui/react-dropdown-menu": "^2.1.1",
58
+ "@radix-ui/react-separator": "^1.1.0",
59
  "@radix-ui/react-tooltip": "^1.1.4",
60
  "@remix-run/cloudflare": "^2.10.2",
61
  "@remix-run/cloudflare-pages": "^2.10.2",
 
72
  "file-saver": "^2.0.5",
73
  "framer-motion": "^11.2.12",
74
  "isbot": "^4.1.0",
75
+ "isomorphic-git": "^1.27.1",
76
  "istextorbinary": "^9.5.0",
77
  "jose": "^5.6.3",
78
  "js-cookie": "^3.0.5",
 
105
  "fast-glob": "^3.3.2",
106
  "is-ci": "^3.0.1",
107
  "node-fetch": "^3.3.2",
108
+ "pnpm": "9.4.0",
109
  "prettier": "^3.3.2",
110
  "sass-embedded": "^1.80.3",
111
  "typescript": "^5.5.2",
pnpm-lock.yaml CHANGED
@@ -98,6 +98,9 @@ importers:
98
  '@radix-ui/react-dropdown-menu':
99
  specifier: ^2.1.1
100
 
 
 
101
  '@radix-ui/react-tooltip':
102
  specifier: ^1.1.4
103
@@ -146,6 +149,9 @@ importers:
146
  isbot:
147
  specifier: ^4.1.0
148
  version: 4.4.0
 
 
 
149
  istextorbinary:
150
  specifier: ^9.5.0
151
  version: 9.5.0
@@ -237,6 +243,9 @@ importers:
237
  node-fetch:
238
  specifier: ^3.3.2
239
  version: 3.3.2
 
 
 
240
  prettier:
241
  specifier: ^3.3.2
242
  version: 3.3.2
@@ -1607,6 +1616,19 @@ packages:
1607
  '@types/react-dom':
1608
  optional: true
1609
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1610
  '@radix-ui/[email protected]':
1611
  resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
1612
  peerDependencies:
@@ -2371,6 +2393,9 @@ packages:
2371
  resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
2372
  hasBin: true
2373
 
 
 
 
2374
2375
  resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
2376
  engines: {node: '>= 0.4'}
@@ -2564,6 +2589,9 @@ packages:
2564
2565
  resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==}
2566
 
 
 
 
2567
2568
  resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
2569
  engines: {node: '>=6'}
@@ -2673,6 +2701,11 @@ packages:
2673
2674
  resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
2675
 
 
 
 
 
 
2676
2677
  resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
2678
 
@@ -2745,6 +2778,10 @@ packages:
2745
2746
  resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
2747
 
 
 
 
 
2748
2749
  resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
2750
  peerDependencies:
@@ -2812,6 +2849,9 @@ packages:
2812
  resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
2813
  engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
2814
 
 
 
 
2815
2816
  resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
2817
  engines: {node: '>=0.3.1'}
@@ -3545,6 +3585,11 @@ packages:
3545
3546
  resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
3547
 
 
 
 
 
 
3548
3549
  resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==}
3550
  engines: {node: '>=10'}
@@ -4035,6 +4080,10 @@ packages:
4035
  resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
4036
  engines: {node: '>=12'}
4037
 
 
 
 
 
4038
4039
  resolution: {integrity: sha512-m9+I+7JNyqDGftCMKp9cK9pCZkK72hAL2mM9IWwhct+ZmucLBA8Uu6+rHQqA5iod86cpwOkrB2PrPA3wx9YNgw==}
4040
  engines: {node: '>=16.13'}
@@ -4056,6 +4105,9 @@ packages:
4056
4057
  resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
4058
 
 
 
 
4059
4060
  resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
4061
  engines: {node: '>= 8'}
@@ -4380,6 +4432,10 @@ packages:
4380
  engines: {node: '>=0.10'}
4381
  hasBin: true
4382
 
 
 
 
 
4383
4384
  resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
4385
  engines: {node: '>=10'}
@@ -4387,6 +4443,11 @@ packages:
4387
4388
  resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==}
4389
 
 
 
 
 
 
4390
4391
  resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
4392
  engines: {node: '>= 0.4'}
@@ -5006,6 +5067,12 @@ packages:
5006
  resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
5007
  engines: {node: '>=14'}
5008
 
 
 
 
 
 
 
5009
5010
  resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
5011
  engines: {node: '>= 10'}
@@ -7043,6 +7110,15 @@ snapshots:
7043
  '@types/react': 18.3.3
7044
  '@types/react-dom': 18.3.0
7045
 
 
 
 
 
 
 
 
 
 
7046
7047
  dependencies:
7048
  '@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
@@ -8004,6 +8080,8 @@ snapshots:
8004
 
8005
8006
 
 
 
8007
8008
  dependencies:
8009
  possible-typed-array-names: 1.0.0
@@ -8260,6 +8338,8 @@ snapshots:
8260
  inherits: 2.0.4
8261
  safe-buffer: 5.2.1
8262
 
 
 
8263
8264
 
8265
@@ -8351,6 +8431,8 @@ snapshots:
8351
 
8352
8353
 
 
 
8354
8355
  dependencies:
8356
  bn.js: 4.12.0
@@ -8428,6 +8510,10 @@ snapshots:
8428
  dependencies:
8429
  character-entities: 2.0.2
8430
 
 
 
 
 
8431
8432
 
8433
@@ -8479,6 +8565,8 @@ snapshots:
8479
 
8480
8481
 
 
 
8482
8483
 
8484
@@ -9398,6 +9486,20 @@ snapshots:
9398
 
9399
9400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9401
9402
 
9403
@@ -10265,6 +10367,8 @@ snapshots:
10265
 
10266
10267
 
 
 
10268
10269
  dependencies:
10270
  '@cspotcode/source-map-support': 0.8.1
@@ -10298,6 +10402,10 @@ snapshots:
10298
 
10299
10300
 
 
 
 
 
10301
10302
  dependencies:
10303
  minipass: 3.3.6
@@ -10639,6 +10747,8 @@ snapshots:
10639
 
10640
10641
 
 
 
10642
10643
  dependencies:
10644
  find-up: 5.0.0
@@ -10649,6 +10759,8 @@ snapshots:
10649
  mlly: 1.7.1
10650
  pathe: 1.1.2
10651
 
 
 
10652
10653
 
10654
@@ -11314,6 +11426,14 @@ snapshots:
11314
 
11315
11316
 
 
 
 
 
 
 
 
 
11317
11318
  dependencies:
11319
  '@polka/url': 1.0.0-next.25
 
98
  '@radix-ui/react-dropdown-menu':
99
  specifier: ^2.1.1
100
101
+ '@radix-ui/react-separator':
102
+ specifier: ^1.1.0
103
104
  '@radix-ui/react-tooltip':
105
  specifier: ^1.1.4
106
 
149
  isbot:
150
  specifier: ^4.1.0
151
  version: 4.4.0
152
+ isomorphic-git:
153
+ specifier: ^1.27.1
154
+ version: 1.27.1
155
  istextorbinary:
156
  specifier: ^9.5.0
157
  version: 9.5.0
 
243
  node-fetch:
244
  specifier: ^3.3.2
245
  version: 3.3.2
246
+ pnpm:
247
+ specifier: 9.4.0
248
+ version: 9.4.0
249
  prettier:
250
  specifier: ^3.3.2
251
  version: 3.3.2
 
1616
  '@types/react-dom':
1617
  optional: true
1618
 
1619
+ '@radix-ui/[email protected]':
1620
+ resolution: {integrity: sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==}
1621
+ peerDependencies:
1622
+ '@types/react': '*'
1623
+ '@types/react-dom': '*'
1624
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1625
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
1626
+ peerDependenciesMeta:
1627
+ '@types/react':
1628
+ optional: true
1629
+ '@types/react-dom':
1630
+ optional: true
1631
+
1632
  '@radix-ui/[email protected]':
1633
  resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
1634
  peerDependencies:
 
2393
  resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
2394
  hasBin: true
2395
 
2396
2397
+ resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==}
2398
+
2399
2400
  resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
2401
  engines: {node: '>= 0.4'}
 
2589
2590
  resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==}
2591
 
2592
2593
+ resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==}
2594
+
2595
2596
  resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
2597
  engines: {node: '>=6'}
 
2701
2702
  resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
2703
 
2704
2705
+ resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
2706
+ engines: {node: '>=0.8'}
2707
+ hasBin: true
2708
+
2709
2710
  resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
2711
 
 
2778
2779
  resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
2780
 
2781
2782
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
2783
+ engines: {node: '>=10'}
2784
+
2785
2786
  resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
2787
  peerDependencies:
 
2849
  resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
2850
  engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
2851
 
2852
2853
+ resolution: {integrity: sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==}
2854
+
2855
2856
  resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
2857
  engines: {node: '>=0.3.1'}
 
3585
3586
  resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
3587
 
3588
3589
+ resolution: {integrity: sha512-X32ph5zIWfT75QAqW2l3JCIqnx9/GWd17bRRehmn3qmWc34OYbSXY6Cxv0o9bIIY+CWugoN4nQFHNA+2uYf2nA==}
3590
+ engines: {node: '>=12'}
3591
+ hasBin: true
3592
+
3593
3594
  resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==}
3595
  engines: {node: '>=10'}
 
4080
  resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
4081
  engines: {node: '>=12'}
4082
 
4083
4084
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
4085
+ engines: {node: '>=10'}
4086
+
4087
4088
  resolution: {integrity: sha512-m9+I+7JNyqDGftCMKp9cK9pCZkK72hAL2mM9IWwhct+ZmucLBA8Uu6+rHQqA5iod86cpwOkrB2PrPA3wx9YNgw==}
4089
  engines: {node: '>=16.13'}
 
4105
4106
  resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
4107
 
4108
4109
+ resolution: {integrity: sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==}
4110
+
4111
4112
  resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
4113
  engines: {node: '>= 8'}
 
4432
  engines: {node: '>=0.10'}
4433
  hasBin: true
4434
 
4435
4436
+ resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
4437
+ engines: {node: '>=6'}
4438
+
4439
4440
  resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
4441
  engines: {node: '>=10'}
 
4443
4444
  resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==}
4445
 
4446
4447
+ resolution: {integrity: sha512-9Um4pSydK4U2di+ZwHIiBe/Fr5E+d4NdvMw7CwssqefcgCK3gGLBcpHEjoh0nHDOiOtadPH6jEv14Yu0bIvYOg==}
4448
+ engines: {node: '>=18.12'}
4449
+ hasBin: true
4450
+
4451
4452
  resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
4453
  engines: {node: '>= 0.4'}
 
5067
  resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
5068
  engines: {node: '>=14'}
5069
 
5070
5071
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
5072
+
5073
5074
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
5075
+
5076
5077
  resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
5078
  engines: {node: '>= 10'}
 
7110
  '@types/react': 18.3.3
7111
  '@types/react-dom': 18.3.0
7112
 
7113
7114
+ dependencies:
7115
+ '@radix-ui/react-primitive': 2.0.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
7116
+ react: 18.3.1
7117
+ react-dom: 18.3.1([email protected])
7118
+ optionalDependencies:
7119
+ '@types/react': 18.3.3
7120
+ '@types/react-dom': 18.3.0
7121
+
7122
7123
  dependencies:
7124
  '@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
 
8080
 
8081
8082
 
8083
8084
+
8085
8086
  dependencies:
8087
  possible-typed-array-names: 1.0.0
 
8338
  inherits: 2.0.4
8339
  safe-buffer: 5.2.1
8340
 
8341
8342
+
8343
8344
 
8345
 
8431
 
8432
8433
 
8434
8435
+
8436
8437
  dependencies:
8438
  bn.js: 4.12.0
 
8510
  dependencies:
8511
  character-entities: 2.0.2
8512
 
8513
8514
+ dependencies:
8515
+ mimic-response: 3.1.0
8516
+
8517
8518
 
8519
 
8565
 
8566
8567
 
8568
8569
+
8570
8571
 
8572
 
9486
 
9487
9488
 
9489
9490
+ dependencies:
9491
+ async-lock: 1.4.1
9492
+ clean-git-ref: 2.0.1
9493
+ crc-32: 1.2.2
9494
+ diff3: 0.0.3
9495
+ ignore: 5.3.1
9496
+ minimisted: 2.0.1
9497
+ pako: 1.0.11
9498
+ pify: 4.0.1
9499
+ readable-stream: 3.6.2
9500
+ sha.js: 2.4.11
9501
+ simple-get: 4.0.1
9502
+
9503
9504
 
9505
 
10367
 
10368
10369
 
10370
10371
+
10372
10373
  dependencies:
10374
  '@cspotcode/source-map-support': 0.8.1
 
10402
 
10403
10404
 
10405
10406
+ dependencies:
10407
+ minimist: 1.2.8
10408
+
10409
10410
  dependencies:
10411
  minipass: 3.3.6
 
10747
 
10748
10749
 
10750
10751
+
10752
10753
  dependencies:
10754
  find-up: 5.0.0
 
10759
  mlly: 1.7.1
10760
  pathe: 1.1.2
10761
 
10762
10763
+
10764
10765
 
10766
 
11426
 
11427
11428
 
11429
11430
+
11431
11432
+ dependencies:
11433
+ decompress-response: 6.0.0
11434
+ once: 1.4.0
11435
+ simple-concat: 1.0.1
11436
+
11437
11438
  dependencies:
11439
  '@polka/url': 1.0.0-next.25