codacus commited on
Commit
bd23686
Β·
1 Parent(s): b499ee1

chore: fixed lock file

Browse files
.husky/pre-commit CHANGED
@@ -2,15 +2,24 @@
2
 
3
  echo "πŸ” Running pre-commit hook to check the code looks good... πŸ”"
4
 
 
 
 
 
 
 
5
  if ! pnpm typecheck; then
6
- echo "❌ Type checking failed! Please review TypeScript types."
7
- echo "Once you're done, don't forget to add your changes to the commit! πŸš€"
8
- exit 1
 
9
  fi
10
 
 
11
  if ! pnpm lint; then
12
  echo "❌ Linting failed! 'pnpm lint:check' will help you fix the easy ones."
13
  echo "Once you're done, don't forget to add your beautification to the commit! 🀩"
 
14
  exit 1
15
  fi
16
 
 
2
 
3
  echo "πŸ” Running pre-commit hook to check the code looks good... πŸ”"
4
 
5
+ export NVM_DIR="$HOME/.nvm"
6
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Load nvm if you're using i
7
+
8
+ echo "Running typecheck..."
9
+ which pnpm
10
+
11
  if ! pnpm typecheck; then
12
+ echo "❌ Type checking failed! Please review TypeScript types."
13
+ echo "Once you're done, don't forget to add your changes to the commit! πŸš€"
14
+ echo "Typecheck exit code: $?"
15
+ exit 1
16
  fi
17
 
18
+ echo "Running lint..."
19
  if ! pnpm lint; then
20
  echo "❌ Linting failed! 'pnpm lint:check' will help you fix the easy ones."
21
  echo "Once you're done, don't forget to add your beautification to the commit! 🀩"
22
+ echo "lint exit code: $?"
23
  exit 1
24
  fi
25
 
app/components/chat/BaseChat.tsx CHANGED
@@ -260,7 +260,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
260
  <GitCloneButton />
261
  <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" />
262
  <div className="flex items-center gap-3"></div>
263
-
264
  <div className={isModelSettingsCollapsed ? 'hidden' : ''}>
265
  <ModelSelector
266
  key={provider?.name + ':' + modelList.length}
 
260
  <GitCloneButton />
261
  <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" />
262
  <div className="flex items-center gap-3"></div>
263
+
264
  <div className={isModelSettingsCollapsed ? 'hidden' : ''}>
265
  <ModelSelector
266
  key={provider?.name + ':' + modelList.length}
app/components/chat/GitCloneButton.tsx CHANGED
@@ -1,24 +1,30 @@
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
  }
 
1
+ import { IconButton } from '~/components/ui/IconButton';
2
+ import { useGit } from '~/lib/hooks/useGit';
 
 
3
 
4
  export default function GitCloneButton() {
5
+ const { ready, gitClone } = useGit();
6
+ const onClick = async (_e: any) => {
7
+ if (!ready) {
8
+ return;
 
 
 
9
  }
10
+
11
+ const repoUrl = prompt('Enter the Git url');
12
+
13
+ if (repoUrl) {
14
+ await gitClone(repoUrl);
15
+ }
16
+ };
17
+
18
  return (
19
+ <IconButton
20
+ onClick={(e) => {
21
+ onClick(e);
22
+ }}
23
+ className="w-full justify-center"
24
+ title="Clone A Git Repo"
25
+ >
26
+ <span className="mr-2 text-xs lg:text-sm">Clone A Git Repo</span>
27
+ <div className="i-ph:git-branch" />
28
  </IconButton>
29
+ );
30
  }
app/lib/hooks/useGit.ts CHANGED
@@ -1,254 +1,258 @@
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
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { WebContainer } 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
  export function useGit() {
9
+ const [ready, setReady] = useState(false);
10
+ const [webcontainer, setWebcontainer] = useState<WebContainer>();
11
+ const [fs, setFs] = useState<PromiseFsClient>();
12
+ const lookupSavedPassword: (url: string) => any | null = (url: string) => {
13
+ try {
14
+ // Save updated API keys to cookies with 30 day expiry and secure settings
15
+ const creds = Cookies.get(`git:${url}`);
16
+
17
+ if (creds) {
18
+ const parsedCreds = JSON.parse(creds);
19
+
20
+ if (typeof parsedCreds === 'object' && parsedCreds !== null) {
21
+ return parsedCreds;
 
 
 
 
 
 
 
 
22
  }
23
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ return null;
26
+ } catch (error) {
27
+ console.error('Error saving API keys to cookies:', error);
28
+ return null;
 
 
 
 
 
 
 
 
 
 
29
  }
30
+ };
31
+ useEffect(() => {
32
+ webcontainerPromise.then((container) => {
33
+ setWebcontainer(container);
34
+ setFs(getFs(container));
35
+ setReady(true);
36
+ });
37
+ }, []);
38
+
39
+ const gitClone = useCallback(
40
+ async (url: string) => {
41
+ if (!webcontainer || !fs || !ready) {
42
+ return;
43
+ }
44
+
45
+ const repo = await git.clone({
46
+ fs,
47
+ http,
48
+ dir: webcontainer.workdir,
49
+ url,
50
+ depth: 1,
51
+ singleBranch: true,
52
+ corsProxy: 'https://cors.isomorphic-git.org',
53
+ onAuth: (url) => {
54
+ let auth = lookupSavedPassword(url);
55
+
56
+ if (auth) {
57
+ return auth;
58
+ }
59
+
60
+ if (confirm('This repo is password protected. Ready to enter a username & password?')) {
61
+ auth = {
62
+ username: prompt('Enter username'),
63
+ password: prompt('Enter password'),
64
+ };
65
+ return auth;
66
+ } else {
67
+ return { cancel: true };
68
+ }
 
 
 
 
69
  },
70
+ });
71
+ console.log(repo);
72
+ },
73
+ [webcontainer],
74
+ );
75
 
76
+ return { ready, gitClone };
77
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
+ const getFs: (c: WebContainer) => PromiseFsClient = (webcontainer: WebContainer) => ({
80
+ promises: {
81
+ readFile: async (path: string, options: any) => {
82
+ const encoding = options.encoding;
83
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
84
+ console.log('readFile', relativePath, encoding);
85
 
86
+ return await webcontainer.fs.readFile(relativePath, encoding);
87
+ },
88
+ writeFile: async (path: string, data: any, options: any) => {
89
+ const encoding = options.encoding;
90
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
91
+ console.log('writeFile', { relativePath, data, encoding });
92
 
93
+ return await webcontainer.fs.writeFile(relativePath, data, { ...options, encoding });
94
+ },
95
+ mkdir: async (path: string, options: any) => {
96
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
97
+ console.log('mkdir', relativePath, options);
98
 
99
+ return await webcontainer.fs.mkdir(relativePath, { ...options, recursive: true });
100
+ },
101
+ readdir: async (path: string, options: any) => {
102
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
103
+ console.log('readdir', relativePath, options);
 
 
104
 
105
+ return await webcontainer.fs.readdir(relativePath, options);
106
+ },
107
+ rm: async (path: string, options: any) => {
108
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
109
+ console.log('rm', relativePath, options);
110
 
111
+ return await webcontainer.fs.rm(relativePath, { ...(options || {}) });
112
+ },
113
+ rmdir: async (path: string, options: any) => {
114
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
115
+ console.log('rmdir', relativePath, options);
116
 
117
+ return await webcontainer.fs.rm(relativePath, { recursive: true, ...options });
 
118
  },
119
 
120
+ // Mock implementations for missing functions
121
+ unlink: async (path: string) => {
122
+ // unlink is just removing a single file
123
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
124
+ return await webcontainer.fs.rm(relativePath, { recursive: false });
125
+ },
126
 
127
+ stat: async (path: string) => {
128
+ try {
129
+ const relativePath = pathUtils.relative(webcontainer.workdir, path);
130
+ const resp = await webcontainer.fs.readdir(pathUtils.dirname(relativePath), { withFileTypes: true });
131
+ const name = pathUtils.basename(relativePath);
132
+ const fileInfo = resp.find((x) => x.name == name);
133
 
134
+ if (!fileInfo) {
135
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
 
136
  }
137
 
138
+ return {
139
+ isFile: () => fileInfo.isFile(),
140
+ isDirectory: () => fileInfo.isDirectory(),
141
+ isSymbolicLink: () => false,
142
+ size: 1,
143
+ mode: 0o666, // Default permissions
144
+ mtimeMs: Date.now(),
145
+ uid: 1000,
146
+ gid: 1000,
147
+ };
148
+ } catch (error: any) {
149
+ console.log(error?.message);
150
+
151
+ const err = new Error(`ENOENT: no such file or directory, stat '${path}'`) as NodeJS.ErrnoException;
152
+ err.code = 'ENOENT';
153
+ err.errno = -2;
154
+ err.syscall = 'stat';
155
+ err.path = path;
156
+ throw err;
157
+ }
158
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ lstat: async (path: string) => {
161
+ /*
162
+ * For basic usage, lstat can return the same as stat
163
+ * since we're not handling symbolic links
164
+ */
165
+ return await getFs(webcontainer).promises.stat(path);
166
+ },
167
+
168
+ readlink: async (path: string) => {
169
+ /*
170
+ * Since WebContainer doesn't support symlinks,
171
+ * we'll throw a "not a symbolic link" error
172
+ */
173
+ throw new Error(`EINVAL: invalid argument, readlink '${path}'`);
174
+ },
175
+
176
+ symlink: async (target: string, path: string) => {
177
+ /*
178
+ * Since WebContainer doesn't support symlinks,
179
+ * we'll throw a "operation not supported" error
180
+ */
181
+ throw new Error(`EPERM: operation not permitted, symlink '${target}' -> '${path}'`);
182
+ },
183
+
184
+ chmod: async (_path: string, _mode: number) => {
185
+ /*
186
+ * WebContainer doesn't support changing permissions,
187
+ * but we can pretend it succeeded for compatibility
188
+ */
189
+ return await Promise.resolve();
190
+ },
191
+ },
192
+ });
193
+
194
+ const pathUtils = {
195
+ dirname: (path: string) => {
196
+ // Handle empty or just filename cases
197
+ if (!path || !path.includes('/')) {
198
+ return '.';
199
+ }
200
+
201
+ // Remove trailing slashes
202
+ path = path.replace(/\/+$/, '');
203
 
204
+ // Get directory part
205
+ return path.split('/').slice(0, -1).join('/') || '/';
206
+ },
207
 
208
+ basename: (path: string, ext?: string) => {
209
+ // Remove trailing slashes
210
+ path = path.replace(/\/+$/, '');
 
 
211
 
212
+ // Get the last part of the path
213
+ const base = path.split('/').pop() || '';
214
+
215
+ // If extension is provided, remove it from the result
216
+ if (ext && base.endsWith(ext)) {
217
+ return base.slice(0, -ext.length);
218
+ }
219
+
220
+ return base;
221
+ },
222
+ relative: (from: string, to: string): string => {
223
+ // Handle empty inputs
224
+ if (!from || !to) {
225
+ return '.';
226
  }
227
+
228
+ // Normalize paths by removing trailing slashes and splitting
229
+ const normalizePathParts = (p: string) => p.replace(/\/+$/, '').split('/').filter(Boolean);
230
+
231
+ const fromParts = normalizePathParts(from);
232
+ const toParts = normalizePathParts(to);
233
+
234
+ // Find common parts at the start of both paths
235
+ let commonLength = 0;
236
+ const minLength = Math.min(fromParts.length, toParts.length);
237
+
238
+ for (let i = 0; i < minLength; i++) {
239
+ if (fromParts[i] !== toParts[i]) {
240
+ break;
241
+ }
242
+
243
+ commonLength++;
244
+ }
245
+
246
+ // Calculate the number of "../" needed
247
+ const upCount = fromParts.length - commonLength;
248
+
249
+ // Get the remaining path parts we need to append
250
+ const remainingPath = toParts.slice(commonLength);
251
+
252
+ // Construct the relative path
253
+ const relativeParts = [...Array(upCount).fill('..'), ...remainingPath];
254
+
255
+ // Handle empty result case
256
+ return relativeParts.length === 0 ? '.' : relativeParts.join('/');
257
+ },
258
+ };
package-lock.json DELETED
The diff for this file is too large to render. See raw diff
 
package.json CHANGED
@@ -58,6 +58,7 @@
58
  "@openrouter/ai-sdk-provider": "^0.0.5",
59
  "@radix-ui/react-dialog": "^1.1.2",
60
  "@radix-ui/react-dropdown-menu": "^2.1.2",
 
61
  "@radix-ui/react-tooltip": "^1.1.4",
62
  "@remix-run/cloudflare": "^2.15.0",
63
  "@remix-run/cloudflare-pages": "^2.15.0",
@@ -75,13 +76,13 @@
75
  "framer-motion": "^11.12.0",
76
  "ignore": "^6.0.2",
77
  "isbot": "^4.4.0",
 
78
  "istextorbinary": "^9.5.0",
79
  "jose": "^5.9.6",
80
  "js-cookie": "^3.0.5",
81
  "jszip": "^3.10.1",
82
  "nanostores": "^0.10.3",
83
  "ollama-ai-provider": "^0.15.2",
84
- "pnpm": "^9.14.4",
85
  "react": "^18.3.1",
86
  "react-dom": "^18.3.1",
87
  "react-hotkeys-hook": "^4.6.1",
@@ -109,6 +110,7 @@
109
  "husky": "9.1.7",
110
  "is-ci": "^3.0.1",
111
  "node-fetch": "^3.3.2",
 
112
  "prettier": "^3.4.1",
113
  "sass-embedded": "^1.81.0",
114
  "typescript": "^5.7.2",
 
58
  "@openrouter/ai-sdk-provider": "^0.0.5",
59
  "@radix-ui/react-dialog": "^1.1.2",
60
  "@radix-ui/react-dropdown-menu": "^2.1.2",
61
+ "@radix-ui/react-separator": "^1.1.0",
62
  "@radix-ui/react-tooltip": "^1.1.4",
63
  "@remix-run/cloudflare": "^2.15.0",
64
  "@remix-run/cloudflare-pages": "^2.15.0",
 
76
  "framer-motion": "^11.12.0",
77
  "ignore": "^6.0.2",
78
  "isbot": "^4.4.0",
79
+ "isomorphic-git": "^1.27.2",
80
  "istextorbinary": "^9.5.0",
81
  "jose": "^5.9.6",
82
  "js-cookie": "^3.0.5",
83
  "jszip": "^3.10.1",
84
  "nanostores": "^0.10.3",
85
  "ollama-ai-provider": "^0.15.2",
 
86
  "react": "^18.3.1",
87
  "react-dom": "^18.3.1",
88
  "react-hotkeys-hook": "^4.6.1",
 
110
  "husky": "9.1.7",
111
  "is-ci": "^3.0.1",
112
  "node-fetch": "^3.3.2",
113
+ "pnpm": "^9.14.4",
114
  "prettier": "^3.4.1",
115
  "sass-embedded": "^1.81.0",
116
  "typescript": "^5.7.2",
pnpm-lock.yaml CHANGED
The diff for this file is too large to render. See raw diff