Merge branch 'main' into context-optimization
Browse files- .github/workflows/commit.yaml +32 -0
- .husky/pre-commit +9 -3
- README.md +13 -10
- app/commit.json +1 -0
- app/components/chat/Artifact.tsx +1 -1
- app/components/chat/BaseChat.module.scss +0 -76
- app/components/chat/BaseChat.tsx +91 -54
- app/components/chat/GitCloneButton.tsx +115 -0
- app/components/chat/ImportFolderButton.tsx +65 -129
- app/components/chat/ModelSelector.tsx +73 -4
- app/components/chat/SendButton.client.tsx +8 -3
- app/components/chat/chatExportAndImport/ImportButtons.tsx +1 -1
- app/components/editor/codemirror/languages.ts +7 -0
- app/components/git/GitUrlImport.client.tsx +117 -0
- app/components/header/Header.tsx +7 -8
- app/components/settings/Settings.module.scss +63 -0
- app/components/settings/SettingsWindow.tsx +483 -0
- app/components/sidebar/Menu.client.tsx +7 -2
- app/components/ui/BackgroundRays/index.tsx +18 -0
- app/components/ui/BackgroundRays/styles.module.scss +246 -0
- app/components/ui/SettingsButton.tsx +17 -0
- app/components/ui/Switch.tsx +37 -0
- app/components/workbench/Workbench.client.tsx +13 -11
- app/lib/hooks/useGit.ts +287 -0
- app/lib/stores/settings.ts +24 -0
- app/lib/stores/workbench.ts +9 -8
- app/routes/_index.tsx +3 -1
- app/routes/git.tsx +23 -0
- app/styles/index.scss +10 -0
- app/types/model.ts +1 -0
- app/utils/constants.ts +9 -6
- app/utils/fileUtils.ts +105 -0
- app/utils/folderImport.ts +68 -0
- app/utils/projectCommands.ts +80 -0
- docs/docs/FAQ.md +57 -28
- docs/docs/index.md +0 -25
- package.json +5 -1
- pnpm-lock.yaml +438 -270
- public/favicon.svg +1 -1
- public/logo-dark-styled.png +0 -0
- public/logo-dark.png +0 -0
- public/logo-light-styled.png +0 -0
- public/logo-light.png +0 -0
- public/logo.svg +15 -1
- public/social_preview_index.jpg +0 -0
- uno.config.ts +11 -11
.github/workflows/commit.yaml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Update Commit Hash File
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- main
|
7 |
+
|
8 |
+
permissions:
|
9 |
+
contents: write
|
10 |
+
|
11 |
+
jobs:
|
12 |
+
update-commit:
|
13 |
+
runs-on: ubuntu-latest
|
14 |
+
|
15 |
+
steps:
|
16 |
+
- name: Checkout the code
|
17 |
+
uses: actions/checkout@v3
|
18 |
+
|
19 |
+
- name: Get the latest commit hash
|
20 |
+
run: echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
21 |
+
|
22 |
+
- name: Update commit file
|
23 |
+
run: |
|
24 |
+
echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
|
25 |
+
|
26 |
+
- name: Commit and push the update
|
27 |
+
run: |
|
28 |
+
git config --global user.name "github-actions[bot]"
|
29 |
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
30 |
+
git add app/commit.json
|
31 |
+
git commit -m "chore: update commit hash to $COMMIT_HASH"
|
32 |
+
git push
|
.husky/pre-commit
CHANGED
@@ -5,15 +5,21 @@ echo "🔍 Running pre-commit hook to check the code looks good... 🔍"
|
|
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 |
if ! pnpm typecheck; then
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
12 |
fi
|
13 |
|
|
|
14 |
if ! pnpm lint; then
|
15 |
echo "❌ Linting failed! 'pnpm lint:fix' will help you fix the easy ones."
|
16 |
echo "Once you're done, don't forget to add your beautification to the commit! 🤩"
|
|
|
17 |
exit 1
|
18 |
fi
|
19 |
|
|
|
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:fix' 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 |
|
README.md
CHANGED
@@ -1,12 +1,14 @@
|
|
1 |
[](https://bolt.new)
|
2 |
|
3 |
-
# Bolt.
|
4 |
|
5 |
-
|
6 |
|
7 |
-
Check the [
|
8 |
|
9 |
-
|
|
|
|
|
10 |
|
11 |
https://thinktank.ottomator.ai
|
12 |
|
@@ -41,6 +43,7 @@ https://thinktank.ottomator.ai
|
|
41 |
- ✅ Mobile friendly (@qwikode)
|
42 |
- ✅ Better prompt enhancing (@SujalXplores)
|
43 |
- ✅ Attach images to prompts (@atrokhym)
|
|
|
44 |
- ⬜ **HIGH PRIORITY** - Prevent Bolt from rewriting files as often (file locking and diffs)
|
45 |
- ⬜ **HIGH PRIORITY** - Better prompting for smaller LLMs (code window sometimes doesn't start)
|
46 |
- ⬜ **HIGH PRIORITY** - Run agents in the backend as opposed to a single model call
|
@@ -55,7 +58,7 @@ https://thinktank.ottomator.ai
|
|
55 |
|
56 |
## Bolt.new: AI-Powered Full-Stack Web Development in the Browser
|
57 |
|
58 |
-
Bolt.new is an AI-powered web development agent that allows you to prompt, run, edit, and deploy full-stack applications directly from your browser—no local setup required. If you're here to build your own AI-powered web dev agent using the Bolt open source codebase, [click here to get started!](./CONTRIBUTING.md)
|
59 |
|
60 |
## What Makes Bolt.new Different
|
61 |
|
@@ -95,7 +98,7 @@ If you see usr/local/bin in the output then you're good to go.
|
|
95 |
3. Clone the repository (if you haven't already) by opening a Terminal window (or CMD with admin permissions) and then typing in this:
|
96 |
|
97 |
```
|
98 |
-
git clone https://github.com/
|
99 |
```
|
100 |
|
101 |
3. Rename .env.example to .env.local and add your LLM API keys. You will find this file on a Mac at "[your name]/bold.new-any-llm/.env.example". For Windows and Linux the path will be similar.
|
@@ -224,11 +227,11 @@ pnpm run dev
|
|
224 |
|
225 |
This will start the Remix Vite development server. You will need Google Chrome Canary to run this locally if you use Chrome! It's an easy install and a good browser for web development anyway.
|
226 |
|
227 |
-
## How do I contribute to
|
228 |
|
229 |
-
[Please check out our dedicated page for contributing to
|
230 |
|
231 |
-
## What are the future plans for
|
232 |
|
233 |
[Check out our Roadmap here!](https://roadmap.sh/r/ottodev-roadmap-2ovzo)
|
234 |
|
@@ -236,4 +239,4 @@ Lot more updates to this roadmap coming soon!
|
|
236 |
|
237 |
## FAQ
|
238 |
|
239 |
-
[Please check out our dedicated page for FAQ's related to
|
|
|
1 |
[](https://bolt.new)
|
2 |
|
3 |
+
# Bolt.diy (Previously oTToDev)
|
4 |
|
5 |
+
Welcome to Bolt.diy, the official open source version of Bolt.new (previously known as oTToDev and Bolt.new ANY LLM), which allows you to choose the LLM that you use for each prompt! Currently, you can use OpenAI, Anthropic, Ollama, OpenRouter, Gemini, LMStudio, Mistral, xAI, HuggingFace, DeepSeek, or Groq models - and it is easily extended to use any other model supported by the Vercel AI SDK! See the instructions below for running this locally and extending it to include more models.
|
6 |
|
7 |
+
Check the [Bolt.diy Docs](https://stackblitz-labs.github.io/bolt.diy/) for more information. This documentation is still being updated after the transfer.
|
8 |
|
9 |
+
Bolt.diy was originally started by [Cole Medin](https://www.youtube.com/@ColeMedin) but has quickly grown into a massive community effort to build the BEST open source AI coding assistant!
|
10 |
+
|
11 |
+
## Join the community for Bolt.diy!
|
12 |
|
13 |
https://thinktank.ottomator.ai
|
14 |
|
|
|
43 |
- ✅ Mobile friendly (@qwikode)
|
44 |
- ✅ Better prompt enhancing (@SujalXplores)
|
45 |
- ✅ Attach images to prompts (@atrokhym)
|
46 |
+
- ✅ Detect package.json and commands to auto install and run preview for folder and git import (@wonderwhy-er)
|
47 |
- ⬜ **HIGH PRIORITY** - Prevent Bolt from rewriting files as often (file locking and diffs)
|
48 |
- ⬜ **HIGH PRIORITY** - Better prompting for smaller LLMs (code window sometimes doesn't start)
|
49 |
- ⬜ **HIGH PRIORITY** - Run agents in the backend as opposed to a single model call
|
|
|
58 |
|
59 |
## Bolt.new: AI-Powered Full-Stack Web Development in the Browser
|
60 |
|
61 |
+
Bolt.new (and by extension Bolt.diy) is an AI-powered web development agent that allows you to prompt, run, edit, and deploy full-stack applications directly from your browser—no local setup required. If you're here to build your own AI-powered web dev agent using the Bolt open source codebase, [click here to get started!](./CONTRIBUTING.md)
|
62 |
|
63 |
## What Makes Bolt.new Different
|
64 |
|
|
|
98 |
3. Clone the repository (if you haven't already) by opening a Terminal window (or CMD with admin permissions) and then typing in this:
|
99 |
|
100 |
```
|
101 |
+
git clone https://github.com/stackblitz-labs/bolt.diy.git
|
102 |
```
|
103 |
|
104 |
3. Rename .env.example to .env.local and add your LLM API keys. You will find this file on a Mac at "[your name]/bold.new-any-llm/.env.example". For Windows and Linux the path will be similar.
|
|
|
227 |
|
228 |
This will start the Remix Vite development server. You will need Google Chrome Canary to run this locally if you use Chrome! It's an easy install and a good browser for web development anyway.
|
229 |
|
230 |
+
## How do I contribute to Bolt.diy?
|
231 |
|
232 |
+
[Please check out our dedicated page for contributing to Bolt.diy here!](CONTRIBUTING.md)
|
233 |
|
234 |
+
## What are the future plans for Bolt.diy?
|
235 |
|
236 |
[Check out our Roadmap here!](https://roadmap.sh/r/ottodev-roadmap-2ovzo)
|
237 |
|
|
|
239 |
|
240 |
## FAQ
|
241 |
|
242 |
+
[Please check out our dedicated page for FAQ's related to Bolt.diy here!](FAQ.md)
|
app/commit.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{ "commit": "154935cdeb054d2cc22dfb0c7e6cf084f02b95d0" }
|
app/components/chat/Artifact.tsx
CHANGED
@@ -52,7 +52,7 @@ export const Artifact = memo(({ messageId }: ArtifactProps) => {
|
|
52 |
if (actions.length !== 0 && artifact.type === 'bundled') {
|
53 |
const finished = !actions.find((action) => action.status !== 'complete');
|
54 |
|
55 |
-
if (
|
56 |
setAllActionFinished(finished);
|
57 |
}
|
58 |
}
|
|
|
52 |
if (actions.length !== 0 && artifact.type === 'bundled') {
|
53 |
const finished = !actions.find((action) => action.status !== 'complete');
|
54 |
|
55 |
+
if (allActionFinished !== finished) {
|
56 |
setAllActionFinished(finished);
|
57 |
}
|
58 |
}
|
app/components/chat/BaseChat.module.scss
CHANGED
@@ -18,82 +18,6 @@
|
|
18 |
opacity: 1;
|
19 |
}
|
20 |
|
21 |
-
.RayContainer {
|
22 |
-
--gradient-opacity: 0.85;
|
23 |
-
--ray-gradient: radial-gradient(rgba(83, 196, 255, var(--gradient-opacity)) 0%, rgba(43, 166, 255, 0) 100%);
|
24 |
-
transition: opacity 0.25s linear;
|
25 |
-
position: fixed;
|
26 |
-
inset: 0;
|
27 |
-
pointer-events: none;
|
28 |
-
user-select: none;
|
29 |
-
}
|
30 |
-
|
31 |
-
.LightRayOne {
|
32 |
-
width: 480px;
|
33 |
-
height: 680px;
|
34 |
-
transform: rotate(80deg);
|
35 |
-
top: -540px;
|
36 |
-
left: 250px;
|
37 |
-
filter: blur(110px);
|
38 |
-
position: absolute;
|
39 |
-
border-radius: 100%;
|
40 |
-
background: var(--ray-gradient);
|
41 |
-
}
|
42 |
-
|
43 |
-
.LightRayTwo {
|
44 |
-
width: 110px;
|
45 |
-
height: 400px;
|
46 |
-
transform: rotate(-20deg);
|
47 |
-
top: -280px;
|
48 |
-
left: 350px;
|
49 |
-
mix-blend-mode: overlay;
|
50 |
-
opacity: 0.6;
|
51 |
-
filter: blur(60px);
|
52 |
-
position: absolute;
|
53 |
-
border-radius: 100%;
|
54 |
-
background: var(--ray-gradient);
|
55 |
-
}
|
56 |
-
|
57 |
-
.LightRayThree {
|
58 |
-
width: 400px;
|
59 |
-
height: 370px;
|
60 |
-
top: -350px;
|
61 |
-
left: 200px;
|
62 |
-
mix-blend-mode: overlay;
|
63 |
-
opacity: 0.6;
|
64 |
-
filter: blur(21px);
|
65 |
-
position: absolute;
|
66 |
-
border-radius: 100%;
|
67 |
-
background: var(--ray-gradient);
|
68 |
-
}
|
69 |
-
|
70 |
-
.LightRayFour {
|
71 |
-
position: absolute;
|
72 |
-
width: 330px;
|
73 |
-
height: 370px;
|
74 |
-
top: -330px;
|
75 |
-
left: 50px;
|
76 |
-
mix-blend-mode: overlay;
|
77 |
-
opacity: 0.5;
|
78 |
-
filter: blur(21px);
|
79 |
-
border-radius: 100%;
|
80 |
-
background: var(--ray-gradient);
|
81 |
-
}
|
82 |
-
|
83 |
-
.LightRayFive {
|
84 |
-
position: absolute;
|
85 |
-
width: 110px;
|
86 |
-
height: 400px;
|
87 |
-
transform: rotate(-40deg);
|
88 |
-
top: -280px;
|
89 |
-
left: -10px;
|
90 |
-
mix-blend-mode: overlay;
|
91 |
-
opacity: 0.8;
|
92 |
-
filter: blur(60px);
|
93 |
-
border-radius: 100%;
|
94 |
-
background: var(--ray-gradient);
|
95 |
-
}
|
96 |
-
|
97 |
.PromptEffectContainer {
|
98 |
--prompt-container-offset: 50px;
|
99 |
--prompt-line-stroke-width: 1px;
|
|
|
18 |
opacity: 1;
|
19 |
}
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
.PromptEffectContainer {
|
22 |
--prompt-container-offset: 50px;
|
23 |
--prompt-line-stroke-width: 1px;
|
app/components/chat/BaseChat.tsx
CHANGED
@@ -21,6 +21,7 @@ import type { ProviderInfo } from '~/utils/types';
|
|
21 |
import { ExportChatButton } from '~/components/chat/chatExportAndImport/ExportChatButton';
|
22 |
import { ImportButtons } from '~/components/chat/chatExportAndImport/ImportButtons';
|
23 |
import { ExamplePrompts } from '~/components/chat/ExamplePrompts';
|
|
|
24 |
|
25 |
import FilePreview from './FilePreview';
|
26 |
import { ModelSelector } from '~/components/chat/ModelSelector';
|
@@ -87,14 +88,68 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
87 |
ref,
|
88 |
) => {
|
89 |
const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200;
|
90 |
-
const [apiKeys, setApiKeys] = useState<Record<string, string>>({
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
const [modelList, setModelList] = useState(MODEL_LIST);
|
92 |
const [isModelSettingsCollapsed, setIsModelSettingsCollapsed] = useState(false);
|
93 |
const [isListening, setIsListening] = useState(false);
|
94 |
const [recognition, setRecognition] = useState<SpeechRecognition | null>(null);
|
95 |
const [transcript, setTranscript] = useState('');
|
96 |
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
useEffect(() => {
|
99 |
// Load API keys from cookies on component mount
|
100 |
try {
|
@@ -183,23 +238,6 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
183 |
}
|
184 |
};
|
185 |
|
186 |
-
const updateApiKey = (provider: string, key: string) => {
|
187 |
-
try {
|
188 |
-
const updatedApiKeys = { ...apiKeys, [provider]: key };
|
189 |
-
setApiKeys(updatedApiKeys);
|
190 |
-
|
191 |
-
// Save updated API keys to cookies with 30 day expiry and secure settings
|
192 |
-
Cookies.set('apiKeys', JSON.stringify(updatedApiKeys), {
|
193 |
-
expires: 30, // 30 days
|
194 |
-
secure: true, // Only send over HTTPS
|
195 |
-
sameSite: 'strict', // Protect against CSRF
|
196 |
-
path: '/', // Accessible across the site
|
197 |
-
});
|
198 |
-
} catch (error) {
|
199 |
-
console.error('Error saving API keys to cookies:', error);
|
200 |
-
}
|
201 |
-
};
|
202 |
-
|
203 |
const handleFileUpload = () => {
|
204 |
const input = document.createElement('input');
|
205 |
input.type = 'file';
|
@@ -255,19 +293,9 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
255 |
const baseChat = (
|
256 |
<div
|
257 |
ref={ref}
|
258 |
-
className={classNames(
|
259 |
-
styles.BaseChat,
|
260 |
-
'relative flex flex-col lg:flex-row h-full w-full overflow-hidden bg-bolt-elements-background-depth-1',
|
261 |
-
)}
|
262 |
data-chat-visible={showChat}
|
263 |
>
|
264 |
-
<div className={classNames(styles.RayContainer)}>
|
265 |
-
<div className={classNames(styles.LightRayOne)}></div>
|
266 |
-
<div className={classNames(styles.LightRayTwo)}></div>
|
267 |
-
<div className={classNames(styles.LightRayThree)}></div>
|
268 |
-
<div className={classNames(styles.LightRayFour)}></div>
|
269 |
-
<div className={classNames(styles.LightRayFive)}></div>
|
270 |
-
</div>
|
271 |
<ClientOnly>{() => <Menu />}</ClientOnly>
|
272 |
<div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
|
273 |
<div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
|
@@ -317,15 +345,15 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
317 |
gradientUnits="userSpaceOnUse"
|
318 |
gradientTransform="rotate(-45)"
|
319 |
>
|
320 |
-
<stop offset="0%" stopColor="#
|
321 |
-
<stop offset="40%" stopColor="#
|
322 |
-
<stop offset="50%" stopColor="#
|
323 |
-
<stop offset="100%" stopColor="#
|
324 |
</linearGradient>
|
325 |
<linearGradient id="shine-gradient">
|
326 |
<stop offset="0%" stopColor="white" stopOpacity="0%"></stop>
|
327 |
-
<stop offset="40%" stopColor="#
|
328 |
-
<stop offset="50%" stopColor="#
|
329 |
<stop offset="100%" stopColor="white" stopOpacity="0%"></stop>
|
330 |
</linearGradient>
|
331 |
</defs>
|
@@ -333,21 +361,6 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
333 |
<rect className={classNames(styles.PromptShine)} x="48" y="24" width="70" height="1"></rect>
|
334 |
</svg>
|
335 |
<div>
|
336 |
-
<div className="flex justify-between items-center mb-2">
|
337 |
-
<button
|
338 |
-
onClick={() => setIsModelSettingsCollapsed(!isModelSettingsCollapsed)}
|
339 |
-
className={classNames('flex items-center gap-2 p-2 rounded-lg transition-all', {
|
340 |
-
'bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent':
|
341 |
-
isModelSettingsCollapsed,
|
342 |
-
'bg-bolt-elements-item-backgroundDefault text-bolt-elements-item-contentDefault':
|
343 |
-
!isModelSettingsCollapsed,
|
344 |
-
})}
|
345 |
-
>
|
346 |
-
<div className={`i-ph:caret-${isModelSettingsCollapsed ? 'right' : 'down'} text-lg`} />
|
347 |
-
<span>Model Settings</span>
|
348 |
-
</button>
|
349 |
-
</div>
|
350 |
-
|
351 |
<div className={isModelSettingsCollapsed ? 'hidden' : ''}>
|
352 |
<ModelSelector
|
353 |
key={provider?.name + ':' + modelList.length}
|
@@ -359,11 +372,15 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
359 |
providerList={PROVIDER_LIST}
|
360 |
apiKeys={apiKeys}
|
361 |
/>
|
362 |
-
{provider && (
|
363 |
<APIKeyManager
|
364 |
provider={provider}
|
365 |
apiKey={apiKeys[provider.name] || ''}
|
366 |
-
setApiKey={(key) =>
|
|
|
|
|
|
|
|
|
367 |
/>
|
368 |
)}
|
369 |
</div>
|
@@ -451,6 +468,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
451 |
<SendButton
|
452 |
show={input.length > 0 || isStreaming || uploadedFiles.length > 0}
|
453 |
isStreaming={isStreaming}
|
|
|
454 |
onClick={(event) => {
|
455 |
if (isStreaming) {
|
456 |
handleStop?.();
|
@@ -501,6 +519,20 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
501 |
disabled={isStreaming}
|
502 |
/>
|
503 |
{chatStarted && <ClientOnly>{() => <ExportChatButton exportChat={exportChat} />}</ClientOnly>}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
</div>
|
505 |
{input.length > 3 ? (
|
506 |
<div className="text-xs text-bolt-elements-textTertiary">
|
@@ -513,7 +545,12 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
513 |
</div>
|
514 |
</div>
|
515 |
</div>
|
516 |
-
{!chatStarted &&
|
|
|
|
|
|
|
|
|
|
|
517 |
{!chatStarted &&
|
518 |
ExamplePrompts((event, messageInput) => {
|
519 |
if (isStreaming) {
|
|
|
21 |
import { ExportChatButton } from '~/components/chat/chatExportAndImport/ExportChatButton';
|
22 |
import { ImportButtons } from '~/components/chat/chatExportAndImport/ImportButtons';
|
23 |
import { ExamplePrompts } from '~/components/chat/ExamplePrompts';
|
24 |
+
import GitCloneButton from './GitCloneButton';
|
25 |
|
26 |
import FilePreview from './FilePreview';
|
27 |
import { ModelSelector } from '~/components/chat/ModelSelector';
|
|
|
88 |
ref,
|
89 |
) => {
|
90 |
const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200;
|
91 |
+
const [apiKeys, setApiKeys] = useState<Record<string, string>>(() => {
|
92 |
+
const savedKeys = Cookies.get('apiKeys');
|
93 |
+
|
94 |
+
if (savedKeys) {
|
95 |
+
try {
|
96 |
+
return JSON.parse(savedKeys);
|
97 |
+
} catch (error) {
|
98 |
+
console.error('Failed to parse API keys from cookies:', error);
|
99 |
+
return {};
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
return {};
|
104 |
+
});
|
105 |
const [modelList, setModelList] = useState(MODEL_LIST);
|
106 |
const [isModelSettingsCollapsed, setIsModelSettingsCollapsed] = useState(false);
|
107 |
const [isListening, setIsListening] = useState(false);
|
108 |
const [recognition, setRecognition] = useState<SpeechRecognition | null>(null);
|
109 |
const [transcript, setTranscript] = useState('');
|
110 |
|
111 |
+
// Load enabled providers from cookies
|
112 |
+
const [enabledProviders, setEnabledProviders] = useState(() => {
|
113 |
+
const savedProviders = Cookies.get('providers');
|
114 |
+
|
115 |
+
if (savedProviders) {
|
116 |
+
try {
|
117 |
+
const parsedProviders = JSON.parse(savedProviders);
|
118 |
+
return PROVIDER_LIST.filter((p) => parsedProviders[p.name]);
|
119 |
+
} catch (error) {
|
120 |
+
console.error('Failed to parse providers from cookies:', error);
|
121 |
+
return PROVIDER_LIST;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
return PROVIDER_LIST;
|
126 |
+
});
|
127 |
+
|
128 |
+
// Update enabled providers when cookies change
|
129 |
+
useEffect(() => {
|
130 |
+
const updateProvidersFromCookies = () => {
|
131 |
+
const savedProviders = Cookies.get('providers');
|
132 |
+
|
133 |
+
if (savedProviders) {
|
134 |
+
try {
|
135 |
+
const parsedProviders = JSON.parse(savedProviders);
|
136 |
+
setEnabledProviders(PROVIDER_LIST.filter((p) => parsedProviders[p.name]));
|
137 |
+
} catch (error) {
|
138 |
+
console.error('Failed to parse providers from cookies:', error);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
};
|
142 |
+
|
143 |
+
updateProvidersFromCookies();
|
144 |
+
|
145 |
+
const interval = setInterval(updateProvidersFromCookies, 1000);
|
146 |
+
|
147 |
+
return () => clearInterval(interval);
|
148 |
+
}, [PROVIDER_LIST]);
|
149 |
+
|
150 |
+
useEffect(() => {
|
151 |
+
console.log(transcript);
|
152 |
+
}, [transcript]);
|
153 |
useEffect(() => {
|
154 |
// Load API keys from cookies on component mount
|
155 |
try {
|
|
|
238 |
}
|
239 |
};
|
240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
const handleFileUpload = () => {
|
242 |
const input = document.createElement('input');
|
243 |
input.type = 'file';
|
|
|
293 |
const baseChat = (
|
294 |
<div
|
295 |
ref={ref}
|
296 |
+
className={classNames(styles.BaseChat, 'relative flex h-full w-full overflow-hidden')}
|
|
|
|
|
|
|
297 |
data-chat-visible={showChat}
|
298 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
<ClientOnly>{() => <Menu />}</ClientOnly>
|
300 |
<div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
|
301 |
<div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
|
|
|
345 |
gradientUnits="userSpaceOnUse"
|
346 |
gradientTransform="rotate(-45)"
|
347 |
>
|
348 |
+
<stop offset="0%" stopColor="#b44aff" stopOpacity="0%"></stop>
|
349 |
+
<stop offset="40%" stopColor="#b44aff" stopOpacity="80%"></stop>
|
350 |
+
<stop offset="50%" stopColor="#b44aff" stopOpacity="80%"></stop>
|
351 |
+
<stop offset="100%" stopColor="#b44aff" stopOpacity="0%"></stop>
|
352 |
</linearGradient>
|
353 |
<linearGradient id="shine-gradient">
|
354 |
<stop offset="0%" stopColor="white" stopOpacity="0%"></stop>
|
355 |
+
<stop offset="40%" stopColor="#ffffff" stopOpacity="80%"></stop>
|
356 |
+
<stop offset="50%" stopColor="#ffffff" stopOpacity="80%"></stop>
|
357 |
<stop offset="100%" stopColor="white" stopOpacity="0%"></stop>
|
358 |
</linearGradient>
|
359 |
</defs>
|
|
|
361 |
<rect className={classNames(styles.PromptShine)} x="48" y="24" width="70" height="1"></rect>
|
362 |
</svg>
|
363 |
<div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
<div className={isModelSettingsCollapsed ? 'hidden' : ''}>
|
365 |
<ModelSelector
|
366 |
key={provider?.name + ':' + modelList.length}
|
|
|
372 |
providerList={PROVIDER_LIST}
|
373 |
apiKeys={apiKeys}
|
374 |
/>
|
375 |
+
{enabledProviders.length > 0 && provider && (
|
376 |
<APIKeyManager
|
377 |
provider={provider}
|
378 |
apiKey={apiKeys[provider.name] || ''}
|
379 |
+
setApiKey={(key) => {
|
380 |
+
const newApiKeys = { ...apiKeys, [provider.name]: key };
|
381 |
+
setApiKeys(newApiKeys);
|
382 |
+
Cookies.set('apiKeys', JSON.stringify(newApiKeys));
|
383 |
+
}}
|
384 |
/>
|
385 |
)}
|
386 |
</div>
|
|
|
468 |
<SendButton
|
469 |
show={input.length > 0 || isStreaming || uploadedFiles.length > 0}
|
470 |
isStreaming={isStreaming}
|
471 |
+
disabled={enabledProviders.length === 0}
|
472 |
onClick={(event) => {
|
473 |
if (isStreaming) {
|
474 |
handleStop?.();
|
|
|
519 |
disabled={isStreaming}
|
520 |
/>
|
521 |
{chatStarted && <ClientOnly>{() => <ExportChatButton exportChat={exportChat} />}</ClientOnly>}
|
522 |
+
<IconButton
|
523 |
+
title="Model Settings"
|
524 |
+
className={classNames('transition-all flex items-center gap-1', {
|
525 |
+
'bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent':
|
526 |
+
isModelSettingsCollapsed,
|
527 |
+
'bg-bolt-elements-item-backgroundDefault text-bolt-elements-item-contentDefault':
|
528 |
+
!isModelSettingsCollapsed,
|
529 |
+
})}
|
530 |
+
onClick={() => setIsModelSettingsCollapsed(!isModelSettingsCollapsed)}
|
531 |
+
disabled={enabledProviders.length === 0}
|
532 |
+
>
|
533 |
+
<div className={`i-ph:caret-${isModelSettingsCollapsed ? 'right' : 'down'} text-lg`} />
|
534 |
+
{isModelSettingsCollapsed ? <span className="text-xs">{model}</span> : <span />}
|
535 |
+
</IconButton>
|
536 |
</div>
|
537 |
{input.length > 3 ? (
|
538 |
<div className="text-xs text-bolt-elements-textTertiary">
|
|
|
545 |
</div>
|
546 |
</div>
|
547 |
</div>
|
548 |
+
{!chatStarted && (
|
549 |
+
<div className="flex justify-center gap-2">
|
550 |
+
{ImportButtons(importChat)}
|
551 |
+
<GitCloneButton importChat={importChat} />
|
552 |
+
</div>
|
553 |
+
)}
|
554 |
{!chatStarted &&
|
555 |
ExamplePrompts((event, messageInput) => {
|
556 |
if (isStreaming) {
|
app/components/chat/GitCloneButton.tsx
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import ignore from 'ignore';
|
2 |
+
import { useGit } from '~/lib/hooks/useGit';
|
3 |
+
import type { Message } from 'ai';
|
4 |
+
import WithTooltip from '~/components/ui/Tooltip';
|
5 |
+
import { detectProjectCommands, createCommandsMessage } from '~/utils/projectCommands';
|
6 |
+
import { generateId } from '~/utils/fileUtils';
|
7 |
+
|
8 |
+
const IGNORE_PATTERNS = [
|
9 |
+
'node_modules/**',
|
10 |
+
'.git/**',
|
11 |
+
'.github/**',
|
12 |
+
'.vscode/**',
|
13 |
+
'**/*.jpg',
|
14 |
+
'**/*.jpeg',
|
15 |
+
'**/*.png',
|
16 |
+
'dist/**',
|
17 |
+
'build/**',
|
18 |
+
'.next/**',
|
19 |
+
'coverage/**',
|
20 |
+
'.cache/**',
|
21 |
+
'.vscode/**',
|
22 |
+
'.idea/**',
|
23 |
+
'**/*.log',
|
24 |
+
'**/.DS_Store',
|
25 |
+
'**/npm-debug.log*',
|
26 |
+
'**/yarn-debug.log*',
|
27 |
+
'**/yarn-error.log*',
|
28 |
+
'**/*lock.json',
|
29 |
+
'**/*lock.yaml',
|
30 |
+
];
|
31 |
+
|
32 |
+
const ig = ignore().add(IGNORE_PATTERNS);
|
33 |
+
|
34 |
+
interface GitCloneButtonProps {
|
35 |
+
className?: string;
|
36 |
+
importChat?: (description: string, messages: Message[]) => Promise<void>;
|
37 |
+
}
|
38 |
+
|
39 |
+
export default function GitCloneButton({ importChat }: GitCloneButtonProps) {
|
40 |
+
const { ready, gitClone } = useGit();
|
41 |
+
const onClick = async (_e: any) => {
|
42 |
+
if (!ready) {
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
|
46 |
+
const repoUrl = prompt('Enter the Git url');
|
47 |
+
|
48 |
+
if (repoUrl) {
|
49 |
+
const { workdir, data } = await gitClone(repoUrl);
|
50 |
+
|
51 |
+
if (importChat) {
|
52 |
+
const filePaths = Object.keys(data).filter((filePath) => !ig.ignores(filePath));
|
53 |
+
console.log(filePaths);
|
54 |
+
|
55 |
+
const textDecoder = new TextDecoder('utf-8');
|
56 |
+
|
57 |
+
// Convert files to common format for command detection
|
58 |
+
const fileContents = filePaths
|
59 |
+
.map((filePath) => {
|
60 |
+
const { data: content, encoding } = data[filePath];
|
61 |
+
return {
|
62 |
+
path: filePath,
|
63 |
+
content: encoding === 'utf8' ? content : content instanceof Uint8Array ? textDecoder.decode(content) : '',
|
64 |
+
};
|
65 |
+
})
|
66 |
+
.filter((f) => f.content);
|
67 |
+
|
68 |
+
// Detect and create commands message
|
69 |
+
const commands = await detectProjectCommands(fileContents);
|
70 |
+
const commandsMessage = createCommandsMessage(commands);
|
71 |
+
|
72 |
+
// Create files message
|
73 |
+
const filesMessage: Message = {
|
74 |
+
role: 'assistant',
|
75 |
+
content: `Cloning the repo ${repoUrl} into ${workdir}
|
76 |
+
<boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
|
77 |
+
${fileContents
|
78 |
+
.map(
|
79 |
+
(file) =>
|
80 |
+
`<boltAction type="file" filePath="${file.path}">
|
81 |
+
${file.content}
|
82 |
+
</boltAction>`,
|
83 |
+
)
|
84 |
+
.join('\n')}
|
85 |
+
</boltArtifact>`,
|
86 |
+
id: generateId(),
|
87 |
+
createdAt: new Date(),
|
88 |
+
};
|
89 |
+
|
90 |
+
const messages = [filesMessage];
|
91 |
+
|
92 |
+
if (commandsMessage) {
|
93 |
+
messages.push(commandsMessage);
|
94 |
+
}
|
95 |
+
|
96 |
+
await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages);
|
97 |
+
}
|
98 |
+
}
|
99 |
+
};
|
100 |
+
|
101 |
+
return (
|
102 |
+
<WithTooltip tooltip="Clone A Git Repo">
|
103 |
+
<button
|
104 |
+
onClick={(e) => {
|
105 |
+
onClick(e);
|
106 |
+
}}
|
107 |
+
title="Clone A Git Repo"
|
108 |
+
className="px-4 py-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-3 transition-all flex items-center gap-2"
|
109 |
+
>
|
110 |
+
<span className="i-ph:git-branch" />
|
111 |
+
Clone A Git Repo
|
112 |
+
</button>
|
113 |
+
</WithTooltip>
|
114 |
+
);
|
115 |
+
}
|
app/components/chat/ImportFolderButton.tsx
CHANGED
@@ -1,102 +1,75 @@
|
|
1 |
-
import React from 'react';
|
2 |
import type { Message } from 'ai';
|
3 |
import { toast } from 'react-toastify';
|
4 |
-
import
|
|
|
5 |
|
6 |
interface ImportFolderButtonProps {
|
7 |
className?: string;
|
8 |
importChat?: (description: string, messages: Message[]) => Promise<void>;
|
9 |
}
|
10 |
|
11 |
-
|
12 |
-
const
|
13 |
-
'node_modules/**',
|
14 |
-
'.git/**',
|
15 |
-
'dist/**',
|
16 |
-
'build/**',
|
17 |
-
'.next/**',
|
18 |
-
'coverage/**',
|
19 |
-
'.cache/**',
|
20 |
-
'.vscode/**',
|
21 |
-
'.idea/**',
|
22 |
-
'**/*.log',
|
23 |
-
'**/.DS_Store',
|
24 |
-
'**/npm-debug.log*',
|
25 |
-
'**/yarn-debug.log*',
|
26 |
-
'**/yarn-error.log*',
|
27 |
-
];
|
28 |
-
|
29 |
-
const ig = ignore().add(IGNORE_PATTERNS);
|
30 |
-
const generateId = () => Math.random().toString(36).substring(2, 15);
|
31 |
-
|
32 |
-
const isBinaryFile = async (file: File): Promise<boolean> => {
|
33 |
-
const chunkSize = 1024; // Read the first 1 KB of the file
|
34 |
-
const buffer = new Uint8Array(await file.slice(0, chunkSize).arrayBuffer());
|
35 |
-
|
36 |
-
for (let i = 0; i < buffer.length; i++) {
|
37 |
-
const byte = buffer[i];
|
38 |
-
|
39 |
-
if (byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)) {
|
40 |
-
return true; // Found a binary character
|
41 |
-
}
|
42 |
-
}
|
43 |
|
44 |
-
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
|
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
})
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
${
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
}
|
101 |
};
|
102 |
|
@@ -108,46 +81,8 @@ ${fileArtifacts.join('\n\n')}
|
|
108 |
className="hidden"
|
109 |
webkitdirectory=""
|
110 |
directory=""
|
111 |
-
onChange={
|
112 |
-
|
113 |
-
const filteredFiles = allFiles.filter((file) => shouldIncludeFile(file.webkitRelativePath));
|
114 |
-
|
115 |
-
if (filteredFiles.length === 0) {
|
116 |
-
toast.error('No files found in the selected folder');
|
117 |
-
return;
|
118 |
-
}
|
119 |
-
|
120 |
-
try {
|
121 |
-
const fileChecks = await Promise.all(
|
122 |
-
filteredFiles.map(async (file) => ({
|
123 |
-
file,
|
124 |
-
isBinary: await isBinaryFile(file),
|
125 |
-
})),
|
126 |
-
);
|
127 |
-
|
128 |
-
const textFiles = fileChecks.filter((f) => !f.isBinary).map((f) => f.file);
|
129 |
-
const binaryFilePaths = fileChecks
|
130 |
-
.filter((f) => f.isBinary)
|
131 |
-
.map((f) => f.file.webkitRelativePath.split('/').slice(1).join('/'));
|
132 |
-
|
133 |
-
if (textFiles.length === 0) {
|
134 |
-
toast.error('No text files found in the selected folder');
|
135 |
-
return;
|
136 |
-
}
|
137 |
-
|
138 |
-
if (binaryFilePaths.length > 0) {
|
139 |
-
toast.info(`Skipping ${binaryFilePaths.length} binary files`);
|
140 |
-
}
|
141 |
-
|
142 |
-
await createChatFromFolder(textFiles, binaryFilePaths);
|
143 |
-
} catch (error) {
|
144 |
-
console.error('Failed to import folder:', error);
|
145 |
-
toast.error('Failed to import folder');
|
146 |
-
}
|
147 |
-
|
148 |
-
e.target.value = ''; // Reset file input
|
149 |
-
}}
|
150 |
-
{...({} as any)} // if removed webkitdirectory will throw errors as unknow attribute
|
151 |
/>
|
152 |
<button
|
153 |
onClick={() => {
|
@@ -155,9 +90,10 @@ ${fileArtifacts.join('\n\n')}
|
|
155 |
input?.click();
|
156 |
}}
|
157 |
className={className}
|
|
|
158 |
>
|
159 |
<div className="i-ph:upload-simple" />
|
160 |
-
Import Folder
|
161 |
</button>
|
162 |
</>
|
163 |
);
|
|
|
1 |
+
import React, { useState } from 'react';
|
2 |
import type { Message } from 'ai';
|
3 |
import { toast } from 'react-toastify';
|
4 |
+
import { MAX_FILES, isBinaryFile, shouldIncludeFile } from '~/utils/fileUtils';
|
5 |
+
import { createChatFromFolder } from '~/utils/folderImport';
|
6 |
|
7 |
interface ImportFolderButtonProps {
|
8 |
className?: string;
|
9 |
importChat?: (description: string, messages: Message[]) => Promise<void>;
|
10 |
}
|
11 |
|
12 |
+
export const ImportFolderButton: React.FC<ImportFolderButtonProps> = ({ className, importChat }) => {
|
13 |
+
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
+
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
16 |
+
const allFiles = Array.from(e.target.files || []);
|
17 |
|
18 |
+
if (allFiles.length > MAX_FILES) {
|
19 |
+
toast.error(
|
20 |
+
`This folder contains ${allFiles.length.toLocaleString()} files. This product is not yet optimized for very large projects. Please select a folder with fewer than ${MAX_FILES.toLocaleString()} files.`,
|
21 |
+
);
|
22 |
+
return;
|
23 |
+
}
|
24 |
|
25 |
+
const folderName = allFiles[0]?.webkitRelativePath.split('/')[0] || 'Unknown Folder';
|
26 |
+
setIsLoading(true);
|
27 |
+
|
28 |
+
const loadingToast = toast.loading(`Importing ${folderName}...`);
|
29 |
+
|
30 |
+
try {
|
31 |
+
const filteredFiles = allFiles.filter((file) => shouldIncludeFile(file.webkitRelativePath));
|
32 |
+
|
33 |
+
if (filteredFiles.length === 0) {
|
34 |
+
toast.error('No files found in the selected folder');
|
35 |
+
return;
|
36 |
+
}
|
37 |
+
|
38 |
+
const fileChecks = await Promise.all(
|
39 |
+
filteredFiles.map(async (file) => ({
|
40 |
+
file,
|
41 |
+
isBinary: await isBinaryFile(file),
|
42 |
+
})),
|
43 |
+
);
|
44 |
+
|
45 |
+
const textFiles = fileChecks.filter((f) => !f.isBinary).map((f) => f.file);
|
46 |
+
const binaryFilePaths = fileChecks
|
47 |
+
.filter((f) => f.isBinary)
|
48 |
+
.map((f) => f.file.webkitRelativePath.split('/').slice(1).join('/'));
|
49 |
+
|
50 |
+
if (textFiles.length === 0) {
|
51 |
+
toast.error('No text files found in the selected folder');
|
52 |
+
return;
|
53 |
+
}
|
54 |
+
|
55 |
+
if (binaryFilePaths.length > 0) {
|
56 |
+
toast.info(`Skipping ${binaryFilePaths.length} binary files`);
|
57 |
+
}
|
58 |
+
|
59 |
+
const messages = await createChatFromFolder(textFiles, binaryFilePaths, folderName);
|
60 |
+
|
61 |
+
if (importChat) {
|
62 |
+
await importChat(folderName, [...messages]);
|
63 |
+
}
|
64 |
+
|
65 |
+
toast.success('Folder imported successfully');
|
66 |
+
} catch (error) {
|
67 |
+
console.error('Failed to import folder:', error);
|
68 |
+
toast.error('Failed to import folder');
|
69 |
+
} finally {
|
70 |
+
setIsLoading(false);
|
71 |
+
toast.dismiss(loadingToast);
|
72 |
+
e.target.value = ''; // Reset file input
|
73 |
}
|
74 |
};
|
75 |
|
|
|
81 |
className="hidden"
|
82 |
webkitdirectory=""
|
83 |
directory=""
|
84 |
+
onChange={handleFileChange}
|
85 |
+
{...({} as any)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
/>
|
87 |
<button
|
88 |
onClick={() => {
|
|
|
90 |
input?.click();
|
91 |
}}
|
92 |
className={className}
|
93 |
+
disabled={isLoading}
|
94 |
>
|
95 |
<div className="i-ph:upload-simple" />
|
96 |
+
{isLoading ? 'Importing...' : 'Import Folder'}
|
97 |
</button>
|
98 |
</>
|
99 |
);
|
app/components/chat/ModelSelector.tsx
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
import type { ProviderInfo } from '~/types/model';
|
2 |
import type { ModelInfo } from '~/utils/types';
|
|
|
|
|
3 |
|
4 |
interface ModelSelectorProps {
|
5 |
model?: string;
|
@@ -19,12 +21,79 @@ export const ModelSelector = ({
|
|
19 |
modelList,
|
20 |
providerList,
|
21 |
}: ModelSelectorProps) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
return (
|
23 |
<div className="mb-2 flex gap-2 flex-col sm:flex-row">
|
24 |
<select
|
25 |
value={provider?.name ?? ''}
|
26 |
onChange={(e) => {
|
27 |
-
const newProvider =
|
28 |
|
29 |
if (newProvider && setProvider) {
|
30 |
setProvider(newProvider);
|
@@ -38,7 +107,7 @@ export const ModelSelector = ({
|
|
38 |
}}
|
39 |
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all"
|
40 |
>
|
41 |
-
{
|
42 |
<option key={provider.name} value={provider.name}>
|
43 |
{provider.name}
|
44 |
</option>
|
@@ -52,8 +121,8 @@ export const ModelSelector = ({
|
|
52 |
>
|
53 |
{[...modelList]
|
54 |
.filter((e) => e.provider == provider?.name && e.name)
|
55 |
-
.map((modelOption) => (
|
56 |
-
<option key={
|
57 |
{modelOption.label}
|
58 |
</option>
|
59 |
))}
|
|
|
1 |
import type { ProviderInfo } from '~/types/model';
|
2 |
import type { ModelInfo } from '~/utils/types';
|
3 |
+
import { useEffect, useState } from 'react';
|
4 |
+
import Cookies from 'js-cookie';
|
5 |
|
6 |
interface ModelSelectorProps {
|
7 |
model?: string;
|
|
|
21 |
modelList,
|
22 |
providerList,
|
23 |
}: ModelSelectorProps) => {
|
24 |
+
// Load enabled providers from cookies
|
25 |
+
const [enabledProviders, setEnabledProviders] = useState(() => {
|
26 |
+
const savedProviders = Cookies.get('providers');
|
27 |
+
|
28 |
+
if (savedProviders) {
|
29 |
+
try {
|
30 |
+
const parsedProviders = JSON.parse(savedProviders);
|
31 |
+
return providerList.filter((p) => parsedProviders[p.name]);
|
32 |
+
} catch (error) {
|
33 |
+
console.error('Failed to parse providers from cookies:', error);
|
34 |
+
return providerList;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
return providerList;
|
39 |
+
});
|
40 |
+
|
41 |
+
// Update enabled providers when cookies change
|
42 |
+
useEffect(() => {
|
43 |
+
// Function to update providers from cookies
|
44 |
+
const updateProvidersFromCookies = () => {
|
45 |
+
const savedProviders = Cookies.get('providers');
|
46 |
+
|
47 |
+
if (savedProviders) {
|
48 |
+
try {
|
49 |
+
const parsedProviders = JSON.parse(savedProviders);
|
50 |
+
const newEnabledProviders = providerList.filter((p) => parsedProviders[p.name]);
|
51 |
+
setEnabledProviders(newEnabledProviders);
|
52 |
+
|
53 |
+
// If current provider is disabled, switch to first enabled provider
|
54 |
+
if (provider && !parsedProviders[provider.name] && newEnabledProviders.length > 0) {
|
55 |
+
const firstEnabledProvider = newEnabledProviders[0];
|
56 |
+
setProvider?.(firstEnabledProvider);
|
57 |
+
|
58 |
+
// Also update the model to the first available one for the new provider
|
59 |
+
const firstModel = modelList.find((m) => m.provider === firstEnabledProvider.name);
|
60 |
+
|
61 |
+
if (firstModel) {
|
62 |
+
setModel?.(firstModel.name);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
} catch (error) {
|
66 |
+
console.error('Failed to parse providers from cookies:', error);
|
67 |
+
}
|
68 |
+
}
|
69 |
+
};
|
70 |
+
|
71 |
+
// Initial update
|
72 |
+
updateProvidersFromCookies();
|
73 |
+
|
74 |
+
// Set up an interval to check for cookie changes
|
75 |
+
const interval = setInterval(updateProvidersFromCookies, 1000);
|
76 |
+
|
77 |
+
return () => clearInterval(interval);
|
78 |
+
}, [providerList, provider, setProvider, modelList, setModel]);
|
79 |
+
|
80 |
+
if (enabledProviders.length === 0) {
|
81 |
+
return (
|
82 |
+
<div className="mb-2 p-4 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary">
|
83 |
+
<p className="text-center">
|
84 |
+
No providers are currently enabled. Please enable at least one provider in the settings to start using the
|
85 |
+
chat.
|
86 |
+
</p>
|
87 |
+
</div>
|
88 |
+
);
|
89 |
+
}
|
90 |
+
|
91 |
return (
|
92 |
<div className="mb-2 flex gap-2 flex-col sm:flex-row">
|
93 |
<select
|
94 |
value={provider?.name ?? ''}
|
95 |
onChange={(e) => {
|
96 |
+
const newProvider = enabledProviders.find((p: ProviderInfo) => p.name === e.target.value);
|
97 |
|
98 |
if (newProvider && setProvider) {
|
99 |
setProvider(newProvider);
|
|
|
107 |
}}
|
108 |
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all"
|
109 |
>
|
110 |
+
{enabledProviders.map((provider: ProviderInfo) => (
|
111 |
<option key={provider.name} value={provider.name}>
|
112 |
{provider.name}
|
113 |
</option>
|
|
|
121 |
>
|
122 |
{[...modelList]
|
123 |
.filter((e) => e.provider == provider?.name && e.name)
|
124 |
+
.map((modelOption, index) => (
|
125 |
+
<option key={index} value={modelOption.name}>
|
126 |
{modelOption.label}
|
127 |
</option>
|
128 |
))}
|
app/components/chat/SendButton.client.tsx
CHANGED
@@ -3,25 +3,30 @@ import { AnimatePresence, cubicBezier, motion } from 'framer-motion';
|
|
3 |
interface SendButtonProps {
|
4 |
show: boolean;
|
5 |
isStreaming?: boolean;
|
|
|
6 |
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
7 |
onImagesSelected?: (images: File[]) => void;
|
8 |
}
|
9 |
|
10 |
const customEasingFn = cubicBezier(0.4, 0, 0.2, 1);
|
11 |
|
12 |
-
export const SendButton = ({ show, isStreaming, onClick }: SendButtonProps) => {
|
13 |
return (
|
14 |
<AnimatePresence>
|
15 |
{show ? (
|
16 |
<motion.button
|
17 |
-
className="absolute flex justify-center items-center top-[18px] right-[22px] p-1 bg-accent-500 hover:brightness-94 color-white rounded-md w-[34px] h-[34px] transition-theme"
|
18 |
transition={{ ease: customEasingFn, duration: 0.17 }}
|
19 |
initial={{ opacity: 0, y: 10 }}
|
20 |
animate={{ opacity: 1, y: 0 }}
|
21 |
exit={{ opacity: 0, y: 10 }}
|
|
|
22 |
onClick={(event) => {
|
23 |
event.preventDefault();
|
24 |
-
|
|
|
|
|
|
|
25 |
}}
|
26 |
>
|
27 |
<div className="text-lg">
|
|
|
3 |
interface SendButtonProps {
|
4 |
show: boolean;
|
5 |
isStreaming?: boolean;
|
6 |
+
disabled?: boolean;
|
7 |
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
8 |
onImagesSelected?: (images: File[]) => void;
|
9 |
}
|
10 |
|
11 |
const customEasingFn = cubicBezier(0.4, 0, 0.2, 1);
|
12 |
|
13 |
+
export const SendButton = ({ show, isStreaming, disabled, onClick }: SendButtonProps) => {
|
14 |
return (
|
15 |
<AnimatePresence>
|
16 |
{show ? (
|
17 |
<motion.button
|
18 |
+
className="absolute flex justify-center items-center top-[18px] right-[22px] p-1 bg-accent-500 hover:brightness-94 color-white rounded-md w-[34px] h-[34px] transition-theme disabled:opacity-50 disabled:cursor-not-allowed"
|
19 |
transition={{ ease: customEasingFn, duration: 0.17 }}
|
20 |
initial={{ opacity: 0, y: 10 }}
|
21 |
animate={{ opacity: 1, y: 0 }}
|
22 |
exit={{ opacity: 0, y: 10 }}
|
23 |
+
disabled={disabled}
|
24 |
onClick={(event) => {
|
25 |
event.preventDefault();
|
26 |
+
|
27 |
+
if (!disabled) {
|
28 |
+
onClick?.(event);
|
29 |
+
}
|
30 |
}}
|
31 |
>
|
32 |
<div className="text-lg">
|
app/components/chat/chatExportAndImport/ImportButtons.tsx
CHANGED
@@ -5,7 +5,7 @@ import { ImportFolderButton } from '~/components/chat/ImportFolderButton';
|
|
5 |
|
6 |
export function ImportButtons(importChat: ((description: string, messages: Message[]) => Promise<void>) | undefined) {
|
7 |
return (
|
8 |
-
<div className="flex flex-col items-center justify-center
|
9 |
<input
|
10 |
type="file"
|
11 |
id="chat-import"
|
|
|
5 |
|
6 |
export function ImportButtons(importChat: ((description: string, messages: Message[]) => Promise<void>) | undefined) {
|
7 |
return (
|
8 |
+
<div className="flex flex-col items-center justify-center w-auto">
|
9 |
<input
|
10 |
type="file"
|
11 |
id="chat-import"
|
app/components/editor/codemirror/languages.ts
CHANGED
@@ -1,6 +1,13 @@
|
|
1 |
import { LanguageDescription } from '@codemirror/language';
|
2 |
|
3 |
export const supportedLanguages = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
LanguageDescription.of({
|
5 |
name: 'TS',
|
6 |
extensions: ['ts'],
|
|
|
1 |
import { LanguageDescription } from '@codemirror/language';
|
2 |
|
3 |
export const supportedLanguages = [
|
4 |
+
LanguageDescription.of({
|
5 |
+
name: 'VUE',
|
6 |
+
extensions: ['vue'],
|
7 |
+
async load() {
|
8 |
+
return import('@codemirror/lang-vue').then((module) => module.vue());
|
9 |
+
},
|
10 |
+
}),
|
11 |
LanguageDescription.of({
|
12 |
name: 'TS',
|
13 |
extensions: ['ts'],
|
app/components/git/GitUrlImport.client.tsx
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands';
|
11 |
+
|
12 |
+
const IGNORE_PATTERNS = [
|
13 |
+
'node_modules/**',
|
14 |
+
'.git/**',
|
15 |
+
'.github/**',
|
16 |
+
'.vscode/**',
|
17 |
+
'**/*.jpg',
|
18 |
+
'**/*.jpeg',
|
19 |
+
'**/*.png',
|
20 |
+
'dist/**',
|
21 |
+
'build/**',
|
22 |
+
'.next/**',
|
23 |
+
'coverage/**',
|
24 |
+
'.cache/**',
|
25 |
+
'.vscode/**',
|
26 |
+
'.idea/**',
|
27 |
+
'**/*.log',
|
28 |
+
'**/.DS_Store',
|
29 |
+
'**/npm-debug.log*',
|
30 |
+
'**/yarn-debug.log*',
|
31 |
+
'**/yarn-error.log*',
|
32 |
+
'**/*lock.json',
|
33 |
+
'**/*lock.yaml',
|
34 |
+
];
|
35 |
+
|
36 |
+
export function GitUrlImport() {
|
37 |
+
const [searchParams] = useSearchParams();
|
38 |
+
const { ready: historyReady, importChat } = useChatHistory();
|
39 |
+
const { ready: gitReady, gitClone } = useGit();
|
40 |
+
const [imported, setImported] = useState(false);
|
41 |
+
|
42 |
+
const importRepo = async (repoUrl?: string) => {
|
43 |
+
if (!gitReady && !historyReady) {
|
44 |
+
return;
|
45 |
+
}
|
46 |
+
|
47 |
+
if (repoUrl) {
|
48 |
+
const ig = ignore().add(IGNORE_PATTERNS);
|
49 |
+
const { workdir, data } = await gitClone(repoUrl);
|
50 |
+
|
51 |
+
if (importChat) {
|
52 |
+
const filePaths = Object.keys(data).filter((filePath) => !ig.ignores(filePath));
|
53 |
+
|
54 |
+
const textDecoder = new TextDecoder('utf-8');
|
55 |
+
|
56 |
+
// Convert files to common format for command detection
|
57 |
+
const fileContents = filePaths
|
58 |
+
.map((filePath) => {
|
59 |
+
const { data: content, encoding } = data[filePath];
|
60 |
+
return {
|
61 |
+
path: filePath,
|
62 |
+
content: encoding === 'utf8' ? content : content instanceof Uint8Array ? textDecoder.decode(content) : '',
|
63 |
+
};
|
64 |
+
})
|
65 |
+
.filter((f) => f.content);
|
66 |
+
|
67 |
+
// Detect and create commands message
|
68 |
+
const commands = await detectProjectCommands(fileContents);
|
69 |
+
const commandsMessage = createCommandsMessage(commands);
|
70 |
+
|
71 |
+
// Create files message
|
72 |
+
const filesMessage: Message = {
|
73 |
+
role: 'assistant',
|
74 |
+
content: `Cloning the repo ${repoUrl} into ${workdir}
|
75 |
+
<boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
|
76 |
+
${fileContents
|
77 |
+
.map(
|
78 |
+
(file) =>
|
79 |
+
`<boltAction type="file" filePath="${file.path}">
|
80 |
+
${file.content}
|
81 |
+
</boltAction>`,
|
82 |
+
)
|
83 |
+
.join('\n')}
|
84 |
+
</boltArtifact>`,
|
85 |
+
id: generateId(),
|
86 |
+
createdAt: new Date(),
|
87 |
+
};
|
88 |
+
|
89 |
+
const messages = [filesMessage];
|
90 |
+
|
91 |
+
if (commandsMessage) {
|
92 |
+
messages.push(commandsMessage);
|
93 |
+
}
|
94 |
+
|
95 |
+
await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages);
|
96 |
+
}
|
97 |
+
}
|
98 |
+
};
|
99 |
+
|
100 |
+
useEffect(() => {
|
101 |
+
if (!historyReady || !gitReady || imported) {
|
102 |
+
return;
|
103 |
+
}
|
104 |
+
|
105 |
+
const url = searchParams.get('url');
|
106 |
+
|
107 |
+
if (!url) {
|
108 |
+
window.location.href = '/';
|
109 |
+
return;
|
110 |
+
}
|
111 |
+
|
112 |
+
importRepo(url);
|
113 |
+
setImported(true);
|
114 |
+
}, [searchParams, historyReady, gitReady, imported]);
|
115 |
+
|
116 |
+
return <ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>;
|
117 |
+
}
|
app/components/header/Header.tsx
CHANGED
@@ -10,18 +10,17 @@ export function Header() {
|
|
10 |
|
11 |
return (
|
12 |
<header
|
13 |
-
className={classNames(
|
14 |
-
'
|
15 |
-
|
16 |
-
|
17 |
-
'border-bolt-elements-borderColor': chat.started,
|
18 |
-
},
|
19 |
-
)}
|
20 |
>
|
21 |
<div className="flex items-center gap-2 z-logo text-bolt-elements-textPrimary cursor-pointer">
|
22 |
<div className="i-ph:sidebar-simple-duotone text-xl" />
|
23 |
<a href="/" className="text-2xl font-semibold text-accent flex items-center">
|
24 |
-
<span className="i-bolt:logo-text?mask w-[46px] inline-block" />
|
|
|
|
|
25 |
</a>
|
26 |
</div>
|
27 |
{chat.started && ( // Display ChatDescription and HeaderActionButtons only when the chat has started.
|
|
|
10 |
|
11 |
return (
|
12 |
<header
|
13 |
+
className={classNames('flex items-center p-5 border-b h-[var(--header-height)]', {
|
14 |
+
'border-transparent': !chat.started,
|
15 |
+
'border-bolt-elements-borderColor': chat.started,
|
16 |
+
})}
|
|
|
|
|
|
|
17 |
>
|
18 |
<div className="flex items-center gap-2 z-logo text-bolt-elements-textPrimary cursor-pointer">
|
19 |
<div className="i-ph:sidebar-simple-duotone text-xl" />
|
20 |
<a href="/" className="text-2xl font-semibold text-accent flex items-center">
|
21 |
+
{/* <span className="i-bolt:logo-text?mask w-[46px] inline-block" /> */}
|
22 |
+
<img src="/logo-light-styled.png" alt="logo" className="w-[90px] inline-block dark:hidden" />
|
23 |
+
<img src="/logo-dark-styled.png" alt="logo" className="w-[90px] inline-block hidden dark:block" />
|
24 |
</a>
|
25 |
</div>
|
26 |
{chat.started && ( // Display ChatDescription and HeaderActionButtons only when the chat has started.
|
app/components/settings/Settings.module.scss
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.settings-tabs {
|
2 |
+
button {
|
3 |
+
width: 100%;
|
4 |
+
display: flex;
|
5 |
+
align-items: center;
|
6 |
+
gap: 0.5rem;
|
7 |
+
padding: 0.75rem 1rem;
|
8 |
+
border-radius: 0.5rem;
|
9 |
+
text-align: left;
|
10 |
+
font-size: 0.875rem;
|
11 |
+
transition: all 0.2s;
|
12 |
+
margin-bottom: 0.5rem;
|
13 |
+
|
14 |
+
&.active {
|
15 |
+
background: var(--bolt-elements-button-primary-background);
|
16 |
+
color: var(--bolt-elements-textPrimary);
|
17 |
+
}
|
18 |
+
|
19 |
+
&:not(.active) {
|
20 |
+
background: var(--bolt-elements-bg-depth-3);
|
21 |
+
color: var(--bolt-elements-textPrimary);
|
22 |
+
|
23 |
+
&:hover {
|
24 |
+
background: var(--bolt-elements-button-primary-backgroundHover);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
.settings-button {
|
31 |
+
background-color: var(--bolt-elements-button-primary-background);
|
32 |
+
color: var(--bolt-elements-textPrimary);
|
33 |
+
border-radius: 0.5rem;
|
34 |
+
padding: 0.5rem 1rem;
|
35 |
+
transition: background-color 0.2s;
|
36 |
+
|
37 |
+
&:hover {
|
38 |
+
background-color: var(--bolt-elements-button-primary-backgroundHover);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
.settings-danger-area {
|
43 |
+
background-color: transparent;
|
44 |
+
color: var(--bolt-elements-textPrimary);
|
45 |
+
border-radius: 0.5rem;
|
46 |
+
padding: 1rem;
|
47 |
+
margin-bottom: 1rem;
|
48 |
+
border-style: solid;
|
49 |
+
border-color: var(--bolt-elements-button-danger-backgroundHover) ;
|
50 |
+
border-width: thin;
|
51 |
+
|
52 |
+
button {
|
53 |
+
background-color: var(--bolt-elements-button-danger-background);
|
54 |
+
color: var(--bolt-elements-button-danger-text);
|
55 |
+
border-radius: 0.5rem;
|
56 |
+
padding: 0.5rem 1rem;
|
57 |
+
transition: background-color 0.2s;
|
58 |
+
|
59 |
+
&:hover {
|
60 |
+
background-color: var(--bolt-elements-button-danger-backgroundHover);
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
app/components/settings/SettingsWindow.tsx
ADDED
@@ -0,0 +1,483 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as RadixDialog from '@radix-ui/react-dialog';
|
2 |
+
import { motion } from 'framer-motion';
|
3 |
+
import { useState } from 'react';
|
4 |
+
import { classNames } from '~/utils/classNames';
|
5 |
+
import { DialogTitle, dialogVariants, dialogBackdropVariants } from '~/components/ui/Dialog';
|
6 |
+
import { IconButton } from '~/components/ui/IconButton';
|
7 |
+
import { providersList } from '~/lib/stores/settings';
|
8 |
+
import { db, getAll, deleteById } from '~/lib/persistence';
|
9 |
+
import { toast } from 'react-toastify';
|
10 |
+
import { useNavigate } from '@remix-run/react';
|
11 |
+
import commit from '~/commit.json';
|
12 |
+
import Cookies from 'js-cookie';
|
13 |
+
import styles from './Settings.module.scss';
|
14 |
+
import { Switch } from '~/components/ui/Switch';
|
15 |
+
|
16 |
+
interface SettingsProps {
|
17 |
+
open: boolean;
|
18 |
+
onClose: () => void;
|
19 |
+
}
|
20 |
+
|
21 |
+
type TabType = 'chat-history' | 'providers' | 'features' | 'debug' | 'connection';
|
22 |
+
|
23 |
+
// Providers that support base URL configuration
|
24 |
+
const URL_CONFIGURABLE_PROVIDERS = ['Ollama', 'LMStudio', 'OpenAILike'];
|
25 |
+
|
26 |
+
export const SettingsWindow = ({ open, onClose }: SettingsProps) => {
|
27 |
+
const navigate = useNavigate();
|
28 |
+
const [activeTab, setActiveTab] = useState<TabType>('chat-history');
|
29 |
+
const [isDebugEnabled, setIsDebugEnabled] = useState(() => {
|
30 |
+
const savedDebugState = Cookies.get('isDebugEnabled');
|
31 |
+
return savedDebugState === 'true';
|
32 |
+
});
|
33 |
+
const [searchTerm, setSearchTerm] = useState('');
|
34 |
+
const [isDeleting, setIsDeleting] = useState(false);
|
35 |
+
const [githubUsername, setGithubUsername] = useState(Cookies.get('githubUsername') || '');
|
36 |
+
const [githubToken, setGithubToken] = useState(Cookies.get('githubToken') || '');
|
37 |
+
const [isLocalModelsEnabled, setIsLocalModelsEnabled] = useState(() => {
|
38 |
+
const savedLocalModelsState = Cookies.get('isLocalModelsEnabled');
|
39 |
+
return savedLocalModelsState === 'true';
|
40 |
+
});
|
41 |
+
|
42 |
+
// Load base URLs from cookies
|
43 |
+
const [baseUrls, setBaseUrls] = useState(() => {
|
44 |
+
const savedUrls = Cookies.get('providerBaseUrls');
|
45 |
+
|
46 |
+
if (savedUrls) {
|
47 |
+
try {
|
48 |
+
return JSON.parse(savedUrls);
|
49 |
+
} catch (error) {
|
50 |
+
console.error('Failed to parse base URLs from cookies:', error);
|
51 |
+
return {
|
52 |
+
Ollama: 'http://localhost:11434',
|
53 |
+
LMStudio: 'http://localhost:1234',
|
54 |
+
OpenAILike: '',
|
55 |
+
};
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
return {
|
60 |
+
Ollama: 'http://localhost:11434',
|
61 |
+
LMStudio: 'http://localhost:1234',
|
62 |
+
OpenAILike: '',
|
63 |
+
};
|
64 |
+
});
|
65 |
+
|
66 |
+
const handleBaseUrlChange = (provider: string, url: string) => {
|
67 |
+
setBaseUrls((prev: Record<string, string>) => {
|
68 |
+
const newUrls = { ...prev, [provider]: url };
|
69 |
+
Cookies.set('providerBaseUrls', JSON.stringify(newUrls));
|
70 |
+
|
71 |
+
return newUrls;
|
72 |
+
});
|
73 |
+
};
|
74 |
+
|
75 |
+
const tabs: { id: TabType; label: string; icon: string }[] = [
|
76 |
+
{ id: 'chat-history', label: 'Chat History', icon: 'i-ph:book' },
|
77 |
+
{ id: 'providers', label: 'Providers', icon: 'i-ph:key' },
|
78 |
+
{ id: 'features', label: 'Features', icon: 'i-ph:star' },
|
79 |
+
{ id: 'connection', label: 'Connection', icon: 'i-ph:link' },
|
80 |
+
...(isDebugEnabled ? [{ id: 'debug' as TabType, label: 'Debug Tab', icon: 'i-ph:bug' }] : []),
|
81 |
+
];
|
82 |
+
|
83 |
+
// Load providers from cookies on mount
|
84 |
+
const [providers, setProviders] = useState(() => {
|
85 |
+
const savedProviders = Cookies.get('providers');
|
86 |
+
|
87 |
+
if (savedProviders) {
|
88 |
+
try {
|
89 |
+
const parsedProviders = JSON.parse(savedProviders);
|
90 |
+
|
91 |
+
// Merge saved enabled states with the base provider list
|
92 |
+
return providersList.map((provider) => ({
|
93 |
+
...provider,
|
94 |
+
isEnabled: parsedProviders[provider.name] || false,
|
95 |
+
}));
|
96 |
+
} catch (error) {
|
97 |
+
console.error('Failed to parse providers from cookies:', error);
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
return providersList;
|
102 |
+
});
|
103 |
+
|
104 |
+
const handleToggleProvider = (providerName: string, enabled: boolean) => {
|
105 |
+
setProviders((prevProviders) => {
|
106 |
+
const newProviders = prevProviders.map((provider) =>
|
107 |
+
provider.name === providerName ? { ...provider, isEnabled: enabled } : provider,
|
108 |
+
);
|
109 |
+
|
110 |
+
// Save to cookies
|
111 |
+
const enabledStates = newProviders.reduce(
|
112 |
+
(acc, provider) => ({
|
113 |
+
...acc,
|
114 |
+
[provider.name]: provider.isEnabled,
|
115 |
+
}),
|
116 |
+
{},
|
117 |
+
);
|
118 |
+
Cookies.set('providers', JSON.stringify(enabledStates));
|
119 |
+
|
120 |
+
return newProviders;
|
121 |
+
});
|
122 |
+
};
|
123 |
+
|
124 |
+
const filteredProviders = providers
|
125 |
+
.filter((provider) => {
|
126 |
+
const isLocalModelProvider = ['OpenAILike', 'LMStudio', 'Ollama'].includes(provider.name);
|
127 |
+
return isLocalModelsEnabled || !isLocalModelProvider;
|
128 |
+
})
|
129 |
+
.filter((provider) => provider.name.toLowerCase().includes(searchTerm.toLowerCase()))
|
130 |
+
.sort((a, b) => a.name.localeCompare(b.name));
|
131 |
+
|
132 |
+
const handleCopyToClipboard = () => {
|
133 |
+
const debugInfo = {
|
134 |
+
OS: navigator.platform,
|
135 |
+
Browser: navigator.userAgent,
|
136 |
+
ActiveFeatures: providers.filter((provider) => provider.isEnabled).map((provider) => provider.name),
|
137 |
+
BaseURLs: {
|
138 |
+
Ollama: process.env.REACT_APP_OLLAMA_URL,
|
139 |
+
OpenAI: process.env.REACT_APP_OPENAI_URL,
|
140 |
+
LMStudio: process.env.REACT_APP_LM_STUDIO_URL,
|
141 |
+
},
|
142 |
+
Version: versionHash,
|
143 |
+
};
|
144 |
+
navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2)).then(() => {
|
145 |
+
alert('Debug information copied to clipboard!');
|
146 |
+
});
|
147 |
+
};
|
148 |
+
|
149 |
+
const downloadAsJson = (data: any, filename: string) => {
|
150 |
+
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
151 |
+
const url = URL.createObjectURL(blob);
|
152 |
+
const link = document.createElement('a');
|
153 |
+
link.href = url;
|
154 |
+
link.download = filename;
|
155 |
+
document.body.appendChild(link);
|
156 |
+
link.click();
|
157 |
+
document.body.removeChild(link);
|
158 |
+
URL.revokeObjectURL(url);
|
159 |
+
};
|
160 |
+
|
161 |
+
const handleDeleteAllChats = async () => {
|
162 |
+
if (!db) {
|
163 |
+
toast.error('Database is not available');
|
164 |
+
return;
|
165 |
+
}
|
166 |
+
|
167 |
+
try {
|
168 |
+
setIsDeleting(true);
|
169 |
+
|
170 |
+
const allChats = await getAll(db);
|
171 |
+
|
172 |
+
// Delete all chats one by one
|
173 |
+
await Promise.all(allChats.map((chat) => deleteById(db!, chat.id)));
|
174 |
+
|
175 |
+
toast.success('All chats deleted successfully');
|
176 |
+
navigate('/', { replace: true });
|
177 |
+
} catch (error) {
|
178 |
+
toast.error('Failed to delete chats');
|
179 |
+
console.error(error);
|
180 |
+
} finally {
|
181 |
+
setIsDeleting(false);
|
182 |
+
}
|
183 |
+
};
|
184 |
+
|
185 |
+
const handleExportAllChats = async () => {
|
186 |
+
if (!db) {
|
187 |
+
toast.error('Database is not available');
|
188 |
+
return;
|
189 |
+
}
|
190 |
+
|
191 |
+
try {
|
192 |
+
const allChats = await getAll(db);
|
193 |
+
const exportData = {
|
194 |
+
chats: allChats,
|
195 |
+
exportDate: new Date().toISOString(),
|
196 |
+
};
|
197 |
+
|
198 |
+
downloadAsJson(exportData, `all-chats-${new Date().toISOString()}.json`);
|
199 |
+
toast.success('Chats exported successfully');
|
200 |
+
} catch (error) {
|
201 |
+
toast.error('Failed to export chats');
|
202 |
+
console.error(error);
|
203 |
+
}
|
204 |
+
};
|
205 |
+
|
206 |
+
const versionHash = commit.commit; // Get the version hash from commit.json
|
207 |
+
|
208 |
+
const handleSaveConnection = () => {
|
209 |
+
Cookies.set('githubUsername', githubUsername);
|
210 |
+
Cookies.set('githubToken', githubToken);
|
211 |
+
toast.success('GitHub credentials saved successfully!');
|
212 |
+
};
|
213 |
+
|
214 |
+
const handleToggleDebug = (enabled: boolean) => {
|
215 |
+
setIsDebugEnabled(enabled);
|
216 |
+
Cookies.set('isDebugEnabled', String(enabled));
|
217 |
+
};
|
218 |
+
|
219 |
+
const handleToggleLocalModels = (enabled: boolean) => {
|
220 |
+
setIsLocalModelsEnabled(enabled);
|
221 |
+
Cookies.set('isLocalModelsEnabled', String(enabled));
|
222 |
+
};
|
223 |
+
|
224 |
+
return (
|
225 |
+
<RadixDialog.Root open={open}>
|
226 |
+
<RadixDialog.Portal>
|
227 |
+
<RadixDialog.Overlay asChild onClick={onClose}>
|
228 |
+
<motion.div
|
229 |
+
className="bg-black/50 fixed inset-0 z-max backdrop-blur-sm"
|
230 |
+
initial="closed"
|
231 |
+
animate="open"
|
232 |
+
exit="closed"
|
233 |
+
variants={dialogBackdropVariants}
|
234 |
+
/>
|
235 |
+
</RadixDialog.Overlay>
|
236 |
+
<RadixDialog.Content asChild>
|
237 |
+
<motion.div
|
238 |
+
className="fixed top-[50%] left-[50%] z-max h-[85vh] w-[90vw] max-w-[900px] translate-x-[-50%] translate-y-[-50%] border border-bolt-elements-borderColor rounded-lg shadow-lg focus:outline-none overflow-hidden"
|
239 |
+
initial="closed"
|
240 |
+
animate="open"
|
241 |
+
exit="closed"
|
242 |
+
variants={dialogVariants}
|
243 |
+
>
|
244 |
+
<div className="flex h-full">
|
245 |
+
<div
|
246 |
+
className={classNames(
|
247 |
+
'w-48 border-r border-bolt-elements-borderColor bg-bolt-elements-background-depth-1 p-4 flex flex-col justify-between',
|
248 |
+
styles['settings-tabs'],
|
249 |
+
)}
|
250 |
+
>
|
251 |
+
<DialogTitle className="flex-shrink-0 text-lg font-semibold text-bolt-elements-textPrimary mb-2">
|
252 |
+
Settings
|
253 |
+
</DialogTitle>
|
254 |
+
{tabs.map((tab) => (
|
255 |
+
<button
|
256 |
+
key={tab.id}
|
257 |
+
onClick={() => setActiveTab(tab.id)}
|
258 |
+
className={classNames(activeTab === tab.id ? styles.active : '')}
|
259 |
+
>
|
260 |
+
<div className={tab.icon} />
|
261 |
+
{tab.label}
|
262 |
+
</button>
|
263 |
+
))}
|
264 |
+
<div className="mt-auto flex flex-col gap-2">
|
265 |
+
<a
|
266 |
+
href="https://github.com/stackblitz-labs/bolt.diy"
|
267 |
+
target="_blank"
|
268 |
+
rel="noopener noreferrer"
|
269 |
+
className={classNames(styles['settings-button'], 'flex items-center gap-2')}
|
270 |
+
>
|
271 |
+
<div className="i-ph:github-logo" />
|
272 |
+
GitHub
|
273 |
+
</a>
|
274 |
+
<a
|
275 |
+
href="https://coleam00.github.io/bolt.new-any-llm"
|
276 |
+
target="_blank"
|
277 |
+
rel="noopener noreferrer"
|
278 |
+
className={classNames(styles['settings-button'], 'flex items-center gap-2')}
|
279 |
+
>
|
280 |
+
<div className="i-ph:book" />
|
281 |
+
Docs
|
282 |
+
</a>
|
283 |
+
</div>
|
284 |
+
</div>
|
285 |
+
|
286 |
+
<div className="flex-1 flex flex-col p-8 pt-10 bg-bolt-elements-background-depth-2">
|
287 |
+
<div className="flex-1 overflow-y-auto">
|
288 |
+
{activeTab === 'chat-history' && (
|
289 |
+
<div className="p-4">
|
290 |
+
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Chat History</h3>
|
291 |
+
<button
|
292 |
+
onClick={handleExportAllChats}
|
293 |
+
className={classNames(
|
294 |
+
'bg-bolt-elements-button-primary-background',
|
295 |
+
'rounded-lg px-4 py-2 mb-4 transition-colors duration-200',
|
296 |
+
'hover:bg-bolt-elements-button-primary-backgroundHover',
|
297 |
+
'text-bolt-elements-button-primary-text',
|
298 |
+
)}
|
299 |
+
>
|
300 |
+
Export All Chats
|
301 |
+
</button>
|
302 |
+
|
303 |
+
<div
|
304 |
+
className={classNames(
|
305 |
+
'text-bolt-elements-textPrimary rounded-lg py-4 mb-4',
|
306 |
+
styles['settings-danger-area'],
|
307 |
+
)}
|
308 |
+
>
|
309 |
+
<h4 className="font-semibold">Danger Area</h4>
|
310 |
+
<p className="mb-2">This action cannot be undone!</p>
|
311 |
+
<button
|
312 |
+
onClick={handleDeleteAllChats}
|
313 |
+
disabled={isDeleting}
|
314 |
+
className={classNames(
|
315 |
+
'bg-bolt-elements-button-danger-background',
|
316 |
+
'rounded-lg px-4 py-2 transition-colors duration-200',
|
317 |
+
isDeleting
|
318 |
+
? 'opacity-50 cursor-not-allowed'
|
319 |
+
: 'hover:bg-bolt-elements-button-danger-backgroundHover',
|
320 |
+
'text-bolt-elements-button-danger-text',
|
321 |
+
)}
|
322 |
+
>
|
323 |
+
{isDeleting ? 'Deleting...' : 'Delete All Chats'}
|
324 |
+
</button>
|
325 |
+
</div>
|
326 |
+
</div>
|
327 |
+
)}
|
328 |
+
{activeTab === 'providers' && (
|
329 |
+
<div className="p-4">
|
330 |
+
<div className="flex mb-4">
|
331 |
+
<input
|
332 |
+
type="text"
|
333 |
+
placeholder="Search providers..."
|
334 |
+
value={searchTerm}
|
335 |
+
onChange={(e) => setSearchTerm(e.target.value)}
|
336 |
+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
|
337 |
+
/>
|
338 |
+
</div>
|
339 |
+
{filteredProviders.map((provider) => (
|
340 |
+
<div
|
341 |
+
key={provider.name}
|
342 |
+
className="flex flex-col mb-2 provider-item hover:bg-bolt-elements-bg-depth-3 p-4 rounded-lg border border-bolt-elements-borderColor "
|
343 |
+
>
|
344 |
+
<div className="flex items-center justify-between mb-2">
|
345 |
+
<span className="text-bolt-elements-textPrimary">{provider.name}</span>
|
346 |
+
<Switch
|
347 |
+
className="ml-auto"
|
348 |
+
checked={provider.isEnabled}
|
349 |
+
onCheckedChange={(enabled) => handleToggleProvider(provider.name, enabled)}
|
350 |
+
/>
|
351 |
+
</div>
|
352 |
+
{/* Base URL input for configurable providers */}
|
353 |
+
{URL_CONFIGURABLE_PROVIDERS.includes(provider.name) && provider.isEnabled && (
|
354 |
+
<div className="mt-2">
|
355 |
+
<label className="block text-sm text-bolt-elements-textSecondary mb-1">Base URL:</label>
|
356 |
+
<input
|
357 |
+
type="text"
|
358 |
+
value={baseUrls[provider.name]}
|
359 |
+
onChange={(e) => handleBaseUrlChange(provider.name, e.target.value)}
|
360 |
+
placeholder={`Enter ${provider.name} base URL`}
|
361 |
+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
|
362 |
+
/>
|
363 |
+
</div>
|
364 |
+
)}
|
365 |
+
</div>
|
366 |
+
))}
|
367 |
+
</div>
|
368 |
+
)}
|
369 |
+
{activeTab === 'features' && (
|
370 |
+
<div className="p-4 bg-bolt-elements-bg-depth-2 border border-bolt-elements-borderColor rounded-lg mb-4">
|
371 |
+
<div className="mb-6">
|
372 |
+
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Optional Features</h3>
|
373 |
+
<div className="flex items-center justify-between mb-2">
|
374 |
+
<span className="text-bolt-elements-textPrimary">Debug Info</span>
|
375 |
+
<Switch className="ml-auto" checked={isDebugEnabled} onCheckedChange={handleToggleDebug} />
|
376 |
+
</div>
|
377 |
+
</div>
|
378 |
+
|
379 |
+
<div className="mb-6 border-t border-bolt-elements-borderColor pt-4">
|
380 |
+
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">
|
381 |
+
Experimental Features
|
382 |
+
</h3>
|
383 |
+
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
384 |
+
Disclaimer: Experimental features may be unstable and are subject to change.
|
385 |
+
</p>
|
386 |
+
<div className="flex items-center justify-between mb-2">
|
387 |
+
<span className="text-bolt-elements-textPrimary">Enable Local Models</span>
|
388 |
+
<Switch
|
389 |
+
className="ml-auto"
|
390 |
+
checked={isLocalModelsEnabled}
|
391 |
+
onCheckedChange={handleToggleLocalModels}
|
392 |
+
/>
|
393 |
+
</div>
|
394 |
+
</div>
|
395 |
+
</div>
|
396 |
+
)}
|
397 |
+
{activeTab === 'debug' && isDebugEnabled && (
|
398 |
+
<div className="p-4">
|
399 |
+
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Debug Tab</h3>
|
400 |
+
<button
|
401 |
+
onClick={handleCopyToClipboard}
|
402 |
+
className="bg-blue-500 text-white rounded-lg px-4 py-2 hover:bg-blue-600 mb-4 transition-colors duration-200"
|
403 |
+
>
|
404 |
+
Copy to Clipboard
|
405 |
+
</button>
|
406 |
+
|
407 |
+
<h4 className="text-md font-medium text-bolt-elements-textPrimary">System Information</h4>
|
408 |
+
<p className="text-bolt-elements-textSecondary">OS: {navigator.platform}</p>
|
409 |
+
<p className="text-bolt-elements-textSecondary">Browser: {navigator.userAgent}</p>
|
410 |
+
|
411 |
+
<h4 className="text-md font-medium text-bolt-elements-textPrimary mt-4">Active Features</h4>
|
412 |
+
<ul>
|
413 |
+
{providers
|
414 |
+
.filter((provider) => provider.isEnabled)
|
415 |
+
.map((provider) => (
|
416 |
+
<li key={provider.name} className="text-bolt-elements-textSecondary">
|
417 |
+
{provider.name}
|
418 |
+
</li>
|
419 |
+
))}
|
420 |
+
</ul>
|
421 |
+
|
422 |
+
<h4 className="text-md font-medium text-bolt-elements-textPrimary mt-4">Base URLs</h4>
|
423 |
+
<ul>
|
424 |
+
<li className="text-bolt-elements-textSecondary">Ollama: {process.env.REACT_APP_OLLAMA_URL}</li>
|
425 |
+
<li className="text-bolt-elements-textSecondary">OpenAI: {process.env.REACT_APP_OPENAI_URL}</li>
|
426 |
+
<li className="text-bolt-elements-textSecondary">
|
427 |
+
LM Studio: {process.env.REACT_APP_LM_STUDIO_URL}
|
428 |
+
</li>
|
429 |
+
</ul>
|
430 |
+
|
431 |
+
<h4 className="text-md font-medium text-bolt-elements-textPrimary mt-4">Version Information</h4>
|
432 |
+
<p className="text-bolt-elements-textSecondary">Version Hash: {versionHash}</p>
|
433 |
+
</div>
|
434 |
+
)}
|
435 |
+
{activeTab === 'connection' && (
|
436 |
+
<div className="p-4 mb-4 border border-bolt-elements-borderColor rounded-lg bg-bolt-elements-background-depth-3">
|
437 |
+
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">GitHub Connection</h3>
|
438 |
+
<div className="flex mb-4">
|
439 |
+
<div className="flex-1 mr-2">
|
440 |
+
<label className="block text-sm text-bolt-elements-textSecondary mb-1">
|
441 |
+
GitHub Username:
|
442 |
+
</label>
|
443 |
+
<input
|
444 |
+
type="text"
|
445 |
+
value={githubUsername}
|
446 |
+
onChange={(e) => setGithubUsername(e.target.value)}
|
447 |
+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
|
448 |
+
/>
|
449 |
+
</div>
|
450 |
+
<div className="flex-1">
|
451 |
+
<label className="block text-sm text-bolt-elements-textSecondary mb-1">
|
452 |
+
Personal Access Token:
|
453 |
+
</label>
|
454 |
+
<input
|
455 |
+
type="password"
|
456 |
+
value={githubToken}
|
457 |
+
onChange={(e) => setGithubToken(e.target.value)}
|
458 |
+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
|
459 |
+
/>
|
460 |
+
</div>
|
461 |
+
</div>
|
462 |
+
<div className="flex mb-4">
|
463 |
+
<button
|
464 |
+
onClick={handleSaveConnection}
|
465 |
+
className="bg-bolt-elements-button-primary-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-button-primary-text"
|
466 |
+
>
|
467 |
+
Save Connection
|
468 |
+
</button>
|
469 |
+
</div>
|
470 |
+
</div>
|
471 |
+
)}
|
472 |
+
</div>
|
473 |
+
</div>
|
474 |
+
</div>
|
475 |
+
<RadixDialog.Close asChild onClick={onClose}>
|
476 |
+
<IconButton icon="i-ph:x" className="absolute top-[10px] right-[10px]" />
|
477 |
+
</RadixDialog.Close>
|
478 |
+
</motion.div>
|
479 |
+
</RadixDialog.Content>
|
480 |
+
</RadixDialog.Portal>
|
481 |
+
</RadixDialog.Root>
|
482 |
+
);
|
483 |
+
};
|
app/components/sidebar/Menu.client.tsx
CHANGED
@@ -3,6 +3,8 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3 |
import { toast } from 'react-toastify';
|
4 |
import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog';
|
5 |
import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
|
|
|
|
|
6 |
import { db, deleteById, getAll, chatId, type ChatHistoryItem, useChatHistory } from '~/lib/persistence';
|
7 |
import { cubicEasingFn } from '~/utils/easings';
|
8 |
import { logger } from '~/utils/logger';
|
@@ -39,6 +41,7 @@ export const Menu = () => {
|
|
39 |
const [list, setList] = useState<ChatHistoryItem[]>([]);
|
40 |
const [open, setOpen] = useState(false);
|
41 |
const [dialogContent, setDialogContent] = useState<DialogContent>(null);
|
|
|
42 |
|
43 |
const { filteredItems: filteredList, handleSearchChange } = useSearchFilter({
|
44 |
items: list,
|
@@ -200,10 +203,12 @@ export const Menu = () => {
|
|
200 |
</Dialog>
|
201 |
</DialogRoot>
|
202 |
</div>
|
203 |
-
<div className="flex items-center border-t border-bolt-elements-borderColor p-4">
|
204 |
-
<
|
|
|
205 |
</div>
|
206 |
</div>
|
|
|
207 |
</motion.div>
|
208 |
);
|
209 |
};
|
|
|
3 |
import { toast } from 'react-toastify';
|
4 |
import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog';
|
5 |
import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
|
6 |
+
import { SettingsWindow } from '~/components/settings/SettingsWindow';
|
7 |
+
import { SettingsButton } from '~/components/ui/SettingsButton';
|
8 |
import { db, deleteById, getAll, chatId, type ChatHistoryItem, useChatHistory } from '~/lib/persistence';
|
9 |
import { cubicEasingFn } from '~/utils/easings';
|
10 |
import { logger } from '~/utils/logger';
|
|
|
41 |
const [list, setList] = useState<ChatHistoryItem[]>([]);
|
42 |
const [open, setOpen] = useState(false);
|
43 |
const [dialogContent, setDialogContent] = useState<DialogContent>(null);
|
44 |
+
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
45 |
|
46 |
const { filteredItems: filteredList, handleSearchChange } = useSearchFilter({
|
47 |
items: list,
|
|
|
203 |
</Dialog>
|
204 |
</DialogRoot>
|
205 |
</div>
|
206 |
+
<div className="flex items-center justify-between border-t border-bolt-elements-borderColor p-4">
|
207 |
+
<SettingsButton onClick={() => setIsSettingsOpen(true)} />
|
208 |
+
<ThemeSwitch />
|
209 |
</div>
|
210 |
</div>
|
211 |
+
<SettingsWindow open={isSettingsOpen} onClose={() => setIsSettingsOpen(false)} />
|
212 |
</motion.div>
|
213 |
);
|
214 |
};
|
app/components/ui/BackgroundRays/index.tsx
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import styles from './styles.module.scss';
|
2 |
+
|
3 |
+
const BackgroundRays = () => {
|
4 |
+
return (
|
5 |
+
<div className={`${styles.rayContainer} `}>
|
6 |
+
<div className={`${styles.lightRay} ${styles.ray1}`}></div>
|
7 |
+
<div className={`${styles.lightRay} ${styles.ray2}`}></div>
|
8 |
+
<div className={`${styles.lightRay} ${styles.ray3}`}></div>
|
9 |
+
<div className={`${styles.lightRay} ${styles.ray4}`}></div>
|
10 |
+
<div className={`${styles.lightRay} ${styles.ray5}`}></div>
|
11 |
+
<div className={`${styles.lightRay} ${styles.ray6}`}></div>
|
12 |
+
<div className={`${styles.lightRay} ${styles.ray7}`}></div>
|
13 |
+
<div className={`${styles.lightRay} ${styles.ray8}`}></div>
|
14 |
+
</div>
|
15 |
+
);
|
16 |
+
};
|
17 |
+
|
18 |
+
export default BackgroundRays;
|
app/components/ui/BackgroundRays/styles.module.scss
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.rayContainer {
|
2 |
+
// Theme-specific colors
|
3 |
+
--ray-color-primary: color-mix(in srgb, var(--primary-color), transparent 30%);
|
4 |
+
--ray-color-secondary: color-mix(in srgb, var(--secondary-color), transparent 30%);
|
5 |
+
--ray-color-accent: color-mix(in srgb, var(--accent-color), transparent 30%);
|
6 |
+
|
7 |
+
// Theme-specific gradients
|
8 |
+
--ray-gradient-primary: radial-gradient(var(--ray-color-primary) 0%, transparent 70%);
|
9 |
+
--ray-gradient-secondary: radial-gradient(var(--ray-color-secondary) 0%, transparent 70%);
|
10 |
+
--ray-gradient-accent: radial-gradient(var(--ray-color-accent) 0%, transparent 70%);
|
11 |
+
|
12 |
+
position: fixed;
|
13 |
+
inset: 0;
|
14 |
+
overflow: hidden;
|
15 |
+
animation: fadeIn 1.5s ease-out;
|
16 |
+
pointer-events: none;
|
17 |
+
z-index: 0;
|
18 |
+
// background-color: transparent;
|
19 |
+
|
20 |
+
:global(html[data-theme='dark']) & {
|
21 |
+
mix-blend-mode: screen;
|
22 |
+
}
|
23 |
+
|
24 |
+
:global(html[data-theme='light']) & {
|
25 |
+
mix-blend-mode: multiply;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
.lightRay {
|
30 |
+
position: absolute;
|
31 |
+
border-radius: 100%;
|
32 |
+
|
33 |
+
:global(html[data-theme='dark']) & {
|
34 |
+
mix-blend-mode: screen;
|
35 |
+
}
|
36 |
+
|
37 |
+
:global(html[data-theme='light']) & {
|
38 |
+
mix-blend-mode: multiply;
|
39 |
+
opacity: 0.4;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
.ray1 {
|
44 |
+
width: 600px;
|
45 |
+
height: 800px;
|
46 |
+
background: var(--ray-gradient-primary);
|
47 |
+
transform: rotate(65deg);
|
48 |
+
top: -500px;
|
49 |
+
left: -100px;
|
50 |
+
filter: blur(80px);
|
51 |
+
opacity: 0.6;
|
52 |
+
animation: float1 15s infinite ease-in-out;
|
53 |
+
}
|
54 |
+
|
55 |
+
.ray2 {
|
56 |
+
width: 400px;
|
57 |
+
height: 600px;
|
58 |
+
background: var(--ray-gradient-secondary);
|
59 |
+
transform: rotate(-30deg);
|
60 |
+
top: -300px;
|
61 |
+
left: 200px;
|
62 |
+
filter: blur(60px);
|
63 |
+
opacity: 0.6;
|
64 |
+
animation: float2 18s infinite ease-in-out;
|
65 |
+
}
|
66 |
+
|
67 |
+
.ray3 {
|
68 |
+
width: 500px;
|
69 |
+
height: 400px;
|
70 |
+
background: var(--ray-gradient-accent);
|
71 |
+
top: -320px;
|
72 |
+
left: 500px;
|
73 |
+
filter: blur(65px);
|
74 |
+
opacity: 0.5;
|
75 |
+
animation: float3 20s infinite ease-in-out;
|
76 |
+
}
|
77 |
+
|
78 |
+
.ray4 {
|
79 |
+
width: 400px;
|
80 |
+
height: 450px;
|
81 |
+
background: var(--ray-gradient-secondary);
|
82 |
+
top: -350px;
|
83 |
+
left: 800px;
|
84 |
+
filter: blur(55px);
|
85 |
+
opacity: 0.55;
|
86 |
+
animation: float4 17s infinite ease-in-out;
|
87 |
+
}
|
88 |
+
|
89 |
+
.ray5 {
|
90 |
+
width: 350px;
|
91 |
+
height: 500px;
|
92 |
+
background: var(--ray-gradient-primary);
|
93 |
+
transform: rotate(-45deg);
|
94 |
+
top: -250px;
|
95 |
+
left: 1000px;
|
96 |
+
filter: blur(45px);
|
97 |
+
opacity: 0.6;
|
98 |
+
animation: float5 16s infinite ease-in-out;
|
99 |
+
}
|
100 |
+
|
101 |
+
.ray6 {
|
102 |
+
width: 300px;
|
103 |
+
height: 700px;
|
104 |
+
background: var(--ray-gradient-accent);
|
105 |
+
transform: rotate(75deg);
|
106 |
+
top: -400px;
|
107 |
+
left: 600px;
|
108 |
+
filter: blur(75px);
|
109 |
+
opacity: 0.45;
|
110 |
+
animation: float6 19s infinite ease-in-out;
|
111 |
+
}
|
112 |
+
|
113 |
+
.ray7 {
|
114 |
+
width: 450px;
|
115 |
+
height: 600px;
|
116 |
+
background: var(--ray-gradient-primary);
|
117 |
+
transform: rotate(45deg);
|
118 |
+
top: -450px;
|
119 |
+
left: 350px;
|
120 |
+
filter: blur(65px);
|
121 |
+
opacity: 0.55;
|
122 |
+
animation: float7 21s infinite ease-in-out;
|
123 |
+
}
|
124 |
+
|
125 |
+
.ray8 {
|
126 |
+
width: 380px;
|
127 |
+
height: 550px;
|
128 |
+
background: var(--ray-gradient-secondary);
|
129 |
+
transform: rotate(-60deg);
|
130 |
+
top: -380px;
|
131 |
+
left: 750px;
|
132 |
+
filter: blur(58px);
|
133 |
+
opacity: 0.6;
|
134 |
+
animation: float8 14s infinite ease-in-out;
|
135 |
+
}
|
136 |
+
|
137 |
+
@keyframes float1 {
|
138 |
+
0%,
|
139 |
+
100% {
|
140 |
+
transform: rotate(65deg) translate(0, 0);
|
141 |
+
}
|
142 |
+
25% {
|
143 |
+
transform: rotate(70deg) translate(30px, 20px);
|
144 |
+
}
|
145 |
+
50% {
|
146 |
+
transform: rotate(60deg) translate(-20px, 40px);
|
147 |
+
}
|
148 |
+
75% {
|
149 |
+
transform: rotate(68deg) translate(-40px, 10px);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
@keyframes float2 {
|
154 |
+
0%,
|
155 |
+
100% {
|
156 |
+
transform: rotate(-30deg) scale(1);
|
157 |
+
}
|
158 |
+
33% {
|
159 |
+
transform: rotate(-25deg) scale(1.1);
|
160 |
+
}
|
161 |
+
66% {
|
162 |
+
transform: rotate(-35deg) scale(0.95);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
@keyframes float3 {
|
167 |
+
0%,
|
168 |
+
100% {
|
169 |
+
transform: translate(0, 0) rotate(0deg);
|
170 |
+
}
|
171 |
+
25% {
|
172 |
+
transform: translate(40px, 20px) rotate(5deg);
|
173 |
+
}
|
174 |
+
75% {
|
175 |
+
transform: translate(-30px, 40px) rotate(-5deg);
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
@keyframes float4 {
|
180 |
+
0%,
|
181 |
+
100% {
|
182 |
+
transform: scale(1) rotate(0deg);
|
183 |
+
}
|
184 |
+
50% {
|
185 |
+
transform: scale(1.15) rotate(10deg);
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
@keyframes float5 {
|
190 |
+
0%,
|
191 |
+
100% {
|
192 |
+
transform: rotate(-45deg) translate(0, 0);
|
193 |
+
}
|
194 |
+
33% {
|
195 |
+
transform: rotate(-40deg) translate(25px, -20px);
|
196 |
+
}
|
197 |
+
66% {
|
198 |
+
transform: rotate(-50deg) translate(-25px, 20px);
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
@keyframes float6 {
|
203 |
+
0%,
|
204 |
+
100% {
|
205 |
+
transform: rotate(75deg) scale(1);
|
206 |
+
filter: blur(75px);
|
207 |
+
}
|
208 |
+
50% {
|
209 |
+
transform: rotate(85deg) scale(1.1);
|
210 |
+
filter: blur(65px);
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
@keyframes float7 {
|
215 |
+
0%,
|
216 |
+
100% {
|
217 |
+
transform: rotate(45deg) translate(0, 0);
|
218 |
+
opacity: 0.55;
|
219 |
+
}
|
220 |
+
50% {
|
221 |
+
transform: rotate(40deg) translate(-30px, 30px);
|
222 |
+
opacity: 0.65;
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
@keyframes float8 {
|
227 |
+
0%,
|
228 |
+
100% {
|
229 |
+
transform: rotate(-60deg) scale(1);
|
230 |
+
}
|
231 |
+
25% {
|
232 |
+
transform: rotate(-55deg) scale(1.05);
|
233 |
+
}
|
234 |
+
75% {
|
235 |
+
transform: rotate(-65deg) scale(0.95);
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
@keyframes fadeIn {
|
240 |
+
from {
|
241 |
+
opacity: 0;
|
242 |
+
}
|
243 |
+
to {
|
244 |
+
opacity: 1;
|
245 |
+
}
|
246 |
+
}
|
app/components/ui/SettingsButton.tsx
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { memo } from 'react';
|
2 |
+
import { IconButton } from '~/components/ui/IconButton';
|
3 |
+
interface SettingsButtonProps {
|
4 |
+
onClick: () => void;
|
5 |
+
}
|
6 |
+
|
7 |
+
export const SettingsButton = memo(({ onClick }: SettingsButtonProps) => {
|
8 |
+
return (
|
9 |
+
<IconButton
|
10 |
+
onClick={onClick}
|
11 |
+
icon="i-ph:gear"
|
12 |
+
size="xl"
|
13 |
+
title="Settings"
|
14 |
+
className="text-[#666] hover:text-bolt-elements-textPrimary hover:bg-bolt-elements-item-backgroundActive/10 transition-colors"
|
15 |
+
/>
|
16 |
+
);
|
17 |
+
});
|
app/components/ui/Switch.tsx
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { memo } from 'react';
|
2 |
+
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
3 |
+
import { classNames } from '~/utils/classNames';
|
4 |
+
|
5 |
+
interface SwitchProps {
|
6 |
+
className?: string;
|
7 |
+
checked?: boolean;
|
8 |
+
onCheckedChange?: (event: boolean) => void;
|
9 |
+
}
|
10 |
+
|
11 |
+
export const Switch = memo(({ className, onCheckedChange, checked }: SwitchProps) => {
|
12 |
+
return (
|
13 |
+
<SwitchPrimitive.Root
|
14 |
+
className={classNames(
|
15 |
+
'relative h-6 w-11 cursor-pointer rounded-full bg-bolt-elements-button-primary-background',
|
16 |
+
'transition-colors duration-200 ease-in-out',
|
17 |
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2',
|
18 |
+
'disabled:cursor-not-allowed disabled:opacity-50',
|
19 |
+
'data-[state=checked]:bg-bolt-elements-item-contentAccent',
|
20 |
+
className,
|
21 |
+
)}
|
22 |
+
checked={checked}
|
23 |
+
onCheckedChange={(e) => onCheckedChange?.(e)}
|
24 |
+
>
|
25 |
+
<SwitchPrimitive.Thumb
|
26 |
+
className={classNames(
|
27 |
+
'block h-5 w-5 rounded-full bg-white',
|
28 |
+
'shadow-lg shadow-black/20',
|
29 |
+
'transition-transform duration-200 ease-in-out',
|
30 |
+
'translate-x-0.5',
|
31 |
+
'data-[state=checked]:translate-x-[1.375rem]',
|
32 |
+
'will-change-transform',
|
33 |
+
)}
|
34 |
+
/>
|
35 |
+
</SwitchPrimitive.Root>
|
36 |
+
);
|
37 |
+
});
|
app/components/workbench/Workbench.client.tsx
CHANGED
@@ -17,6 +17,7 @@ import { renderLogger } from '~/utils/logger';
|
|
17 |
import { EditorPanel } from './EditorPanel';
|
18 |
import { Preview } from './Preview';
|
19 |
import useViewport from '~/lib/hooks';
|
|
|
20 |
|
21 |
interface WorkspaceProps {
|
22 |
chatStarted?: boolean;
|
@@ -180,21 +181,22 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
|
|
180 |
return;
|
181 |
}
|
182 |
|
183 |
-
const githubUsername =
|
|
|
184 |
|
185 |
-
if (!githubUsername) {
|
186 |
-
|
187 |
-
|
188 |
-
}
|
189 |
|
190 |
-
|
|
|
|
|
|
|
191 |
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
}
|
196 |
-
|
197 |
-
workbenchStore.pushToGitHub(repoName, githubUsername, githubToken);
|
198 |
}}
|
199 |
>
|
200 |
<div className="i-ph:github-logo" />
|
|
|
17 |
import { EditorPanel } from './EditorPanel';
|
18 |
import { Preview } from './Preview';
|
19 |
import useViewport from '~/lib/hooks';
|
20 |
+
import Cookies from 'js-cookie';
|
21 |
|
22 |
interface WorkspaceProps {
|
23 |
chatStarted?: boolean;
|
|
|
181 |
return;
|
182 |
}
|
183 |
|
184 |
+
const githubUsername = Cookies.get('githubUsername');
|
185 |
+
const githubToken = Cookies.get('githubToken');
|
186 |
|
187 |
+
if (!githubUsername || !githubToken) {
|
188 |
+
const usernameInput = prompt('Please enter your GitHub username:');
|
189 |
+
const tokenInput = prompt('Please enter your GitHub personal access token:');
|
|
|
190 |
|
191 |
+
if (!usernameInput || !tokenInput) {
|
192 |
+
alert('GitHub username and token are required. Push to GitHub cancelled.');
|
193 |
+
return;
|
194 |
+
}
|
195 |
|
196 |
+
workbenchStore.pushToGitHub(repoName, usernameInput, tokenInput);
|
197 |
+
} else {
|
198 |
+
workbenchStore.pushToGitHub(repoName, githubUsername, githubToken);
|
199 |
}
|
|
|
|
|
200 |
}}
|
201 |
>
|
202 |
<div className="i-ph:github-logo" />
|
app/lib/hooks/useGit.ts
ADDED
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { WebContainer } from '@webcontainer/api';
|
2 |
+
import { useCallback, useEffect, useRef, useState, type MutableRefObject } from 'react';
|
3 |
+
import { webcontainer as webcontainerPromise } from '~/lib/webcontainer';
|
4 |
+
import git, { type GitAuth, type PromiseFsClient } from 'isomorphic-git';
|
5 |
+
import http from 'isomorphic-git/http/web';
|
6 |
+
import Cookies from 'js-cookie';
|
7 |
+
import { toast } from 'react-toastify';
|
8 |
+
|
9 |
+
const lookupSavedPassword = (url: string) => {
|
10 |
+
const domain = url.split('/')[2];
|
11 |
+
const gitCreds = Cookies.get(`git:${domain}`);
|
12 |
+
|
13 |
+
if (!gitCreds) {
|
14 |
+
return null;
|
15 |
+
}
|
16 |
+
|
17 |
+
try {
|
18 |
+
const { username, password } = JSON.parse(gitCreds || '{}');
|
19 |
+
return { username, password };
|
20 |
+
} catch (error) {
|
21 |
+
console.log(`Failed to parse Git Cookie ${error}`);
|
22 |
+
return null;
|
23 |
+
}
|
24 |
+
};
|
25 |
+
|
26 |
+
const saveGitAuth = (url: string, auth: GitAuth) => {
|
27 |
+
const domain = url.split('/')[2];
|
28 |
+
Cookies.set(`git:${domain}`, JSON.stringify(auth));
|
29 |
+
};
|
30 |
+
|
31 |
+
export function useGit() {
|
32 |
+
const [ready, setReady] = useState(false);
|
33 |
+
const [webcontainer, setWebcontainer] = useState<WebContainer>();
|
34 |
+
const [fs, setFs] = useState<PromiseFsClient>();
|
35 |
+
const fileData = useRef<Record<string, { data: any; encoding?: string }>>({});
|
36 |
+
useEffect(() => {
|
37 |
+
webcontainerPromise.then((container) => {
|
38 |
+
fileData.current = {};
|
39 |
+
setWebcontainer(container);
|
40 |
+
setFs(getFs(container, fileData));
|
41 |
+
setReady(true);
|
42 |
+
});
|
43 |
+
}, []);
|
44 |
+
|
45 |
+
const gitClone = useCallback(
|
46 |
+
async (url: string) => {
|
47 |
+
if (!webcontainer || !fs || !ready) {
|
48 |
+
throw 'Webcontainer not initialized';
|
49 |
+
}
|
50 |
+
|
51 |
+
fileData.current = {};
|
52 |
+
await git.clone({
|
53 |
+
fs,
|
54 |
+
http,
|
55 |
+
dir: webcontainer.workdir,
|
56 |
+
url,
|
57 |
+
depth: 1,
|
58 |
+
singleBranch: true,
|
59 |
+
corsProxy: 'https://cors.isomorphic-git.org',
|
60 |
+
onAuth: (url) => {
|
61 |
+
// let domain=url.split("/")[2]
|
62 |
+
|
63 |
+
let auth = lookupSavedPassword(url);
|
64 |
+
|
65 |
+
if (auth) {
|
66 |
+
return auth;
|
67 |
+
}
|
68 |
+
|
69 |
+
if (confirm('This repo is password protected. Ready to enter a username & password?')) {
|
70 |
+
auth = {
|
71 |
+
username: prompt('Enter username'),
|
72 |
+
password: prompt('Enter password'),
|
73 |
+
};
|
74 |
+
return auth;
|
75 |
+
} else {
|
76 |
+
return { cancel: true };
|
77 |
+
}
|
78 |
+
},
|
79 |
+
onAuthFailure: (url, _auth) => {
|
80 |
+
toast.error(`Error Authenticating with ${url.split('/')[2]}`);
|
81 |
+
},
|
82 |
+
onAuthSuccess: (url, auth) => {
|
83 |
+
saveGitAuth(url, auth);
|
84 |
+
},
|
85 |
+
});
|
86 |
+
|
87 |
+
const data: Record<string, { data: any; encoding?: string }> = {};
|
88 |
+
|
89 |
+
for (const [key, value] of Object.entries(fileData.current)) {
|
90 |
+
data[key] = value;
|
91 |
+
}
|
92 |
+
|
93 |
+
return { workdir: webcontainer.workdir, data };
|
94 |
+
},
|
95 |
+
[webcontainer],
|
96 |
+
);
|
97 |
+
|
98 |
+
return { ready, gitClone };
|
99 |
+
}
|
100 |
+
|
101 |
+
const getFs = (
|
102 |
+
webcontainer: WebContainer,
|
103 |
+
record: MutableRefObject<Record<string, { data: any; encoding?: string }>>,
|
104 |
+
) => ({
|
105 |
+
promises: {
|
106 |
+
readFile: async (path: string, options: any) => {
|
107 |
+
const encoding = options.encoding;
|
108 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
109 |
+
console.log('readFile', relativePath, encoding);
|
110 |
+
|
111 |
+
return await webcontainer.fs.readFile(relativePath, encoding);
|
112 |
+
},
|
113 |
+
writeFile: async (path: string, data: any, options: any) => {
|
114 |
+
const encoding = options.encoding;
|
115 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
116 |
+
console.log('writeFile', { relativePath, data, encoding });
|
117 |
+
|
118 |
+
if (record.current) {
|
119 |
+
record.current[relativePath] = { data, encoding };
|
120 |
+
}
|
121 |
+
|
122 |
+
return await webcontainer.fs.writeFile(relativePath, data, { ...options, encoding });
|
123 |
+
},
|
124 |
+
mkdir: async (path: string, options: any) => {
|
125 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
126 |
+
console.log('mkdir', relativePath, options);
|
127 |
+
|
128 |
+
return await webcontainer.fs.mkdir(relativePath, { ...options, recursive: true });
|
129 |
+
},
|
130 |
+
readdir: async (path: string, options: any) => {
|
131 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
132 |
+
console.log('readdir', relativePath, options);
|
133 |
+
|
134 |
+
return await webcontainer.fs.readdir(relativePath, options);
|
135 |
+
},
|
136 |
+
rm: async (path: string, options: any) => {
|
137 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
138 |
+
console.log('rm', relativePath, options);
|
139 |
+
|
140 |
+
return await webcontainer.fs.rm(relativePath, { ...(options || {}) });
|
141 |
+
},
|
142 |
+
rmdir: async (path: string, options: any) => {
|
143 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
144 |
+
console.log('rmdir', relativePath, options);
|
145 |
+
|
146 |
+
return await webcontainer.fs.rm(relativePath, { recursive: true, ...options });
|
147 |
+
},
|
148 |
+
|
149 |
+
// Mock implementations for missing functions
|
150 |
+
unlink: async (path: string) => {
|
151 |
+
// unlink is just removing a single file
|
152 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
153 |
+
return await webcontainer.fs.rm(relativePath, { recursive: false });
|
154 |
+
},
|
155 |
+
|
156 |
+
stat: async (path: string) => {
|
157 |
+
try {
|
158 |
+
const relativePath = pathUtils.relative(webcontainer.workdir, path);
|
159 |
+
const resp = await webcontainer.fs.readdir(pathUtils.dirname(relativePath), { withFileTypes: true });
|
160 |
+
const name = pathUtils.basename(relativePath);
|
161 |
+
const fileInfo = resp.find((x) => x.name == name);
|
162 |
+
|
163 |
+
if (!fileInfo) {
|
164 |
+
throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
|
165 |
+
}
|
166 |
+
|
167 |
+
return {
|
168 |
+
isFile: () => fileInfo.isFile(),
|
169 |
+
isDirectory: () => fileInfo.isDirectory(),
|
170 |
+
isSymbolicLink: () => false,
|
171 |
+
size: 1,
|
172 |
+
mode: 0o666, // Default permissions
|
173 |
+
mtimeMs: Date.now(),
|
174 |
+
uid: 1000,
|
175 |
+
gid: 1000,
|
176 |
+
};
|
177 |
+
} catch (error: any) {
|
178 |
+
console.log(error?.message);
|
179 |
+
|
180 |
+
const err = new Error(`ENOENT: no such file or directory, stat '${path}'`) as NodeJS.ErrnoException;
|
181 |
+
err.code = 'ENOENT';
|
182 |
+
err.errno = -2;
|
183 |
+
err.syscall = 'stat';
|
184 |
+
err.path = path;
|
185 |
+
throw err;
|
186 |
+
}
|
187 |
+
},
|
188 |
+
|
189 |
+
lstat: async (path: string) => {
|
190 |
+
/*
|
191 |
+
* For basic usage, lstat can return the same as stat
|
192 |
+
* since we're not handling symbolic links
|
193 |
+
*/
|
194 |
+
return await getFs(webcontainer, record).promises.stat(path);
|
195 |
+
},
|
196 |
+
|
197 |
+
readlink: async (path: string) => {
|
198 |
+
/*
|
199 |
+
* Since WebContainer doesn't support symlinks,
|
200 |
+
* we'll throw a "not a symbolic link" error
|
201 |
+
*/
|
202 |
+
throw new Error(`EINVAL: invalid argument, readlink '${path}'`);
|
203 |
+
},
|
204 |
+
|
205 |
+
symlink: async (target: string, path: string) => {
|
206 |
+
/*
|
207 |
+
* Since WebContainer doesn't support symlinks,
|
208 |
+
* we'll throw a "operation not supported" error
|
209 |
+
*/
|
210 |
+
throw new Error(`EPERM: operation not permitted, symlink '${target}' -> '${path}'`);
|
211 |
+
},
|
212 |
+
|
213 |
+
chmod: async (_path: string, _mode: number) => {
|
214 |
+
/*
|
215 |
+
* WebContainer doesn't support changing permissions,
|
216 |
+
* but we can pretend it succeeded for compatibility
|
217 |
+
*/
|
218 |
+
return await Promise.resolve();
|
219 |
+
},
|
220 |
+
},
|
221 |
+
});
|
222 |
+
|
223 |
+
const pathUtils = {
|
224 |
+
dirname: (path: string) => {
|
225 |
+
// Handle empty or just filename cases
|
226 |
+
if (!path || !path.includes('/')) {
|
227 |
+
return '.';
|
228 |
+
}
|
229 |
+
|
230 |
+
// Remove trailing slashes
|
231 |
+
path = path.replace(/\/+$/, '');
|
232 |
+
|
233 |
+
// Get directory part
|
234 |
+
return path.split('/').slice(0, -1).join('/') || '/';
|
235 |
+
},
|
236 |
+
|
237 |
+
basename: (path: string, ext?: string) => {
|
238 |
+
// Remove trailing slashes
|
239 |
+
path = path.replace(/\/+$/, '');
|
240 |
+
|
241 |
+
// Get the last part of the path
|
242 |
+
const base = path.split('/').pop() || '';
|
243 |
+
|
244 |
+
// If extension is provided, remove it from the result
|
245 |
+
if (ext && base.endsWith(ext)) {
|
246 |
+
return base.slice(0, -ext.length);
|
247 |
+
}
|
248 |
+
|
249 |
+
return base;
|
250 |
+
},
|
251 |
+
relative: (from: string, to: string): string => {
|
252 |
+
// Handle empty inputs
|
253 |
+
if (!from || !to) {
|
254 |
+
return '.';
|
255 |
+
}
|
256 |
+
|
257 |
+
// Normalize paths by removing trailing slashes and splitting
|
258 |
+
const normalizePathParts = (p: string) => p.replace(/\/+$/, '').split('/').filter(Boolean);
|
259 |
+
|
260 |
+
const fromParts = normalizePathParts(from);
|
261 |
+
const toParts = normalizePathParts(to);
|
262 |
+
|
263 |
+
// Find common parts at the start of both paths
|
264 |
+
let commonLength = 0;
|
265 |
+
const minLength = Math.min(fromParts.length, toParts.length);
|
266 |
+
|
267 |
+
for (let i = 0; i < minLength; i++) {
|
268 |
+
if (fromParts[i] !== toParts[i]) {
|
269 |
+
break;
|
270 |
+
}
|
271 |
+
|
272 |
+
commonLength++;
|
273 |
+
}
|
274 |
+
|
275 |
+
// Calculate the number of "../" needed
|
276 |
+
const upCount = fromParts.length - commonLength;
|
277 |
+
|
278 |
+
// Get the remaining path parts we need to append
|
279 |
+
const remainingPath = toParts.slice(commonLength);
|
280 |
+
|
281 |
+
// Construct the relative path
|
282 |
+
const relativeParts = [...Array(upCount).fill('..'), ...remainingPath];
|
283 |
+
|
284 |
+
// Handle empty result case
|
285 |
+
return relativeParts.length === 0 ? '.' : relativeParts.join('/');
|
286 |
+
},
|
287 |
+
};
|
app/lib/stores/settings.ts
CHANGED
@@ -15,10 +15,33 @@ export interface Shortcuts {
|
|
15 |
toggleTerminal: Shortcut;
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
|
|
18 |
export interface Settings {
|
19 |
shortcuts: Shortcuts;
|
|
|
20 |
}
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
export const shortcutsStore = map<Shortcuts>({
|
23 |
toggleTerminal: {
|
24 |
key: 'j',
|
@@ -29,6 +52,7 @@ export const shortcutsStore = map<Shortcuts>({
|
|
29 |
|
30 |
export const settingsStore = map<Settings>({
|
31 |
shortcuts: shortcutsStore.get(),
|
|
|
32 |
});
|
33 |
|
34 |
shortcutsStore.subscribe((shortcuts) => {
|
|
|
15 |
toggleTerminal: Shortcut;
|
16 |
}
|
17 |
|
18 |
+
export interface Provider {
|
19 |
+
name: string;
|
20 |
+
isEnabled: boolean;
|
21 |
+
}
|
22 |
+
|
23 |
export interface Settings {
|
24 |
shortcuts: Shortcuts;
|
25 |
+
providers: Provider[];
|
26 |
}
|
27 |
|
28 |
+
export const providersList: Provider[] = [
|
29 |
+
{ name: 'Groq', isEnabled: false },
|
30 |
+
{ name: 'HuggingFace', isEnabled: false },
|
31 |
+
{ name: 'OpenAI', isEnabled: false },
|
32 |
+
{ name: 'Anthropic', isEnabled: false },
|
33 |
+
{ name: 'OpenRouter', isEnabled: false },
|
34 |
+
{ name: 'Google', isEnabled: false },
|
35 |
+
{ name: 'Ollama', isEnabled: false },
|
36 |
+
{ name: 'OpenAILike', isEnabled: false },
|
37 |
+
{ name: 'Together', isEnabled: false },
|
38 |
+
{ name: 'Deepseek', isEnabled: false },
|
39 |
+
{ name: 'Mistral', isEnabled: false },
|
40 |
+
{ name: 'Cohere', isEnabled: false },
|
41 |
+
{ name: 'LMStudio', isEnabled: false },
|
42 |
+
{ name: 'xAI', isEnabled: false },
|
43 |
+
];
|
44 |
+
|
45 |
export const shortcutsStore = map<Shortcuts>({
|
46 |
toggleTerminal: {
|
47 |
key: 'j',
|
|
|
52 |
|
53 |
export const settingsStore = map<Settings>({
|
54 |
shortcuts: shortcutsStore.get(),
|
55 |
+
providers: providersList,
|
56 |
});
|
57 |
|
58 |
shortcutsStore.subscribe((shortcuts) => {
|
app/lib/stores/workbench.ts
CHANGED
@@ -15,6 +15,7 @@ import { Octokit, type RestEndpointMethodTypes } from '@octokit/rest';
|
|
15 |
import * as nodePath from 'node:path';
|
16 |
import { extractRelativePath } from '~/utils/diff';
|
17 |
import { description } from '~/lib/persistence';
|
|
|
18 |
|
19 |
export interface ArtifactState {
|
20 |
id: string;
|
@@ -402,15 +403,14 @@ export class WorkbenchStore {
|
|
402 |
return syncedFiles;
|
403 |
}
|
404 |
|
405 |
-
async pushToGitHub(repoName: string, githubUsername
|
406 |
try {
|
407 |
-
//
|
408 |
-
const githubToken = ghToken;
|
|
|
409 |
|
410 |
-
|
411 |
-
|
412 |
-
if (!githubToken) {
|
413 |
-
throw new Error('GitHub token is not set in environment variables');
|
414 |
}
|
415 |
|
416 |
// Initialize Octokit with the auth token
|
@@ -507,7 +507,8 @@ export class WorkbenchStore {
|
|
507 |
|
508 |
alert(`Repository created and code pushed: ${repo.html_url}`);
|
509 |
} catch (error) {
|
510 |
-
console.error('Error pushing to GitHub:', error
|
|
|
511 |
}
|
512 |
}
|
513 |
}
|
|
|
15 |
import * as nodePath from 'node:path';
|
16 |
import { extractRelativePath } from '~/utils/diff';
|
17 |
import { description } from '~/lib/persistence';
|
18 |
+
import Cookies from 'js-cookie';
|
19 |
|
20 |
export interface ArtifactState {
|
21 |
id: string;
|
|
|
403 |
return syncedFiles;
|
404 |
}
|
405 |
|
406 |
+
async pushToGitHub(repoName: string, githubUsername?: string, ghToken?: string) {
|
407 |
try {
|
408 |
+
// Use cookies if username and token are not provided
|
409 |
+
const githubToken = ghToken || Cookies.get('githubToken');
|
410 |
+
const owner = githubUsername || Cookies.get('githubUsername');
|
411 |
|
412 |
+
if (!githubToken || !owner) {
|
413 |
+
throw new Error('GitHub token or username is not set in cookies or provided.');
|
|
|
|
|
414 |
}
|
415 |
|
416 |
// Initialize Octokit with the auth token
|
|
|
507 |
|
508 |
alert(`Repository created and code pushed: ${repo.html_url}`);
|
509 |
} catch (error) {
|
510 |
+
console.error('Error pushing to GitHub:', error);
|
511 |
+
throw error; // Rethrow the error for further handling
|
512 |
}
|
513 |
}
|
514 |
}
|
app/routes/_index.tsx
CHANGED
@@ -3,6 +3,7 @@ import { ClientOnly } from 'remix-utils/client-only';
|
|
3 |
import { BaseChat } from '~/components/chat/BaseChat';
|
4 |
import { Chat } from '~/components/chat/Chat.client';
|
5 |
import { Header } from '~/components/header/Header';
|
|
|
6 |
|
7 |
export const meta: MetaFunction = () => {
|
8 |
return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];
|
@@ -12,7 +13,8 @@ export const loader = () => json({});
|
|
12 |
|
13 |
export default function Index() {
|
14 |
return (
|
15 |
-
<div className="flex flex-col h-full w-full">
|
|
|
16 |
<Header />
|
17 |
<ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>
|
18 |
</div>
|
|
|
3 |
import { BaseChat } from '~/components/chat/BaseChat';
|
4 |
import { Chat } from '~/components/chat/Chat.client';
|
5 |
import { Header } from '~/components/header/Header';
|
6 |
+
import BackgroundRays from '~/components/ui/BackgroundRays';
|
7 |
|
8 |
export const meta: MetaFunction = () => {
|
9 |
return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];
|
|
|
13 |
|
14 |
export default function Index() {
|
15 |
return (
|
16 |
+
<div className="flex flex-col h-full w-full bg-bolt-elements-background-depth-1">
|
17 |
+
<BackgroundRays />
|
18 |
<Header />
|
19 |
<ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>
|
20 |
</div>
|
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 |
+
}
|
app/styles/index.scss
CHANGED
@@ -12,3 +12,13 @@ body {
|
|
12 |
height: 100%;
|
13 |
width: 100%;
|
14 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
height: 100%;
|
13 |
width: 100%;
|
14 |
}
|
15 |
+
|
16 |
+
:root {
|
17 |
+
--gradient-opacity: 0.8;
|
18 |
+
--primary-color: rgba(158, 117, 240, var(--gradient-opacity));
|
19 |
+
--secondary-color: rgba(138, 43, 226, var(--gradient-opacity));
|
20 |
+
--accent-color: rgba(128, 59, 239, var(--gradient-opacity));
|
21 |
+
// --primary-color: rgba(147, 112, 219, var(--gradient-opacity));
|
22 |
+
// --secondary-color: rgba(138, 43, 226, var(--gradient-opacity));
|
23 |
+
// --accent-color: rgba(180, 170, 220, var(--gradient-opacity));
|
24 |
+
}
|
app/types/model.ts
CHANGED
@@ -7,4 +7,5 @@ export type ProviderInfo = {
|
|
7 |
getApiKeyLink?: string;
|
8 |
labelForGetApiKey?: string;
|
9 |
icon?: string;
|
|
|
10 |
};
|
|
|
7 |
getApiKeyLink?: string;
|
8 |
labelForGetApiKey?: string;
|
9 |
icon?: string;
|
10 |
+
isEnabled?: boolean;
|
11 |
};
|
app/utils/constants.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import Cookies from 'js-cookie';
|
2 |
import type { ModelInfo, OllamaApiResponse, OllamaModel } from './types';
|
3 |
import type { ProviderInfo } from '~/types/model';
|
|
|
4 |
|
5 |
export const WORK_DIR_NAME = 'project';
|
6 |
export const WORK_DIR = `/home/${WORK_DIR_NAME}`;
|
@@ -10,6 +11,8 @@ export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/;
|
|
10 |
export const DEFAULT_MODEL = 'claude-3-5-sonnet-latest';
|
11 |
export const PROMPT_COOKIE_KEY = 'cachedPrompt';
|
12 |
|
|
|
|
|
13 |
const PROVIDER_LIST: ProviderInfo[] = [
|
14 |
{
|
15 |
name: 'Anthropic',
|
@@ -127,7 +130,7 @@ const PROVIDER_LIST: ProviderInfo[] = [
|
|
127 |
{ name: 'gemini-1.5-flash-8b', label: 'Gemini 1.5 Flash-8b', provider: 'Google', maxTokenAllowed: 8192 },
|
128 |
{ name: 'gemini-1.5-pro-latest', label: 'Gemini 1.5 Pro', provider: 'Google', maxTokenAllowed: 8192 },
|
129 |
{ name: 'gemini-1.5-pro-002', label: 'Gemini 1.5 Pro-002', provider: 'Google', maxTokenAllowed: 8192 },
|
130 |
-
{ name: 'gemini-exp-
|
131 |
],
|
132 |
getApiKeyLink: 'https://aistudio.google.com/app/apikey',
|
133 |
},
|
@@ -383,8 +386,8 @@ async function getOllamaModels(): Promise<ModelInfo[]> {
|
|
383 |
provider: 'Ollama',
|
384 |
maxTokenAllowed: 8000,
|
385 |
}));
|
386 |
-
} catch (e) {
|
387 |
-
|
388 |
return [];
|
389 |
}
|
390 |
}
|
@@ -471,8 +474,8 @@ async function getLMStudioModels(): Promise<ModelInfo[]> {
|
|
471 |
label: model.id,
|
472 |
provider: 'LMStudio',
|
473 |
}));
|
474 |
-
} catch (e) {
|
475 |
-
|
476 |
return [];
|
477 |
}
|
478 |
}
|
@@ -491,7 +494,7 @@ async function initializeModelList(): Promise<ModelInfo[]> {
|
|
491 |
}
|
492 |
}
|
493 |
} catch (error: any) {
|
494 |
-
|
495 |
}
|
496 |
MODEL_LIST = [
|
497 |
...(
|
|
|
1 |
import Cookies from 'js-cookie';
|
2 |
import type { ModelInfo, OllamaApiResponse, OllamaModel } from './types';
|
3 |
import type { ProviderInfo } from '~/types/model';
|
4 |
+
import { createScopedLogger } from './logger';
|
5 |
|
6 |
export const WORK_DIR_NAME = 'project';
|
7 |
export const WORK_DIR = `/home/${WORK_DIR_NAME}`;
|
|
|
11 |
export const DEFAULT_MODEL = 'claude-3-5-sonnet-latest';
|
12 |
export const PROMPT_COOKIE_KEY = 'cachedPrompt';
|
13 |
|
14 |
+
const logger = createScopedLogger('Constants');
|
15 |
+
|
16 |
const PROVIDER_LIST: ProviderInfo[] = [
|
17 |
{
|
18 |
name: 'Anthropic',
|
|
|
130 |
{ name: 'gemini-1.5-flash-8b', label: 'Gemini 1.5 Flash-8b', provider: 'Google', maxTokenAllowed: 8192 },
|
131 |
{ name: 'gemini-1.5-pro-latest', label: 'Gemini 1.5 Pro', provider: 'Google', maxTokenAllowed: 8192 },
|
132 |
{ name: 'gemini-1.5-pro-002', label: 'Gemini 1.5 Pro-002', provider: 'Google', maxTokenAllowed: 8192 },
|
133 |
+
{ name: 'gemini-exp-1206', label: 'Gemini exp-1206', provider: 'Google', maxTokenAllowed: 8192 },
|
134 |
],
|
135 |
getApiKeyLink: 'https://aistudio.google.com/app/apikey',
|
136 |
},
|
|
|
386 |
provider: 'Ollama',
|
387 |
maxTokenAllowed: 8000,
|
388 |
}));
|
389 |
+
} catch (e: any) {
|
390 |
+
logger.warn('Failed to get Ollama models: ', e.message || '');
|
391 |
return [];
|
392 |
}
|
393 |
}
|
|
|
474 |
label: model.id,
|
475 |
provider: 'LMStudio',
|
476 |
}));
|
477 |
+
} catch (e: any) {
|
478 |
+
logger.warn('Failed to get LMStudio models: ', e.message || '');
|
479 |
return [];
|
480 |
}
|
481 |
}
|
|
|
494 |
}
|
495 |
}
|
496 |
} catch (error: any) {
|
497 |
+
logger.warn(`Failed to fetch apikeys from cookies: ${error?.message}`);
|
498 |
}
|
499 |
MODEL_LIST = [
|
500 |
...(
|
app/utils/fileUtils.ts
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import ignore from 'ignore';
|
2 |
+
|
3 |
+
// Common patterns to ignore, similar to .gitignore
|
4 |
+
export const IGNORE_PATTERNS = [
|
5 |
+
'node_modules/**',
|
6 |
+
'.git/**',
|
7 |
+
'dist/**',
|
8 |
+
'build/**',
|
9 |
+
'.next/**',
|
10 |
+
'coverage/**',
|
11 |
+
'.cache/**',
|
12 |
+
'.vscode/**',
|
13 |
+
'.idea/**',
|
14 |
+
'**/*.log',
|
15 |
+
'**/.DS_Store',
|
16 |
+
'**/npm-debug.log*',
|
17 |
+
'**/yarn-debug.log*',
|
18 |
+
'**/yarn-error.log*',
|
19 |
+
];
|
20 |
+
|
21 |
+
export const MAX_FILES = 1000;
|
22 |
+
export const ig = ignore().add(IGNORE_PATTERNS);
|
23 |
+
|
24 |
+
export const generateId = () => Math.random().toString(36).substring(2, 15);
|
25 |
+
|
26 |
+
export const isBinaryFile = async (file: File): Promise<boolean> => {
|
27 |
+
const chunkSize = 1024;
|
28 |
+
const buffer = new Uint8Array(await file.slice(0, chunkSize).arrayBuffer());
|
29 |
+
|
30 |
+
for (let i = 0; i < buffer.length; i++) {
|
31 |
+
const byte = buffer[i];
|
32 |
+
|
33 |
+
if (byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)) {
|
34 |
+
return true;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
return false;
|
39 |
+
};
|
40 |
+
|
41 |
+
export const shouldIncludeFile = (path: string): boolean => {
|
42 |
+
return !ig.ignores(path);
|
43 |
+
};
|
44 |
+
|
45 |
+
const readPackageJson = async (files: File[]): Promise<{ scripts?: Record<string, string> } | null> => {
|
46 |
+
const packageJsonFile = files.find((f) => f.webkitRelativePath.endsWith('package.json'));
|
47 |
+
|
48 |
+
if (!packageJsonFile) {
|
49 |
+
return null;
|
50 |
+
}
|
51 |
+
|
52 |
+
try {
|
53 |
+
const content = await new Promise<string>((resolve, reject) => {
|
54 |
+
const reader = new FileReader();
|
55 |
+
reader.onload = () => resolve(reader.result as string);
|
56 |
+
reader.onerror = reject;
|
57 |
+
reader.readAsText(packageJsonFile);
|
58 |
+
});
|
59 |
+
|
60 |
+
return JSON.parse(content);
|
61 |
+
} catch (error) {
|
62 |
+
console.error('Error reading package.json:', error);
|
63 |
+
return null;
|
64 |
+
}
|
65 |
+
};
|
66 |
+
|
67 |
+
export const detectProjectType = async (
|
68 |
+
files: File[],
|
69 |
+
): Promise<{ type: string; setupCommand: string; followupMessage: string }> => {
|
70 |
+
const hasFile = (name: string) => files.some((f) => f.webkitRelativePath.endsWith(name));
|
71 |
+
|
72 |
+
if (hasFile('package.json')) {
|
73 |
+
const packageJson = await readPackageJson(files);
|
74 |
+
const scripts = packageJson?.scripts || {};
|
75 |
+
|
76 |
+
// Check for preferred commands in priority order
|
77 |
+
const preferredCommands = ['dev', 'start', 'preview'];
|
78 |
+
const availableCommand = preferredCommands.find((cmd) => scripts[cmd]);
|
79 |
+
|
80 |
+
if (availableCommand) {
|
81 |
+
return {
|
82 |
+
type: 'Node.js',
|
83 |
+
setupCommand: `npm install && npm run ${availableCommand}`,
|
84 |
+
followupMessage: `Found "${availableCommand}" script in package.json. Running "npm run ${availableCommand}" after installation.`,
|
85 |
+
};
|
86 |
+
}
|
87 |
+
|
88 |
+
return {
|
89 |
+
type: 'Node.js',
|
90 |
+
setupCommand: 'npm install',
|
91 |
+
followupMessage:
|
92 |
+
'Would you like me to inspect package.json to determine the available scripts for running this project?',
|
93 |
+
};
|
94 |
+
}
|
95 |
+
|
96 |
+
if (hasFile('index.html')) {
|
97 |
+
return {
|
98 |
+
type: 'Static',
|
99 |
+
setupCommand: 'npx --yes serve',
|
100 |
+
followupMessage: '',
|
101 |
+
};
|
102 |
+
}
|
103 |
+
|
104 |
+
return { type: '', setupCommand: '', followupMessage: '' };
|
105 |
+
};
|
app/utils/folderImport.ts
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { Message } from 'ai';
|
2 |
+
import { generateId } from './fileUtils';
|
3 |
+
import { detectProjectCommands, createCommandsMessage } from './projectCommands';
|
4 |
+
|
5 |
+
export const createChatFromFolder = async (
|
6 |
+
files: File[],
|
7 |
+
binaryFiles: string[],
|
8 |
+
folderName: string,
|
9 |
+
): Promise<Message[]> => {
|
10 |
+
const fileArtifacts = await Promise.all(
|
11 |
+
files.map(async (file) => {
|
12 |
+
return new Promise<{ content: string; path: string }>((resolve, reject) => {
|
13 |
+
const reader = new FileReader();
|
14 |
+
|
15 |
+
reader.onload = () => {
|
16 |
+
const content = reader.result as string;
|
17 |
+
const relativePath = file.webkitRelativePath.split('/').slice(1).join('/');
|
18 |
+
resolve({
|
19 |
+
content,
|
20 |
+
path: relativePath,
|
21 |
+
});
|
22 |
+
};
|
23 |
+
reader.onerror = reject;
|
24 |
+
reader.readAsText(file);
|
25 |
+
});
|
26 |
+
}),
|
27 |
+
);
|
28 |
+
|
29 |
+
const commands = await detectProjectCommands(fileArtifacts);
|
30 |
+
const commandsMessage = createCommandsMessage(commands);
|
31 |
+
|
32 |
+
const binaryFilesMessage =
|
33 |
+
binaryFiles.length > 0
|
34 |
+
? `\n\nSkipped ${binaryFiles.length} binary files:\n${binaryFiles.map((f) => `- ${f}`).join('\n')}`
|
35 |
+
: '';
|
36 |
+
|
37 |
+
const filesMessage: Message = {
|
38 |
+
role: 'assistant',
|
39 |
+
content: `I've imported the contents of the "${folderName}" folder.${binaryFilesMessage}
|
40 |
+
|
41 |
+
<boltArtifact id="imported-files" title="Imported Files">
|
42 |
+
${fileArtifacts
|
43 |
+
.map(
|
44 |
+
(file) => `<boltAction type="file" filePath="${file.path}">
|
45 |
+
${file.content}
|
46 |
+
</boltAction>`,
|
47 |
+
)
|
48 |
+
.join('\n\n')}
|
49 |
+
</boltArtifact>`,
|
50 |
+
id: generateId(),
|
51 |
+
createdAt: new Date(),
|
52 |
+
};
|
53 |
+
|
54 |
+
const userMessage: Message = {
|
55 |
+
role: 'user',
|
56 |
+
id: generateId(),
|
57 |
+
content: `Import the "${folderName}" folder`,
|
58 |
+
createdAt: new Date(),
|
59 |
+
};
|
60 |
+
|
61 |
+
const messages = [userMessage, filesMessage];
|
62 |
+
|
63 |
+
if (commandsMessage) {
|
64 |
+
messages.push(commandsMessage);
|
65 |
+
}
|
66 |
+
|
67 |
+
return messages;
|
68 |
+
};
|
app/utils/projectCommands.ts
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { Message } from 'ai';
|
2 |
+
import { generateId } from './fileUtils';
|
3 |
+
|
4 |
+
export interface ProjectCommands {
|
5 |
+
type: string;
|
6 |
+
setupCommand: string;
|
7 |
+
followupMessage: string;
|
8 |
+
}
|
9 |
+
|
10 |
+
interface FileContent {
|
11 |
+
content: string;
|
12 |
+
path: string;
|
13 |
+
}
|
14 |
+
|
15 |
+
export async function detectProjectCommands(files: FileContent[]): Promise<ProjectCommands> {
|
16 |
+
const hasFile = (name: string) => files.some((f) => f.path.endsWith(name));
|
17 |
+
|
18 |
+
if (hasFile('package.json')) {
|
19 |
+
const packageJsonFile = files.find((f) => f.path.endsWith('package.json'));
|
20 |
+
|
21 |
+
if (!packageJsonFile) {
|
22 |
+
return { type: '', setupCommand: '', followupMessage: '' };
|
23 |
+
}
|
24 |
+
|
25 |
+
try {
|
26 |
+
const packageJson = JSON.parse(packageJsonFile.content);
|
27 |
+
const scripts = packageJson?.scripts || {};
|
28 |
+
|
29 |
+
// Check for preferred commands in priority order
|
30 |
+
const preferredCommands = ['dev', 'start', 'preview'];
|
31 |
+
const availableCommand = preferredCommands.find((cmd) => scripts[cmd]);
|
32 |
+
|
33 |
+
if (availableCommand) {
|
34 |
+
return {
|
35 |
+
type: 'Node.js',
|
36 |
+
setupCommand: `npm install && npm run ${availableCommand}`,
|
37 |
+
followupMessage: `Found "${availableCommand}" script in package.json. Running "npm run ${availableCommand}" after installation.`,
|
38 |
+
};
|
39 |
+
}
|
40 |
+
|
41 |
+
return {
|
42 |
+
type: 'Node.js',
|
43 |
+
setupCommand: 'npm install',
|
44 |
+
followupMessage:
|
45 |
+
'Would you like me to inspect package.json to determine the available scripts for running this project?',
|
46 |
+
};
|
47 |
+
} catch (error) {
|
48 |
+
console.error('Error parsing package.json:', error);
|
49 |
+
return { type: '', setupCommand: '', followupMessage: '' };
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
if (hasFile('index.html')) {
|
54 |
+
return {
|
55 |
+
type: 'Static',
|
56 |
+
setupCommand: 'npx --yes serve',
|
57 |
+
followupMessage: '',
|
58 |
+
};
|
59 |
+
}
|
60 |
+
|
61 |
+
return { type: '', setupCommand: '', followupMessage: '' };
|
62 |
+
}
|
63 |
+
|
64 |
+
export function createCommandsMessage(commands: ProjectCommands): Message | null {
|
65 |
+
if (!commands.setupCommand) {
|
66 |
+
return null;
|
67 |
+
}
|
68 |
+
|
69 |
+
return {
|
70 |
+
role: 'assistant',
|
71 |
+
content: `
|
72 |
+
<boltArtifact id="project-setup" title="Project Setup">
|
73 |
+
<boltAction type="shell">
|
74 |
+
${commands.setupCommand}
|
75 |
+
</boltAction>
|
76 |
+
</boltArtifact>${commands.followupMessage ? `\n\n${commands.followupMessage}` : ''}`,
|
77 |
+
id: generateId(),
|
78 |
+
createdAt: new Date(),
|
79 |
+
};
|
80 |
+
}
|
docs/docs/FAQ.md
CHANGED
@@ -1,52 +1,81 @@
|
|
1 |
-
# FAQ
|
2 |
|
3 |
-
|
4 |
|
5 |
-
- **Be specific about your stack**:
|
|
|
6 |
|
7 |
-
- **Use the enhance prompt icon**:
|
|
|
8 |
|
9 |
-
- **Scaffold the basics first, then add features**:
|
|
|
10 |
|
11 |
-
- **Batch simple instructions**:
|
|
|
|
|
12 |
|
13 |
-
|
14 |
|
15 |
-
|
16 |
|
17 |
-
|
18 |
|
19 |
-
|
20 |
|
21 |
-
|
22 |
|
23 |
-
|
24 |
|
25 |
-
|
26 |
|
27 |
-
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
That effort is going well and all of our maintainers are ABSOLUTE rockstars, but it still takes time to organize everything so we can efficiently get through all
|
32 |
-
the issues and PRs. But rest assured, we are working hard and even working on some partnerships behind the scenes to really help this project take off!
|
33 |
|
34 |
-
|
35 |
|
36 |
-
|
37 |
|
38 |
-
|
39 |
|
40 |
-
|
41 |
|
42 |
-
|
43 |
|
44 |
-
|
45 |
|
46 |
-
|
47 |
|
48 |
-
|
49 |
|
50 |
-
|
51 |
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Frequently Asked Questions (FAQ)
|
2 |
|
3 |
+
## How do I get the best results with oTToDev?
|
4 |
|
5 |
+
- **Be specific about your stack**:
|
6 |
+
Mention the frameworks or libraries you want to use (e.g., Astro, Tailwind, ShadCN) in your initial prompt. This ensures that oTToDev scaffolds the project according to your preferences.
|
7 |
|
8 |
+
- **Use the enhance prompt icon**:
|
9 |
+
Before sending your prompt, click the *enhance* icon to let the AI refine your prompt. You can edit the suggested improvements before submitting.
|
10 |
|
11 |
+
- **Scaffold the basics first, then add features**:
|
12 |
+
Ensure the foundational structure of your application is in place before introducing advanced functionality. This helps oTToDev establish a solid base to build on.
|
13 |
|
14 |
+
- **Batch simple instructions**:
|
15 |
+
Combine simple tasks into a single prompt to save time and reduce API credit consumption. For example:
|
16 |
+
*"Change the color scheme, add mobile responsiveness, and restart the dev server."*
|
17 |
|
18 |
+
---
|
19 |
|
20 |
+
## How do I contribute to oTToDev?
|
21 |
|
22 |
+
Check out our [Contribution Guide](CONTRIBUTING.md) for more details on how to get involved!
|
23 |
|
24 |
+
---
|
25 |
|
26 |
+
## Do you plan on merging oTToDev back into the official Bolt.new repo?
|
27 |
|
28 |
+
Stay tuned! We’ll share updates on this early next month.
|
29 |
|
30 |
+
---
|
31 |
|
32 |
+
## What are the future plans for oTToDev?
|
33 |
|
34 |
+
Visit our [Roadmap](https://roadmap.sh/r/ottodev-roadmap-2ovzo) for the latest updates.
|
35 |
+
New features and improvements are on the way!
|
|
|
|
|
36 |
|
37 |
+
---
|
38 |
|
39 |
+
## Why are there so many open issues/pull requests?
|
40 |
|
41 |
+
oTToDev began as a small showcase project on @ColeMedin's YouTube channel to explore editing open-source projects with local LLMs. However, it quickly grew into a massive community effort!
|
42 |
|
43 |
+
We’re forming a team of maintainers to manage demand and streamline issue resolution. The maintainers are rockstars, and we’re also exploring partnerships to help the project thrive.
|
44 |
|
45 |
+
---
|
46 |
|
47 |
+
## How do local LLMs compare to larger models like Claude 3.5 Sonnet for oTToDev/Bolt.new?
|
48 |
|
49 |
+
While local LLMs are improving rapidly, larger models like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b still offer the best results for complex applications. Our ongoing focus is to improve prompts, agents, and the platform to better support smaller local LLMs.
|
50 |
|
51 |
+
---
|
52 |
|
53 |
+
## Common Errors and Troubleshooting
|
54 |
|
55 |
+
### **"There was an error processing this request"**
|
56 |
+
This generic error message means something went wrong. Check both:
|
57 |
+
- The terminal (if you started the app with Docker or `pnpm`).
|
58 |
+
- The developer console in your browser (press `F12` or right-click > *Inspect*, then go to the *Console* tab).
|
59 |
+
|
60 |
+
---
|
61 |
+
|
62 |
+
### **"x-api-key header missing"**
|
63 |
+
This error is sometimes resolved by restarting the Docker container.
|
64 |
+
If that doesn’t work, try switching from Docker to `pnpm` or vice versa. We’re actively investigating this issue.
|
65 |
+
|
66 |
+
---
|
67 |
+
|
68 |
+
### **Blank preview when running the app**
|
69 |
+
A blank preview often occurs due to hallucinated bad code or incorrect commands.
|
70 |
+
To troubleshoot:
|
71 |
+
- Check the developer console for errors.
|
72 |
+
- Remember, previews are core functionality, so the app isn’t broken! We’re working on making these errors more transparent.
|
73 |
+
|
74 |
+
---
|
75 |
+
|
76 |
+
### **"Everything works, but the results are bad"**
|
77 |
+
Local LLMs like Qwen-2.5-Coder are powerful for small applications but still experimental for larger projects. For better results, consider using larger models like GPT-4o, Claude 3.5 Sonnet, or DeepSeek Coder V2 236b.
|
78 |
+
|
79 |
+
---
|
80 |
+
|
81 |
+
Got more questions? Feel free to reach out or open an issue in our GitHub repo!
|
docs/docs/index.md
CHANGED
@@ -148,31 +148,6 @@ sudo npm install -g pnpm
|
|
148 |
pnpm run dev
|
149 |
```
|
150 |
|
151 |
-
## Super Important Note on Running Ollama Models
|
152 |
-
|
153 |
-
Ollama models by default only have 2048 tokens for their context window. Even for large models that can easily handle way more.
|
154 |
-
This is not a large enough window to handle the Bolt.new/oTToDev prompt! You have to create a version of any model you want
|
155 |
-
to use where you specify a larger context window. Luckily it's super easy to do that.
|
156 |
-
|
157 |
-
All you have to do is:
|
158 |
-
|
159 |
-
- Create a file called "Modelfile" (no file extension) anywhere on your computer
|
160 |
-
- Put in the two lines:
|
161 |
-
|
162 |
-
```
|
163 |
-
FROM [Ollama model ID such as qwen2.5-coder:7b]
|
164 |
-
PARAMETER num_ctx 32768
|
165 |
-
```
|
166 |
-
|
167 |
-
- Run the command:
|
168 |
-
|
169 |
-
```
|
170 |
-
ollama create -f Modelfile [your new model ID, can be whatever you want (example: qwen2.5-coder-extra-ctx:7b)]
|
171 |
-
```
|
172 |
-
|
173 |
-
Now you have a new Ollama model that isn't heavily limited in the context length like Ollama models are by default for some reason.
|
174 |
-
You'll see this new model in the list of Ollama models along with all the others you pulled!
|
175 |
-
|
176 |
## Adding New LLMs:
|
177 |
|
178 |
To make new LLMs available to use in this version of Bolt.new, head on over to `app/utils/constants.ts` and find the constant MODEL_LIST. Each element in this array is an object that has the model ID for the name (get this from the provider's API documentation), a label for the frontend model dropdown, and the provider.
|
|
|
148 |
pnpm run dev
|
149 |
```
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
## Adding New LLMs:
|
152 |
|
153 |
To make new LLMs available to use in this version of Bolt.new, head on over to `app/utils/constants.ts` and find the constant MODEL_LIST. Each element in this array is an object that has the model ID for the name (get this from the provider's API documentation), a label for the frontend model dropdown, and the provider.
|
package.json
CHANGED
@@ -44,6 +44,7 @@
|
|
44 |
"@codemirror/lang-markdown": "^6.3.1",
|
45 |
"@codemirror/lang-python": "^6.1.6",
|
46 |
"@codemirror/lang-sass": "^6.0.2",
|
|
|
47 |
"@codemirror/lang-wast": "^6.0.2",
|
48 |
"@codemirror/language": "^6.10.6",
|
49 |
"@codemirror/search": "^6.5.8",
|
@@ -58,6 +59,8 @@
|
|
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 +78,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",
|
@@ -110,6 +113,7 @@
|
|
110 |
"husky": "9.1.7",
|
111 |
"is-ci": "^3.0.1",
|
112 |
"node-fetch": "^3.3.2",
|
|
|
113 |
"prettier": "^3.4.1",
|
114 |
"sass-embedded": "^1.81.0",
|
115 |
"typescript": "^5.7.2",
|
|
|
44 |
"@codemirror/lang-markdown": "^6.3.1",
|
45 |
"@codemirror/lang-python": "^6.1.6",
|
46 |
"@codemirror/lang-sass": "^6.0.2",
|
47 |
+
"@codemirror/lang-vue": "^0.1.3",
|
48 |
"@codemirror/lang-wast": "^6.0.2",
|
49 |
"@codemirror/language": "^6.10.6",
|
50 |
"@codemirror/search": "^6.5.8",
|
|
|
59 |
"@openrouter/ai-sdk-provider": "^0.0.5",
|
60 |
"@radix-ui/react-dialog": "^1.1.2",
|
61 |
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
62 |
+
"@radix-ui/react-separator": "^1.1.0",
|
63 |
+
"@radix-ui/react-switch": "^1.1.1",
|
64 |
"@radix-ui/react-tooltip": "^1.1.4",
|
65 |
"@remix-run/cloudflare": "^2.15.0",
|
66 |
"@remix-run/cloudflare-pages": "^2.15.0",
|
|
|
78 |
"framer-motion": "^11.12.0",
|
79 |
"ignore": "^6.0.2",
|
80 |
"isbot": "^4.4.0",
|
81 |
+
"isomorphic-git": "^1.27.2",
|
82 |
"istextorbinary": "^9.5.0",
|
83 |
"jose": "^5.9.6",
|
84 |
"js-cookie": "^3.0.5",
|
85 |
"jszip": "^3.10.1",
|
86 |
"nanostores": "^0.10.3",
|
87 |
"ollama-ai-provider": "^0.15.2",
|
|
|
88 |
"react": "^18.3.1",
|
89 |
"react-dom": "^18.3.1",
|
90 |
"react-hotkeys-hook": "^4.6.1",
|
|
|
113 |
"husky": "9.1.7",
|
114 |
"is-ci": "^3.0.1",
|
115 |
"node-fetch": "^3.3.2",
|
116 |
+
"pnpm": "^9.14.4",
|
117 |
"prettier": "^3.4.1",
|
118 |
"sass-embedded": "^1.81.0",
|
119 |
"typescript": "^5.7.2",
|
pnpm-lock.yaml
CHANGED
@@ -56,6 +56,9 @@ importers:
|
|
56 |
'@codemirror/lang-sass':
|
57 |
specifier: ^6.0.2
|
58 |
version: 6.0.2(@codemirror/[email protected])
|
|
|
|
|
|
|
59 |
'@codemirror/lang-wast':
|
60 |
specifier: ^6.0.2
|
61 |
version: 6.0.2
|
@@ -98,6 +101,12 @@ importers:
|
|
98 |
'@radix-ui/react-dropdown-menu':
|
99 |
specifier: ^2.1.2
|
100 |
version: 2.1.2(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
'@radix-ui/react-tooltip':
|
102 |
specifier: ^1.1.4
|
103 |
version: 1.1.4(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
@@ -130,7 +139,7 @@ importers:
|
|
130 |
version: 5.5.0
|
131 |
ai:
|
132 |
specifier: ^3.4.33
|
133 |
-
version: 3.4.33([email protected])([email protected](svelte@4.
|
134 |
date-fns:
|
135 |
specifier: ^3.6.0
|
136 |
version: 3.6.0
|
@@ -149,6 +158,9 @@ importers:
|
|
149 |
isbot:
|
150 |
specifier: ^4.4.0
|
151 |
version: 4.4.0
|
|
|
|
|
|
|
152 |
istextorbinary:
|
153 |
specifier: ^9.5.0
|
154 |
version: 9.5.0
|
@@ -167,9 +179,6 @@ importers:
|
|
167 |
ollama-ai-provider:
|
168 |
specifier: ^0.15.2
|
169 |
version: 0.15.2([email protected])
|
170 |
-
pnpm:
|
171 |
-
specifier: ^9.14.4
|
172 |
-
version: 9.14.4
|
173 |
react:
|
174 |
specifier: ^18.3.1
|
175 |
version: 18.3.1
|
@@ -218,7 +227,7 @@ importers:
|
|
218 |
version: 4.20241127.0
|
219 |
'@remix-run/dev':
|
220 |
specifier: ^2.15.0
|
221 |
-
version: 2.15.0(@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@types/[email protected])([email protected])(
|
222 |
'@types/diff':
|
223 |
specifier: ^5.2.3
|
224 |
version: 5.2.3
|
@@ -249,6 +258,9 @@ importers:
|
|
249 |
node-fetch:
|
250 |
specifier: ^3.3.2
|
251 |
version: 3.3.2
|
|
|
|
|
|
|
252 |
prettier:
|
253 |
specifier: ^3.4.1
|
254 |
version: 3.4.1
|
@@ -263,22 +275,22 @@ importers:
|
|
263 |
version: 11.0.5
|
264 |
unocss:
|
265 |
specifier: ^0.61.9
|
266 |
-
version: 0.61.9([email protected])([email protected])([email protected](@types/[email protected])([email protected])
|
267 |
vite:
|
268 |
specifier: ^5.4.11
|
269 |
-
version: 5.4.11(@types/[email protected])([email protected])
|
270 |
vite-plugin-node-polyfills:
|
271 |
specifier: ^0.22.0
|
272 |
-
version: 0.22.0([email protected])([email protected](@types/[email protected])([email protected])
|
273 |
vite-plugin-optimize-css-modules:
|
274 |
specifier: ^1.1.0
|
275 |
-
version: 1.1.0([email protected](@types/[email protected])([email protected])
|
276 |
vite-tsconfig-paths:
|
277 |
specifier: ^4.3.2
|
278 |
-
version: 4.3.2([email protected])([email protected](@types/[email protected])([email protected])
|
279 |
vitest:
|
280 |
specifier: ^2.1.7
|
281 |
-
version: 2.1.
|
282 |
wrangler:
|
283 |
specifier: ^3.91.0
|
284 |
version: 3.91.0(@cloudflare/[email protected])
|
@@ -666,6 +678,9 @@ packages:
|
|
666 |
'@codemirror/[email protected]':
|
667 |
resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==}
|
668 |
|
|
|
|
|
|
|
669 |
'@codemirror/[email protected]':
|
670 |
resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==}
|
671 |
|
@@ -1375,8 +1390,8 @@ packages:
|
|
1375 |
'@lezer/[email protected]':
|
1376 |
resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==}
|
1377 |
|
1378 |
-
'@lezer/[email protected].
|
1379 |
-
resolution: {integrity: sha512-
|
1380 |
|
1381 |
'@lezer/[email protected]':
|
1382 |
resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==}
|
@@ -1717,6 +1732,19 @@ packages:
|
|
1717 |
'@types/react-dom':
|
1718 |
optional: true
|
1719 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1720 |
'@radix-ui/[email protected]':
|
1721 |
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
|
1722 |
peerDependencies:
|
@@ -1726,6 +1754,19 @@ packages:
|
|
1726 |
'@types/react':
|
1727 |
optional: true
|
1728 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1729 |
'@radix-ui/[email protected]':
|
1730 |
resolution: {integrity: sha512-QpObUH/ZlpaO4YgHSaYzrLO2VuO+ZBFFgGzjMUPwtiYnAzzNNDPJeEGRrT7qNOrWm/Jr08M1vlp+vTHtnSQ0Uw==}
|
1731 |
peerDependencies:
|
@@ -1775,6 +1816,15 @@ packages:
|
|
1775 |
'@types/react':
|
1776 |
optional: true
|
1777 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1778 |
'@radix-ui/[email protected]':
|
1779 |
resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
|
1780 |
peerDependencies:
|
@@ -2102,8 +2152,8 @@ packages:
|
|
2102 |
'@types/[email protected]':
|
2103 |
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
2104 |
|
2105 |
-
'@typescript-eslint/eslint-plugin@8.
|
2106 |
-
resolution: {integrity: sha512-
|
2107 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2108 |
peerDependencies:
|
2109 |
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
@@ -2113,8 +2163,8 @@ packages:
|
|
2113 |
typescript:
|
2114 |
optional: true
|
2115 |
|
2116 |
-
'@typescript-eslint/parser@8.
|
2117 |
-
resolution: {integrity: sha512-
|
2118 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2119 |
peerDependencies:
|
2120 |
eslint: ^8.57.0 || ^9.0.0
|
@@ -2123,12 +2173,12 @@ packages:
|
|
2123 |
typescript:
|
2124 |
optional: true
|
2125 |
|
2126 |
-
'@typescript-eslint/scope-manager@8.
|
2127 |
-
resolution: {integrity: sha512
|
2128 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2129 |
|
2130 |
-
'@typescript-eslint/type-utils@8.
|
2131 |
-
resolution: {integrity: sha512-
|
2132 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2133 |
peerDependencies:
|
2134 |
eslint: ^8.57.0 || ^9.0.0
|
@@ -2137,12 +2187,12 @@ packages:
|
|
2137 |
typescript:
|
2138 |
optional: true
|
2139 |
|
2140 |
-
'@typescript-eslint/types@8.
|
2141 |
-
resolution: {integrity: sha512-
|
2142 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2143 |
|
2144 |
-
'@typescript-eslint/typescript-estree@8.
|
2145 |
-
resolution: {integrity: sha512-
|
2146 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2147 |
peerDependencies:
|
2148 |
typescript: '*'
|
@@ -2150,8 +2200,8 @@ packages:
|
|
2150 |
typescript:
|
2151 |
optional: true
|
2152 |
|
2153 |
-
'@typescript-eslint/utils@8.
|
2154 |
-
resolution: {integrity: sha512-
|
2155 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2156 |
peerDependencies:
|
2157 |
eslint: ^8.57.0 || ^9.0.0
|
@@ -2160,8 +2210,8 @@ packages:
|
|
2160 |
typescript:
|
2161 |
optional: true
|
2162 |
|
2163 |
-
'@typescript-eslint/visitor-keys@8.
|
2164 |
-
resolution: {integrity: sha512-
|
2165 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2166 |
|
2167 |
'@uiw/[email protected]':
|
@@ -2275,11 +2325,11 @@ packages:
|
|
2275 |
'@vanilla-extract/[email protected]':
|
2276 |
resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==}
|
2277 |
|
2278 |
-
'@vitest/[email protected].
|
2279 |
-
resolution: {integrity: sha512-
|
2280 |
|
2281 |
-
'@vitest/[email protected].
|
2282 |
-
resolution: {integrity: sha512-
|
2283 |
peerDependencies:
|
2284 |
msw: ^2.4.9
|
2285 |
vite: ^5.0.0
|
@@ -2289,49 +2339,49 @@ packages:
|
|
2289 |
vite:
|
2290 |
optional: true
|
2291 |
|
2292 |
-
'@vitest/[email protected].
|
2293 |
-
resolution: {integrity: sha512-
|
2294 |
|
2295 |
-
'@vitest/[email protected].
|
2296 |
-
resolution: {integrity: sha512-
|
2297 |
|
2298 |
-
'@vitest/[email protected].
|
2299 |
-
resolution: {integrity: sha512-
|
2300 |
|
2301 |
-
'@vitest/[email protected].
|
2302 |
-
resolution: {integrity: sha512-
|
2303 |
|
2304 |
-
'@vitest/[email protected].
|
2305 |
-
resolution: {integrity: sha512-
|
2306 |
|
2307 |
-
'@vue/compiler-core@3.
|
2308 |
-
resolution: {integrity: sha512-
|
2309 |
|
2310 |
-
'@vue/compiler-dom@3.
|
2311 |
-
resolution: {integrity: sha512
|
2312 |
|
2313 |
-
'@vue/compiler-sfc@3.
|
2314 |
-
resolution: {integrity: sha512-
|
2315 |
|
2316 |
-
'@vue/compiler-ssr@3.
|
2317 |
-
resolution: {integrity: sha512-
|
2318 |
|
2319 |
-
'@vue/reactivity@3.
|
2320 |
-
resolution: {integrity: sha512-
|
2321 |
|
2322 |
-
'@vue/runtime-core@3.
|
2323 |
-
resolution: {integrity: sha512-
|
2324 |
|
2325 |
-
'@vue/runtime-dom@3.
|
2326 |
-
resolution: {integrity: sha512-
|
2327 |
|
2328 |
-
'@vue/server-renderer@3.
|
2329 |
-
resolution: {integrity: sha512-
|
2330 |
peerDependencies:
|
2331 |
-
vue: 3.
|
2332 |
|
2333 |
-
'@vue/shared@3.
|
2334 |
-
resolution: {integrity: sha512
|
2335 |
|
2336 |
'@web3-storage/[email protected]':
|
2337 |
resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==}
|
@@ -2368,6 +2418,11 @@ packages:
|
|
2368 |
peerDependencies:
|
2369 |
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
2370 |
|
|
|
|
|
|
|
|
|
|
|
2371 | |
2372 |
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
|
2373 |
engines: {node: '>=0.4.0'}
|
@@ -2459,6 +2514,9 @@ packages:
|
|
2459 |
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
|
2460 |
hasBin: true
|
2461 |
|
|
|
|
|
|
|
2462 | |
2463 |
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
2464 |
engines: {node: '>= 0.4'}
|
@@ -2648,6 +2706,9 @@ packages:
|
|
2648 |
resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==}
|
2649 |
engines: {node: '>= 0.10'}
|
2650 |
|
|
|
|
|
|
|
2651 | |
2652 |
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
2653 |
engines: {node: '>=6'}
|
@@ -2671,9 +2732,6 @@ packages:
|
|
2671 |
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
2672 |
engines: {node: '>=6'}
|
2673 |
|
2674 | |
2675 |
-
resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
|
2676 |
-
|
2677 | |
2678 |
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
2679 |
engines: {node: '>=7.0.0'}
|
@@ -2743,6 +2801,11 @@ packages:
|
|
2743 | |
2744 |
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
2745 |
|
|
|
|
|
|
|
|
|
|
|
2746 | |
2747 |
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
|
2748 |
|
@@ -2819,6 +2882,10 @@ packages:
|
|
2819 | |
2820 |
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
|
2821 |
|
|
|
|
|
|
|
|
|
2822 | |
2823 |
resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
|
2824 |
peerDependencies:
|
@@ -2882,6 +2949,9 @@ packages:
|
|
2882 | |
2883 |
resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
|
2884 |
|
|
|
|
|
|
|
2885 | |
2886 |
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
|
2887 |
engines: {node: '>=0.3.1'}
|
@@ -2913,8 +2983,8 @@ packages:
|
|
2913 | |
2914 |
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
2915 |
|
2916 |
-
[email protected].
|
2917 |
-
resolution: {integrity: sha512-
|
2918 |
|
2919 | |
2920 |
resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==}
|
@@ -3063,6 +3133,9 @@ packages:
|
|
3063 |
jiti:
|
3064 |
optional: true
|
3065 |
|
|
|
|
|
|
|
3066 | |
3067 |
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
|
3068 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
@@ -3075,6 +3148,9 @@ packages:
|
|
3075 |
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
|
3076 |
engines: {node: '>=0.10'}
|
3077 |
|
|
|
|
|
|
|
3078 | |
3079 |
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
|
3080 |
engines: {node: '>=4.0'}
|
@@ -3367,8 +3443,8 @@ packages:
|
|
3367 |
resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==}
|
3368 |
engines: {node: '>= 0.4'}
|
3369 |
|
3370 |
-
[email protected]
|
3371 |
-
resolution: {integrity: sha512-
|
3372 |
engines: {node: '>= 0.4'}
|
3373 |
|
3374 | |
@@ -3472,9 +3548,6 @@ packages:
|
|
3472 | |
3473 |
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
3474 |
|
3475 | |
3476 |
-
resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
|
3477 |
-
|
3478 | |
3479 |
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
|
3480 |
|
@@ -3613,6 +3686,11 @@ packages:
|
|
3613 | |
3614 |
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
3615 |
|
|
|
|
|
|
|
|
|
|
|
3616 | |
3617 |
resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==}
|
3618 |
engines: {node: '>=10'}
|
@@ -4093,6 +4171,10 @@ packages:
|
|
4093 |
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
4094 |
engines: {node: '>=6'}
|
4095 |
|
|
|
|
|
|
|
|
|
4096 | |
4097 |
resolution: {integrity: sha512-dM3RBlJE8rUFxnqlPCaFCq0E7qQqEQvKbYX7W/APGCK+rLcyLmEBzC4GQR/niXdNM/oV6gdg9AA50ghnn2ALuw==}
|
4098 |
engines: {node: '>=16.13'}
|
@@ -4114,6 +4196,9 @@ packages:
|
|
4114 | |
4115 |
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
4116 |
|
|
|
|
|
|
|
4117 | |
4118 |
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
4119 |
engines: {node: '>= 8'}
|
@@ -4417,6 +4502,10 @@ packages:
|
|
4417 |
engines: {node: '>=0.10'}
|
4418 |
hasBin: true
|
4419 |
|
|
|
|
|
|
|
|
|
4420 | |
4421 |
resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
|
4422 |
engines: {node: '>=10'}
|
@@ -4786,8 +4875,8 @@ packages:
|
|
4786 | |
4787 |
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
4788 |
|
4789 |
-
[email protected].
|
4790 |
-
resolution: {integrity: sha512-
|
4791 |
engines: {node: '>=10'}
|
4792 |
|
4793 | |
@@ -4968,11 +5057,6 @@ packages:
|
|
4968 |
engines: {node: '>=16.0.0'}
|
4969 |
hasBin: true
|
4970 |
|
4971 | |
4972 |
-
resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==}
|
4973 |
-
engines: {node: '>=14.0.0'}
|
4974 |
-
hasBin: true
|
4975 |
-
|
4976 | |
4977 |
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
4978 |
|
@@ -5042,6 +5126,12 @@ packages:
|
|
5042 |
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
5043 |
engines: {node: '>=14'}
|
5044 |
|
|
|
|
|
|
|
|
|
|
|
|
|
5045 | |
5046 |
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
|
5047 |
engines: {node: '>= 10'}
|
@@ -5179,9 +5269,9 @@ packages:
|
|
5179 |
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
5180 |
engines: {node: '>= 0.4'}
|
5181 |
|
5182 |
-
svelte@4.
|
5183 |
-
resolution: {integrity: sha512-
|
5184 |
-
engines: {node: '>=
|
5185 |
|
5186 | |
5187 |
resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==}
|
@@ -5315,16 +5405,16 @@ packages:
|
|
5315 |
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
5316 |
engines: {node: '>= 0.8.0'}
|
5317 |
|
5318 |
-
type-fest@4.
|
5319 |
-
resolution: {integrity: sha512-
|
5320 |
engines: {node: '>=16'}
|
5321 |
|
5322 | |
5323 |
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
5324 |
engines: {node: '>= 0.6'}
|
5325 |
|
5326 |
-
typescript-eslint@8.
|
5327 |
-
resolution: {integrity: sha512-
|
5328 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
5329 |
peerDependencies:
|
5330 |
eslint: ^8.57.0 || ^9.0.0
|
@@ -5533,9 +5623,9 @@ packages:
|
|
5533 |
engines: {node: ^18.0.0 || >=20.0.0}
|
5534 |
hasBin: true
|
5535 |
|
5536 |
-
[email protected].
|
5537 |
-
resolution: {integrity: sha512-
|
5538 |
-
engines: {node: ^18.0.0 ||
|
5539 |
hasBin: true
|
5540 |
|
5541 | |
@@ -5587,15 +5677,15 @@ packages:
|
|
5587 |
terser:
|
5588 |
optional: true
|
5589 |
|
5590 |
-
[email protected].
|
5591 |
-
resolution: {integrity: sha512-
|
5592 |
-
engines: {node: ^18.0.0 ||
|
5593 |
hasBin: true
|
5594 |
peerDependencies:
|
5595 |
'@edge-runtime/vm': '*'
|
5596 |
-
'@types/node': ^18.0.0 ||
|
5597 |
-
'@vitest/browser': 2.1.
|
5598 |
-
'@vitest/ui': 2.1.
|
5599 |
happy-dom: '*'
|
5600 |
jsdom: '*'
|
5601 |
peerDependenciesMeta:
|
@@ -5615,8 +5705,8 @@ packages:
|
|
5615 | |
5616 |
resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
|
5617 |
|
5618 |
-
vue@3.
|
5619 |
-
resolution: {integrity: sha512-
|
5620 |
peerDependencies:
|
5621 |
typescript: '*'
|
5622 |
peerDependenciesMeta:
|
@@ -5737,6 +5827,9 @@ packages:
|
|
5737 | |
5738 |
resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
|
5739 |
|
|
|
|
|
|
|
5740 | |
5741 |
resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==}
|
5742 |
peerDependencies:
|
@@ -5863,13 +5956,13 @@ snapshots:
|
|
5863 |
transitivePeerDependencies:
|
5864 |
- zod
|
5865 |
|
5866 |
-
'@ai-sdk/[email protected](svelte@4.
|
5867 |
dependencies:
|
5868 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
5869 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
5870 |
-
sswr: 2.1.0(svelte@4.
|
5871 |
optionalDependencies:
|
5872 |
-
svelte: 4.
|
5873 |
transitivePeerDependencies:
|
5874 |
- zod
|
5875 |
|
@@ -5883,13 +5976,13 @@ snapshots:
|
|
5883 |
optionalDependencies:
|
5884 |
zod: 3.23.8
|
5885 |
|
5886 |
-
'@ai-sdk/[email protected](vue@3.
|
5887 |
dependencies:
|
5888 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
5889 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
5890 |
-
swrv: 1.0.4(vue@3.
|
5891 |
optionalDependencies:
|
5892 |
-
vue: 3.
|
5893 |
transitivePeerDependencies:
|
5894 |
- zod
|
5895 |
|
@@ -6109,16 +6202,16 @@ snapshots:
|
|
6109 |
'@blitz/[email protected](@types/[email protected])([email protected])([email protected])([email protected])':
|
6110 |
dependencies:
|
6111 |
'@stylistic/eslint-plugin-ts': 2.11.0([email protected]([email protected]))([email protected])
|
6112 |
-
'@typescript-eslint/eslint-plugin': 8.
|
6113 |
-
'@typescript-eslint/parser': 8.
|
6114 |
-
'@typescript-eslint/utils': 8.
|
6115 |
common-tags: 1.8.2
|
6116 |
eslint: 9.16.0([email protected])
|
6117 |
eslint-config-prettier: 9.1.0([email protected]([email protected]))
|
6118 |
eslint-plugin-jsonc: 2.18.2([email protected]([email protected]))
|
6119 |
eslint-plugin-prettier: 5.2.1(@types/[email protected])([email protected]([email protected]([email protected])))([email protected]([email protected]))([email protected])
|
6120 |
globals: 15.13.0
|
6121 |
-
typescript-eslint: 8.
|
6122 |
transitivePeerDependencies:
|
6123 |
- '@eslint/json'
|
6124 |
- '@types/eslint'
|
@@ -6208,7 +6301,7 @@ snapshots:
|
|
6208 |
'@codemirror/state': 6.4.1
|
6209 |
'@codemirror/view': 6.35.0
|
6210 |
'@lezer/common': 1.2.3
|
6211 |
-
'@lezer/javascript': 1.4.
|
6212 |
|
6213 |
'@codemirror/[email protected]':
|
6214 |
dependencies:
|
@@ -6245,6 +6338,15 @@ snapshots:
|
|
6245 |
transitivePeerDependencies:
|
6246 |
- '@codemirror/view'
|
6247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6248 |
'@codemirror/[email protected]':
|
6249 |
dependencies:
|
6250 |
'@codemirror/language': 6.10.6
|
@@ -6720,7 +6822,7 @@ snapshots:
|
|
6720 |
'@lezer/highlight': 1.2.1
|
6721 |
'@lezer/lr': 1.4.2
|
6722 |
|
6723 |
-
'@lezer/[email protected].
|
6724 |
dependencies:
|
6725 |
'@lezer/common': 1.2.3
|
6726 |
'@lezer/highlight': 1.2.1
|
@@ -7112,6 +7214,15 @@ snapshots:
|
|
7112 |
'@types/react': 18.3.12
|
7113 |
'@types/react-dom': 18.3.1
|
7114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7115 |
'@radix-ui/[email protected](@types/[email protected])([email protected])':
|
7116 |
dependencies:
|
7117 |
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
|
@@ -7119,6 +7230,21 @@ snapshots:
|
|
7119 |
optionalDependencies:
|
7120 |
'@types/react': 18.3.12
|
7121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7122 |
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
|
7123 |
dependencies:
|
7124 |
'@radix-ui/primitive': 1.1.0
|
@@ -7165,6 +7291,12 @@ snapshots:
|
|
7165 |
optionalDependencies:
|
7166 |
'@types/react': 18.3.12
|
7167 |
|
|
|
|
|
|
|
|
|
|
|
|
|
7168 |
'@radix-ui/[email protected](@types/[email protected])([email protected])':
|
7169 |
dependencies:
|
7170 |
'@radix-ui/rect': 1.1.0
|
@@ -7205,7 +7337,7 @@ snapshots:
|
|
7205 |
optionalDependencies:
|
7206 |
typescript: 5.7.2
|
7207 |
|
7208 |
-
'@remix-run/[email protected](@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@types/[email protected])([email protected])(
|
7209 |
dependencies:
|
7210 |
'@babel/core': 7.26.0
|
7211 |
'@babel/generator': 7.26.2
|
@@ -7222,7 +7354,7 @@ snapshots:
|
|
7222 |
'@remix-run/router': 1.21.0
|
7223 |
'@remix-run/server-runtime': 2.15.0([email protected])
|
7224 |
'@types/mdx': 2.0.13
|
7225 |
-
'@vanilla-extract/integration': 6.5.0(@types/[email protected])([email protected])
|
7226 |
arg: 5.0.2
|
7227 |
cacache: 17.1.4
|
7228 |
chalk: 4.1.2
|
@@ -7261,11 +7393,11 @@ snapshots:
|
|
7261 |
tar-fs: 2.1.1
|
7262 |
tsconfig-paths: 4.2.0
|
7263 |
valibot: 0.41.0([email protected])
|
7264 |
-
vite-node: 1.6.0(@types/[email protected])([email protected])
|
7265 |
ws: 7.5.10
|
7266 |
optionalDependencies:
|
7267 |
typescript: 5.7.2
|
7268 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
7269 |
wrangler: 3.91.0(@cloudflare/[email protected])
|
7270 |
transitivePeerDependencies:
|
7271 |
- '@types/node'
|
@@ -7448,7 +7580,7 @@ snapshots:
|
|
7448 |
|
7449 |
'@stylistic/[email protected]([email protected]([email protected]))([email protected])':
|
7450 |
dependencies:
|
7451 |
-
'@typescript-eslint/utils': 8.
|
7452 |
eslint: 9.16.0([email protected])
|
7453 |
eslint-visitor-keys: 4.2.0
|
7454 |
espree: 10.3.0
|
@@ -7533,14 +7665,14 @@ snapshots:
|
|
7533 |
|
7534 |
'@types/[email protected]': {}
|
7535 |
|
7536 |
-
'@typescript-eslint/eslint-plugin@8.
|
7537 |
dependencies:
|
7538 |
'@eslint-community/regexpp': 4.12.1
|
7539 |
-
'@typescript-eslint/parser': 8.
|
7540 |
-
'@typescript-eslint/scope-manager': 8.
|
7541 |
-
'@typescript-eslint/type-utils': 8.
|
7542 |
-
'@typescript-eslint/utils': 8.
|
7543 |
-
'@typescript-eslint/visitor-keys': 8.
|
7544 |
eslint: 9.16.0([email protected])
|
7545 |
graphemer: 1.4.0
|
7546 |
ignore: 5.3.2
|
@@ -7551,12 +7683,12 @@ snapshots:
|
|
7551 |
transitivePeerDependencies:
|
7552 |
- supports-color
|
7553 |
|
7554 |
-
'@typescript-eslint/parser@8.
|
7555 |
dependencies:
|
7556 |
-
'@typescript-eslint/scope-manager': 8.
|
7557 |
-
'@typescript-eslint/types': 8.
|
7558 |
-
'@typescript-eslint/typescript-estree': 8.
|
7559 |
-
'@typescript-eslint/visitor-keys': 8.
|
7560 |
debug: 4.3.7
|
7561 |
eslint: 9.16.0([email protected])
|
7562 |
optionalDependencies:
|
@@ -7564,15 +7696,15 @@ snapshots:
|
|
7564 |
transitivePeerDependencies:
|
7565 |
- supports-color
|
7566 |
|
7567 |
-
'@typescript-eslint/scope-manager@8.
|
7568 |
dependencies:
|
7569 |
-
'@typescript-eslint/types': 8.
|
7570 |
-
'@typescript-eslint/visitor-keys': 8.
|
7571 |
|
7572 |
-
'@typescript-eslint/type-utils@8.
|
7573 |
dependencies:
|
7574 |
-
'@typescript-eslint/typescript-estree': 8.
|
7575 |
-
'@typescript-eslint/utils': 8.
|
7576 |
debug: 4.3.7
|
7577 |
eslint: 9.16.0([email protected])
|
7578 |
ts-api-utils: 1.4.3([email protected])
|
@@ -7581,12 +7713,12 @@ snapshots:
|
|
7581 |
transitivePeerDependencies:
|
7582 |
- supports-color
|
7583 |
|
7584 |
-
'@typescript-eslint/types@8.
|
7585 |
|
7586 |
-
'@typescript-eslint/typescript-estree@8.
|
7587 |
dependencies:
|
7588 |
-
'@typescript-eslint/types': 8.
|
7589 |
-
'@typescript-eslint/visitor-keys': 8.
|
7590 |
debug: 4.3.7
|
7591 |
fast-glob: 3.3.2
|
7592 |
is-glob: 4.0.3
|
@@ -7598,21 +7730,21 @@ snapshots:
|
|
7598 |
transitivePeerDependencies:
|
7599 |
- supports-color
|
7600 |
|
7601 |
-
'@typescript-eslint/utils@8.
|
7602 |
dependencies:
|
7603 |
'@eslint-community/eslint-utils': 4.4.1([email protected]([email protected]))
|
7604 |
-
'@typescript-eslint/scope-manager': 8.
|
7605 |
-
'@typescript-eslint/types': 8.
|
7606 |
-
'@typescript-eslint/typescript-estree': 8.
|
7607 |
eslint: 9.16.0([email protected])
|
7608 |
optionalDependencies:
|
7609 |
typescript: 5.7.2
|
7610 |
transitivePeerDependencies:
|
7611 |
- supports-color
|
7612 |
|
7613 |
-
'@typescript-eslint/visitor-keys@8.
|
7614 |
dependencies:
|
7615 |
-
'@typescript-eslint/types': 8.
|
7616 |
eslint-visitor-keys: 4.2.0
|
7617 |
|
7618 |
'@uiw/[email protected](@codemirror/[email protected])(@codemirror/[email protected])(@codemirror/[email protected])':
|
@@ -7631,13 +7763,13 @@ snapshots:
|
|
7631 |
|
7632 |
'@ungap/[email protected]': {}
|
7633 |
|
7634 |
-
'@unocss/[email protected]([email protected])([email protected](@types/[email protected])([email protected])
|
7635 |
dependencies:
|
7636 |
'@unocss/core': 0.61.9
|
7637 |
'@unocss/reset': 0.61.9
|
7638 |
-
'@unocss/vite': 0.61.9([email protected])([email protected](@types/[email protected])([email protected])
|
7639 |
optionalDependencies:
|
7640 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
7641 |
transitivePeerDependencies:
|
7642 |
- rollup
|
7643 |
- supports-color
|
@@ -7774,7 +7906,7 @@ snapshots:
|
|
7774 |
dependencies:
|
7775 |
'@unocss/core': 0.61.9
|
7776 |
|
7777 |
-
'@unocss/[email protected]([email protected])([email protected](@types/[email protected])([email protected])
|
7778 |
dependencies:
|
7779 |
'@ampproject/remapping': 2.3.0
|
7780 |
'@rollup/pluginutils': 5.1.3([email protected])
|
@@ -7786,7 +7918,7 @@ snapshots:
|
|
7786 |
chokidar: 3.6.0
|
7787 |
fast-glob: 3.3.2
|
7788 |
magic-string: 0.30.14
|
7789 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
7790 |
transitivePeerDependencies:
|
7791 |
- rollup
|
7792 |
- supports-color
|
@@ -7814,7 +7946,7 @@ snapshots:
|
|
7814 |
transitivePeerDependencies:
|
7815 |
- babel-plugin-macros
|
7816 |
|
7817 |
-
'@vanilla-extract/[email protected](@types/[email protected])([email protected])
|
7818 |
dependencies:
|
7819 |
'@babel/core': 7.26.0
|
7820 |
'@babel/plugin-syntax-typescript': 7.25.9(@babel/[email protected])
|
@@ -7827,8 +7959,8 @@ snapshots:
|
|
7827 |
lodash: 4.17.21
|
7828 |
mlly: 1.7.3
|
7829 |
outdent: 0.8.0
|
7830 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
7831 |
-
vite-node: 1.6.0(@types/[email protected])([email protected])
|
7832 |
transitivePeerDependencies:
|
7833 |
- '@types/node'
|
7834 |
- babel-plugin-macros
|
@@ -7843,99 +7975,99 @@ snapshots:
|
|
7843 |
|
7844 |
'@vanilla-extract/[email protected]': {}
|
7845 |
|
7846 |
-
'@vitest/[email protected].
|
7847 |
dependencies:
|
7848 |
-
'@vitest/spy': 2.1.
|
7849 |
-
'@vitest/utils': 2.1.
|
7850 |
chai: 5.1.2
|
7851 |
tinyrainbow: 1.2.0
|
7852 |
|
7853 |
-
'@vitest/[email protected].
|
7854 |
dependencies:
|
7855 |
-
'@vitest/spy': 2.1.
|
7856 |
estree-walker: 3.0.3
|
7857 |
magic-string: 0.30.14
|
7858 |
optionalDependencies:
|
7859 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
7860 |
|
7861 |
-
'@vitest/[email protected].
|
7862 |
dependencies:
|
7863 |
tinyrainbow: 1.2.0
|
7864 |
|
7865 |
-
'@vitest/[email protected].
|
7866 |
dependencies:
|
7867 |
-
'@vitest/utils': 2.1.
|
7868 |
pathe: 1.1.2
|
7869 |
|
7870 |
-
'@vitest/[email protected].
|
7871 |
dependencies:
|
7872 |
-
'@vitest/pretty-format': 2.1.
|
7873 |
magic-string: 0.30.14
|
7874 |
pathe: 1.1.2
|
7875 |
|
7876 |
-
'@vitest/[email protected].
|
7877 |
dependencies:
|
7878 |
tinyspy: 3.0.2
|
7879 |
|
7880 |
-
'@vitest/[email protected].
|
7881 |
dependencies:
|
7882 |
-
'@vitest/pretty-format': 2.1.
|
7883 |
loupe: 3.1.2
|
7884 |
tinyrainbow: 1.2.0
|
7885 |
|
7886 |
-
'@vue/compiler-core@3.
|
7887 |
dependencies:
|
7888 |
'@babel/parser': 7.26.2
|
7889 |
-
'@vue/shared': 3.
|
7890 |
entities: 4.5.0
|
7891 |
estree-walker: 2.0.2
|
7892 |
source-map-js: 1.2.1
|
7893 |
|
7894 |
-
'@vue/compiler-dom@3.
|
7895 |
dependencies:
|
7896 |
-
'@vue/compiler-core': 3.
|
7897 |
-
'@vue/shared': 3.
|
7898 |
|
7899 |
-
'@vue/compiler-sfc@3.
|
7900 |
dependencies:
|
7901 |
'@babel/parser': 7.26.2
|
7902 |
-
'@vue/compiler-core': 3.
|
7903 |
-
'@vue/compiler-dom': 3.
|
7904 |
-
'@vue/compiler-ssr': 3.
|
7905 |
-
'@vue/shared': 3.
|
7906 |
estree-walker: 2.0.2
|
7907 |
magic-string: 0.30.14
|
7908 |
postcss: 8.4.49
|
7909 |
source-map-js: 1.2.1
|
7910 |
|
7911 |
-
'@vue/compiler-ssr@3.
|
7912 |
dependencies:
|
7913 |
-
'@vue/compiler-dom': 3.
|
7914 |
-
'@vue/shared': 3.
|
7915 |
|
7916 |
-
'@vue/reactivity@3.
|
7917 |
dependencies:
|
7918 |
-
'@vue/shared': 3.
|
7919 |
|
7920 |
-
'@vue/runtime-core@3.
|
7921 |
dependencies:
|
7922 |
-
'@vue/reactivity': 3.
|
7923 |
-
'@vue/shared': 3.
|
7924 |
|
7925 |
-
'@vue/runtime-dom@3.
|
7926 |
dependencies:
|
7927 |
-
'@vue/reactivity': 3.
|
7928 |
-
'@vue/runtime-core': 3.
|
7929 |
-
'@vue/shared': 3.
|
7930 |
csstype: 3.1.3
|
7931 |
|
7932 |
-
'@vue/server-renderer@3.
|
7933 |
dependencies:
|
7934 |
-
'@vue/compiler-ssr': 3.
|
7935 |
-
'@vue/shared': 3.
|
7936 |
-
vue: 3.
|
7937 |
|
7938 |
-
'@vue/shared@3.
|
7939 |
|
7940 |
'@web3-storage/[email protected]': {}
|
7941 |
|
@@ -7967,6 +8099,10 @@ snapshots:
|
|
7967 |
dependencies:
|
7968 |
acorn: 8.14.0
|
7969 |
|
|
|
|
|
|
|
|
|
7970 | |
7971 |
dependencies:
|
7972 |
acorn: 8.14.0
|
@@ -7978,15 +8114,15 @@ snapshots:
|
|
7978 |
clean-stack: 2.2.0
|
7979 |
indent-string: 4.0.0
|
7980 |
|
7981 |
-
[email protected]([email protected])([email protected](svelte@4.
|
7982 |
dependencies:
|
7983 |
'@ai-sdk/provider': 0.0.26
|
7984 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
7985 |
'@ai-sdk/react': 0.0.70([email protected])([email protected])
|
7986 |
'@ai-sdk/solid': 0.0.54([email protected])
|
7987 |
-
'@ai-sdk/svelte': 0.0.57(svelte@4.
|
7988 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
7989 |
-
'@ai-sdk/vue': 0.0.59(vue@3.
|
7990 |
'@opentelemetry/api': 1.9.0
|
7991 |
eventsource-parser: 1.1.2
|
7992 |
json-schema: 0.4.0
|
@@ -7995,8 +8131,8 @@ snapshots:
|
|
7995 |
zod-to-json-schema: 3.23.5([email protected])
|
7996 |
optionalDependencies:
|
7997 |
react: 18.3.1
|
7998 |
-
sswr: 2.1.0(svelte@4.
|
7999 |
-
svelte: 4.
|
8000 |
zod: 3.23.8
|
8001 |
transitivePeerDependencies:
|
8002 |
- solid-js
|
@@ -8058,6 +8194,8 @@ snapshots:
|
|
8058 |
|
8059 | |
8060 |
|
|
|
|
|
8061 | |
8062 |
dependencies:
|
8063 |
possible-typed-array-names: 1.0.0
|
@@ -8178,7 +8316,7 @@ snapshots:
|
|
8178 | |
8179 |
dependencies:
|
8180 |
caniuse-lite: 1.0.30001685
|
8181 |
-
electron-to-chromium: 1.5.
|
8182 |
node-releases: 2.0.18
|
8183 |
update-browserslist-db: 1.1.1([email protected])
|
8184 |
|
@@ -8292,6 +8430,8 @@ snapshots:
|
|
8292 |
inherits: 2.0.4
|
8293 |
safe-buffer: 5.2.1
|
8294 |
|
|
|
|
|
8295 | |
8296 |
|
8297 | |
@@ -8306,14 +8446,6 @@ snapshots:
|
|
8306 |
|
8307 | |
8308 |
|
8309 | |
8310 |
-
dependencies:
|
8311 |
-
'@jridgewell/sourcemap-codec': 1.5.0
|
8312 |
-
'@types/estree': 1.0.6
|
8313 |
-
acorn: 8.14.0
|
8314 |
-
estree-walker: 3.0.3
|
8315 |
-
periscopic: 3.1.0
|
8316 |
-
|
8317 | |
8318 |
dependencies:
|
8319 |
color-name: 1.1.4
|
@@ -8358,6 +8490,8 @@ snapshots:
|
|
8358 |
|
8359 | |
8360 |
|
|
|
|
|
8361 | |
8362 |
dependencies:
|
8363 |
bn.js: 4.12.1
|
@@ -8438,6 +8572,10 @@ snapshots:
|
|
8438 |
dependencies:
|
8439 |
character-entities: 2.0.2
|
8440 |
|
|
|
|
|
|
|
|
|
8441 | |
8442 |
|
8443 | |
@@ -8487,6 +8625,8 @@ snapshots:
|
|
8487 |
|
8488 | |
8489 |
|
|
|
|
|
8490 | |
8491 |
|
8492 | |
@@ -8516,7 +8656,7 @@ snapshots:
|
|
8516 |
|
8517 | |
8518 |
|
8519 |
-
[email protected].
|
8520 |
|
8521 | |
8522 |
dependencies:
|
@@ -8559,7 +8699,7 @@ snapshots:
|
|
8559 |
'@jspm/core': 2.0.1
|
8560 |
esbuild: 0.17.6
|
8561 |
local-pkg: 0.5.1
|
8562 |
-
resolve.exports: 2.0.
|
8563 |
|
8564 | |
8565 |
optionalDependencies:
|
@@ -8761,6 +8901,8 @@ snapshots:
|
|
8761 |
transitivePeerDependencies:
|
8762 |
- supports-color
|
8763 |
|
|
|
|
|
8764 | |
8765 |
dependencies:
|
8766 |
acorn: 8.14.0
|
@@ -8777,6 +8919,11 @@ snapshots:
|
|
8777 |
dependencies:
|
8778 |
estraverse: 5.3.0
|
8779 |
|
|
|
|
|
|
|
|
|
|
|
8780 | |
8781 |
dependencies:
|
8782 |
estraverse: 5.3.0
|
@@ -9019,7 +9166,7 @@ snapshots:
|
|
9019 |
es-errors: 1.3.0
|
9020 |
function-bind: 1.1.2
|
9021 |
has-proto: 1.1.0
|
9022 |
-
has-symbols: 1.0
|
9023 |
hasown: 2.0.2
|
9024 |
|
9025 | |
@@ -9095,11 +9242,11 @@ snapshots:
|
|
9095 |
dependencies:
|
9096 |
call-bind: 1.0.7
|
9097 |
|
9098 |
-
[email protected]
|
9099 |
|
9100 | |
9101 |
dependencies:
|
9102 |
-
has-symbols: 1.0
|
9103 |
|
9104 | |
9105 |
dependencies:
|
@@ -9274,9 +9421,6 @@ snapshots:
|
|
9274 |
|
9275 | |
9276 |
|
9277 | |
9278 |
-
optional: true
|
9279 |
-
|
9280 | |
9281 |
|
9282 | |
@@ -9391,6 +9535,21 @@ snapshots:
|
|
9391 |
|
9392 | |
9393 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9394 | |
9395 |
|
9396 | |
@@ -10248,6 +10407,8 @@ snapshots:
|
|
10248 |
|
10249 | |
10250 |
|
|
|
|
|
10251 | |
10252 |
dependencies:
|
10253 |
'@cspotcode/source-map-support': 0.8.1
|
@@ -10281,6 +10442,10 @@ snapshots:
|
|
10281 |
|
10282 | |
10283 |
|
|
|
|
|
|
|
|
|
10284 | |
10285 |
dependencies:
|
10286 |
minipass: 3.3.6
|
@@ -10431,7 +10596,7 @@ snapshots:
|
|
10431 |
dependencies:
|
10432 |
call-bind: 1.0.7
|
10433 |
define-properties: 1.2.1
|
10434 |
-
has-symbols: 1.0
|
10435 |
object-keys: 1.1.1
|
10436 |
|
10437 | |
@@ -10598,6 +10763,8 @@ snapshots:
|
|
10598 |
|
10599 | |
10600 |
|
|
|
|
|
10601 | |
10602 |
dependencies:
|
10603 |
find-up: 5.0.0
|
@@ -10973,7 +11140,7 @@ snapshots:
|
|
10973 |
|
10974 |
[email protected](@remix-run/[email protected](@cloudflare/[email protected])([email protected]))(@remix-run/[email protected]([email protected]))(@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@remix-run/[email protected])([email protected])([email protected]):
|
10975 |
dependencies:
|
10976 |
-
type-fest: 4.
|
10977 |
optionalDependencies:
|
10978 |
'@remix-run/cloudflare': 2.15.0(@cloudflare/[email protected])([email protected])
|
10979 |
'@remix-run/node': 2.15.0([email protected])
|
@@ -10988,7 +11155,7 @@ snapshots:
|
|
10988 |
|
10989 | |
10990 |
|
10991 |
-
[email protected].
|
10992 |
|
10993 | |
10994 |
dependencies:
|
@@ -11158,13 +11325,6 @@ snapshots:
|
|
11158 |
sass-embedded-win32-ia32: 1.81.0
|
11159 |
sass-embedded-win32-x64: 1.81.0
|
11160 |
|
11161 | |
11162 |
-
dependencies:
|
11163 |
-
chokidar: 3.6.0
|
11164 |
-
immutable: 4.3.7
|
11165 |
-
source-map-js: 1.2.1
|
11166 |
-
optional: true
|
11167 |
-
|
11168 | |
11169 |
dependencies:
|
11170 |
loose-envify: 1.4.0
|
@@ -11255,6 +11415,14 @@ snapshots:
|
|
11255 |
|
11256 | |
11257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11258 | |
11259 |
dependencies:
|
11260 |
'@polka/url': 1.0.0-next.28
|
@@ -11294,9 +11462,9 @@ snapshots:
|
|
11294 |
dependencies:
|
11295 |
minipass: 7.1.2
|
11296 |
|
11297 |
-
[email protected](svelte@4.
|
11298 |
dependencies:
|
11299 |
-
svelte: 4.
|
11300 |
swrev: 4.0.0
|
11301 |
|
11302 | |
@@ -11389,22 +11557,21 @@ snapshots:
|
|
11389 |
|
11390 | |
11391 |
|
11392 |
-
svelte@4.
|
11393 |
dependencies:
|
11394 |
'@ampproject/remapping': 2.3.0
|
11395 |
'@jridgewell/sourcemap-codec': 1.5.0
|
11396 |
-
'@jridgewell/trace-mapping': 0.3.25
|
11397 |
'@types/estree': 1.0.6
|
11398 |
acorn: 8.14.0
|
|
|
11399 |
aria-query: 5.3.2
|
11400 |
axobject-query: 4.1.0
|
11401 |
-
|
11402 |
-
|
11403 |
-
estree-walker: 3.0.3
|
11404 |
is-reference: 3.0.3
|
11405 |
locate-character: 3.0.0
|
11406 |
magic-string: 0.30.14
|
11407 |
-
|
11408 |
|
11409 | |
11410 |
dependencies:
|
@@ -11414,9 +11581,9 @@ snapshots:
|
|
11414 |
|
11415 | |
11416 |
|
11417 |
-
[email protected](vue@3.
|
11418 |
dependencies:
|
11419 |
-
vue: 3.
|
11420 |
|
11421 | |
11422 |
dependencies:
|
@@ -11527,18 +11694,18 @@ snapshots:
|
|
11527 |
dependencies:
|
11528 |
prelude-ls: 1.2.1
|
11529 |
|
11530 |
-
type-fest@4.
|
11531 |
|
11532 | |
11533 |
dependencies:
|
11534 |
media-typer: 0.3.0
|
11535 |
mime-types: 2.1.35
|
11536 |
|
11537 |
-
typescript-eslint@8.
|
11538 |
dependencies:
|
11539 |
-
'@typescript-eslint/eslint-plugin': 8.
|
11540 |
-
'@typescript-eslint/parser': 8.
|
11541 |
-
'@typescript-eslint/utils': 8.
|
11542 |
eslint: 9.16.0([email protected])
|
11543 |
optionalDependencies:
|
11544 |
typescript: 5.7.2
|
@@ -11661,9 +11828,9 @@ snapshots:
|
|
11661 |
|
11662 | |
11663 |
|
11664 | |
11665 |
dependencies:
|
11666 |
-
'@unocss/astro': 0.61.9([email protected])([email protected](@types/[email protected])([email protected])
|
11667 |
'@unocss/cli': 0.61.9([email protected])
|
11668 |
'@unocss/core': 0.61.9
|
11669 |
'@unocss/extractor-arbitrary-variants': 0.61.9
|
@@ -11682,9 +11849,9 @@ snapshots:
|
|
11682 |
'@unocss/transformer-compile-class': 0.61.9
|
11683 |
'@unocss/transformer-directives': 0.61.9
|
11684 |
'@unocss/transformer-variant-group': 0.61.9
|
11685 |
-
'@unocss/vite': 0.61.9([email protected])([email protected](@types/[email protected])([email protected])
|
11686 |
optionalDependencies:
|
11687 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11688 |
transitivePeerDependencies:
|
11689 |
- postcss
|
11690 |
- rollup
|
@@ -11789,13 +11956,13 @@ snapshots:
|
|
11789 |
'@types/unist': 3.0.3
|
11790 |
vfile-message: 4.0.2
|
11791 |
|
11792 | |
11793 |
dependencies:
|
11794 |
cac: 6.7.14
|
11795 |
debug: 4.3.7
|
11796 |
pathe: 1.1.2
|
11797 |
picocolors: 1.1.1
|
11798 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11799 |
transitivePeerDependencies:
|
11800 |
- '@types/node'
|
11801 |
- less
|
@@ -11807,13 +11974,13 @@ snapshots:
|
|
11807 |
- supports-color
|
11808 |
- terser
|
11809 |
|
11810 |
-
[email protected].
|
11811 |
dependencies:
|
11812 |
cac: 6.7.14
|
11813 |
debug: 4.3.7
|
11814 |
es-module-lexer: 1.5.4
|
11815 |
pathe: 1.1.2
|
11816 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11817 |
transitivePeerDependencies:
|
11818 |
- '@types/node'
|
11819 |
- less
|
@@ -11825,30 +11992,30 @@ snapshots:
|
|
11825 |
- supports-color
|
11826 |
- terser
|
11827 |
|
11828 | |
11829 |
dependencies:
|
11830 |
'@rollup/plugin-inject': 5.0.5([email protected])
|
11831 |
node-stdlib-browser: 1.3.0
|
11832 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11833 |
transitivePeerDependencies:
|
11834 |
- rollup
|
11835 |
|
11836 | |
11837 |
dependencies:
|
11838 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11839 |
|
11840 | |
11841 |
dependencies:
|
11842 |
debug: 4.3.7
|
11843 |
globrex: 0.1.2
|
11844 |
tsconfck: 3.1.4([email protected])
|
11845 |
optionalDependencies:
|
11846 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11847 |
transitivePeerDependencies:
|
11848 |
- supports-color
|
11849 |
- typescript
|
11850 |
|
11851 | |
11852 |
dependencies:
|
11853 |
esbuild: 0.21.5
|
11854 |
postcss: 8.4.49
|
@@ -11856,18 +12023,17 @@ snapshots:
|
|
11856 |
optionalDependencies:
|
11857 |
'@types/node': 22.10.1
|
11858 |
fsevents: 2.3.3
|
11859 |
-
sass: 1.77.6
|
11860 |
sass-embedded: 1.81.0
|
11861 |
|
11862 |
-
[email protected].
|
11863 |
dependencies:
|
11864 |
-
'@vitest/expect': 2.1.
|
11865 |
-
'@vitest/mocker': 2.1.
|
11866 |
-
'@vitest/pretty-format': 2.1.
|
11867 |
-
'@vitest/runner': 2.1.
|
11868 |
-
'@vitest/snapshot': 2.1.
|
11869 |
-
'@vitest/spy': 2.1.
|
11870 |
-
'@vitest/utils': 2.1.
|
11871 |
chai: 5.1.2
|
11872 |
debug: 4.3.7
|
11873 |
expect-type: 1.1.0
|
@@ -11878,8 +12044,8 @@ snapshots:
|
|
11878 |
tinyexec: 0.3.1
|
11879 |
tinypool: 1.0.2
|
11880 |
tinyrainbow: 1.2.0
|
11881 |
-
vite: 5.4.11(@types/[email protected])([email protected])
|
11882 |
-
vite-node: 2.1.
|
11883 |
why-is-node-running: 2.3.0
|
11884 |
optionalDependencies:
|
11885 |
'@types/node': 22.10.1
|
@@ -11896,13 +12062,13 @@ snapshots:
|
|
11896 |
|
11897 | |
11898 |
|
11899 |
-
vue@3.
|
11900 |
dependencies:
|
11901 |
-
'@vue/compiler-dom': 3.
|
11902 |
-
'@vue/compiler-sfc': 3.
|
11903 |
-
'@vue/runtime-dom': 3.
|
11904 |
-
'@vue/server-renderer': 3.
|
11905 |
-
'@vue/shared': 3.
|
11906 |
optionalDependencies:
|
11907 |
typescript: 5.7.2
|
11908 |
|
@@ -11968,7 +12134,7 @@ snapshots:
|
|
11968 |
nanoid: 3.3.8
|
11969 |
path-to-regexp: 6.3.0
|
11970 |
resolve: 1.22.8
|
11971 |
-
resolve.exports: 2.0.
|
11972 |
selfsigned: 2.4.1
|
11973 |
source-map: 0.6.1
|
11974 |
unenv: [email protected]
|
@@ -12018,6 +12184,8 @@ snapshots:
|
|
12018 |
mustache: 4.2.0
|
12019 |
stacktracey: 2.1.8
|
12020 |
|
|
|
|
|
12021 | |
12022 |
dependencies:
|
12023 |
zod: 3.23.8
|
|
|
56 |
'@codemirror/lang-sass':
|
57 |
specifier: ^6.0.2
|
58 |
version: 6.0.2(@codemirror/[email protected])
|
59 |
+
'@codemirror/lang-vue':
|
60 |
+
specifier: ^0.1.3
|
61 |
+
version: 0.1.3
|
62 |
'@codemirror/lang-wast':
|
63 |
specifier: ^6.0.2
|
64 |
version: 6.0.2
|
|
|
101 |
'@radix-ui/react-dropdown-menu':
|
102 |
specifier: ^2.1.2
|
103 |
version: 2.1.2(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
104 |
+
'@radix-ui/react-separator':
|
105 |
+
specifier: ^1.1.0
|
106 |
+
version: 1.1.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
107 |
+
'@radix-ui/react-switch':
|
108 |
+
specifier: ^1.1.1
|
109 |
+
version: 1.1.1(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
110 |
'@radix-ui/react-tooltip':
|
111 |
specifier: ^1.1.4
|
112 |
version: 1.1.4(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
|
|
139 |
version: 5.5.0
|
140 |
ai:
|
141 |
specifier: ^3.4.33
|
142 |
+
version: 3.4.33([email protected])([email protected](svelte@5.4.0))(svelte@5.4.0)(vue@3.5.13([email protected]))([email protected])
|
143 |
date-fns:
|
144 |
specifier: ^3.6.0
|
145 |
version: 3.6.0
|
|
|
158 |
isbot:
|
159 |
specifier: ^4.4.0
|
160 |
version: 4.4.0
|
161 |
+
isomorphic-git:
|
162 |
+
specifier: ^1.27.2
|
163 |
+
version: 1.27.2
|
164 |
istextorbinary:
|
165 |
specifier: ^9.5.0
|
166 |
version: 9.5.0
|
|
|
179 |
ollama-ai-provider:
|
180 |
specifier: ^0.15.2
|
181 |
version: 0.15.2([email protected])
|
|
|
|
|
|
|
182 |
react:
|
183 |
specifier: ^18.3.1
|
184 |
version: 18.3.1
|
|
|
227 |
version: 4.20241127.0
|
228 |
'@remix-run/dev':
|
229 |
specifier: ^2.15.0
|
230 |
+
version: 2.15.0(@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected](@cloudflare/[email protected]))
|
231 |
'@types/diff':
|
232 |
specifier: ^5.2.3
|
233 |
version: 5.2.3
|
|
|
258 |
node-fetch:
|
259 |
specifier: ^3.3.2
|
260 |
version: 3.3.2
|
261 |
+
pnpm:
|
262 |
+
specifier: ^9.14.4
|
263 |
+
version: 9.14.4
|
264 |
prettier:
|
265 |
specifier: ^3.4.1
|
266 |
version: 3.4.1
|
|
|
275 |
version: 11.0.5
|
276 |
unocss:
|
277 |
specifier: ^0.61.9
|
278 |
+
version: 0.61.9([email protected])([email protected])([email protected](@types/[email protected])([email protected]))
|
279 |
vite:
|
280 |
specifier: ^5.4.11
|
281 |
+
version: 5.4.11(@types/[email protected])([email protected])
|
282 |
vite-plugin-node-polyfills:
|
283 |
specifier: ^0.22.0
|
284 |
+
version: 0.22.0([email protected])([email protected](@types/[email protected])([email protected]))
|
285 |
vite-plugin-optimize-css-modules:
|
286 |
specifier: ^1.1.0
|
287 |
+
version: 1.1.0([email protected](@types/[email protected])([email protected]))
|
288 |
vite-tsconfig-paths:
|
289 |
specifier: ^4.3.2
|
290 |
+
version: 4.3.2([email protected])([email protected](@types/[email protected])([email protected]))
|
291 |
vitest:
|
292 |
specifier: ^2.1.7
|
293 |
+
version: 2.1.8(@types/[email protected])([email protected])
|
294 |
wrangler:
|
295 |
specifier: ^3.91.0
|
296 |
version: 3.91.0(@cloudflare/[email protected])
|
|
|
678 |
'@codemirror/[email protected]':
|
679 |
resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==}
|
680 |
|
681 |
+
'@codemirror/[email protected]':
|
682 |
+
resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==}
|
683 |
+
|
684 |
'@codemirror/[email protected]':
|
685 |
resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==}
|
686 |
|
|
|
1390 |
'@lezer/[email protected]':
|
1391 |
resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==}
|
1392 |
|
1393 |
+
'@lezer/[email protected].20':
|
1394 |
+
resolution: {integrity: sha512-Qhl3x+hVPnZkylv+BS//zx77KR4GLxM4PiL02r/D1Zoa4WLQI1A0cHuOr6k0FOTTSCPNNfeNANax0I5DWcXBYw==}
|
1395 |
|
1396 |
'@lezer/[email protected]':
|
1397 |
resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==}
|
|
|
1732 |
'@types/react-dom':
|
1733 |
optional: true
|
1734 |
|
1735 |
+
'@radix-ui/[email protected]':
|
1736 |
+
resolution: {integrity: sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==}
|
1737 |
+
peerDependencies:
|
1738 |
+
'@types/react': '*'
|
1739 |
+
'@types/react-dom': '*'
|
1740 |
+
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
1741 |
+
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
1742 |
+
peerDependenciesMeta:
|
1743 |
+
'@types/react':
|
1744 |
+
optional: true
|
1745 |
+
'@types/react-dom':
|
1746 |
+
optional: true
|
1747 |
+
|
1748 |
'@radix-ui/[email protected]':
|
1749 |
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
|
1750 |
peerDependencies:
|
|
|
1754 |
'@types/react':
|
1755 |
optional: true
|
1756 |
|
1757 |
+
'@radix-ui/[email protected]':
|
1758 |
+
resolution: {integrity: sha512-diPqDDoBcZPSicYoMWdWx+bCPuTRH4QSp9J+65IvtdS0Kuzt67bI6n32vCj8q6NZmYW/ah+2orOtMwcX5eQwIg==}
|
1759 |
+
peerDependencies:
|
1760 |
+
'@types/react': '*'
|
1761 |
+
'@types/react-dom': '*'
|
1762 |
+
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
1763 |
+
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
1764 |
+
peerDependenciesMeta:
|
1765 |
+
'@types/react':
|
1766 |
+
optional: true
|
1767 |
+
'@types/react-dom':
|
1768 |
+
optional: true
|
1769 |
+
|
1770 |
'@radix-ui/[email protected]':
|
1771 |
resolution: {integrity: sha512-QpObUH/ZlpaO4YgHSaYzrLO2VuO+ZBFFgGzjMUPwtiYnAzzNNDPJeEGRrT7qNOrWm/Jr08M1vlp+vTHtnSQ0Uw==}
|
1772 |
peerDependencies:
|
|
|
1816 |
'@types/react':
|
1817 |
optional: true
|
1818 |
|
1819 |
+
'@radix-ui/[email protected]':
|
1820 |
+
resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==}
|
1821 |
+
peerDependencies:
|
1822 |
+
'@types/react': '*'
|
1823 |
+
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
1824 |
+
peerDependenciesMeta:
|
1825 |
+
'@types/react':
|
1826 |
+
optional: true
|
1827 |
+
|
1828 |
'@radix-ui/[email protected]':
|
1829 |
resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
|
1830 |
peerDependencies:
|
|
|
2152 |
'@types/[email protected]':
|
2153 |
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
2154 |
|
2155 |
+
'@typescript-eslint/eslint-plugin@8.17.0':
|
2156 |
+
resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==}
|
2157 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2158 |
peerDependencies:
|
2159 |
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
|
|
2163 |
typescript:
|
2164 |
optional: true
|
2165 |
|
2166 |
+
'@typescript-eslint/parser@8.17.0':
|
2167 |
+
resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==}
|
2168 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2169 |
peerDependencies:
|
2170 |
eslint: ^8.57.0 || ^9.0.0
|
|
|
2173 |
typescript:
|
2174 |
optional: true
|
2175 |
|
2176 |
+
'@typescript-eslint/scope-manager@8.17.0':
|
2177 |
+
resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==}
|
2178 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2179 |
|
2180 |
+
'@typescript-eslint/type-utils@8.17.0':
|
2181 |
+
resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==}
|
2182 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2183 |
peerDependencies:
|
2184 |
eslint: ^8.57.0 || ^9.0.0
|
|
|
2187 |
typescript:
|
2188 |
optional: true
|
2189 |
|
2190 |
+
'@typescript-eslint/types@8.17.0':
|
2191 |
+
resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==}
|
2192 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2193 |
|
2194 |
+
'@typescript-eslint/typescript-estree@8.17.0':
|
2195 |
+
resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==}
|
2196 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2197 |
peerDependencies:
|
2198 |
typescript: '*'
|
|
|
2200 |
typescript:
|
2201 |
optional: true
|
2202 |
|
2203 |
+
'@typescript-eslint/utils@8.17.0':
|
2204 |
+
resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==}
|
2205 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2206 |
peerDependencies:
|
2207 |
eslint: ^8.57.0 || ^9.0.0
|
|
|
2210 |
typescript:
|
2211 |
optional: true
|
2212 |
|
2213 |
+
'@typescript-eslint/visitor-keys@8.17.0':
|
2214 |
+
resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==}
|
2215 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
2216 |
|
2217 |
'@uiw/[email protected]':
|
|
|
2325 |
'@vanilla-extract/[email protected]':
|
2326 |
resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==}
|
2327 |
|
2328 |
+
'@vitest/[email protected].8':
|
2329 |
+
resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
|
2330 |
|
2331 |
+
'@vitest/[email protected].8':
|
2332 |
+
resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
|
2333 |
peerDependencies:
|
2334 |
msw: ^2.4.9
|
2335 |
vite: ^5.0.0
|
|
|
2339 |
vite:
|
2340 |
optional: true
|
2341 |
|
2342 |
+
'@vitest/[email protected].8':
|
2343 |
+
resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
|
2344 |
|
2345 |
+
'@vitest/[email protected].8':
|
2346 |
+
resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
|
2347 |
|
2348 |
+
'@vitest/[email protected].8':
|
2349 |
+
resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
|
2350 |
|
2351 |
+
'@vitest/[email protected].8':
|
2352 |
+
resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
|
2353 |
|
2354 |
+
'@vitest/[email protected].8':
|
2355 |
+
resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
|
2356 |
|
2357 |
+
'@vue/compiler-core@3.5.13':
|
2358 |
+
resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==}
|
2359 |
|
2360 |
+
'@vue/compiler-dom@3.5.13':
|
2361 |
+
resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
|
2362 |
|
2363 |
+
'@vue/compiler-sfc@3.5.13':
|
2364 |
+
resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
|
2365 |
|
2366 |
+
'@vue/compiler-ssr@3.5.13':
|
2367 |
+
resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
|
2368 |
|
2369 |
+
'@vue/reactivity@3.5.13':
|
2370 |
+
resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==}
|
2371 |
|
2372 |
+
'@vue/runtime-core@3.5.13':
|
2373 |
+
resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==}
|
2374 |
|
2375 |
+
'@vue/runtime-dom@3.5.13':
|
2376 |
+
resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==}
|
2377 |
|
2378 |
+
'@vue/server-renderer@3.5.13':
|
2379 |
+
resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==}
|
2380 |
peerDependencies:
|
2381 |
+
vue: 3.5.13
|
2382 |
|
2383 |
+
'@vue/shared@3.5.13':
|
2384 |
+
resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
|
2385 |
|
2386 |
'@web3-storage/[email protected]':
|
2387 |
resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==}
|
|
|
2418 |
peerDependencies:
|
2419 |
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
2420 |
|
2421 | |
2422 |
+
resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==}
|
2423 |
+
peerDependencies:
|
2424 |
+
acorn: '>=8.9.0'
|
2425 |
+
|
2426 | |
2427 |
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
|
2428 |
engines: {node: '>=0.4.0'}
|
|
|
2514 |
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
|
2515 |
hasBin: true
|
2516 |
|
2517 | |
2518 |
+
resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==}
|
2519 |
+
|
2520 | |
2521 |
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
2522 |
engines: {node: '>= 0.4'}
|
|
|
2706 |
resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==}
|
2707 |
engines: {node: '>= 0.10'}
|
2708 |
|
2709 | |
2710 |
+
resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==}
|
2711 |
+
|
2712 | |
2713 |
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
2714 |
engines: {node: '>=6'}
|
|
|
2732 |
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
2733 |
engines: {node: '>=6'}
|
2734 |
|
|
|
|
|
|
|
2735 | |
2736 |
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
2737 |
engines: {node: '>=7.0.0'}
|
|
|
2801 | |
2802 |
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
2803 |
|
2804 | |
2805 |
+
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
|
2806 |
+
engines: {node: '>=0.8'}
|
2807 |
+
hasBin: true
|
2808 |
+
|
2809 | |
2810 |
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
|
2811 |
|
|
|
2882 | |
2883 |
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
|
2884 |
|
2885 | |
2886 |
+
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
2887 |
+
engines: {node: '>=10'}
|
2888 |
+
|
2889 | |
2890 |
resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
|
2891 |
peerDependencies:
|
|
|
2949 | |
2950 |
resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
|
2951 |
|
2952 | |
2953 |
+
resolution: {integrity: sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==}
|
2954 |
+
|
2955 | |
2956 |
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
|
2957 |
engines: {node: '>=0.3.1'}
|
|
|
2983 | |
2984 |
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
2985 |
|
2986 |
+
[email protected].68:
|
2987 |
+
resolution: {integrity: sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==}
|
2988 |
|
2989 | |
2990 |
resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==}
|
|
|
3133 |
jiti:
|
3134 |
optional: true
|
3135 |
|
3136 | |
3137 |
+
resolution: {integrity: sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==}
|
3138 |
+
|
3139 | |
3140 |
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
|
3141 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
|
|
3148 |
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
|
3149 |
engines: {node: '>=0.10'}
|
3150 |
|
3151 | |
3152 |
+
resolution: {integrity: sha512-ZlQmCCK+n7SGoqo7DnfKaP1sJZa49P01/dXzmjCASSo04p72w8EksT2NMK8CEX8DhKsfJXANioIw8VyHNsBfvQ==}
|
3153 |
+
|
3154 | |
3155 |
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
|
3156 |
engines: {node: '>=4.0'}
|
|
|
3443 |
resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==}
|
3444 |
engines: {node: '>= 0.4'}
|
3445 |
|
3446 |
+
has-symbols@1.1.0:
|
3447 |
+
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
3448 |
engines: {node: '>= 0.4'}
|
3449 |
|
3450 | |
|
|
3548 | |
3549 |
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
3550 |
|
|
|
|
|
|
|
3551 | |
3552 |
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
|
3553 |
|
|
|
3686 | |
3687 |
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
3688 |
|
3689 | |
3690 |
+
resolution: {integrity: sha512-nCiz+ieOkWb5kDJSSckDTiMjTcgkxqH2xuiQmw1Y6O/spwx4d6TKYSfGCd4f71HGvUYcRSUGqJEI+3uN6UQlOw==}
|
3691 |
+
engines: {node: '>=12'}
|
3692 |
+
hasBin: true
|
3693 |
+
|
3694 | |
3695 |
resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==}
|
3696 |
engines: {node: '>=10'}
|
|
|
4171 |
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
4172 |
engines: {node: '>=6'}
|
4173 |
|
4174 | |
4175 |
+
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
|
4176 |
+
engines: {node: '>=10'}
|
4177 |
+
|
4178 | |
4179 |
resolution: {integrity: sha512-dM3RBlJE8rUFxnqlPCaFCq0E7qQqEQvKbYX7W/APGCK+rLcyLmEBzC4GQR/niXdNM/oV6gdg9AA50ghnn2ALuw==}
|
4180 |
engines: {node: '>=16.13'}
|
|
|
4196 | |
4197 |
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
4198 |
|
4199 | |
4200 |
+
resolution: {integrity: sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==}
|
4201 |
+
|
4202 | |
4203 |
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
4204 |
engines: {node: '>= 8'}
|
|
|
4502 |
engines: {node: '>=0.10'}
|
4503 |
hasBin: true
|
4504 |
|
4505 | |
4506 |
+
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
|
4507 |
+
engines: {node: '>=6'}
|
4508 |
+
|
4509 | |
4510 |
resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
|
4511 |
engines: {node: '>=10'}
|
|
|
4875 | |
4876 |
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
4877 |
|
4878 |
+
[email protected].3:
|
4879 |
+
resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==}
|
4880 |
engines: {node: '>=10'}
|
4881 |
|
4882 | |
|
|
5057 |
engines: {node: '>=16.0.0'}
|
5058 |
hasBin: true
|
5059 |
|
|
|
|
|
|
|
|
|
|
|
5060 | |
5061 |
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
5062 |
|
|
|
5126 |
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
5127 |
engines: {node: '>=14'}
|
5128 |
|
5129 | |
5130 |
+
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
|
5131 |
+
|
5132 | |
5133 |
+
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
|
5134 |
+
|
5135 | |
5136 |
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
|
5137 |
engines: {node: '>= 10'}
|
|
|
5269 |
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
5270 |
engines: {node: '>= 0.4'}
|
5271 |
|
5272 |
+
svelte@5.4.0:
|
5273 |
+
resolution: {integrity: sha512-2I/mjD8cXDpKfdfUK+T6yo/OzugMXIm8lhyJUFM5F/gICMYnkl3C/+4cOSpia8TqpDsi6Qfm5+fdmBNMNmaf2g==}
|
5274 |
+
engines: {node: '>=18'}
|
5275 |
|
5276 | |
5277 |
resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==}
|
|
|
5405 |
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
5406 |
engines: {node: '>= 0.8.0'}
|
5407 |
|
5408 |
+
type-fest@4.30.0:
|
5409 |
+
resolution: {integrity: sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==}
|
5410 |
engines: {node: '>=16'}
|
5411 |
|
5412 | |
5413 |
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
5414 |
engines: {node: '>= 0.6'}
|
5415 |
|
5416 |
+
typescript-eslint@8.17.0:
|
5417 |
+
resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==}
|
5418 |
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
5419 |
peerDependencies:
|
5420 |
eslint: ^8.57.0 || ^9.0.0
|
|
|
5623 |
engines: {node: ^18.0.0 || >=20.0.0}
|
5624 |
hasBin: true
|
5625 |
|
5626 |
+
[email protected].8:
|
5627 |
+
resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
|
5628 |
+
engines: {node: ^18.0.0 || >=20.0.0}
|
5629 |
hasBin: true
|
5630 |
|
5631 | |
|
|
5677 |
terser:
|
5678 |
optional: true
|
5679 |
|
5680 |
+
[email protected].8:
|
5681 |
+
resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
|
5682 |
+
engines: {node: ^18.0.0 || >=20.0.0}
|
5683 |
hasBin: true
|
5684 |
peerDependencies:
|
5685 |
'@edge-runtime/vm': '*'
|
5686 |
+
'@types/node': ^18.0.0 || >=20.0.0
|
5687 |
+
'@vitest/browser': 2.1.8
|
5688 |
+
'@vitest/ui': 2.1.8
|
5689 |
happy-dom: '*'
|
5690 |
jsdom: '*'
|
5691 |
peerDependenciesMeta:
|
|
|
5705 | |
5706 |
resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
|
5707 |
|
5708 |
+
vue@3.5.13:
|
5709 |
+
resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
|
5710 |
peerDependencies:
|
5711 |
typescript: '*'
|
5712 |
peerDependenciesMeta:
|
|
|
5827 | |
5828 |
resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
|
5829 |
|
5830 | |
5831 |
+
resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
|
5832 |
+
|
5833 | |
5834 |
resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==}
|
5835 |
peerDependencies:
|
|
|
5956 |
transitivePeerDependencies:
|
5957 |
- zod
|
5958 |
|
5959 |
+
'@ai-sdk/[email protected](svelte@5.4.0)([email protected])':
|
5960 |
dependencies:
|
5961 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
5962 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
5963 |
+
sswr: 2.1.0(svelte@5.4.0)
|
5964 |
optionalDependencies:
|
5965 |
+
svelte: 5.4.0
|
5966 |
transitivePeerDependencies:
|
5967 |
- zod
|
5968 |
|
|
|
5976 |
optionalDependencies:
|
5977 |
zod: 3.23.8
|
5978 |
|
5979 |
+
'@ai-sdk/[email protected](vue@3.5.13([email protected]))([email protected])':
|
5980 |
dependencies:
|
5981 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
5982 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
5983 |
+
swrv: 1.0.4(vue@3.5.13([email protected]))
|
5984 |
optionalDependencies:
|
5985 |
+
vue: 3.5.13([email protected])
|
5986 |
transitivePeerDependencies:
|
5987 |
- zod
|
5988 |
|
|
|
6202 |
'@blitz/[email protected](@types/[email protected])([email protected])([email protected])([email protected])':
|
6203 |
dependencies:
|
6204 |
'@stylistic/eslint-plugin-ts': 2.11.0([email protected]([email protected]))([email protected])
|
6205 |
+
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])
|
6206 |
+
'@typescript-eslint/parser': 8.17.0([email protected]([email protected]))([email protected])
|
6207 |
+
'@typescript-eslint/utils': 8.17.0([email protected]([email protected]))([email protected])
|
6208 |
common-tags: 1.8.2
|
6209 |
eslint: 9.16.0([email protected])
|
6210 |
eslint-config-prettier: 9.1.0([email protected]([email protected]))
|
6211 |
eslint-plugin-jsonc: 2.18.2([email protected]([email protected]))
|
6212 |
eslint-plugin-prettier: 5.2.1(@types/[email protected])([email protected]([email protected]([email protected])))([email protected]([email protected]))([email protected])
|
6213 |
globals: 15.13.0
|
6214 |
+
typescript-eslint: 8.17.0([email protected]([email protected]))([email protected])
|
6215 |
transitivePeerDependencies:
|
6216 |
- '@eslint/json'
|
6217 |
- '@types/eslint'
|
|
|
6301 |
'@codemirror/state': 6.4.1
|
6302 |
'@codemirror/view': 6.35.0
|
6303 |
'@lezer/common': 1.2.3
|
6304 |
+
'@lezer/javascript': 1.4.20
|
6305 |
|
6306 |
'@codemirror/[email protected]':
|
6307 |
dependencies:
|
|
|
6338 |
transitivePeerDependencies:
|
6339 |
- '@codemirror/view'
|
6340 |
|
6341 |
+
'@codemirror/[email protected]':
|
6342 |
+
dependencies:
|
6343 |
+
'@codemirror/lang-html': 6.4.9
|
6344 |
+
'@codemirror/lang-javascript': 6.2.2
|
6345 |
+
'@codemirror/language': 6.10.6
|
6346 |
+
'@lezer/common': 1.2.3
|
6347 |
+
'@lezer/highlight': 1.2.1
|
6348 |
+
'@lezer/lr': 1.4.2
|
6349 |
+
|
6350 |
'@codemirror/[email protected]':
|
6351 |
dependencies:
|
6352 |
'@codemirror/language': 6.10.6
|
|
|
6822 |
'@lezer/highlight': 1.2.1
|
6823 |
'@lezer/lr': 1.4.2
|
6824 |
|
6825 |
+
'@lezer/[email protected].20':
|
6826 |
dependencies:
|
6827 |
'@lezer/common': 1.2.3
|
6828 |
'@lezer/highlight': 1.2.1
|
|
|
7214 |
'@types/react': 18.3.12
|
7215 |
'@types/react-dom': 18.3.1
|
7216 |
|
7217 |
+
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
|
7218 |
+
dependencies:
|
7219 |
+
'@radix-ui/react-primitive': 2.0.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
7220 |
+
react: 18.3.1
|
7221 |
+
react-dom: 18.3.1([email protected])
|
7222 |
+
optionalDependencies:
|
7223 |
+
'@types/react': 18.3.12
|
7224 |
+
'@types/react-dom': 18.3.1
|
7225 |
+
|
7226 |
'@radix-ui/[email protected](@types/[email protected])([email protected])':
|
7227 |
dependencies:
|
7228 |
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
|
|
|
7230 |
optionalDependencies:
|
7231 |
'@types/react': 18.3.12
|
7232 |
|
7233 |
+
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
|
7234 |
+
dependencies:
|
7235 |
+
'@radix-ui/primitive': 1.1.0
|
7236 |
+
'@radix-ui/react-compose-refs': 1.1.0(@types/[email protected])([email protected])
|
7237 |
+
'@radix-ui/react-context': 1.1.1(@types/[email protected])([email protected])
|
7238 |
+
'@radix-ui/react-primitive': 2.0.0(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
|
7239 |
+
'@radix-ui/react-use-controllable-state': 1.1.0(@types/[email protected])([email protected])
|
7240 |
+
'@radix-ui/react-use-previous': 1.1.0(@types/[email protected])([email protected])
|
7241 |
+
'@radix-ui/react-use-size': 1.1.0(@types/[email protected])([email protected])
|
7242 |
+
react: 18.3.1
|
7243 |
+
react-dom: 18.3.1([email protected])
|
7244 |
+
optionalDependencies:
|
7245 |
+
'@types/react': 18.3.12
|
7246 |
+
'@types/react-dom': 18.3.1
|
7247 |
+
|
7248 |
'@radix-ui/[email protected](@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])':
|
7249 |
dependencies:
|
7250 |
'@radix-ui/primitive': 1.1.0
|
|
|
7291 |
optionalDependencies:
|
7292 |
'@types/react': 18.3.12
|
7293 |
|
7294 |
+
'@radix-ui/[email protected](@types/[email protected])([email protected])':
|
7295 |
+
dependencies:
|
7296 |
+
react: 18.3.1
|
7297 |
+
optionalDependencies:
|
7298 |
+
'@types/react': 18.3.12
|
7299 |
+
|
7300 |
'@radix-ui/[email protected](@types/[email protected])([email protected])':
|
7301 |
dependencies:
|
7302 |
'@radix-ui/rect': 1.1.0
|
|
|
7337 |
optionalDependencies:
|
7338 |
typescript: 5.7.2
|
7339 |
|
7340 |
+
'@remix-run/[email protected](@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@types/[email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected]))([email protected](@cloudflare/[email protected]))':
|
7341 |
dependencies:
|
7342 |
'@babel/core': 7.26.0
|
7343 |
'@babel/generator': 7.26.2
|
|
|
7354 |
'@remix-run/router': 1.21.0
|
7355 |
'@remix-run/server-runtime': 2.15.0([email protected])
|
7356 |
'@types/mdx': 2.0.13
|
7357 |
+
'@vanilla-extract/integration': 6.5.0(@types/[email protected])([email protected])
|
7358 |
arg: 5.0.2
|
7359 |
cacache: 17.1.4
|
7360 |
chalk: 4.1.2
|
|
|
7393 |
tar-fs: 2.1.1
|
7394 |
tsconfig-paths: 4.2.0
|
7395 |
valibot: 0.41.0([email protected])
|
7396 |
+
vite-node: 1.6.0(@types/[email protected])([email protected])
|
7397 |
ws: 7.5.10
|
7398 |
optionalDependencies:
|
7399 |
typescript: 5.7.2
|
7400 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
7401 |
wrangler: 3.91.0(@cloudflare/[email protected])
|
7402 |
transitivePeerDependencies:
|
7403 |
- '@types/node'
|
|
|
7580 |
|
7581 |
'@stylistic/[email protected]([email protected]([email protected]))([email protected])':
|
7582 |
dependencies:
|
7583 |
+
'@typescript-eslint/utils': 8.17.0([email protected]([email protected]))([email protected])
|
7584 |
eslint: 9.16.0([email protected])
|
7585 |
eslint-visitor-keys: 4.2.0
|
7586 |
espree: 10.3.0
|
|
|
7665 |
|
7666 |
'@types/[email protected]': {}
|
7667 |
|
7668 |
+
'@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])':
|
7669 |
dependencies:
|
7670 |
'@eslint-community/regexpp': 4.12.1
|
7671 |
+
'@typescript-eslint/parser': 8.17.0([email protected]([email protected]))([email protected])
|
7672 |
+
'@typescript-eslint/scope-manager': 8.17.0
|
7673 |
+
'@typescript-eslint/type-utils': 8.17.0([email protected]([email protected]))([email protected])
|
7674 |
+
'@typescript-eslint/utils': 8.17.0([email protected]([email protected]))([email protected])
|
7675 |
+
'@typescript-eslint/visitor-keys': 8.17.0
|
7676 |
eslint: 9.16.0([email protected])
|
7677 |
graphemer: 1.4.0
|
7678 |
ignore: 5.3.2
|
|
|
7683 |
transitivePeerDependencies:
|
7684 |
- supports-color
|
7685 |
|
7686 |
+
'@typescript-eslint/parser@8.17.0([email protected]([email protected]))([email protected])':
|
7687 |
dependencies:
|
7688 |
+
'@typescript-eslint/scope-manager': 8.17.0
|
7689 |
+
'@typescript-eslint/types': 8.17.0
|
7690 |
+
'@typescript-eslint/typescript-estree': 8.17.0([email protected])
|
7691 |
+
'@typescript-eslint/visitor-keys': 8.17.0
|
7692 |
debug: 4.3.7
|
7693 |
eslint: 9.16.0([email protected])
|
7694 |
optionalDependencies:
|
|
|
7696 |
transitivePeerDependencies:
|
7697 |
- supports-color
|
7698 |
|
7699 |
+
'@typescript-eslint/scope-manager@8.17.0':
|
7700 |
dependencies:
|
7701 |
+
'@typescript-eslint/types': 8.17.0
|
7702 |
+
'@typescript-eslint/visitor-keys': 8.17.0
|
7703 |
|
7704 |
+
'@typescript-eslint/type-utils@8.17.0([email protected]([email protected]))([email protected])':
|
7705 |
dependencies:
|
7706 |
+
'@typescript-eslint/typescript-estree': 8.17.0([email protected])
|
7707 |
+
'@typescript-eslint/utils': 8.17.0([email protected]([email protected]))([email protected])
|
7708 |
debug: 4.3.7
|
7709 |
eslint: 9.16.0([email protected])
|
7710 |
ts-api-utils: 1.4.3([email protected])
|
|
|
7713 |
transitivePeerDependencies:
|
7714 |
- supports-color
|
7715 |
|
7716 |
+
'@typescript-eslint/types@8.17.0': {}
|
7717 |
|
7718 |
+
'@typescript-eslint/typescript-estree@8.17.0([email protected])':
|
7719 |
dependencies:
|
7720 |
+
'@typescript-eslint/types': 8.17.0
|
7721 |
+
'@typescript-eslint/visitor-keys': 8.17.0
|
7722 |
debug: 4.3.7
|
7723 |
fast-glob: 3.3.2
|
7724 |
is-glob: 4.0.3
|
|
|
7730 |
transitivePeerDependencies:
|
7731 |
- supports-color
|
7732 |
|
7733 |
+
'@typescript-eslint/utils@8.17.0([email protected]([email protected]))([email protected])':
|
7734 |
dependencies:
|
7735 |
'@eslint-community/eslint-utils': 4.4.1([email protected]([email protected]))
|
7736 |
+
'@typescript-eslint/scope-manager': 8.17.0
|
7737 |
+
'@typescript-eslint/types': 8.17.0
|
7738 |
+
'@typescript-eslint/typescript-estree': 8.17.0([email protected])
|
7739 |
eslint: 9.16.0([email protected])
|
7740 |
optionalDependencies:
|
7741 |
typescript: 5.7.2
|
7742 |
transitivePeerDependencies:
|
7743 |
- supports-color
|
7744 |
|
7745 |
+
'@typescript-eslint/visitor-keys@8.17.0':
|
7746 |
dependencies:
|
7747 |
+
'@typescript-eslint/types': 8.17.0
|
7748 |
eslint-visitor-keys: 4.2.0
|
7749 |
|
7750 |
'@uiw/[email protected](@codemirror/[email protected])(@codemirror/[email protected])(@codemirror/[email protected])':
|
|
|
7763 |
|
7764 |
'@ungap/[email protected]': {}
|
7765 |
|
7766 |
+
'@unocss/[email protected]([email protected])([email protected](@types/[email protected])([email protected]))':
|
7767 |
dependencies:
|
7768 |
'@unocss/core': 0.61.9
|
7769 |
'@unocss/reset': 0.61.9
|
7770 |
+
'@unocss/vite': 0.61.9([email protected])([email protected](@types/[email protected])([email protected]))
|
7771 |
optionalDependencies:
|
7772 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
7773 |
transitivePeerDependencies:
|
7774 |
- rollup
|
7775 |
- supports-color
|
|
|
7906 |
dependencies:
|
7907 |
'@unocss/core': 0.61.9
|
7908 |
|
7909 |
+
'@unocss/[email protected]([email protected])([email protected](@types/[email protected])([email protected]))':
|
7910 |
dependencies:
|
7911 |
'@ampproject/remapping': 2.3.0
|
7912 |
'@rollup/pluginutils': 5.1.3([email protected])
|
|
|
7918 |
chokidar: 3.6.0
|
7919 |
fast-glob: 3.3.2
|
7920 |
magic-string: 0.30.14
|
7921 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
7922 |
transitivePeerDependencies:
|
7923 |
- rollup
|
7924 |
- supports-color
|
|
|
7946 |
transitivePeerDependencies:
|
7947 |
- babel-plugin-macros
|
7948 |
|
7949 |
+
'@vanilla-extract/[email protected](@types/[email protected])([email protected])':
|
7950 |
dependencies:
|
7951 |
'@babel/core': 7.26.0
|
7952 |
'@babel/plugin-syntax-typescript': 7.25.9(@babel/[email protected])
|
|
|
7959 |
lodash: 4.17.21
|
7960 |
mlly: 1.7.3
|
7961 |
outdent: 0.8.0
|
7962 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
7963 |
+
vite-node: 1.6.0(@types/[email protected])([email protected])
|
7964 |
transitivePeerDependencies:
|
7965 |
- '@types/node'
|
7966 |
- babel-plugin-macros
|
|
|
7975 |
|
7976 |
'@vanilla-extract/[email protected]': {}
|
7977 |
|
7978 |
+
'@vitest/[email protected].8':
|
7979 |
dependencies:
|
7980 |
+
'@vitest/spy': 2.1.8
|
7981 |
+
'@vitest/utils': 2.1.8
|
7982 |
chai: 5.1.2
|
7983 |
tinyrainbow: 1.2.0
|
7984 |
|
7985 |
+
'@vitest/[email protected].8([email protected](@types/[email protected])([email protected]))':
|
7986 |
dependencies:
|
7987 |
+
'@vitest/spy': 2.1.8
|
7988 |
estree-walker: 3.0.3
|
7989 |
magic-string: 0.30.14
|
7990 |
optionalDependencies:
|
7991 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
7992 |
|
7993 |
+
'@vitest/[email protected].8':
|
7994 |
dependencies:
|
7995 |
tinyrainbow: 1.2.0
|
7996 |
|
7997 |
+
'@vitest/[email protected].8':
|
7998 |
dependencies:
|
7999 |
+
'@vitest/utils': 2.1.8
|
8000 |
pathe: 1.1.2
|
8001 |
|
8002 |
+
'@vitest/[email protected].8':
|
8003 |
dependencies:
|
8004 |
+
'@vitest/pretty-format': 2.1.8
|
8005 |
magic-string: 0.30.14
|
8006 |
pathe: 1.1.2
|
8007 |
|
8008 |
+
'@vitest/[email protected].8':
|
8009 |
dependencies:
|
8010 |
tinyspy: 3.0.2
|
8011 |
|
8012 |
+
'@vitest/[email protected].8':
|
8013 |
dependencies:
|
8014 |
+
'@vitest/pretty-format': 2.1.8
|
8015 |
loupe: 3.1.2
|
8016 |
tinyrainbow: 1.2.0
|
8017 |
|
8018 |
+
'@vue/compiler-core@3.5.13':
|
8019 |
dependencies:
|
8020 |
'@babel/parser': 7.26.2
|
8021 |
+
'@vue/shared': 3.5.13
|
8022 |
entities: 4.5.0
|
8023 |
estree-walker: 2.0.2
|
8024 |
source-map-js: 1.2.1
|
8025 |
|
8026 |
+
'@vue/compiler-dom@3.5.13':
|
8027 |
dependencies:
|
8028 |
+
'@vue/compiler-core': 3.5.13
|
8029 |
+
'@vue/shared': 3.5.13
|
8030 |
|
8031 |
+
'@vue/compiler-sfc@3.5.13':
|
8032 |
dependencies:
|
8033 |
'@babel/parser': 7.26.2
|
8034 |
+
'@vue/compiler-core': 3.5.13
|
8035 |
+
'@vue/compiler-dom': 3.5.13
|
8036 |
+
'@vue/compiler-ssr': 3.5.13
|
8037 |
+
'@vue/shared': 3.5.13
|
8038 |
estree-walker: 2.0.2
|
8039 |
magic-string: 0.30.14
|
8040 |
postcss: 8.4.49
|
8041 |
source-map-js: 1.2.1
|
8042 |
|
8043 |
+
'@vue/compiler-ssr@3.5.13':
|
8044 |
dependencies:
|
8045 |
+
'@vue/compiler-dom': 3.5.13
|
8046 |
+
'@vue/shared': 3.5.13
|
8047 |
|
8048 |
+
'@vue/reactivity@3.5.13':
|
8049 |
dependencies:
|
8050 |
+
'@vue/shared': 3.5.13
|
8051 |
|
8052 |
+
'@vue/runtime-core@3.5.13':
|
8053 |
dependencies:
|
8054 |
+
'@vue/reactivity': 3.5.13
|
8055 |
+
'@vue/shared': 3.5.13
|
8056 |
|
8057 |
+
'@vue/runtime-dom@3.5.13':
|
8058 |
dependencies:
|
8059 |
+
'@vue/reactivity': 3.5.13
|
8060 |
+
'@vue/runtime-core': 3.5.13
|
8061 |
+
'@vue/shared': 3.5.13
|
8062 |
csstype: 3.1.3
|
8063 |
|
8064 |
+
'@vue/server-renderer@3.5.13(vue@3.5.13([email protected]))':
|
8065 |
dependencies:
|
8066 |
+
'@vue/compiler-ssr': 3.5.13
|
8067 |
+
'@vue/shared': 3.5.13
|
8068 |
+
vue: 3.5.13([email protected])
|
8069 |
|
8070 |
+
'@vue/shared@3.5.13': {}
|
8071 |
|
8072 |
'@web3-storage/[email protected]': {}
|
8073 |
|
|
|
8099 |
dependencies:
|
8100 |
acorn: 8.14.0
|
8101 |
|
8102 | |
8103 |
+
dependencies:
|
8104 |
+
acorn: 8.14.0
|
8105 |
+
|
8106 | |
8107 |
dependencies:
|
8108 |
acorn: 8.14.0
|
|
|
8114 |
clean-stack: 2.2.0
|
8115 |
indent-string: 4.0.0
|
8116 |
|
8117 |
+
[email protected]([email protected])([email protected](svelte@5.4.0))(svelte@5.4.0)(vue@3.5.13([email protected]))([email protected]):
|
8118 |
dependencies:
|
8119 |
'@ai-sdk/provider': 0.0.26
|
8120 |
'@ai-sdk/provider-utils': 1.0.22([email protected])
|
8121 |
'@ai-sdk/react': 0.0.70([email protected])([email protected])
|
8122 |
'@ai-sdk/solid': 0.0.54([email protected])
|
8123 |
+
'@ai-sdk/svelte': 0.0.57(svelte@5.4.0)([email protected])
|
8124 |
'@ai-sdk/ui-utils': 0.0.50([email protected])
|
8125 |
+
'@ai-sdk/vue': 0.0.59(vue@3.5.13([email protected]))([email protected])
|
8126 |
'@opentelemetry/api': 1.9.0
|
8127 |
eventsource-parser: 1.1.2
|
8128 |
json-schema: 0.4.0
|
|
|
8131 |
zod-to-json-schema: 3.23.5([email protected])
|
8132 |
optionalDependencies:
|
8133 |
react: 18.3.1
|
8134 |
+
sswr: 2.1.0(svelte@5.4.0)
|
8135 |
+
svelte: 5.4.0
|
8136 |
zod: 3.23.8
|
8137 |
transitivePeerDependencies:
|
8138 |
- solid-js
|
|
|
8194 |
|
8195 | |
8196 |
|
8197 |
+
[email protected]: {}
|
8198 |
+
|
8199 | |
8200 |
dependencies:
|
8201 |
possible-typed-array-names: 1.0.0
|
|
|
8316 | |
8317 |
dependencies:
|
8318 |
caniuse-lite: 1.0.30001685
|
8319 |
+
electron-to-chromium: 1.5.68
|
8320 |
node-releases: 2.0.18
|
8321 |
update-browserslist-db: 1.1.1([email protected])
|
8322 |
|
|
|
8430 |
inherits: 2.0.4
|
8431 |
safe-buffer: 5.2.1
|
8432 |
|
8433 |
+
[email protected]: {}
|
8434 |
+
|
8435 | |
8436 |
|
8437 | |
|
|
8446 |
|
8447 | |
8448 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8449 | |
8450 |
dependencies:
|
8451 |
color-name: 1.1.4
|
|
|
8490 |
|
8491 | |
8492 |
|
8493 |
+
[email protected]: {}
|
8494 |
+
|
8495 | |
8496 |
dependencies:
|
8497 |
bn.js: 4.12.1
|
|
|
8572 |
dependencies:
|
8573 |
character-entities: 2.0.2
|
8574 |
|
8575 | |
8576 |
+
dependencies:
|
8577 |
+
mimic-response: 3.1.0
|
8578 |
+
|
8579 | |
8580 |
|
8581 | |
|
|
8625 |
|
8626 | |
8627 |
|
8628 |
+
[email protected]: {}
|
8629 |
+
|
8630 | |
8631 |
|
8632 | |
|
|
8656 |
|
8657 | |
8658 |
|
8659 |
+
[email protected].68: {}
|
8660 |
|
8661 | |
8662 |
dependencies:
|
|
|
8699 |
'@jspm/core': 2.0.1
|
8700 |
esbuild: 0.17.6
|
8701 |
local-pkg: 0.5.1
|
8702 |
+
resolve.exports: 2.0.3
|
8703 |
|
8704 | |
8705 |
optionalDependencies:
|
|
|
8901 |
transitivePeerDependencies:
|
8902 |
- supports-color
|
8903 |
|
8904 |
+
[email protected]: {}
|
8905 |
+
|
8906 | |
8907 |
dependencies:
|
8908 |
acorn: 8.14.0
|
|
|
8919 |
dependencies:
|
8920 |
estraverse: 5.3.0
|
8921 |
|
8922 | |
8923 |
+
dependencies:
|
8924 |
+
'@jridgewell/sourcemap-codec': 1.5.0
|
8925 |
+
'@types/estree': 1.0.6
|
8926 |
+
|
8927 | |
8928 |
dependencies:
|
8929 |
estraverse: 5.3.0
|
|
|
9166 |
es-errors: 1.3.0
|
9167 |
function-bind: 1.1.2
|
9168 |
has-proto: 1.1.0
|
9169 |
+
has-symbols: 1.1.0
|
9170 |
hasown: 2.0.2
|
9171 |
|
9172 | |
|
|
9242 |
dependencies:
|
9243 |
call-bind: 1.0.7
|
9244 |
|
9245 |
+
has-symbols@1.1.0: {}
|
9246 |
|
9247 | |
9248 |
dependencies:
|
9249 |
+
has-symbols: 1.1.0
|
9250 |
|
9251 | |
9252 |
dependencies:
|
|
|
9421 |
|
9422 | |
9423 |
|
|
|
|
|
|
|
9424 | |
9425 |
|
9426 | |
|
|
9535 |
|
9536 | |
9537 |
|
9538 | |
9539 |
+
dependencies:
|
9540 |
+
async-lock: 1.4.1
|
9541 |
+
clean-git-ref: 2.0.1
|
9542 |
+
crc-32: 1.2.2
|
9543 |
+
diff3: 0.0.3
|
9544 |
+
ignore: 5.3.2
|
9545 |
+
minimisted: 2.0.1
|
9546 |
+
pako: 1.0.11
|
9547 |
+
path-browserify: 1.0.1
|
9548 |
+
pify: 4.0.1
|
9549 |
+
readable-stream: 3.6.2
|
9550 |
+
sha.js: 2.4.11
|
9551 |
+
simple-get: 4.0.1
|
9552 |
+
|
9553 | |
9554 |
|
9555 | |
|
|
10407 |
|
10408 | |
10409 |
|
10410 |
+
[email protected]: {}
|
10411 |
+
|
10412 | |
10413 |
dependencies:
|
10414 |
'@cspotcode/source-map-support': 0.8.1
|
|
|
10442 |
|
10443 | |
10444 |
|
10445 | |
10446 |
+
dependencies:
|
10447 |
+
minimist: 1.2.8
|
10448 |
+
|
10449 | |
10450 |
dependencies:
|
10451 |
minipass: 3.3.6
|
|
|
10596 |
dependencies:
|
10597 |
call-bind: 1.0.7
|
10598 |
define-properties: 1.2.1
|
10599 |
+
has-symbols: 1.1.0
|
10600 |
object-keys: 1.1.1
|
10601 |
|
10602 | |
|
|
10763 |
|
10764 | |
10765 |
|
10766 |
+
[email protected]: {}
|
10767 |
+
|
10768 | |
10769 |
dependencies:
|
10770 |
find-up: 5.0.0
|
|
|
11140 |
|
11141 |
[email protected](@remix-run/[email protected](@cloudflare/[email protected])([email protected]))(@remix-run/[email protected]([email protected]))(@remix-run/[email protected]([email protected]([email protected]))([email protected])([email protected]))(@remix-run/[email protected])([email protected])([email protected]):
|
11142 |
dependencies:
|
11143 |
+
type-fest: 4.30.0
|
11144 |
optionalDependencies:
|
11145 |
'@remix-run/cloudflare': 2.15.0(@cloudflare/[email protected])([email protected])
|
11146 |
'@remix-run/node': 2.15.0([email protected])
|
|
|
11155 |
|
11156 | |
11157 |
|
11158 |
+
[email protected].3: {}
|
11159 |
|
11160 | |
11161 |
dependencies:
|
|
|
11325 |
sass-embedded-win32-ia32: 1.81.0
|
11326 |
sass-embedded-win32-x64: 1.81.0
|
11327 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11328 | |
11329 |
dependencies:
|
11330 |
loose-envify: 1.4.0
|
|
|
11415 |
|
11416 | |
11417 |
|
11418 |
+
[email protected]: {}
|
11419 |
+
|
11420 | |
11421 |
+
dependencies:
|
11422 |
+
decompress-response: 6.0.0
|
11423 |
+
once: 1.4.0
|
11424 |
+
simple-concat: 1.0.1
|
11425 |
+
|
11426 | |
11427 |
dependencies:
|
11428 |
'@polka/url': 1.0.0-next.28
|
|
|
11462 |
dependencies:
|
11463 |
minipass: 7.1.2
|
11464 |
|
11465 |
+
[email protected](svelte@5.4.0):
|
11466 |
dependencies:
|
11467 |
+
svelte: 5.4.0
|
11468 |
swrev: 4.0.0
|
11469 |
|
11470 | |
|
|
11557 |
|
11558 | |
11559 |
|
11560 |
+
svelte@5.4.0:
|
11561 |
dependencies:
|
11562 |
'@ampproject/remapping': 2.3.0
|
11563 |
'@jridgewell/sourcemap-codec': 1.5.0
|
|
|
11564 |
'@types/estree': 1.0.6
|
11565 |
acorn: 8.14.0
|
11566 |
+
acorn-typescript: 1.4.13([email protected])
|
11567 |
aria-query: 5.3.2
|
11568 |
axobject-query: 4.1.0
|
11569 |
+
esm-env: 1.2.1
|
11570 |
+
esrap: 1.2.3
|
|
|
11571 |
is-reference: 3.0.3
|
11572 |
locate-character: 3.0.0
|
11573 |
magic-string: 0.30.14
|
11574 |
+
zimmerframe: 1.1.2
|
11575 |
|
11576 | |
11577 |
dependencies:
|
|
|
11581 |
|
11582 | |
11583 |
|
11584 |
+
[email protected](vue@3.5.13([email protected])):
|
11585 |
dependencies:
|
11586 |
+
vue: 3.5.13([email protected])
|
11587 |
|
11588 | |
11589 |
dependencies:
|
|
|
11694 |
dependencies:
|
11695 |
prelude-ls: 1.2.1
|
11696 |
|
11697 |
+
type-fest@4.30.0: {}
|
11698 |
|
11699 | |
11700 |
dependencies:
|
11701 |
media-typer: 0.3.0
|
11702 |
mime-types: 2.1.35
|
11703 |
|
11704 |
+
typescript-eslint@8.17.0([email protected]([email protected]))([email protected]):
|
11705 |
dependencies:
|
11706 |
+
'@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected])
|
11707 |
+
'@typescript-eslint/parser': 8.17.0([email protected]([email protected]))([email protected])
|
11708 |
+
'@typescript-eslint/utils': 8.17.0([email protected]([email protected]))([email protected])
|
11709 |
eslint: 9.16.0([email protected])
|
11710 |
optionalDependencies:
|
11711 |
typescript: 5.7.2
|
|
|
11828 |
|
11829 | |
11830 |
|
11831 | |
11832 |
dependencies:
|
11833 |
+
'@unocss/astro': 0.61.9([email protected])([email protected](@types/[email protected])([email protected]))
|
11834 |
'@unocss/cli': 0.61.9([email protected])
|
11835 |
'@unocss/core': 0.61.9
|
11836 |
'@unocss/extractor-arbitrary-variants': 0.61.9
|
|
|
11849 |
'@unocss/transformer-compile-class': 0.61.9
|
11850 |
'@unocss/transformer-directives': 0.61.9
|
11851 |
'@unocss/transformer-variant-group': 0.61.9
|
11852 |
+
'@unocss/vite': 0.61.9([email protected])([email protected](@types/[email protected])([email protected]))
|
11853 |
optionalDependencies:
|
11854 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
11855 |
transitivePeerDependencies:
|
11856 |
- postcss
|
11857 |
- rollup
|
|
|
11956 |
'@types/unist': 3.0.3
|
11957 |
vfile-message: 4.0.2
|
11958 |
|
11959 |
+
[email protected](@types/[email protected])([email protected]):
|
11960 |
dependencies:
|
11961 |
cac: 6.7.14
|
11962 |
debug: 4.3.7
|
11963 |
pathe: 1.1.2
|
11964 |
picocolors: 1.1.1
|
11965 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
11966 |
transitivePeerDependencies:
|
11967 |
- '@types/node'
|
11968 |
- less
|
|
|
11974 |
- supports-color
|
11975 |
- terser
|
11976 |
|
11977 |
+
[email protected].8(@types/[email protected])([email protected]):
|
11978 |
dependencies:
|
11979 |
cac: 6.7.14
|
11980 |
debug: 4.3.7
|
11981 |
es-module-lexer: 1.5.4
|
11982 |
pathe: 1.1.2
|
11983 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
11984 |
transitivePeerDependencies:
|
11985 |
- '@types/node'
|
11986 |
- less
|
|
|
11992 |
- supports-color
|
11993 |
- terser
|
11994 |
|
11995 | |
11996 |
dependencies:
|
11997 |
'@rollup/plugin-inject': 5.0.5([email protected])
|
11998 |
node-stdlib-browser: 1.3.0
|
11999 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
12000 |
transitivePeerDependencies:
|
12001 |
- rollup
|
12002 |
|
12003 | |
12004 |
dependencies:
|
12005 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
12006 |
|
12007 | |
12008 |
dependencies:
|
12009 |
debug: 4.3.7
|
12010 |
globrex: 0.1.2
|
12011 |
tsconfck: 3.1.4([email protected])
|
12012 |
optionalDependencies:
|
12013 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
12014 |
transitivePeerDependencies:
|
12015 |
- supports-color
|
12016 |
- typescript
|
12017 |
|
12018 |
+
[email protected](@types/[email protected])([email protected]):
|
12019 |
dependencies:
|
12020 |
esbuild: 0.21.5
|
12021 |
postcss: 8.4.49
|
|
|
12023 |
optionalDependencies:
|
12024 |
'@types/node': 22.10.1
|
12025 |
fsevents: 2.3.3
|
|
|
12026 |
sass-embedded: 1.81.0
|
12027 |
|
12028 |
+
[email protected].8(@types/[email protected])([email protected]):
|
12029 |
dependencies:
|
12030 |
+
'@vitest/expect': 2.1.8
|
12031 |
+
'@vitest/mocker': 2.1.8([email protected](@types/[email protected])([email protected]))
|
12032 |
+
'@vitest/pretty-format': 2.1.8
|
12033 |
+
'@vitest/runner': 2.1.8
|
12034 |
+
'@vitest/snapshot': 2.1.8
|
12035 |
+
'@vitest/spy': 2.1.8
|
12036 |
+
'@vitest/utils': 2.1.8
|
12037 |
chai: 5.1.2
|
12038 |
debug: 4.3.7
|
12039 |
expect-type: 1.1.0
|
|
|
12044 |
tinyexec: 0.3.1
|
12045 |
tinypool: 1.0.2
|
12046 |
tinyrainbow: 1.2.0
|
12047 |
+
vite: 5.4.11(@types/[email protected])([email protected])
|
12048 |
+
vite-node: 2.1.8(@types/[email protected])([email protected])
|
12049 |
why-is-node-running: 2.3.0
|
12050 |
optionalDependencies:
|
12051 |
'@types/node': 22.10.1
|
|
|
12062 |
|
12063 | |
12064 |
|
12065 |
+
vue@3.5.13([email protected]):
|
12066 |
dependencies:
|
12067 |
+
'@vue/compiler-dom': 3.5.13
|
12068 |
+
'@vue/compiler-sfc': 3.5.13
|
12069 |
+
'@vue/runtime-dom': 3.5.13
|
12070 |
+
'@vue/server-renderer': 3.5.13(vue@3.5.13([email protected]))
|
12071 |
+
'@vue/shared': 3.5.13
|
12072 |
optionalDependencies:
|
12073 |
typescript: 5.7.2
|
12074 |
|
|
|
12134 |
nanoid: 3.3.8
|
12135 |
path-to-regexp: 6.3.0
|
12136 |
resolve: 1.22.8
|
12137 |
+
resolve.exports: 2.0.3
|
12138 |
selfsigned: 2.4.1
|
12139 |
source-map: 0.6.1
|
12140 |
unenv: [email protected]
|
|
|
12184 |
mustache: 4.2.0
|
12185 |
stacktracey: 2.1.8
|
12186 |
|
12187 |
+
[email protected]: {}
|
12188 |
+
|
12189 | |
12190 |
dependencies:
|
12191 |
zod: 3.23.8
|
public/favicon.svg
CHANGED
|
|
public/logo-dark-styled.png
ADDED
![]() |
public/logo-dark.png
ADDED
![]() |
public/logo-light-styled.png
ADDED
![]() |
public/logo-light.png
ADDED
![]() |
public/logo.svg
CHANGED
|
|
public/social_preview_index.jpg
CHANGED
![]() |
![]() |
uno.config.ts
CHANGED
@@ -35,17 +35,17 @@ const BASE_COLORS = {
|
|
35 |
950: '#0A0A0A',
|
36 |
},
|
37 |
accent: {
|
38 |
-
50: '#
|
39 |
-
100: '#
|
40 |
-
200: '#
|
41 |
-
300: '#
|
42 |
-
400: '#
|
43 |
-
500: '#
|
44 |
-
600: '#
|
45 |
-
700: '#
|
46 |
-
800: '#
|
47 |
-
900: '#
|
48 |
-
950: '#
|
49 |
},
|
50 |
green: {
|
51 |
50: '#F0FDF4',
|
|
|
35 |
950: '#0A0A0A',
|
36 |
},
|
37 |
accent: {
|
38 |
+
50: '#F8F5FF',
|
39 |
+
100: '#F0EBFF',
|
40 |
+
200: '#E1D6FF',
|
41 |
+
300: '#CEBEFF',
|
42 |
+
400: '#B69EFF',
|
43 |
+
500: '#9C7DFF',
|
44 |
+
600: '#8A5FFF',
|
45 |
+
700: '#7645E8',
|
46 |
+
800: '#6234BB',
|
47 |
+
900: '#502D93',
|
48 |
+
950: '#2D1959',
|
49 |
},
|
50 |
green: {
|
51 |
50: '#F0FDF4',
|