Stijnus commited on
Commit
58d3853
·
unverified ·
2 Parent(s): 0db9ce2 68bbbd0

Merge branch 'main' into FEAT_BoltDYI_NEW_SETTINGS_UI_V2

Browse files
app/components/chat/GitCloneButton.tsx CHANGED
@@ -1,11 +1,12 @@
1
  import ignore from 'ignore';
2
  import { useGit } from '~/lib/hooks/useGit';
3
  import type { Message } from 'ai';
4
- import { detectProjectCommands, createCommandsMessage } from '~/utils/projectCommands';
5
  import { generateId } from '~/utils/fileUtils';
6
  import { useState } from 'react';
7
  import { toast } from 'react-toastify';
8
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
 
9
 
10
  const IGNORE_PATTERNS = [
11
  'node_modules/**',
@@ -35,7 +36,7 @@ const ig = ignore().add(IGNORE_PATTERNS);
35
 
36
  interface GitCloneButtonProps {
37
  className?: string;
38
- importChat?: (description: string, messages: Message[]) => Promise<void>;
39
  }
40
 
41
  export default function GitCloneButton({ importChat }: GitCloneButtonProps) {
@@ -83,7 +84,7 @@ ${fileContents
83
  .map(
84
  (file) =>
85
  `<boltAction type="file" filePath="${file.path}">
86
- ${file.content}
87
  </boltAction>`,
88
  )
89
  .join('\n')}
@@ -98,7 +99,7 @@ ${file.content}
98
  messages.push(commandsMessage);
99
  }
100
 
101
- await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages);
102
  }
103
  } catch (error) {
104
  console.error('Error during import:', error);
 
1
  import ignore from 'ignore';
2
  import { useGit } from '~/lib/hooks/useGit';
3
  import type { Message } from 'ai';
4
+ import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from '~/utils/projectCommands';
5
  import { generateId } from '~/utils/fileUtils';
6
  import { useState } from 'react';
7
  import { toast } from 'react-toastify';
8
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
9
+ import type { IChatMetadata } from '~/lib/persistence';
10
 
11
  const IGNORE_PATTERNS = [
12
  'node_modules/**',
 
36
 
37
  interface GitCloneButtonProps {
38
  className?: string;
39
+ importChat?: (description: string, messages: Message[], metadata?: IChatMetadata) => Promise<void>;
40
  }
41
 
42
  export default function GitCloneButton({ importChat }: GitCloneButtonProps) {
 
84
  .map(
85
  (file) =>
86
  `<boltAction type="file" filePath="${file.path}">
87
+ ${escapeBoltTags(file.content)}
88
  </boltAction>`,
89
  )
90
  .join('\n')}
 
99
  messages.push(commandsMessage);
100
  }
101
 
102
+ await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages, { gitUrl: repoUrl });
103
  }
104
  } catch (error) {
105
  console.error('Error during import:', error);
app/components/chat/Markdown.tsx CHANGED
@@ -7,6 +7,7 @@ import { Artifact } from './Artifact';
7
  import { CodeBlock } from './CodeBlock';
8
 
9
  import styles from './Markdown.module.scss';
 
10
 
11
  const logger = createScopedLogger('MarkdownComponent');
12
 
@@ -22,6 +23,8 @@ export const Markdown = memo(({ children, html = false, limitedMarkdown = false
22
  const components = useMemo(() => {
23
  return {
24
  div: ({ className, children, node, ...props }) => {
 
 
25
  if (className?.includes('__boltArtifact__')) {
26
  const messageId = node?.properties.dataMessageId as string;
27
 
@@ -32,6 +35,10 @@ export const Markdown = memo(({ children, html = false, limitedMarkdown = false
32
  return <Artifact messageId={messageId} />;
33
  }
34
 
 
 
 
 
35
  return (
36
  <div className={className} {...props}>
37
  {children}
 
7
  import { CodeBlock } from './CodeBlock';
8
 
9
  import styles from './Markdown.module.scss';
10
+ import ThoughtBox from './ThoughtBox';
11
 
12
  const logger = createScopedLogger('MarkdownComponent');
13
 
 
23
  const components = useMemo(() => {
24
  return {
25
  div: ({ className, children, node, ...props }) => {
26
+ console.log(className, node);
27
+
28
  if (className?.includes('__boltArtifact__')) {
29
  const messageId = node?.properties.dataMessageId as string;
30
 
 
35
  return <Artifact messageId={messageId} />;
36
  }
37
 
38
+ if (className?.includes('__boltThought__')) {
39
+ return <ThoughtBox title="Thought process">{children}</ThoughtBox>;
40
+ }
41
+
42
  return (
43
  <div className={className} {...props}>
44
  {children}
app/components/chat/ThoughtBox.tsx ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState, type PropsWithChildren } from 'react';
2
+
3
+ const ThoughtBox = ({ title, children }: PropsWithChildren<{ title: string }>) => {
4
+ const [isExpanded, setIsExpanded] = useState(false);
5
+
6
+ return (
7
+ <div
8
+ onClick={() => setIsExpanded(!isExpanded)}
9
+ className={`
10
+ bg-bolt-elements-background-depth-2
11
+ shadow-md
12
+ rounded-lg
13
+ cursor-pointer
14
+ transition-all
15
+ duration-300
16
+ ${isExpanded ? 'max-h-96' : 'max-h-13'}
17
+ overflow-auto
18
+ border border-bolt-elements-borderColor
19
+ `}
20
+ >
21
+ <div className="p-4 flex items-center gap-4 rounded-lg text-bolt-elements-textSecondary font-medium leading-5 text-sm border border-bolt-elements-borderColor">
22
+ <div className="i-ph:brain-thin text-2xl" />
23
+ <div className="div">
24
+ <span> {title}</span>{' '}
25
+ {!isExpanded && <span className="text-bolt-elements-textTertiary"> - Click to expand</span>}
26
+ </div>
27
+ </div>
28
+ <div
29
+ className={`
30
+ transition-opacity
31
+ duration-300
32
+ p-4
33
+ rounded-lg
34
+ ${isExpanded ? 'opacity-100' : 'opacity-0'}
35
+ `}
36
+ >
37
+ {children}
38
+ </div>
39
+ </div>
40
+ );
41
+ };
42
+
43
+ export default ThoughtBox;
app/components/git/GitUrlImport.client.tsx CHANGED
@@ -7,7 +7,7 @@ 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
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
12
  import { toast } from 'react-toastify';
13
 
@@ -74,12 +74,12 @@ export function GitUrlImport() {
74
  const filesMessage: Message = {
75
  role: 'assistant',
76
  content: `Cloning the repo ${repoUrl} into ${workdir}
77
- <boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
78
  ${fileContents
79
  .map(
80
  (file) =>
81
  `<boltAction type="file" filePath="${file.path}">
82
- ${file.content}
83
  </boltAction>`,
84
  )
85
  .join('\n')}
@@ -94,7 +94,7 @@ ${file.content}
94
  messages.push(commandsMessage);
95
  }
96
 
97
- await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages);
98
  }
99
  } catch (error) {
100
  console.error('Error during import:', error);
 
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, escapeBoltTags } from '~/utils/projectCommands';
11
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
12
  import { toast } from 'react-toastify';
13
 
 
74
  const filesMessage: Message = {
75
  role: 'assistant',
76
  content: `Cloning the repo ${repoUrl} into ${workdir}
77
+ <boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
78
  ${fileContents
79
  .map(
80
  (file) =>
81
  `<boltAction type="file" filePath="${file.path}">
82
+ ${escapeBoltTags(file.content)}
83
  </boltAction>`,
84
  )
85
  .join('\n')}
 
94
  messages.push(commandsMessage);
95
  }
96
 
97
+ await importChat(`Git Project:${repoUrl.split('/').slice(-1)[0]}`, messages, { gitUrl: repoUrl });
98
  }
99
  } catch (error) {
100
  console.error('Error during import:', error);
app/components/workbench/Workbench.client.tsx CHANGED
@@ -18,6 +18,7 @@ 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;
@@ -66,6 +67,8 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
66
  const unsavedFiles = useStore(workbenchStore.unsavedFiles);
67
  const files = useStore(workbenchStore.files);
68
  const selectedView = useStore(workbenchStore.currentView);
 
 
69
 
70
  const isSmallViewport = useViewport(1024);
71
 
@@ -171,18 +174,28 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
171
  <PanelHeaderButton
172
  className="mr-1 text-sm"
173
  onClick={() => {
174
- const repoName = prompt(
175
- 'Please enter a name for your new GitHub repository:',
176
- 'bolt-generated-project',
177
- );
 
 
 
 
 
 
 
 
 
 
178
 
179
  if (!repoName) {
180
  alert('Repository name is required. Push to GitHub cancelled.');
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:');
@@ -193,9 +206,26 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
193
  return;
194
  }
195
 
196
- workbenchStore.pushToGitHub(repoName, usernameInput, tokenInput);
197
- } else {
198
- workbenchStore.pushToGitHub(repoName, githubUsername, githubToken);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
200
  }}
201
  >
 
18
  import { Preview } from './Preview';
19
  import useViewport from '~/lib/hooks';
20
  import Cookies from 'js-cookie';
21
+ import { chatMetadata, useChatHistory } from '~/lib/persistence';
22
 
23
  interface WorkspaceProps {
24
  chatStarted?: boolean;
 
67
  const unsavedFiles = useStore(workbenchStore.unsavedFiles);
68
  const files = useStore(workbenchStore.files);
69
  const selectedView = useStore(workbenchStore.currentView);
70
+ const metadata = useStore(chatMetadata);
71
+ const { updateChatMestaData } = useChatHistory();
72
 
73
  const isSmallViewport = useViewport(1024);
74
 
 
174
  <PanelHeaderButton
175
  className="mr-1 text-sm"
176
  onClick={() => {
177
+ let repoName = metadata?.gitUrl?.split('/').slice(-1)[0]?.replace('.git', '') || null;
178
+ let repoConfirmed: boolean = true;
179
+
180
+ if (repoName) {
181
+ repoConfirmed = confirm(`Do you want to push to the repository ${repoName}?`);
182
+ }
183
+
184
+ if (!repoName || !repoConfirmed) {
185
+ repoName = prompt(
186
+ 'Please enter a name for your new GitHub repository:',
187
+ 'bolt-generated-project',
188
+ );
189
+ } else {
190
+ }
191
 
192
  if (!repoName) {
193
  alert('Repository name is required. Push to GitHub cancelled.');
194
  return;
195
  }
196
 
197
+ let githubUsername = Cookies.get('githubUsername');
198
+ let githubToken = Cookies.get('githubToken');
199
 
200
  if (!githubUsername || !githubToken) {
201
  const usernameInput = prompt('Please enter your GitHub username:');
 
206
  return;
207
  }
208
 
209
+ githubUsername = usernameInput;
210
+ githubToken = tokenInput;
211
+
212
+ Cookies.set('githubUsername', usernameInput);
213
+ Cookies.set('githubToken', tokenInput);
214
+ Cookies.set(
215
+ 'git:github.com',
216
+ JSON.stringify({ username: tokenInput, password: 'x-oauth-basic' }),
217
+ );
218
+ }
219
+
220
+ const commitMessage =
221
+ prompt('Please enter a commit message:', 'Initial commit') || 'Initial commit';
222
+ workbenchStore.pushToGitHub(repoName, commitMessage, githubUsername, githubToken);
223
+
224
+ if (!metadata?.gitUrl) {
225
+ updateChatMestaData({
226
+ ...(metadata || {}),
227
+ gitUrl: `https://github.com/${githubUsername}/${repoName}.git`,
228
+ });
229
  }
230
  }}
231
  >
app/lib/hooks/useGit.ts CHANGED
@@ -92,6 +92,7 @@ export function useGit() {
92
  },
93
  onAuthFailure: (url, _auth) => {
94
  toast.error(`Error Authenticating with ${url.split('/')[2]}`);
 
95
  },
96
  onAuthSuccess: (url, auth) => {
97
  saveGitAuth(url, auth);
@@ -107,6 +108,8 @@ export function useGit() {
107
  return { workdir: webcontainer.workdir, data };
108
  } catch (error) {
109
  console.error('Git clone error:', error);
 
 
110
  throw error;
111
  }
112
  },
 
92
  },
93
  onAuthFailure: (url, _auth) => {
94
  toast.error(`Error Authenticating with ${url.split('/')[2]}`);
95
+ throw `Error Authenticating with ${url.split('/')[2]}`;
96
  },
97
  onAuthSuccess: (url, auth) => {
98
  saveGitAuth(url, auth);
 
108
  return { workdir: webcontainer.workdir, data };
109
  } catch (error) {
110
  console.error('Git clone error:', error);
111
+
112
+ // toast.error(`Git clone error ${(error as any).message||""}`);
113
  throw error;
114
  }
115
  },
app/lib/modules/llm/providers/deepseek.ts CHANGED
@@ -2,7 +2,7 @@ import { BaseProvider } from '~/lib/modules/llm/base-provider';
2
  import type { ModelInfo } from '~/lib/modules/llm/types';
3
  import type { IProviderSetting } from '~/types/model';
4
  import type { LanguageModelV1 } from 'ai';
5
- import { createOpenAI } from '@ai-sdk/openai';
6
 
7
  export default class DeepseekProvider extends BaseProvider {
8
  name = 'Deepseek';
@@ -38,11 +38,12 @@ export default class DeepseekProvider extends BaseProvider {
38
  throw new Error(`Missing API key for ${this.name} provider`);
39
  }
40
 
41
- const openai = createOpenAI({
42
- baseURL: 'https://api.deepseek.com/beta',
43
  apiKey,
44
  });
45
 
46
- return openai(model);
 
 
47
  }
48
  }
 
2
  import type { ModelInfo } from '~/lib/modules/llm/types';
3
  import type { IProviderSetting } from '~/types/model';
4
  import type { LanguageModelV1 } from 'ai';
5
+ import { createDeepSeek } from '@ai-sdk/deepseek';
6
 
7
  export default class DeepseekProvider extends BaseProvider {
8
  name = 'Deepseek';
 
38
  throw new Error(`Missing API key for ${this.name} provider`);
39
  }
40
 
41
+ const deepseek = createDeepSeek({
 
42
  apiKey,
43
  });
44
 
45
+ return deepseek(model, {
46
+ // simulateStreaming: true,
47
+ });
48
  }
49
  }
app/lib/modules/llm/providers/groq.ts CHANGED
@@ -19,6 +19,7 @@ export default class GroqProvider extends BaseProvider {
19
  { name: 'llama-3.2-3b-preview', label: 'Llama 3.2 3b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
20
  { name: 'llama-3.2-1b-preview', label: 'Llama 3.2 1b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
21
  { name: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
 
22
  ];
23
 
24
  getModelInstance(options: {
 
19
  { name: 'llama-3.2-3b-preview', label: 'Llama 3.2 3b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
20
  { name: 'llama-3.2-1b-preview', label: 'Llama 3.2 1b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
21
  { name: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70b (Groq)', provider: 'Groq', maxTokenAllowed: 8000 },
22
+ { name: 'deepseek-r1-distill-llama-70b', label: 'Deepseek R1 Distill Llama 70b (Groq)', provider: 'Groq', maxTokenAllowed: 131072 },
23
  ];
24
 
25
  getModelInstance(options: {
app/lib/modules/llm/providers/lmstudio.ts CHANGED
@@ -40,7 +40,7 @@ export default class LMStudioProvider extends BaseProvider {
40
  * Running in Server
41
  * Backend: Check if we're running in Docker
42
  */
43
- const isDocker = process.env.RUNNING_IN_DOCKER === 'true';
44
 
45
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
46
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
@@ -58,7 +58,7 @@ export default class LMStudioProvider extends BaseProvider {
58
  }
59
  getModelInstance: (options: {
60
  model: string;
61
- serverEnv: Env;
62
  apiKeys?: Record<string, string>;
63
  providerSettings?: Record<string, IProviderSetting>;
64
  }) => LanguageModelV1 = (options) => {
@@ -75,8 +75,9 @@ export default class LMStudioProvider extends BaseProvider {
75
  throw new Error('No baseUrl found for LMStudio provider');
76
  }
77
 
 
 
78
  if (typeof window === 'undefined') {
79
- const isDocker = process.env.RUNNING_IN_DOCKER === 'true';
80
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
81
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
82
  }
@@ -84,7 +85,7 @@ export default class LMStudioProvider extends BaseProvider {
84
  logger.debug('LMStudio Base Url used: ', baseUrl);
85
 
86
  const lmstudio = createOpenAI({
87
- baseUrl: `${baseUrl}/v1`,
88
  apiKey: '',
89
  });
90
 
 
40
  * Running in Server
41
  * Backend: Check if we're running in Docker
42
  */
43
+ const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
44
 
45
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
46
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
 
58
  }
59
  getModelInstance: (options: {
60
  model: string;
61
+ serverEnv?: Env;
62
  apiKeys?: Record<string, string>;
63
  providerSettings?: Record<string, IProviderSetting>;
64
  }) => LanguageModelV1 = (options) => {
 
75
  throw new Error('No baseUrl found for LMStudio provider');
76
  }
77
 
78
+ const isDocker = process.env.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
79
+
80
  if (typeof window === 'undefined') {
 
81
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
82
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
83
  }
 
85
  logger.debug('LMStudio Base Url used: ', baseUrl);
86
 
87
  const lmstudio = createOpenAI({
88
+ baseURL: `${baseUrl}/v1`,
89
  apiKey: '',
90
  });
91
 
app/lib/modules/llm/providers/ollama.ts CHANGED
@@ -63,7 +63,7 @@ export default class OllamaProvider extends BaseProvider {
63
  * Running in Server
64
  * Backend: Check if we're running in Docker
65
  */
66
- const isDocker = process.env.RUNNING_IN_DOCKER === 'true';
67
 
68
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
69
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
@@ -83,7 +83,7 @@ export default class OllamaProvider extends BaseProvider {
83
  }
84
  getModelInstance: (options: {
85
  model: string;
86
- serverEnv: Env;
87
  apiKeys?: Record<string, string>;
88
  providerSettings?: Record<string, IProviderSetting>;
89
  }) => LanguageModelV1 = (options) => {
@@ -101,7 +101,7 @@ export default class OllamaProvider extends BaseProvider {
101
  throw new Error('No baseUrl found for OLLAMA provider');
102
  }
103
 
104
- const isDocker = process.env.RUNNING_IN_DOCKER === 'true';
105
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
106
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
107
 
 
63
  * Running in Server
64
  * Backend: Check if we're running in Docker
65
  */
66
+ const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
67
 
68
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
69
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
 
83
  }
84
  getModelInstance: (options: {
85
  model: string;
86
+ serverEnv?: Env;
87
  apiKeys?: Record<string, string>;
88
  providerSettings?: Record<string, IProviderSetting>;
89
  }) => LanguageModelV1 = (options) => {
 
101
  throw new Error('No baseUrl found for OLLAMA provider');
102
  }
103
 
104
+ const isDocker = process?.env?.RUNNING_IN_DOCKER === 'true' || serverEnv?.RUNNING_IN_DOCKER === 'true';
105
  baseUrl = isDocker ? baseUrl.replace('localhost', 'host.docker.internal') : baseUrl;
106
  baseUrl = isDocker ? baseUrl.replace('127.0.0.1', 'host.docker.internal') : baseUrl;
107
 
app/lib/persistence/db.ts CHANGED
@@ -2,6 +2,11 @@ import type { Message } from 'ai';
2
  import { createScopedLogger } from '~/utils/logger';
3
  import type { ChatHistoryItem } from './useChatHistory';
4
 
 
 
 
 
 
5
  const logger = createScopedLogger('ChatHistory');
6
 
7
  // this is used at the top level and never rejects
@@ -53,6 +58,7 @@ export async function setMessages(
53
  urlId?: string,
54
  description?: string,
55
  timestamp?: string,
 
56
  ): Promise<void> {
57
  return new Promise((resolve, reject) => {
58
  const transaction = db.transaction('chats', 'readwrite');
@@ -69,6 +75,7 @@ export async function setMessages(
69
  urlId,
70
  description,
71
  timestamp: timestamp ?? new Date().toISOString(),
 
72
  });
73
 
74
  request.onsuccess = () => resolve();
@@ -204,6 +211,7 @@ export async function createChatFromMessages(
204
  db: IDBDatabase,
205
  description: string,
206
  messages: Message[],
 
207
  ): Promise<string> {
208
  const newId = await getNextId(db);
209
  const newUrlId = await getUrlId(db, newId); // Get a new urlId for the duplicated chat
@@ -214,6 +222,8 @@ export async function createChatFromMessages(
214
  messages,
215
  newUrlId, // Use the new urlId
216
  description,
 
 
217
  );
218
 
219
  return newUrlId; // Return the urlId instead of id for navigation
@@ -230,5 +240,19 @@ export async function updateChatDescription(db: IDBDatabase, id: string, descrip
230
  throw new Error('Description cannot be empty');
231
  }
232
 
233
- await setMessages(db, id, chat.messages, chat.urlId, description, chat.timestamp);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  }
 
2
  import { createScopedLogger } from '~/utils/logger';
3
  import type { ChatHistoryItem } from './useChatHistory';
4
 
5
+ export interface IChatMetadata {
6
+ gitUrl: string;
7
+ gitBranch?: string;
8
+ }
9
+
10
  const logger = createScopedLogger('ChatHistory');
11
 
12
  // this is used at the top level and never rejects
 
58
  urlId?: string,
59
  description?: string,
60
  timestamp?: string,
61
+ metadata?: IChatMetadata,
62
  ): Promise<void> {
63
  return new Promise((resolve, reject) => {
64
  const transaction = db.transaction('chats', 'readwrite');
 
75
  urlId,
76
  description,
77
  timestamp: timestamp ?? new Date().toISOString(),
78
+ metadata,
79
  });
80
 
81
  request.onsuccess = () => resolve();
 
211
  db: IDBDatabase,
212
  description: string,
213
  messages: Message[],
214
+ metadata?: IChatMetadata,
215
  ): Promise<string> {
216
  const newId = await getNextId(db);
217
  const newUrlId = await getUrlId(db, newId); // Get a new urlId for the duplicated chat
 
222
  messages,
223
  newUrlId, // Use the new urlId
224
  description,
225
+ undefined, // Use the current timestamp
226
+ metadata,
227
  );
228
 
229
  return newUrlId; // Return the urlId instead of id for navigation
 
240
  throw new Error('Description cannot be empty');
241
  }
242
 
243
+ await setMessages(db, id, chat.messages, chat.urlId, description, chat.timestamp, chat.metadata);
244
+ }
245
+
246
+ export async function updateChatMetadata(
247
+ db: IDBDatabase,
248
+ id: string,
249
+ metadata: IChatMetadata | undefined,
250
+ ): Promise<void> {
251
+ const chat = await getMessages(db, id);
252
+
253
+ if (!chat) {
254
+ throw new Error('Chat not found');
255
+ }
256
+
257
+ await setMessages(db, id, chat.messages, chat.urlId, chat.description, chat.timestamp, metadata);
258
  }
app/lib/persistence/useChatHistory.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
  setMessages,
14
  duplicateChat,
15
  createChatFromMessages,
 
16
  } from './db';
17
 
18
  export interface ChatHistoryItem {
@@ -21,6 +22,7 @@ export interface ChatHistoryItem {
21
  description?: string;
22
  messages: Message[];
23
  timestamp: string;
 
24
  }
25
 
26
  const persistenceEnabled = !import.meta.env.VITE_DISABLE_PERSISTENCE;
@@ -29,7 +31,7 @@ export const db = persistenceEnabled ? await openDatabase() : undefined;
29
 
30
  export const chatId = atom<string | undefined>(undefined);
31
  export const description = atom<string | undefined>(undefined);
32
-
33
  export function useChatHistory() {
34
  const navigate = useNavigate();
35
  const { id: mixedId } = useLoaderData<{ id?: string }>();
@@ -65,6 +67,7 @@ export function useChatHistory() {
65
  setUrlId(storedMessages.urlId);
66
  description.set(storedMessages.description);
67
  chatId.set(storedMessages.id);
 
68
  } else {
69
  navigate('/', { replace: true });
70
  }
@@ -81,6 +84,21 @@ export function useChatHistory() {
81
  return {
82
  ready: !mixedId || ready,
83
  initialMessages,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  storeMessageHistory: async (messages: Message[]) => {
85
  if (!db || messages.length === 0) {
86
  return;
@@ -109,7 +127,7 @@ export function useChatHistory() {
109
  }
110
  }
111
 
112
- await setMessages(db, chatId.get() as string, messages, urlId, description.get());
113
  },
114
  duplicateCurrentChat: async (listItemId: string) => {
115
  if (!db || (!mixedId && !listItemId)) {
@@ -125,13 +143,13 @@ export function useChatHistory() {
125
  console.log(error);
126
  }
127
  },
128
- importChat: async (description: string, messages: Message[]) => {
129
  if (!db) {
130
  return;
131
  }
132
 
133
  try {
134
- const newId = await createChatFromMessages(db, description, messages);
135
  window.location.href = `/chat/${newId}`;
136
  toast.success('Chat imported successfully');
137
  } catch (error) {
 
13
  setMessages,
14
  duplicateChat,
15
  createChatFromMessages,
16
+ type IChatMetadata,
17
  } from './db';
18
 
19
  export interface ChatHistoryItem {
 
22
  description?: string;
23
  messages: Message[];
24
  timestamp: string;
25
+ metadata?: IChatMetadata;
26
  }
27
 
28
  const persistenceEnabled = !import.meta.env.VITE_DISABLE_PERSISTENCE;
 
31
 
32
  export const chatId = atom<string | undefined>(undefined);
33
  export const description = atom<string | undefined>(undefined);
34
+ export const chatMetadata = atom<IChatMetadata | undefined>(undefined);
35
  export function useChatHistory() {
36
  const navigate = useNavigate();
37
  const { id: mixedId } = useLoaderData<{ id?: string }>();
 
67
  setUrlId(storedMessages.urlId);
68
  description.set(storedMessages.description);
69
  chatId.set(storedMessages.id);
70
+ chatMetadata.set(storedMessages.metadata);
71
  } else {
72
  navigate('/', { replace: true });
73
  }
 
84
  return {
85
  ready: !mixedId || ready,
86
  initialMessages,
87
+ updateChatMestaData: async (metadata: IChatMetadata) => {
88
+ const id = chatId.get();
89
+
90
+ if (!db || !id) {
91
+ return;
92
+ }
93
+
94
+ try {
95
+ await setMessages(db, id, initialMessages, urlId, description.get(), undefined, metadata);
96
+ chatMetadata.set(metadata);
97
+ } catch (error) {
98
+ toast.error('Failed to update chat metadata');
99
+ console.error(error);
100
+ }
101
+ },
102
  storeMessageHistory: async (messages: Message[]) => {
103
  if (!db || messages.length === 0) {
104
  return;
 
127
  }
128
  }
129
 
130
+ await setMessages(db, chatId.get() as string, messages, urlId, description.get(), undefined, chatMetadata.get());
131
  },
132
  duplicateCurrentChat: async (listItemId: string) => {
133
  if (!db || (!mixedId && !listItemId)) {
 
143
  console.log(error);
144
  }
145
  },
146
+ importChat: async (description: string, messages: Message[], metadata?: IChatMetadata) => {
147
  if (!db) {
148
  return;
149
  }
150
 
151
  try {
152
+ const newId = await createChatFromMessages(db, description, messages, metadata);
153
  window.location.href = `/chat/${newId}`;
154
  toast.success('Chat imported successfully');
155
  } catch (error) {
app/lib/runtime/message-parser.ts CHANGED
@@ -64,6 +64,10 @@ function cleanoutMarkdownSyntax(content: string) {
64
  return content;
65
  }
66
  }
 
 
 
 
67
  export class StreamingMessageParser {
68
  #messages = new Map<string, MessageState>();
69
 
@@ -110,6 +114,7 @@ export class StreamingMessageParser {
110
  // Remove markdown code block syntax if present and file is not markdown
111
  if (!currentAction.filePath.endsWith('.md')) {
112
  content = cleanoutMarkdownSyntax(content);
 
113
  }
114
 
115
  content += '\n';
@@ -141,6 +146,7 @@ export class StreamingMessageParser {
141
 
142
  if (!currentAction.filePath.endsWith('.md')) {
143
  content = cleanoutMarkdownSyntax(content);
 
144
  }
145
 
146
  this._options.callbacks?.onActionStream?.({
 
64
  return content;
65
  }
66
  }
67
+
68
+ function cleanEscapedTags(content: string) {
69
+ return content.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
70
+ }
71
  export class StreamingMessageParser {
72
  #messages = new Map<string, MessageState>();
73
 
 
114
  // Remove markdown code block syntax if present and file is not markdown
115
  if (!currentAction.filePath.endsWith('.md')) {
116
  content = cleanoutMarkdownSyntax(content);
117
+ content = cleanEscapedTags(content);
118
  }
119
 
120
  content += '\n';
 
146
 
147
  if (!currentAction.filePath.endsWith('.md')) {
148
  content = cleanoutMarkdownSyntax(content);
149
+ content = cleanEscapedTags(content);
150
  }
151
 
152
  this._options.callbacks?.onActionStream?.({
app/lib/stores/workbench.ts CHANGED
@@ -434,7 +434,7 @@ export class WorkbenchStore {
434
  return syncedFiles;
435
  }
436
 
437
- async pushToGitHub(repoName: string, githubUsername?: string, ghToken?: string) {
438
  try {
439
  // Use cookies if username and token are not provided
440
  const githubToken = ghToken || Cookies.get('githubToken');
@@ -523,7 +523,7 @@ export class WorkbenchStore {
523
  const { data: newCommit } = await octokit.git.createCommit({
524
  owner: repo.owner.login,
525
  repo: repo.name,
526
- message: 'Initial commit from your app',
527
  tree: newTree.sha,
528
  parents: [latestCommitSha],
529
  });
 
434
  return syncedFiles;
435
  }
436
 
437
+ async pushToGitHub(repoName: string, commitMessage?: string, githubUsername?: string, ghToken?: string) {
438
  try {
439
  // Use cookies if username and token are not provided
440
  const githubToken = ghToken || Cookies.get('githubToken');
 
523
  const { data: newCommit } = await octokit.git.createCommit({
524
  owner: repo.owner.login,
525
  repo: repo.name,
526
+ message: commitMessage || 'Initial commit from your app',
527
  tree: newTree.sha,
528
  parents: [latestCommitSha],
529
  });
app/routes/api.chat.ts CHANGED
@@ -63,6 +63,8 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
63
  const totalMessageContent = messages.reduce((acc, message) => acc + message.content, '');
64
  logger.debug(`Total message length: ${totalMessageContent.split(' ').length}, words`);
65
 
 
 
66
  const dataStream = createDataStream({
67
  async execute(dataStream) {
68
  const filePaths = getFilePaths(files || {});
@@ -247,15 +249,42 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
247
  }
248
  }
249
  })();
250
-
251
  result.mergeIntoDataStream(dataStream);
252
  },
253
  onError: (error: any) => `Custom error: ${error.message}`,
254
  }).pipeThrough(
255
  new TransformStream({
256
  transform: (chunk, controller) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  // Convert the string stream to a byte stream
258
- const str = typeof chunk === 'string' ? chunk : JSON.stringify(chunk);
259
  controller.enqueue(encoder.encode(str));
260
  },
261
  }),
 
63
  const totalMessageContent = messages.reduce((acc, message) => acc + message.content, '');
64
  logger.debug(`Total message length: ${totalMessageContent.split(' ').length}, words`);
65
 
66
+ let lastChunk: string | undefined = undefined;
67
+
68
  const dataStream = createDataStream({
69
  async execute(dataStream) {
70
  const filePaths = getFilePaths(files || {});
 
249
  }
250
  }
251
  })();
 
252
  result.mergeIntoDataStream(dataStream);
253
  },
254
  onError: (error: any) => `Custom error: ${error.message}`,
255
  }).pipeThrough(
256
  new TransformStream({
257
  transform: (chunk, controller) => {
258
+ if (!lastChunk) {
259
+ lastChunk = ' ';
260
+ }
261
+
262
+ if (typeof chunk === 'string') {
263
+ if (chunk.startsWith('g') && !lastChunk.startsWith('g')) {
264
+ controller.enqueue(encoder.encode(`0: "<div class=\\"__boltThought__\\">"\n`));
265
+ }
266
+
267
+ if (lastChunk.startsWith('g') && !chunk.startsWith('g')) {
268
+ controller.enqueue(encoder.encode(`0: "</div>\\n"\n`));
269
+ }
270
+ }
271
+
272
+ lastChunk = chunk;
273
+
274
+ let transformedChunk = chunk;
275
+
276
+ if (typeof chunk === 'string' && chunk.startsWith('g')) {
277
+ let content = chunk.split(':').slice(1).join(':');
278
+
279
+ if (content.endsWith('\n')) {
280
+ content = content.slice(0, content.length - 1);
281
+ }
282
+
283
+ transformedChunk = `0:${content}\n`;
284
+ }
285
+
286
  // Convert the string stream to a byte stream
287
+ const str = typeof transformedChunk === 'string' ? transformedChunk : JSON.stringify(transformedChunk);
288
  controller.enqueue(encoder.encode(str));
289
  },
290
  }),
app/routes/api.models.ts CHANGED
@@ -41,11 +41,17 @@ function getProviderInfo(llmManager: LLMManager) {
41
  export async function loader({
42
  request,
43
  params,
 
44
  }: {
45
  request: Request;
46
  params: { provider?: string };
 
 
 
 
 
47
  }): Promise<Response> {
48
- const llmManager = LLMManager.getInstance(import.meta.env);
49
 
50
  // Get client side maintained API keys and provider settings from cookies
51
  const cookieHeader = request.headers.get('Cookie');
@@ -63,7 +69,7 @@ export async function loader({
63
  if (provider) {
64
  const staticModels = provider.staticModels;
65
  const dynamicModels = provider.getDynamicModels
66
- ? await provider.getDynamicModels(apiKeys, providerSettings, import.meta.env)
67
  : [];
68
  modelList = [...staticModels, ...dynamicModels];
69
  }
@@ -72,7 +78,7 @@ export async function loader({
72
  modelList = await llmManager.updateModelList({
73
  apiKeys,
74
  providerSettings,
75
- serverEnv: import.meta.env,
76
  });
77
  }
78
 
 
41
  export async function loader({
42
  request,
43
  params,
44
+ context,
45
  }: {
46
  request: Request;
47
  params: { provider?: string };
48
+ context: {
49
+ cloudflare?: {
50
+ env: Record<string, string>;
51
+ };
52
+ };
53
  }): Promise<Response> {
54
+ const llmManager = LLMManager.getInstance(context.cloudflare?.env);
55
 
56
  // Get client side maintained API keys and provider settings from cookies
57
  const cookieHeader = request.headers.get('Cookie');
 
69
  if (provider) {
70
  const staticModels = provider.staticModels;
71
  const dynamicModels = provider.getDynamicModels
72
+ ? await provider.getDynamicModels(apiKeys, providerSettings, context.cloudflare?.env)
73
  : [];
74
  modelList = [...staticModels, ...dynamicModels];
75
  }
 
78
  modelList = await llmManager.updateModelList({
79
  apiKeys,
80
  providerSettings,
81
+ serverEnv: context.cloudflare?.env,
82
  });
83
  }
84
 
app/utils/folderImport.ts CHANGED
@@ -1,6 +1,6 @@
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[],
@@ -42,7 +42,7 @@ export const createChatFromFolder = async (
42
  ${fileArtifacts
43
  .map(
44
  (file) => `<boltAction type="file" filePath="${file.path}">
45
- ${file.content}
46
  </boltAction>`,
47
  )
48
  .join('\n\n')}
 
1
  import type { Message } from 'ai';
2
  import { generateId } from './fileUtils';
3
+ import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from './projectCommands';
4
 
5
  export const createChatFromFolder = async (
6
  files: File[],
 
42
  ${fileArtifacts
43
  .map(
44
  (file) => `<boltAction type="file" filePath="${file.path}">
45
+ ${escapeBoltTags(file.content)}
46
  </boltAction>`,
47
  )
48
  .join('\n\n')}
app/utils/markdown.ts CHANGED
@@ -61,7 +61,13 @@ const rehypeSanitizeOptions: RehypeSanitizeOptions = {
61
  tagNames: allowedHTMLElements,
62
  attributes: {
63
  ...defaultSchema.attributes,
64
- div: [...(defaultSchema.attributes?.div ?? []), 'data*', ['className', '__boltArtifact__']],
 
 
 
 
 
 
65
  },
66
  strip: [],
67
  };
 
61
  tagNames: allowedHTMLElements,
62
  attributes: {
63
  ...defaultSchema.attributes,
64
+ div: [
65
+ ...(defaultSchema.attributes?.div ?? []),
66
+ 'data*',
67
+ ['className', '__boltArtifact__', '__boltThought__'],
68
+
69
+ // ['className', '__boltThought__']
70
+ ],
71
  },
72
  strip: [],
73
  };
app/utils/projectCommands.ts CHANGED
@@ -78,3 +78,39 @@ ${commands.setupCommand}
78
  createdAt: new Date(),
79
  };
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  createdAt: new Date(),
79
  };
80
  }
81
+
82
+ export function escapeBoltArtifactTags(input: string) {
83
+ // Regular expression to match boltArtifact tags and their content
84
+ const regex = /(<boltArtifact[^>]*>)([\s\S]*?)(<\/boltArtifact>)/g;
85
+
86
+ return input.replace(regex, (match, openTag, content, closeTag) => {
87
+ // Escape the opening tag
88
+ const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
89
+
90
+ // Escape the closing tag
91
+ const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
92
+
93
+ // Return the escaped version
94
+ return `${escapedOpenTag}${content}${escapedCloseTag}`;
95
+ });
96
+ }
97
+
98
+ export function escapeBoltAActionTags(input: string) {
99
+ // Regular expression to match boltArtifact tags and their content
100
+ const regex = /(<boltAction[^>]*>)([\s\S]*?)(<\/boltAction>)/g;
101
+
102
+ return input.replace(regex, (match, openTag, content, closeTag) => {
103
+ // Escape the opening tag
104
+ const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
105
+
106
+ // Escape the closing tag
107
+ const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
108
+
109
+ // Return the escaped version
110
+ return `${escapedOpenTag}${content}${escapedCloseTag}`;
111
+ });
112
+ }
113
+
114
+ export function escapeBoltTags(input: string) {
115
+ return escapeBoltArtifactTags(escapeBoltAActionTags(input));
116
+ }
bindings.sh CHANGED
@@ -2,15 +2,32 @@
2
 
3
  bindings=""
4
 
5
- while IFS= read -r line || [ -n "$line" ]; do
6
- if [[ ! "$line" =~ ^# ]] && [[ -n "$line" ]]; then
7
- name=$(echo "$line" | cut -d '=' -f 1)
8
- value=$(echo "$line" | cut -d '=' -f 2-)
9
- value=$(echo $value | sed 's/^"\(.*\)"$/\1/')
10
- bindings+="--binding ${name}=${value} "
11
- fi
12
- done < .env.local
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  bindings=$(echo $bindings | sed 's/[[:space:]]*$//')
15
 
16
- echo $bindings
 
2
 
3
  bindings=""
4
 
5
+ # Function to extract variable names from the TypeScript interface
6
+ extract_env_vars() {
7
+ grep -o '[A-Z_]\+:' worker-configuration.d.ts | sed 's/://'
8
+ }
9
+
10
+ # First try to read from .env.local if it exists
11
+ if [ -f ".env.local" ]; then
12
+ while IFS= read -r line || [ -n "$line" ]; do
13
+ if [[ ! "$line" =~ ^# ]] && [[ -n "$line" ]]; then
14
+ name=$(echo "$line" | cut -d '=' -f 1)
15
+ value=$(echo "$line" | cut -d '=' -f 2-)
16
+ value=$(echo $value | sed 's/^"\(.*\)"$/\1/')
17
+ bindings+="--binding ${name}=${value} "
18
+ fi
19
+ done < .env.local
20
+ else
21
+ # If .env.local doesn't exist, use environment variables defined in .d.ts
22
+ env_vars=($(extract_env_vars))
23
+ # Generate bindings for each environment variable if it exists
24
+ for var in "${env_vars[@]}"; do
25
+ if [ -n "${!var}" ]; then
26
+ bindings+="--binding ${var}=${!var} "
27
+ fi
28
+ done
29
+ fi
30
 
31
  bindings=$(echo $bindings | sed 's/[[:space:]]*$//')
32
 
33
+ echo $bindings
docker-compose.yaml CHANGED
@@ -72,3 +72,21 @@ services:
72
  - "5173:5173"
73
  command: pnpm run dev --host 0.0.0.0
74
  profiles: ["development", "default"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  - "5173:5173"
73
  command: pnpm run dev --host 0.0.0.0
74
  profiles: ["development", "default"]
75
+
76
+ app-prebuild:
77
+ image: ghcr.io/stackblitz-labs/bolt.diy:latest
78
+ ports:
79
+ - "5173:5173"
80
+ environment:
81
+ - NODE_ENV=production
82
+ - COMPOSE_PROFILES=production
83
+ # No strictly needed but serving as hints for Coolify
84
+ - PORT=5173
85
+ - OLLAMA_API_BASE_URL=http://127.0.0.1:11434
86
+ - DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768}
87
+ - RUNNING_IN_DOCKER=true
88
+ extra_hosts:
89
+ - "host.docker.internal:host-gateway"
90
+ command: pnpm run dockerstart
91
+ profiles:
92
+ - prebuilt
package.json CHANGED
@@ -33,9 +33,10 @@
33
  "@ai-sdk/amazon-bedrock": "1.0.6",
34
  "@ai-sdk/anthropic": "^0.0.39",
35
  "@ai-sdk/cohere": "^1.0.3",
 
36
  "@ai-sdk/google": "^0.0.52",
37
  "@ai-sdk/mistral": "^0.0.43",
38
- "@ai-sdk/openai": "^0.0.66",
39
  "@codemirror/autocomplete": "^6.18.3",
40
  "@codemirror/commands": "^6.7.1",
41
  "@codemirror/lang-cpp": "^6.0.2",
@@ -80,7 +81,7 @@
80
  "@xterm/addon-fit": "^0.10.0",
81
  "@xterm/addon-web-links": "^0.11.0",
82
  "@xterm/xterm": "^5.5.0",
83
- "ai": "^4.0.13",
84
  "chalk": "^5.4.1",
85
  "chart.js": "^4.4.7",
86
  "class-variance-authority": "^0.7.1",
@@ -147,7 +148,7 @@
147
  "vite-tsconfig-paths": "^4.3.2",
148
  "vitest": "^2.1.7",
149
  "wrangler": "^3.91.0",
150
- "zod": "^3.23.8"
151
  },
152
  "resolutions": {
153
  "@typescript-eslint/utils": "^8.0.0-alpha.30"
 
33
  "@ai-sdk/amazon-bedrock": "1.0.6",
34
  "@ai-sdk/anthropic": "^0.0.39",
35
  "@ai-sdk/cohere": "^1.0.3",
36
+ "@ai-sdk/deepseek": "^0.1.3",
37
  "@ai-sdk/google": "^0.0.52",
38
  "@ai-sdk/mistral": "^0.0.43",
39
+ "@ai-sdk/openai": "^1.1.2",
40
  "@codemirror/autocomplete": "^6.18.3",
41
  "@codemirror/commands": "^6.7.1",
42
  "@codemirror/lang-cpp": "^6.0.2",
 
81
  "@xterm/addon-fit": "^0.10.0",
82
  "@xterm/addon-web-links": "^0.11.0",
83
  "@xterm/xterm": "^5.5.0",
84
+ "ai": "^4.1.2",
85
  "chalk": "^5.4.1",
86
  "chart.js": "^4.4.7",
87
  "class-variance-authority": "^0.7.1",
 
148
  "vite-tsconfig-paths": "^4.3.2",
149
  "vitest": "^2.1.7",
150
  "wrangler": "^3.91.0",
151
+ "zod": "^3.24.1"
152
  },
153
  "resolutions": {
154
  "@typescript-eslint/utils": "^8.0.0-alpha.30"
pnpm-lock.yaml CHANGED
@@ -13,22 +13,25 @@ importers:
13
  dependencies:
14
  '@ai-sdk/amazon-bedrock':
15
  specifier: 1.0.6
16
- version: 1.0.6(zod@3.23.8)
17
  '@ai-sdk/anthropic':
18
  specifier: ^0.0.39
19
- version: 0.0.39(zod@3.23.8)
20
  '@ai-sdk/cohere':
21
  specifier: ^1.0.3
22
- version: 1.0.3(zod@3.23.8)
 
 
 
23
  '@ai-sdk/google':
24
  specifier: ^0.0.52
25
- version: 0.0.52(zod@3.23.8)
26
  '@ai-sdk/mistral':
27
  specifier: ^0.0.43
28
- version: 0.0.43(zod@3.23.8)
29
  '@ai-sdk/openai':
30
- specifier: ^0.0.66
31
- version: 0.0.66(zod@3.23.8)
32
  '@codemirror/autocomplete':
33
  specifier: ^6.18.3
34
  version: 6.18.3(@codemirror/[email protected])(@codemirror/[email protected])(@codemirror/[email protected])(@lezer/[email protected])
@@ -97,13 +100,13 @@ importers:
97
  version: 13.6.2
98
  '@openrouter/ai-sdk-provider':
99
  specifier: ^0.0.5
100
- version: 0.0.5([email protected])
101
  '@phosphor-icons/react':
102
  specifier: ^2.1.7
103
104
  '@radix-ui/react-collapsible':
105
  specifier: ^1.0.3
106
 
107
  '@radix-ui/react-context-menu':
108
  specifier: ^2.2.2
109
@@ -162,8 +165,8 @@ importers:
162
  specifier: ^5.5.0
163
  version: 5.5.0
164
  ai:
165
- specifier: ^4.0.13
166
- version: 4.0.18([email protected])(zod@3.23.8)
167
  chalk:
168
  specifier: ^5.4.1
169
  version: 5.4.1
@@ -220,7 +223,7 @@ importers:
220
221
  ollama-ai-provider:
222
  specifier: ^0.15.2
223
- version: 0.15.2(zod@3.23.8)
224
  react:
225
  specifier: ^18.3.1
226
  version: 18.3.1
@@ -358,8 +361,8 @@ importers:
358
  specifier: ^3.91.0
359
  version: 3.91.0(@cloudflare/[email protected])
360
  zod:
361
- specifier: ^3.23.8
362
- version: 3.23.8
363
 
364
  packages:
365
 
@@ -381,6 +384,12 @@ packages:
381
  peerDependencies:
382
  zod: ^3.0.0
383
 
 
 
 
 
 
 
384
  '@ai-sdk/[email protected]':
385
  resolution: {integrity: sha512-bfsA/1Ae0SQ6NfLwWKs5SU4MBwlzJjVhK6bTVBicYFjUxg9liK/W76P1Tq/qK9OlrODACz3i1STOIWsFPpIOuQ==}
386
  engines: {node: '>=18'}
@@ -393,8 +402,14 @@ packages:
393
  peerDependencies:
394
  zod: ^3.0.0
395
 
396
- '@ai-sdk/openai@0.0.66':
397
- resolution: {integrity: sha512-V4XeDnlNl5/AY3GB3ozJUjqnBLU5pK3DacKTbCNH3zH8/MggJoH6B8wRGdLUPVFMcsMz60mtvh4DC9JsIVFrKw==}
 
 
 
 
 
 
398
  engines: {node: '>=18'}
399
  peerDependencies:
400
  zod: ^3.0.0
@@ -435,8 +450,8 @@ packages:
435
  zod:
436
  optional: true
437
 
438
- '@ai-sdk/[email protected].4':
439
- resolution: {integrity: sha512-GMhcQCZbwM6RoZCri0MWeEWXRt/T+uCxsmHEsTwNvEH3GDjNzchfX25C8ftry2MeEOOn6KfqCLSKomcgK6RoOg==}
440
  engines: {node: '>=18'}
441
  peerDependencies:
442
  zod: ^3.0.0
@@ -444,8 +459,8 @@ packages:
444
  zod:
445
  optional: true
446
 
447
- '@ai-sdk/provider-utils@2.0.5':
448
- resolution: {integrity: sha512-2M7vLhYN0ThGjNlzow7oO/lsL+DyMxvGMIYmVQvEYaCWhDzxH5dOp78VNjJIVwHzVLMbBDigX3rJuzAs853idw==}
449
  engines: {node: '>=18'}
450
  peerDependencies:
451
  zod: ^3.0.0
@@ -469,16 +484,16 @@ packages:
469
  resolution: {integrity: sha512-mV+3iNDkzUsZ0pR2jG0sVzU6xtQY5DtSCBy3JFycLp6PwjyLw/iodfL3MwdmMCRJWgs3dadcHejRnMvF9nGTBg==}
470
  engines: {node: '>=18'}
471
 
472
- '@ai-sdk/[email protected]':
473
- resolution: {integrity: sha512-YYtP6xWQyaAf5LiWLJ+ycGTOeBLWrED7LUrvc+SQIWhGaneylqbaGsyQL7VouQUeQ4JZ1qKYZuhmi3W56HADPA==}
474
- engines: {node: '>=18'}
475
-
476
  '@ai-sdk/[email protected]':
477
  resolution: {integrity: sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ==}
478
  engines: {node: '>=18'}
479
 
480
- '@ai-sdk/react@1.0.6':
481
- resolution: {integrity: sha512-8Hkserq0Ge6AEi7N4hlv2FkfglAGbkoAXEZ8YSp255c3PbnZz6+/5fppw+aROmZMOfNwallSRuy1i/iPa2rBpQ==}
 
 
 
 
482
  engines: {node: '>=18'}
483
  peerDependencies:
484
  react: ^18 || ^19 || ^19.0.0-rc
@@ -489,8 +504,8 @@ packages:
489
  zod:
490
  optional: true
491
 
492
- '@ai-sdk/ui-utils@1.0.5':
493
- resolution: {integrity: sha512-DGJSbDf+vJyWmFNexSPUsS1AAy7gtsmFmoSyNbNbJjwl9hRIf2dknfA1V0ahx6pg3NNklNYFm53L8Nphjovfvg==}
494
  engines: {node: '>=18'}
495
  peerDependencies:
496
  zod: ^3.0.0
@@ -3212,8 +3227,8 @@ packages:
3212
  resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
3213
  engines: {node: '>=8'}
3214
 
3215
- ai@4.0.18:
3216
- resolution: {integrity: sha512-BTWzalLNE1LQphEka5xzJXDs5v4xXy1Uzr7dAVk+C/CnO3WNpuMBgrCymwUv0VrWaWc8xMQuh+OqsT7P7JyekQ==}
3217
  engines: {node: '>=18'}
3218
  peerDependencies:
3219
  react: ^18 || ^19 || ^19.0.0-rc
@@ -6821,112 +6836,125 @@ packages:
6821
6822
  resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
6823
 
6824
- zod-to-json-schema@3.23.5:
6825
- resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==}
6826
  peerDependencies:
6827
- zod: ^3.23.3
6828
 
6829
- zod@3.23.8:
6830
- resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
6831
 
6832
6833
  resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
6834
 
6835
  snapshots:
6836
 
6837
- '@ai-sdk/[email protected](zod@3.23.8)':
6838
  dependencies:
6839
  '@ai-sdk/provider': 1.0.3
6840
- '@ai-sdk/provider-utils': 2.0.5(zod@3.23.8)
6841
  '@aws-sdk/client-bedrock-runtime': 3.716.0
6842
- zod: 3.23.8
6843
  transitivePeerDependencies:
6844
  - aws-crt
6845
 
6846
- '@ai-sdk/[email protected](zod@3.23.8)':
6847
  dependencies:
6848
  '@ai-sdk/provider': 0.0.17
6849
- '@ai-sdk/provider-utils': 1.0.9(zod@3.23.8)
6850
- zod: 3.23.8
6851
 
6852
- '@ai-sdk/[email protected](zod@3.23.8)':
6853
  dependencies:
6854
  '@ai-sdk/provider': 1.0.1
6855
- '@ai-sdk/provider-utils': 2.0.2(zod@3.23.8)
6856
- zod: 3.23.8
6857
 
6858
- '@ai-sdk/google@0.0.52(zod@3.23.8)':
 
 
 
 
 
 
 
6859
  dependencies:
6860
  '@ai-sdk/provider': 0.0.24
6861
- '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8)
6862
  json-schema: 0.4.0
6863
- zod: 3.23.8
6864
 
6865
- '@ai-sdk/[email protected](zod@3.23.8)':
6866
  dependencies:
6867
  '@ai-sdk/provider': 0.0.24
6868
- '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8)
6869
- zod: 3.23.8
6870
 
6871
- '@ai-sdk/openai@0.0.66(zod@3.23.8)':
6872
  dependencies:
6873
- '@ai-sdk/provider': 0.0.24
6874
- '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8)
6875
- zod: 3.23.8
6876
 
6877
- '@ai-sdk/provider-utils@1.0.2(zod@3.23.8)':
 
 
 
 
 
 
6878
  dependencies:
6879
  '@ai-sdk/provider': 0.0.12
6880
  eventsource-parser: 1.1.2
6881
  nanoid: 3.3.6
6882
  secure-json-parse: 2.7.0
6883
  optionalDependencies:
6884
- zod: 3.23.8
6885
 
6886
- '@ai-sdk/[email protected](zod@3.23.8)':
6887
  dependencies:
6888
  '@ai-sdk/provider': 0.0.24
6889
  eventsource-parser: 1.1.2
6890
  nanoid: 3.3.6
6891
  secure-json-parse: 2.7.0
6892
  optionalDependencies:
6893
- zod: 3.23.8
6894
 
6895
- '@ai-sdk/[email protected](zod@3.23.8)':
6896
  dependencies:
6897
  '@ai-sdk/provider': 0.0.17
6898
  eventsource-parser: 1.1.2
6899
  nanoid: 3.3.6
6900
  secure-json-parse: 2.7.0
6901
  optionalDependencies:
6902
- zod: 3.23.8
6903
 
6904
- '@ai-sdk/[email protected](zod@3.23.8)':
6905
  dependencies:
6906
  '@ai-sdk/provider': 1.0.1
6907
  eventsource-parser: 3.0.0
6908
  nanoid: 3.3.8
6909
  secure-json-parse: 2.7.0
6910
  optionalDependencies:
6911
- zod: 3.23.8
6912
 
6913
- '@ai-sdk/[email protected].4(zod@3.23.8)':
6914
  dependencies:
6915
- '@ai-sdk/provider': 1.0.2
6916
  eventsource-parser: 3.0.0
6917
  nanoid: 3.3.8
6918
  secure-json-parse: 2.7.0
6919
  optionalDependencies:
6920
- zod: 3.23.8
6921
 
6922
- '@ai-sdk/provider-utils@2.0.5(zod@3.23.8)':
6923
  dependencies:
6924
- '@ai-sdk/provider': 1.0.3
6925
  eventsource-parser: 3.0.0
6926
  nanoid: 3.3.8
6927
  secure-json-parse: 2.7.0
6928
  optionalDependencies:
6929
- zod: 3.23.8
6930
 
6931
  '@ai-sdk/[email protected]':
6932
  dependencies:
@@ -6944,31 +6972,31 @@ snapshots:
6944
  dependencies:
6945
  json-schema: 0.4.0
6946
 
6947
- '@ai-sdk/[email protected].2':
6948
  dependencies:
6949
  json-schema: 0.4.0
6950
 
6951
- '@ai-sdk/[email protected].3':
6952
  dependencies:
6953
  json-schema: 0.4.0
6954
 
6955
- '@ai-sdk/react@1.0.6([email protected])(zod@3.23.8)':
6956
  dependencies:
6957
- '@ai-sdk/provider-utils': 2.0.4(zod@3.23.8)
6958
- '@ai-sdk/ui-utils': 1.0.5(zod@3.23.8)
6959
  swr: 2.2.5([email protected])
6960
  throttleit: 2.1.0
6961
  optionalDependencies:
6962
  react: 18.3.1
6963
- zod: 3.23.8
6964
 
6965
- '@ai-sdk/ui-utils@1.0.5(zod@3.23.8)':
6966
  dependencies:
6967
- '@ai-sdk/provider': 1.0.2
6968
- '@ai-sdk/provider-utils': 2.0.4(zod@3.23.8)
6969
- zod-to-json-schema: 3.23.5(zod@3.23.8)
6970
  optionalDependencies:
6971
- zod: 3.23.8
6972
 
6973
  '@ampproject/[email protected]':
6974
  dependencies:
@@ -7664,7 +7692,7 @@ snapshots:
7664
  '@cloudflare/[email protected]':
7665
  dependencies:
7666
  mime: 3.0.0
7667
- zod: 3.23.8
7668
 
7669
  '@cloudflare/[email protected]': {}
7670
 
@@ -8535,11 +8563,11 @@ snapshots:
8535
  dependencies:
8536
  '@octokit/openapi-types': 22.2.0
8537
 
8538
- '@openrouter/[email protected](zod@3.23.8)':
8539
  dependencies:
8540
  '@ai-sdk/provider': 0.0.12
8541
- '@ai-sdk/provider-utils': 1.0.2(zod@3.23.8)
8542
- zod: 3.23.8
8543
 
8544
  '@opentelemetry/[email protected]': {}
8545
 
@@ -10151,18 +10179,17 @@ snapshots:
10151
  clean-stack: 2.2.0
10152
  indent-string: 4.0.0
10153
 
10154
- ai@4.0.18([email protected])(zod@3.23.8):
10155
  dependencies:
10156
- '@ai-sdk/provider': 1.0.2
10157
- '@ai-sdk/provider-utils': 2.0.4(zod@3.23.8)
10158
- '@ai-sdk/react': 1.0.6([email protected])(zod@3.23.8)
10159
- '@ai-sdk/ui-utils': 1.0.5(zod@3.23.8)
10160
  '@opentelemetry/api': 1.9.0
10161
  jsondiffpatch: 0.6.0
10162
- zod-to-json-schema: 3.23.5([email protected])
10163
  optionalDependencies:
10164
  react: 18.3.1
10165
- zod: 3.23.8
10166
 
10167
10168
  dependencies:
@@ -12535,7 +12562,7 @@ snapshots:
12535
  workerd: 1.20241106.1
12536
  ws: 8.18.0
12537
  youch: 3.3.4
12538
- zod: 3.23.8
12539
  transitivePeerDependencies:
12540
  - bufferutil
12541
  - supports-color
@@ -12753,13 +12780,13 @@ snapshots:
12753
 
12754
12755
 
12756
- [email protected](zod@3.23.8):
12757
  dependencies:
12758
  '@ai-sdk/provider': 0.0.24
12759
- '@ai-sdk/provider-utils': 1.0.20(zod@3.23.8)
12760
  partial-json: 0.1.7
12761
  optionalDependencies:
12762
- zod: 3.23.8
12763
 
12764
12765
  dependencies:
@@ -13371,7 +13398,6 @@ snapshots:
13371
  '@remix-run/server-runtime': 2.15.2([email protected])
13372
  react: 18.3.1
13373
  react-dom: 18.3.1([email protected])
13374
-
13375
13376
  dependencies:
13377
  type-fest: 4.30.0
@@ -13381,7 +13407,7 @@ snapshots:
13381
13382
  '@remix-run/router': 1.21.0
13383
  react: 18.3.1
13384
- zod: 3.23.8
13385
 
13386
13387
 
@@ -14473,10 +14499,10 @@ snapshots:
14473
  mustache: 4.2.0
14474
  stacktracey: 2.1.8
14475
 
14476
- zod-to-json-schema@3.23.5(zod@3.23.8):
14477
  dependencies:
14478
- zod: 3.23.8
14479
 
14480
- zod@3.23.8: {}
14481
 
14482
 
13
  dependencies:
14
  '@ai-sdk/amazon-bedrock':
15
  specifier: 1.0.6
16
+ version: 1.0.6(zod@3.24.1)
17
  '@ai-sdk/anthropic':
18
  specifier: ^0.0.39
19
+ version: 0.0.39(zod@3.24.1)
20
  '@ai-sdk/cohere':
21
  specifier: ^1.0.3
22
+ version: 1.0.3(zod@3.24.1)
23
+ '@ai-sdk/deepseek':
24
+ specifier: ^0.1.3
25
+ version: 0.1.3([email protected])
26
  '@ai-sdk/google':
27
  specifier: ^0.0.52
28
+ version: 0.0.52(zod@3.24.1)
29
  '@ai-sdk/mistral':
30
  specifier: ^0.0.43
31
+ version: 0.0.43(zod@3.24.1)
32
  '@ai-sdk/openai':
33
+ specifier: ^1.1.2
34
+ version: 1.1.2(zod@3.24.1)
35
  '@codemirror/autocomplete':
36
  specifier: ^6.18.3
37
  version: 6.18.3(@codemirror/[email protected])(@codemirror/[email protected])(@codemirror/[email protected])(@lezer/[email protected])
 
100
  version: 13.6.2
101
  '@openrouter/ai-sdk-provider':
102
  specifier: ^0.0.5
 
103
  '@phosphor-icons/react':
104
  specifier: ^2.1.7
105
106
  '@radix-ui/react-collapsible':
107
  specifier: ^1.0.3
108
109
+ version: 0.0.5([email protected])
110
  '@radix-ui/react-context-menu':
111
  specifier: ^2.2.2
112
 
165
  specifier: ^5.5.0
166
  version: 5.5.0
167
  ai:
168
+ specifier: ^4.1.2
169
+ version: 4.1.2([email protected])(zod@3.24.1)
170
  chalk:
171
  specifier: ^5.4.1
172
  version: 5.4.1
 
223
224
  ollama-ai-provider:
225
  specifier: ^0.15.2
226
+ version: 0.15.2(zod@3.24.1)
227
  react:
228
  specifier: ^18.3.1
229
  version: 18.3.1
 
361
  specifier: ^3.91.0
362
  version: 3.91.0(@cloudflare/[email protected])
363
  zod:
364
+ specifier: ^3.24.1
365
+ version: 3.24.1
366
 
367
  packages:
368
 
 
384
  peerDependencies:
385
  zod: ^3.0.0
386
 
387
+ '@ai-sdk/[email protected]':
388
+ resolution: {integrity: sha512-cj0uYgFk0TWWtHKtwB8v17frttquLll9hCpRWtKpiZO69SbiZOwNSjENaoyZvN1sHMLQoQkw+hnbMGtWuU2yOg==}
389
+ engines: {node: '>=18'}
390
+ peerDependencies:
391
+ zod: ^3.0.0
392
+
393
  '@ai-sdk/[email protected]':
394
  resolution: {integrity: sha512-bfsA/1Ae0SQ6NfLwWKs5SU4MBwlzJjVhK6bTVBicYFjUxg9liK/W76P1Tq/qK9OlrODACz3i1STOIWsFPpIOuQ==}
395
  engines: {node: '>=18'}
 
402
  peerDependencies:
403
  zod: ^3.0.0
404
 
405
+ '@ai-sdk/openai-compatible@0.1.3':
406
+ resolution: {integrity: sha512-3dr81jVNTd7Tg4i6JwGKHX47DnQ+jn3zOuxLvu6bM2hFylchtIFn/ut3Et7VfsdMWf4gj9tXp/9rUiQ0JokkrQ==}
407
+ engines: {node: '>=18'}
408
+ peerDependencies:
409
+ zod: ^3.0.0
410
+
411
+ '@ai-sdk/[email protected]':
412
+ resolution: {integrity: sha512-9rfcwjl4g1/Bdr2SmgFQr+aw81r62MvIKE7QDHMC4ulFd/Hej2oClROSMpDFZHXzs7RGeb32VkRyCHUWWgN3RQ==}
413
  engines: {node: '>=18'}
414
  peerDependencies:
415
  zod: ^3.0.0
 
450
  zod:
451
  optional: true
452
 
453
+ '@ai-sdk/[email protected].5':
454
+ resolution: {integrity: sha512-2M7vLhYN0ThGjNlzow7oO/lsL+DyMxvGMIYmVQvEYaCWhDzxH5dOp78VNjJIVwHzVLMbBDigX3rJuzAs853idw==}
455
  engines: {node: '>=18'}
456
  peerDependencies:
457
  zod: ^3.0.0
 
459
  zod:
460
  optional: true
461
 
462
+ '@ai-sdk/provider-utils@2.1.2':
463
+ resolution: {integrity: sha512-ezpQT6kzy/2O4yyn/2YigMqynBYjZIOam3/EMNVzju+Ogj+Z+pf27c/Th78ce0A2ltgrXx6xN14sal/HHZNOOw==}
464
  engines: {node: '>=18'}
465
  peerDependencies:
466
  zod: ^3.0.0
 
484
  resolution: {integrity: sha512-mV+3iNDkzUsZ0pR2jG0sVzU6xtQY5DtSCBy3JFycLp6PwjyLw/iodfL3MwdmMCRJWgs3dadcHejRnMvF9nGTBg==}
485
  engines: {node: '>=18'}
486
 
 
 
 
 
487
  '@ai-sdk/[email protected]':
488
  resolution: {integrity: sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ==}
489
  engines: {node: '>=18'}
490
 
491
+ '@ai-sdk/provider@1.0.6':
492
+ resolution: {integrity: sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==}
493
+ engines: {node: '>=18'}
494
+
495
+ '@ai-sdk/[email protected]':
496
+ resolution: {integrity: sha512-bBcRsDaNHzCKSIBbPngMeqbnwZ1RFadXQo9XzHoGrvLANYRwuphGNB8XTXYVLC/eXjoaGVGw2wWf/TYigEnCuA==}
497
  engines: {node: '>=18'}
498
  peerDependencies:
499
  react: ^18 || ^19 || ^19.0.0-rc
 
504
  zod:
505
  optional: true
506
 
507
+ '@ai-sdk/ui-utils@1.1.2':
508
+ resolution: {integrity: sha512-+0kfBF4Y9jmlg1KlbNKIxchmXx9PzuReSpgRNWhpU10vfl1eeer4xK/XL2qHnzAWhsMFe/SVZXJIQObk44zNEQ==}
509
  engines: {node: '>=18'}
510
  peerDependencies:
511
  zod: ^3.0.0
 
3227
  resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
3228
  engines: {node: '>=8'}
3229
 
3230
+ ai@4.1.2:
3231
+ resolution: {integrity: sha512-11efhPorWFphIpeCgjW6r/jk4wB5RWUGjxayHblBXCq6YEc7o5ki7vlmSnESprsDkMEfmONBWb/xM8pWjR5O2g==}
3232
  engines: {node: '>=18'}
3233
  peerDependencies:
3234
  react: ^18 || ^19 || ^19.0.0-rc
 
6836
6837
  resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==}
6838
 
6839
+ zod-to-json-schema@3.24.1:
6840
+ resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==}
6841
  peerDependencies:
6842
+ zod: ^3.24.1
6843
 
6844
+ zod@3.24.1:
6845
+ resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
6846
 
6847
6848
  resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
6849
 
6850
  snapshots:
6851
 
6852
+ '@ai-sdk/[email protected](zod@3.24.1)':
6853
  dependencies:
6854
  '@ai-sdk/provider': 1.0.3
6855
+ '@ai-sdk/provider-utils': 2.0.5(zod@3.24.1)
6856
  '@aws-sdk/client-bedrock-runtime': 3.716.0
6857
+ zod: 3.24.1
6858
  transitivePeerDependencies:
6859
  - aws-crt
6860
 
6861
+ '@ai-sdk/[email protected](zod@3.24.1)':
6862
  dependencies:
6863
  '@ai-sdk/provider': 0.0.17
6864
+ '@ai-sdk/provider-utils': 1.0.9(zod@3.24.1)
6865
+ zod: 3.24.1
6866
 
6867
+ '@ai-sdk/[email protected](zod@3.24.1)':
6868
  dependencies:
6869
  '@ai-sdk/provider': 1.0.1
6870
+ '@ai-sdk/provider-utils': 2.0.2(zod@3.24.1)
6871
+ zod: 3.24.1
6872
 
6873
+ '@ai-sdk/deepseek@0.1.3(zod@3.24.1)':
6874
+ dependencies:
6875
+ '@ai-sdk/openai-compatible': 0.1.3([email protected])
6876
+ '@ai-sdk/provider': 1.0.6
6877
+ '@ai-sdk/provider-utils': 2.1.2([email protected])
6878
+ zod: 3.24.1
6879
+
6880
6881
  dependencies:
6882
  '@ai-sdk/provider': 0.0.24
6883
+ '@ai-sdk/provider-utils': 1.0.20(zod@3.24.1)
6884
  json-schema: 0.4.0
6885
+ zod: 3.24.1
6886
 
6887
+ '@ai-sdk/[email protected](zod@3.24.1)':
6888
  dependencies:
6889
  '@ai-sdk/provider': 0.0.24
6890
+ '@ai-sdk/provider-utils': 1.0.20(zod@3.24.1)
6891
+ zod: 3.24.1
6892
 
6893
+ '@ai-sdk/openai-compatible@0.1.3(zod@3.24.1)':
6894
  dependencies:
6895
+ '@ai-sdk/provider': 1.0.6
6896
+ '@ai-sdk/provider-utils': 2.1.2(zod@3.24.1)
6897
+ zod: 3.24.1
6898
 
6899
+ '@ai-sdk/openai@1.1.2(zod@3.24.1)':
6900
+ dependencies:
6901
+ '@ai-sdk/provider': 1.0.6
6902
+ '@ai-sdk/provider-utils': 2.1.2([email protected])
6903
+ zod: 3.24.1
6904
+
6905
6906
  dependencies:
6907
  '@ai-sdk/provider': 0.0.12
6908
  eventsource-parser: 1.1.2
6909
  nanoid: 3.3.6
6910
  secure-json-parse: 2.7.0
6911
  optionalDependencies:
6912
+ zod: 3.24.1
6913
 
6914
+ '@ai-sdk/[email protected](zod@3.24.1)':
6915
  dependencies:
6916
  '@ai-sdk/provider': 0.0.24
6917
  eventsource-parser: 1.1.2
6918
  nanoid: 3.3.6
6919
  secure-json-parse: 2.7.0
6920
  optionalDependencies:
6921
+ zod: 3.24.1
6922
 
6923
+ '@ai-sdk/[email protected](zod@3.24.1)':
6924
  dependencies:
6925
  '@ai-sdk/provider': 0.0.17
6926
  eventsource-parser: 1.1.2
6927
  nanoid: 3.3.6
6928
  secure-json-parse: 2.7.0
6929
  optionalDependencies:
6930
+ zod: 3.24.1
6931
 
6932
+ '@ai-sdk/[email protected](zod@3.24.1)':
6933
  dependencies:
6934
  '@ai-sdk/provider': 1.0.1
6935
  eventsource-parser: 3.0.0
6936
  nanoid: 3.3.8
6937
  secure-json-parse: 2.7.0
6938
  optionalDependencies:
6939
+ zod: 3.24.1
6940
 
6941
+ '@ai-sdk/[email protected].5(zod@3.24.1)':
6942
  dependencies:
6943
+ '@ai-sdk/provider': 1.0.3
6944
  eventsource-parser: 3.0.0
6945
  nanoid: 3.3.8
6946
  secure-json-parse: 2.7.0
6947
  optionalDependencies:
6948
+ zod: 3.24.1
6949
 
6950
+ '@ai-sdk/provider-utils@2.1.2(zod@3.24.1)':
6951
  dependencies:
6952
+ '@ai-sdk/provider': 1.0.6
6953
  eventsource-parser: 3.0.0
6954
  nanoid: 3.3.8
6955
  secure-json-parse: 2.7.0
6956
  optionalDependencies:
6957
+ zod: 3.24.1
6958
 
6959
  '@ai-sdk/[email protected]':
6960
  dependencies:
 
6972
  dependencies:
6973
  json-schema: 0.4.0
6974
 
6975
+ '@ai-sdk/[email protected].3':
6976
  dependencies:
6977
  json-schema: 0.4.0
6978
 
6979
+ '@ai-sdk/[email protected].6':
6980
  dependencies:
6981
  json-schema: 0.4.0
6982
 
6983
+ '@ai-sdk/react@1.1.2([email protected])(zod@3.24.1)':
6984
  dependencies:
6985
+ '@ai-sdk/provider-utils': 2.1.2(zod@3.24.1)
6986
+ '@ai-sdk/ui-utils': 1.1.2(zod@3.24.1)
6987
  swr: 2.2.5([email protected])
6988
  throttleit: 2.1.0
6989
  optionalDependencies:
6990
  react: 18.3.1
6991
+ zod: 3.24.1
6992
 
6993
+ '@ai-sdk/ui-utils@1.1.2(zod@3.24.1)':
6994
  dependencies:
6995
+ '@ai-sdk/provider': 1.0.6
6996
+ '@ai-sdk/provider-utils': 2.1.2(zod@3.24.1)
6997
+ zod-to-json-schema: 3.24.1(zod@3.24.1)
6998
  optionalDependencies:
6999
+ zod: 3.24.1
7000
 
7001
  '@ampproject/[email protected]':
7002
  dependencies:
 
7692
  '@cloudflare/[email protected]':
7693
  dependencies:
7694
  mime: 3.0.0
7695
+ zod: 3.24.1
7696
 
7697
  '@cloudflare/[email protected]': {}
7698
 
 
8563
  dependencies:
8564
  '@octokit/openapi-types': 22.2.0
8565
 
8566
+ '@openrouter/[email protected](zod@3.24.1)':
8567
  dependencies:
8568
  '@ai-sdk/provider': 0.0.12
8569
+ '@ai-sdk/provider-utils': 1.0.2(zod@3.24.1)
8570
+ zod: 3.24.1
8571
 
8572
  '@opentelemetry/[email protected]': {}
8573
 
 
10179
  clean-stack: 2.2.0
10180
  indent-string: 4.0.0
10181
 
10182
+ ai@4.1.2([email protected])(zod@3.24.1):
10183
  dependencies:
10184
+ '@ai-sdk/provider': 1.0.6
10185
+ '@ai-sdk/provider-utils': 2.1.2(zod@3.24.1)
10186
+ '@ai-sdk/react': 1.1.2([email protected])(zod@3.24.1)
10187
+ '@ai-sdk/ui-utils': 1.1.2(zod@3.24.1)
10188
  '@opentelemetry/api': 1.9.0
10189
  jsondiffpatch: 0.6.0
 
10190
  optionalDependencies:
10191
  react: 18.3.1
10192
+ zod: 3.24.1
10193
 
10194
10195
  dependencies:
 
12562
  workerd: 1.20241106.1
12563
  ws: 8.18.0
12564
  youch: 3.3.4
12565
+ zod: 3.24.1
12566
  transitivePeerDependencies:
12567
  - bufferutil
12568
  - supports-color
 
12780
 
12781
12782
 
12783
+ [email protected](zod@3.24.1):
12784
  dependencies:
12785
  '@ai-sdk/provider': 0.0.24
12786
+ '@ai-sdk/provider-utils': 1.0.20(zod@3.24.1)
12787
  partial-json: 0.1.7
12788
  optionalDependencies:
12789
+ zod: 3.24.1
12790
 
12791
12792
  dependencies:
 
13398
  '@remix-run/server-runtime': 2.15.2([email protected])
13399
  react: 18.3.1
13400
  react-dom: 18.3.1([email protected])
 
13401
13402
  dependencies:
13403
  type-fest: 4.30.0
 
13407
13408
  '@remix-run/router': 1.21.0
13409
  react: 18.3.1
13410
+ zod: 3.24.1
13411
 
13412
13413
 
 
14499
  mustache: 4.2.0
14500
  stacktracey: 2.1.8
14501
 
14502
+ zod-to-json-schema@3.24.1(zod@3.24.1):
14503
  dependencies:
14504
+ zod: 3.24.1
14505
 
14506
+ zod@3.24.1: {}
14507
 
14508
worker-configuration.d.ts CHANGED
@@ -1,5 +1,6 @@
1
  interface Env {
2
- DEFAULT_NUM_CTX:Settings;
 
3
  ANTHROPIC_API_KEY: string;
4
  OPENAI_API_KEY: string;
5
  GROQ_API_KEY: string;
 
1
  interface Env {
2
+ RUNNING_IN_DOCKER: Settings;
3
+ DEFAULT_NUM_CTX: Settings;
4
  ANTHROPIC_API_KEY: string;
5
  OPENAI_API_KEY: string;
6
  GROQ_API_KEY: string;